ROS初学者笔记,谨慎参考
话题通信
话题发布者Publisher
代码
包含头文件(ros/ros.h以及消息类型的头文件)
定义main函数
初始化节点
通过nodehandle发布一个话题并得到话题发布对象
声明消息类型对象
操作消息类型对象
设置循环,发布消息
其他注意事项:
发布频率,消息队列长度等
//向/cmd_vel话题发布速度控制信息
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>//包含头文件(ros/ros.h以及消息类型的头文件)
int main(int argc, char *argv[])//定义main函数
{
ros::init(argc,argv,"vel_node");//初始化节点
ros::NodeHandle n;
ros::Publisher vel_pub = n.advertise<geometry_msgs::Twist>("/cmd_vel",10);//发布一个话题并得到话题发布对象
geometry_msgs::Twist vel_msg;//声明消息类型对象 //注意这里的话题名称是约定俗成的(用于控制速度),不能随意设置
vel_msg.linear.x=0;
vel_msg.linear.y=0;
vel_msg.linear.z=0;
vel_msg.angular.x=0;
vel_msg.angular.y=0;
vel_msg.angular.z=0.5;//操作消息类型对象
ros::Rate r(30);
while(ros::ok()){
vel_pub.publish(vel_msg);//发布消息
r.sleep();
}
return 0;
}
配置CMakeList.txt
添加一个可执行文件,修改文件名称和文件路径
将目标文件与库文件进行链接,修改目标文件名称
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
## add_executable(${PROJECT_NAME}_node src/vel_pkg_node.cpp)
add_executable(vel_node src/vel_node.cpp)
## 将${PROJECT_NAME}_node换成你编写的节点的名字
## 将src/vel_pkg_node.cpp换成节点源文件的位置
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
target_link_libraries(vel_node
${catkin_LIBRARIES}
)
## 将${PROJECT_NAME}_node换成节点名
话题订阅者Subscriber
代码
包含头文件(ros/ros.h以及消息类型的头文件)
定义main函数
初始化节点
通过nodehandle订阅一个话题
编写回调函数
消息回调处理函数spin()
其他注意事项:
话题消息由回调函数的参数传入,消息队列大小
#include "ros/ros.h"
#include "std_msgs/String.h"//包含头文件
void doMsg(const std_msgs::String::ConstPtr& msg_p){//传入话题消息
ROS_INFO("I heard:%s",msg_p->data.c_str());
}
int main(int argc, char *argv[])//定义main函数
{
ros::init(argc,argv,"listener");//初始化节点
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);//通过NodeHandle订阅话题
ros::spin();//spin循环
return 0;
}
配置CMakeList.txt
同上
自定义msg
源文件
直接写入包含的数据类型和名称
string name
uint16 age
float64 height
配置package.xml和CMakeList
向package.xml中添加编译依赖和执行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
CMakeList.txt
添加message_generation(必须先有std_msgs)
添加message源文件
添加生成消息的依赖
添加执行时的依赖
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
message_generation
roscpp
rospy
std_msgs
)
#添加message_generation(必须先有std_msgs)
## Generate messages in the 'msg' folder
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )
add_message_files(
FILES
Carry.msg
)
#添加message源文件
## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# std_msgs
# )
generate_messages(
DEPENDENCIES
std_msgs
)
#添加生成消息的依赖
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES qq_msgs
CATKIN_DEPENDS message_generation message_runtime roscpp rospy std_msgs
# DEPENDS system_lib
)
#执行时的依赖
服务通信
自定义srv
源文件
格式如下(数量任意)
提交参数1
提交参数2
---
输出1
//文件后缀为srv
int32 num1
int32 num2
---
int32 sum
配置package.xml和CMakeList
向package.xml中添加编译依赖和执行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
配置CMakeList.txt
加入 message_generation,必须有 std_msgs
添加srv源文件
添加生成服务的依赖
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
# 需要加入 message_generation,必须有 std_msgs
add_service_files(
FILES
AddInts.srv
)
#添加srv源文件
generate_messages(
DEPENDENCIES
std_msgs
)
#添加生成服务的依赖
服务端
代码
包含头文件(ros/ros.h以及服务消息的头文件)
定义main函数
初始化节点
通过nodehandle发布一个服务
编写回调函数
消息回调处理函数spin()
其他注意事项:
注意回调函数的参数
#include<ros/ros.h>
#include<add_ints_server_client/AddInts.h>//添加头文件和服务消息的文件
//这里的回调函数负责处理客户端提交的参数并将结果保存在参数中
bool doReq(add_ints_server_client::AddInts::Request& req,
add_ints_server_client::AddInts::Response& resp){
int num1 = req.num1;
int num2 = req.num2;
ROS_INFO("the datas server receives are num1 = %d,num2 = %d",num1,num2);
if(num1 < 0|| num2 < 0){
ROS_ERROR("the nums you submit can not be less than 0");
return false;
}
resp.sum = num1 + num2;
return true;
}
int main(int argc,char *argv[]){//定义main函数
ros::init(argc,argv,"AddInts_server");//初始化节点
ros::NodeHandle n;
ros::ServiceServer server = n.advertiseService("AddInts",doReq);
//通过nodehandle发布服务,参数为服务名称和回调函数
ROS_INFO("the server has been initiated");
ros::spin();//一直观测客户端有没有传输消息
return 0;
}
配置CakeList.txt
添加一个可执行文件
添加可执行文件所需的依赖
将目标文件与库文件进行链接
add_executable(AddInts_client src/AddInts_client.cpp)
add_dependencies(AddInts_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(AddInts_client
${catkin_LIBRARIES}
)
客户端
代码
包含头文件(ros/ros.h以及服务消息的头文件)
定义main函数
初始化节点
通过nodehandle创建一个客户端
创建一个服务类型的对象来组织接收到的数据
调用客户端返回是否处理成功
其他注意事项:
传入的参数个数
#include<ros/ros.h>
#include<add_ints_server_client/AddInts.h>//包含头文件(ros/ros.h以及服务消息的头文件)
int main(int argc,char *argv[]){//定义main函数
if(argc != 3){//判断用户输入参数个数是否合法
ROS_ERROR("please submit two nums");
return 1;
}
ros::init(argc,argv,"AddInts_client");//初始化节点
ros::NodeHandle n;//通过nodehandle创建一个客户端
ros::ServiceClient client = n.serviceClient<add_ints_server_client::AddInts>("AddInts");
ros::service::waitForService("AddInts");
add_ints_server_client::AddInts ai;//创建一个服务类型的对象来组织接收到的数据
ai.request.num1 = atoi(argv[1]);
ai.request.num2 = atoi(argv[2]);
bool flag = client.call(ai);//调用服务AddInts,若此时该客户端未与服务端建立通信则返回false
if(flag){
ROS_INFO("process done return: %d",ai.response.sum);
}
else{
ROS_ERROR("process failed ....");
return 1;
}
return 0;
}
配置CakeList.txt
同上
参数通信
为保证一致性,使用NodeHandle实现
模板代码
包含头文件(ros/ros.h以及服务消息的头文件)
定义main函数
初始化节点
得到NodeHandle句柄
使用相关API操作参数
#include <ros/ros.h>//包含头文件(ros/ros.h以及服务消息的头文件)
int main(int argc, char *argv[])//定义main函数
{
ros::init(argc,argv,"demo01_param_set");//初始化节点
ros::NodeHandle n;//得到NodeHandle句柄
n.setParam("radius",0.15);//设置参数名称和数值
n.deleteParam("radius");//删除参数
return 0;
}
配置CMakeList.txt文件
添加一个可执行文件
将目标文件与库文件进行链接
add_executable(demo01_param_set src/demo01_param_set.cpp)
target_link_libraries(demo01_param_set
${catkin_LIBRARIES}
)
常见参数操作
getParam(参数名,数值)//设置参数
deleteParam(参数名)//删除参数,返回值bool类型,表示是否删除成功
getParam(参数名,变量)//将参数赋值给某个已定义变量
参考资料
http://www.autolabor.com.cn/book/ROSTutorials/
【机器人操作系统 ROS 快速入门教程-哔哩哔哩】 https://b23.tv/04zXEoJ
【【Autolabor初级教程】ROS机器人入门-哔哩哔哩】 https://b23.tv/gJ9Nm1P