素材巴巴 > 程序开发 >

ROS基础学习(一)

程序开发 2023-09-07 15:06:55

参考古月居胡春旭ROS入门21讲视频等内容,跟着练习整理

ROS基本概念

ROS(Robot Operating System)是一个适用于机器人的开源的元操作系统。是一种新的标准化机器人软件框架,它提供了操作系统应有的服务,为机器人开发提供包括硬件抽象,底层驱动,消息传递,程序管理,应用原型等功能机制,并整合了许多第三方工具和库文件。ROS被设计为一种分布式结构,框架中每个功能模块都可以被单独设计、编译,并且运行时以松散耦合方式结合在一起,它也提供用于获取、编译、编写、和跨计算机运行代码所需的工具和库函数。

工作空间(workspace);是ROS存放工程开发相关文件的文件夹,工作空间中一般包括四个目录空间:src(代码空间):最常用的文件夹,用来储存所有ROS功能包的源码文件;build(编译空间):储存编译过程中的缓存信息和中间文件;devel(开发空间):放置编译生成的可执行文件;install(安装空间):编译成功后使用make install执行安装文件到该空间,运行该空间中的环境变量脚本,在终端运行这些可执行文件。

功能包(package):是ROS应用程序代码的组织单元,每个软件包都可以包含程序库、节点、可执行文件、脚本或者其它手动创建的东西。 创建了相应的软件包才能实现相应的功能。功能包中通常可包含如下文件夹:include(放置头文件)scripts(放置可直接运行的python文件)src(放置需要编译的C++文件)launch(放置启动文件)msg(放置自定义的消息类型)srv(放置自定义的服务类型)action(放置自定义的动作指令)CMakeLists.txt(编译器编译功能包的规则)package.xml(功能包清单:包括功能包名称,版本号,信息描述,作者信息,许可信息等,以及功能包中代码编译所依赖的其他功能包,运行功能包中可执行程序所依赖的其他功能包)

节点(Node):是 ROS 功能包中的一个可执行文件,一个系统通常由多个节点构成,节点之间可以通过 ROS 客户端库(如roscpp 、 rospy )相互通信。一个机器人控制系统由许多节点组成,这些节点各司其职,如,一个节点控制激光距离传感器,一个节点控制轮子的马达,一个节点执行定位,一个节点执行路径规划,一个节点提供系统的整个视图等。也就是能够执行特定工作任务的工作单元。

节点管理器(Master):顾名思义,使所有节点有条不紊执行的模块,节点通过与节点管理器通信来报告他们的注册信息,帮助节点之间相互查找,建立连接,同时还为系统提供参数服务器,管理全局参数,ROS master作为管理者,必不可少。

消息(Message):是一种ROS数据类型。节点之间做重要的通讯机制就是基于发布/订阅模型的消息(Message)通讯,一个节点向特定主题发布消息,从而将数据发送到另一个节点。消息具有一定的类型和数据结构,包括ROS提供的标准类型和用户自定义类型。消息与话题(发布 / 订阅模式)是紧密联系在一起的,msg文件实质上就是一个从结构上描述ROS中所使用消息类型的简单文本,描述的是消息的数据类型。

话题( Topic ): 是节点间用来传输数据的总线,通过主题进行消息路由不需要节点之间直接连接。节点可以发布消息到话题,也可以订阅话题以接收消息。一个话题可能对应有许多节点作为话题发布者和话题订阅者。当然,一个节点可以发布和订阅许多话题。一个节点对某一类型的数据感兴趣,它只需订阅相关话题即可。一般来说。话题发布者和话题订阅者不知道对方的存在。发布者将信息发布在一个全局的工作区内,当订阅者发现该信息是它所订阅的,就可以接收到这个信息。

