ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

flybody视觉引导飞行任务实战:32×32“眼睛“相机如何教会果蝇飞行

flybody视觉引导飞行任务实战:32×32“眼睛“相机如何教会果蝇飞行

【免费下载链接】flybody

MuJoCo fruit fly body model and locomotion RL tasks

项目地址:https://gitcode.com/gh_mirrors/fl/flybody
点击查看免费下载

flybody 是一个为 MuJoCo 物理模拟器打造的果蝇(Drosophila melanogaster)全身模型与运动强化学习任务库。其中最硬核的任务是视觉引导飞行(vision-guided flight):果蝇仅靠头部两只32×32 像素的"眼睛"相机和惯性传感器,学习在随机生成的丘陵或蜿蜒沟壑上方保持目标高度与速度飞行。本文将带你拆解这个任务的完整机制:眼睛相机如何定义、奖励函数如何设计、单一标量动作如何控制 218Hz 的翅膀拍频,以及如何用 Ray 分布式训练。

🦟 flybody 是什么:一只可以"活过来"的仿真果蝇

flybody 由 Google DeepMind 与 HHMI Jeline 研究院合作开发,其模型包含头部、胸部、腹部、6 条腿、翅膀、平衡棒与口器等解剖学细节(见 flybody/fruitfly/assets/fruitfly.xml)。模型支持:

  • 飞行模式:翅膀使用力控执行器 + 椭圆流体模型(fluidshape='ellipsoid')模拟空气动力,物理步长仅5e-5秒;
  • 行走模式:腿足带摩擦与粘附执行器,可在球面上行走;
  • 任务抽象:所有任务基于 dm_control 的composer.Task,观察量(observables)以传感器方式声明。

任务工厂集中在 flybody/fly_envs.py,视觉飞行任务由vision_guided_flight()函数一行创建:

from flybody.fly_envs import vision_guided_flight env = vision_guided_flight(bumps_or_trench='trench') # 或 'bumps'

👁️ 32×32"眼睛"相机:视觉输入的真相

视觉任务的核心观察量是两只眼睛。相机在果蝇模型的 XML 中定义,位于头部两侧(flybody/fruitfly/assets/fruitfly.xml):

<camera name="eye_right" fovy="140" pos="0.0219 0.0131 0" quat="0.474 0.688 -0.344 -0.429"/> <camera name="eye_left" fovy="140" pos="-0.0219 0.0131 0" quat="0.474 0.688 0.344 0.429"/>

关键参数由任务构造函数控制(见 flybody/tasks/vision_flight.py):

参数默认值含义
eye_camera_size32每只眼睛的分辨率(32×32 像素)
eye_camera_fovy150°眼睛垂直视场角(宽视角,类似昆虫复眼)
target_height_range(0.5, 0.8)随机目标飞行高度(米)
target_speed_range(20, 40)随机目标速度(cm/s)

在 flybody/fruitfly/fruitfly.py 中,left_eye与right_eye被实现为observable.MJCFCamera观察量——每次env.step()时直接从仿真场景渲染 32×32 的 RGB 图像,作为策略网络的输入。分辨率极低是刻意设计:真实果蝇单眼的光感受器数量与之相当,这也是任务难度来源之一。

一个有趣的细节:视觉任务会移除场景中所有光源(vision_flight.py中对light节点的清空循环),并调小znear/zfar/force等渲染参数(见 flybody/tasks/base.py 的注释:"对视觉引导飞行任务至关重要"),迫使果蝇只能依靠地形本身的光照与轮廓来判断障碍。

🏔️ 两种地形:bumps 与 trench

vision_guided_flight()支持两种可随机再生的竞技场(见 flybody/tasks/arenas/hills.py):

  • bumps(丘陵):SineBumps生成碗状地形 + 正弦波状隆起,波长 10~15m、振幅 0.5~1.0m 每回合随机采样,果蝇需要"看"前方地形起伏来维持高度;
  • trench(沟壑):SineTrench在碗状地形上开出一条蜿蜒的正弦形沟渠,果蝇需要沿沟中线飞行,且地形参数经过约束(width = 2*amplitude + 0.604*width_factor,0.604 正是果蝇翅展),杜绝直线穿越的平凡解。

每个回合开始时,目标高度与目标速度随机重采样,并通过task_input观察量(目标高度 + 目标速度,2 个标量)告诉策略"这轮飞多高、多快"。

📐 奖励与动作:七个因子 × 一个标量

奖励函数:7 个因子的几何平均

get_reward_factors()(flybody/tasks/vision_flight.py)返回 7 项容忍度(tolerance)奖励因子,总奖励为其乘积:

  1. height:相对地形的当前高度逼近随机目标高度(容差 ±0.15m);
  2. x_speed:世界系 x 方向速度不低于目标速度;
  3. speed:合速度模长逼近目标速度;
  4. side_speed:自身坐标系下横向速度为 0(不许侧滑);
  5. world_zaxis:机体竖直轴对齐目标姿态(果蝇飞行时身体前倾 47.5°,来自真实飞行数据);
  6. center_of_trench:trench 任务中保持贴近沟渠中心线;
  7. retract_legs:飞行时保持腿部收拢(向折叠参考角度看齐)。

此外,触碰地面直接终止回合(floor_contacts_fatal=True),坠机是最快的失败方式。

动作空间:一个数字控制拍翅频率

