参考:1.https://answers.ros.org/question/27655/what-is-the-correct-way-to-do-stuff-before-a-node-is-shutdown/
2.http://wiki.ros.org/roscpp/Overview/Initialization%20and%20Shutdown
小车由于在关闭节点后无法发布Twist消息而不能停止,查找后发现可以使用自己的shutdown回调函数解决这一问题。思路是在ros::init中使用ros::init_options::NoSigintHandler选项,然后用signal函数注册自己的回调函数,用该回调函数控制原子变量g_request_shutdown从而获得节点的运行状态,最后用ros::shutdown()手动关闭节点。
在python中可以直接使用rospy.on_shutdown()来更改节点关闭时的行为。
#include <ros/ros.h>
#include "calc_motion.h"
#include "geometry_msgs/Twist.h"
#include <signal.h>
// Signal-safe flag for whether shutdown is requested
sig_atomic_t volatile g_request_shutdown = 0;
void mySigIntHandler(int sig){
g_request_shutdown = 1;
}
int main(int argc, char **argv){
// 关闭时使用自己的回调函数
ros::init(argc, argv, "motion", ros::init_options::NoSigintHandler);
signal(SIGINT, mySigIntHandler);
ros::NodeHandle nh;
geometry_msgs::Twist twist;
CalcMotion cm;
ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/cmd_vel", 5);
ros::Subscriber sub = nh.subscribe<ball_follow::Direction>("/direction", 1, &CalcMotion::getDirection, &cm);
ros::Rate r(10);
while(!g_request_shutdown){
ros::spinOnce();
// ROS_DEBUG("Twist x = %f, z = %f", twist.linear.x, twist.angular.z);
cm.calcTwist(twist);
pub.publish(twist);
r.sleep();
}
twist.linear.x = twist.angular.z = 0;
pub.publish(twist);
// 手动关闭ros节点
ros::shutdown();
return 0;
}