ROS教程4 ROS自定义srv类型及使用
創(chuàng)建srv文件
在上一節(jié)單獨(dú)為自定義的消息和服務(wù)的包 test_msgs 里面
創(chuàng)建 srv文件夾
進(jìn)入創(chuàng)建 testsrv.srv 文件 ,內(nèi)容為;
(srv文件和msg文件類似,唯一不同的是它包含兩個(gè)部分——request和response。兩部分用---分隔:)
int64 A int64 B --- int64 Sum
(1)打開(kāi)test_msgs 包里的package.xml文件,確保里面存在這兩行且去掉它們的注釋:(上節(jié)已做過(guò))
<build_depend>message_generation</build_depend> <run_depend>message_runtime</run_depend>
(2)打開(kāi)包目錄下的CMakeLists.txt文件,在find_message調(diào)用中添加message_generation依賴,讓你可以生成ROS信息。(上節(jié)已經(jīng)做過(guò))
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation )
(3) 添加srv文件
去掉注釋且修改為:
add_service_files( FILES testsrv.srv )
(4)然后是generate_messages,指定生成消息文件時(shí)的依賴項(xiàng),比如上面嵌套了其他消息類型geometry_msgs,那么必須注明
#generate_messages必須在catkin_package前面 generate_messages( DEPENDENCIES geometry_msgs )
(4)然后是catkin_package設(shè)置運(yùn)行依賴
catkin_package( CATKIN_DEPENDS message_runtime )
編譯
回到test_msgs文件夾下
catkin_make
查看是否成功
rossrv show test_msgs/testsrv
使用自定義的srv (testsrv.srv)
要使用自定義的消息類型必須source自定義消息所在的工作空間,否則rosmsg show test_msgs/testsrv和rostopic echo /test_msg(/test_msg是節(jié)點(diǎn)中使用自定義消息類型test_msgs/Test的topic)都會(huì)報(bào)錯(cuò),因?yàn)闆](méi)有source的情況下自定義消息類型是不可見(jiàn)的,被認(rèn)為是未定義類型
1 調(diào)用自定義srv類型
(1)如果是在test_msgs包內(nèi)的節(jié)點(diǎn)中調(diào)用test_msgs/testsrv類型,只需要在.cpp文件中如下調(diào)用即可
#include <test_msgs/testsrv.h> test_msgs::testsrv mysrv;
( 2 ) 如果是在其他包調(diào)用test_msgs/testsrv類型則還需要修改package.xml和CMakeLists.txt,
比如同樣在工作空間catkin_arduino_ros內(nèi)有一個(gè)名為test1_pub_sub包,在它的src文件夾下,有兩個(gè)節(jié)點(diǎn)add_two_ints_client和add_two_ints_server,
調(diào)用test_msgs包下面的srv文件夾中的自定義的srv類型testsrv.srv,完成一個(gè)請(qǐng)求加法的服務(wù)。
add_two_ints_client.cpp
#include "ros/ros.h"
#include <test_msgs/testsrv.h>
#include <cstdlib>
int main(int argc, char **argv)
{
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;
ros::ServiceClient client = n.serviceClient<test_msgs::testsrv>("add_two_ints");
test_msgs::testsrv srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
if (client.call(srv))
{
ROS_INFO("Sum: %ld", (long int)srv.response.sum);
}
else
{
ROS_ERROR("Failed to call service add_two_ints");
return 1;
}
return 0;
}
add_two_ints_server.cpp
#include "ros/ros.h"
#include <test_msgs/testsrv.h>
bool add(test_msgs::testsrv::Request &req,
test_msgs::testsrv::Response &res)
{
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.sum);
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_server");
ros::NodeHandle n;
ros::ServiceServer service = n.advertiseService("add_two_ints", add);
ROS_INFO("Ready to add two ints.");
ros::spin();
return 0;
}
代碼中添加的關(guān)鍵點(diǎn):
1頭文件調(diào)用
#include <test_msgs/testsrv.h>
2 實(shí)例化自定義srv
test_msgs::testsrv srv; (根據(jù)創(chuàng)建的包名test_msgs和文件名testsrv)
3 srv 分兩部分
請(qǐng)求部分
test_msgs::testsrv::Request &req
req.a
req.a
響應(yīng)部分
test_msgs::testsrv::Response &res
res.sum
2為編譯添加依賴項(xiàng)
修改調(diào)用包test1_pub_sub的編譯文件,來(lái)調(diào)用包test_msgs里面的自定義服務(wù) testsrv.srv
(1)修改package.xml (創(chuàng)建msg時(shí)已經(jīng)添加)
<build_depend>roscpp</build_depend> <run_depend>roscpp</run_depend> <build_depend>test_msgs</build_depend> <run_depend>test_msgs</run_depend>
(2)修改CMakeLists.txt:
1 find_package中需要聲明查找包含該消息類型的包test_msgs;
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs geometry_msgs // 上節(jié)自定義的msg中使用 跟srv沒(méi)關(guān)系 test_msgs // 使用自定義testsrv.srv 重點(diǎn)調(diào)用 # message_generation )
2 add_dependencies要注明該消息的依賴 [包名]_gencpp (test_msgs_gencpp)其他地方和普通節(jié)點(diǎn)一樣
add_dependencies(add_two_ints_server test_msgs_gencpp)
add_dependencies(add_two_ints_client test_msgs_gencpp)
如果缺少add_dependencies中對(duì)test_msgs_gencpp的依賴聲明,在編譯的時(shí)候如果先編譯test包再編譯test_msgs包則會(huì)出現(xiàn)如下報(bào)錯(cuò)(ROS工作空間各個(gè)軟件包的編譯順序是隨機(jī)的),因?yàn)轭^文件test_msgs/Test.h還未生成
測(cè)試
roscore
總結(jié)
以上是生活随笔為你收集整理的ROS教程4 ROS自定义srv类型及使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。