ROS2 Unity 项目中的异常行为:接收主题数据时出现问题

Anomalous Behavior in ROS2 Unity Project: Issue with Receiving Topic Data

提问人:jvmoraiscb 提问时间:11/17/2023 更新时间:11/17/2023 访问量:13

问:

我正在使用这个库(https://github.com/RobotecAI/ros2-for-unity)在 Unity 中使用 ROS2 进行一个项目 (https://github.com/jvmoraiscb/rhcr)。

在虚拟机中,我运行一个节点,其中包含与控制器相关的主题(它发布位置并接收应施加的力)。该节点位于我有一段时间未修改的容器中。

然而,在上周,一个非常奇怪的错误开始发生,我不知道它可能是什么:当我在 Unity 和容器中运行程序时,控制器行为异常(好像它正在接收来自与强制相关的主题的垃圾)。但是,如果我打开另一个终端并运行“ros2 topic echo /force_vector”,控制器会停止移动(这是正常的,因为我没有在 Unity 中发送任何力值),并且项目正常工作。

这些是与控制节点相关的代码(我忽略了falcon.cpp,因为它只抽象了控制函数):

main.cpp:

#include <csignal>

#include "falcon_node.hpp"

// global pointers
bool* debug_mode_pt;
Falcon* falcon_pt;

void signal_handler(int sig) {
    if (sig == SIGTSTP) {
        if (*debug_mode_pt) {
            *debug_mode_pt = false;
            falcon_pt->print_info();
        } else {
            *debug_mode_pt = true;
        }
    }
}

int main(int argc, char* argv[]) {
    // initialize falcon variables
    auto falcon = Falcon();
    auto debug_mode = false;

    // initialize global pointers
    debug_mode_pt = &debug_mode;
    falcon_pt = &falcon;

    // register custom handler to ctrl-z
    signal(SIGTSTP, signal_handler);

    // initialize ros variables
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<Falcon_Node>(falcon_pt, debug_mode_pt));
    rclcpp::shutdown();

    return 0;
}

falcon_node.cpp:

#include "falcon_node.hpp"

using namespace std;
using namespace chrono_literals;

Falcon_Node::Falcon_Node(Falcon* falcon, bool* debug_mode) : Node("falcon_node"), count_(0) {
    falcon_ = falcon;
    debug_mode_ = debug_mode;
    timer_ = this->create_wall_timer(10ms, std::bind(&Falcon_Node::timer_callback, this));

    position_vector_pub = this->create_publisher<geometry_msgs::msg::Vector3>("position_vector", 10);
    right_button_pub = this->create_publisher<std_msgs::msg::Int16>("right_button", 10);
    up_button_pub = this->create_publisher<std_msgs::msg::Int16>("up_button", 10);
    center_button_pub = this->create_publisher<std_msgs::msg::Int16>("center_button", 10);
    left_button_pub = this->create_publisher<std_msgs::msg::Int16>("left_button", 10);
    force_vector_sub = this->create_subscription<geometry_msgs::msg::Vector3>("force_vector", 10, std::bind(&Falcon_Node::force_callback, this, std::placeholders::_1));
    rgb_vector_sub = this->create_subscription<geometry_msgs::msg::Vector3>("rgb_vector", 10, std::bind(&Falcon_Node::rgb_callback, this, std::placeholders::_1));

    printf("Please calibrate the controller: move it around and then press the center button.\n");

    falcon_->rgb(true, false, false);
    falcon_->calibrate();
    falcon_->rgb(false, true, false);

    falcon_->print_info();
}

void Falcon_Node::timer_callback() {
    double x, y, z;
    int button1, button2, button3, button4;

    falcon_->update();
    falcon_->get(&x, &y, &z, &button1, &button2, &button3, &button4);

    if (*debug_mode_) {
        printf("X: %+.2f | Y: %+.2f | Z: %+.2f | B1: %d | B2: %d | B3: %d | B4: %d\n", x, y, z, button1, button2, button3, button4);
    }

    auto pos = geometry_msgs::msg::Vector3();
    pos.x = (float)x;
    pos.y = (float)y;
    pos.z = (float)z;

    auto right = std_msgs::msg::Int16();
    right.data = button1;

    auto up = std_msgs::msg::Int16();
    up.data = button2;

    auto center = std_msgs::msg::Int16();
    center.data = button3;

    auto left = std_msgs::msg::Int16();
    left.data = button4;

    position_vector_pub->publish(pos);
    right_button_pub->publish(right);
    up_button_pub->publish(up);
    center_button_pub->publish(center);
    left_button_pub->publish(left);
}

void Falcon_Node::force_callback(const geometry_msgs::msg::Vector3::SharedPtr msg) {
    falcon_->set(msg->x, msg->y, msg->z);
}

