ROS通信编程入门

目录

一、工作空间的创建

二、创建功能包

三、话题编程

自定义话题编程

四、服务编程

五、动作编程


 

 


 

 


 

 

一、工作空间的创建

首先创建一个工作空间

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

然后进行工作空间的编译

cd ~/catkin_ws
catkin_make

设置环境变量

source devel/setup.bash

进行环境变量的检查

echo $ROS_PACKAGE_PATH

若打印的路径中包括当前工作空间的路径,则说明环境变量设置成功

如果想要设置的环境变量对所有的终端都生效

sudo gedit ~/.bashrc
//在文件末尾添加
source /home/用户名/catkin_ws/devel/setup.bash
//使配置好的环境变量对所有终端都生效
source ~/.bashrc

再次使用echo命令进行环境变量的检查即可

二、创建功能包

命令格式:catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
同一个工作空间下,不允许存在同名功能包
不同工作空间下,允许存在同名功能包

在catkin_ws/src路径下创建功能包,并设置依赖包

cd ~/catkin_ws/src
catkin_create_pkg learning_communication std_msgs rospy roscpp

编译工作空间

cd ~/catkin_ws
catkin_make

三、话题编程

ros的通信机制是分布式通信机制

话题编程的流程:

——创建发布者

——创建订阅者

——添加编译选项

——运行可执行程序

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NzajkyNTMxOQ==,size_16,color_FFFFFF,t_70

 创建发布者

发布者的实现流程:

——初始化ros节点

——向ros master注册节点信息,包括发布的话题名与话题的消息类型

——按照一定的频率循环发布消息

1、在 ~/catkin_ws/src/learning_communicaiton/src下创建talker.cpp文件

cd ~/catkin_ws/src/learning_communication/src
gedit talker

在文件中写入以下代码

#include <sstream>
#include "ros/ros.h"
#include "std_msgs/String.h"
int main(int argc, char **argv)
{
	//ROS节点初始化
	ros::init(argc, argv, "talker");
	//创建节点句柄
	ros::NodeHandle n;
	//创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
	ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
	//设置循环的频率
	ros::Rate loop_rate(10);
	int count = 0;
	while(ros::ok())
	{
		//初始化std_msgs::String类型的消息
		std_msgs::String msg;
		std::stringstream ss;
		ss<<"hello world"<<count;
		msg.data = ss.str();
		//发布消息
		ROS_INFO("%s", msg.data.c_str());
		chatter_pub.publish(msg);
		//循环等待回调函数
		ros::spinOnce();
		//接受循环频率延时
		loop_rate.sleep();
		++count;
	}
	return 0;
}

创建订阅者

订阅者的实现流程

——初始化ros节点

——订阅所需要的话题

——循环等待话题消息。接受后进入回调函数

——在回调函数中完成消息处理

在 ~/catkin_ws/src/learning_communicaiton/src下创建listener.cpp文件

vi listener.cpp

写入以下代码

#include "ros/ros.h"
#include "std_msgs/String.h"
//接收到订阅的消息,会进入消息的回调函数
void chatterCallback(const std_mmsgs::String::ConstPtr& msg)
{
	//将接收到的消息打印处理
	ROS_INFO("I heard: [%s]",msg->data.c_str());
}
int main(int argc, char **argv)
{
	//初始化ROS节点
	ros::init(argc, argv, "listener");
	//创建节点句柄
	ros::NodeHandle n;
	//创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallback
	ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
	//循环等待回调函数
	ros::spin();
	return 0;
}

进行代码的编译

1.编译配置文件CMakeLists.txt

cd ~/catkinx_ws/src/learning_communicaiton
ls -a
//此时会看到显示出来的CMakeLists.txt文件
gedit CMakeLists.txt

在配置文件中加入以下代码

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

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

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NzajkyNTMxOQ==,size_16,color_FFFFFF,t_70

 然后进行工作空间的编译

cd ~/catkin_ws
catkin_make

编译完成并且正确会看到以下提示信息

337fc370a3264aa08e65adddd643c38a.png

 

