——师从B站 机器人工匠阿杰
创建并编译运行一个Node节点
框架:
步骤
1、进入工作空间的src目录中
cd catkin_ws/src/
使用catkin_create_pkg创建软件包
catkin_create_pkg ssr_pkg rospy roscpp std_msgs
其中 rospy、roscpp、std_msgs是依赖项列表
2、打开VScode,在src文件下创建cpp的源文件 名称为 chao_node.cpp
3、4、5、C++程序
#include <ros/ros.h> //ros的头文件
int main(int argc, char *argv[])
{
ros::init(argc,argv,"chao_node");//ros节点初始化(才可和ROS连接,进行后续调用)
printf("hhh\n");
while(ros::ok()) //ros节点可用Ctrl+c终止
{
printf("别投,我还能秀!\n");
}
return 0;
}
6、VScode中设置编译规则
在 CMakeList.txt 中 Build栏下
## Declare a C++ executable 规则(添加需要编译的c++文件),将下面代码放到最后面
## Specify libraries to link a library or executable target against函数也放到后面,用来将ros初始化函数所在库文件一起编译(选中句子,Ctrl+/ 可以直接去除 # )
#只需要将节点名称改为对应
add_executable(chao_node src/chao_node.cpp)
target_link_libraries(chao_node
${catkin_LIBRARIES}
)
7、运行编译
(1)编译:VScode中按键 Ctrl+Shift+B进行编译,或进入工作空间(第一句) 使用下面命令进行编译(第二句)
cd catkin_ws
catkin_make
(2)工作空间参数加载到终端程序
将source指令添加到bashrc文件中,这样打开中断程序就会自动加载工作空间参数
用VScode编写bashrc文件,在终端中运行
code ~/.bashrc
在文件末尾添加
source ~/catkin_ws/devel/setup.bash
(3)运行节点
启动ROS系统核心,终端中运行,并保持ROS系统在运行状态中
roscore
新终端中运行
rosrun ssr_pkg chao_node
节点就启动了
Topic话题和Message消息
Topic话题
小结:
1、话题Topic是节点间进行持续通讯的一种形式。
2、话题通讯的两个节点通过话题的名称建立起话题通讯连接。
3、话题中通讯的数据,叫做消息Message。
4、消息Message通常会按照一定的频率持续不断的发送,以保证消息数据的实时性。
5、消息的发送方叫做话题的发布者Publisher。
6、消息的接收方叫做话题的订阅者Subcriber。
补充:
消息Message
标准数据类型消息包 std_msgs
从 index.ros.org中可以了解各种消息的类型,复杂的消息类型也可以理解为C语言中的结构体,各种类型的嵌套。
话题消息的发送
基于C++的消息发送节点
所添加的过程在注释中
#include <ros/ros.h> //ros的头文件
#include<std_msgs/String.h>//2.标准消息类型的String头文件
int main(int argc, char *argv[])
{
ros::init(argc,argv,"chao_node");//ros节点初始化(才可和ROS连接,进行后续调用)
printf("hhh\n");
//2、通过NodeHandler句柄(大管家)发布一个话题并创建消息发送对象
ros::NodeHandle nh; //初始化句柄 可以让你通过构造函数指定命名空间
//创建发布者
ros::Publisher pub = nh.advertise<std_msgs::String>("Play_together",10);
//话题名称不能是中文
ros::Rate loop_rate(10);//引入循环的频率函数 单位: x次/s
while(ros::ok()) //ros节点可用Ctrl+c终止
{
printf("我要开始刷屏了!\n");
std_msgs::String msg; //4、生成消息包::类型是String 名称msgs
msg.data = "国服马超,带飞"; //消息类型变量
pub.publish(msg); //5、发送消息
loop_rate.sleep(); //指定发布周期函数
}
return 0;
}
在CMakeList.txt文件中加入下面的程序
add_executable(yao_node src/yao_node.cpp)
target_link_libraries(yao_node
${catkin_LIBRARIES}
)
基于Pyhton的消息发送节点
创建文件夹时,需要有 rospy文件,并且编译一遍。
在src文件夹下创建scripts文件夹,并新建chao_node.py文件;写入内容
#!/usr/bin/env python3
#coding=utf-8
import rospy
from std_msgs.msg import String #从标准信息包中导入字符串类型
if __name__ == '__main__': #主函数定义
rospy.init_node("chao_node") #ros节点初始化
rospy.logwarn("我的枪去而复返!") #记载标志,表示当前初始化成功
#创建消息发布者 ("话题名称",消息类型,queue_size=缓存长度)
pub = rospy.Publisher("kuai_shang_che_kai_hei_qun",String,queue_size=10)
#发送频率
rate = rospy.Rate(10)
while not rospy.is_shutdown():
rospy.loginfo("我要刷屏了")
msg = String() #数据类型
msg.data = "国服马超,带飞" #在数据包的数据段data写入消息内容
pub.publish(msg) #发送消息
rate.sleep() #休眠等待,控制循环频率
代码写完要给程序运行权限。
首先打开终端,进入scripts文件夹,执行给权限的代码
chmod +x /chao_node.py
输入ls,文件名变成绿色表示文件已经具有执行权限。
yao_node.py可直接由chao_node.py复制修改得来,就带有执行权限了。
#!/usr/bin/env python3
#coding=utf-8
import rospy
from std_msgs.msg import String
if __name__ == '__main__':
rospy.init_node("yao_node")
rospy.logwarn("我的枪去而复返!")
pub = rospy.Publisher("gie_gie_dai_wo",String,queue_size=10)
rate = rospy.Rate(10)
while not rospy.is_shutdown():
rospy.loginfo("giegie~")
msg = String()
msg.data = "求上车+++"
pub.publish(msg)
rate.sleep()
消息发送相关调试工具
rostopic list
列出当前系统中所有活跃着的话题名称
rostopic echo /话题名称
显示该话题的发布的消息包内容
中文是Unicode编码,无法直接显示,执行下面语句进行转换
echo -e "\u56FD\u670D\u9A6C\u8D85\uFF0C\u5E26\u98DE"
rostopic hz /主题名称
可以查看消息发送的频率 /后面是话题名称
消息的接收
基于C++的消息接收节点
#include<ros/ros.h>
#include<std_msgs/String.h>
void chao_callback(std_msgs::String msg) //定义回调函数
{
ROS_INFO(msg.data.c_str());//可诶显示接受时间的接收函数
}
void yao_callback(std_msgs::String msg)
{
ROS_WARN(msg.data.c_str());//字体颜色为黄色的显示信息函数
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//从当前系统读取默认设置;中文Ubantu系统写一对“”;英文版系统写“zh_CN.UTF-8”
ros::init(argc,argv,"ma_node");
ros::NodeHandle nh; //初始化句柄
//创建订阅者1
ros::Subscriber sub = nh.subscribe("Play_together",10,chao_callback);
//创建订阅者2
ros::Subscriber sub_2 = nh.subscribe("Help_Me",10,yao_callback);
//sub = nh.subscribe("话题名称", 缓存长度 , 回调函数);
while (ros::ok())
{
ros::spinOnce();//消息回调处理函数
}
return 0;
}
消息回调处理函数
ros::spin()、ros::spinOnce():使用细节、区别-CSDN博客
基于Python的消息接收节点
同样创建python需要有rospy依赖,并且创建了文件夹就要运行一次
#!/usr/bin/env python3
#coding=utf-8
import rospy
from std_msgs.msg import String #引入字符串类型数据包
def chao_callback(msg): #回调函数chao
rospy.loginfo(msg.data) #打印接收到的数据
def yao_callback(msg): #回调函数yao
rospy.logwarn(msg.data) #以黄色字体打印收到的数据
if __name__ == "__main__": #主函数
rospy.init_node("ma_node") #节点初始化
#创建订阅对象 ("话题名称",数据类型,回调函数,缓存长度)
sub = rospy.Subscriber("kuai_shang_che_kai_hei_qun",String,chao_callback,queue_size=10)
sub_2 = rospy.Subscriber("gie_gie_dai_wo",String,yao_callback,queue_size=10)
rospy.spin() #再执行一次回调函数
常用工具
rqt_graph 图形化显示当前系统活跃的节点以及节点间的话题通讯关系
launch文件的使用
在工作空间中添加一个新的文件夹来写launch文件
<launch>
<node pkg="ssr_pkg" type="yao_node" name="yao_node"/>
<node pkg="ssr_pkg" type="chao_node" name="chao_node" launch-prefix="gnome-terminal -e"/>
<node pkg="atr_pkg" type="ma_node" name="ma_node" output="screen"/>
</launch>