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

chrono车辆仿真_03_车架系统详解

车架系统详解

一、车架系统的整体架构

1.1 车架在整车中的角色

车架(Chassis)是车辆的"骨架"——所有其他子系统都直接或间接地附着在车架上。在 Chrono 物理引擎中,车架是唯一一个创建 ChBody 的子系统(其他子系统如制动器、传动系是力元素,惯量为零,不贡献质量)。

ChVehicle(整车) │ ┌─────────┼─────────┐ │ │ m_chassis m_chassis_rear[] (主车架) (后车架列表) │ │ │ 通过 m_chassis_connectors[] 连接 │ │ ┌──────────┼──────────┐ │ │ │ │ │ 悬架[0] 悬架[1] 转向[0] SubChassis[] │ │ │ │ 车轮 车轮 转向连杆 平衡梁

1.2 完整类层次图

ChPart (所有子系统根基类) │ ├── ChChassis(主车架基类) │ │ │ ├── ChRigidChassis(刚性车架模板) │ │ │ │ │ ├── RigidChassis(JSON 构建的具体类) │ │ └── HMMWV_Chassis(硬编码具体类) │ │ │ └── ChChassisRear(后车架基类) │ │ │ └── ChRigidChassisRear(刚性后车架模板) │ │ │ └── RigidChassisRear(JSON 构建的具体类) │ ├── ChChassisConnector(车架连接器基类,继承 ChPart 非 ChChassis) │ │ │ ├── ChChassisConnectorArticulated → ChassisConnectorArticulated │ ├── ChChassisConnectorHitch → ChassisConnectorHitch │ └── ChChassisConnectorTorsion → ChassisConnectorTorsion │ └── ChSubchassis(子车架基类) │ └── ChBalancer(平衡梁子车架) │ └── Balancer(JSON 构建的具体类)

关键设计特点

  1. ChChassisConnector 继承 ChPart 而非 ChChassis:连接器不创建刚体,是纯力元素/约束元素
  2. ChChassisRear 继承 ChChassis:后车架也是完整的车架,有自己的 ChBodyAuxRef
  3. 三层继承模板化:ChPart → ChXxx抽象模板 → Xxx具体参数化类,这是 Chrono 所有子系统的统一模式

二、ChChassis 基类详解

2.1 核心职责

ChChassis 是所有车架子系统的根基类,承担以下职责:

  1. 持有 ChBodyAuxRef 刚体——整车多体系统的运动学根节点
  2. 管理三个 ChLoadContainer——bushing / 外部力 / 地形力各司其职
  3. 管理外部力/力矩载荷ExternalForceTorque 机制
  4. 管理标记点ChMarker(驾驶员位置、COM 等)
  5. 管理关节ChVehicleJoint(运动学约束或 bushing 的变体容器)
  6. 提供空气阻力模型ChassisDragForce

2.2 头文件全景(ChChassis.h 278行)

