4、位置控制基础:setpoint位置控制、速度控制、加速度控制、坐标系(NED/ENU)理解

各位同学,欢迎来到第四讲。今天咱们聊点实在的——怎么让无人机按照你想要的轨迹飞。

说白了,位置控制就是告诉飞机「你去哪儿、怎么去、多快去」。我刚开始接触MAVSDK时,觉得这玩意儿不就是发个坐标嘛,结果第一次试飞差点把飞机怼树上。嗯,这里面的门道,咱们今天一条条捋清楚。

4.1 坐标系:NED和ENU,别搞混了

先讲坐标系。为什么?因为坐标系搞错了,你发的指令飞机根本听不懂。

我个人习惯把坐标系想象成「地球的骨架」。无人机所有的位置、速度、加速度,都得在这个骨架里定义。

4.1.1 NED坐标系(北东地)

NED是无人机行业的老标准。你看它的名字:

  • X轴:指向北(North)
  • Y轴:指向东(East)
  • Z轴:指向地(Down),也就是向下为正

等等,Z轴向下为正?对,你没看错。这意味着高度越高,Z值越小。比如海平面是0,飞高10米,Z就是-10。

⚠️ 我曾经踩过的坑: 第一次用NED时,我习惯性地把高度设成正数,结果飞机直接往地里钻。还好高度设得不高,油门推得快。记住:NED下,向上飞是负Z!

4.1.2 ENU坐标系(东东北)

ENU是另一个常见坐标系,ROS和很多地面站喜欢用这个:

  • X轴:指向东(East)
  • Y轴:指向北(North)
  • Z轴:指向上(Up),向上为正

你看,ENU的Z轴向上为正,这更符合我们日常直觉。飞高10米,Z就是10。

为什么会存在两套坐标系?说白了,历史原因。NED是航空航天的老传统,ENU是机器人领域后来推的。MAVSDK默认用NED,但很多API也支持ENU转换。

💡 我的建议: 如果你在写地面站或者和ROS交互,用ENU。如果只是控制无人机飞行,用NED更稳妥,因为PX4固件底层就是NED。

4.2 setpoint位置控制:告诉飞机「去哪儿」

位置控制是最直观的。你给一个目标点,飞机自己飞过去。

在MAVSDK里,位置控制的核心是setpoint_position。看代码:

// C++示例:发送位置setpoint
Telemetry::Position current_pos = telemetry->position();
SetpointPosition setpoint;
setpoint.target_ned_frame.x = current_pos.north_m + 10.0f;  // 向北10米
setpoint.target_ned_frame.y = current_pos.east_m + 5.0f;   // 向东5米
setpoint.target_ned_frame.z = current_pos.down_m - 2.0f;   // 向上2米(注意NED的Z)
setpoint.yaw_deg = 0.0f;                                    // 机头朝北

offboard->set_position(setpoint);

这段代码的意思是:让飞机从当前位置,向北10米、向东5米、向上2米,机头朝北。

你想想看,这其实就是一个「点到点」的移动。飞机内部会自己算路径、调姿态、控油门。你只需要告诉它终点就行。

🔧 实战技巧: 位置控制适合「去某个点执行任务」,比如飞到A点拍照,再飞到B点投递。但如果你想让飞机走一条平滑的曲线,位置控制就不够用了——这时候需要速度控制。

4.3 速度控制:告诉飞机「怎么去」

速度控制,说白了就是给飞机一个速度矢量,让它按这个速度飞。

我遇到过这样一个场景:需要让无人机沿着一条河道匀速飞行,拍摄河岸两侧。如果用位置控制,你得每隔几米发一个点,飞起来一顿一顿的。用速度控制就顺滑多了。

// C++示例:发送速度setpoint
SetpointVelocity velocity;
velocity.target_ned_frame.vx_m_s = 5.0f;   // 向北5m/s
velocity.target_ned_frame.vy_m_s = 0.0f;   // 向东0m/s
velocity.target_ned_frame.vz_m_s = 0.0f;   // 垂直方向0m/s(保持高度)
velocity.yaw_deg = 0.0f;

