拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于Unity ML-Agents的多智能体自行车协同避障项目实战

简介强化学习作为人工智能的核心技术之一通过智能体与环境的交互试错来学习最优策略其核心原理是奖励机制引导下的策略优化。在机器人控制领域这项技术能解决传统方法难以处理的复杂决策问题具有极高的技术价值。多智能体协同避障是强化学习的典型应用场景它要求多个智能体在共享环境中通过局部观测实现安全、高效的协同运动广泛应用于自动驾驶、无人机编队等领域。本文以Unity ML-Agents为实践框架深入探讨了如何构建一个自行车机器人多智能体系统其中涉及奖励函数设计与参数共享等关键工程环节通过调整奖励信号平衡个体与群体目标并利用参数共享机制加速同构智能体的策略学习最终实现虚拟自行车在动态环境中的自主平衡与智能避障。1. 项目概述当自行车学会“社交”最近在整理过去的项目资料翻到了一个挺有意思的毕设/课设项目名字叫“基于Unity ML-Agents release_15开发能够智能躲避同伴的自行车机器人”。这个标题听起来有点学术但说白了就是让一个虚拟的自行车机器人在一个有多个同伴其他自行车的环境里学会自己骑车还不撞到别人。这本质上是一个多智能体协同避障问题是机器人学和强化学习领域一个非常经典且具有挑战性的课题。为什么说它经典因为现实世界中的自动驾驶、无人机编队、服务机器人集群核心难题之一就是如何在动态、不确定的环境中实现安全、高效的协同运动。直接用自行车这种两轮不稳定模型来搞难度又上了一个台阶——它不仅要处理避障还要维持自身的平衡。这个项目把Unity的实时3D仿真能力、ML-Agents的强化学习框架以及自行车动力学模型结合在了一起提供了一个从零到一、可复现的研究与学习平台。无论是用于毕业设计、课程实践还是作为进入机器人强化学习领域的敲门砖它都极具价值。我自己在复现和扩展这个项目的过程中踩了不少坑也积累了一些在官方文档里未必会详细说明的经验。今天我就把这个项目的核心思路、技术细节、实操步骤以及避坑指南系统地梳理一遍希望能帮你绕过那些“暗礁”更高效地完成你的智能自行车机器人项目。2. 项目核心思路与技术选型解析2.1 为什么选择Unity ML-Agents在机器人强化学习仿真领域选择很多比如PyBullet、Gazebo、Isaac Sim等。但这个项目选择Unity ML-Agents release_15版本背后有非常实际的考量。首先可视化与调试的便利性无与伦比。强化学习训练是个“黑盒”过程智能体为什么做出某个决策经常让人摸不着头脑。Unity强大的实时3D渲染能力让你可以像玩赛车游戏一样直观地观察自行车机器人的每一个动作、每一次碰撞、每一次奖励的获取。你可以随时暂停、慢放、多角度观察这对于理解算法行为、定位训练问题至关重要。相比之下在Gazebo里看URDF模型或者看PyBullet的简单几何体信息量要少得多。其次ML-Agents框架的成熟度与易用性。release_15是一个相对稳定且功能完善的版本。它提供了从环境搭建、智能体定义、训练配置到模型导出的完整工具链。其Python API与PyTorch深度集成让习惯于Python生态的研究者和学生能够快速上手。框架内置了PPO、SAC等多种主流算法省去了我们从零实现算法的巨大工作量。再者物理仿真的真实性与可控性。Unity内置的PhysX物理引擎虽然不像一些专业的多体动力学软件那样“硬核”但对于自行车机器人这种级别的模型其精度已经足够。更重要的是我们可以通过调整重力、摩擦系数、碰撞体形状等参数在“真实感”和“训练效率”之间取得平衡。比如初期为了加快收敛可以适当调低物理模拟的精度或频率。最后社区与生态。Unity和ML-Agents拥有庞大的开发者社区遇到问题时更容易找到相关的讨论、教程甚至开源项目参考。这对于课程设计和毕业设计来说能显著降低技术风险。2.2 自行车机器人模型平衡与控制的基石这个项目的核心被控对象是自行车机器人。它不是一个简单的刚体方块而是一个具有非完整约束和静不稳定特性的复杂系统。2.2.1 动力学模型简析一个简化的自行车模型主要包含以下几个部分车架主体承载所有部件。前轮与后轮通常建模为圆柱体或胶囊体通过铰链关节Hinge Joint与车架连接提供滚动自由度。转向关节连接车架和前叉控制前轮的转向角度。这是我们的一个核心控制输入。驱动关节通常施加在后轮上提供前进或制动的扭矩。这是我们的另一个核心控制输入。它的不稳定性来源于其两轮结构必须通过持续的控制调整转向和驱动来维持直立。在ML-Agents中我们并不需要手动推导并编码复杂的动力学方程。相反我们利用Unity的物理引擎来模拟这些物理效应智能体通过试错来学习如何产生合适的控制信号。2.2.2 状态观测空间设计智能体要知道“自己现在是什么状态”才能做出决策。对于自行车机器人观测空间通常包括本体状态车身的俯仰角、横滚角、偏航角欧拉角或四元数车身的角速度、线速度局部坐标系或世界坐标系。轮子状态前轮转向角、后轮转速。与环境/同伴的相对状态这是实现“躲避”的关键。例如到最近同伴的距离、方向向量相对速度同伴的朝向等。为了避免维度灾难通常只观测最近的一个或几个同伴。在ML-Agents中我们通过编写CollectObservations方法将这些信息归一化后添加到VectorSensor中。2.2.3 动作空间设计动作空间决定了智能体能做什么。通常采用连续动作空间转向控制一个连续值例如[-1, 1]映射到前轮的最大左转与最大右转角度。驱动控制一个连续值例如[-1, 1]映射为后轮的驱动扭矩正为加速负为制动。在OnActionReceived方法中我们将神经网络输出的动作值通过一定的缩放比例应用到对应的关节上。2.3 多智能体避障从独奏到协奏单辆自行车自平衡和循迹已经是个挑战加入多辆自行车后问题变成了部分可观测环境下的博弈。每辆自行车智能体的决策会影响其他自行车的环境目标从单纯的“自己别摔倒”变成了“自己别摔倒还别撞到别人”。2.3.1 训练范式选择ML-Agents支持多种多智能体训练范式独立学习每个智能体拥有自己独立的策略网络将其他智能体视为环境的一部分。这种方式简单但在动态环境中策略可能难以收敛因为其他智能体的策略也在不断变化。集中式训练分布式执行在训练时一个中心化的“评论家”网络可以获取所有智能体的观测信息来更好地评估某个智能体动作的价值。但执行时每个智能体仍然只依赖自己的局部观测进行决策。这种方式通常能学到更协同的策略。参数共享所有智能体共享同一个策略网络。这适用于同构智能体所有自行车参数相同的场景能极大地加速训练并隐式地鼓励智能体学习通用的、具有协作性的行为。对于“躲避同伴”这个任务参数共享结合CTDE是一个高效且合理的选择。所有自行车都使用同一个神经网络在训练中它们会共同探索如何在一个拥挤空间里和谐共处。2.3.2 奖励函数设计强化学习的指挥棒奖励函数是强化学习项目的灵魂直接决定了智能体学习的方向。一个糟糕的奖励函数会让训练永远无法收敛。对于我们的任务奖励函数需要精心设计生存奖励每存活一步未摔倒、未出界给予一个小的正奖励如0.01。鼓励智能体“活着”。前进奖励沿着预设方向或目标前进的速度分量奖励。鼓励智能体运动起来。平衡惩罚当车身俯仰角或横滚角过大时给予负奖励。这是维持平衡的核心约束。碰撞惩罚与同伴或墙壁发生碰撞时给予一个较大的负奖励如-1.0并通常结束本轮回合。这是“躲避”行为的直接驱动。距离惩罚/奖励可以设置与同伴保持一定安全距离的奖励。当距离小于安全阈值时给予惩罚大于阈值时给予小奖励或零奖励。这能引导智能体主动保持距离。平滑性惩罚对转向和驱动控制量的变化率施加微小惩罚鼓励生成平滑的控制信号使骑行看起来更自然。实操心得奖励函数的调参是个艺术活。初期可以简化先让智能体学会平衡和前进再逐步引入避障相关的奖励。所有奖励的数值量级需要平衡避免某一项奖励占主导地位。大量使用Debug.Log或在Unity中可视化奖励值的变化是调试奖励函数的关键手段。3. 环境搭建与ML-Agents工程配置3.1 Unity工程与ML-Agents插件安装首先你需要一个Unity项目。建议使用与ML-Agents release_15版本兼容的Unity LTS版本如2019.4或2020.3以减少不必要的兼容性问题。创建新项目选择3D模板即可。安装ML-Agentsrelease_15的安装方式与新版略有不同。通常你需要从GitHub仓库的release_15分支下载源码或直接下载对应的.unitypackage发布包。通过Assets - Import Package - Custom Package导入。更规范的做法是使用Unity的Package Manager从Git URL添加https://github.com/Unity-Technologies/ml-agents.git?pathcom.unity.ml-agents#release_15。安装Python依赖在项目目录外创建一个Python虚拟环境推荐使用Anaconda然后根据ML-Agents仓库中的requirements.txt对应release_15分支安装mlagents等包。核心命令是pip install mlagents0.15.1具体版本号需核对release_15的文档。3.2 构建自行车机器人场景创建地形与边界使用Unity的Terrain工具或简单Plane创建一个地面并在四周放置立方体作为围墙防止智能体跑出训练区域。建模自行车使用基本几何体立方体、圆柱体拼接一个长方体作为车架两个圆柱体作为车轮。这是最快的方式。为前轮添加一个空物体作为“转向中心”将前轮作为其子物体。这样旋转这个空物体就能实现转向。为车架和前轮、后轮添加刚体组件。车架的刚体质量最大车轮的质量较小。添加关节使用Hinge Joint连接车轮和车架。对于后轮锁住其X轴和Z轴的旋转只允许Y轴旋转滚动。对于前轮除了Y轴滚动还需要允许绕其父物体转向中心的Y轴旋转转向。关键步骤务必调整碰撞体。车轮使用胶囊碰撞体比圆柱碰撞体更稳定。适当增加物理材质的摩擦系数防止打滑。预制体化将组装好的自行车机器人做成预制体方便在场景中复制多份。3.3 编写智能体脚本这是项目的核心代码部分。你需要创建一个继承自Agent的C#脚本并挂载到自行车预制体的根物体上。using UnityEngine; using Unity.MLAgents; using Unity.MLAgents.Sensors; public class BicycleAgent : Agent { // 公共变量用于在Inspector中链接 public Rigidbody rb; // 车架刚体 public Transform frontWheel; // 前轮Transform public Transform steeringPivot; // 转向中心 public float maxSteerAngle 30f; // 最大转向角 public float motorTorque 200f; // 最大驱动扭矩 // 其他自行车智能体列表用于计算相对状态 private BicycleAgent[] otherAgents; public override void Initialize() { if (rb null) rb GetComponentRidigbody(); // 查找场景中其他同类智能体 otherAgents FindObjectsOfTypeBicycleAgent().Where(a a ! this).ToArray(); } public override void CollectObservations(VectorSensor sensor) { // 1. 本体姿态与速度 (约8-10个值) sensor.AddObservation(transform.rotation.normalized); // 四元数4个值 sensor.AddObservation(rb.angularVelocity); // 角速度3个值 sensor.AddObservation(rb.velocity); // 线速度3个值 // 2. 轮子状态 (2个值) sensor.AddObservation(frontWheel.localRotation.eulerAngles.y); // 前轮转向角归一化 // 后轮转速可以通过车轮刚体的角速度计算 // 3. 与最近同伴的相对状态 (例如距离方向相对速度) if (otherAgents.Length 0) { BicycleAgent nearestAgent FindNearestAgent(); Vector3 toNearest nearestAgent.transform.position - transform.position; sensor.AddObservation(toNearest.normalized); // 方向3个值 sensor.AddObservation(toNearest.magnitude / 20f); // 归一化距离1个值 Vector3 relativeVel rb.velocity - nearestAgent.rb.velocity; sensor.AddObservation(relativeVel); // 相对速度3个值 } else { // 如果没有同伴用零向量填充 sensor.AddObservation(Vector3.zero); sensor.AddObservation(0f); sensor.AddObservation(Vector3.zero); } } public override void OnActionReceived(float[] vectorAction) { // 解析动作 float steerAction Mathf.Clamp(vectorAction[0], -1f, 1f); float motorAction Mathf.Clamp(vectorAction[1], -1f, 1f); // 执行动作转向 float steerAngle steerAction * maxSteerAngle; steeringPivot.localRotation Quaternion.Euler(0, steerAngle, 0); // 执行动作驱动 (简化模型直接对后轮施加扭矩) // 注意这里需要获取后轮刚体 // rearWheelRb.AddTorque(transform.forward * motorAction * motorTorque); // 计算奖励 float balanceReward CalculateBalanceReward(); float forwardReward CalculateForwardReward(); float collisionPenalty CheckCollision(); float totalReward balanceReward forwardReward collisionPenalty; AddReward(totalReward); // 检查回合结束条件摔倒或出界 if (IsFallen() || IsOutOfBounds()) { EndEpisode(); } } // 以下为辅助方法示例 private BicycleAgent FindNearestAgent() { /* 实现查找逻辑 */ } private float CalculateBalanceReward() { /* 根据俯仰角计算 */ } private float CalculateForwardReward() { /* 根据Z轴速度计算 */ } private float CheckCollision() { /* 检查碰撞并返回惩罚值 */ } private bool IsFallen() { /* 判断车身倾斜是否过大 */ } private bool IsOutOfBounds() { /* 判断是否超出边界 */ } // 可选实现Heuristic方法用于手动控制测试 public override void Heuristic(float[] actionsOut) { actionsOut[0] Input.GetAxis(Horizontal); // 转向 actionsOut[1] Input.GetAxis(Vertical); // 油门 } }3.4 配置训练参数与启动训练创建Behavior Parameters在自行车智能体上挂载Behavior Parameters组件。设置Behavior Name如BicycleBehaviorVector Observation Space Size与CollectObservations中添加的总数量一致Actions-Continuous Actions设为2转向和驱动。Model暂时为空训练后会生成。创建Decision Requester挂载Decision Requester组件设置Decision Period如5表示每5个物理帧做一次决策。这能平衡反应速度和训练稳定性。编写配置文件在项目根目录创建config文件夹新建一个.yaml文件例如bicycle_multi.yaml。behaviors: BicycleBehavior: trainer_type: ppo hyperparameters: batch_size: 1024 buffer_size: 10240 learning_rate: 3.0e-4 beta: 5.0e-3 epsilon: 0.2 lambd: 0.95 num_epoch: 3 learning_rate_schedule: linear network_settings: normalize: true hidden_units: 128 num_layers: 2 reward_signals: extrinsic: gamma: 0.99 strength: 1.0 max_steps: 1e6 time_horizon: 64 summary_freq: 10000 threaded: true启动训练在命令行中激活Python环境导航到项目目录运行命令mlagents-learn config/bicycle_multi.yaml --run-idbicycle_multi_01 --envpath/to/your/unity_build --num-envs4--num-envs4表示同时启动4个训练环境副本可以大幅加快数据收集速度。你需要先通过File - Build Settings构建一个可执行文件--env参数指定或者在Editor中直接运行使用--envEditor。4. 训练过程优化与问题排查实录4.1 训练不收敛的常见原因与对策训练强化学习智能体大部分时间都在与“不收敛”作斗争。以下是我遇到过的典型问题问题1智能体“躺平”一动不动。可能原因奖励函数设计不当生存奖励或平衡惩罚过重导致智能体发现“不动就不会摔倒能获得最大累积奖励”。排查与解决检查奖励曲线。使用TensorBoardML-Agents训练会自动启动查看Cumulative Reward和各个奖励分量的曲线。如果总奖励是一条缓慢上升的直线而前进奖励始终为0说明智能体没在动。增加前进奖励的权重或引入“停滞惩罚”长时间速度低于阈值则给予负奖励。在回合开始时给自行车一个微小的随机初速度或角度扰动打破对称性鼓励它探索。问题2智能体疯狂转圈或行为怪异。可能原因观测空间或动作空间没有正确归一化物理参数如扭矩、质量设置不合理网络结构或超参数不合适。排查与解决归一化确保所有输入AddObservation的值都在一个合理的范围内如[-1, 1]或[0, 1]。角度可以除以180距离可以除以一个最大观测距离。动作缩放检查maxSteerAngle和motorTorque是否过大。过大的控制量会导致系统不稳定。从小值开始尝试。简化问题先在一个空旷场景训练自行车直线行驶和平衡成功后再加入同伴和避障任务。调整超参数降低learning_rate增加batch_size或buffer_size可能会使训练更稳定。问题3多智能体相互“卡死”或形成奇怪阵型。可能原因在部分可观测环境下智能体缺乏全局协调能力奖励函数只鼓励个体避障未鼓励群体流动。排查与解决在观测空间中为每个智能体添加一个全局的“目标方向”或“车道中心线”信息引导群体整体移动。在奖励函数中除了个体碰撞惩罚可以加入“全局平均速度”奖励鼓励整体向前推进。尝试使用self-play或课程学习从简单同伴少、速度慢到复杂逐步增加难度。4.2 性能调优与加速训练技巧增加并行环境这是加速训练最有效的方法。使用--num-envs参数根据你的CPU核心数可以设置8个、16个甚至更多环境。在Unity中可以通过复制场景中的智能体并设置不同的Behavior Parameters中的Team Id来实现。简化视觉如果场景中有复杂的3D模型和纹理会严重影响仿真速度。训练时使用最简单的材质和低多边形模型关闭阴影、后处理等效果。调整物理模拟在Edit - Project Settings - Time中可以适当调低Fixed Timestep如从0.02调到0.04这会降低物理更新频率提升速度但可能会影响模拟精度。需要在速度和精度间权衡。使用Raycast替代碰撞检测进行观测对于远距离的同伴感知持续计算距离和方向向量可能开销较大。可以改为从自行车向前方发射几条射线观测射线是否击中同伴及其距离。这更符合传感器如激光雷达的原理且计算效率可能更高。课程学习手动设计训练阶段。第一阶段空旷场地学习平衡与前进。第二阶段加入一个静止的同伴。第三阶段加入一个匀速运动的同伴。第四阶段加入多个智能体。通过代码控制阶段切换可以显著提高最终策略的鲁棒性和训练效率。4.3 模型部署与效果测试训练完成后ML-Agents会在results文件夹下生成一个.onnx模型文件。导入模型将这个.onnx文件拖入Unity项目的Assets文件夹。部署模型在训练好的自行车智能体的Behavior Parameters组件中将Model字段指定为刚才导入的.onnx文件并将Behavior Type从Default改为Inference Only。测试效果运行Unity场景。现在自行车应该能使用训练好的神经网络进行决策了。你可以通过复制多辆自行车观察它们之间的避让行为。性能分析在Window - Analysis - Profiler中可以查看神经网络推理Barracuda是Unity的推理引擎所占用的时间确保在目标平台如PC、移动设备上能达到实时性能要求。5. 项目扩展与进阶思考完成基础的避障功能后这个项目还有很大的扩展空间可以深化你的毕设或项目内涵。5.1 引入更复杂的感知系统视觉感知使用ML-Agents的CameraSensor或RenderTextureSensor让自行车通过第一人称或第三人称摄像头“看到”世界。这需要处理图像输入通常结合卷积神经网络训练难度和计算量会剧增但更贴近现实。激光雷达模拟通过代码模拟激光雷达在自行车周围均匀发射一系列射线返回射线击中的物体距离和标签。这比视觉信息更结构化易于处理。5.2 实现更复杂的任务编队骑行让多辆自行车不仅躲避还能保持特定的队形如一字长蛇、三角形。目标导航为每辆自行车设置独立的目标点要求其在躲避同伴的同时到达各自目的地。混合交通场景在环境中加入由传统脚本控制的“NPC”车辆或行人让自行车学会在更不可预测的环境中行驶。5.3 算法层面的探索尝试其他算法ML-Agents也支持SAC软演员-评论家算法对于连续控制任务SAC有时能比PPO获得更优的策略。好奇心驱动探索对于稀疏奖励任务如只在到达终点时给奖励可以引入内在好奇心模块鼓励智能体探索未知状态。模仿学习先用传统的PID控制器或路径规划算法生成一些“专家”演示数据然后用这些数据对策略网络进行预训练再进行强化学习微调可以大大加快训练速度。这个项目就像一把钥匙帮你打开了机器人强化学习与多智能体系统的大门。从动力学建模、环境搭建到奖励函数设计、训练调参再到问题排查与优化整个过程几乎涵盖了智能体开发的全链路。最大的收获可能不是那个最终会躲避的自行车模型而是在解决层出不穷的“为什么不行”的过程中积累下的对强化学习核心思想的深刻理解和对工程问题的实战解决能力。当你看到几辆自行车在场景中流畅地穿梭、彼此礼让时那种成就感就是对这个项目最好的回报。如果在实现过程中遇到任何具体问题不妨从简化开始一步步增加复杂度耐心调试你一定能让你自行车机器人“聪明”起来。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门