当前位置: 首页 > news >正文

[pilot智驾系统] 模型守护进程(modeld)

第5章:模型守护进程(modeld)

在上一章中,我们看到控制守护进程(controlsd)如何将高层命令转化为精确的转向和踏板输入。

但这些高层命令,特别是期望路径和未来速度,究竟从何而来sunnypilot如何"看到"世界并预测接下来会发生什么?

这就是**模型守护进程(modeld)**的职责所在!

modeld视为sunnypilot的**视觉先知**。

它就像一个训练有素的专家,通过车辆摄像头持续观察道路。它不仅能看到当前的情况,还能以闪电般的速度处理这些图像,理解驾驶环境,最重要的是预测未来

modeld使用先进的人工智能(特别是神经网络)来预测:

  • 车道线位置(以及它们未来的位置)。
  • 其他车辆和障碍物的位置(以及它们的移动方向)。
  • 车辆未来几秒的路径和速度
  • 潜在的驾驶员行为,比如是否可能尝试接管控制。

这种对车辆周围环境的深入理解和预测,对sunnypilot做出安全智能的自动驾驶决策至关重要。

为什么需要模型守护进程?

没有modeldsunnypilot将如同盲人,无法预测未来。它不知道道路如何弯曲,交通速度如何变化,或者前方车辆是否在减速。这将无法规划出平稳、安全和高效的驾驶路径。

modeldsunnypilot提供了"眼睛"和"水晶球"。它将原始摄像头像素转化为对驾驶场景的丰富结构化理解,并精确预测未来事件,使sunnypilot能够有效规划行动。

用例:预测车辆未来路径

想象我们正接近一个平缓的弯道。sunnypilot需要知道精确的转向角度和速度以平稳通过弯道。

modeld如何帮助?它通过摄像头持续观察前方道路,识别车道的曲率,并预测车辆未来10秒应遵循的精确路径。它还观察前方车辆的速度并预测其未来移动,帮助sunnypilot决定最佳加速度。

模型守护进程的工作原理

modeld在持续循环中运行,尽可能快地处理新的摄像头帧。以下是简化流程:

  1. 捕获图像:从车辆的主摄像头和广角摄像头接收实时视频帧。
  2. 输入AI模型:这些图像被输入高度优化的神经网络(AI模型)。这些模型经过数百万英里真实驾驶数据的广泛训练。
  3. 处理与预测:模型分析像素以识别道路上的一切:车道线、道路边缘、其他车辆(称为"前导车")以及前方道路的整体几何形状。基于此,它们预测车辆的最佳未来路径、速度和加速度。
  4. 打包输出modeld将所有原始预测组织成易于理解的消息。
  5. 发布消息:最后,它发布这些消息,主要是modelV2drivingModelDatacameraOdometry,供其他sunnypilot组件使用。

让我们可视化这一流程:

在这里插入图片描述

如何使用模型守护进程(与其输出交互)

作为初学者,我们不会直接"使用"modeld调用其函数。

相反,我们会读取它发布的详细消息,特别是modelV2消息。此消息包含关于驾驶环境的所有预测。

以下是sunnypilot其他部分(如控制守护进程(controlsd)或纵向规划器(LongitudinalPlanner))读取这些信息的方式:

import cereal.messaging as messaging
from cereal import log# 创建SubMaster以监听消息
sm = messaging.SubMaster(["modelV2"])# 在运行非常频繁的循环中
while True:sm.update(0) # 检查新消息if sm.updated["modelV2"]:model_output = sm["modelV2"]# 获取转向的期望曲率(来自'action'字段)desired_curvature = model_output.action.desiredCurvatureprint(f"Modeld预测期望曲率: {desired_curvature:.4f} (弧度/米)")# 获取油门/刹车的期望加速度(来自'action'字段)desired_accel = model_output.action.desiredAccelerationprint(f"Modeld预测期望加速度: {desired_accel:.2f} m/s^2")# 检查模型是否认为我们应该停止if model_output.action.shouldStop:print("Modeld提示: 该停车了!")# ... 其他逻辑 ...

这段代码展示了控制守护进程(controlsd)如何从modeldmodelV2消息中获取转向的desiredCurvature,以及纵向规划器(LongitudinalPlanner)如何获取desiredAcceleration

这是驱动sunnypilot路径和速度控制的核心数据。

底层原理:modeld核心循环

在这里插入图片描述

modeldselfdrive/modeld/modeld.py中实现并持续运行。

其主while True循环负责管理摄像头输入、运行AI模型和发布结果。

让我们看看主循环的简化版本:

