学习笔记---机器人操作系统ROS浅析

本文介绍了ROS系统的使用方法,包括节点管理、消息传递、服务调用等核心概念,并提供了创建节点、发布与订阅消息、调用服务的具体实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

机器人操作系统ROS浅析

获得节点列表:rosnode list
查看特定节点信息:rosnode info node-name
终止节点:rosnode kill node-name
//使用Ctrl+c终止节点,在节点管理器中仍然会出现在rosnode列表中,可以使用rosnode cleanup删除

话题和消息

消息传递的理念是:当一个节点想要分享信息时,他就会发布消息到对应的一个或多个话题;当一个节点想要接收信息时,他就会订阅塔索需要的一个或者多个话题。ROS节点管理器负责确保发布节点和订阅节点能找到对方;而且消息是直接地从发布节点传递到订阅节点,中间并不经过节点管理器转交。

查看节点构成的计算图:rqt_graph
查看话题列表:rostopic list
用命令行发布消息:rostopic pub -r rate-in-hz topic-name message-type message-content
例如:
rostopic pub -r 1/turtle1/cmd_vel geometry_msgs/Twist ‘[2,0,0]’’[0,0,0]’

创建功能包:catkin_create_pkg package-name
以上代码创建了一个存放这个功能包的目录,并在那个目录下生成了两个配置文件
1.package.xml
2.CMakeList.txt
Cmake是一个符合工业标准的跨平台编译系统,包括应该生成哪种可执行文件,需要哪些源文件,以及在哪里可以找到所需的头文件和链接库。

头文件ros/ros.h包含了标准ROS类的声明,你将会在每一个你写的ROS程序中包含它。

#include <ros/ros.h>
int main(int argc,char **argv)
{
	/*ros::init函数初始化ROS客户端库。 请在你程序的起始处调用
	一次该函数 。函数最后的参数是一个包含节点默认名的字符
	串。*/
	ros::init(argc,argv,"hello_ros");
	/*
	ros::NodeHandle(节点句柄) 对象是你的程序用于和ROS系统
	交互的主要机制 。创建此对象会将你的程序注册为ROS节点
	管理器的节点。最简单的方法就是在整个程序中只创建一个
	NodeHandle对象。
	*/
	ros::NodeHandle nh;
	/*
	ROS_INFO_STREAM 宏将生成一条消息,且这一消息被发送到
	不同的位置,包括控制台窗口。
	*/
	ROS_INFO_STREAM("Hello,_ros!");
}

编译Hello程序

要编译和运行以上程序,需要四个步骤
1.声明依赖库
2.声明可执行文件
3.编译工作区
4.Sourcing setup.bash
soucre devel/setup.bash

在pubvel程序中,我们要发布一条类型为geometry_msgs/Twist的消息(名为geometry_msgs的包所拥有的类型为Twist的消息),我们应该
#include <geometry_msgs/Twist.h>
这个头文件的目的是定义一个C++类,此类和给定的消息类型含有相同的数据类型成员。这个类定义在以包名命名的域名空间中。这样命名的实际影响是当引用C++代码中的消息类时,你将会使用双分号(::)来区分开包名和类型名,双分号也称为范围解析运算符。

pubvel.cpp 用于给turtlesim仿真器中的海龟发布随机生成的运动速度指令消息

#include <ros/ros,h>
#include <geometry_msgs/Twist.h>  //为了使用geometry_msgs::Twist
#include <stdlib.h> //为了使用rand() 和 RAND_MAX

int main(int argv,char** argv)
{
	ros::init(argc,argv,"publish_velocity");
	ros::NodeHandle nh;

	ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("turtle1/cmd_vel",1 0 0 0);

	srand(time(0));
	
	ros::Raterate(2);
	while(ros::ok())
	{
		geometry_msgs::Twist msg;
		msg.linear.x=double(rand())/double(RAND_MAX);
		msg.angular.z=2* double ( rand ( ) )/double (RAND_MAX) − 1 ;

		pub . publish ( msg ) ;

		ROS_INFO_STREAM( "Sending random velocity command : "
		<< " linear=" << msg.linear.x
		<< " angular=" << msg.angular.z) ;

		rate.sleep();
	}
}

pubvel的while循环的条件是:
ros::ok()
这个函数检查我们的程序作为ROS节点是否仍处于运行良好的状态。

控制消息发布频率ros::Rate rate(2);
这个对象控制循环运行速度,其构造函数中的参数以赫兹为单位。这个例子创建了旨在规范每秒钟执行两个迭代循环的速率对象。

rate.sleep();调用此方法时可以在程序中产生延迟。

编写回调函数
发布和订阅消息的一个重要的区别是订阅者节点无法知道消息什么时候到达。为了应对这一事实,我们必须把响应到消息事件的代码放到回调函数里,ROS每接收到一个新的消息将调用一次这个函数。如
void function_name(const package_name::type_name&msg)
{

}