运行可执行文件

roscore

80f3b952a5e64b149c70bd52a96203c5.png

 然后分别新建两个终端,依次输入

rosrun learning_communication talker
rosrun learning_communication listener

运行话题发布者端口

203c98061aec4f709c4cf917829aeafe.png

运行话题订阅者端口

 c6759ed832174e8db80ead82f011312b.png

 此时说明操作成功,已经成功实现了话题编程

自定义话题编程

1、创建一个msg文件夹

mkdir ~/catkin_ws/src/learning_communication/msg
cd ~/catkin_ws/src/learning_communication/msg
sudo vi Person.msg

在其中写入以下代码

string name
uint8 sex
uint8 age

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

然后返回到learning_communication目录下,进行package.xml文件的编辑

在其中添加以下功能包依赖

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

注意:部分ros版本中exec_depend需要修改为run_depend

gedit CMakeLists.txt

在CMakeListis.txt文件中添加

find_package(catkin REQUIRED COMPONENTS
  std_msgs
  roscpp
  message_generation
)
 
catkin_package(
  CATKIN_DEPENDS std_msgs roscpp message_runtime
)
 
## Generate messages in the 'msg' folder
 add_message_files(
   FILES
   my_Mecanum_speed.msg
 )
 
## Generate added messages and services with any dependencies listed here
 generate_messages(
   DEPENDENCIES
   std_msgs
 )

然后编译即可

cd ~/catkin_ws
catkin_make

然后在现有终端直接输入命令查看自定义消息即可

rosmsg show Person

四、服务编程

服务编程的流程:

——创建服务器server

——创建客户端client

——添加编译选项

——运行可执行程序

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NzajkyNTMxOQ==,size_16,color_FFFFFF,t_70

 1、创建srv文件

mkdir ~/catkin_ws/src/learning_communication/srv
cd ~/catkin_ws/src/learning_communication/srv
sudo vi AddTwoInts.srv

写入以下代码

int64 a
int64 b
---
int64 sum

2、添加功能包依赖

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

3、编辑CMakeLists.txt文件

添加以下代码即可(已经实现了前两步并且添加过功能包依赖的话只需要再添加以下一节语句)

add_service_files(FILES AddTwoInts.srv)

4、创建服务器与客户端

在~catkin_ws/src/learning_communication/src路径下创建server.cpp文件并写入以下代码

#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
//service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request &req,learning_communication::AddTwoInts::Response &res)
{
	//将输入的参数中的请求数据相加,结果放到应答变量中
	res.sum=req.a+req.b;
	ROS_INFO("request: x=%1d,y=%1d",(long int)req.a,(long int)req.b);
	ROS_INFO("sending back response:[%1d]",(long int)res.sum);
	return true;
}
int main(int argc,char **argv)
{
	//ROS节点初始化
	ros::init(argc,argv,"add_two_ints_server");
	//创建节点句柄
	ros::NodeHandle n;
	//创建一个名为add_two_ints的server,注册回调函数add()
	ros::ServiceServer service=n.advertiseService("add_two_ints",add);
	//循环等待回调函数
	ROS_INFO("Ready to add two ints.");
	ros::spin();
	return 0;
}

同样路径下创建client.cpp文件写入以下代码

#include<cstdlib>
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
int main(int argc,char **argv)
{
	//ROS节点初始化
	ros::init(argc,argv,"add_two_ints_client");
	//从终端命令行获取两个加数
	if(argc!=3)
	{
		ROS_INFO("usage:add_two_ints_client X Y");
		return 1;
	}
	//创建节点句柄
	ros::NodeHandle n;
	//创建一个client,请求add_two_ints_service
	//service消息类型是learning_communication::AddTwoInts
	ros::ServiceClient client=n.serviceClient<learning_communication::AddTwoInts>("add_two_ints");
	//创建learning_communication::AddTwoInts类型的service消息
	learning_communication::AddTwoInts srv;
	srv.request.a=atoll(argv[1]);
	srv.request.b=atoll(argv[2]);
	//发布service请求,等待加法运算的应答请求
	if(client.call(srv))
	{
		ROS_INFO("sum: %1d",(long int)srv.response.sum);
	}
	else
	{
		ROS_INFO("Failed to call service add_two_ints");
		return 1;
	}
	return 0;
}

