具有更多参数的信号处理程序

时间:2019-07-09 07:36:56

标签: c++ signals ros

我正在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,还是需要将其声明为全局参数?

1 个答案:

答案 0 :(得分:1)

可以从信号处理程序中调用的功能列表有限,请参见man signal-safety。因此,从信号处理程序上下文中可能无法发送Twist消息。

self-pipe trick通常用于处理信号处理程序上下文之外的信号:

  

维护管道并选择管道输入的可读性。在信号处理程序内部,向管道输出写入一个字节(非阻塞,以防万一)。完成。

除此之外,我建议将信号编号字节写入管道,以便对任何信号(如果适用)可以使用完全相同的信号处理程序和管道。

希望处理信号的线程必须等待管道的读取端变得可读,读取该字节并处理信号。可以使用事件循环(例如selectepoll等)或阻塞的read调用来完成等待。

或者,您可以使用signalfd代替管道(请参见此处的示例)。或sigsuspend阻止并等待信号。