ROS开发专栏---基于激光雷达的自动避障---适配Ubuntu 22.04

🎬 渡水无言 :个人主页渡水无言

❄专栏传送门 : 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》

❄专栏传送门 : 《freertos专栏》 《STM32 HAL库专栏》《linux裸机开发专栏》

❄专栏传送门 :《产品测评专栏》 《Ai智能体专栏) 《ROS开发专栏》

⭐️流水不争先,争的是滔滔不绝

📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生

| 省级优秀毕业生获得者 | csdn新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生

在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连

​

目录

前言

一、避障原理

二、避障程序流程框图

三、创建避障节点的代码实现

3.1、编写避障节点代码

3.2、编写CMakeLists.txt

[3.3、package.xml 依赖](#3.3、package.xml 依赖)

四、编译与运行

总结


前言

上一期博客我们实现了激光雷达数据读取的实验,本期博客我们本章我们将雷达数据 + 运动控制结合,实现机器人自动避障。为后续 SLAM 建图、自主导航打下基础。


一、避障原理

程序订阅雷达数据的"/scan"话题,从中接收激光雷达节点发来的sensor_msgs::LaserScan类型消息包,并解析出雷达测距值。根据雷达测距值让机器人做出反应:前方没有障碍物就前进,前方遇到障碍物就转向。如下图所示:

二、避障程序流程框图

订阅雷达数据:获取 /scan 话题的激光雷达数据,解析正前方障碍物距离

判断障碍物:

若前方距离 > 安全阈值(1.5m)→ 机器人保持前进

若前方距离 < 安全阈值 → 机器人原地左转,避开障碍物

发布速度指令:通过 /cmd_vel 话题控制机器人运动,实现 "遇障就转、无障就走"

三、创建避障节点的代码实现

我们直接在上一期的博客创建 lidar_pkg功能包中新增避障节点,无需新建包。

3.1、编写避障节点代码

在 lidar_pkg/src/ 目录下新建 lidar_avoid.cpp 文件,编写代码如下所示:

cpp 复制代码
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/laser_scan.hpp>
#include <geometry_msgs/msg/twist.hpp>

// 全局节点指针
std::shared_ptr<rclcpp::Node> node;
// 速度发布器
rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr vel_pub;
// 延时计数器,防止频繁抖动
int nCount = 0;

// 雷达数据回调函数
void LidarCallback(const sensor_msgs::msg::LaserScan::SharedPtr msg)
{
    // 获取雷达数据总数
    int nNum = msg->ranges.size();
    // 正前方索引
    int nMid = nNum / 2;
    // 正前方距离
    float fMidDist = msg->ranges[nMid];

    // 打印信息
    RCLCPP_INFO(node->get_logger(), "ranges[%d] = %f m", nMid, fMidDist);

    // 延时处理
    if (nCount > 0)
    {
        nCount--;
        return;
    }

    // 定义速度消息
    geometry_msgs::msg::Twist vel_msg;

    // 避障判断
    if (fMidDist < 1.5f)
    {
        // 左转避障
        vel_msg.angular.z = 0.3;
        nCount = 100;
    }
    else
    {
        // 直行
        vel_msg.linear.x = 0.1;
    }

    // 发布速度
    vel_pub->publish(vel_msg);
}

int main(int argc, char** argv)
{
    // 初始化ROS2
    rclcpp::init(argc, argv);

    // 创建节点
    node = std::make_shared<rclcpp::Node>("lidar_behavior_node");

    // 创建速度发布者
    vel_pub = node->create_publisher<geometry_msgs::msg::Twist>("/cmd_vel", 10);

    // 创建雷达订阅者
    auto lidar_sub = node->create_subscription<sensor_msgs::msg::LaserScan>(
        "/scan", 10, LidarCallback);

    // 循环等待回调
    rclcpp::spin(node);

    // 关闭ROS2
    rclcpp::shutdown();

    return 0;
}

3.2、编写CMakeLists.txt

编写代码如下:

cpp 复制代码
cmake_minimum_required(VERSION 3.8)
project(lidar_pkg)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)

# 编译雷达数据获取节点
add_executable(lidar_data src/lidar_data.cpp)
ament_target_dependencies(lidar_data
  rclcpp
  sensor_msgs
)

# 编译避障节点
add_executable(lidar_behavior src/lidar_behavior.cpp)
ament_target_dependencies(lidar_behavior
  rclcpp
  sensor_msgs
  geometry_msgs
)

# 安装节点
install(TARGETS
  lidar_data
  lidar_behavior
  DESTINATION lib/${PROJECT_NAME}
)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  set(ament_cmake_copyright_FOUND TRUE)
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

3.3、package.xml 依赖

添加一行<depend>geometry_msgs</depend>,全部代码如下所示:

cpp 复制代码
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>lidar_pkg</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="duan@todo.todo">duan</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <depend>rclcpp</depend>
  <depend>sensor_msgs</depend>
  <depend>geometry_msgs</depend>


  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

四、编译与运行

编译功能包并运行仿真程序

cpp 复制代码
cd ~/ros2_ws
colcon build
source install/setup.bash
ros2 launch wpr_simulation2 wpb_simple.launch.py

打开第二个终端

运行避障节点

cpp 复制代码
ros2 run lidar_pkg lidar_behavior

节点运行起来之后,切换到刚才的仿真窗口。如图所示,可以看到机器人先以0.1米/秒的速度向前移动。当机器人距离书柜1.5米时,机器人停止前进,开始向左逆时针旋转。旋转一段时间后,机器人恢复直行,顺利的避开前方的书柜。


总结

本期博客完成了 ROS2 激光雷达自动避障 的完整实现,通过订阅 /scan 雷达数据、解析障碍物距离、结合 /cmd_vel 速度控制,实现了一套简单可靠的自主避障系统。

相关推荐
用户05101225729614 小时前
RGA(二)——RK3588 的核拓扑与能力差异
linux·嵌入式
用户05101225729614 小时前
RGA(一)——基础知识
linux·嵌入式
用户05101225729614 小时前
RGA(三)——实宽高、虚宽高与对齐约束
linux·嵌入式
燕卫博15 小时前
SSD201 BSP 开发教程
嵌入式·bsp·ssd201
一直C15 小时前
【嵌入式 ARM 驱动开发】PWM 脉宽调制原理与 GT9147 电容触控屏驱动开发详解
嵌入式硬件·lcd·嵌入式·arm汇编·imx6ull·cortex-a7
haliu16 小时前
【FHE 同态加密】我们如何实现同态加密推理(十四):为什么 `RESULT=PASS` 不是判据(纯 C11 · 零依赖)
人工智能·嵌入式·c·fhe·推理引擎·c11·边缘推理·同态加密推理
jianqiang.xue1 天前
【CStackGUI 实战】深色主题终端:app.dark 默认深色 + 顶层命名样式表 + 运行时切换
单片机·嵌入式·cstackgui·c语言gui·可视化拖拽
追涨杀跌老能手1 天前
GD32H759 + RT-Thread 工控实战--第7篇 OSPI Flash
开源·嵌入式
凉、介1 天前
深入理解 ARM SCP Firmware 的 Event 与 Notification 机制
学习·scp·嵌入式·arm
jianqiang.xue2 天前
【CStackGUI 实战】采集记录器:模拟采集 + 双曲线 + CSV 落盘 + 回放
单片机·嵌入式·cstackgui·c语言gui·可视化拖拽