实验编号: 实验指导书 实验项目: ROS基本元素实验 所属课程: ROS机器人操作系统基础与实战 课程代码: 面向专业: 机电专业 课程负责人: 朱笑笑 年月 日
实验编号: 实 验 指 导 书 实验项目: ROS 基本元素实验 所属课程: ROS 机器人操作系统基础与实战 课程代码: 面向专业: 机电专业 课程负责人: 朱笑笑 年 月 日
实验目的 通过实际动手操作和观察体验,让学生熟悉OS程序的创建、运行、编译等。 、 实验内容 1 运行一个已安装Node 2. 编写一个程序 3. 观察ROS计算图结构的性质 三、 实验过程或其他示意图 1.运行一个已安装Node 通过ROS己有安装的包对各种计算图元素进行测试。rqt_graph命令显示当前环境的计算 图结构 1.1用roscoret命令开启master roscore是在运行所有ROS程序前首先要运行的命令。有如下类似输出信息: ..logging to ~/.ros/log/9cf88ce4-b14d-11df-8a75-00251148e8cf/roslaunch- machine name-13039.log Checking log directory for disk usage.This may take awhile. Press Ctrl-C to interrupt Done checking log file disk usage.Usage is <1GB. started roslaunch server http://machine name:33919/ ros_comm version 1.4.7 SUMMARY ======== PARAMETERS */rosversion /rosdistro NODES auto-starting new master process[master]:started with pid [13054] ROS_MASTER_URI=http://machine name:11311/ setting /run_id to 9cf88ce4-b14d-11df-8a75-00251148e8cf -2-
- 2 - 一、 实验目的 通过实际动手操作和观察体验,让学生熟悉ROS程序的创建、运行、编译等。 二、 实验内容 1. 运行一个已安装Node 2. 编写一个程序 3. 观察ROS计算图结构的性质 三、 实验过程或其他示意图 1. 运行一个已安装Node 通过ROS已有安装的包对各种计算图元素进行测试。rqt_graph命令显示当前环境的计算 图结构 1.1 用roscore命令开启master roscore 是在运行所有ROS程序前首先要运行的命令。有如下类似输出信息: ... logging to ~/.ros/log/9cf88ce4-b14d-11df-8a75-00251148e8cf/roslaunch- machine_name-13039.log Checking log directory for disk usage. This may take awhile. Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http://machine_name:33919/ ros_comm version 1.4.7 SUMMARY ======== PARAMETERS * /rosversion * /rosdistro NODES auto-starting new master process[master]: started with pid [13054] ROS_MASTER_URI=http://machine_name:11311/ setting /run_id to 9cf88ce4-b14d-11df-8a75-00251148e8cf
process[rosout-1]:started with pid [13067] started core service [/rosout] l.2.rosnode使用 打开一个新的终端,可以使用rosnode像运行roscore一样看看在运行什么.… rosnode有以下功能: rosnode list:显示当前活动的node rosnode info node:打印node的信息 rosnode kill node:关闭一个node或者发送一个信号 rosnode machine hostname:显示在一台特定主机上运行的node或者显示主机列表 rosnode ping node:测试node的可连接性 rosnode cleanup:清除已经失效的node 在终端中运行 rosnode list 将会返回 /rosout 这表示当前只有一个节点在运行:rOs0ut。因为这个节点用于收集和记录节点调试输出 信息,所以它总是在运行的。 测试rosnode info命令 rosnode info /rosout 返回 Node [/rosout] Publications: /rosout agg [rosgraph_msgs/Log] Subscriptions: /rosout [unknown type] Services: /rosout/set logger level */rosout/get_loggers contacting node http://machine name:54614/... -3-
- 3 - process[rosout-1]: started with pid [13067] started core service [/rosout] 1.2. rosnode 使用 打开一个新的终端, 可以使用 rosnode 像运行 roscore 一样看看在 运行什么... rosnode有以下功能: rosnode list: 显示当前活动的node rosnode info node: 打印node的信息 rosnode kill node: 关闭一个node或者发送一个信号 rosnode machine hostname: 显示在一台特定主机上运行的node或者显示主机列表 rosnode ping node: 测试node的可连接性 rosnode cleanup: 清除已经失效的node 在终端中运行 rosnode list 将会返回 /rosout 这表示当前只有一个节点在运行: rosout。因为这个节点用于收集和记录节点调 试输出 信息,所以它总是在运行的。 测试 rosnode info 命令 rosnode info /rosout 返回 ------------------------------------------------------------- ----------- Node [/rosout] Publications: * /rosout_agg [rosgraph_msgs/Log] Subscriptions: * /rosout [unknown type] Services: * /rosout/set_logger_level * /rosout/get_loggers contacting node http://machine_name:54614/
Pid:5092 1.3运行rosrun rosrun 允许你使用包名直接运行一个包内的节点(而不需要知道这个包的路径)。 用法: rosrun[package_name][node_name]/运行一个ROS包中的一个node rosrun package node_parameter:=value/运行node时将parameter参数设置为 value 其中parameter可以是用户自定义的参数,或者是系统定义的参数如: _name:This is a special reserved keyword for the name of the node _log:This is a reserved keyword that designates the location where the _ip andhostname:These are substitutes for ROS IP and ROS HOSTNAME _master:This is a substitute for ROS MASTER URI _ns:This is a substitute for ROS NAMESPACE rosrun package node topicoldName:newName /运行node将其中的一个topic的名字修改为newName rosrun --prefix 'gdb -ex run --args'my_package my_node /-prefix前缀用于调试 现在我们可以运行turtlesim包中的turtlesim node。 然后,在一个新的终端: rosrun turtlesim turtlesim node 你会看到turtlesim窗口: -4-
- 4 - Pid: 5092 1.3 运行 rosrun rosrun 允许你使用包名直 接运行一个包内的节点(而不需要知道这个包的路径)。 用法: rosrun [package_name] [node_name] //运行一个 ROS 包中的一个 node rosrun package node _parameter:=value //运行 node 时将 parameter 参数设置为 value 其中 parameter 可以是用户自定义的参数,或者是系统定义的参数如: __name: This is a special reserved keyword for the name of the node __log: This is a reserved keyword that designates the location where the __ip and __hostname: These are substitutes for ROS_IP and ROS_HOSTNAME __master: This is a substitute for ROS_MASTER_URI __ns: This is a substitute for ROS_NAMESPACE rosrun package node topicOldName: = newName //运行 node 将其中的一个 topic 的名字修改为 newName rosrun --prefix 'gdb -ex run --args' my_package my_node //--prefix 前缀用于调试 现在我们可以运行 turtlesim 包中的 turtlesim_node。 然后, 在一个新的终端: $ rosrun turtlesim turtlesim_node 你会看到 turtlesim 窗口:
TurtleSim ✉× 2.编写一个程序 编写一个发送端,监听端程序。 2.1新建一个文件夹作为堆 cd ~/catkin ws/src mkdir -p chapter2/intro to ros cd chapter2/intro to ros 2.2创建一个talker的R0S包 利用catkin_create_,pkg命令创建一个名为talkerf的,后面几项std_msgs roscpp为这个 ROS包的一些依赖项。 catkin create pkg talker std msgs roscpp 创建完成后我们可以观察生成的文件结构, talker/ CMakeLists.txt package.xml 我们再创建一个src文件夹 cd talker mkdir src cd src 创建一个talker.cpp文件 gedit talker.cpp -5-
- 5 - 2.编写一个程序 编写一个发送端,监听端程序。 2.1新建一个文件夹作为堆 cd ~/catkin_ws/src mkdir –p chapter2/intro_to_ros cd chapter2/intro_to_ros 2.2创建一个talker的ROS包 利用catkin_create_pkg命令创建一个名为talker的,后面几项std_msgs roscpp为这个 ROS包的一些依赖项。 catkin_create_pkg talker std_msgs roscpp 创建完成后我们可以观察生成的文件结构, talker/ CMakeLists.txt package.xml 我们再创建一个src文件夹 cd talker mkdir src cd src 创建一个talker.cpp文件 gedit talker.cpp
输入以下程序 #include "ros/ros.h" /ROS基本头文件 #include "std_msgs/String.h" /标准message类型库 #include /字符串处理头文件 int main(int argc,char **argv){ ros:init (argc,argv,"talker"); /Node初始化,名字为talker ros:NodeHandle n; /Node变量 ros:Publisher chatter_pub =n.advertise("chatter", 100o):/定义一个名为“chatter”的Topics,可以发布标准的String类型Messages。其 中1000为发送队列最大的容量 ros:Rate loop_.rate(1);/定义循环周期为ls int count=0;/计数变量 while (ros:ok()){ std_msgs:String msg; //定义标准的String消息变量 std:stringstream ss; ss "hello world "count; msg.data ss.str(); /川为消息变量赋值 ROS_INF0("%s”,msg.data.c_str(O);/打印消息变量的值 chatter_pub.publish(msg);/发布消息 ros:spinOnce(; /ros处理系统中所有的消息 loop_rate.sleep(); /根据定义的循环时间进行休眠 ++count; /技术变量累加 } return 0; 2.3创建一个listener的R0S包 同上创建一个listener包,并创建src文件及,新建listener.cpp文件并输入以下内容 #include"ros/ros.h”/ROS基本头文件 #include"std_msgs//String.h”/字符串处理头文件 /topicl回调函数,将收到的信息打印出来 void chatterCallback(const std_msgs:String:ConstPtr msg){ ROS_INFO("I heard:[%s]",msg->data.c_str()); int main(int argc,char **argv){ ros:init(argc,argv,"listener");/Node初始化,名字为1 listener ros:NodeHandle n;/Node变量 ros:Subscriber sub n.subscribe("chatter",1000,chatterCallback); /定义对名为“chatter”的topic的订阅,回调函数为chatterCallback,消息缓冲队列最 大的1000个 ros:spin(); //ROS循环处理系统消息 -6-
- 6 - 输入以下程序 #include "ros/ros.h" //ROS基本头文件 #include "std_msgs/String.h" //标准message 类型库 #include //字符串处理头文件 int main(int argc, char **argv) { ros::init(argc, argv, "talker"); //Node 初始化,名字为talker ros::NodeHandle n; //Node 变量 ros::Publisher chatter_pub = n.advertise("chatter", 1000); //定义一个名为“chatter”的Topics,可以发布标准的String类型 Messages。其 中1000为发送队列最大的容量 ros::Rate loop_rate(1); //定义循环周期为1s int count = 0; //计数变量 while (ros::ok()) { std_msgs::String msg; //定义标准的String消息变量 std::stringstream ss; ss data.c_str());} int main(int argc, char **argv) { ros::init(argc, argv, "listener"); //Node 初始化,名字为listener ros::NodeHandle n; // Node 变量 ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback); // 定义对名为“chatter”的topic的订阅,回调函数为chatterCallback,消息缓冲队列最 大的1000个 ros::spin(); //ROS循环处理系统消息
return 0; } 2.4编译程序 2.4.1对每一个R0S都需要做以下两步 修改程序依赖项。在package..xml文件中可以添加依赖项,初始的文件如下,如果程序中 用到其它的功能库,则需要在该文件中加入。 。。 catkin roscpp std msgs 修改CMakelist.txt文件。该文件管理具体编译的一些参数,如一些编译的标志,编译 的对象,名称等等。在初始文件基础上,需修改以下内容: 声明编译结果,这里是可执行文件,名字为talker_node,源文件为talker.cpp。这里 可以指定多个输出文件,一个包可以包含多个执行文件或者库文件。这样也可以理解rosrun 的调用格式,小先指定包然后指定node名字。 #Declare a C++executable add_executable(talker_node src/talker.cpp) 声明连接的库文件。这里catkin LIBRARIES既是由上面package..xml导入的。 target_link_libraries(talker_node $(catkin_LIBRARIES}) 2.4.2利用catkin make完成工作空间内文件的编译。 cd ~/catin ws/ catkin make 2.5运行程序 在一个终端运行roscore roscore 在新终端运行talker rosrun talkertalker node 在新终端运行listener s rosrun listener listener node -7-
- 7 - return 0; } 2.4 编译程序 2.4.1对每一个ROS都需要做以下两步 修改程序依赖项。在package.xml文件中可以添加依赖项,初始的文件如下,如果程序中 用到其它的功能库,则需要在该文件中加入。 ... catkin roscpp std_msgs ... 修改CMakelist.txt文件。该文件管理具体编译的一些参数,如一些编译的标志,编译 的对象,名称等等。在初始文件基础上,需修改以下内容: 声明编译结果,这里是可执行文件,名字为talker_node,源文件为talker.cpp。这里 可以指定多个输出文件,一个包可以包含多个执行文件或者库文件。这样也可以理解rosrun 的调用格式,小先指定包然后指定node名字。 ## Declare a C++ executable add_executable(talker_node src/talker.cpp) 声明连接的库文件。这里catkin_LIBRARIES既是由上面package.xml导入的。 target_link_libraries(talker_node ${catkin_LIBRARIES} ) 2.4.2 利用catkin_make完成工作空间内文件的编译。 cd ~/catin_ws/ catkin_make 2.5 运行程序 在一个终端运行roscore roscore 在新终端运行talker $ rosrun talker talker_node 在新终端运行listener $ rosrun listener listener_node
3.观察R0S计算图结构的性质 3.1利用rqt_graph命令观察整体的图结构,并选择不同细节显示模式。 3.2利用rosnode命令观察系统中节点的属性 3.3利用rostopici观察系统中topicl的情况 3.4利用Ctrl+c关闭两个node,观察两个node不同的启动顺序对效果的影响,体验ROS的通 讯机制。 四、 实验原理及原始计算数据、所应用的公式 ROS图结构包括以下关键部分 Nodes Master Parameter Server Messages Computation Graph Level Topics Services Bags Nodes::节点主要执行计算处理。ROS被设计为细粒度的模块化的系统;一个机器人控 制系统通常有很多节点组成。例如,一个节点控制激光测距仪,一个节点控制轮电机, 一个节点执行定位,一个节点执行路径规划,一个节点提供系统图形界面,等等。一个 ROS节点通过ROS客户端库client library编写,例如roscpp o或rospy Master::ROS Master为计算图的其余部分提供名称注册和查找。如果没有Master,节 点将无法找到对方,交换消息或调用服务。 Parameter Server:参数服务器允许通过密钥将数据存储在中央位置。它目前是师父的 一部分。 Messages:节点通过传递消息相互通信。消息只是一个数据结构,包含类型字段。标准 的基本类型(整型,浮点型,布尔型等)和原始类型的数组都是受支持的。消息可以包 含任意嵌套的结构和数组(很像C结构)。 Topics::消息通过具有发布/订阅语义的传输系统进行路由。节点通过将消息发布到给定 主题来发送消息。该主题是用于标识消息内容的名称。对某种数据感兴趣的节点将订阅 适当的主题。单个主题可能有多个并发发布者和订阅者,并且单个节点可以发布和/或 订阅多个主题。一般而言,发布者和订阅者不知道彼此的存在。这个想法是将信息的生 产与其消费分离开来。从逻辑上讲,人们可以把一个主题看成一个强类型的消息总线。 每个公共汽车都有一个名字,只要他们是正确的类型,任何人都可以连接到公共汽车发 送或接收消息。 Services:发布/订阅模型是一种非常灵活的通信模式,但是其多对多的单向传输不适合 于分布式系统中经常需要的请求/回复交互。请求/回复是通过服务完成的,服务由一对 消息结构定义:一个用于请求,另一个用于回复。提供节点在名称下提供服务,客户端 -8-
- 8 - 3.观察ROS计算图结构的性质 3.1 利用rqt_graph命令观察整体的图结构,并选择不同细节显示模式。 3.2 利用rosnode命令观察系统中节点的属性 3.3 利用rostopic观察系统中topic的情况 3.4 利用Ctrl+c关闭两个node,观察两个node不同的启动顺序对效果的影响,体验ROS的通 讯机制。 四、 实验原理及原始计算数据、所应用的公式 ROS图结构包括以下关键部分 Nodes: 节点主要执行计算处理 。ROS 被设计为细粒度的模块化的系统;一个机器人控 制系统通常有很多节点组成 。例如,一个节点控制激光测距仪,一个节点控制轮电机, 一个节点执行定位,一个节点执行路径规划,一个节点提供系统图形界面,等等。一个 ROS 节点通过 ROS 客户端库 client library 编写,例如 roscpp o 或 rospy Master: ROS Master 为计算图的其余部分提供名称注册和查找。 如果没有 Master,节 点将无法找到对方,交换消息或调用服务。 Parameter Server: 参数服务器允许通过密钥将数据存储在中央位置。它目前是师父的 一部分。 Messages: 节点通过传递消息相互通信。消息只是一个数据结构,包含类型字段。标准 的基本类型(整型,浮点型,布尔型等)和原始类型的数组都是受支持的。消息可以包 含任意嵌套的结构和数组(很像 C 结构)。 Topics: 消息通过具有发布/订阅语义的传输系统进行路由。节点通过将消息发布到给定 主题来发送消息。该主题是用于标识消息内容的名称。对某种数据感兴趣的节点将订阅 适当的主题。单个主题可能有多个并发发布者和订阅者,并且单个节点可以发布和/或 订阅多个主题。一般而言,发布者和订阅者不知道彼此的存在。这个想法是将信息的生 产与其消费分离开来。从逻辑上讲,人们可以把一个主题看成一个强类型的消息总线。 每个公共汽车都有一个名字,只要他们是正确的类型,任何人都可以连接到公共汽车发 送或接收消息。 Services: 发布/订阅模型是一种非常灵活的通信模式,但是其多对多的单向传输不适合 于分布式系统中经常需要的请求/回复交互。请求/回复是通过服务完成的,服务由一对 消息结构定义:一个用于请求,另一个用于回复。提供节点在名称下提供服务,客户端
通过发送请求消息和等待答复来使用服务。ROS客户端库通常将这种交互作用呈现给 程序员,就像它是一个远程过程调用一样。 Bags:用于保存和回放ROS消息数据的格式。数据包是存储数据的重要机制,例如传感 器数据,这些数据可能难以收集,但对于开发和测试算法是必需的。 catkin_make是一个命令行工具,它简化了catkin的标准工作流程。你可以认为 catkin_,make是在CMake标准工作流程中依次调用了cmake和make。 CMake标准工作流程主要可以分为以下几个步骤: #在一个CMake项目里 mkdir build ed build cmake.. make $make install#(可选) 每个CMake工程在编译时都会执行这个操作过程。 五、 实验数据记录 无 六、实验结果计算及曲线 无 七、 对实验结果和实验中某些现象的分析讨论 八、 实验方法指示及注意事项 九、 实验仪器环境要求 十、 对学生的要求 掌握ROS包的创建,简单程序的开发、运行。了解ROS图的工作模式,查看办法 十一、参考文献与资料 1.http://wiki.ros.org/cn/ROS/Tutorials/CreatingPackage 十二、备注 -9
- 9 - 通过发送请求消息和等待答复来使用服务。 ROS 客户端库通常将这种交互作用呈现给 程序员,就像它是一个远程过程调用一样。 Bags:用于保存和回放 ROS 消息数据的格式。数据包是存储数据的重要机制,例如传感 器数据,这些数据可能难以收集,但对于开发和测试算法是必需的。 catkin_make 是一个命令行工具,它简化了 catkin 的标准工作流程。你可以认为 catkin_make 是在 CMake 标准工作流程中依次调用了 cmake 和 make。 CMake 标准工作流程主要可以分为以下几个步骤: # 在一个 CMake 项目里 $ mkdir build $ cd build $ cmake .. $ make $ make install # (可选) 每个 CMake 工程在编译时都会执行这个操作过程。 五、 实验数据记录 无 六、 实验结果计算及曲线 无 七、 对实验结果和实验中某些现象的分析讨论 八、 实验方法指示及注意事项 九、 实验仪器环境要求 十、 对学生的要求 掌握ROS包的创建,简单程序的开发、运行。了解ROS图的工作模式,查看办法 十一、参考文献与资料 1. http://wiki.ros.org/cn/ROS/Tutorials/CreatingPackage 十二、备注