ROS之命令与编程实践
参考资料
- 古月居ROS21讲
- ROSwiki
ROS命令行概述
- 
roscore启动命令 
- 
rosrun rosrun [package_name] [node_name] #允许你使用包名直接运行一个包内的节点(而不需要知道这个包的路径)。 
- 
rosls rosls是rosbash命令集中的一部分,它允许你直接按软件包的名称而不是绝对路径执行ls命令(罗列目录). rosls beginner_tutorials/ 
 CMakeLists.txt include package.xml src
- 
roscd log 使用roscd log可以切换到ROS保存日记文件的目录下。需要注意的是,如果你没有执行过任何ROS程序,系统会报错说该目录不存在。 
- 
rosed rosed 是 rosbash 的一部分。利用它可以直接通过package名来获取到待编辑的文件而无需指定该文件的存储路径了。 rosed [package_name] [filename] 这个实例展示了如何编辑roscpp package里的Logger.msg文件。 
- 
rospack命令 rospack允许你获取软件包的有关信息 rospack find roscpp 
 /opt/ros/kinetic/share/roscpp
 rospack list #显示出当前的包信息
 rospack depends1 beginner_tutorials #显示当前包的一级依赖
 rospack depends beginner_tutorials #显示当前包的所有依赖
- 
rqt rqt_graph #显示计算图 
- 
rosnode rosnode ping 节点名 #测试节点的联通情况 
 rosnode list #显示全部节点
 rosnode info 节点名 #显示节点信息
 rosnode machine #显示当前机器
 rosnode kill 节点名 #结束一个正在运行的node
 rosnode cleanup #清除无法访问的节点的注册信息
- 
rostopic rostopic bw #显示主题使用的带宽 
 rostopic delay #从标题中的时间戳显示主题的延迟
 rostopic echo #将消息打印到屏幕,可以显 示在某个话题上发布的数据.
 rostopic find #按类型查找主题
 rostopic hz #显示主题的发布率
 rostopic info #打印有关活动主题的信息
 rostopic list #列出活动主题
 -h, --help #(显示此帮助消息并退出)
 -b BAGFILE, --bag=BAGFILE #(列出.bag文件中的主题)
 -v, --verbose #(列出每个主题的完整详细信息)
 -p #(仅列出发布商)
 -s #(仅列出订阅者)
 --host #(按主机名分组)
 rostopic pub #将数据发布到主题
 rostopic type #打印主题或字段类型,命令用来查看所发布话题的消息类型。
- 
rostopic pub rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]' 
 发送一条消息给turtlesim,告诉它以2.0大小的线速度和1.8大小的角速度开始移动。
 这条命令以1Hz的频率发布速度命令到速度话题上。
 rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist"linear:
 x:1.0
 y:0.0
 z:0.0
 angular:
 x:0.0
 y:0.0
 z:0.0"
 /turtle1/cmd_vel话题名
 geometry_msgs/Twist消息结构
 -r 表示循环
- 
rostopic hz rostopic hz /turtle1/pose 
 subscribed to [/turtle1/pose]
 average rate: 62.486
 min: 0.015s max: 0.017s std dev: 0.00047s window: 60
 average rate: 62.476
 min: 0.015s max: 0.018s std dev: 0.00045s window: 122
 average rate: 62.514
 min: 0.014s max: 0.020s std dev: 0.00057s window: 185
 average rate: 62.506
 min: 0.013s max: 0.020s std dev: 0.00061s window: 248
- 
rosmsg rosmsg show geometry_msgs/Twist 
 geometry_msgs/Vector3 linear
 float64 x
 float64 y
 float64 z
 geometry_msgs/Vector3 angular
 float64 x
 float64 y
 float64 z
- 
rosbag 将ROS系统运行过程中的数据录制到一个.bag文件中,然后可以通过回放数据来重现相似的运行过程.退出录制时按Ctrl-C退出该命令,你应该会看到在当前目录下一个以年份、日期和时间命名并以.bag作为后缀的文件。 录制所有发布的话题,其中 -a 选项,该选项表示将当前发布的所有话题数据都录制保存到一个bag文件中。 
 rosbag record -a
 回放bag文件以再现系统运行过程
 rosbag play <your bagfile>
 以某一频率发布消息(控制bag包播放的频率) : rosbag play -r 2
 从某一时间节点开始播放发布消息 : rosbag play -s 2
 rosbag info <your bagfile> #rosbag info 查看bag文件信息
 rosbag record -O 2018-12.bag /turtle1/command_velocity /turtle1/pose
 rosbag record命令支持只录制某些特别指定的话题到单个bag文件中,这样就允许用户只录制他们感兴趣的话题
 rosbag record -a -O 2018-12.bag
 可以使用rosbag info 2018-12.bag 命令查看录制时指定话题的信息.
 也可以只指定bag包的文件名,录制所有数据
 rosbag record --split --duration=5m -e /radar/back_targets /vehicle_speed /imu_data
 录取指定topic,并且每五分钟分割一次, -e为正则匹配。
 rosrun image_view image_view image:=/camera/front_middle compressed
 如果查看视频,就可以实现视频播放功能
