零、参考链接
https://www.bilibili.com/video/BV1zt411G7Vn
http://wiki.ros.org/cn/ROS/Tutorials/
一、ROS安装
1.1 参考网址
http://wiki.ros.org/melodic/Installation/Ubuntu
1.2 安装步骤
1.2.1 Setup your sources.list
软件源镜像版参考页面:http://wiki.ros.org/ROS/Installation/UbuntuMirrors
1 2 3 sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/ros-latest.list'
1.2.2 Set up your keys
1 sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
1.2.3 Installation ROS
First, make sure your Debian package index is up-to-date:
Desktop-Full Install: (Recommended) : ROS, rqt , rviz , robot-generic libraries, 2D/3D
simulators and 2D/3D perception
1 sudo apt install ros-melodic-desktop-full
1.2.4 Environment setup
It's convenient if the ROS environment variables are automatically
added to your bash session every time a new shell is launched:
1 2 echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrcsource ~/.bashrc
1.2.5 Dependencies for
building packages
Up to now you have installed what you need to run the core ROS
packages. To create and manage your own ROS workspaces, there are
various tools and requirements that are distributed separately. For
example, rosinstall is a
frequently used command-line tool that enables you to easily download
many source trees for ROS packages with one command.
To install this tool and other dependencies for building ROS
packages, run:
1 sudo apt install python-rosinstall python-rosinstall-generator python-wstool build-essential
1.2.6 Initialize
rosdep(optional)
Before you can use many ROS tools, you will need to initialize
rosdep
. rosdep
enables you to easily install
system dependencies for source you want to compile and is required to
run some core components in ROS. If you have not yet installed
rosdep
, do so as follows.
1 sudo apt install python-rosdep
With the following, you can initialize rosdep
.
1 2 3 sudo rosdep init rosdep update
1.3 测试安装
1 rosrun turtlesim turtlesim_node
1 rosrun turtlesim turtle_teleop_key
二、ROS概念
2.1 节点
2.1.1 Node——执行单元
节点实际上只不过是ROS软件包中的一个可执行文件。ROS节点使用ROS客户端库 与其他节点通信。节点可以发布或订阅话题,也可以提供或使用服务 。
执行具体任务的进程、独立运行的可执行文件
不同节点可使用不同编程语言,可分布式运行在不同主机
节点在系统中命名必须唯一
2.1.2 ROS Master——控制中心
为节点提供命名和注册服务
跟踪和记录话题/服务 通信,辅助节点相互查找、建立连接
提供参数服务器,节点使用此服务器存储和检索运行时的参数
2.2 通信
2.2.1 话题通信
1、 话题Topic——异步通信
节点间用来传输数据的重要总线
使用
发布publish/订阅subscribe 模型,数据由发布者传输到订阅者,同一个话题的订阅者或发布者可以不唯一
2、 消息Message——话题数据
具有一定的类型和数据结构,包括ROS提供的标准类型和用户自定义类型
使用编程语言无关的.msg文件定义,编译过程中产生对应的代码文件
2.2.2 服务通信
服务Service——同步通信
使用客户端/服务器 模型,客户端发送请求 数据,服务器完成处理后返回应答 数据
使用编程语言无关的.srv文件定义请求和应答数据结构,编译过程中生成对应的代码文件
2.2.3 话题 vs 服务
同步性
异步
同步
通信模型
发布/订阅
服务器/客户端
底层协议
ROSTCP/ROSUDP
ROSTCP/ROSUDP
反馈机制
无
有
缓冲区
有
无
实时性
弱
强
节点关系
多对多
一对多(一个service)
适用场景
数据传输
逻辑处理
2.2.4 参数
参数Parameter——全局共享字典
可通过网络 访问的共享、多变量字典
节点使用此服务器来存储和检索运行时的参数
适合存储静态 、非二进制的配置参数,不适合存储动态配置的数据
2.3 文件系统
2.4 主要命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 roscore rosrun turtlesim turtlesim_node rosrun turtlesim turtle_teleop_key rtq_graph rosnode list rosnode info /turtlesim rostopic list 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" rosmsg show geometry_msgs/Twist rosservice list rosservice call /spawn "x:5.0 y:5.0 theta:0.0 name:'turtle2'" rosbag record -a -O cmd_record rosbag play cmd_record.bag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 rospack find [package_name] rospack find roscpp /opt/ros/<distro>/share/roscpp roscd [locationname[/subdir]] roscd roscpp pwd YOUR_INSTALL_PATH/share/roscpp rospack = ros + pack(age) roscd = ros + cd rosls = ros + ls
三、话题应用
3.1 创建工作空间和功能包
工作空间workspace:一个存放工程开发相关文件的文件夹。
工作空间下共有四个主要文件夹:
src:代码空间,放功能包的源码等
build:编译空间,编译过程中的中间二进制文件等
devel:开发空间,开发过程中生成的可执行文件和库等,与install功能类似
install:安装空间,开发结束后生成的可执行文件等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 mkdir -p ~/catkin_ws/srccd ~/catkin_ws/srccatkin_init_workspace cd ~/catkin_ws/catkin_make catkin_make install cd ~/catkin_ws/srccatkin_create_pkg test_pkg std_msgs rospy roscpp cd ~/catkin_wscatkin_make source ~/catkin_ws/devel/setup.bashecho $ROS_PACKAGE_PATH /home/<username>/catkin_ws/src:/opt/ros/<distro>/share export ROS_PACKAGE_PATH=/home/user/ros/ros-pkg:/another/path
3.2 Publisher实现
1 2 3 cd ~/catkin_ws/srccatkin_create_pkg learning_topic std_msgs rospy roscpp geometry_msgs turtlesim
3.2.1 C++版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <ros/ros.h> #include <geometry_msgs/Twist.h> int main (int argc, char **argv) { ros::init (argc, argv, "velocity_publisher" ); ros::NodeHandle n; 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 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 ; }
1 2 3 add_executable (velocity_publisher src/velocity_publisher.cpp)target_link_libraries (velocity_publisher ${catkin_LIBRARIES} )
1 2 3 4 5 6 7 cd ~/catkin_wscatkin_make source devel/setup.bash roscore rosrun turtlesim turtlesim_node rosrun learning_topic velocity_publisher
3.2.2 python版
~/catkin_ws/src/learning_topic/scripts/velocity_publisher.py代码如下
第三行代码的python解释器由于版本问题可能要写为python3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import rospyfrom geometry_msgs.msg import Twistdef velocity_publisher (): 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("Publsh 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
1 2 3 4 5 6 7 cd ~/catkin_ws/src/learning_topic/scripts/sudo chmod 777 velocity_publisher.py source devel/setup.bash roscore rosrun turtlesim turtlesim_node rosrun learning_topic velocity_publisher.py
3.3 Subscriber实现
3.3.1 C++版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <ros/ros.h> #include "turtlesim/Pose.h" 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::init (argc, argv, "pose_subscriber" ); ros::NodeHandle n; ros::Subscriber pose_sub = n.subscribe ("/turtle1/pose" , 10 , poseCallback); ros::spin (); return 0 ; }
1 2 3 add_executable (pose_subscriber src/pose_subscriber.cpp)target_link_libraries (pose_subscriber ${catkin_LIBRARIES} )
1 2 3 4 5 6 7 8 cd ~/catkin_wscatkin_make source devel/setup.bash roscore rosrun turtlesim turtlesim_node rosrun learning_topic velocity_publisher rosrun learning_topic pose_subscriber
3.3.2 python版
~/catkin_ws/src/learning_topic/scripts/pose_subscriber.py代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import rospyfrom turtlesim.msg import Posedef 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()
1 2 3 4 5 6 7 8 cd ~/catkin_ws/src/learning_topic/scripts/sudo chmod 755 pose_subscriber.py source devel/setup.bash roscore rosrun turtlesim turtlesim_node rosrun turtlesim turtle_teleop_key rosrun learning_topic pose_subscriber.py
3.4 话题消息自定义
3.4.1 定义msg文件
1 2 3 4 5 6 7 8 9 10 11 12 cd ~/catkin_ws/src/learning_topic/mkdir msgcd msgtouch Person.msgstring name uint8 age uint8 sex uint8 unknown = 0 uint8 male = 1 uint8 female = 2
3.4.2
在package.xml添加功能包依赖
1 2 3 4 cd ~/catkin_ws/src/learning_topic/<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend>
3.4.3
在CMakeLists.txt添加编译内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cd ~/catkin_ws/src/learning_topic/ find_package (catkin REQUIRED COMPONENTS geometry_msgs roscpp rospy std_msgs turtlesim message_generation ) add_message_files( FILES Person.msg ) generate_messages( DEPENDENCIES std_msgs ) catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim message_runtime )
3.4.4 编译生成语言相关文件
1 2 3 cd ~/catkin_wscatkin_make
3.4.5 自定义话题消息的使用
1、publisher(c++)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <ros/ros.h> #include "learning_topic/Person.h" int main (int argc, char **argv) { ros::init (argc, argv, "person_publisher" ); ros::NodeHandle n; ros::Publisher person_info_pub = n.advertise <learning_topic::Person>("/person_info" , 10 ); ros::Rate loop_rate (1 ) ; int count = 0 ; while (ros::ok ()) { learning_topic::Person person_msg; person_msg.name = "Tom" ; person_msg.age = 18 ; person_msg.sex = learning_topic::Person::male; person_info_pub.publish (person_msg); ROS_INFO ("Publish Person Info: name:%s age:%d sex:%d" , person_msg.name.c_str (), person_msg.age, person_msg.sex); loop_rate.sleep (); } return 0 ; }
2、subscriber(c++)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <ros/ros.h> #include "learning_topic/Person.h" void personInfoCallback (const learning_topic::Person::ConstPtr& msg) { ROS_INFO ("Subcribe Person Info: name:%s age:%d sex:%d" , msg->name.c_str (), msg->age, msg->sex); } int main (int argc, char **argv) { ros::init (argc, argv, "person_subscriber" ); ros::NodeHandle n; ros::Subscriber person_info_sub = n.subscribe ("/person_info" , 10 , personInfoCallback); ros::spin (); return 0 ; }
3、在CMakeLists.txt添加编译内容
1 2 3 4 5 6 7 8 9 cd ~/catkin_ws/src/learning_topic/ add_executable (person_publisher src/person_publisher.cpp)target_link_libraries (person_publisher ${catkin_LIBRARIES} )add_dependencies (person_publisher ${PROJECT_NAME} _generate_messages_cpp)add_executable (person_subscriber src/person_subscriber.cpp)target_link_libraries (person_subscriber ${catkin_LIBRARIES} )add_dependencies (person_subscriber ${PROJECT_NAME} _generate_messages_cpp)
4、编译与运行
1 2 3 4 5 6 7 cd ~/catkin_wscatkin_make roscore rosrun learning_topic person_subscriber rosrun learning_topic person_publisher
5、publisher(python)
~/catkin_ws/src/learning_topic/scripts/person_publisher.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import rospyfrom learning_topic.msg import Persondef velocity_publisher (): rospy.init_node('person_publisher' , anonymous=True ) person_info_pub = rospy.Publisher('/person_info' , Person, queue_size=10 ) rate = rospy.Rate(10 ) while not rospy.is_shutdown(): person_msg = Person() person_msg.name = "Tom" ; person_msg.age = 18 ; person_msg.sex = Person.male; person_info_pub.publish(person_msg) rospy.loginfo("Publsh person message[%s, %d, %d]" , person_msg.name, person_msg.age, person_msg.sex) rate.sleep() if __name__ == '__main__' : try : velocity_publisher() except rospy.ROSInterruptException: pass
6、subscriber(python)
~/catkin_ws/src/learning_topic/scripts/person_subscriber.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import rospyfrom learning_topic.msg import Persondef personInfoCallback (msg ): rospy.loginfo("Subcribe Person Info: name:%s age:%d sex:%d" , msg.name, msg.age, msg.sex) def person_subscriber (): rospy.init_node('person_subscriber' , anonymous=True ) rospy.Subscriber("/person_info" , Person, personInfoCallback) rospy.spin() if __name__ == '__main__' : person_subscriber()
四、服务应用
4.1 创建功能包
1 2 cd ~/catkin_ws/srccatkin_create_pkg learning_service roscpp rospy std_msgs geometry_msgs turtlesim
4.2 Client实现
4.2.1 C++版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <ros/ros.h> #include <turtlesim/Spawn.h> int main (int argc, char ** argv) { ros::init (argc, argv, "turtle_spawn" ); ros::NodeHandle node; ros::service::waitForService ("/spawn" ); ros::ServiceClient add_turtle = node.serviceClient <turtlesim::Spawn>("/spawn" ); turtlesim::Spawn srv; srv.request.x = 2.0 ; srv.request.y = 2.0 ; srv.request.name = "turtle2" ; ROS_INFO ("Call service to spawn 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 ("Spawn turtle successfully [name:%s]" , srv.response.name.c_str ()); return 0 ; };
1 2 3 add_executable(turtle_spawn src/turtle_spawn.cpp) target_link_libraries(turtle_spawn ${catkin_LIBRARIES} )
1 2 3 4 5 6 7 cd ~/catkin_wscatkin_make source devel/setup.bash roscore rosrun turtlesim turtlesim_node rosrun learning_service turtle_spawn
4.2.2 python版
~/catkin_ws/src/learning_service/scripts/turtle_spawn.py内容如下(注意添加执行权限)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import sysimport rospyfrom turtlesim.srv import Spawndef turtle_spawn (): rospy.init_node('turtle_spawn' ) rospy.wait_for_service('/spawn' ) try : add_turtle = rospy.ServiceProxy('/spawn' , Spawn) response = add_turtle(2.0 , 2.0 , 0.0 , "turtle2" ) return response.name except rospy.ServiceException, e: print "Service call failed: %s" %e if __name__ == "__main__" : print "Spwan turtle successfully [name:%s]" %(turtle_spawn())
4.3 Server实现
4.3.1 C++版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <ros/ros.h> #include <geometry_msgs/Twist.h> #include <std_srvs/Trigger.h> ros::Publisher turtle_vel_pub; bool pubCommand = false ;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::init (argc, argv, "turtle_command_server" ); ros::NodeHandle n; ros::ServiceServer command_service = n.advertiseService ("/turtle_command" , commandCallback); 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 (); 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 ; }
1 2 3 add_executable (turtle_command_server src/turtle_command_server.cpp)target_link_libraries (turtle_command_server ${catkin_LIBRARIES} )
1 2 3 4 5 6 7 8 cd ~/catkin_wscatkin_make source devel/setup.bash roscore rosrun turtlesim turtlesim_node rosrun learning_service turtle_command_server rosservice call /turtle_command "{}"
4.3.2 python版
~/catkin_ws/src/learning_service/scripts/turtle_command_server.py内容如下(注意添加执行权限)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import rospyimport thread,timefrom geometry_msgs.msg import Twistfrom std_srvs.srv import Trigger, TriggerResponsepubCommand = False ; turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel' , Twist, queue_size=10 ) def command_thread (): while True : if pubCommand: vel_msg = Twist() vel_msg.linear.x = 0.5 vel_msg.angular.z = 0.2 turtle_vel_pub.publish(vel_msg) time.sleep(0.1 ) def commandCallback (req ): global pubCommand pubCommand = bool (1 -pubCommand) rospy.loginfo("Publish turtle velocity command![%d]" , pubCommand) return TriggerResponse(1 , "Change turtle command state!" ) def turtle_command_server (): rospy.init_node('turtle_command_server' ) s = rospy.Service('/turtle_command' , Trigger, commandCallback) print "Ready to receive turtle command." thread.start_new_thread(command_thread, ()) rospy.spin() if __name__ == "__main__" : turtle_command_server()
4.4 服务数据自定义
4.4.1 定义srv文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 cd ~/catkin_ws/src/learning_service/mkdir srvcd srvtouch Person.srvstring name uint8 age uint8 sex uint8 unknown = 0 uint8 male = 1 uint8 female = 2 --- string result
4.4.2
在package.xml添加功能包依赖
1 2 3 4 cd ~/catkin_ws/src/learning_service/<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend>
4.4.3
在CMakeLists.txt添加编译内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cd ~/catkin_ws/src/learning_service/ find_package (catkin REQUIRED COMPONENTS geometry_msgs roscpp rospy std_msgs turtlesim message_generation ) add_service_files( FILES Person.srv ) generate_messages( DEPENDENCIES std_msgs ) catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim message_runtime )
4.4.4 编译生成语言相关文件
1 2 3 cd ~/catkin_wscatkin_make
4.4.5 自定义服务数据的使用
1、server(c++)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <ros/ros.h> #include "learning_service/Person.h" 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::init (argc, argv, "person_server" ); ros::NodeHandle n; ros::ServiceServer person_service = n.advertiseService ("/show_person" , personCallback); ROS_INFO ("Ready to show person informtion." ); ros::spin (); return 0 ; }
2、client(c++)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <ros/ros.h> #include "learning_service/Person.h" int main (int argc, char ** argv) { ros::init (argc, argv, "person_client" ); ros::NodeHandle node; ros::service::waitForService ("/show_person" ); ros::ServiceClient person_client = node.serviceClient <learning_service::Person>("/show_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 ; };
3、在CMakeLists.txt添加编译内容
1 2 3 4 5 6 7 8 9 cd ~/catkin_ws/src/learning_service/ 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)
4、编译与运行
1 2 3 4 5 6 cd ~/catkin_wscatkin_make source devel/setup.bashroscore rosrun learning_service person_server rosrun learning_service person_client
5、server(python)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import rospyfrom learning_service.srv import Person, PersonResponsedef personCallback (req ): rospy.loginfo("Person: name:%s age:%d sex:%d" , req.name, req.age, req.sex) return PersonResponse("OK" ) def person_server (): rospy.init_node('person_server' ) s = rospy.Service('/show_person' , Person, personCallback) print "Ready to show person informtion." rospy.spin() if __name__ == "__main__" : person_server()
6、client(python)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import sysimport rospyfrom learning_service.srv import Person, PersonRequestdef person_client (): rospy.init_node('person_client' ) rospy.wait_for_service('/show_person' ) try : person_client = rospy.ServiceProxy('/show_person' , Person) response = person_client("Tom" , 20 , PersonRequest.male) return response.result except rospy.ServiceException, e: print "Service call failed: %s" %e if __name__ == "__main__" : print "Show person result : %s" %(person_client())
五、参数应用
5.1 创建功能包
1 2 cd ~/catkin_ws/srccatkin_create_pkg learning_parameter roscpp rospy std_srvs
5.2 参数命令行使用
1 2 3 4 5 6 7 8 9 10 11 12 rosparam list rosparam get param_key rosparam set param_key param_value rosparam dump file_name rosparam load file_name rosparam delete param_key
5.3 实现
5.3.1 C++版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <string> #include <ros/ros.h> #include <std_srvs/Empty.h> int main (int argc, char **argv) { int red, green, blue; 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 ; }
1 2 3 4 cd ~/catkin_ws/src/learning_parameter/ add_executable (parameter_config src/parameter_config.cpp)target_link_libraries (parameter_config ${catkin_LIBRARIES} )
1 2 3 4 5 6 cd ~/catkin_wscatkin_make source devel/setup.bashroscore rosrun turtlesim turtlesim_node rosrun learning_parameter parameter_config
5.3.2 python版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import sysimport rospyfrom std_srvs.srv import Emptydef parameter_config (): rospy.init_node('parameter_config' , anonymous=True ) red = rospy.get_param('/background_r' ) green = rospy.get_param('/background_g' ) blue = rospy.get_param('/background_b' ) rospy.loginfo("Get Backgroud Color[%d, %d, %d]" , red, green, blue) rospy.set_param("/background_r" , 255 ); rospy.set_param("/background_g" , 255 ); rospy.set_param("/background_b" , 255 ); rospy.loginfo("Set Backgroud Color[255, 255, 255]" ); red = rospy.get_param('/background_r' ) green = rospy.get_param('/background_g' ) blue = rospy.get_param('/background_b' ) rospy.loginfo("Get Backgroud Color[%d, %d, %d]" , red, green, blue) rospy.wait_for_service('/clear' ) try : clear_background = rospy.ServiceProxy('/clear' , Empty) response = clear_background() return response except rospy.ServiceException, e: print "Service call failed: %s" %e if __name__ == "__main__" : parameter_config()
六、tf坐标系
6.1 创建功能包
1 2 3 sudo apt-get install ros-melodic-turtle-tf cd ~/catkin_ws/srccatkin_create_pkg learning_tf roscpp rospy tf turtlesim
6.2 实现
6.2.1 broadcaster(c++)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <ros/ros.h> #include <tf/transform_broadcaster.h> #include <turtlesim/Pose.h> std::string turtle_name; void poseCallback (const turtlesim::PoseConstPtr& msg) { static tf::TransformBroadcaster br; 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); br.sendTransform (tf::StampedTransform (transform, ros::Time::now (), "world" , turtle_name)); } int main (int argc, char ** argv) { 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 ; };
6.2.2 listener(c++)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #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::init (argc, argv, "my_tf_listener" ); ros::NodeHandle node; ros::service::waitForService ("/spawn" ); ros::ServiceClient add_turtle = node.serviceClient <turtlesim::Spawn>("/spawn" ); turtlesim::Spawn srv; add_turtle.call (srv); ros::Publisher turtle_vel = node.advertise <geometry_msgs::Twist>("/turtle2/cmd_vel" , 10 ); tf::TransformListener listener; ros::Rate rate (10.0 ) ; while (node.ok ()) { 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 ; } 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 ; };
6.2.3
在CMakeLists.txt添加编译内容
1 2 3 4 5 6 7 cd ~/catkin_ws/src/learning_tf/ 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} )
6.2.4 编译与运行
1 2 3 4 5 6 7 8 9 10 11 12 cd ~/catkin_wscatkin_make source devel/setup.bashroscore 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
6.2.5 broadcaster(python)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import roslibroslib.load_manifest('learning_tf' ) import rospyimport tfimport turtlesim.msgdef handle_turtle_pose (msg, turtlename ): br = tf.TransformBroadcaster() br.sendTransform((msg.x, msg.y, 0 ), tf.transformations.quaternion_from_euler(0 , 0 , msg.theta), rospy.Time.now(), turtlename, "world" ) if __name__ == '__main__' : rospy.init_node('turtle_tf_broadcaster' ) turtlename = rospy.get_param('~turtle' ) rospy.Subscriber('/%s/pose' % turtlename, turtlesim.msg.Pose, handle_turtle_pose, turtlename) rospy.spin()
6.2.6 listener(python)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import roslibroslib.load_manifest('learning_tf' ) import rospyimport mathimport tfimport geometry_msgs.msgimport turtlesim.srvif __name__ == '__main__' : rospy.init_node('turtle_tf_listener' ) listener = tf.TransformListener() rospy.wait_for_service('spawn' ) spawner = rospy.ServiceProxy('spawn' , turtlesim.srv.Spawn) spawner(4 , 2 , 0 , 'turtle2' ) turtle_vel = rospy.Publisher('turtle2/cmd_vel' , geometry_msgs.msg.Twist,queue_size=1 ) rate = rospy.Rate(10.0 ) while not rospy.is_shutdown(): try : (trans,rot) = listener.lookupTransform('/turtle2' , '/turtle1' , rospy.Time(0 )) except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException): continue angular = 4 * math.atan2(trans[1 ], trans[0 ]) linear = 0.5 * math.sqrt(trans[0 ] ** 2 + trans[1 ] ** 2 ) cmd = geometry_msgs.msg.Twist() cmd.linear.x = linear cmd.angular.z = angular turtle_vel.publish(cmd) rate.sleep()
6.2.7 运行
1 rosrun learning_tf turtle_tf_broadcaster.py __name:=turtle1_tf_broadcaster _turtle:=/turtle1
七、launch启动文件
7.1 简单启动文件
1 2 3 4 5 6 7 8 cd ~/catkin_ws/srccatkin_create_pkg learning_launch cd learning_launchmkdir launchcd launchtouch simple.launchsudo vim simple.launch
1 2 3 4 <launch > <node pkg ="learning_topic" type ="person_subscriber" name ="talker" /> <node pkg ="learning_topic" type ="person_publisher" name ="listener" /> </launch >
1 2 3 4 cd ~/catkin_wscatkin_make roslaunch learning_launch simple.launch
7.2 官方参考网址
https://wiki.ros.org/roslaunch/XML
7.3 常用标签注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 <launch > <node name ="bar1" pkg ="foo_pkg" type ="bar" args ="--test" respawn ="true" output ="sceen" /> <group ns ="namespace" > <node pkg ="pkg_name1" ... /> <node pkg ="pkg_name2" ... /> ... </group > <group if ="$(arg foo1)" > <node pkg ="pkg_name1" ... /> </group > <group unless ="$(arg foo2)" > <node pkg ="pkg_name2" ... /> </group > <remap from = "/different_topic" to = "/needed_topic" /> <machine name ="foo" address ="foo-address" env-loader ="/opt/ros/kinetic/env.sh" user ="someone" > <env name ="ENV_EXAMPLE" value ="some value" /> <param name ="publish_frequency" type ="double" value ="10.0" /> <rosparam file ="params.yaml" command ="load" ns ="params" /> <arg name ="arg-name" default ="arg-value" /> <param name ="foo" value ="$(arg arg-name)" /> <node name ="node" pkg ="package" type ="type" args ="$(arg arg-name)" /> <include file ="$(dirname)/other.launch" /> </launch >
八、可视化工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 rqt rqt_console rqt_graph rqt_plot rqt_image_view rviz roslaunch gazebo_ros + tab补全