服务: 当需要直接与节点通信并获得应答时,将无法通过话题来实现,而需要服务(Service)。可以看出,发布 / 订阅模式是一种多对多的传输方式,显然这种传输方式不适用于请求 / 回复的交互方式。请求 / 回复交互方式经常被用于分布式系统中。请求服务通过 Service 来进行,Service 被定义为一对消息结构:一个用于请求,一个用于回复。一个客户通过发送请求信息并等待响应来使用服务( ROS中的请求 / 回复交互方式类似于一个远程函数调用,srv文件类似于函数参数和返回值的定义)。

参数管理器( Parameter Server ): 是节点管理器的一部分,是一个可通过网络访问的共享的多变量字典。节点使用此服务器来存储和检索运行时参数。

消息记录包(Bag): 是一种用于保存和回放 ROS 消息数据的格式。消息记录包是检索传感器数据的重要机制,这些数据虽然很难收集,但是对于发展和测试算法很有必要。

清单(Manifest): 是对于功能包相关信息的描述,用于定义软件包相关元信息之间的依赖关系,这些信息包括版本、维护者和许可协议等。 也就是 package.xml文件。

脚本文件: CMakeLists.txt是一个Cmake的脚本文件,Cmake是一个符合工业标准的跨平台编译系统。这个文件包含了一系列的编译指令,包括应该生成哪种可执行文件,需要哪些源文件,以及在哪里可以找到所需的头文件和链接库。
ROS中有四种通讯方式:Topic(话题)、Service(服务)、Parameter Serivce(参数服务器)、Actionlib(动作库)。

常用指令:

roscore 			//开启rosmaster
 catkin_create_pkg 	//创建功能包
 rospack  			//获取功能包信息rospack find [包名称]    				//找到一个软件包的目录rospack list                  //显示出当前的包信息rospack depends1 beginner_tutorials        //显示当前包的一级依赖rospack depends beginner_tutorials     //显示当前包的所有依赖
 catkin_make  //编译工作空间中功能包
 rosdep  //自动安装功能包依赖的其他包
 roscd [ 本地包名称[/子目录] ] //允许你直接切换(cd)工作目录到某个软件包或者软件包集当中
 roscp  //拷贝功能包中文件
 rosed  //编辑功能包中文件
 rosrun [package_name] [node_name]  //运行功能包中可执行文件
 roslaunch  //运行启动文件
 rosnode 显示当前运行的ROS节点信息rosnode list                  获得运行节点列表rosnode info node-name        获得特定节点的信息rosnode ping  node-name       测试节点是否连通rosnode kill node-name        终止节点
 rostopic		//获取有关ROS话题的信息
 rossrv       //针对静态服务文件rossrv show /srv_name            显示服务类型的所有信息rossrv list                                显示所有服务类型信息rossrv md5  /srv_name             显示服务类型的md5sum信息rossrv package                          列出一个程序包中的所有服务类型rossrv packages                          列出包含服务的所有程序包
 rossevice     rossevice args             //打印服务的参数rosservice call             //以命令行的形式调用服务,可以指定具体参数rosservice find             //根据服务类型寻找当前服务rosservice info             //打印服务信息rosservice list              //列出当前服务类型rosservice type            //打印服务类型    rosservice uri               //打印服务的ROSRPC uri
 rosmsg					//查看消息的详细情况
 

ROS创建工作空间和包

工作空间:一个存放工程开发相关的文件夹
功能包package:是ROS软件的基本单元,包含ROS节点、库、配置文件等
Src:代码空间(source space)功能包代码,配置文件,launch文件
Build:编译空间(build space)
Devel:开发空间(development space)放置编译生成的可执行文件,一些库,脚本
Install:安装空间(install space)

创建工作空间

mkdir –p~/catkin_ws/src
cd~/catkin_ws/src
catkin_init_workspace

编译工作空间

cd ~/catkin_ws/
catkin_make
catkin _make install(创建安装空间)

创建功能包

catkin_create_pkg test_pkg roscpp rospy std_msgs
创建的功能包名为 test_pkg,依赖c++,python以及msgs等库,后期可添加,生成的test_pkg文件中包含src文件,用来存放代码,其中include用来存放头文件

设置环境变量

source devel/setup.bash

检查环境变量

