- 其他ROS1学习笔记: ROS1学习笔记
- 代码仓库:Github连接地址
- 欢迎各位互相学习交流
VS Code的下载链接:VS Code 官网连接;历史版本下载链接:VS Code历史版本,选择合适的版本,对于Linux系统下载deb文件双击运行,或者输入命令sudo dpkg -i vscode安装包名.deb即可。
cd catkin_ws
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"}}]
}
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
}
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"
}
Crtl+Shift+B
,点击之后选择catkin_make: build_by_vscode
(在task.json的label名字)即可编译整个工作空间。在catkin_ws/src/
目录下右键create catkin package
创建包,然后按照提示命名如test
,然后输入依赖项roscpp rospy std_msgs
等
在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;
}
add_executable(${PROJECT_NAME}_node src/test_node.cpp)
的注释,修改为 add_executable(i_am_nodename src/test_c.cpp)
target_link_libraries(${PROJECT_NAME}_node…)
修改为 target_link_libraries(i_am_nodename…)
即可roscore
,新建终端输入rosrun test i_am_nodename
即可查看INFO的消息)。catkin_ws/src/test/
文件夹下创建Python文件夹scripts
,在scripts
文件夹里新建Python文件test_p.py
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的连接。
在任何ROS的大型系统中,如果向节点发送请求以执行某些任务,最后收到对请求的回复,这一操作主要是通过ROS的服务编程实现,但是如果服务需要很长时间来执行,用户可能希望能够在执行期间取消请求或获得有关请求进展情况的定期反馈,基本的服务编程的应答模式是满足不了的,因此ROS提供actionlib
即动作编程完成这些操作。
动作编程的作用:针对服务编程的应答模式的提升,在服务端执行过程中能够取消或者获得服务器状态,动作编程一般适用于耗时的请求响应场景,用以获取连续的状态反馈。
动作编程的例子:如巡检机器人导航过程中,从A到B的导航过程,应该是一个动作编程,即目标是B,在A到B时,提供导航状态。
在动作编程中,客户端发送目标(goal)或者取消指令(cancel)给服务端,服务端提供状态(status)、实时反馈(feedback)和结果(result)。
官方以移动机器人为例解释goal、feedback和result,即
动作编程的基本思想和自定义的消息话题编程是一致的。
动作编程内容:洗盘子动作编程,两个节点,一个为客户端一个为服务端,客户端发送数字1(代码实现)给给服务端,作为选择哪个洗碗工,服务端接收到之后持续反馈进度给客户端,最后发送数字100(代码实现)作为结果返回。
(一)使用VS Code新建功能包:
catkin_ws
下输入命令code .
打开VS Code,打开后如果出现提示Select a kit for catkin_ws
,则选择第一项Scan for kit
即可。create catkin package
然后在VS Code的提示下输入包名action_communication
,回车之后输入依赖项roscpp rospy std_msgs
即可action
文件夹和scripts
文件夹。(二)定义action动作文件:
# 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文件
// /catkin_ws/src/action_communication/package.xmlactionlib actionlib_msgs actionlib actionlib_msgs
find_package(catkin REQUIRED COMPONENTS ..+ 依赖项功能包)
,大约在第10行,添加actionlib
和actionlib_msgs
两项:# /catkin_ws/src/action_communication/CMakeLists.txt
find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgsactionlibactionlib_msgs
)
add_action_files(FILES 文件名)
,大约在第66行,如此时的文件名为DoDishes.action
:# /catkin_ws/src/action_communication/CMakeLists.txt
add_action_files(FILESDoDishes.action
)
std_msgs
和actionlib_msgs:generate_messages(DEPENDENCIES 依赖项名)
,大约在第71行,即表示在编译msg时候得依赖于std_msgs
:# /catkin_ws/src/action_communication/CMakeLists.txt
generate_messages(DEPENDENCIESstd_msgsactionlib_msgs
)
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文件,查看中间文件:
/home/ubuntu/catkin_ws/devel/include/功能包名/文件夹下
,Python的中间文件在/home/ubuntu/catkin_ws/devel/lib/python2.7/dist-packages/功能包名/msg
(五)C++实现action基本编程:
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;
}
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;
}
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})
rosrun action_communication DoDishes_server
运行服务程序。最后新建终端输入rosrun action_communication DoDishes_client
即运行客户端并执行动作操作。(六)Python实现action基本编程:
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()
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()
和
四项;find_package
;add_action_files
;generate_messages里添加std_msgs和actionlib_msgs
;catkin_package里添加actionlib actionlib_msgs
;add_executable和target_link_libraries还包括add_dependencies
);from 功能包名.msg import *
;