创建工作空间和功能包
工程文件 workspace
四个文件夹:
- src代码空间
- build编译空间
- devel开发空间
- install安装空间
| 创建工作空间 | 
发布者publisher编程实现
| 创建功能包 | 
代码放到src目录
创建一个.cpp文件即可,注意文件名不能重复!!
| /** | 
接下来需要编译运行,需要配置CMakeLists.txt中的编译规则
| cmake_minimum_required(VERSION 3.0.2) | 
接下来就可以编译,在你的工作空间的src下
| catkin_make | 
设置环境变量
| source devel/setup.bash | 
也可以在主文件夹下
| cd / | 
接下来就可以执行
| roscore | 
也可用python来完成,首行注意添加 #!/usr/bin/env python
| #!/usr/bin/env python | 
订阅者subscriber的编程实现
项目工程文件夹下src中创建代码
| //pose_subscriber.CPP | 
| 编译执行过程同发布者 | 
| #!/usr/bin/env python | 
话题消息定义与使用
如何自定义一个话题的消息
- 
定义msg文件 在项目文件夹下创建一个msg文件夹,专门存放.msg文件,不能随便命名 string name 
 uint8 sex
 uint8 age
 uint8 unknown = 0
 uint8 male = 1
 uint8 female =2
- 
在package.xml中添加功能包依赖 <build_depend>message_generation</build_depend> 
 <exec_depend>message_runtime</exec_depend>
- 
在CMakeList.txt添加编译选项 # Find catkin macros and libraries 
 # if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
 # is used, also find other catkin packages
 find_package(catkin REQUIRED COMPONENTS
 geometry_msgs
 roscpp
 rospy
 std_msgs
 turtlesim
 message_generation #添加功能包
 )
 # Generate added messages and services with any dependencies listed here
 generate_messages(
 DEPENDENCIES
 geometry_msgs# std_msgs
 )
 add_message_files(FILES Person.msg)
 generate_messages(DEPENDENCIES std_msgs)
 ##################################
 # catkin specific configuration ##
 ##################################
 # The catkin_package macro generates cmake config files for your package
 # Declare things to be passed to dependent projects
 # INCLUDE_DIRS: uncomment this if your package contains header files
 # LIBRARIES: libraries you create in this project that dependent projects also need
 # CATKIN_DEPENDS: catkin_packages dependent projects also need
 # DEPENDS: system dependencies of this project that dependent projects also need
 catkin_package(
 INCLUDE_DIRS include
 LIBRARIES learning_topic
 CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim message_runtime #添加此处
 DEPENDS system_lib
 )
- 
最后直接编译catkin_make编译即可 
客户端Client的编程实现
- 
创建一个新的功能包文件夹 cd ~/catkin_ws/src 
 catkin_create_pkg learnin_service roscpp rospy std_msgs geometry_msgs turtlesim
- 
在learnin_service的src下创建cpp代码 /** 
 *该程序将请求/spawn服务,服务数据类型turtlesim::Spawn
 */
 int main(int argc,char **argv)
 {
 //初始化ROS节点
 ros::init(argc,argv,"turtle_spawn");
 
 //创建节点句柄
 ros::NodeHandle node;
 
 //发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
 ros::service::waitForService("/spawn"); //循环等待
 ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
 
 //初始化turtlesim::Spawn的请求数据
 turtlesim::Spawn srv;
 srv.request.x = 2.0;
 srv.request.y = 2.0;
 srv.request.name = "turtle2";
 
 //请求服务调用
 ROS_INFO("Call service to spwan turtle[x:%0.6f,y:%0.6f,name:%s]",srv.request.x,srv.request.y,srv.request.name.c_str());
 
 add_turtle.call(srv);
 
 //显示服务调用结果
 ROS_INFO("Spwan turtle successfully [name:%s]",srv.response.name.c_str());
 
 return 0;
 }配置编译规则CMakeList.txt add_executable(turtle_spawn src/turtle_spawn.cpp) //设置需要编译的代码和生成的可执行文件; 
 target_link_libraries(turtle_spawn ${catkin_LIBRARIES}) //设置链接库;回到根目录/catkin_ws编译并运行客户端 编译成功后在devel/lib下产生功能包 
