ROS 使用笔记
2026/7/14 20:31:12 网站建设 项目流程

1.什么是 ROS?

ROS (Robot Operating System)是一个适用于机器人的开源的元操作系统。它提供了操作系统应有的服务,包括

  • 硬件抽象
  • 底层设备控制
  • 常用函数的实现
  • 进程间消息传递
  • 包管理
  • 用于获取、编译、编写、和跨计算机运行代码所需的工具和库函数

2. 为什么使用ROS?

ROS 的主要目标是为机器人研究和开发提供代码复用的支持。简单来说就是避免重复造轮子。

为什么ROS可以提高代码复用率?

因为ROS有程序包功能包概念,类比与C++Python的库的概念,这些包易于被分享和发布,而且ROS也支持一种类似于代码储存库的联合系统,这个系统也可以实现工程的协作及发布。这个设计可以使一个工程的开发和实现完全模块化,同时,所有的工程都可以被ROS的基础工具整合在一起。

除此之外,ROS还有以下优势:

  • 精简:ROS被设计为尽可能精简,易于与其他机器人软件框架集成
  • 语言独立性:为了支持更多应用开发和移植,ROS设计为一种语言弱相关的框架结构,中立的定义语言描述模块间的消息接口,JavaC++Python都可以进行ROS开发。
  • 大型应用:ROS适用于大型运行时系统和大型开发流程
  • 丰富的组件化工具包:ROS可采用组件化方式集成一些工具和软件到系统中并作为一个组件直接使用,如RVIZGazebo等,后面都会介绍。
  • 免费且开源:开发者众多,功能包多

3. 创建ROS工作空间

mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_init_workspace

4. 头文件

#include <ros/ros.h> #include <nav_msgs/Odometry.h> #include <sensor_msgs/Imu.h> #include <sensor_msgs/NavSatFix.h> #include <sensor_msgs/PointCloud2.h> #include <std_msgs/Float32.h> #include <cv_bridge/cv_bridge.h>

5. 类定义

class Scheduler { public: Scheduler(ros::NodeHandle& node_handle); ~Scheduler(); void initialize(); void run(); private: void imuHandler(const sensor_msgs::Imu::ConstPtr& msg); void gpsHandler(const sensor_msgs::NavSatFix::ConstPtr& msg); void cloudHandler(const sensor_msgs::PointCloud2ConstPtr& msg); void imageHandler(const sensor_msgs::Image::ConstPtr& msg); void compressedImageHandler(const sensor_msgs::CompressedImage::ConstPtr& msg); private: ros::NodeHandle node_handle_; // Subscriber ros::Subscriber imu_sub_; ros::Subscriber gnss_sub_; ros::Subscriber cloud_sub_; ros::Subscriber image_sub_; ros::Subscriber compressed_image_sub_; // Publisher ros::Publisher location_pub_; };

6. 初始化

void Scheduler::initialize() { imu_sub_ = node_handle_.subscribe("imu_topic", 10, &Scheduler::imuHandler, this, ros::TransportHints().tcpNoDelay()); gnss_sub_ = node_handle_.subscribe("gps_topic", 2, &Scheduler::gpsHandler, this); cloud_sub_ = node_handle_.subscribe<sensor_msgs::PointCloud2>("lidar_topic", 1, &Scheduler::cloudHandler, this); image_sub_ = node_handle_.subscribe("camera_topic", 5, &Scheduler::imageHandler, this); compressed_image_sub_ = node_handle_.subscribe("camera_topic", 5, &Scheduler::compressedImageHandler, this); location_pub_ = n.advertise<std_msgs::String>("topic_m",1000); }

7. 回调函数

void Scheduler::imuHandler(const sensor_msgs::Imu::ConstPtr& msg) { time = msg->header.stamp.toSec(); // acceleration Eigen::Vector3d acceleration(msg->linear_acceleration.x, msg->linear_acceleration.y, msg->linear_acceleration.z); // angular velocity Eigen::Vector3d angular_velocity(msg->angular_velocity.x, msg->angular_velocity.y, msg->angular_velocity.z); } void Scheduler::gpsHandler(const sensor_msgs::NavSatFix::ConstPtr& msg) { Eigen::Vector3d position(msg->longitude, msg->latitude, msg->altitude); } void Scheduler::cloudHandler(const sensor_msgs::PointCloud2ConstPtr& msg) { pcl::PointCloud<pcl::PointXYZI>::Ptr cloud; pcl::fromROSMsg(*msg, *cloud); } void Scheduler::imageHandler(const sensor_msgs::ImageConstPtr &msg) { double time_nsecond = msg->header.stamp.toNSec(); cv::Mat color_image; cv_bridge::CvImageConstPtr srcImage = cv_bridge::toCvShare(msg, sensor_msgs::image_encodings::RGB8); }

8. 服务器

bool add(beginner_tutorials::AddTwoInts::Request &req, beginner_tutorials::AddTwoInts::Response &res) { res.sum = req.a + req.b; ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b); ROS_INFO("sending back response: [%ld]", (long int)res.sum); return true; } ros::ServiceServer service = n.advertiseService("add_two_ints", add);

9. 客户端

ros::NodeHandle n; ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts("add_two_ints"); beginner_tutorials::AddTwoInts srv; srv.request.a = atoll(argv[1]); srv.request.b = atoll(argv[2]); if (client.call(srv)) { ROS_INFO("Sum: %ld", (long int)srv.response.sum); } else { ROS_ERROR("Failed to call service add_two_ints"); return 1; }

10. 参数服务器

参数服务器一般用两个函数getParam和param

getParam就是获取参数

std::string parameter; node_handle_.getParam<std::string>("param", parameter);

param使用时比较容易出错,因为它有两种使用方式

// 设置参数 node_handle_.param<std::string>("param", parameter); // 获取参数 node_handle_.param<std::string>("param", parameter, "parameters.xml");

11. 主函数

int main(int argc, char **argv) { ros::init(argc, argv, "node"); ros::NodeHandle node_handle("~"); ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Info); double time = ros::Time::now().toSec() // 获取系统时间 Scheduler scheduler(node_handle); scheduler.initialize(); scheduler.run(); return 0; }

12. 读包

rosbag::Bag bag; bag.open(bag_path, rosbag::bagmode::Read); //打开一个bag文件 rosbag::View view(bag); for (rosbag::View::iterator it = view.begin(); it != view.end(); ++it) { std::string topic = it->getTopic(); if (topic == raw_canbus_driver_topic_) { std_msgs::String::ConstPtr msg = it->instantiate<std_msgs::String>(); ProcessRawChassis(msg); } else { // do something } }

13. 写包

rosbag::Bag bag_file(output_file_path.string(),rosbag::bagmode::Write); ros::Duration duration(1.0 / 50); ros::Time time_stamp = ros::Time::now(); for (const WheelOdom &wheel_odom_msg : wheel_odom_carrier) { localization_msg::Proto msg; if (wheel_odom_msg.SerializeToString(&(msg.buf))) { msg.header.stamp = time_stamp; bag_file.write(config.wheel_odom_config.wheel_odom_topic, time_stamp, msg); } time_stamp += duration; }

参考文献

rosbag record录包(ROS入门学习笔记五)_文科升的博客-CSDN博客_ros 录包

ROS的学习(十六)用C++写一个简单的服务器(service)和客户端(client)_BigHerbert的博客-CSDN博客

ROS services (ros::advertiseService和ros::serviceClient)的简单demo_jack_20的博客-CSDN博客_advertiseservice

rostopic 只echo部分信息_泠山的博客-CSDN博客

ROS从入门到精通(一) ROS简介、安装与常见问题 - 知乎

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询