echo $ROS_PACKAGE_PATH

通过运行小海龟了解ROS基本信息

roscore                               // 启动rosmaster  运行节点管理器
 rosrun turtlesim turtlesim_node 	  //运行海龟仿真器节点指令
 rosrun turtlesim turtle_teleop_key    //启动键盘操作节点
 rqt_graph/rqt                         //是基于qt的可视化工具,rqt_graph为显示系统计算处理工具Ros中默认单位为m和弧度
 ## 常用指令:
 

rosnode 显示系统中所有节点相关信息的指令;
rostopic 显示系统中所有话题相关的指令;
rosmsg 与消息相关的指令;
rosservice 显示与服务相关指令
rosbag
rosnode list 列出系统中所有节点;
rosnode info 节点名称 查看节点具体信息;
rostopic list 列出系统中所有话题;

发布话题:
 rostopic pub /话题名/节点类型/数据结构“具体数据”可用tab键补齐
 例子:rostopic pub –r 10 /turtle1/cmd_vel geometry_msgs/Twist "linear:x: 0.0y: 0.0z: 0.0
 angular:x: 0.0y: 0.0z: 0.0"
 其中-r 10 为频率,以10Hz每秒发送数据,具体数据包括:角速度和线速度。查看发布话题的消息结构:rosmsg show geometry_msgs/Twist
 eg:发布服务请求:rosservice call/spawn”x:5.0
 Y:5.0
 Theta:0.0
 name:’turtle2’”话题记录:rosbag record –a-O cmd_record/record记录,-a所有信息-o保存为压缩包+名字
 话题复现:rosbag play 压缩包名字# 话题通讯模型
 ## 创建功能包
 cd~/catkin_ws/src
 catkin_create_pkg learning_topic rospy std_msgs geometry_msgs turtlesim
 ## 发布者publisher编程实现### 创建发布者代码
 ## 订阅者subscriber编程实现
 初始化ROS节点
 订阅需要的话题
 循环等待话题消息,接收到消息后进入回调函数,在回调函数中完成消息处理
 话题消息订阅使用
 ## 自定义话题消息
 ### 定义msg文件
 创建msg文件夹,存放与消息有关的文件。使用touch person.msg命令创建文件,打开后编写msg文件
 string name
 uint8 sex
 uint8 age
 uint8 unknow = 0
 uint8 male = 1
 uint8 female = 2
 ### 在package.xml中添加功能包依赖
 编译依赖message_generation动态产生msg的功能包
 执行依赖message_runtime
 ### 在CMakeList.txt添加编译选项
 1.添加功能包依赖find…package(…message_generation)
 2.把msg文件编译成对应的程序文件add_message_files(FILES person.msg)
 3.声明编译msg文件时需要依赖ros已有的库generate_messages(DEPENDENCIES std_msgs)
 4创建msg运行依赖
 catkin_package(INCLUDE_DIRS includeLIBRARIES lenrnking_topicCATKIN_DEPENDS roscpp rospy std_msgsDEPENDS system_libmessage_runtime
 )
 5编译catkin_make;根据msg文件生成include头文件,必须采用大写首字母命名
 ###	编译生成语言相关文件
 创建subscriber和publisher文件在CMakeList.txt中设置需要编译的代码和生成的可执行文件;
 add_executable(person_publisher src/person_publisher.cpp)
 add_executable(person_subscriber src/person_subscriber.cpp)
 设置链接库;
 target_link_libraries(person_publisher ${catkin_LIBRARIES}) 
 target_link_libraries(person_subscriber ${catkin_LIBRARIES})
 添加依赖项
 add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp)
 add_dependencies(person_subscriber ${PROJECT_NAME}_generate_messages_cpp)运行roscore;
 运行rosrun learning_topic person_subscriber;
 运行rosrun learning_topic person_publisher;
 可观察到发布者发布信息,订阅者显示打印信息# 服务通信模型
 服务(services)是节点之间通讯的另一种方式。服务允许节点发送请求(request) 并获得一个响应(response)
 ## 在工作空间src目录下创建learning_service功能包并添加依赖
 catkin_create_pkg learning_service roscpp rospy std_msg geometry_msg turtlesim
 ## 客户端client编程实现
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200602173756793.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzM2NTc1MQ==,size_16,color_FFFFFF,t_70)
 创建客户端turtle_spawn节点,发布request给server(海龟仿真器)
 当server收到request后会回馈一个response给客户端,client端与server端通过service消息结构建立联系在创建的learning_service功能包的src中使用命令行创建文件
 touch turtle_spawe.cpp  
 编写client端程序
 ```cpp
 /**
 请求/spawn服务,服务数据类型turtlesim::spawn**/
 #include 
 #include int main(int argc, char** argv)
 {//初始化节点 节点名为turtle_spawnros::init(argc,argv,"turtle_spawn");//创建节点句柄ros::NodeHandle node;//发现/spawn服务后,创建一个ServiceClient实例服务客户端,连接名为/spawn的service,请求的数据类型为turtlesim::Spawnros::service::waitForService("/spawn");//查询当前系统中是否有/spawn服务,阻塞型api,循环等待ros::ServiceClient add_turtle = node.serviceClient("/spawn");//封装初始化turtlesim::Spawn的请求数据turtlesim::Spawn srv;//定义名为srv,类型为turtlesim::Spawn的请求数据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);//调用call方法,把封装好的srv发出去,等待服务器反馈。//显示服务调用结果ROS_INFO("Spwan turtle successfully [name:%s]",srv.response.name.c_str());return 0;
 }

配置CMakeList.txt编译规则

设置需要编译的代码和生成的可执行文件

打开learning_service功能包中的CMakeList.txt,在build中声明C++可执行文件并指定库链接另一个库或一个可执行目标:

add_executable(turtle_spawn  src/turtle_spawn.cpp)        //把spawn.cpp代码编译为turtle_spawn规则target_link_libraries(turtle_spawn ${catkin_LIBRARIES})     //把生成的turtle_spawn连接到ros中的库
 

返回到工作空间根目录进行编译
catkin_make
在这里插入图片描述
编译结束中,可在工作空间目录的devel文件夹中的lib文件夹可找到生成的learning_service功能包,包含代码编译生成的可执行文件turtle_spawn

编译并运行客户端

cd ~/ros_novice
 catkin_make
 roscore
 rosrun turtlesim tuetlesim_node
 rosrun learning_service turtle_spawn
 

在这里插入图片描述

Server服务器模型

在这里插入图片描述
在功能包src文件夹下打开命令行 touch turtle_command_server.cpp 创建代码文件

编写服务器端turtle_command_server代码

/*** 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger*/#include 
 #include 
 #include 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的server,注册回调函数commandCallbackros::ServiceServer command_service = n.advertiseService("/turtle_command", commandCallback);// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10turtle_vel_pub = n.advertise("/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;
 }

配置CMakeList.txt编译规则

设置需要编译的代码和生成的可执行文件

打开learning_service功能包中的CMakeList.txt,在build中声明C++可执行文件并指定库链接另一个库或一个可执行目标:

add_executable(turtle_command_server src/turtle_command_server.cpp)        //把spawn.cpp代码编译为turtle_spawn规则target_link_libraries(turtle_command_server ${catkin_LIBRARIES})     //把生成的turtle_spawn连接到ros中的库
 

返回到工作空间根目录进行编译
catkin_make
在这里插入图片描述

编译并运行客户端

cd ~/ros_novice
 catkin_make
 roscore
 rosrun turtlesim tuetlesim_node
 rosrun learning_service turtle_command_server
 rosservice call/turtle_command
 

在这里插入图片描述
通过反复call service可以实现对海龟的开关命令

服务数据的定义使用

在这里插入图片描述
Client端request发布显示人信息的请求,把信息通过service端发布数据,server端收到service发布的数据

自定义show_person服务数据结构

1、在功能包下创建srv文件夹,touch show_person.srv
定义.src文件;//—以上为request数据,—以下为response数据
string name
uint8 age
uint8 sex

uint8 unknown = 0
uint8 male =1
uint8 female = 2


string result
2、在package.xml中添加动态生成msg依赖的功能包

message_generation
 message_runtime
 

3、在CMakeList.txt添加编译选项

################################################
 ## Declare ROS messages, services and actions ##
 ################################################
 在此目录下添加如下命令
 add_service_files(FILES Person.srv)
 ##自动搜索srv下的文件
 generate_messages(DEPENDENCIES std_msgs )
 ##根据文件定义和std_msgs依赖产生对应头文件
 添加依赖
 catkin_package(
 #  INCLUDE_DIRS include
 #  LIBRARIES learning_serviceCATKIN_DEPENDS geometry_msg roscpp rospy std_msg turtlesim message_runtime
 #  DEPENDS system_lib
 )
 

在工作目录中使用catkin_make编译生成头文件

创建服务器代码

/** 该例程用于将请求/show_person服务,服务数据类型learning_service::Person*
 */
 #include
 #includeint main(int argc,char** argv)
 {//初始化节点ros::init(argc,argv,"person_client");//创建节点句柄ros::NodeHandle node;//发现/spawn服务后,创建一个服务客户端,连接名为/spawn的serviceros::service::waitForService("show_person");ros::ServiceClient person_client = node.serviceClient("/show_person");//初始化learning_serviceL::Person请求数据learning_service::Person srv;srv.request.name = "Tom";srv.request.age = 27;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 ;
 }
 

创建客户端代码

/** 该例程将执行/show_person服务,服务数据类型learning_service::Person* */
 #include
 #include//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的server,注册回调函数personCallbackros::ServiceServer person_service = n.advertiseService("/show_person",personCallback);//循环等待回调函数ROS_INFO("Ready to show person inforntion");ros::spin();return 0;
 }

配置服务器/客户端代码编译规则

add_executable(person_client  src/person_client.cpp)        
 ##把person_client.cpp代码编译为person_client可执行文件
 target_link_libraries(person_client ${catkin_LIBRARIES})     
 ##把生成的person_client连接到ros中的库
 add_executable(person_server  src/person_server.cpp)        
 ##把person_server.cpp代码编译为person_server可执行文件
 target_link_libraries(person_server ${catkin_LIBRARIES})     
 ##把生成的person_server连接到ros中的库add_dependencies(person_client ${PROJECT_NAME}_gencpp)
 ## 和动态生成的头文件做依赖
 add_dependencies(person_server ${PROJECT_NAME}_gencpp)
 ## 和动态生成的头文件做依赖
 

在工作空间根目录使用catkin_make编译

运行查看

roscore
 rosrun learning_service person_server
 rosrun learning_service person_client
 

可查看结果
在这里插入图片描述
运行server会发现等待show_person的数据
在这里插入图片描述
运行client请求service端show_person,与此同时可发现server端打印显示client发送的信息。

参数模型

参数命令行使用

rosparam list		列出当前所有参数
 rosparam get param_key 		显示某个参数值
 rosparam set param_key param_value 		设置某个参数值
 rosparam dump file_name 	保存参数到文件
 rosparam load file_name		从文件读取参数
 rosparam delete param_key		删除参数
 

首先在src中创建参数功能包

catkin_create_pkg learning_parameter roscpp rospy std_srvs
 

创建parameter.cpp文件

/*** 该例程设置/读取海龟例程中的参数*/
 #include 
 #include 
 #include 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("/clear");std_srvs::Empty srv;clear_background.call(srv);sleep(1);return 0;
 }

在CMakeList.txt中添加依赖

add_executable(parameter_config src/parameter_config.cpp)
 target_link_libraries(parameter_config ${catkin_LIBRARIES})
 

在工作空间下catkin_make编译
运行测试
roscore
rosrun toutlesim turtlesim_node
rosrun learning_perameter parameter_config
在这里插入图片描述


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。