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。
4.1.2 ENU坐标系(东东北)
ENU是另一个常见坐标系,ROS和很多地面站喜欢用这个:
- X轴:指向东(East)
- Y轴:指向北(North)
- Z轴:指向上(Up),向上为正
你看,ENU的Z轴向上为正,这更符合我们日常直觉。飞高10米,Z就是10。
为什么会存在两套坐标系?说白了,历史原因。NED是航空航天的老传统,ENU是机器人领域后来推的。MAVSDK默认用NED,但很多API也支持ENU转换。
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米,机头朝北。
你想想看,这其实就是一个「点到点」的移动。飞机内部会自己算路径、调姿态、控油门。你只需要告诉它终点就行。
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²的加速度向北加速。注意,加速度控制下,飞机不会自动减速。你需要发负加速度来让它停下来。
4.5 三种控制的对比与选择
咱们用一张表来总结:
| 控制方式 | 输入参数 | 适用场景 | 注意事项 |
|---|---|---|---|
| 位置控制 | 目标位置 (x, y, z, yaw) | 点到点飞行、航点任务 | 飞机自动规划路径,适合静态目标 |
| 速度控制 | 目标速度 (vx, vy, vz, yaw) | 匀速巡航、跟踪移动目标 | 需要手动发停止指令 |
| 加速度控制 | 目标加速度 (ax, ay, az) | 科研、精确轨迹控制 | 容易失控,谨慎使用 |
我个人习惯是:能用位置控制就用位置控制,简单可靠。需要平滑运动时切速度控制。加速度控制?嗯,除非你写论文或者做特殊算法,否则尽量别碰。
4.6 知识体系总览
下面这张图,帮你把今天的内容串起来:
这张图把今天的内容串起来了。你看,坐标系是基础,三种控制方式从粗到细,应用场景各有侧重。记住这个结构,以后写代码时就知道该选哪个了。
4.7 避坑指南:我踩过的那些坑
最后,分享几个我实际项目中遇到的坑,希望能帮你省点时间:
- 坐标系搞混:我曾经在ENU坐标系下发了NED的坐标,飞机直接往反方向飞。解决方案:在代码开头统一声明坐标系,并加注释。
- 忘记切换offboard模式:位置控制必须在offboard模式下才能生效。我见过有人发了setpoint,飞机没反应,结果发现还在position模式。
- 速度控制不设停止:速度控制下,飞机不会自动停。记得在到达目标后发一个零速度指令。
- 加速度控制太猛:加速度值设太大,飞机会剧烈晃动,甚至触发EKF保护。建议从1m/s²开始试。
好了,这一章的内容就到这里。位置控制是自主飞行的基础,搞懂了它,后面的航点飞行、轨迹规划就水到渠成了。
公众号:蓝海资料掘金营,微信deep3321