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)

这里有几个骚操作:

  1. 用Z轴控制吃水深度(负值代表水面下深度)
  2. 速度PID的输出直接作为油门量
  3. 航向修正量限制在±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...

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