我是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
方法进行此操作。从构造函数中删除所有代码,并像这样初始化nodeletvoid 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/