我是ROS的新手,我正在尝试将actionserver用作Nodelet,或者至少在带有Nodelet的程序包中使用。
那有可能吗?
如果没有,那么什么是不需要主函数调用即可运行actionServer的正确方法?

我尝试使用following tutorial并将其修改为nodelet,但是看不到匹配。

这是我编写的用于测试的类:

#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的初始化与节点不同。本教程Porting nodes to nodelets的主要重点是将代码从构造函数移动到onInit()。由于ROS未正确初始化,因此无法在构造函数中启动 Action 服务器。

要使用C++ 11修复代码,首先需要在 header 中声明onInit和 Action 服务器的(唯一)指针mActionServer:

public:
    virtual void onInit() override;

private:
    std::unique_ptr<actionlib::SimpleActionServer<my_local_mission_manager::MissionAction>> mActionServer;

现在,您无需在构造函数中初始化此 Action 服务器,而是需要在正式初始化期间使用getNodeHandle方法进行此操作。从构造函数中删除所有代码,并像这样初始化nodelet
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();
}

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

关于c++ - ROS actionServer作为nodelet,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49368124/

10-12 03:46