classCH_VEHICLE_APIChChassis:publicChPart{public:ChChassis(conststd::string&name,boolfixed=false);virtual~ChChassis();// ===== 纯虚函数(子类必须实现)=====virtualChCoordsys<>GetLocalDriverCoordsys()const=0;// ===== 可选覆写的虚函数 =====virtualconstChVector3dGetLocalPosRearConnector()const{returnChVector3d(0);}// ===== 获取刚体句柄 =====std::shared_ptr<ChBodyAuxRef>GetBody()const{returnm_body;}ChSystem*GetSystem()const{returnm_body->GetSystem();}// ===== 状态查询 =====constChVector3d&GetPos()const;ChQuaternion<>GetRot()const;ChVector3dGetDriverPos()const;doubleGetSpeed()const;doubleGetCOMSpeed()const;doubleGetRollRate()const;doubleGetPitchRate()const;doubleGetYawRate()const;doubleGetTurnRate()const;ChVector3dGetPointLocation(constChVector3d&locpos)const;ChVector3dGetPointVelocity(constChVector3d&locpos)const;ChVector3dGetPointAcceleration(constChVector3d&locpos)const;// ===== 初始化 =====virtualvoidInitialize(ChSystem*system,constChCoordsys<>&chassisPos,doublechassisFwdVel,intcollision_family=0);// ===== 碰撞 =====virtualvoidEnableCollision(boolstate)=0;voidSetFixed(boolval){m_body->SetFixed(val);}boolIsFixed()const{returnm_body->IsFixed();}// ===== Bushing/连接器 =====boolHasBushings()const{returnm_container_bushings->GetNumLoads()>0;}voidAddJoint(std::shared_ptr<ChVehicleJoint>joint);staticvoidRemoveJoint(std::shared_ptr<ChVehicleJoint>joint);// ===== 标记点 =====voidAddMarker(conststd::string&name,constChFrame<>&frame);conststd::vector<std::shared_ptr<ChMarker>>&GetMarkers()const{returnm_markers;}// ===== 外力系统 =====voidSetAerodynamicDrag(doubleCd,doublearea,doubleair_density);voidAddExternalForceTorque(std::shared_ptr<ExternalForceTorque>load);voidAddTerrainLoad(std::shared_ptr<ChLoadBase>terrain_load);// ===== 同步 =====virtualvoidSynchronize(doubletime);// ===== 惯性属性(两阶段)=====virtualvoidInitializeInertiaProperties()override;virtualvoidUpdateInertiaProperties()override;// ===== 内部类:自定义外力/力矩 =====classExternalForceTorque{public:ExternalForceTorque(conststd::string&name=""){m_name=name;}virtual~ExternalForceTorque(){}virtualvoidUpdate(doubletime,constChChassis&chassis,ChVector3d&force,ChVector3d&point,ChVector3d&torque){}std::string m_name;};protected:virtualdoubleGetBodyMass()const=0;virtualChFrame<>GetBodyCOMFrame()const=0;virtualChMatrix33<>GetBodyInertia()const=0;std::shared_ptr<ChBodyAuxRef>m_body;std::shared_ptr<ChLoadContainer>m_container_bushings;std::shared_ptr<ChLoadContainer>m_container_external;std::shared_ptr<ChLoadContainer>m_container_terrain;std::vector<std::shared_ptr<ExternalForceTorque>>m_external_loads;std::vector<std::shared_ptr<ChMarker>>m_markers;boolm_fixed;};

2.3 成员变量逐一解释

成员类型作用
m_bodyshared_ptr<ChBodyAuxRef>车架物理刚体。用 ChBodyAuxRef 而非 ChBody 是因为车架参考点不一定是质心
m_container_bushingsshared_ptr<ChLoadContainer>收集所有 bushing(柔性连接)的载荷容器
m_container_externalshared_ptr<ChLoadContainer>收集所有外力/力矩的载荷容器
m_container_terrainshared_ptr<ChLoadContainer>收集地形力的载荷容器(由轮胎-地形接口生成)
m_external_loadsvector<ExternalForceTorque>外部载荷列表(空气阻力、自定义风力等)
m_markersvector<ChMarker>附着在车架上的标记点(驾驶员位置、COM等)
m_fixedbool车架是否固定到地面(调试/台架测试用)

为什么用三个 ChLoadContainer?

将 bushing、外部力、地形力分开存放,便于在车架销毁时分别清理(析构函数中逐一 Remove),也便于调试时知道力的来源。

2.4 构造函数与析构函数

// 构造函数:创建三个载荷容器ChChassis::ChChassis(conststd::string&name,boolfixed):ChPart(name),m_fixed(fixed){// 构造时立即创建三个载荷容器// (但在 Initialize 之前不会加入 ChSystem),这是因为载荷容器必须和刚体在同一个物理系统中注册。m_container_bushings=chrono_types::make_shared<ChLoadContainer>();m_container_external=chrono_types::make_shared<ChLoadContainer>();m_container_terrain=chrono_types::make_shared<ChLoadContainer>();}// 析构函数:从系统中移除刚体和三个载荷容器ChChassis::~ChChassis(){if(!m_initialized)return;autosys=m_body->GetSystem();if(!sys)return;sys->Remove(m_body);sys->Remove(m_container_bushings);sys->Remove(m_container_external);sys->Remove(m_container_terrain);}

2.5 Initialize 流程(逐行分析)

voidChChassis::Initialize(ChSystem*system,constChCoordsys<>&chassisPos,doublechassisFwdVel,intcollision_family){// ① 坐标系转换// 用户传入的 chassisPos 是基于"当前世界坐标系"约定的(如 Z-up)// 需要转换为 Chrono 内部的世界坐标系ChFrame<>chassis_pos(chassisPos.pos,ChMatrix33<>(chassisPos.rot)*ChWorldFrame::Rotation().transpose());// ② 创建 ChBodyAuxRef 刚体m_body=chrono_types::make_shared<ChBodyAuxRef>();m_body->SetTag(0);// Tag=0 标记为车架m_body->SetName(m_name+" body");m_body->SetMass(GetBodyMass());// 子类提供的质量m_body->SetFrameCOMToRef(GetBodyCOMFrame());// 质心偏移m_body->SetInertia(GetBodyInertia());// 子类提供的惯量m_body->SetFixed(m_fixed);// 是否固定到地面// ③ 设置初始位姿和速度m_body->SetFrameRefToAbs(chassis_pos);m_body->SetPosDt(chassisFwdVel*chassis_pos.TransformDirectionLocalToParent(ChVector3d(1,0,0)));// ④ 添加到物理系统system->Add(m_body);system->Add(m_container_bushings);system->Add(m_container_external);system->Add(m_container_terrain);// ⑤ 预定义标记点AddMarker("driver position",ChFrame<>(GetLocalDriverCoordsys()));AddMarker("COM",GetCOMFrame());// ⑥ 标记已初始化(注意:collision_family 在此基类中未使用,由子类处理)m_initialized=true;}

关键理解:ChBodyAuxRef 允许参考点(Ref)和质心(COM)分离。GetBodyCOMFrame()返回质心相对于参考点的位姿。物理引擎内部用参考点做运动学积分,用力学方程时自动转换到质心。

2.6 Synchronize 流程

voidChChassis::Synchronize(doubletime){// 遍历所有外部力/力矩,更新其数值// 每个 ExternalForceTorque 对应 2 个 ChLoad:力的索引为 2*i,力矩的索引为 2*i+1auto&loads=m_container_external->GetLoadList();ChVector3d force;ChVector3d point;ChVector3d torque;for(size_t i=0;i<m_external_loads.size();++i){m_external_loads[i]->Update(time,*this,force,point,torque);autobody_force=std::static_pointer_cast<ChLoadBodyForce>(loads[2*i]);body_force->SetForce(force,true);body_force->SetApplicationPoint(point,true);autobody_torque=std::static_pointer_cast<ChLoadBodyTorque>(loads[2*i+1]);body_torque->SetTorque(torque,true);}}

设计要点:每个ExternalForceTorqueAddExternalForceTorque中会创建两个 ChLoad 对象:一个ChLoadBodyForce(力)和一个ChLoadBodyTorque(力矩),都作用在m_body上。所以loads中的元素数是m_external_loads.size() * 2

2.6 AddExternalForceTorque 实现

voidChChassis::AddExternalForceTorque(std::shared_ptr<ExternalForceTorque>load){m_external_loads.push_back(load);// 为每个 ExternalForceTorque 创建一对 ChLoad(力 + 力矩)autoforce_load=chrono_types::make_shared<ChLoadBodyForce>(m_body,ChVector3d(0),true,ChVector3d(0),true);force_load->SetName(load->m_name+"_force");m_container_external->Add(force_load);autotorque_load=chrono_types::make_shared<ChLoadBodyTorque>(m_body,ChVector3d(0),
http://www.cnnetsun.cn/news/2624508.html

相关文章:

  • 如何通过Python快速调用Taotoken平台上的多款大模型
  • 怎样完整导出微信聊天记录:WeChatMsg终极数据保存实战指南
  • 基于树莓派与Python的智能调酒机DIY:从GPIO控制到GUI开发全解析
  • 高层次综合设计中一些细节
  • ESP32-Arduino 实战指南:构建工业级物联网解决方案
  • 从1080p摄像机到视频服务器:手把手拆解GS2972-IBE3这颗3G-SDI芯片的实战应用
  • GitHub Copilot与Cursor深度对比:AI编程助手如何重塑开发工作流
  • 照着用就行:2026年最火AI论文写作工具榜单,免费生成高质初稿无忧
  • 为什么选择 tf_efficientnet_b7.ns_jft_in1k?深度解析Noisy Student训练优势
  • DesignKit:基于CSS变量与AI协议的开源设计系统,加速原型到代码工作流
  • Qwen-Edit-2509-Multiple-angles:基于LoRA的视角控制技术架构解析与实现
  • 为工程团队构建AI上下文层:从RAG架构到IDE集成的实践指南
  • AlwaysOnTop:Windows窗口管理的终极解决方案,让重要信息永不消失
  • 【限时解密】某头部金融科技公司内部禁用的Claude测试生成策略——因违反GDPR导致测试数据泄露的真实案例(含合规改造checklist)
  • LayoutLMv3-base-chinese应用场景大全:表单理解到文档视觉问答的8大案例
  • Qwopus3.5-27B-v3-GGUF开源贡献指南:如何参与项目开发和社区建设
  • YOLOv10-NPU优化技术终极指南:PYTORCH_NPU_ALLOC_CONF参数配置深度解析 [特殊字符]
  • 3分钟搞定!猫抓浏览器插件:网页视频下载的终极解决方案
  • 【腾讯云AI平台深度适配报告】:DeepSeek-V2.5在TI-ONE环境中的Token吞吐量实测提升47.3%
  • ScrollBooster核心功能深度解析:弹性回弹、惯性滚动与方向锁定
  • 如何在Vue3项目中快速集成专业代码编辑器:vue-codemirror完整指南
  • Ascend-SACT/Mineru-Optimization环境变量配置:解锁NPU性能的10个关键参数 [特殊字符]
  • 13702黄大年茶思屋榜文137期·第二题:基于N:M Sparsity的激活稀疏量化技术
  • Ubuntu 20.04上安装OpenJDK 8,为什么我推荐你用apt而不是手动下载?
  • 从Mate桌面到QT应用:深度解析麒麟系统高分辨率适配的‘坑’与‘桥’
  • Gemini客单价临界点突破指南,30天内完成价值传递重构、交付升级与合同重谈(附合规话术包)
  • 基于Arduino的音乐可视化LED系统:从声音采集到动态光影的完整实现
  • Arduino超声波避障系统:从传感器原理到RC车智能改造实战
  • Prometheus - 安全加固:端口防护 / 认证授权 / HTTPS 配置
  • 如何实现3种安全场景下的本地Cookie管理:隐私优先的浏览器扩展方案