3 ROS1通讯编程提高(1)
创始人
2025-06-01 21:54:04
0

3 ROS1通讯编程提高

  • 3.1 使用VS Code编译ROS1
    • 3.1.1 VS Code的安装和配置
      • 3.1.1.1 VS Code以及插件安装
      • 3.1.1.2 VS Code配置ROS1工作空间
      • 3.1.1.3 VS Code运行ROS1的方法
      • 3.1.1.3 参考资料
    • 3.1.2 使用VScode编译C++文件
    • 3.1.3使用VScode编译Python文件
  • 3.2 ROS1动作编程
    • 3.2.1 动作编程模型
    • 3.2.2 动作编程基础示例
      • 3.2.2.1 使用VS Code创建动作编程项目
      • 3.2.2.2 配置action动作文件
      • 3.2.2.3 C++实现action基本编程
      • 3.2.2.4 Python实现action基本编程\
    • 3.2.3 动作编程总结
      • 3.2.3.1 动作编程的顺序流程
      • 3.2.3.2 动作编程逻辑
    • 3.2.4 参考

  • 其他ROS1学习笔记: ROS1学习笔记
  • 代码仓库:Github连接地址
  • 欢迎各位互相学习交流

3.1 使用VS Code编译ROS1

3.1.1 VS Code的安装和配置

3.1.1.1 VS Code以及插件安装

  1. VS Code的下载安装:

VS Code的下载链接:VS Code 官网连接;历史版本下载链接:VS Code历史版本,选择合适的版本,对于Linux系统下载deb文件双击运行,或者输入命令sudo dpkg -i vscode安装包名.deb即可。

  1. VS Code的插件配置:
    1. VS Code编译ROS需要的插件主要包括:ROS、C/C++、Python、CMake、CMake Tools以及中文汉化插件Chinese(simplified) Language Pack for Visual Studio Code,如图所示:

在这里插入图片描述

    1. 其中Python可能需要设置解析器的位置即usr/bin/python2.7,重启VS Code,配置好的插件环境如图所示:

在这里插入图片描述

3.1.1.2 VS Code配置ROS1工作空间

  1. VS Code打开工作空间:
    1. 在终端进入到工作空间即cd catkin_ws
    1. 输入命令code .直接在VS Code打开工作空间,如图所示

在这里插入图片描述

  1. 配置工作空间下的json文件:在VS Code打开的工作空间,会出现一个.vscode文件夹,里面存放了三个json文件,用于配置C++和Python编译ROS,下面依次介绍:
    1. task.json文件:用于配置C++和Python编译ROS任务,配置好之后,可基本上后续不需要进行改动。
// /home/ubuntu/catkin_ws/.vscode/tasks.json
{"version": "2.0.0","tasks": [{"type": "shell","args": ["--directory","/home/ubuntu/catkin_ws"],"problemMatcher": ["$catkin-gcc"],"command":"catkin_make","group": "build","label": "catkin_make: build_by_vscode","presentation": {"reveal": "always"}}]
}
    1. c_cpp_properties.json:用于配置C++编译ROS时的一些C++特有的路径和代码规范,配置本次配置好,后续可能出现修改地方主要在于这些路径位置。
