欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > ROS系统(三)编程基础

ROS系统(三)编程基础

2025/7/6 21:42:16 来源:https://blog.csdn.net/qq_48361010/article/details/146051790  浏览:    关键词:ROS系统(三)编程基础

一、创建功能包。

请查看第一章的前三个知识点。

ROS系统(二)常用工具及命令https://blog.csdn.net/qq_48361010/article/details/146033554?spm=1001.2014.3001.5501

二、发布/订阅节点(C++)

        前期准备:在工作站中新建src文件夹,进入src中新建包,然后回到工作站的目录下编译包会在功能包的目录下自动生成package.xmlCMakeLists.txt。然后进入包的目录下创建src文件夹,进入该目录下,创建c++文件。

1. 编写C++文件。

test_talker.cpp

#include "ros/ros.h"           // ROS 头文件
#include "std_msgs/String.h"    // ROS 标准消息类型 String
#include <sstream>              // C++ 字符串流,用于拼接字符串int main(int argc, char **argv) {// 初始化 ROS 节点,节点名称为 "talker"ros::init(argc, argv, "talker");// 创建节点句柄ros::NodeHandle n;// 创建一个发布者 (Publisher)// 话题名称为 "chatter",消息类型为 std_msgs::String,消息队列大小为 1000ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);// 设定循环频率为 10Hz,即每 0.1 秒运行一次ros::Rate loop_rate(10);int count = 0;  // 计数变量,记录消息发送次数// 进入循环,持续发布消息while (ros::ok()) {  std_msgs::String msg;  // 定义 ROS 消息std::stringstream ss;  // 创建字符串流ss << "hello world " << count;  // 拼接消息内容msg.data = ss.str();  // 赋值给消息的 data 字段// 在终端输出消息内容 (ROS_INFO 相当于 printf 或 cout)ROS_INFO("%s", msg.data.c_str());// 发布消息到 "chatter" 话题chatter_pub.publish(msg);// 处理 ROS 事件(虽然当前节点没有订阅者,但养成调用的习惯)ros::spinOnce();// 休眠以维持 10Hz 运行频率loop_rate.sleep();count++;  // 计数器递增}return 0;  // 结束程序
}

test_listener.cpp

#include "ros/ros.h"        // ROS 头文件
#include "std_msgs/String.h" // 用于发布/订阅字符串消息的标准消息类型// 订阅者回调函数,接收并打印从 "chatter" 主题接收到的消息
void chatterCallback(const std_msgs::String::ConstPtr& msg) {ROS_INFO("I heard: [%s]", msg->data.c_str());  // 使用 c_str() 转换 std::string 为 C 字符串
}int main(int argc, char **argv) {ros::init(argc, argv, "listener"); // 初始化 ROS 节点,命名为 "listener"ros::NodeHandle n;                 // 创建节点句柄// 创建一个订阅者,订阅 "chatter" 主题,队列大小为 1000,回调函数为 chatterCallbackros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);ros::spin();  // 进入循环,等待回调函数处理消息return 0;
}

2. 修改编译规则。   

        返回到功能包目录下,修改CMakelist.txt文件来构建编译规则,该文件内容知识点请查看下面文章。

ROS系统(一)安装及基础知识https://blog.csdn.net/qq_48361010/article/details/146005869?sharetype=blogdetail&sharerId=146005869&sharerefer=PC&sharesource=qq_48361010&spm=1011.2480.3001.8118功能包目录下的CMakelist.txt修改为以下内容。

cmake_minimum_required(VERSION 3.0.2)   # 1. 指定最低 CMake 版本
project(my_ros_tutorials)               # 2. 定义项目名称,与 package.xml 一致find_package(catkin REQUIRED COMPONENTS  # 3. 查找 ROS 依赖组件roscpp    # C++ 版 ROS 运行库rospy     # python 版 ROS 运行库std_msgs  # 使用的消息类型
)catkin_package()  # 4. 声明 catkin 包include_directories(                      # 5. 指定头文件路径include ${catkin_INCLUDE_DIRS}
)add_executable(talker src/test_talker.cpp)     # 6. (要生成的可执行文件  源文件)
target_link_libraries(talker              # 7. 连接 ROS 相关库${catkin_LIBRARIES}
)add_executable(listener src/test_listener.cpp)     # 6. (要生成的可执行文件  源文件)
target_link_libraries(listener               # 7. 连接 ROS 相关库${catkin_LIBRARIES}
)

3. 编译生成可执行文件。

        在工作站目录下,使用命令:catkin_make。如果编译成功,就会在 ~/catkin_ws/devel/lib/包名/ 目录下生成 talker、listener 可执行文件。

