ROS源码研究(二):命令roscore执行流程及添加开机自动启动的节点(类似/rosout)

        ROS源码量对于本菜鸟来说还是挺大的,单是roscore下就牵扯了各种类和函数调用。这篇文章仅代表我的个人见解,错误之处望各位不吝赐教。

       ROS启动时首先会要求执行roscore这条命令,在wiki里面是这样对roscore进行介绍的:

       roscore是一个节点和程序的集合,为了让ROS节点进行通信,必须运行roscore。注意:若使用的是roslaunch,如果ROS检测到roscore没有运行,ROS也将将自动启动roscore。

       roscore将启动ros master、ros参数服务器和rosout节点。

    一、roscore源码分析:

       1、如果按照前一篇博客来安装ros_comm,roscore命令的位置在~/ros_catkin_ws/install_isolated/bin/roscore。roscore首先会调用roslaunch(跟roscore相同文件夹),由roslaunch来调用roslaunch包下的其他文件,roslaunch包的位置与roslaunch文件位置不同,roslaunch包在~/ros_catkin_ws/install_isolated/lib/python2.7/dist-packages/roslaunch,同样的,这个路径不是每个人都完全一样,各位请根据自己情况自行调整。

       roslaunch首先调用的是_init_.py的main(),初始化各种参数和环境变量,如设置roslaunch的日志文件位置。然后检查已存在的日志文件大小,若已超过1GB则会提醒用户执行rosclean purge命令。

    roslaunch文件在~/.ros/log下,每次执行roscore都会生成唯一的uuid,以uuid号为日志文件夹名,该文件夹下的roslaunch-........log便是roslaunch的日志,省略号处是机器号和pid号。

     2、_init_.py各种参数配置好后就到了p.start(),p为类ROSLaunchParent,定义是在roslaunch文件夹下的parent.py。ROSLaunchParent的类函数start负责启动ROSlaunch,自然包括其下各自服务的启动:

       2.1、 _start_infrastructure():加载配置,启动XMLRPC服务器和进程监视器

       _start_infrastructure()首先调用_load_config(),加载配置变量;

        然后调用_start_pm()来启动进程监视器,进程监视器的代码部分在pemon.py实现;

       接着是_start_server(),该函数启动XMLRPC服务器,涉及到的文件主要是:server.py->rosgraph的xmlrpc.py->rosgraph的network.py;

       最后是_start_remote(),用于初始化并运行远程进程运行器,若不存在远程运行器,则不执行相关操作。

       2.2、_init_runner():初始化roslaunch运行器。

      _init_runner()初始化了在launch.py的类ROSLaunchRunner,再调用config.py的summary()将roslaunch的相关启动信息输出给用户。

       2.3、launch.py的launch()调用_setup()来设置ROS网络状态,包括参数服务器状态和核心服务,_launch_nodes()来启动声明的节点和ros master。

      2.4、pmon.py的registrations_complete()设置registrations_complete标志后,如果没有其他进程需要监控,进程监视器将退出。

      到这一步已经将各种参数初始化,完成好了准备工作,下面开始运行roslaunch执行器。

      3、_init_.py的p.spin()调用的是parent.py的spin(),运行ROSLaunch直到程序退出。

      roscore的工作大体就是这些内容,下图是我纪录的roscore函数的调用顺序,不全,给大家参考一下吧。。


      官方也给出roscore涉及到的类的继承关系及类中的数据成员和成员函数:



    二、添加开机节点

      roscore从roscore.xml读取需要启动的节点的信息,roscore.xml位于ros_catkin_ws/install_isolated/etc/ros/roscore.xml,未修改的roscore.xml是这样的:

<!-- 
  ROS Core Stack definition

  Before making any modifications to this file, please read:
  http://ros.org/wiki/roscore
  -->
<launch>
  <group ns="/">
    <param name="rosversion" command="rosversion roslaunch" />
    <param name="rosdistro" command="rosversion -d" />
    <node pkg="rosout" type="rosout" name="rosout" respawn="true"/>
  </group>
</launch>

      若要添加开机一起启动的节点,可以修改roscore.xml文件,下面我以ros官方tutorial的编写新节点的talker节点为例来进行说明。创建的talker节点在/home/haroroda/catkin_ws/src/talker/scripts/talker.py,按照tutorial里source好路径便可以进行下一步。修改如下:

<!-- 
  ROS Core Stack definition

  Before making any modifications to this file, please read:
  http://ros.org/wiki/roscore
  -->
<launch>
  <group ns="/">
    <param name="rosversion" command="rosversion roslaunch" />
    <param name="rosdistro" command="rosversion -d" />
    <node pkg="rosout" type="rosout" name="rosout" respawn="true"/>
  </group>
  <group ns="/">
    <node pkg="talker" type="talker.py" name="talker" respawn="false"/>
  </group>
</launch>

      这里ns仍是“/”,个人认为只有路径写入$ROS_PACKAGE_PATH的都可以认为是“/”,然后很明显的pkg是包名。值得注意的是type和name分别代表带扩展名的文件名和文件名,我在这卡了很久,一开始type写的是文件名,name是带扩展名的文件名,然后就报错,一层层代码查过去,最后将type和name交换就好了。虽然不懂为啥但也不想深究了(知道答案的大佬们可以留言或私心告诉我,谢谢啦)。如果是c++写的可执行文件,则type和name是一样的。respawn表示是否要在roscore生命期间重启该节点,因为有些节点执行完就结束退出了,如果respawn设为true则roslaunch会在你的节点结束时又给重新启动,直到roscore退出执行。修改好后运行roscore测试一下:

      talker.py成功启动并结束,日志文件如图最后一行所示。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值