设置配置文件

在CMakelist.txt文件中添加以下依赖

add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)

add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)

然后进行编译

cd ~/catkin_ws
catkin_make

看到以下信息提示即为编译成功

967c68fa1af7479dafa6012df3150b55.png

 然后跟话题编程执行过程相同

roscore
rosrun learning_communication server
rosrun learning_communication client 15 26

直接执行即可。

五、动作编程

9fbf52246aec4440aad76054622702b4.png

 

创建一个action文件

mkdir ~/catkin_ws/src/learning_communication/action
cd ~/catkin_ws/src/learning_communication/action
gedit DoDishes.action

然后在其中写入以下内容

#定义目标信息
uint32 dishwasher_id
---
#定义结果信息
uint32 total_dishes_cleaned
---
#定义周期反馈的消息
float32 percent_complete

返回learning_communication 路径下进行package.xml文件的配置

添加以下依赖

<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<exec_depend>actionlib</exec_depend>
<exec_depend>actionlib_msgs</exec_depend>

然后配置CMakeLists.txt文件

添加以下内容

find_package(catkin REQUIRED actionlib_msgs actionlib)

add_action_files(DIRECTORY action FILES DoDishes.action)

generate_messages(DEPENDENCIES actionlib_msgs)

5766d6e5c14f4ca6b4c43d33a1310aee.png

 然后创建服务器和客户端

cd src

进入src路径下创建DoDishes_server.cpp

#include "ros/ros.h"
#include "actionlib/server/simple_action_server.h"
#include "learning_communication/DoDishesAction.h"
typedef actionlib::SimpleActionServer<learning_communication::DoDishesAction> Server;
// 收到action的goal后调用该回调函数
void execute(const learning_communication::DoDishesGoalConstPtr &goal, Server *as)
{
	ros::Rate r(1);
	learning_communication::DoDishesFeedback feedback;
	ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id);
	// 假设洗盘子的进度,并且按照1Hz的频率发布进度feedback 
	for(int i = 1; i <= 10; i++)
	{
		feedback.percent_complete = i * 10;
		as->publishFeedback(feedback);
		r.sleep();
	}	
	// 当action完成后,向客户端返回结果
	ROS_INFO("Dishwasher %d finish working.", goal->dishwasher_id);
	as->setSucceeded();
}
int main(int argc, char **argv)
{
	ros::init(argc, argv, "do_dishes_server");
	ros::NodeHandle hNode;
	// 定义一个服务器
	Server server(hNode, "do_dishes", boost::bind(&execute, _1, &server), false);
	// 服务器开始运行
	server.start();
	ros::spin();
	return 0;
}

DoDishes_client.cpp

#include "ros/ros.h"
#include "actionlib/client/simple_action_client.h"
#include "learning_communication/DoDishesAction.h"
typedef actionlib::SimpleActionClient<learning_communication::DoDishesAction> Client;
// 当action完成后会调用该回调函数一次
void doneCallback(const actionlib::SimpleClientGoalState &state
	, const learning_communication::DoDishesResultConstPtr &result)
{
	ROS_INFO("Yay! The dishes are now clean");
	ros::shutdown();
}
// 当action激活后会调用该回调函数一次
void activeCallback()
{
	ROS_INFO("Goal just went active");
}
// 收到feedback后调用该回调函数
void feedbackCallback(const learning_communication::DoDishesFeedbackConstPtr &feedback)
{
	ROS_INFO("percent_complete : %f", feedback->percent_complete);
}
int main(int argc, char **argv)
{
	ros::init(argc, argv, "do_dishes_client");
	// 定义一个客户端
	Client client("do_dishes", true);
	// 等待服务器端
	ROS_INFO("Waiting for action server to start.");
	client.waitForServer();
	ROS_INFO("Action server started, sending goal.");
	// 创建一个 action 的 goal
	learning_communication::DoDishesGoal goal;
	goal.dishwasher_id = 1;
	// 发送action的goal给服务端,并且设置回调函数
	client.sendGoal(goal, &doneCallback, &activeCallback, &feedbackCallback);
	ros::spin();
	return 0;
}