4. 运行节点。

        使用命令:roscore开始主节点,然后使用命令:rosrun 包名 talker
,如果运行完成后出现下面内容,说明编写成功!

三、发布/订阅节点(Python)

         编写python代码时,由于不需要被编译,但是为了保持项目的整洁性,应该遵循 ROS 的目录结构,并放在功能包(package)目录下,创建scripts目录来存放python代码。

1. 编写py代码。

talker.py

#!/usr/bin/env python
import rospy
from std_msgs.msg import Stringdef talker():pub = rospy.Publisher("chatter", String, queue_size=10)rospy.init_node("talker", anonymous=False)rate = rospy.Rate(10)  # 10Hzwhile not rospy.is_shutdown():hello_str = "hello world %s" % rospy.get_time()rospy.loginfo(hello_str)pub.publish(hello_str)rate.sleep()if __name__ == '__main__':try:talker()except rospy.ROSInterruptException:pass

listener.py 

#!/usr/bin/env python
import rospy
from std_msgs.msg import String  # std_msgs.msg 的 String 需要大写def callback(data):rospy.loginfo(rospy.get_caller_id() + " I heard: %s", data.data)  # 修正 loginfo 语法错误def listener():rospy.init_node("listener", anonymous=False)  # 修正 init_node 语法错误rospy.Subscriber("chatter", String, callback)  # 修正 String 类型拼写rospy.spin()if __name__ == "__main__":  # 修正 if __name__ 语句错误listener()

2. 运行节点。

        需要先开启主节点,然后使用命令rosrun 包名 talker.py来运行节点。这里C++和python都可以互通,比如运行C++写的talker,再运行python写的listener.py,都是可用互相通信的。

        在 ROS中,C++ 和 Python 节点是可以互通的。这是因为 ROS 中的消息传递是基于发布-订阅(publish-subscribe)模型的,只要 talkerlistener 节点使用相同的消息类型和主题(topic),它们就可以互相通信。而 ROS 提供了多语言支持,使得使用不同语言编写的节点能够通过共享消息格式进行通信。

四、编写一个launch文件

 my_launch_file.launch

<launch><node name="talker" pkg="ros_tutorials" type="talker" respawn="true" output="screen"/><param name="rate" value="10" /><node name="listener" pkg="ros_tutorials" type="listener" respawn="true" output="screen"/><!-- 启动基础系统 --><include file="$(find my_package)/launch/base_system.launch" /><!-- 启动其他模块 --><include file="$(find my_package)/launch/advanced_module.launch" />
</launch>
<!--
#  name="talker":ROS 节点名称为 talker。
#  pkg="ros_tutorials":该节点来自 ros_tutorials 包。
#  type="talker":执行 ros_tutorials 包中的 talker 可执行文件。
#  respawn="true":如果该节点崩溃或意外退出,会 自动重启 该节点。
#  output="screen":终端会打印 talker 运行时的日志信息。
#  $(find my_package) 会找到包 my_package 的路径,
-->

(1)<launch> 标签:是 ROS 启动文件的根标签,所有的 ROS 节点、参数等内容都必须包含在这个标签内。一个 .launch 文件必须以 <launch> 开头,并以 </launch> 结束。

(2)<node> 标签:用于启动 ROS 中的一个可执行程序(节点)。

<node name="节点名称" pkg="包名称" type="可执行文件名"  />

(3)<param> 标签:用于在ROS参数服务器中设置参数。

        缩进 <param> 语句,把它放进 <node> 里面,就能让这个参数只作用于该节点!

<launch><node name="talker" pkg="ros_tutorials" type="talker" respawn="true" output="screen"><param name="rate" value="10" />  #这个参数只能被talker读取,因为在talker内部。</node><node name="listener" pkg="ros_tutorials" type="listener" respawn="true" output="screen"/>
</launch># 参数名为rate,值为10

那么这个参数如何被代码读取或修改呢?

import rospy
rate = rospy.get_param("rate", 1)  # 读取 ROS 参数服务器上的 "rate",如果不存在,则默认为 1
r = rospy.Rate(rate)  # 控制 talker 发送消息的频率

(4)<include> 标签:用于包含其他的launch文件。

(5)使用命令:roslaunch my_package my_launch_file.launch,会启动 talker和listener,它会不断发布消息到 /chatter 话题。 listener,它会订阅 /chatter 话题,并打印收到的消息。

相当于手动运行以下命令:

roscore
rosrun ros_tutorials talker
rosrun ros_tutorials listener

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词