offboard->set_velocity(velocity);

这段代码让飞机以5m/s的速度向北飞,高度不变。飞机自己会保持这个速度,直到你发新的指令。

注意:速度控制下,飞机不会自动停。你如果不发一个零速度指令,它会一直飞下去。嗯,这个要小心,我曾经在测试时忘了发停止指令,飞机差点飞出视距。

4.4 加速度控制:告诉飞机「多快去」

加速度控制更底层。你直接控制飞机的加速度,相当于控制了力。

说实话,加速度控制在日常开发中用得不多。它更多用在科研或者特殊场景,比如需要精确控制飞行轨迹的平滑度、或者做碰撞规避时。

// C++示例:发送加速度setpoint
SetpointAcceleration accel;
accel.target_ned_frame.ax_m_s2 = 2.0f;   // 向北加速2m/s²
accel.target_ned_frame.ay_m_s2 = 0.0f;
accel.target_ned_frame.az_m_s2 = 0.0f;

offboard->set_acceleration(accel);

这段代码让飞机以2m/s²的加速度向北加速。注意,加速度控制下,飞机不会自动减速。你需要发负加速度来让它停下来。

⚠️ 重要提醒: 加速度控制非常「暴力」。如果你设的加速度太大,飞机会剧烈倾斜,甚至可能触发安全保护。我建议加速度值不要超过5m/s²,除非你很清楚自己在做什么。

4.5 三种控制的对比与选择

咱们用一张表来总结:

控制方式 输入参数 适用场景 注意事项
位置控制 目标位置 (x, y, z, yaw) 点到点飞行、航点任务 飞机自动规划路径,适合静态目标
速度控制 目标速度 (vx, vy, vz, yaw) 匀速巡航、跟踪移动目标 需要手动发停止指令
加速度控制 目标加速度 (ax, ay, az) 科研、精确轨迹控制 容易失控,谨慎使用

我个人习惯是:能用位置控制就用位置控制,简单可靠。需要平滑运动时切速度控制。加速度控制?嗯,除非你写论文或者做特殊算法,否则尽量别碰。

4.6 知识体系总览

下面这张图,帮你把今天的内容串起来:

位置控制基础:知识体系 坐标系 NED(北东地) ENU(东东北) Z轴方向不同 三种控制方式 📍 位置控制 🚀 速度控制 ⚡ 加速度控制 从粗到细,从易到难 应用场景 航点任务 → 位置控制 匀速巡航 → 速度控制 科研实验 → 加速度控制 核心要点 1. 先确认坐标系(NED还是ENU),再发指令 2. 位置控制最安全,速度控制最灵活,加速度控制最底层 3. 实际开发中,80%的场景用位置控制就够了

这张图把今天的内容串起来了。你看,坐标系是基础,三种控制方式从粗到细,应用场景各有侧重。记住这个结构,以后写代码时就知道该选哪个了。

4.7 避坑指南:我踩过的那些坑

最后,分享几个我实际项目中遇到的坑,希望能帮你省点时间:

  1. 坐标系搞混:我曾经在ENU坐标系下发了NED的坐标,飞机直接往反方向飞。解决方案:在代码开头统一声明坐标系,并加注释。
  2. 忘记切换offboard模式:位置控制必须在offboard模式下才能生效。我见过有人发了setpoint,飞机没反应,结果发现还在position模式。
  3. 速度控制不设停止:速度控制下,飞机不会自动停。记得在到达目标后发一个零速度指令。
  4. 加速度控制太猛:加速度值设太大,飞机会剧烈晃动,甚至触发EKF保护。建议从1m/s²开始试。

好了,这一章的内容就到这里。位置控制是自主飞行的基础,搞懂了它,后面的航点飞行、轨迹规划就水到渠成了。


公众号:蓝海资料掘金营,微信deep3321