创建订阅者对象
一个ros::Subscriber对象
ros::Subscribe sub = node_handle.subscribe(topic_name,queue_size,pointer_to_callback_function);

  1. node_handle 与我们之前多次见到的节点句柄对象是相同的。
  2. topic_name 是我们想要订阅的话题的名称,以字符串的形式
    表示。ruru
  3. queue_size 是本订阅者接收消息的队列大小,是一个整数。
    通常,你可以使用一个较大的整数,例如 1000,而不用太多
    关心队列处理过程

**ros::spinOnce()**要求ROS去执行所有挂起的回调函数,然后将控制权限返回给我们
**ros::spin()**要求ROS等待并且执行回调函数,直到这个节点关机。

生成简单的日志消息
总共有五个基本的C++宏用来产生日志消息。
ROS_DEBUG_STREAM(message);
ROS_INFO_STREAM(message);
ROS_WARN_STREAM(message);
ROS_ERROR_STREAM(message);
ROS_FATAL_STREAM(message);
生成一次性日志消息
ROS_DEBUG_STREAM_ONCE(message);
ROS_INFO_STREAM_ONCE (message);
ROS_WARN_STREAM_ONCE (message);
ROS_ERROR_STREAM_ONCE (message);
ROS_FATAL_STREAM_ONCE (message);
生成频率受控的日志消息
ROS_DEBUG_STREAM_THROTTLE(interval, message);
ROS_INFO_STREAM_THROTTLE(interval, message);
ROS_WARN_STREAM_THROTTLE(interval, message);
ROS_ERROR_STREAM_THROTTLE(interval, messge);
ROS_FATAL_STREAM_THROTTLE(interval, message);

除了在控制台上显示,每一个日志消息都被发布到话题
/rosout 上。该话题的消息类型是 rosgraph_msgs/Log。
rostopic echo /rosout
或者
rqt_console

查看当前账户中被ROS日志消耗的硬盘空间
rosclean check
清空日志
rosclean purge

计算图源命名

节点、 话题、 服务和参数统称为计算图源,而每个计算图源
由一个叫计算图源名称(graph resource name)的短字符串标识。

启动文件的基本元素

最简单的启动文件由一个包含若干节点元素的根元素组成
1.插入根元素,对于ROS启动文件,根元素由一对launch标签定义

<launch>
...
<launch>

每个启动文件的其他元素都应该包含在这两个标签之内
2.启动节点任何启动文件的核心都是一系列的节点元素,每个节点元素指向一个需要启动的节点。节点元素的形式为:

<node
	pkg="package-name"
	type="executable-name"
	name="node-name"
/>

请求复位respawn=“true”
//当节点停止的时候,roslaunch会重新启动该节点。

必要节点required="“true”
//当一个必要节点终止的时候, roslaunch 会终止所有其他活跃节点并退出。

respawn和required二者的作用是相互矛盾的,因此,如果对一个节点同时配置了这两种属性,roslaunch会报错。

在新终端中执行后续操作
在launch文件中添加如下内容:

launch-prefix=”xetrm-e”

配置命名空间(ns)属性
ns=“namespace”

<launch>
	<node
		name="turtlesim_node"
		pkg="turtlesim "
		type="turtlesim_node"
		ns="sim1
	/>
	<node
		pkg="turtlesim "
		type="turtle_teleop_key"
		name="teleop_key"
		required="true "
		launch −prefix="xterm −e"
		ns="sim1"
	 />
	<node
		name="turtlesim_node"
		pkg="turtlesim "
		type="turtlesim_node"
		ns="sim2"
	/>
	<node
		pkg="agitr "
		type="pubvel"
		name="velocity_publisher "
		ns="sim2"
	/>
<launch>

在这里插入图片描述
创建组

<group ns = "namespace"/>
...
</group>

参数

查看参数列表
rosparam list

获取参数
如获取背景颜色
rosparam get /background_r

设置参数
如设置背景颜色
rosparam set /backgroup_r 255

使参数生效
rosservice call /clear

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

使用如下语句生效

ros::ServiceClient clearClient = nh.serviceClient<std_srvs::Empty>("/clear")

服务

服务调用
服务调用与消息的区别主要体现在两个方面。

  1. 服务调用是双向的,一个节点给另一个节点发送信息并等待响应,因此信息流是双向的。作为对比,当消息发布后,并没有响应的概念,甚至不能保证系统内有节点订阅了这些消息。
  2. 服务调用实现的是一对一通信。每一个服务由一个节点发起,对这个服务的响应返回同一个节点。另一方面,每一个消息都和一个话题相关,这个话题可能有很多的发布者和订阅者。

其过程是一个客户端(client)节点发送一些称为请(request)的数据到一个服务器(server) 节点, 并且等待回应。
列出所有服务
rosservice list
调用服务

bool success = service_client_call(request,reponse);

编写服务的回调函数
bool function_name(
package_name::service_type::Request &req),
package_name::service_type::Response &resp)
)
{

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值