1. Parameter Server
参数服务器是和 ros Master 属于同一进程的另一项功能模块。参数服务器通过维护一个字符串到各类数据的键值表,在一个网络可访问的数据库中储存系统的各项配置参数。各个节点可以对参数服务器进行读写。
ros 中的参数是用来进行配置,而不是进行数据通信的。用 ros 参数在节点中交换高频或大容量数据,你会发现性能完全跟不上,此类需求应该用 ros 消息来实现。
参数服务器的维护方式非常的简单灵活,总的来讲有三种方式:
(1)可以在node源文件代码中用 API 访问:
rospy.get_param()
rospy.set_param()
spy.search_param()
rospy.has_param()
rospy.delete_param()
rospy.get_param_names()
(2)用命令行工具 rosparam
与参数服务器交互。
(3)launch文件内读写。实际项目中我们对参数进行设置,尤其是添加参数,一般都不是在程序中,而是在launch文件中。因为launch文件可以方便的修改参数,而写成代码之后,修改参数必须重新编译。 因此我们会在launch文件中将param都定义好。详见:roslaunch 详解。
2. 时钟 Time、Duration、Rate
rospy中的关于时钟的操作和roscpp是一致的,都有Time、Duration和Rate三个类。
Time和Duration前者标识的是某个时刻(例如今天22:00),而Duration表示的是时长(例如一周)。但他们具有相同的结构(秒和纳秒)。Rate的功能是指定一个频率,让某些动作按照这个频率来循环执行。
Time 和 Duration 之间可以进行加减运算(Time+Duration),但要注意没有Time+Time的做法。
duration1 = rospy.Duration(3*60) #创建3min时长
time_now1 = rospy.get_rostime() # or rospy.Time.now() 当前时刻的Time对象 返回Time对象
time_now2 = rospy.Time.now() + duration # Time加减Duration返回都是Time
duration2 = time_now2 - time_now1 #从t1到t2的时长,两个Time相减返回Duration类型
duration3 = duration2 - rospy.Duration(2*60) # 两个Duration相减,还是Duration
time_now3 = rospy.get_time() #得到当前时间,返回float 4单位秒
time_4 = rospy.Time(5) #创建5s的时刻
3. 定时器 Timer
rospy.Timer(Duration, callback)
def my_callback(event):
print 'Timer called at ' + str(event.current_real)
rospy.Timer(rospy.Duration(2), my_callback) # 第一个参数是时长,第二个参数是回调函数。
#每2s触发一次callback函数
rospy.spin() # 只有spin才能触发回调函数
回调函数的传入值是TimerEvent类型。
4. Log
ROS为开发者和用户提供了一套日志记录和输出系统,这套系统的实现方式是基于topic,也 就是每个节点都会把一些日志信息发到一个统一的topic上去,这个topic就是 /rosout 。 rosout 本身也是一个node,它专门负责进行日志的记录。我们在启动master的时候,系统就
会附带启动rosout。
包括了五个级别的
DEBUG INFO WARN ERROR FATAL
用法
rospy.loginfo(“info”,vel)
5. TF
wiki.ros/tf
tf/Tutorials
TF的相关数据类型,向量、点、四元数、矩阵都可以表示成类似数组形式,就是它们都可以 用Tuple,List,Numpy Array来表示:
例如:
t = (1.0,1.5,0) #平移,可以用List表示成 t=[1.0,1.5,0],或 numpy.array(1.0,1.5,0)来表示。
q = [1,0,0,0] #四元数
m = numpy.identity(3) #旋转矩阵
TransformStamped.msg
的格式规范如下:

