尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ROS四旋翼开发实战:工程文件框架与功能包职责全解析

ROS四旋翼开发实战:工程文件框架与功能包职责全解析 上一讲我们把仿真起飞到悬停的流程跑通了很多同学在群里问代码文件为什么这么放每个功能包到底负责干什么如果自己加一个算法该往哪里塞这篇就专门把整个工作环境从文件层面拆开来讲把每个目录、每个功能包的职责讲透。先说明一下适用场景这套框架对应的是典型的中小型四旋翼二次开发项目基于ROS以Noetic为主兼顾Melodic加Gazebo仿真环境飞控用PX4/ArduPilot这类开源方案机载计算机用NVIDIA Jetson或工控机。不管你是刚把ROS装好准备跑通第一个demo还是已经在改代码但是被各种包依赖绕晕了这篇内容都适合用来当一份案头参考。1. Ros工程的整体设计为什么文件要这么摆搞清楚文件框架之前得先明白ROS工程的组织哲学。ROS不是一个大而全的软件它天生就是“一堆小进程通过话题和服务互相通信”的架构。这个架构天然逼迫你把功能拆开——你的四旋翼系统的通信模块、控制模块、感知模块、任务模块本身就是相对独立的ROS只是把这个“天然独立”结构化成了工作空间。对于四旋翼项目来说文件框架的规划直接影响三个东西编译效率、多机协作的可维护性、以及团队分工的清晰度。很多人图省事把所有节点写进一个包里初期跑demo没问题一旦涉及多传感器融合、多机编队或者换飞控硬件就会陷入“改一行代码重新编译半个小时”的噩梦。1.1 核心需求解析在动手搭工作空间之前先把四旋翼项目必然涉及的基础模块列一遍通信与驱动模块与飞控通信Mavlink/MAVROS、底层传感器驱动GPS、IMU、激光雷达、相机仿真模块无人机模型、环境模型、传感器模型、Gazebo仿真插件状态估计与定位模块姿态、速度、位置估计视觉/激光SLAM或里程计控制模块内外环控制、位置/速度/姿态控制、自稳、特定轨迹跟踪任务规划模块路径规划、航线管理、任务状态机、应急逻辑工具与基础库消息定义、通用数学库、DEBUG与可视化工具这些模块不是互相孤立的它们之间通过ROS话题和服务连接。文件框架规划得好就是把这些模块的“边界”先切清楚不同的包放在独立的目录下、定义稳定的接口、避免循环依赖。1.2 为什么用Catkin工作空间ROS开发中Catkin是目前主流的工作空间构建系统。很多人问为什么不用ROS 2的Ament或者直接把代码放在IDE里编译答案是生态。目前四旋翼相关的绝大多数开源功能包、Mavlink工具链、Gazebo插件还是以Catkin为主你这个项目只要不是从零起步必须兼容ROS 1生态。Catkin工作空间的核心逻辑是“源码、编译产物、环境变量”三者分离src放源代码build放编译中间文件devel放编译出来的可执行文件、库文件、配置和脚本这个分离不只是为了整洁更关键的是你可以随时把build和devel目录删掉重新编译源码不受影响。实际开发里我经常“rm -rf build devel”之后重新catkin_make这种做法在做版本升级、改CMakeLists、切换分支之后几乎是日常操作没有这个隔离机制源码目录会很快被污染。2. 工作空间目录的完整解剖2.1 src目录所有源码的家src目录是开发者最常打交道的。很多人直接建一个src目录然后把所有功能包往下一扔短期内没什么问题但项目一旦达到10个包以上就需要在src内部再做分组。我在项目里习惯这样组织src/ ├── CMakeLists.txt ├── uav_bringup/ # 启动文件总入口 ├── uav_driver/ # 驱动层 │ ├── mavros_wrapper/ │ ├── gps_driver/ │ └── lidar_driver/ ├── uav_control/ # 控制层 │ ├── attitude_control/ │ ├── position_control/ │ └── controller_pkg/ ├── uav_estimation/ # 状态估计层 │ ├── ekf_fusion/ │ └── visual_odom/ ├── uav_planning/ # 规划层 │ └── path_planner/ ├── uav_sim/ # 仿真层 │ ├── uav_model/ │ ├── uav_gazebo/ │ └── sim_bridge/ ├── uav_msgs/ # 自定义消息 └── uav_utils/ # 外部依赖库封装这种分组的核心好处在于依赖方向是单向的底层驱动不会依赖上层控制逻辑控制层不会依赖任务层。如果哪天要换飞控协议只需要改驱动层其他层的代码基本不动。我踩过的最大坑就是一开始图省事把控制逻辑和Mavlink通信写在一个包里后来从PX4换到ArduPilotmavlink心跳的包名和话题结构变了把控制层连带改了一个星期。2.2 CMakeLists.txt工作空间的“总绳”src目录下有一个顶层CMakeLists.txt这是Catkin工作空间编译的入口。它通常只有几行作用是通过add_subdirectory风格把各个功能包纳入编译体系。很多人忽略这个文件的作用导致新加的包不参与编译。实际上Catkin会通过find_package机制自动发现工作空间内的包但如果在某些环境下手动添加了独立包就需要显式在顶层CMakeLists.txt里处理。最常见的命令是catkin_make # 或指定源码目录 catkin_make --source src编译完成后需要source devel/setup.bash才能让当前终端找到这些包。这条命令建议写入~/.bashrc否则每次新开终端都会报“Package not found”。注意setup.bash有顺序问题如果系统同时装了ROS 1和ROS 2必须先source ROS 1的setup.bash再source工作空间的setup.bash顺序反了会直接导致环境变量打架。2.3 build与devel目录理解编译产物的生命周期build目录存放编译过程的中间文件包括CMake缓存、各种Makefile、编译日志。这个目录基本不需要主动修改但它有几个重要用途查看CMakeCache.txt可以排查依赖库搜索路径问题编译失败时build目录下的日志是最直观的定位依据devel目录存放“可运行版本”的可执行文件和库。它不是最终安装目录只是把编译结果集中起来供当前开发环境使用。最终部署时可以用catkin_make install生成install目录把可执行文件、头文件、配置打包起来。但日常开发阶段用devel就够了它可以配合setup.bash实现“修改代码-重编译-立即生效”的开发循环。这里有一个很实用的经验如果你改了某个包的CMakeLists.txt但是没有改任何代码重新catkin_make可能不会生效。这时候不要慌找到build目录下对应包的子目录手动删除该子目录再编译或者直接在所有代码编译前加一个--pkg参数只编译指定包catkin_make --pkg uav_control这条命令在调试一个包时特别省时间不用每次全量编译。缺点是这样的增量编译偶尔会漏掉一些消息生成步骤所以全量编译出现问题的时候该全量还是要全量。3. 功能包的分类与整体职责功能包是ROS开发的最小单元在包内部有package.xml描述依赖关系有CMakeLists.txt定义编译规则。四旋翼项目的功能包种类比较多但万变不离其宗包的边界应该和“功能边界”保持一致。3.1 驱动层功能包帮系统感知和通信驱动层是离硬件最近的一层职责是把飞控、传感器、执行机构的原始数据接入ROS体系。最常见的几个驱动包Mavros与Mavlink通信包mavros是四旋翼和飞控之间的灵魂通信桥。它通过串口、USB或UDP与PX4/ArduPilot通信把飞控输出的姿态、速度、位置等状态翻译成标准的ROS话题同时把机载计算机的指令发给飞控。它的核心配置文件是config目录下的px4config.yaml、apm_config.yaml等里面定义了Mavlink消息和ROS话题的映射、坐标系变换、传感器数据是否启用等。实际配置里需要注意连接方式的选择USB直连选/dev/ttyACM0或者/dev/ttyUSB0PX4 SITL仿真选择UDP端口14550真实PX4硬件通过UART接入时还需要设置飞控端和机载端的波特率一致。mavros常见的坑是启动后没有任何话题输出排查思路首先看飞控是否输出Mavlink心跳接着检查端口权限Linux下串口设备经常需要将当前用户加入dialout用户组。传感器驱动包包括激光雷达驱动、相机驱动、GPS驱动等。这类包的作用大同小异无非是把原始数据解析成ROS点云话题、图像话题或GPS的NavSatFix消息。需要注意传感器驱动包和算法包解耦——驱动包只管数据采集和发布不做任何算法处理。这样在更换同类型传感器时只需要修改驱动包的参数算法层不用动。下面是一个典型的lidar驱动launch文件简化示例launch node namelidar_node pkgurg_node typeurg_node outputscreen param nameserial_port value/dev/ttyUSB0/ param nameserial_baudrate value115200/ remap fromscan to/lidar/scan/ /node /launch注意端口名不要写死用udev规则为不同传感器分配固定别名例如/dev/sensors/lidar、/dev/sensors/gps。这种做法在四旋翼上电和USB设备插入顺序变化时非常有用否则你每次开机都要重新确认哪个设备节点对应哪个传感器。3.2 状态估计与定位层功能包搞清楚“我在哪”状态估计是四旋翼真正飞稳的关键层。飞控内部有自己的姿态估计但机载计算机一旦要做更高层的自主飞行和导航就需要把飞控外部的传感器数据融合进来得到更准确的姿态、位置和速度估计。典型的包有EKF融合包融合IMU、GPS、气压计、视觉里程计输出全局定位视觉SLAM包基于单目或双目相机完成视觉里程计常见开源方案有ORB-SLAM3、VINS-Fusion激光定位包基于激光的2D/3D SLAM比如cartographer、loam系列这一层的文件设计要点是确认坐标系关系。四旋翼涉及多个坐标系机体系body、世界系/ENU系world、地图系map、里程计系odom。每加一个传感器都要想清楚它输出的是哪个坐标系下的量、是否经过了外参标定。否则即使是同一个位置两个传感器输出的坐标相减就引入一个很大的固定偏差融合出来的状态会奇怪地漂移。这里有一个非常容易踩的坑坐标系约定不一致。飞控PX4/ArduPilot用的是NED北东地坐标系而ROS默认是ENU东东北上坐标系。mavros在中间做了变换但如果你直接在代码里拿飞控数据做导航算法不确认坐标变换飞机会出现“向前飞却斜着走”这种诡异现象。处理办法是使用mavros提供的mavros::setpoint_position和mavros::local_position话题时严格按照任务类型选择数据接口不要混用mavros里的世界系、机体系统话题。3.3 控制层功能包让四旋翼循规蹈矩四旋翼的控制包是整个项目中最需要谨慎对待的部分。常见方案是分内外环内环控制姿态角速度外环控制位置和速度。如果只是做仿真和简单自主飞行直接用PX4/ArduPilot自带的位置控制器就够但做精细的轨迹追踪、编队或者特殊飞行动作时机载端往往需要跑一个独立的位置控制器通过mavros把位置/速度设定值发给飞控。控制层依赖“模型”的地方很多。如果你的控制器用到了四旋翼的转动惯量、质量、电机时间常数等参数这些参数在真实飞机和仿真模型里可能相差很大。我建议在文件框架中单独划分一个uav_params/目录专门存放不同飞机型号的参数文件并通过launch文件动态加载不要硬编码在代码里。后面换飞机或做半物理仿真时只需要修改参数文件不用重新编译。控制器包的输出一般会接mavros的/mavros/setpoint_position/local或/mavros/setpoint_raw/attitude这类话题。这里的要点是区分“控制器输出”和“控制器输入”的接口消息类型输入可能是期望位置和期望速度输出可能是期望姿态或期望推力。搞混了这两个消息四旋翼要么失去控制要么进入非预期的失控状态。实际操作中我见过太多人用setpoint_position/local却往里面填姿态数据导致飞控不响应。注意控制包是安全敏感代码。我建议所有加入控制包的文件都在文件头注明“此文件属于实时控制链路请勿阻塞线程”之类的警告并把控制循环单独放一个优先级较高的线程避免被日志打印、网络通信阻塞。3.4 任务规划层与行为决策包“接下来做啥”规划层是四旋翼“智能”的体现。它负责根据当前状态和目标点计算接下来要走哪条航道或者执行什么任务。典型的包是路径规划器和任务状态机。路径规划器输出一系列航点或速度引导量交给控制层执行。任务状态机则管理整个飞行的行为切换起飞、降落、悬停、巡航、返航、失控保护。规划层的文件设计建议把所有可能切换的状态枚举写在一个mission_state.h里并在状态机里把异常状态显式列出。比如“电量不足”、“定位失效”、“通信丢失”这些异常必须提前规划好对应的紧急行为。不要等到日志里报错再去查。我还强烈建议在规划层加一个“仿真-真机模式切换”的开关。例如launch参数传入sim_mode:true时使用Gazebo中的状态话题sim_mode:false时切换到真实传感器话题。这样可以先在地面站看仿真脚本跑通全流程再切到真机试飞而不用改动任何算法代码。3.5 仿真层与虚拟环境包本系列教程前两讲跑的就是Gazebo仿真环境。仿真层的功能包包括无人机模型描述文件URDF/XACRO、传感器模型摄像头、激光雷达、IMU、仿真世界模型和插件。它的作用是抽象出真实硬件的接口让上层代码不区分仿真和真实环境。Gazebo环境里要注意的是插件路径和模型库路径。很多人spawn_model失败往往是因为没有把模型目录加入GAZEBO_MODEL_PATH环境变量。常见做法是在启动脚本最前面export一下export GAZEBO_MODEL_PATH$GAZEBO_MODEL_PATH:$(rospack find uav_gazebo)/models在文件框架设计上仿真层虽然不属于最终机载运行环境但它的目录结构必须和真实环境保持一致。也就是说仿真里的话题名称和消息类型必须和真机一一对应否则你在仿真里调的算法搬到真机时通通要改话题名这等于白做了一遍仿真。4. 深入launch文件与参数配置launch文件在四旋翼项目中扮演“一键启动”的角色。它把无数个节点、参数、配置、坐标变换集中调起来。偏偏这个文件看似简单实际坑最多。4.1 launch文件的结构与职责划分一个标准的多机launch文件通常分三层顶层launch调用下层launch设置全局参数例如要不要启动仿真、GPS是否可用、日志记录级别等中间launch负责一类节点的集合例如启动传感器层、启动控制层底层launch启动单个或少量节点配置节点专属参数这里给一个简化的顶层launch示意launch arg namesim_mode defaulttrue/ arg nameuav_id default1/ group if$(arg sim_mode) include file$(find uav_sim)/launch/sim_world.launch/ /group include file$(find uav_bringup)/launch/driver.launch arg nameuav_id value$(arg uav_id)/ /include include file$(find uav_control)/launch/control.launch arg namesim_mode value$(arg sim_mode)/ /include /launch传参和复用是launch文件的精髓。不要在一个launch文件里写死所有数字尽量用arg传参。尤其是uav_id这类参数多机编队时同一个launch文件通过传不同id就可以拉起多架飞机不需要复制粘贴一堆launch文件。4.2 参数配置yaml的命名与加载最佳实践四旋翼项目的参数往往非常多PID控制器参数、滤波器参数、传感器噪声参数、导航坐标系偏移等。我见过很多人把参数直接写在源码并硬编码这个习惯一定要改。ROS提供动态参数配置机制可以让参数在运行时通过rqt_reconfigure实时调节这在调试控制效果时几乎是救命级功能。参数文件建议放在每个包内部的config/目录下命名规则采用“项目-载体-用途”三段式例如uav_control/config/px4_target/position_pid.yaml。这样在多机多机型场景中不会搞混。一个经验是控制频率和话题超时参数必须写在配置文件里而且要有默认值。控制器的输入话题如果在200ms内没有更新必须做安全处理比如自动切换为悬停或降落。这个“数据老化保护”参数如果硬编码在代码里换一个机型时改起来很容易漏后果是定位丢了但飞控还在傻傻地指望新数据轻则剧烈抖动重则炸机。4.3 坐标系与静态变换的管理四旋翼工程中最容易乱的槽点是TF坐标系。机载计算机上跑多个算法时每个算法都有自己期望的坐标系输入。推荐的做法是在launch文件中用static_transform_publisher显式声明所有传感器坐标系和机体系之间的外参关系。举一个实例激光雷达安装在无人机底盘下前方外参是从机体中心到雷达中心的平移和旋转。如果用固定安装在launch里写node pkgtf2_ros typestatic_transform_publisher namelidar_tf args0.05 0.0 -0.1 0 0 0 base_link laser_link /注意旋转量的顺序是“偏航、俯仰、滚转”不同版本的TF工具有时需要用四元数表示很容易写反。我一贯的做法是先在rviz里用Fixed Frame设为base_link观察点云和模型是不是重合如果重合再继续下一步算法开发。5. 环境搭建与工作空间初始化实录很多读者是从“ROS安装”这个关键词找到本系列文章的。这里结合我用的最多的“一键安装”方式来演示从零搭建四旋翼工作环境。5.1 用镜像脚本快速完成ROS安装“鱼香ROS一键安装”是ROS社区里广泛使用的一套自动化安装脚本它的本质是自动换源、自动安装ROS本体和常用依赖、自动配置环境变量。对于国内网络环境来说这套脚本能省去很多手敲命令和反复换源的痛苦特别适合装在虚拟机或没有代理的实验室机器上。安装命令大致是wget http://fishros.com/install -O fishros . fishros执行后会弹出一个选择菜单通常选“1”或“2”对应ROS 1或者ROS 2再按提示选择桌面版或基础版。如果是给四旋翼项目准备环境建议选桌面完整版因为后面Gazebo、rviz、rqt这些工具链都会用到零散安装很容易漏依赖。需要注意的是脚本适合在刚装好Ubuntu、干净的系统上执行。不要一开始就装一堆别的软件再去跑脚本源替换可能会受影响。另外Ubuntu版本要和ROS版本严格对应Ubuntu 18.04对应ROS MelodicUbuntu 20.04对应ROS NoeticUbuntu 22.04对应ROS 2 Humble。四旋翼老项目多数还在ROS 1 Noetic环境下本系列的基础环境默认按Noetic讲。5.2 创建四旋翼项目工作空间安装完ROS后初始化工作空间非常简单mkdir -p ~/uav_ws/src cd ~/uav_ws catkin_make执行完catkin_make之后工作空间里自动多出build和devel目录。紧接着source环境echo source ~/uav_ws/devel/setup.bash ~/.bashrc source ~/.bashrc这一步做完用rospack find验证包路径是否指向自己的工作空间rospack find mavros如果返回的是/opt/ros/noetic/share/mavros说明mavros是系统安装的如果后续你自己的工作空间里有同名包返回的路径会变成~/uav_ws/src/...。这个细节可以快速判断当前终端的工作空间是否生效。5.3 功能包依赖管理快速补齐四旋翼项目常见的功能包依赖包括mavros、mavlink、gazebo_ros、gazebo_plugins、controller_manager、joy、geographic_info、robot_localization等。一个比较高效的做法是先在package.xml里写清依赖然后用rosdep自动安装rosdep update rosdep install --from-paths src --ignore-src -r -y如果在国内执行rosdep经常卡在下载资源上可以手动把缺的包用apt逐个补齐。下面是控制类项目最常见的几个sudo apt install ros-noetic-mavros ros-noetic-mavros-extras sudo apt install ros-noetic-gazebo-ros-pkgs ros-noetic-gazebo-ros-control sudo apt install ros-noetic-robot-localization ros-noetic-gps-common sudo apt install ros-noetic-tf2-geometry-msgs ros-noetic-eigen-conversions安装mavros后还要下载地理数据文件否则启动时会提示找不到geographiclib数据。这句是很多初学者卡住的地方sudo /opt/ros/noetic/lib/mavros/install_geographiclib_datasets.sh这一步会下载一系列地球模型数据文件如果网络不好可能中途失败失败后重新执行即可属于幂等操作。6. 编译踩坑与疑难排查实录6.1 “程序包找不到”的全链路排查如果你编译或运行自己的包时报Could not find a package configuration file provided by mavros有80%的概率是环境变量没生效。先检查echo $ROS_PACKAGE_PATH正常输出应该包含/opt/ros/noetic/share:/home/用户名/uav_ws/src。如果没有包含自己的工作空间说明setup.bash没被source。这时候执行source ~/uav_ws/devel/setup.bash还有一种情况当前终端是ROS 2环境ROS 1包自然找不到这时候需要检查ROS_DISTRO环境变量。多版本ROS并存的环境建议把不同版本的环境加载写成独立的别名不要都塞进.bashrc。6.2 编译时“未定义引用”和依赖缺失C编译报“undefined reference to”是四旋翼项目里的常客尤其集中在Eigen、OpenCV、PCL这类库上。原因是CMakeLists里链接的库和头文件版本不匹配。例如Eigen只有头文件如果你用了find_package(Eigen3 REQUIRED)但在CMakeLists中忘了include_directories(${EIGEN3_INCLUDE_DIR})编译时头文件能飘过但链接时基本必炸。另一个经典问题OpenCV 3和OpenCV 4混用。ROS Noetic默认带OpenCV 4但有些旧代码按OpenCV 3写。编译不过时优先用grep -r “opencv” CMakeLists.txt查看有没有写死路径然后统一改成find_package(OpenCV REQUIRED)加系统默认版本尽量不要手动指定lib路径。6.3 ROS运行时的“话题空转”问题节点能启动但rostopic echo /mavros/state没有数据。这个问题的排查顺序是固定的先看飞控是否在发心跳用mavlink地面的控制台或串口调试工具确认再看端口是否被占用ls -l /dev/ttyACM*查看设备是否存在并有权限最后看mavros是否被正确的连接类型启动排查fw参数是不是设对了如果手动rostopic list能看到话题但频率是0多半是连接通了但数据格式不匹配检查波特率、校验位和停止位尤其是波特率真机接USB转串口时飞控端和mavros端的波特率不一致是最容易被忽略的问题。仿真环境虽然没有串口问题但要注意UDP端口冲突——如果你同时开了两个mavros节点连接同一个端口后启动的会把先启动的连接挤掉。6.4 仿真崩溃与模型不加载Gazebo在加载四旋翼模型时崩溃最可能的原因是模型里用到了某个未安装的插件例如libhector_gazebo_plugins.so之类。排查方法是启动Gazebo时加上verbose参数gazebo --verbose或者直接看~/.gazebo/log/下的日志。插件路径问题一般在启动时就会打印“Failed to load plugin”的提示。解决思路是安装对应的插件包或者把模型里不需要的传感器插件注释掉。还有一类情况是模型加载成功但视野全黑这多半是Gazebo的GUI环境问题常见于虚拟机。这时候把guitrue/gui改为false用rviz来看画面效率还更高。6.5 多机场景下的端口与命名空间冲突项目做到一定规模很多人会开始做多机仿真。多机环境最痛苦的是命名空间和通信端口冲突。在一个Gazebo里拉3架无人机时如果每架飞机的话题都叫/mavros/local_position/pose后启动的主机就会把前一个顶掉。解决办法是给mavros和所有算法包都加上命名空间前缀在launch里用ns或者给每个节点设置__ns参数。我自己的习惯是从mavros的启动文件开始就预留uav_id参数。每架飞机的所有话题都挂在/uav0/、/uav1/这样的命名空间下监控和调试工具用--ns指定命名空间去监听对应飞机。这样的设计在后面扩展到实际机队时不会产生“代码里到处是硬编码无人机编号”的问题。7. 功能包开发时的文件组织规范建议功能包内部的组织同样要有规矩。我通常在每个包里固定维护这些子目录include/公共头文件src/C源文件launch/启动文件config/参数与配置文件msg/和srv/自定义消息和服务urdf/或xacro/模型描述rviz/rviz保存的视角配置scripts/Python节点或辅助脚本一个很多人忽略的细节是节点代码里的日志打印要有统一的模块前缀。例如控制包里的节点统一在ROS_INFO和ROS_ERROR前加[control]标识驱动包加[driver]这样多机运行的时候能一眼看出日志来自哪个模块。在四旋翼这种强实时、高安全要求的系统里日志可读性直接影响排障效率一条清晰的日志比几百句注释管用得多。另外我强烈建议从项目一开始就引入.gitignore把build、devel、install这些目录排除在版本管理之外。这个习惯能在团队协作时省掉无数因为编译产物冲突引起的麻烦。7.1 消息定义与版本管理四旋翼项目中自定义msg服务强烈建议单独放在一个包里比如前面提到的uav_msgs。不要在多个包中重复定义类似的消息后面改字段时会非常痛苦。消息修改涉及所有调用方因此要格外谨慎尤其是消息字段变更后需要同步更新所有依赖包并重新编译这个成本经常被低估。消息字段的类型选择也要考虑字节对齐和带宽。真实无人机的机载通信链路可能是数传电台带宽有限。能用float32的地方就不要用float64能用一个消息打包的状态就不要拆成多个话题。实际测试中50Hz的里程计话题和50Hz的IMU话题如果分开发布链路的调度开销远大于打包成一个消息带来的收益。7.2 启动脚本与自动部署开发到后期单纯依赖launch文件可能不够。我一般会额外写一个start_uav.sh脚本完成环境检测、设备检查、日志目录创建、工作空间source、launch启动这几步#!/bin/bash set -e echo Checking workspace... if [ ! -d $HOME/uav_ws/devel ]; then echo Build directory not found, building... cd $HOME/uav_ws catkin_make fi source $HOME/uav_ws/devel/setup.bash export GAZEBO_MODEL_PATH$GAZEBO_MODEL_PATH:$(rospack find uav_gazebo)/models mkdir -p $HOME/uav_logs roslaunch uav_bringup start.launch sim_mode:$1这个脚本配合chmod x就可以作为开发机和地面站上的一键启动入口。实时飞行时还可以再加一句记录rosbag的命令把关键话题都录下来方便后续分析。8. 从文件框架到实际工程我的最终体会这套工作环境与功能包的划分思想本质上是在用ROS的组织方式约束四旋翼系统各模块的边界。文件目录不是摆着好看的它是在帮你对抗无人机开发中最大的敌人——复杂度。真机试飞的时候一旦飞机出现异常你要能在10分钟内定位到是底层通信、状态估计、控制参数还是任务逻辑的问题这全靠前期目录规划和包设计的清晰程度。我个人经过这几个项目之后的体会是别一上来就追求代码算法层面的花活先把文件框架打磨稳当每个包只干一件事所有接口清晰可见后面调试控制算法、接入新传感器、扩展到多机编队都会顺滑很多。相反如果一开始不重视组织架构后面会在无限循环的“改一个参数导致另外一个地方报错”里面消耗掉大量时间。如果你正在照着本系列教程一步步搭建你的第一套四旋翼环境我建议你先把工作空间目录建立好再逐个添加功能包每添加一个就编译一次、验证一次话题不要一口气把所有代码堆进去再统一调试。这应该就是我们常说的“小步快跑”在无人机这种系统上尤其适用因为错误被分隔得越小越容易定位。下一讲我准备专门讲mavros话题与飞控状态数据的具体读法包括怎么从飞控读取姿态、位置、速度以及如何区分mavros里那几个高度相似却容易用混的坐标话题那是很多飞行控制逻辑异常的总根源。
返回列表