在哪里创建,怎么创建,怎么查看创建是否成功
CMakefile该怎么写,为什么要这么写 package要怎么写 遇到了那些问题
程序是怎么写的,遇到了什么问题
在test_ws工作空间中创建一个package --->testsrv 来说明整个创建过程
首先来到:cd test_ws/src
catkin_create_pkg testsrv roscpp rospy std_msgs 创建一个package testsrv,然后创建srv文件夹,并在文件夹中vi Add.srv
创建的Add.srv 内容为:
---上面为request 下面为response。创建完之后,要进行编译,这就需要我们去更改package.xml和CMakeLists.txt,为什么要更改,目的是什么?
更改的package.xml是。。。。。如图所示:
更改的CMakeLists.txt是。。。如图所示:
通过编写CMakeLists.txt,可以控制生成的Makefile,从而控制编译过程。在这里说下CMakeList.txt 里面都有那些东西 :
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.版本
2.project name
3.组建该项目所需要的包 find_package(),举例来讲:构建这个package需要依赖的package,我们使用catkin_make的编译方式,至少需要catkin这个包。另外在创建该功能包时,依赖了roscpp rospy std_msgs,要创建srv/msg/action 就要依赖message_generation,所以最终我们看到:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation ) 要建立srv find_package()必须依赖包message_generation
一个包被被find_package,那么就会导致一些CMake变量的产生,这些变量后面将在CMake的脚本中用到,这些变量描述了所依赖的包输出的头文件、源文件、库文件在哪里。上面这种形式会把所有pacakge里面的头文件和库文件等等目录加到一组变量上。
4.添加的消息,服务 add_message_files(), add_service_files(), add_action_files(),
5.将这些添加的消息、服务(msg .srv .actio)形式的文件转化为系统可以识别特定编程语言(.h .cpp)。当我们需要使用.msg .srv .action形式的文件时,我们需要特殊的预处理器把他们转化为系统可以识别特定编程语言(.h .cpp)。系统会用里面所有的(一些编程语言)生成器(比如 gencpp, genpy, genlisp, etc)生成相应的.cpp .py文件。这就需要三个宏:add_message_files, add_service_files,add_action_files来相应的控制.msg .srv .action。这些宏后面必须跟着一个调用generate_messages()。
这里要对package.xml文件进行配置,build_depend必须包含 message_generation,run_depend必须包含 message_runtime。
6.编译catkin_package(...),这是一个catkin提供的cmake宏,指定构建系统多需要的特定信息,产生配置文件pkg-config,CMake.
catkin_package存在的位置如下:
find_package(catkin REQUIRED COMPONENTS ...)
add_message_files(...)
add_service_files(...)
add_action_files(...)
generate_messages(...)
catkin_package(...)
add_executable(foo src/foo.cpp)//执行
add_dependencies(some_target ${PROJECT_NAME}_generate_messages_cpp)//依赖
target_link_libraries(foo moo)//链接
有几点需要注意的:
1)控制转化的生成器(add_message_files, add_service_files,add_action_files)必须位于catkin_package后面,相当与前面提供构建项目的信息,这里去产生一些配置文件。所以catkin_package()必须位于须在声明add_library()或者 add_executable()生成target前面。
2)宏 catkin_package()中必须有CATKIN_DEPENDS依赖于message_runtime,即:
catkin_package( ... CATKIN_DEPENDS message_runtime ... ...)
7.需要创建一个显式的依赖项
如果你有一个包编译.msg .srv,并且可执行文件要使用他们,那么你就需要创建一个显式的依赖项,自动生成message的target。这样才能按顺序来进行编译:
add_dependencies(some_target ${PROJECT_NAME}_generate_messages_cpp)
这里的some_target是add_executable()设置的target的名字。
该部分内容参照:https://blog.csdn.net/u013243710/article/details/35795841
创建完成之后,使用rossrv查看,如果找不到就去source一下:
到目前位置,srv文件创建成功。
下面开始写程序,使用该服务。编写程序,分别命名为Servnode.cpp 和Clientnode.cpp
phe-E40-70:~/test_ws/src/testsrv/src$ vi Servnode.cpp
phe@phe-E40-70:~/test_ws/src/testsrv/src$ vi Clientnode.cpp
phe@phe-E40-70:~/test_ws/src/testsrv/src$ ls
Clientnode.cpp Servnode.cpp
程序贴在下面:
Servnode.cpp
#include "ros/ros.h"
#include "testsrv/Add.h"//srv编译成功后 会生成.h文件 包名/srvname.h
bool add(testsrv::Add::Request &req, testsrv::Add::Response &res)
{
res.sum = req.a + req.b ;
ROS_INFO("sending service add");
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "service_server");
ros::NodeHandle n;
ros::ServiceServer service = n.advertiseService("service1", add);
ROS_INFO("service Ready!");
ros::spin();
return 0;
}
Clientnode.cpp:
#include"ros/ros.h"
#include"testsrv/Add.h"
#include <cstdlib>
int main(int argc, char **argv)
{
ros::init(argc, argv, "service_client");
ros::NodeHandle n;
ros::ServiceClient client = n.serviceClient<testsrv::Add>("service1");
testsrv::Add srv;
srv.request.a = 1;
srv.request.b = 2;
// srv.response.sum =srv.a+srv.b; 在服务器端做了加的运算 可以知道 srv结构体
//中有一个request 另外一个是response 怎么看结构体类型?
if(client.call(srv))
{
ROS_INFO("service success. result : %d", srv.response.sum);
}
else
{ ROS_INFO("service failed!");
return 1;
}
ROS_INFO("client!");
return 0;
}
更改CMakeList.txt:
phe@phe-E40-70:~/test_ws$ catkin_make 报错的话,就source一下
phe@phe-E40-70:~/test_ws$ source devel/setup.bash
phe@phe-E40-70:~/test_ws$ catkin_make ,贴一张编译成功的图
新开两个终端,分别运行程序: