Ros

日志api、ROSOutAppender和rosout节点

caller调用ros日志api时,像ROS_INFO_NAMED、ROS_WARN,除了会把日志输出到output,还可能会把日志发布向话题/rosout,以及存储到日志文件rosout.log。

图1 ros::console::impl::print

图1显示了ros日志api最终会调用ros::console::impl::print,print执行两个操作:1)输出到ouput,2)调用rosconsole_print_appender->log。第一个操作较简单,这里深入分析第二个。从图1的Watch1可看到,rosconsole_print_appender类型是LogAppender,但实际上是从它派生的ROSOutAppender。

图2 ROSOutAppender、rosout节点

图2显示ros日志api、ROSOutAppender、rosout节点大致关系,以下是逻辑。

  1. {节点A}创建第一个NodeHandle时,会创建ROSOutAppender,并赋值给rosconsole_print_appender。
  2. {节点A}调用了ros日志api,像ROS_WARN。ROS_WARN调用rosconsole_print_appender->log(...)。由于rosconsole_print_appender就是ROSOutAppender,调用的就是ROSOutAppender::log。
  3. {ROSOutAppender}log(...)把日志放在类成员local_queue_,并唤醒logThread线程。
  4. {ROSOutAppender}logThread线程把日志从local_queue_复制到栈内变量local_queue。并把日志发布向话题:/rosout。
  5. {rosout节点}正订阅/rosout话题,于是收到这个日志。收到后执行两个操作,1)把日志存入日志文件rosout.log。2)日志原样发布向话题/rosout_agg。
  6. {节点A}最后一个NodeHandle被销毁时,会调用deregister_appender把rosconsole_print_appender置为nullptr,然后销毁ROSOutAppender。

ROSOutAppender是一个类,可认为是节点A内的一个模块,是每个节点都含有一个ROSOutAppender模块。所以某个ROSOutAppender向/rosout话题发布的只是本节点产生的日志。

rosout节点订阅/routout话题,于是收集了当前正运行的所有节点的日志,它发布的/rosout_agg话题包含所有节点的日志。

rose_ros默认不会运行rosout节点;nocopy_intra==true时,ROSOutAppender不会发布/rosout话题。

 

全部评论: 0

    写评论: