描述
- ROS是一个开发机器人软件的框架,软件被设计成许多互相之间高速传递信息的小程序。
- ROS是一个介于典型客户端/服务器系统和完全分布式系统之间,因为有一个处于中央角色的roscore在为点对点信息服务提供命名服务。
- ROS节点交换信息的渠道叫做话题(topic),一个定义了类型的消息流。
- ROS对大量的底层实现进行了封装,很多网络编程中常见的概念在这里被封装成了高级接口。
- ROS图中的节点表示的是独立运行的程序,而图中的边表示数据流。这些数据可以是传感器的数据、执行器的命令、规划器的状态等信息。
辅助工具
- 介绍:catkin是ROS的构建系统:ROS用于可执行程序、库、脚本和其他代码可以用的接口的一系列工具。
- 技巧:使用
rqt_graph
可以清晰看到当前启动节点的ROS图。 - 技巧:使用
rostopic
检查当前系统状态。相关帮助使用$rostopic -h
进行查看 - 技巧:可以使用
rosmsg
来查看是否有已经满足你的需求的类型
软件结构
ROS以包括代码、数据和文档在内的包的形式进行管理。
核心结构
graph BT roscore(roscore) node1(node1) node2(node2) subgraph ros system roscore subgraph nodes node1 node2 end roscore -.->node1 roscore -.->node2 end
- 当一个新节点出现时,roscore向它提供连接其他节点的必要信息。
- 每个节点周期性地调用roscore提供的服务找到其他节点。
- 节点之间的信息交换是两个节点直接完成的
软件结构
graph TD subgraph "3.cd到ws" subgraph 编译包 make_file end subgraph 运行节点 initialisation_run run launch end end subgraph "2.cd到ws下src" subgraph 初始化工作区 initialisation_ws end subgraph 创建包 create_pkg modify_info end end subgraph "1.系统环境" subgraph ROS环境配置 install initialisation_ros end subgraph 创建工作目录 mk_ws_dir mk_src_dir end end install--> initialisation_ros-.-> mk_ws_dir--> mk_src_dir initialisation_ws-..-> create_pkg--> modify_info make_file-..-> initialisation_run-->run initialisation_run-->launch
系统路径/任意
- 确保ROS1安装正确
- 执行ROS初始化:
$source /opt/ros/<ROS1版本名称>/setup.bash
- 新建工作目录:
$mkdir -p <新建工作区路径>/src
,-p
parent参数表示按路径创建,同时创建src
文件夹。
cd
到工作区下的src文件夹
- 初始化工作区
- 执行工作区初始化命令:
$catkin_init_workspace
- 新建包
- 执行新建包命令:
$catkin_create_pkg <新包名称> rospy [<其他的依赖包>]
- 修改新创建的
package.xml
,添加包信息,例如版本号和包依赖等等。注意:包名称不允许修改。
cd
到工作区ws下
- 编译工作区
- 执行
catkin_make
- 运行编译好的包
cd
到工作区- 执行环境初始化:
$source devel/setup.bash
- 运行:
$rosrun <包名> <包内可执行程序/python脚本> [<其他参数>]
(默认已经启动roscore
)- 运行:
$roslaunch <包名> <包内.launch文件>
程序细节
命名问题
- 命名空间概念
- ROS使用
/
来分隔命名空间,像是我们的文件系统一样
- ROS使用
- 命名处理方法
在程序运行指令后按照下面的格式添加重命名规则。- 消息重命名:
$rosrun <包名> <程序名> <消息名>:=<新消息名>
- 命名空间重映射:
$rosrun <包名> <程序名> __ns:=<新命名空间名称>
。ns
naming space,所有消息全部转移到新的命名空间,简单来讲就是所有名称前多了新命名空间的路径 - 节点重命名:
$rosrun <包名> <程序名> __name:=<新节点名>
详见:【机器人】ROS程序运行指北
- 消息重命名:
自动化问题
包内有代码,部分代码作为可执行程序存在,一个包会有很多的可执行程序,在包内程序执行一系列合作任务的时候使用.launch实现自动化。
launch文件结构:树状XML结构
1
2
3
4
5
6
7
8 - launch
- node
- name="<节点名称>"
- pkg="<包名>"
- type="<软件名>"
- output="screen",这是一个调试的方法,输出到终端。调试完成后可以去掉,以保证终端的干净。
- node
- ···
类型问题
- 基本类型列表
ROS消息类型 | 序列化结果 | C++类型 | Python类型 | 注释 |
---|---|---|---|---|
bool | Unsigned 8-bit integer | uint8_t | Boolean | |
int8 | Signed 8-bit integer | int8_t | Int | |
uint8 | Unsigned 8-bit integer | uint8_t | Int | uint[]8 在python中以String表示 |
int16 | Signed 16-bit integer | int16_t | Int | |
uint16 | Unsigned 16-bit integer | uint16_t | Int | |
int32 | Signed 32-bit integer | int32_t | Int | |
uint32 | Unsigned 32-bit integer | uint32_t | Int | |
int64 | Signed 64-bit integer | int64_t | Int | |
uint64 | Unsigned 64-bit integer | uint64_t | Int | |
float32 | 32-bit IEEE float | float | Float | |
float64 | 64-bit IEEE float | double | Float | |
string | ASCII string | std::string | String | ROS不支持Unicode字符串,需要用UTF-8编码 |
time | secs/nsecs unsigned 32-bit ints | rows::Time | rospy.Time | duration |
- 注意python中的类型和ROS内置类型存在差异,犹如c++的int8和python的Int(32位)。所以在Python使用范围受限的ROS类型时一定要小心。
- ROS中的类型已经很丰富了,可以使用
rosmsg
来查看是否有已经满足你的需求的类型。推荐优先使用已有类型,可以更方便与已有包/软件交互。如果没有,那么可以就需要自定义。
graph TD subgraph cd到ws下的src下的包下的msg subgraph 新建 msg_new["编辑<类名>.msg文件"] --> catkin_make1[catkin_make]--> build_depend[确认package.xml文件]--> cmak[编辑CMake.txt文件] end subgraph 修改 msg_edit["编辑<类名>.msg文件"]--> catkin_make2[catkin_make]-.如果存在调用关系..-> catkin_make_other end end
自定义消息
- 自定义消息在包下的
msg
目录中的消息定义文件说明。- 自定义消息
<类名>.msg
文件结构
- 一个
<类型> <名称>
的列表- 定义以后使用
catkin_make
进行编译/处理,生成一系列文件。- 添加消息构建依赖到
package.xml
- 修改
CMakeLists.txt
文件
更改自定义类型
- 那么需要重新运行
catkin_make
,否则python会一直使用旧版本的消息类。- 而且因为消息是有一个MD5验证的,为了确保消息是正确版本,所以你需要对每一个使用了这个类型的包重新使用
catkin_make
来保证校验成功。- 综上所述,尽量不要去改类型。
ROS代码部分
工程示例和解析,请参见博客文章:TODO已经在写了,待更新。
参考
- 《ROS机器人编程实践》