接着上一期,这一期进行DDS的安装以及ROS2工作区的创建,并通过DDS实现与PX4的通信。

1.安装 Micro XRCE-DDS Agent

1.1 安装依赖

sudo apt update
sudo apt install git cmake g++ build-essential libasio-dev libtinyxml2-dev -y

1.2 下载并编译 Agent

cd ~
git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
cd Micro-XRCE-DDS-Agent
mkdir build
cd build
cmake ..
make -j$(nproc)
sudo make install
sudo ldconfig

验证安装

MicroXRCEAgent --help

DDS到此就已经安装完成了,下一步,进行ROS2工作空间的创建,在此之前呢,先安装vscode的代码编辑器。

2.vscode安装

直接在ubuntu中的浏览器中,搜索vscode,并进行下载
下载地址(供参考):https://code.visualstudio.com/Download

下载完成后,使用sudo dpkg -i 进行安装:

出现该页面直接勾选Yes,然后回车即可:

安装完成:

接下来安装一些vscode的插件:

新打开一个终端,输入code,打开vscode:

在左侧边栏点击插件选项:

可在搜索栏中直接搜索插件安装,博主这值安装了三个插件:
1.中文包

2.C/C++

3.Python

后续插件可在使用过程中在进行添加,这里就不过多的记录了。安装完成后,重启vscode页面即变为中文显示:

现在,代码的编译工具也有了,接下来,

3.创建 ROS2 工作区和工程包

drone_drl(博主自己的工程包名称,根据自己的项目而定,这里只是做示范用)

3.1 创建工作区目录并进入该文件夹下:

mkdir -p ~/Drone_drl_ws/src
cd ~/Drone_drl_ws/src

此时,在主目录的文件夹下,可看到我们所建立的工程包:

3.2 创建 ROS2 C++ 包:drone_drl

此时如果提示找不到 px4_msgs 没关系,下面会克隆它。

此时,项目的结构如图所示:

~/Drone_drl_ws
  └── src
      └── drone_drl
          ├── CMakeLists.txt
          ├── package.xml
          ├── include/drone_drl/
          └── src/

3.3 克隆 PX4 消息定义包 px4_msgs

cd ~/Drone_drl_ws/src
git clone https://github.com/PX4/px4_msgs.git

现在,我们的工程包目录结构如下:

~/Drone_drl_ws/src
  ├── drone_drl
  └── px4_msgs

3.4 添加bashrc

打开新终端(博主这里使用nano编译器)

nano ~/.bashrc

在打开的页面中,滑到最底部,写入下面的两行(缺哪行写哪行即可):

source /opt/ros/humble/setup.bash
source ~/Drone_drl_ws/install/setup.bash

