ROS学习记录(一)核心概念:话题、服务、文件系统

ROS中的基本执行单元是节点,它们通过ROSMaster进行管理和通信。节点间通过话题异步传输数据,使用发布/订阅模型。消息作为话题的数据,有特定类型和结构。服务则采用同步的服务器/客户端模型,用于处理逻辑。参数是全局共享的,适合存储静态配置。此外,功能包是ROS软件的基本组织形式,包含源码、配置和数据定义。
摘要由CSDN通过智能技术生成

在ROS中重要的是理解各种通信机制以及组成结构,学习时多想想计算机网络课程上的相关概念会更好理解

节点与节点管理器

节点(Node

节点是ROS的基本执行单元。通过节点可以执行一个具体任务的进程、独立运行的可执行文件;
在不同节点之间可以使用不同的编程语言,并且可以分布在不同的主机上运行,ROS提供了一整套通信的底层方案用于节点或不同设备间的通信

节点管理器(ROS Master

节点管理器是ROS所有节点任务的控制中心。它负责为节点提供命名和注册服务;
节点控制器会跟踪和记录话题/服务通信,辅助节点之间相互查找、建立连接;
它提供了参数服务器,各个节点之间可以通过服务器存储和检索运行时的参数。

通信方式

通信协议的底层为ROSTCP/ROSUDP

话题通信(Topic

话题通信属于异步通信,通信模型为发布/订阅,多用于数据传输
话题是节点间用于传输数据的重要总线,话题的模型是发布/订阅模型,数据由发布者传输到订阅者,同一个话题的订阅者可以不唯一。属于一对多的结构。
消息 Message
消息是话题的数据,消息具有一定的类型和数据结构,包括ROS提供的标准类型和用户自定义类型;消息使用的是与编程语言无关的.msg文件定义内容,在编译的过程中生成对应的代码。通过独立的文件定义,使得消息数据可以不依赖于某一种具体的编程语言实现通信。
Node(Publisher)->(Topic\Message Type)->Node(Subscriber)…多对多
在话题模型中,我们使用发布+订阅的方式进行通信。Publisher发布一个Topic,其中包含消息Message,订阅者Subscriber来订阅这个Topic获得其中的Message。

创建功能包

cd ~/workplace-path/src
catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim

创建发布者和订阅者代码

Publisher

下面的代码以pose_subscriber为例演示了:初始化ROS节点;向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型;创建了消息数据;按照一定的评率循环发布消息;

#include <ros/ros.h>
#include "learning_topic/Person.h"

int main(int argc, char **argv)
{
	ros::init(argc, argv, "person_publisher");	//ROS节点初始化
	ros::NodeHandle n;		//创建节点句柄
	//创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度为10
	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类型的消息
		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;
}
Subscriber

代码流程:初始化ROS节点;订阅需要的话题;循环等待话题消息,接收到消息后进入回调函数;在回调函数中完成具体的操作。

#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节点
	ros::init(argc, argv, "person_subscriber");
	
	//创建节点句柄
	ros::NodeHandle n;
	
	//创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
	ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
	
	//循环等待回调函数
	ros::spin();

	return 0;

}
CMakeLists.txt

需要设置编译的代码和生成可执行文件,并且设置链接库;

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)

编译和运行
#进入工作空间目录
cd ~/workplace-Path
#编译
catkin_make
#添加环境变量
source devel/setup.bash
#启动ROS
roscore
#运行publisher和subscriber的可执行文件
rosrun person_publisher person_subscriber

服务(Service

服务属于同步通信通信模型为服务器/客户端,多用于逻辑处理
Service是使用客户端/服务端(C/S)模型,客户端发送请求数据,服务器完成处理后返回应答数据,不同于话题通信具有数据缓冲区,服务是没有缓冲区的。在Service中与Topic类似的,使用和编程语言无关的.srv文件定义请求和应答数据结构,编译过程中生成相对应的代码。
Node(Service Server) -->(>request,response<)–>Node(Service Client)…一对多(一个server)

Server
#include <ros/ros.h>
#include <learning_service/Person.h>

//回调函数,输入参数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的service,注册回调函数personCallback
	ros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);
	
	//进入循环等待回调函数
	ROS_INFO("Ready to show person informtion");
	ros::spin();

	return 0;
}
Client
#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;

	//发现/show_person服务后,创建一个服务客户端,连接名为/show_person的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;

}
CMakeLists.txt
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)

参数(Parameter

参数是一种全局共享字典
它可以提供通过网络访问的共享、多变量字典。节点可以使用参数服务器来存储和检索运行时的参数。在使用上更加合适用来存储静态、非二进制的配置参数,不适合用来存储动态的配置数据。

#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("/turtlesim/background_r", red);
	ros::param::get("/turtlesim/background_g", green);
	ros::param::get("/turtlesim/background_b", blue);

	ROS_INFO("Get Backgroud Colorp[%d, %d, %d]",red, green, blue);

	ros::param::set("/turtlesim/background_r", 255);
	ros::param::set("/turtlesim/background_g", 255);
	ros::param::set("/turtlesim/background_b", 255);

	ROS_INFO("Set Background Color[255, 255, 255]");

	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;
}

文件系统

功能包(Package

是ROS软件中的基本单元,包含节点源码、配置文件、数据定义;

功能包清单(Pack manifest

用来记录功能包的基本信息,包含作者信息、依赖选项、编译标志等

元功能包(Meta Packages

组织多个用于同一目的的功能包

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

絮沫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值