服务端Server的编程实现
 在src下turtle_command_server.cpp
| /** | 
配置CMakeLists
| add_executable(turtle_command_server src/turtle_command_server.cpp) | 
编译运行服务器
| cd ~/catkin_ws | 
自定义服务数据
- 
定义srv文件 string name 
 uint8 age
 uint8 sex
 uint8 unknown = 0
 uint8 male = 1
 uint8 female = 2
 --- //之上表示request,之下表示respons
 string result
- 
在package.xml中添加功能包依赖 <build_depend>message_generation</build_depend> 
 <exec_depend>message_runtime</exec_depend>
- 
在CMakeLists.txt提娜佳编译选项 find_package( …… message_generation) 
 add_service_files(FILES Person.srv)
 generate_messages(DEPENDENCIES std_msgs)
 catkin_package(…… message_runtime)
- 
编译生成语言相关文件 
- 
服务端实现 /** 
 * 该例程将请求/show_person服务,服务数据类型learning_service::Person
 */
 
 // service回调函数,输入参数req,输出参数res
 bool personCallback(learning_service::Person::Request &req,
 learning_service::Person::Response &res)
 {
 // 显示请求数据
 ROS_INFO("Person: name:%s age:%d sex:%d", req.name.c_str(), req.age, req.sex);
 // 设置反馈数据
 res.result = "OK";
 return true;
 }
 int main(int argc, char **argv)
 {
 // ROS节点初始化
 ros::init(argc, argv, "person_server");
 // 创建节点句柄
 ros::NodeHandle n;
 // 创建一个名为show_person的erver,注册回调函数ersonCallback
 ros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);
 // 循环等待回调函数
 ROS_INFO("Ready to show person informtion.");
 ros::spin();
 return 0;
 }
- 
客户端实现 /** 
 * 该例程将请求/show_person服务,服务数据类型learning_service::Person
 */
 int main(int argc, char** argv)
 {
 // 初始化ROS节点
 ros::init(argc, argv, "person_client");
 // 创建节点句柄
 ros::NodeHandle node;
 // 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
 ros::service::waitForService("/show_person");
 ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person");
 // 初始化learning_service::Person的请求数据
 learning_service::Person srv;
 srv.request.name = "Tom";
 srv.request.age = 20;
 srv.request.sex = learning_service::Person::Request::male;
 // 请求服务调用
 ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]",
 srv.request.name.c_str(), srv.request.age, srv.request.sex);
 person_client.call(srv);
 // 显示服务调用结果
 ROS_INFO("Show person result : %s", srv.response.result.c_str());
 return 0;
 };配置编译规则 add_executable(person_server src/person_server.cpp) 
 target_link_libraries(person_server ${catkin_LIBRARIES})
 add_dependencies(person_server ${PROJECT_NAME}_gencpp)
 add_executable(person_client src/person_client.cpp)
 target_link_libraries(person_client ${catkin_LIBRARIES})
 add_dependencies(person_client ${PROJECT_NAME}_gencpp)
- 
运行 cd ~/catkin_ws 
 catkin_make
 source devel/setup.bash
 roscore
 rosrun learning_service person_server
 rosrun learning_service person_client
参数的使用与编程方法
- 
创建功能包 cd ~/catkin_ws/src 
 catkin_create_pkg learning_parameter roscpp rospy std_srvs
- 
参数命令行使用 rosparam list #列出当前多有参数 
 rosparam get param_key #显示某个参数值
 rosparam set param_key param_value #设置某个参数值
 rosparam dump file_name #保存参数到文件
 rosparam load file_name #从文件读取参数
 rosparam delete param_key #删除参数
- 
创建parameter_conflg.cpp /** 
 * 该例程设置/读取海龟例程中的参数
 */
 int main(int argc, char **argv)
 {
 int red, green, blue;
 // ROS节点初始化
 ros::init(argc, argv, "parameter_config");
 // 创建节点句柄
 ros::NodeHandle node;
 // 读取背景颜色参数
 ros::param::get("/background_r", red);
 ros::param::get("/background_g", green);
 ros::param::get("/background_b", blue);
 ROS_INFO("Get Backgroud Color[%d, %d, %d]", red, green, blue);
 // 设置背景颜色参数
 ros::param::set("/background_r", 255);
 ros::param::set("/background_g", 255);
 ros::param::set("/background_b", 255);
 ROS_INFO("Set Backgroud Color[255, 255, 255]");
 // 读取背景颜色参数
 ros::param::get("/background_r", red);
 ros::param::get("/background_g", green);
 ros::param::get("/background_b", blue);
 ROS_INFO("Re-get Backgroud Color[%d, %d, %d]", red, green, blue);
 // 调用服务,刷新背景颜色
 ros::service::waitForService("/clear");
 ros::ServiceClient clear_background = node.serviceClient<std_srvs::Empty>("/clear");
 std_srvs::Empty srv;
 clear_background.call(srv);
 
 sleep(1);
 return 0;
 }