void Falcon_Node::rgb_callback(const geometry_msgs::msg::Vector3::SharedPtr msg) {
    bool red = ((int)msg->x == 1) ? true : false;
    bool green = ((int)msg->y == 1) ? true : false;
    bool blue = ((int)msg->z == 1) ? true : false;

    falcon_->rgb(red, green, blue);
}

这是 Unity 中节点的代码:

Ros2FalconUnityNode.cs

using UnityEngine;

namespace ROS2
{
    public class Ros2FalconNode : MonoBehaviour
    {
        [SerializeField]
        private FalconEnv falconEnv;
        [SerializeField]
        private string nodeName;
        [SerializeField]
        private string positionTopicName;
        [SerializeField]
        private string rightButtonTopicName;
        [SerializeField]
        private string upButtonTopicName;
        [SerializeField]
        private string centerButtonTopicName;
        [SerializeField]
        private string leftButtonTopicName;
        [SerializeField]
        private string forceTopicName;
        [SerializeField]
        private string rgbTopicName;

        private ROS2UnityComponent ros2Unity;
        private ROS2Node ros2Node;
        private IPublisher<geometry_msgs.msg.Vector3> force_pub;
        private IPublisher<geometry_msgs.msg.Vector3> rgb_pub;

        private const int RIGHT = 1;
        private const int UP = 2;
        private const int CENTER = 3;
        private const int LEFT = 4;
        private int lastStatus_right = -1;
        private int lastStatus_up = -1;
        private int lastStatus_center = -1;
        private int lastStatus_left = -1;

        void Start()
        {
            ros2Unity = GetComponent<ROS2UnityComponent>();
            if (ros2Node == null)
                ros2Node = ros2Unity.CreateNode(nodeName);
            if (ros2Unity.Ok())
            {
                ros2Node.CreateSubscription<geometry_msgs.msg.Vector3>(positionTopicName, msg => PositionHandler(msg.X, msg.Y, msg.Z));
                ros2Node.CreateSubscription<std_msgs.msg.Int16>(rightButtonTopicName, msg => ButtonHandler(RIGHT, msg.Data));
                ros2Node.CreateSubscription<std_msgs.msg.Int16>(upButtonTopicName, msg => ButtonHandler(UP, msg.Data));
                ros2Node.CreateSubscription<std_msgs.msg.Int16>(centerButtonTopicName, msg => ButtonHandler(CENTER, msg.Data));
                ros2Node.CreateSubscription<std_msgs.msg.Int16>(leftButtonTopicName, msg => ButtonHandler(LEFT, msg.Data));

                force_pub = ros2Node.CreatePublisher<geometry_msgs.msg.Vector3>(forceTopicName);
                rgb_pub = ros2Node.CreatePublisher<geometry_msgs.msg.Vector3>(rgbTopicName);
            }
        }

        void Update()
        {
            if (ros2Unity.Ok())
            {
                ForceHandler();
                RgbHandler();
            }
            
        }

        void ForceHandler()
        {
            geometry_msgs.msg.Vector3 msg = new geometry_msgs.msg.Vector3
            {
                X = falconEnv.force.x,
                Y = falconEnv.force.y,
                Z = falconEnv.force.z
            };

            force_pub.Publish(msg);
        }

        void RgbHandler()
        {
            geometry_msgs.msg.Vector3 msg = new geometry_msgs.msg.Vector3
            {
                X = falconEnv.rgb.x,
                Y = falconEnv.rgb.y,
                Z = falconEnv.rgb.z
            };

            rgb_pub.Publish(msg);
        }

        void PositionHandler(double x, double y, double z)
        {
            falconEnv.position.x = (float)x;
            falconEnv.position.y = (float)y;
            falconEnv.position.z = (float)z;
        }

        void ButtonHandler(int button, int value)
        {
            if (button == RIGHT && value != lastStatus_right) {
                if (lastStatus_right != -1)
                    falconEnv.RightButtonHandler();
                lastStatus_right = value;
            }
            if (button == UP && value != lastStatus_up) {
                if (lastStatus_up != -1)
                    falconEnv.UpButtonHandler();
                lastStatus_up = value;
            }
            if (button == CENTER && value != lastStatus_center) {
                if (lastStatus_center != -1)
                    falconEnv.CenterButtonHandler();
                lastStatus_center = value;
            }
            if (button == LEFT && value != lastStatus_left) {
                if (lastStatus_left != -1)
                    falconEnv.LeftButtonHandler();
                lastStatus_left = value;
            }
        }
    }

}

我尝试将项目恢复到一切正常的先前版本,尝试重新编译项目,但错误仍然存在。我也尝试使用ros2bag来检查状态,但是当我运行程序时,它订阅了该主题,并且项目再次开始正常工作。

有谁知道我能做些什么来解决这个问题?

unity-游戏引擎 ros ros2

评论

0赞 jvmoraiscb 11/27/2023
我从“独立”模式切换到“叠加”模式,项目又开始工作了。

答: 暂无答案