X00218-AirSim无人艇控制程序:Python编程的完整解决方案
X00218-AirSim无人艇控制程序python完整程序

最近在折腾AirSim里的无人艇仿真,发现这玩意儿比四旋翼无人机有意思多了。水面上的物理特性完全不一样,控制程序写起来手感特别微妙。今天就跟大伙儿唠唠我的调试经历,顺便把压箱底的Python控制程序拆开看看。

先上段连接模拟器的代码热热身:
from airsim import MultirotorClient
import time
boat = MultirotorClient()
boat.confirmConnection()
boat.enableApiControl(True)
print("推进器状态:", boat.getRotorStates().rotors)
别看这几行简单,当初调试时差点没把我整哭。enableApiControl这个开关要是没开,后面所有控制指令都会石沉大海。有次测试时发现无人艇原地打转,查了半天才发现是API控制没激活,程序还特贴心地不报错...

控制核心部分用了个PID调节器,专门对付水面运动的随机扰动:
class WaterPID:
def __init__(self, kp=0.5, ki=0.01, kd=0.2):
self.kp, self.ki, self.kd = kp, ki, kd
self.last_error = 0
self.integral = 0
def update(self, target, current, dt):
error = target - current
self.integral += error * dt
derivative = (error - self.last_error) / dt
output = self.kp*error + self.ki*self.integral + self.kd*derivative
self.last_error = error
return output
这里有个坑——水流的积分项特别容易饱和。后来加了个积分限幅才解决,不过为了代码易读性这里先简化了。实际使用时记得把self.integral限制在±100之间,不然遇到强侧风时无人艇能给你表演360度水上漂移。

X00218-AirSim无人艇控制程序python完整程序

控制主循环里有个反直觉的设计:速度控制优先于方向控制。因为水面载具惯性大,先调速度能避免方向过度修正。
def navigate_to_target(target_pos, max_speed=5):
current_pos = boat.getMultirotorState().kinematics_estimated.position
velocity = boat.getMultirotorState().kinematics_estimated.linear_velocity
heading = np.arctan2(target_pos.y_val - current_pos.y_val,
target_pos.x_val - current_pos.x_val)
# 先调速再转向
speed_error = np.sqrt(velocity.x_val**2 + velocity.y_val**2) - max_speed
throttle = speed_pid.update(0, speed_error, 0.1)
# 航向修正量不要超过30度
heading_correction = heading_pid.update(heading, current_yaw, 0.1)
heading_correction = np.clip(heading_correction, -0.5, 0.5)
boat.moveByVelocityZ(throttle * np.cos(heading + heading_correction),
throttle * np.sin(heading + heading_correction),
-0.5, # 保持吃水深度
0.1)
这里有几个骚操作:
- 用Z轴控制吃水深度(负值代表水面下深度)
- 速度PID的输出直接作为油门量
- 航向修正量限制在±0.5弧度(约28.6度)避免急转弯侧翻
实测时发现个有趣现象:当速度超过3m/s时,转向灵敏度会突然降低。后来发现是AirSim的水面物理引擎在高速时自动增加了转向阻尼,这反而让控制逻辑变简单了——不用自己写速度-转向耦合补偿。

最后给新手们提个醒:水面载具的传感器噪声比无人机大得多,千万别直接相信姿态仪数据。我这有个滤波土方子:
from scipy import signal
# 创建5阶巴特沃斯低通滤波器
b, a = signal.butter(5, 0.1, 'low')
def smooth_attitude(raw_data):
global filter_state
smoothed, filter_state = signal.lfilter(b, a, [raw_data], zi=filter_state)
return smoothed[0]
这滤波器能把波浪造成的姿态抖动滤掉七成。记得初始化时给filter_state赋个初始值,不然前几次滤波会输出妖魔鬼怪的数据。
程序跑起来后看着无人艇在水面划出漂亮的航迹线,成就感比玩无人机高好几个level。不过要小心别沉迷——有次测试到凌晨三点,关掉模拟器才发现现实中的鱼缸水花声让我产生了PTSD...
更多推荐


所有评论(0)