两种数据在建立的时候都建议放在一个单独的文件夹内方便管理
msg文件
srv文件
1、定义对应的msg/srv文件
2、在package.xml中添加功能包依赖
//xml配置 位置在位于靠近xml结尾处的一串后
message_generation
message_runtime
3、在CMakeLists.txt添加编译选项
//txt配置
find_package(
...
message_generation
) //位置位于txt文件开头
add_message_files(FILES person.msg)//person.msg是你定义的msg文件的名字,若为srv文件则改成srv文件名即可
generate_messages(DEPENDENCIES std_msgs)
//以上两条代码一同添加,位置在一串被注释掉的generate_messages下方
catkin_package(
...
CATKIN_DEPENDS ... message_runtime
...
)
//该函数内所有内容均被注释,包括CATKIN_DEPENDS,添加message_runtime时需将包括CATKIN_DEPENDS的注释去除,位置在build上方
4、catkin_make重新编译文件
1、设置需要编译的代码和生成的可执行文件
2、设置连接库
3、添加依赖项
add_executable(person_publisher src/person_publisher.cpp)//将person_publisher.cpp文件编译成可执行文件
target_link_libraries(person_publisher ${catkin_LIBRARIES})//设置链接库
add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp)//添加依赖项
//若不使用自定义数据类型,则在编译配置时可省去添加依赖项这一步
//注意, ${catkin_LIBRARIES} ${PROJECT_NAME} 两个均为中括号,不是小括号,打错了编译会失败!!!!
1、初始化ROS节点
2、向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型
3、创建消息数据
4、按照一定频率循环发布消息
#include
#include "test_pkg/person.h"
int main(int argc,char **argv)
{
//ros节点初始化
ros::init(argc,argv,"person_publisher");
//创建节点句柄
ros::NodeHandle n;
//创建一个Publisher,发布名为/person_info的topic,消息类型为test_pkg::person,队列长度10
ros::Publisher person_info_pub=n.advertise("/person_info",10);
//设置循环频率
ros::Rate loop_rate(1);
int count=0;
while (ros::ok())
{
//初始化test_pkg::person类型的消息
test_pkg::person person_msg;
person_msg.name="TOM";
person_msg.age=18;
person_msg.sex=test_pkg::person::male;
//发布消息
person_info_pub.publish(person_msg);
ROS_INFO("Publish Person Info : name:%s age:%d sex:%d",person_msg.name.c_str(),person_msg.age,person_msg.sex);
//按照循环频率计时
loop_rate.sleep();
}
}
1、初始化ROS节点
2、订阅需要的话题
3、循环等待话题消息,接收到消息后进入回调函数
4、在回调函数中完成消息处理
#include
#include "test_pkg/person.h"
//回调函数声明,因为将回调函数放在main之前后编译报错,故将函数实现放在main之后
void personInfoCallbak(const test_pkg::person::ConstPtr& msg);
int main(int argc,char **argv)
{
//初始化ros节点
ros::init(argc,argv,"person_subscriber");
//创建节点句柄
ros::NodeHandle n;
//创建一个subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallbak
ros::Subscriber person_info_sub = n.subscribe("/person_info",10,personInfoCallbak);
//循环等待回调函数
ros::spin();
return 0;
}
void personInfoCallbak(const test_pkg::person::ConstPtr& msg)
{
//打印接收到的消息
ROS_INFO("Subscribe Person Info: name :%s age : %d sex : %d",msg->name.c_str(),msg->age,msg->sex);
}
参照上一部分对Cmakelists进行配置即可
1、初始化ROS节点
2、创建Server实例
3、循环等待服务请求,进入回调函数
4、在回调函数中完成服务功能的处理,并反馈应答数据
#include
#include "learning_service/person.h"
bool personCallback(learning_service::person::Request &req,learning_service::person::Response &res)
{
//显示请求数据
ROS_INFO("Person::name:%s age:%d sex:%d ",req.name.c_str(),req.age,req.sex);
//设置反馈数据
res.result="OK";
return true;
}
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"person_server");
//创建节点句柄
ros::NodeHandle n;
//创建一个名为/show_person的server,注册回调函数personCallback
ros::ServiceServer person_service=n.advertiseService("/show_person",personCallback);
//循环等待回调函数
ROS_INFO("Ready to show person information.");
ros::spin();
return 0;
}
1、初始化ROS节点
2、创建一个Client实例
3、发布服务请求数据
4、等待server处理之后的应答结果
#include
#include "learning_service/person.h"
int main(int argc,char** argv)
{
//初始化ROS节点
ros::init(argc,argv,"person_client");
//创建节点句柄
ros::NodeHandle node;
//发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
ros::service::waitForService("/show_person");
ros::ServiceClient person_client=node.serviceClient("/show_person");
//初始化learning_service::person的请求数据
learning_service::person srv;
srv.request.name="hubery";
srv.request.age=20;
srv.request.sex=learning_service::person::Request::male;
// 请求服务调用
ROS_INFO("Call service to show person[name:%s,age:%d,sex:%d]",srv.request.name.c_str(),srv.request.age,srv.request.sex);
person_client.call(srv);
//显示服务调用结果
ROS_INFO("Show person result :%s",srv.response.result.c_str());
return 0;
}
参照上一部分对Cmakelists进行配置即可
1、当没有提前配好环境变量时,在运行个人功能包时需提前配置环境变量
2、${catkin_LIBRARIES} ${PROJECT_NAME} 两个均为中括号,不是小括号,打错了编译会失败!!!!