// /home/ubuntu/catkin_ws/.vscode/c_cpp_properties.json
{"configurations": [{"browse": {"databaseFilename": "","limitSymbolsToIncludedHeaders": true},"includePath": ["/opt/ros/melodic/include/**","${workspaceFolder}/devel/include/**",//配置成自身工作空间的devel文件夹的路径;//目的是指向自定义msg/action/srv等路径."/usr/include/**"],"name": "ROS","cppStandard":"c++17","intelliSenseMode": "gcc-x64","compilerPath": "/usr/bin/gcc","cStandard": "c11"}],"version": 4
}
    1. settings.json:用于配置Python编译ROS时的一些Python包路径和规范,配置好之后,可能出现变换的地方也在这些路径位置。
// /home/ubuntu/catkin_ws/.vscode/settings.json
{"python.autoComplete.extraPaths": ["/opt/ros/melodic/lib/python2.7/dist-packages","${workspaceFolder}/devel/lib/python2.7/dist-packages"// 如果是高版本ROS可能是Python3,按照自定义消息一样查看中间文件位置确定],"cmake.configureOnOpen": true,"cmake.sourceDirectory": "${workspaceFolder}/src"
}

3.1.1.3 VS Code运行ROS1的方法

  1. 编译运行:
  • 方法一:使用快捷键或者在VS Code的编译器【终端】–【运行生成任务】即Crtl+Shift+B,点击之后选择catkin_make: build_by_vscode(在task.json的label名字)即可编译整个工作空间。
  • 方法二:在VS Code下面的终端(或者在【终端】–【新终端】即Crtl+Shift+`)cd 到catkin_ws下进行catkin_make编译

3.1.1.3 参考资料

  1. 参考文献:
    VS Code的tast.json查考文件;
    VS Code的C++查考文件;
    VS Code的Python查考文件;
    【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程

3.1.2 使用VScode编译C++文件

  1. catkin_ws/src/目录下右键create catkin package创建包,然后按照提示命名如test,然后输入依赖项roscpp rospy std_msgs

  2. catkin_ws/src/test/src下右键新建test_c.cpp文件,编辑test_c.cpp文件。

// test_c.cpp文件用于测试ROS1环境
#include "ros/ros.h"
int main(int argc, char* argv[])
{ros::init(argc,argv,"i_am_nodename");ROS_INFO("HELLO");return 0;
}
  1. 配置catkin_ws/src/test/src/CMakeLists.txt文件,然后编译运行。
    1. 在136行,取消 add_executable(${PROJECT_NAME}_node src/test_node.cpp)的注释,修改为 add_executable(i_am_nodename src/test_c.cpp)
    1. 其次在149-151行的target_link_libraries(${PROJECT_NAME}_node…) 修改为 target_link_libraries(i_am_nodename…)即可
    1. 编译运行(直接在VScode的终端下的+号新建终端,输入roscore,新建终端输入rosrun test i_am_nodename即可查看INFO的消息)。

3.1.3使用VScode编译Python文件

  1. 之前同编译C++是Step1-Step3,此时在catkin_ws/src/test/文件夹下创建Python文件夹scripts,在scripts文件夹里新建Python文件test_p.py
  2. 编写Python程序,赋予可执行权限,然后运行客户端roscore,最后rosrun test test_p.py即可。
#! /usr/bin/env python
import rospy
if __name__ =='__main__':rospy.init_node("test_p")rospy.loginfo("ok")

Tips:
在Ubuntu20.04版本的ROS需要配置CMakeLists文件,大约在161行处,类似C++一样添加Python文件的位置。同时对于高版本的Python编译ROS在Python文件头部是没有#!/usr/bin/env
python,采用命令:sudo ln -s /usr/bin/python3 /usr/bin/python创建Python的连接。

3.2 ROS1动作编程

3.2.1 动作编程模型

在任何ROS的大型系统中,如果向节点发送请求以执行某些任务,最后收到对请求的回复,这一操作主要是通过ROS的服务编程实现,但是如果服务需要很长时间来执行,用户可能希望能够在执行期间取消请求或获得有关请求进展情况的定期反馈,基本的服务编程的应答模式是满足不了的,因此ROS提供actionlib即动作编程完成这些操作。

  • 动作编程的作用:针对服务编程的应答模式的提升,在服务端执行过程中能够取消或者获得服务器状态,动作编程一般适用于耗时的请求响应场景,用以获取连续的状态反馈。

  • 动作编程的例子:如巡检机器人导航过程中,从A到B的导航过程,应该是一个动作编程,即目标是B,在A到B时,提供导航状态。

在这里插入图片描述
在动作编程中,客户端发送目标(goal)或者取消指令(cancel)给服务端,服务端提供状态(status)、实时反馈(feedback)和结果(result)。

官方以移动机器人为例解释goal、feedback和result,即

  • 1)目标(goal):为了使用动作完成任务,引入了可以由 ActionClient 发送到 ActionServer 的目标的概念。在移动基地的情况下,目标是 PoseStamped 消息,其中包含有关机器人应移动到世界何处的信息,在官方洗碗例子中对目标的描述也是需要选择的那个洗碗工是谁。
  • 2)回馈(feedback):服务器持续反馈 ActionClient目标的增量进度。对于移动机器人,这可能是机器人沿路径的当前位置。
  • 3)结果(result):目标完成后,结果从 ActionServer 发送到 ActionClient,这与反馈不同,因为它只发送一次。当客户端请求的目的(goal)是提供某种信息时,这就非常有用。对于移动机器人,结果不是很重要,但它可以是机器人的最终位置(不代表就是目的地)。

3.2.2 动作编程基础示例

动作编程的基本思想和自定义的消息话题编程是一致的。

动作编程内容:洗盘子动作编程,两个节点,一个为客户端一个为服务端,客户端发送数字1(代码实现)给给服务端,作为选择哪个洗碗工,服务端接收到之后持续反馈进度给客户端,最后发送数字100(代码实现)作为结果返回。

3.2.2.1 使用VS Code创建动作编程项目

(一)使用VS Code新建功能包:

  1. 打开VS Code和工作空间,新建动作编程功能包并创建ROS文件夹结构。
    1. 打开VS Code和工作空间,在工作空间catkin_ws下输入命令code .打开VS Code,打开后如果出现提示Select a kit for catkin_ws,则选择第一项Scan for kit即可。

在这里插入图片描述

    1. 新建动作编程功能包,右键工作空间catkin_ws的src目录,选择create catkin package然后在VS Code的提示下输入包名action_communication,回车之后输入依赖项roscpp rospy std_msgs即可

在这里插入图片描述

    1. 新建ROS结构的文件夹,即在功能包下新建action文件夹和scripts文件夹。

3.2.2.2 配置action动作文件

(二)定义action动作文件:

  1. 定义动作文件。在action_communication/action下创建自定义动作文件.action,这里为DoDishes.action文件。其中的内容分为三个部分:
  • 第一部分goal对应目标数据,即客户端发布数据。
  • 第二部分result定义结果,服务端应答给客户端的结果。
  • 第三部分是反馈部分,服务端反馈一些信息给客户端。
# catkin_ws/src/action_communication/action/DoDishes.action
# Define the goal
uint32 dishwasher_id  # Specify which dishwasher we want to use
---
# Define the result
uint32 total_dishes_cleaned
---
# Define a feedback message
float32 percent_complete

(三)配置action文件

  • 配置msg文件包括在package.xml和CMakeList.txt配置两部分。
  1. 在package.xml添加依赖项actionlib和actionlib_msgs四项,二者都是依赖项和执行依赖项。
// /catkin_ws/src/action_communication/package.xmlactionlibactionlib_msgsactionlibactionlib_msgs
  1. 在功能包的CmakeLists.txt添加编译选项,包括四部分。
    1. 添加编译依赖项功能包:find_package(catkin REQUIRED COMPONENTS ..+ 依赖项功能包),大约在第10行,添加actionlibactionlib_msgs两项:
# /catkin_ws/src/action_communication/CMakeLists.txt
find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgsactionlibactionlib_msgs
)
    1. 添加自定义action文件:add_action_files(FILES 文件名),大约在第66行,如此时的文件名为DoDishes.action
# /catkin_ws/src/action_communication/CMakeLists.txt
add_action_files(FILESDoDishes.action
)
    1. 添加action的编译依赖项std_msgsactionlib_msgs:generate_messages(DEPENDENCIES 依赖项名),大约在第71行,即表示在编译msg时候得依赖于std_msgs
# /catkin_ws/src/action_communication/CMakeLists.txt
generate_messages(DEPENDENCIESstd_msgsactionlib_msgs
)
    1. 添加执行时的依赖:catkin_package的关键字CATKIN_DEPENDS后+包,大约在106行,添加actionlib和actionlib_msgs如:
# /catkin_ws/src/action_communication/CMakeLists.txt
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES action_communicationCATKIN_DEPENDS roscpp rospy std_msgs actionlib actionlib_msgs
#  DEPENDS system_lib
)

(四)编译action文件,查看中间文件:

  1. 在工作空间下编译,此时在工作空间的devel目录会多出几个文件,如C++的中间文件在/home/ubuntu/catkin_ws/devel/include/功能包名/文件夹下,Python的中间文件在/home/ubuntu/catkin_ws/devel/lib/python2.7/dist-packages/功能包名/msg

3.2.2.3 C++实现action基本编程

(五)C++实现action基本编程:

  1. 实现动作服务器
    1. 首先在工作空间的根目录的src文件夹里创建服务程序DoDishes_server_cpp.cpp
# catkin_ws/src/action_communication/src/DoDishes_server_cpp.cpp
#include 
#include 
#include "action_communication/DoDishesAction.h"typedef actionlib::SimpleActionServer Server;// 收到action的goal后调用该回调函数
void callback(const action_communication::DoDishesGoalConstPtr& goal, Server* server)
{ros::Rate r(1);action_communication::DoDishesFeedback feedback;ROS_INFO("收到客户端的goal,洗碗工 %d 开始洗盘子.", goal->dishwasher_id);// 假设洗盘子的进度,并且按照1hz的频率发布进度feedbackfor(int i=1; i<=10; i++){feedback.percent_complete = i * 10;server->publishFeedback(feedback);ROS_INFO("feedback ing ...");r.sleep();}// 当action完成后,向客户端返回结果ROS_INFO("洗碗工完成了工作,发送result(100个)给客户端.");action_communication::DoDishesResult res;res.total_dishes_cleaned = 100;server->setSucceeded(res);
}int main(int argc, char** argv)
{setlocale(LC_ALL,"");ros::init(argc, argv, "do_dishes_server");ros::NodeHandle nh;// 定义一个服务器Server server(nh, "do_dishes", boost::bind(&callback, _1, &server), false);// 服务器开始运行ROS_INFO("action服务端启动,等待指令");server.start();ros::spin();return 0;
}
    1. 创建客户端文件DoDishes_client_cpp.cpp
# catkin_ws/src/l_t/src/DoDishes_client_cpp.cpp
#include 
#include "action_communication/DoDishesAction.h"typedef actionlib::SimpleActionClient Client;// 当action完成后会调用该回调函数一次
void doneCb(const actionlib::SimpleClientGoalState& state,const action_communication::DoDishesResultConstPtr& result){ROS_INFO("result:洗碗工把盘子已经洗完啦!洗了%d个",result->total_dishes_cleaned);ros::shutdown();
}// 当action激活后会调用该回调函数一次
void activeCb(){ROS_INFO("服务器已经打开,可以执行任务");
}// 收到feedback后调用该回调函数
void feedbackCb(const action_communication::DoDishesFeedbackConstPtr& feedback)
{ROS_INFO("feedback:洗盘子的进度:%f", feedback->percent_complete);
}int main(int argc, char** argv)
{setlocale(LC_ALL,"");ros::init(argc, argv, "do_dishes_client");// 定义一个客户端Client client("do_dishes", true);// 等待服务器端client.waitForServer();ROS_INFO("goal:选择员工1洗盘子:");// 创建一个action的goalaction_communication::DoDishesGoal goal;goal.dishwasher_id = 1;// 发送action的goal给服务器端,并且设置回调函数client.sendGoal(goal,  &doneCb, &activeCb, &feedbackCb);ros::spin();return 0;
}
    1. 配置动作的服务端和客户端代码的编译选项。在功能包的目录下,打开其CMakeLists.txt文件。
# catkin_ws/src/action_communication/CMakeLists.txt
add_executable(dodisher_server_cpp src/DoDishes_server_cpp.cpp)
add_executable(dodisher_client_cpp src/DoDishes_client_cpp.cpp)add_dependencies(dodisher_server_cpp ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(dodisher_client_cpp ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})target_link_libraries(dodisher_server_cpp ${catkin_LIBRARIES})
target_link_libraries(dodisher_client_cpp ${catkin_LIBRARIES})
    1. 在工作空间的根目录下进行编译操作。
    1. 运行服务编程。首先打开一个终端输入roscore,打开ROS,再新建一个终端输入rosrun action_communication DoDishes_server运行服务程序。最后新建终端输入rosrun action_communication DoDishes_client即运行客户端并执行动作操作。

在这里插入图片描述

3.2.2.4 Python实现action基本编程\

(六)Python实现action基本编程:

  1. 在scripts文件夹创建Python服务端文件
    1. DoDishes_server_py.py,代码见注释

#!/usr/bin/env python
# -*- coding: utf-8 -*-# catkin_ws/src/action_communication/scripts/DoDishes_server_py.pyimport rospy
import actionlib
from action_communication.msg import *class myActionServer:def __init__(self):# 1.创建服务器,执行服务器回调函数self.server = actionlib.SimpleActionServer("dodishes", DoDishesAction, self.serverCb, False)self.server.start()rospy.loginfo("服务端启动")def serverCb(self,goal):id = goal.dishwasher_idrospy.loginfo("收到来自客户端的goal,洗碗工 %d 开始工作",id)rate = rospy.Rate(1)for i in range(1, 10):rospy.loginfo("feedback ing...")feedBack_obj = DoDishesFeedback()feedBack_obj.percent_complete = iself.server.publish_feedback(feedBack_obj)rate.sleep()res = DoDishesResult()res.total_dishes_cleaned = 100rospy.loginfo("洗碗工完成了工作,发送result(100个)给客户端.")self.server.set_succeeded(res)if __name__ == "__main__":rospy.init_node("action_server_py")server = myActionServer()rospy.spin()
    1. 编写客户端DoDishes_client_py.py文件
#!/usr/bin/env python
# -*- coding: utf-8 -*-# catkin_ws/src/action_communication/scripts/DoDishes_client_py.pyimport rospy
import actionlib
from action_communication.msg import *def result_cb(state,result):if state == actionlib.GoalStatus.SUCCEEDED:rospy.loginfo("result:洗碗工把盘子已经洗完啦!洗了%d个",result.total_dishes_cleaned)def active_cb():rospy.loginfo("服务被激活....")def feedback_cb(f):rospy.loginfo("当前进度:%.2f",f.percent_complete)if __name__ == "__main__":# 2.初始化 ROS 节点rospy.init_node("action_client_py")# 3.创建 action Client 对象client = actionlib.SimpleActionClient("dodishes",DoDishesAction)# 4.等待服务client.wait_for_server()# 5.组织目标对象并发送goal_obj = DoDishesGoal()goal_obj.dishwasher_id = 1rospy.loginfo("goal:选择员工1洗盘子:")client.send_goal(goal_obj,result_cb,active_cb,feedback_cb)# 6.编写回调, 激活、连续反馈、最终响应# 7.spinrospy.spin()
    1. 给Python文件赋予可执行权限,在script文件夹下输入命令sudo chmod +x *.py即可赋予所有Python可执行权限。
    1. 运行py文件

在这里插入图片描述

3.2.3 动作编程总结

3.2.3.1 动作编程的顺序流程

  1. 动作编程的顺序流程:
    1. 在action文件夹编写自定义action文件,配置package.xml文件包括actionlib和actionlib_msg,分别包括四项;
    1. 配置CMakeList.txt文件包括
      1. 添加编译依赖项功能包find_package
      1. 添加自定义action文件add_action_files
      1. 添加action的编译依赖项generate_messages里添加std_msgs和actionlib_msgs
      1. 添加执行时的依赖catkin_package里添加actionlib actionlib_msgs
    1. C++代码:
      1. 添加头文件(头文件为功能包名字/自定义动作.h)
      1. 正常编写代码;
      1. CMakeList.txt进行配置(不仅有add_executable和target_link_libraries还包括add_dependencies);
      1. 编译运行;
    1. Python代码:
      1. 添加包from 功能包名.msg import *
      1. 正常代码编写;②CMakeList.txt进行配置(目前配置不配置影响不大);
      1. 赋予py文件可执行权限
      1. 编译运行。

3.2.3.2 动作编程逻辑

  1. 编程逻辑顺序:

在这里插入图片描述

3.2.4 参考

  • ROS-WIKI:actionlib package summary(DoDishes)
  • 高级action教程-ROS-WIKI:cn/actionlib_tutorials/Tutorials
  • B站视频:【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程

相关内容

热门资讯

【MySQL】锁 锁 文章目录锁全局锁表级锁表锁元数据锁(MDL)意向锁AUTO-INC锁...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
GCN的几种模型复现笔记 引言 本篇笔记紧接上文,主要是上一篇看写了快2w字,再去接入代码感觉有点...
数据分页展示逻辑 import java.util.Arrays;import java.util.List;impo...
Redis为什么选择单线程?R... 目录专栏导读一、Redis版本迭代二、Redis4.0之前为什么一直采用单线程?三、R...
【已解决】ERROR: Cou... 正确指令: pip install pyyaml
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
Lock 接口解读 前置知识点Synchronized synchronized 是 Java 中的关键字,...
Win7 专业版安装中文包、汉... 参考资料:http://www.metsky.com/archives/350.htm...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
大模型未来趋势 大模型是人工智能领域的重要发展趋势之一,未来有着广阔的应用前景和发展空间。以下是大模型未来的趋势和展...
python实战应用讲解-【n... 目录 如何在Python中计算残余的平方和 方法1:使用其Base公式 方法2:使用statsmod...
学习u-boot 需要了解的m... 一、常用函数 1. origin 函数 origin 函数的返回值就是变量来源。使用格式如下...
常用python爬虫库介绍与简... 通用 urllib -网络库(stdlib)。 requests -网络库。 grab – 网络库&...
药品批准文号查询|药融云-中国... 药品批文是国家食品药品监督管理局(NMPA)对药品的审评和批准的证明文件...
【2023-03-22】SRS... 【2023-03-22】SRS推流搭配FFmpeg实现目标检测 说明: 外侧测试使用SRS播放器测...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
初级算法-哈希表 主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-哈希表...
进程间通信【Linux】 1. 进程间通信 1.1 什么是进程间通信 在 Linux 系统中,进程间通信...
【Docker】P3 Dock... Docker数据卷、宿主机与挂载数据卷的概念及作用挂载宿主机配置数据卷挂载操作示例一个容器挂载多个目...