std_mags/Header header
uint32 seq
time stamp
string frame_id
string child_frame_id
geometry_msgs/Transform transform
geometry_msgs/Vector3 translation
float64 x
float64 y
float64 z
geometry_msgs/Quaternion rotation
float64 x
float64 y
flaot64 z
float64 w
header定义了序号,时间以及frame的名称。
child_frame_id 定义了子link坐标系的 id。
geometry_msgs/Transform 定义了两个frame之间的坐标变换,Vector3三维向量表示平移,Quaternion四元数表示旋转。
TF tree 是由很多的frame之间TF拼接而成。TF树的数据类型为tf2_msgs/TFMessage.msg
。ROS Hydro版本以前的 tf 树为 tf/tfMessage.msg ,现已弃用。
tf.transformations
提供了一些基本的数学运算函数。
tf 常用指令:
rosrun tf view_frames # 生成tf树信息的 frames.pdf 文件,打开pdf可以查看坐标系关系
rosrun rqt_tf_tree rqt_tf_tree # 直接查看tf 树信息
rosrun tf tf_echo [reference_frame] [target_frame] # 两坐标系之间的转换关系
在很多api中,存在着target frame,source frame,parent frame,child frame,这些名字的参数。
source、target frame是在进行坐标变换时的概念,source是坐标变换的源坐标系,target是目标坐标系。
parent、child frame是在描述坐标系变换时的概念。也是child坐标系在parent坐标系下的描述。如果把child固结于一个刚体,那么这个变换描述的就是刚体在parent坐标系下的姿态。
从child到parent的坐标变换等于从parent到child的frame transform。
static_transform_publisher
static_transform_publisher工具的功能是发布两个参考系之间的静态坐标变换,两个参考系一般不发生相对位置变化
标定后发布机器人和相机的关系可以用 static_transform_publisher,
角度可以是四元数也可以是 RPY 角。最后一个是周期,周期越小频率越高.
rosrun tf static_transform_publisher x y z qx qy qz qw frame_id child_frame_id period_in_ms
如果要放到launch中
<launch>
<node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="1 0 0 0 0 0 1 link1_parent link1 100" />
</launch>
6. robot_state_publisher
robot_state_publisher uses the URDF specified by the parameter robot_description and the joint positions from the topic joint_states to calculate the forward kinematics of the robot and publish the results via tf.
7. 如何从另一个ROS包中导入python模块
参考:
ROS Import Python Module From Another Package
How to import python modules from different ROS packages
ROS Package中的Python使用规范
仅需两步:
- 导出 python module 到 ROS 全局命名空间。
- 将可执行文件导出到 ROS 全局命名空间。
例如,现在已经 build 了一个名为 robot_helper 的package:
robot_helper
├── api
│ ├── api.py
│ ├── api2.py
│ ├── my_test_exe
│ └── __init__.py
├── scripts
│ ├── manager.py
├── package.xml
├── CMakeLists.txt
├── setup.py
#And inside the api.py, you have some class
class MY_API():
def __init__(self):
#And inside the api2.py, you have some class
class MY_API2():
def __init__(self):
7.1 export the Python module (class)
- 在
api
文件夹中创建一个空文件__init__.py
. - 创建
setup.py
,以帮助ROS系统找到该程序包。代码如下:
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
setup_args = generate_distutils_setup(
packages=['my_api'],
package_dir={
'': 'api'}
)
setup(**setup_args)
- 在 CMakeLists.txt 文件的
find_package
后添加:
find_package(catkin REQUIRED COMPONENTS
rospy
···
)
## Uncomment if the package has a setup.py
catkin_python_setup()
解析:
catkin_python_setup()
会使 ros 运行setup.py
._init__.py
将文件夹内容公开给setup.py
,如果安全的话,可以将__init__.py
放在程序包的根目录中。packages = ['my_python_stuff']
告诉ROS查找python包,这与python模块无关,不要搞混。package_dir = {'':'api'}
告诉ROS将(./api)中的所有python文件放入全局 python环境中。
现在就可以在其他 packages 中导入 python 模块了,例如:
from api import MY_API
from api2 import MY_API2
install the executable
你可以在CMakeLists中找到:
## this is used only when you have a script and want to make is an executable
# catkin_install_python(PROGRAMS api/my_test_exe
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
the my_test_exe
is actually the file you created and made +x
to it.
This my_test_exe
is available inside the CMakeList Project name that is:
rosrun robot_helper my_test_exe
这会将包中所有的script 和 launch文件安装到系统lib文件夹中,以便所有python的脚本都可以访问该模块。