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 构建的具体类)关键设计特点:
- ChChassisConnector 继承 ChPart 而非 ChChassis:连接器不创建刚体,是纯力元素/约束元素
- ChChassisRear 继承 ChChassis:后车架也是完整的车架,有自己的 ChBodyAuxRef
- 三层继承模板化:ChPart → ChXxx抽象模板 → Xxx具体参数化类,这是 Chrono 所有子系统的统一模式
二、ChChassis 基类详解
2.1 核心职责
ChChassis 是所有车架子系统的根基类,承担以下职责:
- 持有 ChBodyAuxRef 刚体——整车多体系统的运动学根节点
- 管理三个 ChLoadContainer——bushing / 外部力 / 地形力各司其职
- 管理外部力/力矩载荷ExternalForceTorque 机制
- 管理标记点ChMarker(驾驶员位置、COM 等)
- 管理关节ChVehicleJoint(运动学约束或 bushing 的变体容器)
- 提供空气阻力模型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_body | shared_ptr<ChBodyAuxRef> | 车架物理刚体。用 ChBodyAuxRef 而非 ChBody 是因为车架参考点不一定是质心 |
m_container_bushings | shared_ptr<ChLoadContainer> | 收集所有 bushing(柔性连接)的载荷容器 |
m_container_external | shared_ptr<ChLoadContainer> | 收集所有外力/力矩的载荷容器 |
m_container_terrain | shared_ptr<ChLoadContainer> | 收集地形力的载荷容器(由轮胎-地形接口生成) |
m_external_loads | vector<ExternalForceTorque> | 外部载荷列表(空气阻力、自定义风力等) |
m_markers | vector<ChMarker> | 附着在车架上的标记点(驾驶员位置、COM等) |
m_fixed | bool | 车架是否固定到地面(调试/台架测试用) |
为什么用三个 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);}}设计要点:每个ExternalForceTorque在AddExternalForceTorque中会创建两个 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),