ROS笔记:Python

ROS笔记:Python

@(ROS)[ROS|Python|rospy|环境变量]
记录并分析ROS的整个Python系统体系,争取搞清楚内部原理。同时深入学习Python编程。

  • ROS笔记Python
    • rospy
      • Initialization and Shutdown
      • Messages
      • Publishers and Subscribers
      • Services
      • Parameter Server
      • Logging
      • Time
      • Exceptions
    • rospy_tutorials示例包

1. rospy

http://wiki.ros.org/rospy/Overview

Initialization and Shutdown

  • PYTHONPATH:

    可使用 echo $PYTHONPATH 查看。

    • 这个环境变量是bash下的python使用的,根据这个环境变量里的目录去搜索可被import的Python模块。
    • 执行$ source xxx/setup.bash”命令时自动将当前工作区的python包目录添加到这个环境变量中。
    • 比如安装ros时执行过$ source /opt/ros/indigo/setup.bash”,是在PYTHONPATH中添加了目录“/opt/ros/indigo/lib/python2.7/dist-packages”
    • 比如在自己工作区执行$ source devel/setup.bash”,是在PYTHONPATH中添加了目录“{YOUR_CATKIN_WS}/devel/lib/python2.7/dist-packages”
    • ? 似乎setup.bash 和 setup.py 还有些关系 ?
  • init and shutdown

    • rospy.init_node(name, anonymous=False, log_level=rospy.INFO, disable_signals=False)
    • rospy.on_shutdown(h)这个函数为Ctrl+C这类shutdown事件创建一个退出之前的回调函数h,可以在程序退出之前做点什么。如果在h函数内Publish消息,不保证能成功发出消息!在rospy_tutorial示例中经过验证。

Messages

  • Message generation

    • 自定义的msg和srv,在catkin_make时被自动生成为python模块源码,存储在“{YOUR_CATKIN_WS}/devel/lib/python2.7/dist-packages”目录下。
    • msg文件和Python模块的对应关系是:package_name/msg/Foo.msg → package_name.msg.Foo
    • srv文件和Python模块的对应关系是:package_name/srv/Bar.srv → package_name.srv.Bar
  • Message initialization
    遵循Python的语法进行消息变量的实例化。有三种方式:无参数、顺序参数、关键字参数。

    • No arguments

      msg = std_msgs.msg.ColorRGBA( )
      msg.b=255
      msg.a=121

    • In-order arguments (*args)

      msg = std_msgs.msg.ColorRGBA(255.0, 255.0, 255.0, 128.0)

    • Keyword arguments (**kwds)

      msg = std_msgs.msg.ColorRGBA(b=255)

    三种方式各有利弊。官方推荐用keyword方式,能更好的适应message类型定义的变化。

Publishers and Subscribers

  • rospy.Publisher initialization

    pub = rospy.Publisher(‘topic_name’, std_msgs.msg.String, queue_size=10)

    其它参数:

    • subscriber_listener=rospy.SubscribeListener
      当有subscriber连接或断开时的回调函数。
    • tcp_nodelay=False
      是否使能TCP_NODELAY 功能。传输低延迟,也更耗资源。
    • latch=False
      是否使能链接锁存功能。保存最后发送的数据,再有新链接时发送锁存数据。有利于比如map这类改变很小的大数据量消息。
    • headers=None (dict)
      在建立链接时的header中加入自定义的键值对(dict类型)。
    • queue_size=None (int)
      这个很重要!!!见下面详解。
  • Publisher.publish()
    遵循Python语法,有三种方式调用publish()函数:

    • 显式方法:

      pub.publish(std_msgs.msg.ColorRGBA(255, 255, 255, 128))

    • 隐式(顺序参数)方法:

      pub.publish(255, 255, 255, 128)

    • 隐式(关键字参数)方法:

      pub.publish(b=255)

  • queue_size: 发送模式
    因为历史原因向后兼容,rospy中的publish()默认是阻塞式同步发送模式。这将导致连接断开后publish卡死(比如无线连接的publisher和subscriber)。
    不过,可以将publish和subscribe的queue_size写入一个大于0的值使publish成为异步模式。

  • queue_size:

    • queue_size: None(不建议)
      这将设置为阻塞式同步收发模式!
    • queue_size: 0(不建议)
      这将设置为无限缓冲区模式,很危险!
    • queue_size: 1,2,3
      对于只关心最新数据的sensor消息,可以设为1;
      对于系统负载不高,能及时处理的消息,可以设为1,2,3.
    • queue_size: 10 or more
      一般情况下,设为10 。queue_size太大了会导致数据延迟不同步。
  • _connection_header
    topic连接后,发送的数据中包括header信息,订阅者subscriber可以在回调函数的data中查看header信息:data._connection_header。内部可能包含的内容为:

    {‘callerid’: ‘/talker_38321_1284999593611’,
    ‘latching’: ‘0’,
    ‘md5sum’: ‘992ce8a1687cec8c8bd883ec73ca41d1’,
    ‘message_definition’: ‘string data\n\n’,
    ‘topic’: ‘/chatter’,
    ‘type’: ‘std_msgs/String’}

    发布者talker可以在创建topic时添加自定义的header内容,示例为:

    pub = rospy.Publisher(‘topic_demo’, String, headers={‘cookies’:’hello’}, queue_size=10)

