ROS2服务通讯基础
- 3.1 服务通讯介绍
- 3.2 ROS2服务通讯的基本流程
- 3.2.1 创建ROS2服务通讯功能包的基本流程
- 3.2.2 创建ROS2服务通讯功能包示例
- 3.3 使用C/C++实现ROS2服务通讯
- 3.3.1 创建C/C++服务通讯服务端功能包并编写节点文件
- 3.3.2 配置C/C++服务通讯服务端功能包
- 3.3.3 编译并运行C/C++服务通讯服务端
- 3.3.4 创建C/C++服务通讯客户端功能包并编写节点文件
- 3.3.5 编译并运行C/C++服务通讯客户端节点
- 3.4 使用Python实现ROS2服务通讯
- 3.4.1 创建Python服务通讯服务端功能包并编写节点文件
- 3.4.2 配置Python服务通讯服务端功能包
- 3.4.3 编译并运行Python服务通讯服务端功能包
- 3.3.4 创建Python服务通讯客户端功能包并编写节点文件
- 3.4.5 编译并运行Python服务通讯客户端节点
- 3.5 服务通讯小结
- 其他ROS2学习笔记: ROS2学习笔记
- 代码仓库:Github连接地址
- 欢迎各位互相学习交流
3.1 服务通讯介绍
参考内容
Understanding services
服务通讯是ROS2的一种基于请求响应式的通讯方式,与之前的话题通讯不同的是服务通讯不是连续的数据流式的通讯,而是需要特定的触发才能收到回复的模式。
服务通讯可以是单个服务端和和单个客户端直接的通讯,一对一的模式
服务通讯也可以是单个服务端和多个客户端通讯,一对多的模式
3.2 ROS2服务通讯的基本流程
事实上,服务通讯和自定义的话题通讯的操作过程很类似,即将所需要利用到服务模块利用ament_camke
工具编译成.c
和.py
的ROS2功能包,然后新建的功能包依赖这个服务功能包完成通讯。
3.2.1 创建ROS2服务通讯功能包的基本流程
-
- 创建ROS2功能包,功能包可以只用来作为存放自定义的
msg/srv/action
,不需要节点node的功能包,且--build-type
必须是ament_camke
,因为目前来看,Python的自定义的消息或者服务也需要通过cmake编译出来再调用,功能包必须是下划线的推荐命名方法,而不是大小写的驼峰,否则会报错,如下所示:
- 创建ROS2功能包,功能包可以只用来作为存放自定义的
rosidl_adapter.parser.InvalidResourceName: 'xxxxx' is an invalid
package name. It should have the pattern
'^(?!.*__)(?!.*_$)[a-z][a-z0-9_]*$'
-
- 在ROS2功能包内创建
srv
文件夹,里面存放自定义的.srv
消息文件,并且.srv
文件必须是大写开头的符合类的命名规则
- 在ROS2功能包内创建
-
- 配置
packages.xml
文件,都需要配置下面的内容(下面的配置项与.srv
文件无关,是默认的固定配置)
- 配置
<!-- 这一项是针对在srv文件中可能用到的其他依赖项,例如geomtry_msgs等等,如过没有用到就不添加 -->
<depend>其他的depend</depend>
<!-- 下面三项是必须的 -->
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
-
- 配置
CMakeLists.txt
文件,find_package
和rosidl_generate_interfaces
- 配置
# 0. 是针对在srv文件中可能用到的其他依赖项,例如geomtry_msgs等等,则需要添加
# find_package(geometry_msgs REQUIRED)
# 1. rosidl_default_generators是必须添加的内容
find_package(rosidl_default_generators REQUIRED)
# 2. rosidl_generate_interfaces必须配置,里面添加srv文件位置
rosidl_generate_interfaces(${PROJECT_NAME}
# 2.1 添加自定义的srv位置,例如存放在功能包的srv文件夹下的xxx.srv
"srv/xxx.srv"
# 2.2 可选,如果xxx.srv依赖了其他的内容,例如依赖了geometry_msgs
DEPENDENCIES geometry_msgs
)
-
- 编译功能包:
colcon build --packages-select <功能包名>
- 编译功能包:
-
- 此时激活
install
目录下的setup.bash
如. install/setup.bash
,可以通过ros2 interface show <功能包名称>/srv/xxx.srv
查看到xxx.srv
内容,此时编译好的srv
的.c
文件存放在install/<功能包名>/include
下,.py
文件则存放在install/<功能包名>/local/
- 此时激活
3.2.2 创建ROS2服务通讯功能包示例
-
创建自定义消息功能包
srv_demo
,采用ament_cmake
方式:ros2 pkg create srv_demo --build-type ament_cmake
-
在功能包内创建
srv
文件夹,其中存放AddInt.srv
文件,需要利用到---
符号作为分割,文件在---
上面的内容作为请求体的参数,在---
下面的内容作为响应体的参数,文件内容如下:
int32 num1
int32 num2
---
int32 sum
- 此时的功能包内部的目录结构如下:
tree -a
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code/srv_demo$ tree -a
.
├── CMakeLists.txt
├── include
│ └── srv_demo
├── package.xml
├── src
└── srv
└── AddInt.srv
- 配置
packages.xml
添加依赖项,由于AddInt.srv
没有依赖任何的东西因此不需要添加其他的depend
:
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>msg_demo</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="pldz@R7000.com">pldz</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<!-- 构建自定义功能包的的必须依赖项 -->
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
- 配置
CMakeLists.txt
文件,添加构建自定义AddInt.srv
的依赖:
cmake_minimum_required(VERSION 3.8)
project(srv_demo)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)
# 1. 构建自定义功能包必须的依赖
find_package(rosidl_default_generators REQUIRED)
# 2. 配置自定义的srv的位置
rosidl_generate_interfaces(${PROJECT_NAME}
"srv/AddInt.srv"
)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
-
构建功能包:
colcon build --packages-select srv_demo
-
查看自定义的消息:激活环境:
. install/setup.bash
,查看自定义消息ros2 interface show srv_demo/srv/AddInt
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ colcon build --packages-select srv_demo
Starting >>> srv_demo
Finished <<< srv_demo [12.2s]
Summary: 1 package finished [12.5s]
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ . install/setup.bash
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ ros2 interface show srv_demo/srv/AddInt
int32 num1
int32 num2
---
int32 sum
- 查看
instll
下面的文件:其中.c
的class文件在install/<功能包名>/include/<功能包名>/<功能包名>/msg/**
,.py
在install/<功能包名>/local/lib/python3.10/dist-packages/<功能包名>/msg/**
,后续Vscode可以通过配置settings.json
添加提示
3.3 使用C/C++实现ROS2服务通讯
这里直接使用3.2.2创建的srv_demo服务功能包进行ROS2 C/C++的服务通讯的实现
参考内容:
Writing a simple service and client (C++)
2.3.3_服务通信_C++实现_01框架搭建
ROS2探索(三)service
3.3.1 创建C/C++服务通讯服务端功能包并编写节点文件
-
创建功能包,其中功能包名称为
cpp_srv_server
,节点名为cppSrvServerNode
:ros2 pkg create cpp_srv_server --build-type ament_cmake --node-name cppSrvServerNode
-
配置Vscode环境,在工作空间创建
.vscode
文件夹,并加入settings.json
文件,添加ROS2
的include
环境和当前工作空间的install
文件夹下的srv_demo
功能包的include
路径:
{
"C_Cpp.default.includePath": [
"/opt/ros/humble/include/**",
"./install/srv_demo/include/**"
],
}
- 编写服务端节点文件,主要包括导入包,创建服务节点,实现回调函数:
// 1. 调用自定义的服务文件
// 1.1 rclcpp和srv_demo两个功能包的头文件
// 如果有vscode的下划线提示,说明是settings.json没有配置好
#include "rclcpp/rclcpp.hpp"
#include "srv_demo/srv/add_int.hpp"
// 1.2. 调用功能包下的自定义的服务,其中自定义的服务名已经变成了一个类名
using srv_demo::srv::AddInt;
// std_bind的占位符
using std::placeholders::_1;
using std::placeholders::_2;
// 2.定义节点类;
class CppSrvServer: public rclcpp::Node{
public:
// 2.1 构造函数,其中节点名直接赋予cppSrvServerNode
CppSrvServer():Node("cppSrvServerNode"){
// 2.2 创建服务端
server_ = this->create_service<AddInt>("mySrvName",std::bind(&CppSrvServer::addIntFunc, this, _1, _2));
RCLCPP_INFO(this->get_logger(),"Server is starting ...");
}
private:
// 3. 服务端的回调函数实现,其中参数的写法区分主要在于类型,参数数量包括请求体req和响应体rsp
void addIntFunc(const AddInt::Request::SharedPtr req, const AddInt::Response::SharedPtr rsp)
{
rsp->sum = req->num1 + req->num2;
RCLCPP_INFO(this->get_logger(),"request body :(%d,%d), response is :%d", req->num1, req->num2, rsp->sum);
}
// 4 服务的声明
rclcpp::Service<AddInt>::SharedPtr server_;
};
int main(int argc, char const *argv[])
{
rclcpp::init(argc,argv);
auto server_ = std::make_shared<CppSrvServer>();
rclcpp::spin(server_);
rclcpp::shutdown();
return 0;
}
3.3.2 配置C/C++服务通讯服务端功能包
- 配置
packages.xml
文件,添加依赖项有rclcpp
用于构建节点,和srv_demo
用于构建AddInt
:
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>cpp_srv_server</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="pldz@R7000.com">pldz</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<!-- 依赖rclcpp创建节点和自定义的服务功能包 -->
<depend>rclcpp</depend>
<depend>srv_demo</depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
- 配置
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.8)
project(cpp_srv_server)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)
# 1. 列出依赖项的包
find_package(rclcpp REQUIRED)
find_package(srv_demo REQUIRED)
# 2. 默认是已经创建了构建节点的文件配置
add_executable(cppSrvServerNode src/cppSrvServerNode.cpp)
# 3. 默认已经包括<INSTALL_INTERFACE>的路径也不用更改
target_include_directories(cppSrvServerNode PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_compile_features(cppSrvServerNode PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17
# 4. ament工具构建节点的依赖配置
ament_target_dependencies(
cppSrvServerNode
rclcpp
srv_demo
)
# 5. Install配置,默认ros2 run <包名>的配置
install(TARGETS cppSrvServerNode
DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
# 6. 生成包的环境
ament_package()
3.3.3 编译并运行C/C++服务通讯服务端
-
编译:
colcon build --packages-select cpp_srv_server
-
激活环境:
. install/setup.bash
-
运行:
ros2 run cpp_srv_server cppSrvServerNode
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ colcon build --packages-select cpp_srv_server
Starting >>> cpp_srv_server
Finished <<< cpp_srv_server [20.6s]
Summary: 1 package finished [21.0s]
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ . install/setup.bash
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ ros2 run cpp_srv_server cppSrvServerNode
[INFO] [1683125184.734934447] [cppSrvServerNode]: Server is starting ...
^C[INFO] [1683125186.240946812] [rclcpp]: signal_handler(signum=2)
3.3.4 创建C/C++服务通讯客户端功能包并编写节点文件
-
创建功能包,功能包名为
cpp_srv_client
,节点名称为cppSrvClientNode
,依赖rclcpp
和srv_demo
:ros2 pkg create cpp_srv_client --build-type ament_cmake --node-name cppSrvClientNode --dependencies rclcpp srv_demo
-
编写客户端节点,注意在此过程中需要和 服务端的连接进行判断,以及发送的请求是否能够收到返回值的用法的操作:
// 1. 调用自定义的服务文件
// 1.1 rclcpp和srv_demo两个功能包的头文件
#include "rclcpp/rclcpp.hpp"
#include "srv_demo/srv/add_int.hpp"
// 1.2. 调用功能包下的自定义的服务,其中自定义的服务名已经变成了一个类名
using srv_demo::srv::AddInt;
// 时间函数用于持续访问服务端
using namespace std::chrono_literals;
// 2.定义节点类;
class CppSrvClient: public rclcpp::Node{
public:
CppSrvClient():Node("cppSrvClientNode")
{
// 2.1 创建客户端,并绑定服务通讯名称为mySrvName
client_ = this->create_client<AddInt>("mySrvName");
RCLCPP_INFO(this->get_logger(),"Client is starting ...");
}
// 2.2 等待与服务的连接
bool connect_server(){
while (!client_->wait_for_service(1s))
{
if (!rclcpp::ok())
{
RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Interrupted while waiting for the service. Exiting.");
return false;
}
RCLCPP_INFO(this->get_logger(),"service not available, waiting again...");
}
return true;
}
// 2.3 客户端发送请求;
rclcpp::Client<srv_demo::srv::AddInt>::FutureAndRequestId send_request(int32_t num1, int32_t num2)
{
auto request = std::make_shared<AddInt::Request>();
request->num1 = num1;
request->num2 = num2;
// 2.3.1 发送请求
auto response = client_->async_send_request(request);
return response;
}
private:
// 2.4 服务通讯客户端的声明
rclcpp::Client<AddInt>::SharedPtr client_;
};
int main(int argc, char ** argv)
{
// 3. 初始化ROS2客户端
rclcpp::init(argc,argv);
// 3.1 创建对象指针并调用其功能;
auto cppSrvClientNode = std::make_shared<CppSrvClient>();
// 3.2 连接客户端
bool flag = cppSrvClientNode->connect_server();
if (!flag)
{
RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Connect failed! ");
return 0;
}
// 3.3 发送请求并等待响应
auto response = cppSrvClientNode->send_request(100,200);
// 3.4 节点处理响应
if (rclcpp::spin_until_future_complete(cppSrvClientNode,response) == rclcpp::FutureReturnCode::SUCCESS)
{
RCLCPP_INFO(cppSrvClientNode->get_logger(),"The response is :%d!", response.get()->sum);
} else {
RCLCPP_INFO(cppSrvClientNode->get_logger(),"Request error");
}
rclcpp::shutdown();
return 0;
}
3.3.5 编译并运行C/C++服务通讯客户端节点
-
由于在创建包的过程中已经指明了所有依赖项,不需要进行额外的配置,直接编译运行即可:
colcon build --packages-select cpp_srv_client
-
激活环境并运行节点
3.4 使用Python实现ROS2服务通讯
参考内容
Writing a simple service and client (Python)
2.3.4_服务通信_Python实现_01框架搭建
3.4.1 创建Python服务通讯服务端功能包并编写节点文件
-
创建功能包,包名为
python_srv_server
,节点名为pythonSrvServerNode
:ros2 pkg create python_srv_server --build-type ament_python --node-name pythonSrvServerNode
-
配置Vscode,主要添加功能包的提示环境,编辑
settings.json
:
{
"C_Cpp.default.includePath": [
"/opt/ros/humble/include/**",
"./install/srv_demo/include/**"
],
"python.analysis.include": [
"/opt/ros/humble/local/lib/python3.10/dist-packages/**",
"./install/srv_demo/local/lib/python3.10/dist-packages/**"
]
}
- 编写Python服务端节点文件:
import rclpy
from rclpy.node import Node
# 1. 导入包,其中的类名等于服务文件名称
from srv_demo.srv import AddInt
# 2. 定义服务端节点
class PythonSrvServer(Node):
def __init__(self):
super().__init__('pythonSrvServerNode')
# 2.1 创建服务端
self.srver_ = self.create_service(AddInt, 'mySrvName', self.addIntFunc)
self.get_logger().info("Server is starting ...")
# 2.2 服务端的处理回调函数
def addIntFunc(self, request:AddInt, response:AddInt):
response.sum = request.num1 + request.num2
self.get_logger().info('The request is :{} {},Response is :{}'.format(request.num1, request.num2, response.sum))
return response
def main():
rclpy.init()
pythonSrvServerNode = PythonSrvServer()
rclpy.spin(pythonSrvServerNode)
rclpy.shutdown()
if __name__ == '__main__':
main()
3.4.2 配置Python服务通讯服务端功能包
- 配置
packages.xml
增加rclpy
和srv_demo
两个依赖项,注意Python本身是可执行文件,因此它的为<exec_depend>
与C/C++
的<depend>
关键字不同:
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>python_srv_server</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="pldz@R7000.com">pldz</maintainer>
<license>TODO: License declaration</license>
<!-- 添加依赖项的包,注意是exec_depend -->
<exec_depend>rclpy</exec_depend>
<exec_depend>srv_demo</exec_depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
- 配置
setup.py
文件,事实上,我们已经创建包的时候已经指定了节点名,其实应该是不用配置生成节点的main
入口的:
from setuptools import setup
package_name = 'python_srv_server'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='pldz',
maintainer_email='pldz@R7000.com',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
# 配置节点main函数入口
entry_points={
'console_scripts': [
'pythonSrvServerNode = python_srv_server.pythonSrvServerNode:main'
],
},
)
3.4.3 编译并运行Python服务通讯服务端功能包
-
编译:
colcon build --packages-select python_srv_server
-
激活环境:
. install/setup.bash
-
运行节点:
ros2 run python_srv_server pythonSrvServerNode
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ colcon build --packages-select python_srv_server
Starting >>> python_srv_server
--- stderr: python_srv_server
/usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
warnings.warn(
---
Finished <<< python_srv_server [2.18s]
Summary: 1 package finished [2.71s]
1 package had stderr output: python_srv_server
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ . install/setup.bash
pldz@pldz-pc:~/share/ROS2_DEMO/3_Chapter/code$ ros2 run python_srv_server pythonSrvServerNode
[INFO] [1683157866.794236460] [pythonSrvServerNode]: Server is starting ...
3.3.4 创建Python服务通讯客户端功能包并编写节点文件
-
创建Python功能包时,包名为
python_srv_client
,节点名为pythonSrvClientNode
,直接指定依赖项rclpy
和srv_demo
:ros2 pkg create python_srv_client --build-type ament_python --node-name pythonSrvClientNode --dependencies rclpy srv_demo
-
编写节点:主要是统一节点的订阅话题,异步接收返回的结果
import sys
import rclpy
from rclpy.node import Node
# 1. 导入包
from srv_demo.srv import AddInt
# 2.定义客户端节点
class pythonSrvClient(Node):
def __init__(self):
# 2.1 继承node节点,节点名为pythonSrvClientNode
super().__init__('pythonSrvClientNode')
# 2.2 创建客户端
self.client_ = self.create_client(AddInt, 'mySrvName')
# 2.3 等待连接
self.wait_for_connect()
# 3. 实现等待函数
def wait_for_connect(self):
while not self.client_.wait_for_service(timeout_sec=1.0):
self.get_logger().info('Waiting for connect ...')
# 4. 实现发送请求函数
def send_request(self, num1, num2):
request = AddInt.Request()
request.num1 = num1
request.num2 = num2
self.future = self.client_.call_async(request)
def main():
rclpy.init()
# 5.创建客户端节点
pythonSrvClientNode = pythonSrvClient()
pythonSrvClientNode.send_request(200,300)
# 6. 等待响应
rclpy.spin_until_future_complete(pythonSrvClientNode,pythonSrvClientNode.future)
try:
response = pythonSrvClientNode.future.result()
except Exception as e:
pythonSrvClientNode.get_logger().info('Request error {}'.format(e))
else:
pythonSrvClientNode.get_logger().info(
'Response is {}'.format(response.sum))
rclpy.shutdown()
if __name__ == '__main__':
main()
3.4.5 编译并运行Python服务通讯客户端节点
-
由于指定了依赖项,直接编译即可:
colcon build --packages-select python_srv_client
-
激活环境:
. install/setup.bash
-
运行所有节点:
3.5 服务通讯小结
-
- 创建功能包时,如果能够直接指定节点名和依赖项,可以省去很大部分的配置工作
-
- C/C++手动配置功能包时,
packages.xml
配置依赖项,CMakeLists.txt
配置编译的内容,包括find_package
;add_executable
;target_include_directories
;ament_target_dependencies
;install
;ament_package
这六个部分
- C/C++手动配置功能包时,
-
- Python手动配置功能包时,
packages.xml
配置可执行的依赖项exec_depend
而不是depend
,并且在setup.py
中主要配置节点的main
函数入口
- Python手动配置功能包时,
-
- 服务通讯的导入本质是创建一个C/C++的功能包,将里面的自定义消息编译成可以使用的
.c
和.py
文件,值得注意的是,生成好的中间文件是存放在 工作空间的install
文件夹下,如果这个这个工作空间的install
找不到或者不是一个,那是需要再进一步的手动配置的
- 服务通讯的导入本质是创建一个C/C++的功能包,将里面的自定义消息编译成可以使用的
-
- 服务通讯的请求响应是这里是异步实现的,即客户端需要等待服务端返回的结果,才能判断是否完成接收