- 
配置CMakeLists参数 add_executable(parameter_config src/parameter_config.cpp) 
 target_link_libraries(parameter_config ${catkin_LIBRARIES})
- 
编译运行 cd ~/catkin_ws 
 catkin_make
 source devel/setup.bash
 roscore
 rosrun turtlesim turtlesim_node
 rosrun learning_parameter parameter_config
ROS中的坐标系管理系统
- 
机器人中的坐标变换 TF功能包 sudo apt-get install ros-melodic-turtle-tf 
 roslaunch,启动脚本文件
 roslaunch turtle_tf turtle_tf_demo.launch
 rosrun turtlesim turtle_teleop_key
 各种工具
 rosrun tf view_frames
 rosrun tf tf_echo turtle1 turtle2
 rosrun rviz rviz -d `rospack find turtle_tf`/rviz/turtle_rviz.rviz
TF坐标系广播监听的编程管理
- 
创建功能包 cd ~/catkin_ws/src 
 catkin_create_pkg learning_tf roscpp rospy tf turtlesim
- 
广播器broadcaster.cpp /** 
 * 该例程产生tf数据,并计算、发布turtle2的速度指令
 */
 std::string turtle_name;
 void poseCallback(const turtlesim::PoseConstPtr& msg)
 {
 // 创建tf的广播器
 static tf::TransformBroadcaster br;
 // 初始化tf数据
 tf::Transform transform;
 transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
 tf::Quaternion q;
 q.setRPY(0, 0, msg->theta);
 transform.setRotation(q);
 // 广播world与海龟坐标系之间的tf数据
 br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
 }
 int main(int argc, char** argv)
 {
 // 初始化ROS节点
 ros::init(argc, argv, "my_tf_broadcaster");
 // 输入参数作为海龟的名字
 if (argc != 2)
 {
 ROS_ERROR("need turtle name as argument");
 return -1;
 }
 turtle_name = argv[1];
 // 订阅海龟的位姿话题
 ros::NodeHandle node;
 ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
 // 循环等待回调函数
 ros::spin();
 return 0;
 };
- 
监听器 /** 
 * 该例程监听tf数据,并计算、发布turtle2的速度指令
 */
 int main(int argc, char** argv)
 {
 // 初始化ROS节点
 ros::init(argc, argv, "my_tf_listener");
 // 创建节点句柄
 ros::NodeHandle node;
 // 请求产生turtle2
 ros::service::waitForService("/spawn");
 ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
 turtlesim::Spawn srv;
 add_turtle.call(srv);
 // 创建发布turtle2速度控制指令的发布者
 ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel", 10);
 // 创建tf的监听器
 tf::TransformListener listener;
 ros::Rate rate(10.0);
 while (node.ok())
 {
 // 获取turtle1与turtle2坐标系之间的tf数据
 tf::StampedTransform transform;
 try
 {
 listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
 listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
 }
 catch (tf::TransformException &ex)
 {
 ROS_ERROR("%s",ex.what());
 ros::Duration(1.0).sleep();
 continue;
 }
 // 根据turtle1与turtle2坐标系之间的位置关系,发布turtle2的速度控制指令
 geometry_msgs::Twist vel_msg;
 vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
 transform.getOrigin().x());
 vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
 pow(transform.getOrigin().y(), 2));
 turtle_vel.publish(vel_msg);
 rate.sleep();
 }
 return 0;
 };
- 
编译配置 add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp) 
 target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
 add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
 target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
- 
编译运行 cd ~/catkin_ws 
 catkin_make
 source devel/setup.bash
 roscore
 rosrun turtlesim turtlesim_node
 重命名,避免冲突
 rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1
 rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2
 rosrun learning_tf turtle_tf_listener
 rosrun turtlesim turtle_teleop_key
launch启动文件的使用方法
- 
Launch文件:通过XML文件实现多节点的配置和启动(可自动启动ROS Master) 
- 
node启动节点 : pkg:节点所在的功能包名称 type:节点的可执行文件名称 name:节点运行时的名称 output 、respawn 、required 、ns 、args <node pkg="package-name" type="executable-name" name="node-name" /> 
- 
参数设置 
实例
常用可视化工具
- 
rqt rqt 
- 
Rviz rosrun rviz 
- 
Gazebo 


















