ROS小车——发布与订阅节点(7)【ROS保姆注释教学】


前言

本系列博客参照《ROS机器人编程原理与应用》一书,搭载平台为冰达ROS小车,注释详细,持续更新,点个关注吧!


1.编写发布节点

在工作空间下(bingda_practices)新建一个src文件夹,用来保存文件的代码,然后新建talker.cpp的c++文件。
代码注释如下:

#include "ros/ros.h" //第一个头文件是ros下的核心,ros.h
#include "std_msgs/String.h"//第二个头文件,计划发布的是string类型

int main(int argc,char **argv)//编写主函数,标准的主函数写法
{   
    ros::init(argc,argv,"talker");//先初始化一个ros,第三个参数为节点名称(talker),节点名称在ros网络中是唯一的,不能有俩一样的
    ros::NodeHandle n;//Nodehandle建立节点间的网络通讯, 名字n不重要很少用到
    ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter",1000);
    /*
    类ROS::Publisher实例化名为chatter_pub的对象,在此对象中,ROS系统接到通知:
    创建一个发布器,发布的类型是sting,当前节点(talker)在名为chatter的话题上发布std_msgs::String数据类型的消息。
    当消息来不及发送时会先放到缓存区,超过1000个就会覆盖。
    */
    ros::Rate loop_rate(10);//用10HZ的频率来循环
    int count = 0;//count用来测量发送了多少个话题
    while (ros::ok())//创建一个死循环,一直循环无法跳出,直到停止ROS系统(关闭roscore)才关闭。
    {
        std_msgs::String msg;
        /*
        程序创建了一个std_msgs::String类型对象,并命名为msg。
        需要在 std_msgs中查阅消息定义才能了解如何使用这个对象,他包含一个名为data的成员。
        下面代码是让data里存放一个格式:hellow world 计数
        */
        std::stringstream ss;//建立一个string类型的变量
        ss<< "hello world"<<count;
        /*利用c++自带的头文件sstream,来实现利用输入输出流的方式往string里写东西,并且还可以拼接string和其他类型的变量。
        该语句实现了string型的数据 hello world和int型变量 count的拼接,形成一个新的string。即如果count是1,那么hello world1会作为string被存放在ss当中!
        怎么调用这个string呢? ss.str()就可以了。最后可以用ROS_INFO输出。
        */
        msg.data = ss.str();
        ROS_INFO("%S",msg.data.c_str());
        /*
        输出一个字符串变量.ROS_INFO和类似的函数用来替代printf/cout.
        其中 ROS_INFO(“INFO message %d”,k),相当于c中的printf;
        ROS_INFO_STREAM ( "INFO message." <<k);相当于c++中的cout;
        */
        chatter_pub.publish(msg);
        /*
        调用发布器,chatter_pub会把std_msgs::Stringstream类型的消息发布到名为chatter的话题上。
        发布器对象chatter_pub有成员函数publish来调用发布。
        */
        ros::spinOnce();//回调函数,处理回调函数队列中的回调函数,此处无用
        loop_rate.sleep();//保证用10HZ的频率来执行
        count++;
        /*code*/

    }
}

2.修改CmakeLists

打开CmakeLists.txt

find_package(catkin REQUIRED)

改为

find_package(catkin REQUIRED
roscpp
std_msgs
)

roscpp和std_msgs都为明确的依赖项。
roscpp:使用c++编译器来创建ROS代码,我们还需要兼容c++接口(比如ros::Publisher类和ros::subscriber类)。
std_msgs:依赖项表面我们将需要依赖一些已经在ros中预定义的数据类型格式,例如std_msgs::Float64

include_directories(
# include
# ${catkin_INCLUDE_DIRS}
)

改为

include_directories(
include
${catkin_INCLUDE_DIRS}
)

在最后加上

add_executable(talker src/talker.cpp)
/*
add_executable(hello_vscode_c  src/hello_vscode_c.cpp):
这个函数目的是生成可执行文件。用src文件夹下的hello_vscode_c.cpp文件生成hello_vscode_c可执行文件。
hello_vscode_node.cpp文件是你写的c++源文件,文件名是你创建c++文件时命名的,最终这个文件映射的文件名称为hello_vscode_c,这个名称可以修改,一般源文件和生成的可执行文件的名称设置为一样的,但这两者需要满足计算机语言的命名要求。
可以传入多个源文件,如add_executable(my_node src0.cpp src1.cpp src2.cpp )。函数后面的src0.cpp src1.cpp src2.cpp三个源文件,生成可执行文件my_code这一个可执行文件。
*/
target_link_libraries(talker ${catkin_LIBRARIES})