Services

  • Service definitions

    • 自定义的msg和srv,在catkin_make时被自动生成为python模块源码,存储在“{YOUR_CATKIN_WS}/devel/lib/python2.7/dist-packages”目录下。
    • srv文件和Python模块的对应关系如下:

      my_package/srv/Foo.srv → my_package.srv.Foo
      my_package/srv/Foo.srv → my_package.srv.FooRequest
      my_package/srv/Foo.srv → my_package.srv.FooResponse

    • 需要source {YOUR_CATKIN_WS}/devel/setup.bash将模块目录添加到PYTHONPATH环境变量中,才能在python代码中用from x.srv import * 的形式引入srv模块。

  • Service proxy

    • client端用proxy代理建立同service的通信:

      add_two_ints = rospy.ServiceProxy(‘add_two_ints’, AddTwoInts)

    • 可以用rospy.wait_for_service()阻塞等待service存在。

    • 构建Request实例的方式同样有三种:显示方法、隐式(顺序参数)方法、隐式(关键字参数)方法。
  • exceptions
    service可能抛出3种异常:

    • TypeError
      Request类型不正确!
    • ServiceException
      与远程service连接失败!
    • ROSSerializationException
      数据异常!
  • Persistent connections
    client设置ServiceProxy()参数persistent=True将建立持久连接,否则默认为每次都是连接-通信-断开。
    持久连接比较脆弱,不推荐!

  • Service connection headers
    service的server和client通信数据中也带有header信息,client端可自定义添加其它信息到header中。

    h = { ‘cookies’ : ‘peanut butter’ }
    s = rospy.ServiceProxy(‘foo’, Foo, headers=h)

    在request和response中都可以查看header数据:

    request._connection_header
    response._connection_header

Parameter Server

  • Getting parameters

    global_name = rospy.get_param(“/global_name”)
    relative_name = rospy.get_param(“relative_name”)
    private_param = rospy.get_param(‘~private_name’)
    default_param = rospy.get_param(‘default_param’, ‘default_value’)
    # fetch a group (dictionary) of parameters
    gains = rospy.get_param(‘gains’)
    p, i, d = gains[‘P’], gains[‘I’], gains[‘D’]

  • Setting parameters

    rospy.set_param(‘a_string’, ‘baz’)
    rospy.set_param(‘~private_int’, 2)
    rospy.set_param(‘list_of_floats’, [1., 2., 3., 4.])
    rospy.set_param(‘bool_True’, True)
    rospy.set_param(‘gains’, {‘p’: 1, ‘i’: 2, ‘d’: 3})

  • Deleting parameters

    rospy.delete_param(param_name)

  • Parameter existence
    执行get_param()和delete_param()前,最好检查一下参数名是否存在。否则会引发KeyError异常。

    rospy.has_param(param_name)

Logging

  • Reading log messages
    每个node都可以发送log,可以在4的地方读取这些logs:
Debug Info Warn Error Fatal
stdout X
stderr X X X
log file X X X X X
/rosout o X X X X

Time

  • time和duration是rospy中两个重要的时间概念。
    两者单位一样,直接print则是纳秒。数值形式一样:

    int32 secs
    int32 nsecs

    time时刻,类型是rospy.Time。
    duration时段,类型是rospy.Duration。

  • 时刻和时段之间的计算关系:

    two_hours = rospy.Duration(60*60) + rospy.Duration(60*60)
    one_hour = rospy.Duration(2*60*60) - rospy.Duration(60*60)
    tomorrow = rospy.Time.now() + rospy.Duration(24*60*60)
    negative_one_day = rospy.Time.now() - tomorrow

  • timer

    rospy.Timer(period, callback, oneshot=False)

    在callback函数中参数为event:rospy.TimerEvent。TimerEvent的内部属性包括:

    • current_expected: 理想值,这次callback的被调用时刻。
    • current_real: 现实值,这次callback的被调用时刻。
    • last_expected: 上次的理想值。
    • last_real: 上次的现实值。
    • last_duration: 上次callback的持续时段。

Exceptions

除了python体系内的异常类型,rospy还有下面几种exception异常类型:
- ROSException: ROS相关异常的基类。
- ROSSerializationException: ROS消息串行化异常!
- ROSInitException: ROS初始化异常!
- ROSInterruptException:ROS中断异常!
- ROSInternalException:ROS内部异常!
- ServiceException:Service通信异常!

2. rospy_tutorials示例包

主页:http://wiki.ros.org/rospy_tutorials
源码:https://github.com/ros/ros_tutorials/tree/indigo-devel/rospy_tutorials

rospy_tutorial是ros_tutorial组中的一个package,提供了基本代码示例,便于初学者学习。ros_tutorial在安装desktop-full完整版ros时一并安装了。但是为了便于从源码学习理解,建议删除卸载掉ros_tutorial包及相关依赖包(roscpp_tutorial和rospy_tutorial)

sudo apt-get remove ros-indigo-ros-tutorial

rospy_tutorial包中包括了rospy的大部分常用概念和示例。可以将这个包下载到自己的catkin_workspace下,运行catkin_make编译。

catkin_make将在devel/lib/python2.7/dist-packages/目录下生成msg和srv的模块py文件。

然后,source devel/setup.bash后,就可以用roslaunch或rosrun运行了。也可以直接用python方式运行py文件,和rosrun一样的效果。

注意:自己创建的python文件需要 chmod +x YOUR.py增加执行权限,才能被rosrun补全tab识别。

你可能感兴趣的:(Robot,Python)