# 摘自selfdrive/modeld/modeld.py(简化版)
import cereal.messaging as messaging
from openpilot.selfdrive.modeld.fill_model_msg import fill_model_msg, fill_pose_msg, PublishState
from openpilot.selfdrive.modeld.constants import ModelConstants, Plan
from openpilot.selfdrive.modeld.models.commonmodel_pyx import DrivingModelFrame, CLContext
from openpilot.selfdrive.modeld.parse_model_outputs import Parser
# ... (其他导入) ...class ModelState: # 简化表示# 保存我们的AI模型和缓冲区def run(self, bufs, transforms, inputs, prepare_only):# ... 运行视觉和策略模型的逻辑 ...# 返回从模型解析的输出passdef main():# ... (初始设置) ...model = ModelState(cl_context) # 初始化AI模型状态pm = messaging.PubMaster(["modelV2", "drivingModelData", "cameraOdometry"]) # 发布者sm = messaging.SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "carControl", "liveDelay"]) # 订阅者publish_state = PublishState() # 帮助管理一些输出数据while True:# 1. 接收最新的摄像头帧(bufs)#    这部分等待来自摄像头守护进程的新视频帧。#    (从vipc_client_main和vipc_client_extra接收帧的代码很复杂,此处简化)buf_main, buf_extra = None, None # 假设这些已填充新帧# 2. 更新其他输入(车辆状态、驾驶员意图、校准)sm.update(0) # 从其他守护进程获取最新消息v_ego = max(sm["carState"].vEgo, 0.) # 当前车速desire = DH.desire # 驾驶员意图(如左/右变道)# ... 其他输入如交通规则、校准变换 ...# 3. 为AI模型准备输入vec_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32)if desire >= 0 and desire < ModelConstants.DESIRE_LEN:vec_desire[desire] = 1 # 将驾驶员意图转换为向量inputs = {'desire': vec_desire,'traffic_convention': traffic_convention, # 如右侧通行}bufs = {name: buf_extra if 'big' in name else buf_main for name in model.vision_input_names}transforms = {name: model_transform_extra if 'big' in name else model_transform_main for name in model.vision_input_names}# 4. 运行AI模型获取预测model_output = model.run(bufs, transforms, inputs, prepare_only=False)# model_execution_time = ... (测量耗时) ...if model_output is not None:# 5. 从模型输出中提取期望动作(曲率、加速度)action = get_action_from_model(model_output, prev_action, lat_delay + DT_MDL, long_delay + DT_MDL, v_ego)prev_action = action# 6. 填充并发布消息modelv2_send = messaging.new_message('modelV2')drivingdata_send = messaging.new_message('drivingModelData')posenet_send = messaging.new_message('cameraOdometry')fill_model_msg(drivingdata_send, modelv2_send, model_output, action, publish_state,meta_main.frame_id, meta_extra.frame_id, frame_id, frame_drop_ratio,meta_main.timestamp_eof, model_execution_time, live_calib_seen)fill_pose_msg(posenet_send, model_output, meta_main.frame_id, vipc_dropped_frames, meta_main.timestamp_eof, live_calib_seen)pm.send('modelV2', modelv2_send)pm.send('drivingModelData', drivingdata_send)pm.send('cameraOdometry', posenet_send)# ...

这个简化的main函数展示了modeld的持续循环:获取输入、运行AI模型(model.run)、提取"动作"(期望路径/速度)并发布结果。

两个核心AI模型(视觉与策略)

model.run内部,modeld使用两种主要类型的神经网络协同工作:

  1. 视觉模型:该模型接收原始摄像头图像并从中提取丰富特征。它直接"看到"道路及其上的一切。
    • 输入:原始摄像头图像(像素)。
    • 输出
      • 车道线与道路边缘:车道线和道路边界的精确位置和概率。
      • 前导车:前方车辆的位置、速度和概率。
      • 隐藏状态(特征):对道路场景的浓缩"理解",随后输入到下一个模型。
  2. 策略模型:该模型接收视觉模型的"隐藏状态"(特征),以及一些历史数据和驾驶员意图,以预测未来。
    • 输入:视觉模型的隐藏状态、历史特征、驾驶员意图(如尝试变道)。
    • 输出
      • 未来路径:车辆未来几秒的预测路径(位置、速度、加速度)。这是主要的"计划"。
      • 驾驶员意图:各种驾驶员动作的概率(如踩油门、踩刹车、转向覆盖)。
      • 激活预测:由于驾驶员动作或系统限制导致sunnypilot退出的概率。

通过拆分任务,sunnypilot可以高效处理视觉信息,并利用这种理解对车辆未来行为和环境做出复杂预测。

