roscpp ——ros提供给cpp的接口(client library)
用C++语言与ros系统的topic,service,parameter以及timer等做交互的接口
相关调用函数
roscpp主要包括依次对上图的相关函数做解释,其中最重要的是第二部分,NodeHandle
void ros::init(); // 解析node参数,为本node命名
1. ros::NodeHandle Class
NodeHandle其实是c++的一个类
下面介绍该类中常用的成员函数
// 话题的publisher和subscriber,返回值仍然是个类
ros::Publisher advertise(const string &topic, uint32_t queue_size);
ros::Subscriber subscribe(const string &topic, uint32_t queue_size, void(*)(M));
// service的server和client
ros::ServiceServer advertiseServer(const string &service, bool(*srv_func)(Mreq &, Mres &));
ros::ServiceClient serviceClient(const string &service, bool persistent=false);
// 查询参数,与赋值参数
bool getParam(const string &key, void &val);
bool setParam(const string &key, void val);
具体使用方法举例:
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise(...);
2. ros::master Namespace(是一个命名空间)
与类的区别:namespace没有对象,调用他的函数的时候,直接写就可以,不需要创建master对象。例如:
ros::master::check(); // 检查是否启动
---
using namespace ros::master
check();
常用函数如下图:
master常用函数
3. ros::this_node NameSpace(是命名空间)
相关函数4. ros::Service NameSpace(命名空间)
相关函数5. ros::names NameSpace(命名空间)
相关函数以上namespace的相关函数,没必要记住,要求:知道有这样的函数,用的时候回来查找即可!
举例说明
1. topic_demo
功能描述:
两个node,一个发布模拟GPS信息,一个接受并处理该信息
步骤:
- 建立对应包pkg
$ cd ~/catkin_ws/src
$ catkin_create_pkg topic_demo roscpp rospy std_msgs
- 建立对应文件夹msg并添加massage格式文件:*.msg
$ cd topic_demo
$ mkdir msg
$ cd msg
$ vim gps.msg
---
gps.msg
---
float32 x
float32 y
string state
写完的msg文件需要进行catkin_make编译,生成对应路径的.h头文件,然后在代码中include进去
// 对应路径
~/catkin_ws/devel/include/topic_demo/gps.h
// 代码中include方法
#include </topic_demo/gps.h>
topic_demo::gps msg;
- talker.cpp
#include <ros/ros.c>
#include <topic_demo/gps.h> // msg的头文件,生成一个包含msg的类
// main函数规矩,第一个参数是参数个数,第二个参数是具体参数值
int main(int argc, char** argv){
ros::init(argc, argv, "talker"); // 解析参数,命名节点node
ros::NodeHandle nh; // 创建node句柄,实例化node
topic_demo::gps msg;
msg.x = 1.0;
msg.y = 1.0;
msg.state = 'working';
ros::Publisher publisher = nh.advertise<topic_demo::gps>("gps_info", 1);
ros::Rate loop_rate(1.0); // 定义循环发送的频率
while(ros::ok){
msg.x = 1.03 * msg.x;
msg.y = 1.01 * msg.y;
ROS_INFO("talker:GPS: X = %f, Y = %f", msg.x, msg.y)
publisher.publish(msg);
loop_rate.sleep();
}
return 0;
}
- listener.cpp
#include <ros/ros.c>
#include <topic_demo/gps.h> // msg的头文件,生成一个包含msg的类
#include <std_msgs/Float32.h> // ros提供的32位浮点数类型
void gpsCallback(const topic_demo::gps::ConstPtr &msg){
std_msgs::Float32 distance; // distance 是一个结构体,内存存放在distance.data中
distance.data = sqrt(pow(msg->x,2) + pow(msg->y,2));
ROS_INFO("Listener: distance from origin = %f, State = %s", distance.data, msg->state.c_str());
}
// main函数规矩,第一个参数是参数个数,第二个参数是具体参数值
int main(int argc, char** argv){
ros::init(argc, argv, "listener"); // 解析参数,命名节点node
ros::NodeHandle nh; // 创建node句柄,实例化node
// 参数含义:topic名字, 队列长度L通常为1, 回调函数
ros::Subscriber sub = nh.subscribe("gps_info", 1, gpsCallback);
// 反复调用当前可以触发的回调函数,阻塞
// 还有一种只调用一次回调函数的方法:ros::spinOnce();
ros::spin();
return 0;
}
-
更新CMakelist.txt 和 Package.xml
cmake的写法,注意红色部分
package.xml的写法
2. service_demo
功能描述:两个node,一个分布请求,一个接受处理信息,并返回信息
步骤:
- package
$ cd ~/catkin_ws/src
$ catkin_create_pkg service_demo roscpp rospy std_msgs
- srv
$ cd service_demo/
$ mkdir srv
$ cd srv
$ vim Greeting.srv
---
// request方的数据格式
string name
int32 age
---
// reply的数据格式
string feedback
catkin_make 编译之后会生成对应头文件:
~/catkin_ws/devel/include/service_demo/Greeting.h
.../GreetingRequest.h
.../GreetingResponse.h
- server.cpp
#include <ros/ros.h>
#include <service_demo/Greeting.h>
#include "string"
// req和res 都是结构体 包含在对应的Greeting.h 的头文件中
bool handle_function(service_demo::Greeting::Request &req, service_demo::Greeting::Response &res){
// 处理函数,先将req数据打印出来
ROS_INFO("Request from %s with age %d", req.name.c_str(), req.age());
//
res.feedback = "Hi" + req.name + "I am server!";
return true;
}
int main(int argc, char** argv){
ros::init(argc, argv, "greetings_server"); // 为本node命名
ros::NodeHandle nh;
ros::ServiceServer server = nh.advertiseServer("greetings", handle_function); // 提供服务,回调函数返回的是bool变量
ros::spin();
return 0;
}
- client.cpp
#include <ros/ros.h>
#include <service_demo/Greeting.h>
// 包名叫service_demo
int main(int argc, char ** argv){
ros::init(argc,argv, "greetings_client"); // 该节点的名字
ros::NodeHandle nh;
ros::ServerClient client = nh.serverClient<service_demo::Greeting>("greetings"); // 参数为该服务的名字
service_demo::Greeting request;
request.name = "allen";
request.age = 24;
if(client.call(request)){
ROS_INFO("Response from Server: %s", request.response.feedbadk.c_str());
}else {
ROS_ERROR("Failed to call server greetings");
}
return 0;
}
- CMakeList.txt 和 package.xml
3. param_demo
#include<ros/ros.h>
int main(int argc, char **argv){
ros::init(argc, argv, "param_demo");
ros::NodeHandle nh;
int parameter1, parameter2, parameter3, parameter4, parameter5;
//Get Param的三种方法
//① ros::param::get()获取参数“param1”的value,写入到parameter1上
bool ifget1 = ros::param::get("param1", parameter1);
//② ros::NodeHandle::getParam()获取参数,与①作用相同
bool ifget2 = nh.getParam("param2",parameter2);
//③ ros::NodeHandle::param()类似于①和②
//但如果get不到指定的param,它可以给param指定一个默认值(如33333)
nh.param("param3", parameter3, 33333);
if(ifget1)
ROS_INFO("Get param1 = %d", parameter1);
else
ROS_WARN("Didn't retrieve param1");
if(ifget2)
ROS_INFO("Get param2 = %d", parameter2);
else
ROS_WARN("Didn't retrieve param2");
if(nh.hasParam("param3"))
ROS_INFO("Get param3 = %d", parameter3);
else
ROS_WARN("Didn't retrieve param3");
//Set Param的两种方法
//① ros::param::set()设置参数
parameter4 = 4;
ros::param::set("param4", parameter4);
//② ros::NodeHandle::setParam()设置参数
parameter5 = 5;
nh.setParam("param5",parameter5);
ROS_INFO("Param4 is set to be %d", parameter4);
ROS_INFO("Param5 is set to be %d", parameter5);
//Check Param的两种方法
//① ros::NodeHandle::hasParam()
bool ifparam5 = nh.hasParam("param5");
//② ros::param::has()
bool ifparam6 = ros::param::has("param6");
if(ifparam5)
ROS_INFO("Param5 exists");
else
ROS_INFO("Param5 doesn't exist");
if(ifparam6)
ROS_INFO("Param6 exists");
else
ROS_INFO("Param6 doesn't exist");
//Delete Param的两种方法
//① ros::NodeHandle::deleteParam()
bool ifdeleted5 = nh.deleteParam("param5");
//② ros::param::del()
bool ifdeleted6 = ros::param::del("param6");
if(ifdeleted5)
ROS_INFO("Param5 deleted");
else
ROS_INFO("Param5 not deleted");
if(ifdeleted6)
ROS_INFO("Param6 deleted");
else
ROS_INFO("Param6 not deleted");
ros::Rate rate(0.3);
while(ros::ok()){
int parameter = 0;
ROS_INFO("=============Loop==============");
//roscpp中尚未有ros::param::getallparams()之类的方法
if(ros::param::get("param1", parameter))
ROS_INFO("parameter param1 = %d", parameter);
if(ros::param::get("param2", parameter))
ROS_INFO("parameter param2 = %d", parameter);
if(ros::param::get("param3", parameter))
ROS_INFO("parameter param3 = %d", parameter);
if(ros::param::get("param4", parameter))
ROS_INFO("parameter param4 = %d", parameter);
if(ros::param::get("param5", parameter))
ROS_INFO("parameter param5 = %d", parameter);
if(ros::param::get("param6", parameter))
ROS_INFO("parameter param6 = %d", parameter);
rate.sleep();
}
}
网友评论