我正在Ubuntu 18.04.2 LTS上使用ROS Melodic和Gazebo 9.9.0。
我想在用户杀死节点时向机器人发送“停止”消息(全零的Twist消息)。
要处理Ctrl + C事件,我使用以下方法:
/**
* Override the default ros sigint handler to stop the robot when user press
* Ctrl.+C.
*/
void sigintHandler(int sig)
{
// All the default sigint handler does is call shutdown()
ros::shutdown();
}
但是此函数不允许传递更多参数(我需要传递cmd_vel_pub
)。
我已在主要功能上声明此发布者:
int main(int argc, char **argv)
{
ros::init(argc, argv, "astar_controller");
ros::NodeHandle n;
// Override the default ros sigint handler.
// This must be set after the first NodeHandle is created.
std::signal(SIGINT, sigintHandler);
/**
* Topic where we are going to publish speed commands.
*/
ros::Publisher cmd_vel_pub = n.advertise<geometry_msgs::Twist>(cmdTopic, 1000);
// More code...
}
也许我可以将cmd_vel_pub
声明为全局变量。
是否可以将更多参数传递给sigintHandler
,还是需要将其声明为全局参数?
答案 0 :(得分:1)
可以从信号处理程序中调用的功能列表有限,请参见man signal-safety
。因此,从信号处理程序上下文中可能无法发送Twist消息。
self-pipe trick通常用于处理信号处理程序上下文之外的信号:
维护管道并选择管道输入的可读性。在信号处理程序内部,向管道输出写入一个字节(非阻塞,以防万一)。完成。
除此之外,我建议将信号编号字节写入管道,以便对任何信号(如果适用)可以使用完全相同的信号处理程序和管道。
希望处理信号的线程必须等待管道的读取端变得可读,读取该字节并处理信号。可以使用事件循环(例如select
,epoll
等)或阻塞的read
调用来完成等待。
或者,您可以使用signalfd
代替管道(请参见此处的示例)。或sigsuspend
阻止并等待信号。