保存并退出(Ctrl+O 回车,Ctrl+X

让其立即生效:

source ~/.bashrc

出现下面的提示没关系,因为我们还没有开始编译工程包:

在工程包中配置vscode:

打开工作区:

code ~/Drone_drl_ws

在最开始的基础上,安装Cmake tools拓展包:

配置 IntelliSense 头文件路径:

在打开的vscode项目中,创建

.vscode文件夹:

在该文件夹下,创建c_cpp_properties.json:

在创建的文件中,写入以下内容(注意替换成自己的用户路径):

{
  "configurations": [
    {
      "name": "ROS2-Humble",
      "includePath": [
        "${workspaceFolder}/**",
        "/opt/ros/humble/include/**",
        "/home/z/Drone_drl_ws/install/px4_msgs/include/**"
      ],
      "defines": [],
      "compilerPath": "/usr/bin/g++",
      "cStandard": "c11",
      "cppStandard": "c++14",
      "intelliSenseMode": "linux-gcc-x64"
    }
  ],
  "version": 4
}

写入后,记得保存“ctrl+s”

接下来,创建一个px4_bridge节点代码(订阅PX4位置信息,仅作范例使用)

在Drone_drl_ws/src/drone_drl/src目录下,创建px4_bridge.cpp文件:

在文件中写入以下的范例代码:

#include "rclcpp/rclcpp.hpp"

// PX4 消息类型
#include "px4_msgs/msg/vehicle_local_position.hpp"
#include "px4_msgs/msg/offboard_control_mode.hpp"
#include "px4_msgs/msg/trajectory_setpoint.hpp"
#include "px4_msgs/msg/vehicle_command.hpp"

using namespace std::chrono_literals;

class Px4Bridge : public rclcpp::Node
{
public:
  Px4Bridge()
  : Node("px4_drl_bridge")
  {
    // === 使用与 PX4 匹配的 QoS(传感器数据,Best Effort) ===
    rclcpp::SensorDataQoS sensor_qos;

    // 订阅 PX4 本地位置话题
    local_pos_sub_ = this->create_subscription<px4_msgs::msg::VehicleLocalPosition>(
      "/fmu/out/vehicle_local_position",
      sensor_qos,
      std::bind(&Px4Bridge::localPositionCallback, this, std::placeholders::_1));

    // 预创建 Offboard 控制相关 publisher(后续 DRL 会用到)
    offboard_mode_pub_ = this->create_publisher<px4_msgs::msg::OffboardControlMode>(
      "/fmu/in/offboard_control_mode", 10);
    traj_sp_pub_ = this->create_publisher<px4_msgs::msg::TrajectorySetpoint>(
      "/fmu/in/trajectory_setpoint", 10);
    vehicle_cmd_pub_ = this->create_publisher<px4_msgs::msg::VehicleCommand>(
      "/fmu/in/vehicle_command", 10);

    // 控制定时器(当前只占位,后续可写 Offboard/DRL 控制逻辑)
    control_timer_ = this->create_wall_timer(
      100ms, std::bind(&Px4Bridge::controlLoop, this));

    RCLCPP_INFO(this->get_logger(),
                "Px4Bridge node started. Subscribing /fmu/out/vehicle_local_position");
  }

private:
  // 接收 PX4 本地位置的回调
  void localPositionCallback(const px4_msgs::msg::VehicleLocalPosition::SharedPtr msg)
  {
    RCLCPP_INFO_THROTTLE(
      this->get_logger(),
      *this->get_clock(),
      500,   // 每 500ms 打印一次
      "PX4 Local Position: x=%.2f, y=%.2f, z=%.2f, vx=%.2f, vy=%.2f, vz=%.2f",
      msg->x, msg->y, msg->z, msg->vx, msg->vy, msg->vz);

    // TODO:后续在此处将状态写入 DRL 的状态向量中
  }

  // 控制循环(未来用来做 Offboard 控制 / DRL 控制)
  void controlLoop()
  {
    // TODO:
    //  1. 周期性发布 OffboardControlMode(心跳)
    //  2. 根据 DRL 输出,发布 TrajectorySetpoint
    //  3. 必要时发布 VehicleCommand(解锁、上锁等)
  }

private:
  // 订阅 PX4 状态
  rclcpp::Subscription<px4_msgs::msg::VehicleLocalPosition>::SharedPtr local_pos_sub_;

  // 发布 Offboard 控制相关消息
  rclcpp::Publisher<px4_msgs::msg::OffboardControlMode>::SharedPtr offboard_mode_pub_;
  rclcpp::Publisher<px4_msgs::msg::TrajectorySetpoint>::SharedPtr  traj_sp_pub_;
  rclcpp::Publisher<px4_msgs::msg::VehicleCommand>::SharedPtr      vehicle_cmd_pub_;

  // 控制定时器
  rclcpp::TimerBase::SharedPtr control_timer_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  auto node = std::make_shared<Px4Bridge>();
  rclcpp::spin(node);
  rclcpp::shutdown();
  return 0;
}

代码写入后,保存,会看到编译器报错,提示找不到对应的头文件:

这个没关系,因为我们还没开始编辑Cmake文件,接下来,进行Cmake的编写:

配置 CMakeLists.txt(编译 px4_bridge

直接替换drone_drl目录下的CMakeLists.txt文件内容:

cmake_minimum_required(VERSION 3.5)
project(drone_drl)

# 使用 C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

# 依赖包
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(px4_msgs REQUIRED)

# 可执行文件:px4_bridge
add_executable(px4_bridge src/px4_bridge.cpp)
ament_target_dependencies(px4_bridge rclcpp px4_msgs)

# 安装可执行文件到 lib/drone_drl/
install(TARGETS
  px4_bridge
  DESTINATION lib/${PROJECT_NAME}
)

ament_package()

保存完后,在vscode中,使用终端,输入以下指令进行编译:

等待编译完成即可:

此时,我们的基础工程包已完成了基础的编译,下面就是运行包,测试所搭建的环境是否成功。

4.启动全集:Agent + PX4(gazebo-classic)+px4_bridge

4.1 打开终端1,启动启动 Micro XRCE-DDS Agent:

MicroXRCEAgent udp4 --port 8888

4.2  打开终端2 ,启动 PX4 SITL + Gazebo Classic:

cd ~/PX4-Autopilot
make px4_sitl gazebo-classic

此时,gazebo的页面打开,并显示无人机,同时DDS窗口也有了通信数据,此时,我们新打开一个窗口,输入以下代码,查看当前的无人机话题:

ros2 topic list

可以看到当前无人机的所有话题

下面有一个需要注意的点,在我们的示例代码中,我们使用的是:
/fmu/out/vehicle_local_position 这个话题
但在ros2 topic list打印的话题,话题变为了:

此时,我们需要修改我们的代码,将话题名改为一致,否则会找不到对应的话题名称:

将其改为:

改完代码后,保存,并重新编译:

编译完成后,打开终端3,运行我们的工程包:

ros2 run drone_drl px4_bridge

成功运行,即可看到以下的输出:

至此,我们的工程包已经监听到了当前无人机的位置信息,并且,px4+DDS的通信已完成大同,最基础的工程包已完成搭建。

 

下一步,博主将在无人机模型上,加入mid360激光雷达,并在项目中加入激光slam相应的算法,在ros2的基础上进行仿真验证。后续验证完成后,也会相应的更新在这里,各位同学,请期待下一期:ros2+px4+mid360激光雷达仿真

 

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