整个策略只输出1 个标量动作a ∈ [-1, 1],其余"动作"由拍翅模式发生器(WingBeatPatternGenerator, WBPG)自动生成。before_step中的控制律(flybody/tasks/vision_flight.py):

ctrl_freq = base_freq * (1 + rel_range * a) # base_freq = 218 Hz

即动作将基础拍频 218Hz 上下调节 ±5%。WBPG 根据拍频查表/生成翅膀位置指令,再转换为力控制驱动 6 个翅膀关节(左/右 × yaw/roll/pitch)。这意味着策略的全部自由度只有"扇翅膀快一点还是慢一点"——俯仰、偏航姿态全部涌现自翅膀流体力学与机体耦合,这正是该任务对生物启发控制研究的价值所在。

观察量清单

策略每步(控制步长 2e-4s,单回合上限 0.4s)看到:

  • 左右眼 32×32 RGB 图像(各 3072 维);
  • 前庭传感器:陀螺仪、加速度计、测速计、世界 z 轴;
  • 本体感觉:关节位置/速度、执行器激活状态;
  • task_input:目标高度 + 目标速度。

🚀 快速上手:5 分钟跑通视觉飞行环境

# 1. 克隆仓库并安装(含 ML 依赖) git clone https://gitcode.com/gh_mirrors/fl/flybody cd flybody conda create --name flybody -c conda-forge python=3.10 pip conda activate flybody pip install -e .[tf] # 训练再装 .[ray] export MUJOCO_GL=egl
import numpy as np from flybody.fly_envs import vision_guided_flight env = vision_guided_flight(bumps_or_trench='bumps') timestep = env.reset() # 随机策略飞一会儿(预期很快坠地) for _ in range(50): action = np.random.uniform(-1, 1) timestep = env.step(action) if timestep.last(): break # 看一眼"果蝇的视角" print('双眼输入:', timestep.observation['walker/left_eye'].shape) # (32, 32, 3)

想直观查看三类任务环境的运行效果,官方示例 notebook 是 docs/fly-env-examples.ipynb(飞行模仿 / 行走模仿 / 视觉引导飞行)。

🖥️ 分布式训练:Ray + DMPO

真正教会果蝇飞的是强化学习。flybody/train_dmpo_ray.py 提供了基于Ray的分布式DMPO(Deep Memory Policy Optimization)训练脚本:

python flybody/train_dmpo_ray.py --test # 轻量模式:单 actor,每 10 秒打印统计 python flybody/train_dmpo_ray.py # 全量模式:32 actors + 独立 learner

默认配置 32 个并行 actor、batch size 256、replay buffer 上限 400 万样本。脚本本身任务无关——把environment_factory里的walk_on_ball()换成vision_guided_flight(...)即可训练视觉任务。DMPO 的分布式实现(Learner / ReplayServer / EnvironmentLoop)位于 flybody/agents/ray_distributed_dmpo.py。

🧠 进阶技巧:控制器复用(Controller Reuse)

官方还有一个值得学习的两阶段方案(docs/controller-reuse-vision-flight.ipynb):

  1. 先学技能:用飞行模仿任务(flight_imitation)训练低层飞行控制器,学会"如何飞";
  2. 冻结复用:在视觉任务中加载并冻结低层控制器权重,只训练一个高层策略——高层网络吃双眼图像,输出 1 个拍频标量"驾驶"冻结的低层控制器完成导航。

这种"技能库 + 高层决策"的分层架构,避免了从零学习飞行的巨大样本量开销,也是该工作发表在 Nature 论文中的核心方法论之一。

📂 关键文件导航

文件说明
flybody/tasks/vision_flight.py视觉飞行任务类VisionFlightImitationWBPG:奖励、终止、眼睛观察量
flybody/fly_envs.pyvision_guided_flight()环境工厂(bumps / trench)
flybody/fruitfly/fruitfly.py果蝇 walker 与left_eye/right_eye相机观察量
flybody/fruitfly/assets/fruitfly.xml果蝇 MuJoCo 模型与双眼相机定义
flybody/tasks/arenas/hills.pySineBumps/SineTrench随机地形生成
flybody/tasks/pattern_generators.py拍翅模式发生器 WBPG
flybody/train_dmpo_ray.pyRay 分布式 DMPO 训练入口
docs/fly-env-examples.ipynb三类 RL 任务环境演示 notebook
docs/controller-reuse-vision-flight.ipynb控制器复用视觉导航示例

总结:为什么这个任务值得研究

flybody 的视觉引导飞行任务把生物约束压到了极致:32×32 的低分辨率双眼、一个标量动作、0.4 秒的回合、坠地即死。在这种信息带宽下,策略必须学会从像素流中提取地形高度与走向,并用拍翅频率这一单一操纵面完成六自由度飞行——这正是果蝇神经系统真正做的事。对 RL 研究者而言,它是检验"感知-运动耦合"与分层控制的绝佳基准;对仿真爱好者,一行vision_guided_flight()就能启动这个任务。

【免费下载链接】flybody

MuJoCo fruit fly body model and locomotion RL tasks

项目地址:https://gitcode.com/gh_mirrors/fl/flybody
点击查看免费下载

相关推荐

上一篇:EulerLauncher深度解析:为什么它是openEuler开发者的必备神器?
下一篇:HTML5 游戏免费上线:GitHub Pages 三步部署

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进