ROS之命令与编程实践
参考资料
- 古月居ROS21讲
- ROSwiki
ROS命令行概述
roscore启动命令
rosrun
rosrun [package_name] [node_name] #允许你使用包名直接运行一个包内的节点(而不需要知道这个包的路径)。
rosls
rosls是rosbash命令集中的一部分,它允许你直接按软件包的名称而不是绝对路径执行ls命令(罗列目录).
rosls beginner_tutorials/
CMakeLists.txt include package.xml srcroscd 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: 248rosmsg
$rosmsg show geometry_msgs/Twist
geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 zrosbag
将ROS系统运行过程中的数据录制到一个.bag文件中,然后可以通过回放数据来重现相似的运行过程.退出录制时按Ctrl-C退出该命令,你应该会看到在当前目录下一个以年份、日期和时间命名并以.bag作为后缀的文件。
#录制所有发布的话题,其中 -a 选项,该选项表示将当前发布的所有话题数据都录制保存到一个bag文件中。
$ rosbag record -a
#回放bag文件以再现系统运行过程
$ rosbag play
#以某一频率发布消息(控制bag包播放的频率) : rosbag play -r 2
#从某一时间节点开始播放发布消息 : rosbag play -s 2
$ rosbag info#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安装空间
#创建工作空间
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/src
$ catkin_init_workspace
#编译工作空间
$ cd ~/catkin_ws/
$ catkin_make
$ catkin_make install
#设置环境变量
$ source devel/setup.bash
#检查环境变量
$ echo $ROS_PACKAGE_PATH
home/qxd/catkin_ws/src:/opt/ros/melodic/share
#创建功能包
$ cd ~/catkin_ws/src
$ catkin_create_pkg test_pkg std_msgs rospy roscpp
eg: $ catkin_create_pkg 包名 依赖名 依赖名 依赖名 …
#编译功能包
$ cd ~/catkin_ws
$ catkin_make
$ source ~/catkin_ws/devel/setup.bash
发布者publisher编程实现
#创建功能包
$ cd ~/catkin_ws/src
$ catkin_create_pkg learning_topic std_msgs rospy roscpp geometry_msgs turtlesim
代码放到src目录
创建一个.cpp文件即可,注意文件名不能重复!!
/**
* 该程序将发布turtle1/cmd_vel话题,消息类型geometry——msgs::Twist
*/
#include<ros/ros.h>
#include<geometry_msgs/Twist.h>
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,”velocity_publisher”);
//创建节点句柄
ros::NodeHandle n;
//创建一个Publisher,发布名为/turtle1/cmd\_vel的topic,消息类型为geometry——msgs::Twist,队列长度10
ros::Publisher turtle\_vel\_pub = n.advertise<geometry\_msgs::Twist>("/turtle1/cmd\_vel",10);
//设置循环频率
ros::Rate loop\_rate(10);
int count = 0;
while(ros::ok())
{
//初始化geometry\_msgs::Twist类型的消息
geometry\_msgs::Twist vel\_msg;
vel\_msg.linear.x = 0.5;
vel\_msg.angular.z = 0.2;
//发布消息
turtle\_vel\_pub.publish(vel\_msg);
ROS\_INFO("Publsh turtle velocity command\[%0.2f m/s,%0.2f rad/s\]",
vel_msg.linear.x,vel_msg.angular.z);
//按照循环频率延时
loop\_rate.sleep();
}
return 0;
}
接下来需要编译运行,需要配置CMakeLists.txt中的编译规则
cmake_minimum_required(VERSION 3.0.2)
project(learning_topic)
## Compile as C++11, supported in ROS Kinetic and newer
add_compile_options(-std=c++11)
## 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
)
## System dependencies are found with CMake’s conventions
find_package(Boost REQUIRED COMPONENTS system)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user\_guide/setup\_dot\_py.html
catkin_python_setup()
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, …).
## * In the file package.xml:
## * add a build_depend tag for “message_generation”
## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn’t empty the following dependency has been pulled in
## but can be declared for certainty nonetheless:
## * add a exec_depend tag for “message_runtime”
## * In this file (CMakeLists.txt):
## * add “message_generation” and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS …)
## * add “message_runtime” and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS …)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES …)
## Generate messages in the ‘msg’ folder
add_message_files(
FILES
Message1.msg
Message2.msg
)
## Generate services in the ‘srv’ folder
add_service_files(
FILES
Service1.srv
Service2.srv
)
## Generate actions in the ‘action’ folder
add_action_files(
FILES
Action1.action
Action2.action
)
## 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)
################################################
## Declare ROS dynamic reconfigure parameters ##
################################################
## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
## * add a build_depend and a exec_depend tag for “dynamic_reconfigure”
## * In this file (CMakeLists.txt):
## * add “dynamic_reconfigure” to
## find_package(catkin REQUIRED COMPONENTS …)
## * uncomment the “generate_dynamic_reconfigure_options” section below
## and list every .cfg file to be processed
## Generate dynamic reconfigure parameters in the ‘cfg’ folder
generate_dynamic_reconfigure_options(
cfg/DynReconf1.cfg
cfg/DynReconf2.cfg
)
###################################
## 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
DEPENDS system_lib
message\_runtime
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
include
${catkin_INCLUDE_DIRS}
)
## Declare a C++ library
add_library(${PROJECT_NAME}
src/${PROJECT_NAME}/learning_topic.cpp
)
## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don’t collide
add_executable(${PROJECT_NAME}_node src/learning_topic_node.cpp)
## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. “rosrun someones_pkg node” instead of “rosrun someones_pkg someones_pkg_node”
set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX “”)
## Add cmake target dependencies of the executable
## same as for the library above
add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}_node
${catkin_LIBRARIES}
)
#将velocity_publisher.cpp编译成velocity_publisher可执行文件
add_executable(velocity_publisher src/velocity_publisher.cpp)
#对velocity_publisher做可执行文件的链接
target_link_libraries(velocity_publisher ${catkin_LIBRARIES})
add_executable(pose_subscriber src/pose_subscriber.cpp)
target_link_libraries(pose_subscriber ${catkin_LIBRARIES})
#############
## Install ##
#############
all install targets should use catkin DESTINATION variables
See http://ros.org/doc/api/catkin/html/adv\_user\_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
catkin_install_python(PROGRAMS
scripts/my_python_script
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building\_executables.html
install(TARGETS ${PROJECT_NAME}_node
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building\_libraries.html
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
)
## Mark cpp header files for installation
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN “*.h”
PATTERN “.svn” EXCLUDE
)
## Mark other files for installation (e.g. launch and bag files, etc.)
install(FILES
# myfile1
# myfile2
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
catkin_add_gtest(${PROJECT_NAME}-test test/test_learning_topic.cpp)
if(TARGET ${PROJECT_NAME}-test)
target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
endif()
## Add folders to be run by python nosetests
catkin_add_nosetests(test)
接下来就可以编译,在你的工作空间的src下
$ catkin_make
设置环境变量
source devel/setup.bash
也可以在主文件夹下
cd /
ls -a
vim .bashrc
#最后一行添加 source /home/qxd/catkin_ws/devel/setup.bash
接下来就可以执行
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun learning_topic velocity_publisher
也可用python来完成,首行注意添加 #!/usr/bin/env python
#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
def velocity_publisher():
#ROS
rospy.init_node(‘velocity_publisher’,anonymous=True)
turtle\_vel\_pub = rospy.Publisher('/turtle1/cmd\_vel',Twist,queue\_size=10)
rate = rospy.Rate(10)
while not rospy.is\_shutdown():
vel\_msg = Twist()
vel\_msg.linear.x = 0.5
vel\_msg.angular.z = 0.2
turtle\_vel\_pub.publish(vel\_msg)
rospy.loginfo("Publish turtle velocity command\[%0.2f m/s,%0.2f rad/s\]",
vel\_msg.linear.x,vel\_msg.angular.z)
rate.sleep()
if __name__ == ‘__main__‘:
try:
velocity_publisher()
except rospy.ROSInterruptException:
pass
订阅者subscriber的编程实现
项目工程文件夹下src中创建代码
//pose_subscriber.CPP
/**
* this program will subscribe /turtle/pose topic,message type is turtlesim::pose
*/
#include<ros/ros.h>
#include”turtlesim/Pose.h”
//recived the subscribe,then will go into the function that message recall
void poseCallback(const turtlesim::Pose::ConstPtr& msg)
{
ROS_INFO(“Turtle pose: x:%0.6f,y:%0.6f”,msg->x,msg->y);
}
int main(int argc,char **argv)
{
//初始化ROS节点
ros::init(argc,argv,”pose_subscriber”);
//创建节点句柄
ros::NodeHandle n;
//创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
ros::Subscriber pose\_sub = n.subscribe("/turtle1/pose",10,poseCallback);
//循环等待回调函数
ros::spin();
return 0;
}
编译执行过程同发布者
#!/usr/bin/env python
#-*- coding: utf-8 -*-
#该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
import rospy
from turtlesim.msg import Pose
def poseCallback(msg):
rospy.loginfo(“Turtle pose: x:%0.6f,y:%0.6f”,msg.x,msg.y)
def pose_subscriber():
rospy.init_node(‘pose_subscriber’,anonymous=True)
rospy.Subscriber("/turtle1/pose",Pose,poseCallback)
rospy.spin()
if __name__ == ‘__main__‘:
pose_subscriber()
话题消息定义与使用
如何自定义一个话题的消息
定义msg文件
在项目文件夹下创建一个msg文件夹,专门存放.msg文件,不能随便命名
string name
uint8 sex
uint8 ageuint8 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
*/
#include<ros/ros.h>
#include<turtlesim/Spawn.h>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.serviceClientturtlesim::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
/**
* 该程序将执行/turtle_command服务,服务数据类型td_srvs/Trigger
*/
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <std_srvs/Trigger.h>
ros::Publisher turtle_vel_pub;
bool pubCommand = false;
// service回调函数,输入参数req,输出参数res
bool commandCallback(std_srvs::Trigger::Request &req,
std_srvs::Trigger::Response &res)
{
pubCommand = !pubCommand;
//显示请求数据
ROS\_INFO("Publish turtle velocity command \[%s\]", pubCommand==true?"Yes":"No");
//设置反馈数据
res.success = true;
res.message = "Change turtle command state!"
return true;
}
int main(int argc, char **argv)
{
//ROS节点初始化
ros::init(argc, argv, “turtle_command_server”);
//创建节点”把手”
ros::NodeHandle n;
//创建一个名为turtle_command的erver,注册回调函数ommandCallback
ros::ServiceServer command_service = n.advertiseService(“/turtle_command”, commandCallback);
// 创建一个Publisher,发布名为turtle1/cmd_vel的topic消息类型为geometry_msgs::Twist,队列长度为10
turtle_vel_pub = n.advertise<geometry_msgs::Twist>(“/turtle1/cmd_vel”, 10);
//循环等待回调函数
ROS_INFO(“Ready to receive turtle command.”);
//设置循环的频率
ros::Rate loop_rate(10);
while(ros::ok())
{
//查看一次回调函数队列
ros::spinOnce();
//如果标志为true,则发布速度指令
if(pubCommand)
{
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.5;
vel_msg.angular.z = 0.2;
turtle_vel_pub.publish(vel_msg);
}
//按照循环频率延时
loop_rate.sleep();
}
return 0;
}
配置CMakeLists
add_executable(turtle_command_server src/turtle_command_server.cpp)
target_link_libraries(turtle_command_server ${catkin_LIBRARIES})
编译运行服务器
$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun learning_service turtle_command_server
$ rosservice call /turtle_command “{}”
自定义服务数据
定义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
*/#include <ros/ros.h>
#include “learning_service/Person.h”// 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
*/#include <ros/ros.h>
#include “learning_service/Person.h”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
/**
* 该例程设置/读取海龟例程中的参数
*/
#include
#include <ros/ros.h>
#include <std_srvs/Empty.h>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的速度指令
*/#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>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的速度指令
*/#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>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.serviceClientturtlesim::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

















