目录
(一)常用API
1 初始化
1.1 初始化函数(c++)
(1)函数一般表达式:
(2)使用
(3)举例(c++)
案例1:argc与argv使用
要求
cmakelists.txt配置
代码
效果图
案例2:options的使用
要求
cmakelists.txt配置
代码
效果图
1.2 初始化函数(python)
(1)一般表达式
(2)使用
(3)举例
案例1:argc与argv使用
要求
配置
代码
效果图
案例2:options的使用
要求
配置
代码
效果图
2 话题与服务相关对象
2.1 基于(c++)
2.1.1 发布对象
(1)简介
(2)举例
案例1:有无latch
2.1.2 订阅对象
2.1.3 服务对象
2.1.4 客户端对象
2.2 基于python
2.2.1 发布对象
(1)一般形式
(2)举例
案例1:有无latch
3 回旋函数
3.1 基于C++
(1)spinonce()
(2)spin()
(3)比较
(4)举例
案例1:回旋函数spin()
案例2:回旋spinonce()
3.2 基于Python
4 时间
4.1 基于C++
(1)时刻
(2)持续时间
(3)持续时间与时刻运算
(4)设置运行频率
(5)定时器
(6)举例
案例1
4.2 基于python
(1)时刻
(2)持续时间
(3)持续时间与时刻运算
(4)置运行频率
(5)定时器
(6)举例
案例1
5 其他函数
5.1 基于C++
(1)节点状态判断
(2)节点关闭函数
(3)日志函数
(4)举例
案例1
5.2 基于python
(1)节点状态判断
(2)节点关闭函数
(3)日志函数
(4)举例
案例1
(一)常用API
1 初始化
1.1 初始化函数(c++)
(1)函数一般表达式:
ros::init(argc,argv,"talker",ros::init_options::AnonymousName);
//void init(const M_string& remappings, const std::string& name, uint32_t options = 0);
/*
作用:ROS初始化函数
参数:
1.argc --- 封装实参个数(n+1)
2.argv --- 封装参数的数组
3.name --- 为节点命名(唯一性)
4.options --- 节点启动选项
返回值:void
*/
(2)使用
1. argc 与 argv 的使用
如果按照ROS中的特定格式传入实参,那么ROS可以加以使用,比如设置全局参数,给节点命名
2. options 的使用
节点命名要保证唯一,会导致一个问题:同一节点不能重复启动
结果:ROS中当有重名节点启动时,之前的节点会被关闭
需求:特定场景下,需要一个节点多次启动且能正常运行,怎么办?
解法:设置启动项ros::init_options::AnonymousName
ros::init(argc,argv,"talker",ros::init_options::AnonymousName);
//当创建ROS节点时,会在用户自定义的节点名称后加随机数,从而避免重名问题
(3)举例(c++)
案例1:argc与argv使用
要求
按照ROS中的特定格式传入实参,设置全局参数,给节点命名
cmakelists.txt配置
- cmakelists.txt配置
add_executable(demo01_api_pub src/demo01_api_pub.cpp)
target_link_libraries(demo01_api_pub
${catkin_LIBRARIES}
)
代码
#include "ros/ros.h"
#include "std_msgs/String.h" //普通文本类型的消息
#include <sstream>
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"talker"); //实例化 ROS 句柄
ros::NodeHandle nh; //该类封装了 ROS 中的一些常用功能
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10,true);
std_msgs::String msg;
// msg.data = "你好啊!!!";
std::string msg_front = "Hello 你好!"; //消息前缀
int count = 0; //消息计数器
ros::Rate r(10); //逻辑(一秒10次)
ros::Duration(3).sleep(); //设置循环,循环中发布数据
while (ros::ok()) //节点不死
{
count++;
std::stringstream ss; //使用 stringstream 拼接字符串与编号
ss << msg_front << count;
msg.data = ss.str();
if (count<=10)
{
pub.publish(msg); //发布消息
ROS_INFO("发送的消息:%s",msg.data.c_str());
}
r.sleep();
ros::spinOnce();
}
return 0;
}
效果图
案例2:options的使用
要求
按照ROS中的特定格式传入实参,设置全局参数,给节点命名,即可以重复调用同一个节点
cmakelists.txt配置
add_executable(demo01_api_pub src/demo01_api_pub.cpp)
target_link_libraries(demo01_api_pub
${catkin_LIBRARIES}
)
代码
#include "ros/ros.h"
#include "std_msgs/String.h" //普通文本类型的消息
#include <sstream>
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"talker",ros::init_options::AnonymousName); //实例化 ROS 句柄
ros::NodeHandle nh; //该类封装了 ROS 中的一些常用功能
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10,true);
std_msgs::String msg;
// msg.data = "你好啊!!!";
std::string msg_front = "Hello 你好!"; //消息前缀
int count = 0; //消息计数器
ros::Rate r(10); //逻辑(一秒10次)
ros::Duration(3).sleep(); //设置循环,循环中发布数据
while (ros::ok()) //节点不死
{
count++;
std::stringstream ss; //使用 stringstream 拼接字符串与编号
ss << msg_front << count;
msg.data = ss.str();
if (count<=10)
{
pub.publish(msg); //发布消息
ROS_INFO("发送的消息:%s",msg.data.c_str());
}
r.sleep();
ros::spinOnce();
}
return 0;
}
效果图
1.2 初始化函数(python)
(1)一般表达式
def init_node(name, argv=None, anonymous=False, log_level=None, disable_rostime=False, disable_rosout=False, disable_signals=False, xmlrpc_port=0, tcpros_port=0):
作用: ROS初始化
参数:
name: 节点名称,必须保证节点名称唯一,节点名称中不能使用命名空间(不能包含 '/')
argv=None ---- 封装节点调用时传递参数
anonymous=False --- bool 可以为节点名称生成随即后缀,可以解决重名问题
# rospy.init_node("api_listener_p",True) //不可以简写
rospy.init_node("api_listener_p",anonymous=True)
(2)使用
使用:
1.argc使用
可以按照ROS中指定的语法格式传参,ROS可以解析并加以使用
2.anonymous使用
可以设置值为True,节点名称可以后缀随机数
(3)举例
案例1:argc与argv使用
要求
按照ROS中的特定格式传入实参,设置全局参数,给节点命名
配置
- cmakelists.txt配置
catkin_install_python(PROGRAMS
scripts/demo01_api_pub_p.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
代码
#! /usr/bin/env python
# coding=UTF-8
import rospy
from std_msgs.msg import String
if __name__ == "__main__":
rospy.init_node("api_listener_p")
pub = rospy.Publisher("fang",String,queue_size=10)
msg = String() #创建 msg 对象
msg_front = "hello"
count = 0 #计数器
# 设置循环频率
rate = rospy.Rate(1)
while not rospy.is_shutdown():
count += 1
if count <= 10:
msg.data = msg_front + str(count) #拼接字符串
pub.publish(msg)
rospy.loginfo("写出的数据:%s",msg.data)
rate.sleep()
效果图
案例2:options的使用
要求
按照ROS中的特定格式传入实参,设置全局参数,给节点命名,即可以重复调用同一个节点
配置
- cmakelists.txt配置
catkin_install_python(PROGRAMS
scripts/demo01_api_pub_p.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
代码
#! /usr/bin/env python
# coding=UTF-8
import rospy
from std_msgs.msg import String
if __name__ == "__main__":
rospy.init_node("api_listener_p",anonymous=True)
pub = rospy.Publisher("fang",String,queue_size=10)
msg = String() #创建 msg 对象
msg_front = "hello"
count = 0 #计数器
# 设置循环频率
rate = rospy.Rate(1)
while not rospy.is_shutdown():
count += 1
if count <= 10:
msg.data = msg_front + str(count) #拼接字符串
pub.publish(msg)
rospy.loginfo("写出的数据:%s",msg.data)
rate.sleep()
效果图
2 话题与服务相关对象
2.1 基于(c++)
在 roscpp 中,话题和服务的相关对象一般由 NodeHandle 创建。NodeHandle有一个重要作用是可以用于设置命名空间
2.1.1 发布对象
(1)简介
/*
作用:创建发布者对象
模板:被发布的消息的类型
参数:
1.话题名称
2.队列长度
3.latch(可选) 如果设置为true,他会保存发布方的最后一道消息,并且新的订阅对象连接到发布方时,发布方会将这条信息发给订阅者
使用:
1.latch 设置为true的作用?
以静态地图发布为例,
方案1:可以使用固定频率发布地图数据,但是效率低
方案2:可以将地图发表对象的latch设置为true,并且发布方只发送一次数据,每当订阅者连接时,将地图数据发送给订阅者(只发送一次)
*/
ros::NodeHandle nh;//该类封装了 ROS 中的一些常用功能
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10,true);
(2)举例
案例1:有无latch
要求
查看有无latch情况
cmakelists.txt配置
add_executable(demo01_api_pub src/demo01_api_pub.cpp)
add_executable(demo01_api_sub src/demo01_api_sub.cpp)
target_link_libraries(demo01_api_pub
${catkin_LIBRARIES}
)
target_link_libraries(demo01_api_sub
${catkin_LIBRARIES}
)
发布方代码
#include "ros/ros.h"
#include "std_msgs/String.h" //普通文本类型的消息
#include <sstream>
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"talker",ros::init_options::AnonymousName); //实例化 ROS 句柄
ros::NodeHandle nh; //该类封装了 ROS 中的一些常用功能
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10,true);//latch=true
//ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10,true);latch=false
std_msgs::String msg;
// msg.data = "你好啊!!!";
std::string msg_front = "Hello 你好!"; //消息前缀
int count = 0; //消息计数器
ros::Rate r(10); //逻辑(一秒10次)
ros::Duration(3).sleep(); //设置循环,循环中发布数据
while (ros::ok()) //节点不死
{
count++;
std::stringstream ss; //使用 stringstream 拼接字符串与编号
ss << msg_front << count;
msg.data = ss.str();
if (count<=10)
{
pub.publish(msg); //发布消息
ROS_INFO("发送的消息:%s",msg.data.c_str());
}
r.sleep();
ros::spinOnce();
}
return 0;
}
订阅方代码
/*
需求: 实现基本的话题通信,一方发布数据,一方接收数据,
实现的关键点:
1.发送方
2.接收方
3.数据(此处为普通文本)
消息订阅方:
订阅话题并打印接收到的消息
实现流程:
1.包含头文件
2.初始化 ROS 节点:命名(唯一)
3.实例化 ROS 句柄
4.实例化 订阅者 对象
5.处理订阅的消息(回调函数)
6.设置循环调用回调函数
*/
// 1.包含头文件
#include "ros/ros.h"
#include "std_msgs/String.h"
void doMsg(const std_msgs::String::ConstPtr& msg_p){
ROS_INFO("我听见:%s",msg_p->data.c_str());
// ROS_INFO("我听见:%s",(*msg_p).data.c_str());
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//2.初始化 ROS 节点:命名(唯一)
ros::init(argc,argv,"listener");
//3.实例化 ROS 句柄
ros::NodeHandle nh;
//4.实例化 订阅者 对象
ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);
//5.处理订阅的消息(回调函数)
// 6.设置循环调用回调函数
ros::spin();//循环读取接收的数据,并调用回调函数处理
return 0;
}
效果图
发布方latch=true
发布方latch=false