然后再编辑CMakeLists.txt文件添加编译所需依赖

add_executable(DoDishes_server src/DoDishes_server.cpp)
target_link_libraries(DoDishes_server ${catkin_LIBRARIES})
add_dependencies(DoDishes_server ${${PROJECT_NAME}_EXPORTED_TARGETS})

add_executable(DoDishes_client src/DoDishes_client.cpp)
target_link_libraries(DoDishes_client ${catkin_LIBRARIES})
add_dependencies(DoDishes_client ${${PROJECT_NAME}_EXPORTED_TARGETS})

然后进行工作空间的编译

cd ~/catkin_ws
catkin_make

 然后进行正常执行即可

roscore
rosrun learning_communication DoDishes_client
rosrun learning_communication DoDishes_server

 

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ROS2编程基础课程文档 ROS 2(机器人操作系统2)是用于机器人应用的开源开发套件。ROS 2之目的是为各行各业的开发人员提供标准的软件平台,从研究和原型设计再到部署和生产。 ROS 2建立在ROS 1的成功基础之上,ROS 1目前已在世界各地的无数机器人应用中得到应用。 特色 缩短上市时间 ROS 2提供了开发应用程序所需的机器人工具,库和功能,可以将时间花在对业务非常重要的工作上。因为它 是开源的,所以可以灵活地决定在何处以及如何使用ROS 2,以及根据实际的需求自由定制,使用ROS 2 可以大幅度提升产品和算法研发速度! 专为生产而设计 凭借在建立ROS 1作为机器人研发的事实上的全球标准方面的十年经验,ROS 2从一开始就被建立在工业级 基础上并可用于生产,包括高可靠性和安全关键系统。 ROS 2的设计选择、开发实践和项目管理基于行业利 益相关者的要求。 多平台支持 ROS 2在Linux,Windows和macOS上得到支持和测试,允许无缝开发和部署机器人自动化,后端管理和 用户界面。分层支持模型允许端口到新平台,例如实时和嵌入式操作系统,以便在获得兴趣和投资时引入和推 广。 丰富的应用领域 与之前的ROS 1一样,ROS 2可用于各种机器人应用,从室内到室外、从家庭到汽车、水下到太空、从消费 到工业。 没有供应商锁定 ROS 2建立在一个抽象层上,使机器人库和应用程序与通信技术隔离开来。抽象底层是通信代码的多种实现, 包括开源和专有解决方案。在抽象顶层,核心库和用户应用程序是可移植的。 建立在开放标准之上 ROS 2中的默认通信方法使用IDL、DDS和DDS-I RTPS等行业标准,这些标准已广泛应用于从工厂到航空 航天的各种工业应用中。 开源许可证 ROS 2代码在Apache 2.0许可下获得许可,在3条款(或“新”)BSD许可下使用移植的ROS 1代码。这两个 许可证允许允许使用软件,而不会影响用户的知识产权。 全球社区 超过10年的ROS项目通过发展一个由数十万开发人员和用户组成的全球社区,为机器人技术创建了一个庞大 的生态系统,他们为这些软件做出贡献并进行了改进。 ROS 2由该社区开发并为该社区开发,他们将成为未 来的管理者。 行业支持 正如ROS 2技术指导委员会成员所证明的那样,对ROS 2的行业支持很强。除了开发顶级产品外,来自世界 各地的大大小小公司都在投入资源为ROS 2做出开源贡献。 与ROS1的互操作性 ROS 2包括到ROS 1的桥接器,处理两个系统之间的双向通信。如果有一个现有的ROS 1应用程序, 可 以通过桥接器开始尝试使用ROS 2,并根据要求和可用资源逐步移植应用程序。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值