处理模型输出(parse_model_outputs.py

在这里插入图片描述

这些AI模型的原始输出只是数字数组。selfdrive/modeld/parse_model_outputs.py中的Parser类负责将这些数字解释为有意义的预测,如概率和坐标。

将模型的"猜测"转化为结构化数据

填充消息(fill_model_msg.py

在这里插入图片描述

一旦Parser将原始数字转化为可理解的预测(如车道线随时间变化的X、Y、Z坐标),selfdrive/modeld/fill_model_msg.py中的函数将这些处理后的数据精心组织到发布的modelV2drivingModelDatacameraOdometry消息中。

这是预测路径、车道线、前导车和其他信息被组织成其他守护进程期望格式的地方。

推导动作(get_action_from_model

在这里插入图片描述

关键步骤是从model_output中提取action(期望曲率和加速度)。

这在modeld.py中的get_action_from_model函数中完成:

# 摘自selfdrive/modeld/modeld.py(简化版)
from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan, smooth_value, get_curvature_from_plandef get_action_from_model(model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action,lat_action_t: float, long_action_t: float, v_ego: float) -> log.ModelDataV2.Action:plan = model_output['plan'][0] # 获取主要预测路径# 从预测路径计算期望加速度desired_accel, should_stop = get_accel_from_plan(plan[:,Plan.VELOCITY][:,0], # 预测速度plan[:,Plan.ACCELERATION][:,0], # 预测加速度ModelConstants.T_IDXS, # 时间索引action_t=long_action_t) # 加速度的目标时间desired_accel = smooth_value(desired_accel, prev_action.desiredAcceleration, LONG_SMOOTH_SECONDS)# 从预测路径(方向)计算期望曲率desired_curvature = get_curvature_from_plan(plan[:,Plan.T_FROM_CURRENT_EULER][:,2], # 预测偏航角plan[:,Plan.ORIENTATION_RATE][:,2], # 预测偏航率ModelConstants.T_IDXS, # 时间索引v_ego, # 当前速度lat_action_t) # 曲率的目标时间# 对曲率应用平滑处理以实现更平稳的转向if v_ego > MIN_LAT_CONTROL_SPEED:desired_curvature = smooth_value(desired_curvature, prev_action.desiredCurvature, LAT_SMOOTH_SECONDS)else:desired_curvature = prev_action.desiredCurvature # 如果速度太低,保持之前的曲率return log.ModelDataV2.Action(desiredCurvature=float(desired_curvature),desiredAcceleration=float(desired_accel),shouldStop=bool(should_stop))

这个函数非常重要

它从AI模型的详细plan(预测的未来路径、速度和加速度随时间变化)中提取出单一desiredCurvature(用于转向)和desiredAcceleration(用于油门/刹车)。

它还对这些值应用"平滑"处理,确保sunnypilot对车辆的命令不会突兀,而是平稳舒适。这两个值desiredCurvaturedesiredAcceleration是控制守护进程(controlsd)和纵向规划器(LongitudinalPlanner)直接使用的关键输出。

总结

**模型守护进程(modeld)**是sunnypilot的眼睛和预测大脑。

通过使用复杂的AI模型持续处理摄像头图像,它理解当前的驾驶环境,并准确预测车辆的未来路径、速度和周围障碍物。

然后,它将这些洞察组织成清晰的消息,供其他sunnypilot组件(如控制守护进程(controlsd)和纵向规划器(LongitudinalPlanner))使用,以安全智能地驾驶车辆。

这是sunnypilot能够"看到"和"思考"前方道路的基础。

接下来,我们将看到modeld对未来速度的预测如何被**纵向规划器(LongitudinalPlanner)**用于做出加速和刹车的智能决策

下一章:纵向规划器(LongitudinalPlanner)

http://www.dtcms.com/a/350879.html

相关文章:

  • rbio1:以生物学世界模型为软验证器训练科学推理大语言模型
  • 面试八股文之——JAVA基础
  • 深度学习梯度下降与交叉熵损失
  • 重塑企业沟通与增长:云蝠智能大模型如何成为您的智能语音中枢
  • 大模型(一)什么是 MCP?如何使用 Charry Studio 集成 MCP?
  • SQL查询-设置局部变量(PostgreSQL、MySQL)
  • 嵌入式学习 day58 驱动字符设备驱动
  • 玳瑁的嵌入式日记D25-0825(进程)
  • Java全栈开发实战:从Spring Boot到Vue3的项目实践
  • Android Glide 缓存机制深度解析与优化:从原理到极致实践
  • 集成电路学习:什么是ONNX开放神经网络交换
  • 深度学习③【卷积神经网络(CNN)详解:从卷积核到特征提取的视觉革命(概念篇)】
  • 详解 Transformer 激活值的内存占用公式
  • SOME/IP-SD报文中 Entry Format(条目格式)-理解笔记5
  • 算法题记录01:
  • 0826xd
  • Trip Footprints 旅行App开发全流程解析
  • UALink是什么?
  • 数字化转型:概念性名词浅谈(第四十二讲)
  • 牛客周赛 Round 106(小苯的方格覆盖/小苯的数字折叠/ 小苯的波浪加密器/小苯的数字变换/小苯的洞数组构造/ 小苯的数组计数)
  • 撤回git 提交
  • 算法训练营day62 图论⑪ Floyd 算法精讲、A star算法、最短路算法总结篇
  • C# 中常见的 五大泛型约束
  • [系统架构设计师]应用数学(二十一)
  • 云计算学习笔记——Linux用户和组的归属权限管理、附加权限、ACL策略管理篇
  • 联邦雪框架FedML自学---第四篇---案例一
  • 浅谈:运用幂的性质
  • 程序的“烽火台”:信号的产生与传递
  • 【基础-单选】使用http发起网络请求,需要以下哪种权限?
  • C6.2:小信号、交流电流增益分析