ROS actionServer as nodelet

ROS actionServer as nodelet

本文关键字:nodelet as actionServer ROS      更新时间:2023-10-16

我是ROS的新手,我正在尝试将操作服务器用作节点或至少在带有nodelet的包中使用。这可能吗?如果不是,那么在不需要调用主函数的情况下运行 actionServer 的正确方法是什么?

我尝试使用以下教程并将其修改为节点,但看不到命中。

这是我为测试编写的类:

#include "ros/ros.h"
#include "std_msgs/String.h"
#include "std_msgs/Float32MultiArray.h"
#include <vector>
#include "my_action_server.h"
//Nodelet dependencies
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(my_local_mission_manager::myMissionActionServer, nodelet::Nodelet)
namespace my_local_mission_manager
{
void myMissionActionServer::onInit()
{
    ROS_INFO_STREAM("Starting my Mission Action Server Log Node");
}
myMissionActionServer::myMissionActionServer(std::string missionName) : mActionServer(mNH, missionName, boost::bind(&myMissionActionServer::executeMissionCallBack, this, _1), false),
                                                     mActionName(missionName)
{
    mActionServer.start();
}
myMissionActionServer::~myMissionActionServer(void)
{
    ROS_INFO_STREAM("Done - MissionAction");
}
void myMissionActionServer::executeMissionCallBack(const my_local_mission_manager::missionGoalConstPtr &goal)
{
    // helper variables
    int start = 0;
    ros::Rate r(1);
    bool success = true;
    for (int i = 0; i <= goal->demo_goal; i++)
    {
        if (mActionServer.isPreemptRequested() || !ros::ok())
        {
            ROS_INFO("%s: Preempted", mActionName.c_str());
            // set the action state to preempted
            mActionServer.setPreempted();
            success = false;
            break;
        }
        mFeedback.demo_feedback = i;
        mActionServer.publishFeedback(mFeedback); //publish the feedback
        r.sleep(); // this sleep is not necessary - debug and demo purpose
    }
    if (success)
    {
        mResult.demo_result = mFeedback.demo_feedback;
        ROS_INFO("%s: Succeeded", mActionName.c_str());
        // set the action state to succeeded
        mActionServer.setSucceeded(mResult);
    }
};
}

nodelet 的初始化与节点不同。教程将节点移植到 nodelet 的一个要点是将代码从构造函数移动到 onInit((。无法在构造函数中启动操作服务器,因为 ROS 未正确初始化。

要使用 C++11 修复代码,首先需要在标头中声明操作服务器的onInit和(唯一(指针mActionServer

public:
    virtual void onInit() override;
private:
    std::unique_ptr<actionlib::SimpleActionServer<my_local_mission_manager::MissionAction>> mActionServer;

现在,您需要使用 getNodeHandle 方法在正式初始化期间执行此操作,而不是在构造函数中初始化此操作服务器。从构造函数中删除所有代码并初始化节点,例如

void MyMissionActionServer::onInit()
{
  ROS_INFO_STREAM("Starting my Mission Action Server Log Node");
  ros::NodeHandle nh = getNodeHandle();
  mActionServer = std::unique_ptr<actionlib::SimpleActionServer<my_local_mission_manager::MissionAction>>(
      new actionlib::SimpleActionServer<my_local_mission_manager::MissionAction>(
          nh, mActionName.c_str(), std::bind(&MyMissionActionServer::executeMissionCallBack, this, std::placeholders::_1), false));
  mActionServer->start();
}

需要指向操作服务器的指针,因为初始化未在构造函数中完成。因此,您还需要更新现有代码的所有操作服务器调用。例如,您需要将mActionServer.setSucceeded(mResult);更改为 mActionServer->setSucceeded(mResult);