ROS基本

基础知识

ROS基础知识都是基于:A Gentle Introduction to ROS, Jason M. O'Kane 进行学习的

A Gentle Introduction to ROS - Jason M. O'Kane

ros 中所有的软件(或直观说可执行文件)都被组织成软件包(Packages)的形式,常用命令:

rospack list

rospack find package-name

ros节点(node),相互独立的程序运行实例(可认为是运行中的某个软件包)(可执行相同程序的多个副本,每个副本使用不同的节点名)。节点点是松耦合的(相互独立的),每个节点都不需要显式知道其他节点的存在与否;它们的唯一交互方式是间接地发生在基于话题和消息的通信层。
注意:在一个程序中使用标准的roscpp接口来运行多个节点是不可能的,也就是说一个程序(软件包)对应一个节点

ros节点管理器(The Master),可通过它来实现节点间的通信,常用命令:

roscore 启动节点管理器, 或者 roslaunch 自适应启动节点管理器(如果有节点管理器运行,使用已有的,没有就启动),它可一次性启动多个节点

先启动节点管理器,再启动节点
roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key

启动节点 
rosrun package-name executable-name (软件包名称;软件包中的可执行文件名称;可以用Tab补全)

查看节点列表
rosnode list

查看节点
rosnode info node-name

修改节点名称
rosrun package-name executable-name:=node-name
(rosrun turtlesim turtlesim_node __name:=A)
当试图运行两个同名节点时,新节点将会正常运行,而之前的节点将会终止

终止节点
rosnode kill node-name  (用ctrl+C命令可杀死进程,但是不一定会注销rosnode中的节点名,可使用 rosnode cleanup 来将节点名从列表中删除)

话题与消息
ros节点间的信息传递通过消息完成,而消息的传递渠道是通过话题。当一个节点想分享消息时,会发布一个或多个话题;当一个节点想接收消息时,会订阅一个或多个话题;发布和订阅间的匹配关系由节点管理器来完成。节点只管发布,而不用担心是否有其他节点订阅,即会出现有话题发布但没有订阅的情况。(用 rqt_graph 命令查看节点间发布与订阅关系)

节点/teleop_turtle向话题/turtle1/cmd_vel发布消息;节点/turtlesim从话题/turtle1/cmd_vel订阅消息

基于话题和消息的通信机制是多对多的,即多个发布者和多个订阅者可以共享同一个话题

话题列表
rostopic list

查看某话题详细信息(话题的消息类型——话题中消息的数据类型)
rostopic echo topic-name

查看消息类型
rosmsg show message-type-name

查看某个话题的具体消息(打印消息内容)
rostopic info topic-name

测量消息发布频率(可验证某个话题中的消息是否正常)
rostopic hz topic-name  频率,每秒发布的消息数量
rostopic bw topic-name  带宽,每秒发布消息所占的字节量

手动发布消息
详见P43页

消息类型的命名
packa-name/type-name
每条消息类型都属于一个特定的包,把包的名字包含在消息类型名里能避免命名冲突

编译问题

工作区目录以及工作区目录下的src目录(保存源码)
如 ./learning/src

创建功能包
在src目录下运行:
catkin_create_pkg package-name
会生成一个存放这个功能包的目录,并在那个目录下生成了两个配置文件。即创建一个名为package-name的文件夹,并在该文件夹下生成了 package.xml(配置文件) 和 CMakeLists.txt(脚本文件) 两个配置文件

编辑配置文件
CMakeLists.txt 作用:声明程序所依赖的其他功能包,以确保catkin能够向c++编译器提供合适的标记来定位编译功能包所需的头文件和链接库。

find_package(catkin REQUIRED COMPONENTS package-names)
add_executable(executable-name source-files)
target_link_libraries(executable-name ${catkin_LIBRARIES})

package.xml 清单文件的声明也需要随内容的修改而修改,虽然其中声明的依赖库并没有在编译过程中用到;如果你在此处忽略它们,你可能不会看到任何错误消息,直到发布你的包给其他人,他们可能在没有安装所需包的情况下编译你发布的包而导致报错。

<build_depend>package-name</build_depend>
<exec_depend>package-name</exec_depend>

如以hello.cpp源码为例子:

find_package(catkin REQUIRED COMPONENTS roscpp)
add_executable(hello hello.cpp)
target_link_libraries(hello ${catkin_LIBRARIES})

<build_depend>roscpp</build_depend>
<exec_depend>roscpp</exec_depend>

编译工作区
编译所有包中的所有可执行文件,需要在工作区目录运行
Base path: /home/robomaster/learning
catkin_make
catkin_make -j4 package  // 编译指定的包,-j 对应 --jobs,表示可以同步进行的任务

设置环境变量
仍然在工作区目录运行,且需要注意的是,每个终端重新运行时,需要执行一次,但执行过后,即使重新编译也不需要再次执行。即重启端口后需要运行一次。
source devel/setup.bash

执行/运行

在新端口配置完环境变量后,编译完成的软件包就能被ros找到,它就和其他软件包一样可以被执行。但需注意,软件包都以节点形式运行,所以需要先运行节点管理器:
roscore
rosrun agitr hello  (rosrun package-name executable-name)

日志消息

DEBUG \ INFO \ WARN \ ERROR \ FATAL
共五种消息类型
ROS_DEBUG_STREAM(message);
ROS_INFO_STREAM(message);
ROS_WARN_STREAM(message);
ROS_ERROR_STREAM(message);
ROS_FATAL_STREAM(message);

生成一次性日志消息
消息只生成一次,之后不再生效
ROS_INFO_STREAM_ONCE (message);

生成频率受控的日志消息
ROS_DEBUG_STREAM_THROTTLE(interval, message);
interval 为间隔时间,单位s,表示相邻日志消息出现的最小时间间隔