/*
target_link_libraries(hello_vscode_c  ${catkin_LIBRARIES} ):
这个函数为可执行文件或库添加链接库。函数中 hello_vscode_c是上一个函数语句生成的可执行文件,${catkin_LIBRARIES} 是ROS的基本库:catkin库。
把生成的可执行文件和catkin库链接到一起。
同时,在CMakeListd文件里面,这篇文章中所提到的第二个函数要放在第一个函数后面,因为target_link_libraries函数需要用到add_executable生成的可执行文件。

*/

最后在catkin_make 下编译catkin_make

3.运行程序

打开终端运行roscore
再打开一个终端,运行 rosrun bingda_parctices talker

在这里插入图片描述

4.编写订阅节点

如同listener.cpp,新建一个listener.cpp
代码注释如下:

#include "ros/ros.h" //第一个头文件是ros下的核心,ros.h
#include "std_msgs/String.h"//第二个头文件,计划发布的是string类型

void chatterCallback(const std_msgs::String::ConstPtr& msg)//回调函数作用是打印出来话题
/*
这个函数(callback)有一个指向std_msgs::String类型对象的引用指针参数(由&符号标识)。这是与chatter关联的消息类型,由最小发布器发布。
回调(callback)函数的重要性在于,当在它的关联话题(在本例中设定为topicl)上有新数据可用时,它会被唤醒。当新数据发布到关联话题时,回调函数开始运行,同时已发布的数据会出现在参message_holder中。
(该信息持有者必须是与发布在兴趣话题上的消息类型相兼容的类型,例如:std_msgs::String)
回调函数做的唯-的事情 就是显示接收到的数据
*/
{
	ROS_INFO("I heared:[%s]",msg->data.c_str());
}

int main(int argc,char **argv)//编写主函数,标准的主函数写法
{   
    ros::init(argc,argv,"talker");//先初始化一个ros,第三个参数为节点名称(talker),节点名称在ros网络中是唯一的,不能有俩一样的
    ros::NodeHandle n;//Nodehandle建立节点间的网络通讯, 名字n不重要很少用到
    ros::Subscriber sub = n.subscribe("chatter",1000,chatterCallback); 
    /*
    类ROS::Subscriber实例化名为sub的对象,Subscriber是存在于ROS版本的一个类,
    他包括三个参数用于实例化订阅器对象:参数名、队列大小、回调函数名。
    */
    ros::spin();
    /*
		每当chatter有新消息时,回调函数会被唤醒,然而,主程序必须为回调函数的响应提供一些时		间。
		这可以通过spin()命令完成。虽然spin可以让主程序挂起,但回调函数依旧可以工作。
		如果主函数运行结束,回调函数就不再对新消息做出反应。
		spin()命令不需要消耗大量Cpu的时间就可以保持main()的运行,非常高校。
	*/
	return 0;
 
}

5.修改CmakeLists

在最后加上

add_executable(talker src/talker.cpp)

target_link_libraries(hello_vscode_c  ${catkin_LIBRARIES} )

add_executable(listener src/listener.cpp)

target_link_libraries(listenner  ${catkin_LIBRARIES} )

最后在catkin_make 下编译catkin_make

先运行发布者,再运行接听者。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ROS中,我们可以通过发布命令来控制小车的移动。首先,我们需要创建一个ROS工作空间,并在该空间中创建一个包以进行相关操作。 在创建的包中,我们首先需要编写一个发布节点,用于发布小车的移动命令。在这个节点中,我们可以使用ROS提供的功能包,如`rospy`来进行通信。 首先,我们需要导入`rospy`包,并初始化ROS节点: ``` import rospy rospy.init_node('car_control') ``` 然后,我们需要创建一个发布者`pub`,用于发布小车的命令信息。我们需要指定发布的消息类型,如`geometry_msgs/Twist`: ``` pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10) ``` 接下来,我们可以使用循环来不断发布移动命令。例如,我们可以每秒向前移动0.2米,并同时绕z轴旋转90度(逆时针方向): ``` rate = rospy.Rate(1) # 设置发布频率为1Hz while not rospy.is_shutdown(): move_cmd = Twist() move_cmd.linear.x = 0.2 # 设置线速度为0.2 m/s move_cmd.angular.z = 1.57 # 设置角速度为1.57 rad/s (90度/秒) pub.publish(move_cmd) # 发布移动命令 rate.sleep() ``` 这样,小车就会按照我们设置的速度和角度进行移动了。 另外,我们还需要在ROS系统中创建一个订阅节点,用于监听小车的位置信息,并进行处理。这部分的代码可以在一个单独的节点中实现,通过订阅小车移动的消息,我们可以实现一些更加复杂的控制逻辑,如避障或自动导航等。 以上就是通过发布命令来使小车移动的一般步骤。在实际使用中,根据具体的小车类型和硬件接口,还需要进一步编写驱动程序来控制小车的电机和传感器等设备。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值