日志消息的传递目的地
控制台 、rosout话题的消息、由rosout节点生成的日志文件

计算图源命名

全局命名空间(/)
全局名称、相对名称、私有名称
默认命名空间(默认的命名空间是单独地为每个节点设置的,而不是在系统范围进行。)
编写节点时并不推荐使用全局名称,推荐使用相对名称,移植性更强。

注意:默认命名空间本身也是相对名称,是在全局命名空间(/)下的相对名称,如果一个相对名称是:sim,它的解析就是:/sim 。

roslaunch

启动文件写法
插入根元素:
<launch> …… </launch>
启动节点:
<node
  pkg=”package-name”        // 软件包名
  type=”executable-name”  // 可执行文件名
  name=”node-name”  //  节点名称,需要填写相对名称,不然会报错
  output=”screen”  // 标准输出会输出在控制台中,而不是储存在日志文件下
  respawn=”true”  // 请求复位。当节点停止的时候, roslaunch会重新启动该节点。
  required=”true”  // 必要节点。如果该节点终止,,roslaunch会终止所有其他活跃节点并退出
// respawn 和 required 是相矛盾的,一个节点至多只能配置一种属性
  launch-prefix=“command-prefix”  // 启动前缀 launch-prefix=”xetrm-e” ,可为节点保留独立的终端
  ns=”namespace”  // 对一个节点压入(pushing down)默认命名空间
/>  // 隐式结束标签,但是当节点有remap或者param元素,那么该显式结束标签是必不缺少的。

<node
  pkg=”turtlesim”
  type=”turtlesim_node”
  name=”turtlesim_node”>
  <remap from=”turtle1/pose”to ”tim”/>
</node>

也可以在启动文件顶层使用重映射属性
<launch>
  <remap from=”original-name”to ”new-name”
  />  // 将会应用到所有后续节点
<include file=”$(find package-name)/launch-file-name”>  // 包含其他启动文件
// 搜索一个功能包中的启动文件时,会搜索功能包内的所有子目录
<include file=”…” ns=”namespace”/>  // 包含元素支持命名空间属性,可以将内容压入一个指定的// 命名空间中去。
<arg name=”arg-name” default=”arg-value”/>  // default参数可覆盖,value参数不可覆盖
  ....
</launch>

roslaunch package-name launch-file-name arg-name:=arg-value  // 对启动文件中的参数赋值(每一个参数都需要赋值,且只能给默认值default赋值)
可用 $(arg arg-name) 来获取参数值

<incluce file=”path–to-launch-file”>
  <arg name=”arg-name” value=”arg-value”/>  // 向包括的启动文件中发送参数值
  <arg name=”arg-name” value=”$(arg arg-name)”>  // 两个启动文件(包含文件和被包含文件)有// 一些共同的参数
  …
</include>

创建组

<group ns=”namespace” if ="$(arg arg-name)" >  // 只有ns、if和unless三个属性可以通过组进行
//传递

</group>

参数

命令行获取参数
rosparam list  // 查看参数列表,得到参数的字符串名称,也即计算图源的全局名称
// 参数名是一个字符串,名称字符串
rosparam get parameter_name  // 查询参数,查询某个参数的值
rosparam get namespace  // 检索给定命名空间中的每一个参数的值;如 rosparam get / 查询全局//命名空间,可以得到所有参数的值
rosparam set parameter_name(namespace) parameter_value  // 设置参数的值
rosparam dump filename namespace  // 创建参数文件,以YAML文件的形式存储命名空间中的所
//有参数
rosparam load filename namespace  // 加载参数文件
// 创建和加载参数文件的命名空间参数是可选的,默认值为全局命名空间(/)

使用C++获取参数
void ros::param::set(parameter_name, input_value);
bool ros::param::get(parameter_name, output_value);

在启动文件中设置参数
<param name="param-name" value="param-value" />  // 如果是在节点元素中包含param元素,那// 么它总是被当作私有名称解析的
<rosparam command="load" file="path-to-param-file" />
<rosparam
command="load"
file="$(find package-name)/param-file"
/>  // 参数文件通常是通过rosparam dump命令创建的

服务

命令行查看和调用服务
rosservice list  // 目前活跃的所有服务
rosnode info node-name  // 某个特定节点提供的服务
rosservice node service-name  // 反向查询,查找提供给特定服务的节点
rosservice info service-name  // 查询某个服务的详细信息,推荐(提供服务节点,服务数据类型)
rossrv show service-data-type-name  // 查询服务数据类型的详情,短横线(---)之前的数据是请
// 求项,短横线之后的所有字段是响应项
命令行调用服务
rosservice call service-name request-content  // request-content 由调用服务的数据类型决定

客户端程序声明请求和响应类型
#include <package_name/type_name.h>  // 需包含将要使用的服务数据类型,消息数据类型同理
创建客户端对象
ros::ServiceClient client = node_handle.serviceClient<service_type>(service_name)
// 调用 serviceClient 方法,service_type 为服务数据类型,service_name 为服务名称(相对名称)
创建请求和响应对象
package_name::service_type::Request  // turtlesim::Spawn::Request req
package_name::service_type::Response  // turtlesim::Spawn::Response resp
// Request 类的构造函数给这些域提供的是无意义的缺省值,因而要给每个域重新赋值
// Response 对象的信息应该来自于服务器节点,不应该试图给它的数据成员赋值
// std_srvs/Empty(空字符串)作为其数据类型
bool success = service_client.call(request,reponse)  // 调用服务

 

常见问题

1. 重启终端后需运行配置文件:
source devel/setup.bash (找到需要运行文件的devel文件夹路径)

2.启动任何包之前,需要先启动节点管理器:
roscore
建议单独一个终端运行改命令

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值