chrono车辆仿真_07_转向系统详解

转向系统详解

一、转向系统的角色:控制行驶方向

1.1 转向器的作用

复制代码
驾驶员打方向盘
      │
      ▼
   转向器 (ChSteering)
      │
      ├── 将方向盘转角转换为转向连杆位移
      ├── 通过转向横拉杆推动转向节(进而推转车轮)
      └── 产生阿克曼转向几何(内外轮转角不同)

转向器与悬架的配合:

复制代码
     转向器(方向盘→转向连杆)
          │
          │ m_link(转向连杆刚体)
          │
     ┌────┴────┐
     │         │
  左转向横拉杆  右转向横拉杆
     │         │
     ▼         ▼
  左悬架转向节  右悬架转向节
  (tierod连接)  (tierod连接)
     │         │
     ▼         ▼
  左轮偏转角度  右轮偏转角度

二、ChSteering 基类

2.1 类定义

cpp 复制代码
class CH_VEHICLE_API ChSteering : public ChPart {
  public:
    virtual ~ChSteering();

    /// 获取转向子系统相对于车架参考系的变换
    const ChFrame<>& GetRelTransform() const { return m_rel_xform; }

    /// 获取转向连杆刚体(悬架横拉杆的连接点)
    std::shared_ptr<ChBody> GetSteeringLink() const { return m_link; }

    /// 初始化:安装到车架的指定位置和方向
    virtual void Initialize(std::shared_ptr<ChChassis> chassis,
                            const ChVector3d& location,
                            const ChQuaternion<>& rotation);

    /// 同步:根据驾驶员转向输入 [-1, +1] 更新状态
    ///   steering = -1 → 向右打满
    ///   steering =  0 → 直行
    ///   steering = +1 → 向左打满
    virtual void Synchronize(double time,
                             const DriverInputs& driver_inputs) = 0;

    /// 约束违反日志
    virtual void LogConstraintViolations() {}

  protected:
    ChSteering(const std::string& name);

    ChFrame<> m_rel_xform;            ///< 相对于车架的位置和方向
    std::shared_ptr<ChBody> m_link;   ///< 转向连杆刚体
};

2.2 继承体系

复制代码
                    ChPart
                      │
                  ChSteering (抽象基类)
                  /        |         \
          ChPitmanArm  ChRackPinion  ChRotaryArm
          (循环球式)    (齿轮齿条式)  (旋转臂式)
               │
          ChPitmanArmShafts
          (带弹性转向柱)

2.3 四种转向类型对比

类型 机械结构 适用车型 转向连杆类型
RackPinion 齿轮齿条 轿车、SUV(HMMWV) 棱柱副滑动的齿条
PitmanArm 循环球+转向垂臂 卡车、越野车 垂臂+连杆的刚体
PitmanArmShafts 带弹性转向柱的循环球 高保真卡车 垂臂+连杆+ChShaft弹性柱
RotaryArm 旋转臂 军用/特种车辆 单个旋转臂

三、ChRackPinion --- 齿轮齿条转向

3.1 设计原理

齿轮齿条是乘用车中最常见的转向机构。Chrono 的实现做了简化------不显式建模 pinion 齿轮,而是直接通过 pinion 半径将方向盘转角转换为齿条位移。

复制代码
方向盘转角 θ
      │
      │ displacement = θ × pinion_radius
      ▼
齿条(棱柱副沿 Y 轴滑动)
      │
      ├── 左端 → 左横拉杆 → 左转向节
      └── 右端 → 右横拉杆 → 右转向节

3.2 内部结构

!\[Pasted image 20260528160125.png\|410]

3.3 关键源码解析

Initialize:

cpp 复制代码
void ChRackPinion::Initialize(std::shared_ptr<ChChassis> chassis,
                               const ChVector3d& location,
                               const ChQuaternion<>& rotation) {
    ChSteering::Initialize(chassis, location, rotation);

    m_parent = chassis;
    m_rel_xform = ChFrame<>(location, rotation);

    auto chassisBody = chassis->GetBody();
    auto sys = chassisBody->GetSystem();

    // 将转向参考系转换到绝对坐标系
    ChFrame<> steering_to_abs(location, rotation);
    steering_to_abs.ConcatenatePreTransformation(chassisBody->GetFrameRefToAbs());

    // 创建齿条刚体(位置在 steering link COM 处)
    ChVector3d link_pos = steering_to_abs.TransformPointLocalToParent(
        ChVector3d(0, GetSteeringLinkCOM(), 0));
    ChQuaternion<> link_rot = steering_to_abs.GetRot().GetNormalized();

    m_link = chrono_types::make_shared<ChBody>();
    m_link->SetName(m_name + "_link");
    m_link->SetPos(link_pos);
    m_link->SetRot(link_rot);
    m_link->SetMass(GetSteeringLinkMass());
    m_link->SetInertiaXX(GetSteeringLinkInertia());
    sys->AddBody(m_link);

    // 棱柱副:齿条只能沿 Y 轴平移(相对于车架)
    m_prismatic = chrono_types::make_shared<ChLinkLockPrismatic>();
    m_prismatic->SetName(m_name + "_prismatic");
    m_prismatic->Initialize(chassisBody, m_link,
        ChFrame<>(link_pos, link_rot * QuatFromAngleX(CH_PI_2)));
    sys->AddLink(m_prismatic);

    // 线性作动器:驱动齿条沿 Y 轴移动
    // offset 必须大于最大齿条位移,避免奇点
    double offset = 2;
    ChVector3d pt1 = link_pos;
    ChVector3d pt2 = link_pos - offset * link_rot.GetAxisY();

    m_actuator = chrono_types::make_shared<ChLinkLockLinActuator>();
    m_actuator->SetName(m_name + "_actuator");
    m_actuator->Initialize(chassisBody, m_link, false,
        ChFrame<>(pt1, link_rot), ChFrame<>(pt2, link_rot));
    m_actuator->SetDistanceOffset(offset);
    sys->AddLink(m_actuator);
}

Synchronize:

cpp 复制代码
void ChRackPinion::Synchronize(double time, const DriverInputs& driver_inputs) {
    // 方向盘转角 → pinion 转角 → 齿条位移
    double angle = driver_inputs.m_steering * GetMaxAngle();
    double displ = angle * GetPinionRadius();  // s = r × θ

    // 设置线性作动器的目标位移
    if (auto fun = std::dynamic_pointer_cast<ChFunctionConst>(
            m_actuator->GetActuatorFunction()))
        fun->SetConstant(displ);
}

物理关系:

复制代码
方向盘转角 θ (由 driver_inputs.m_steering 换算)
  │  θ = steering × GetMaxAngle()
  ▼
Pinion 线位移 s = θ × r_pinion
  │
  ▼
齿条位移 = s (沿 Y 轴)
  │
  ▼
横拉杆 → 转向节 → 车轮偏转

3.4 JSON 配置示例

json 复制代码
{
  "Name": "HMMWV Rack-Pinion Steering",
  "Type": "Steering",
  "Template": "RackPinion",
  "Steering Link": {
    "Mass": 9.072,
    "COM": 0,
    "Inertia": [1, 1, 1],
    "Radius": 0.03,
    "Length": 0.896
  },
  "Pinion": {
    "Radius": 0.1,
    "Maximum Angle (deg)": 50
  }
}
JSON 字段 含义
Steering Link.Mass 齿条质量 (kg)
Steering Link.COM 齿条质心 Y 向偏移 (m)
Steering Link.Inertia 齿条转动惯量 (kg·m²)
Steering Link.Radius 可视化半径 (m)
Steering Link.Length 齿条长度 (m)
Pinion.Radius pinion 齿轮半径 (m)
Pinion.Maximum Angle 最大方向盘转角 (°)

四、ChPitmanArm --- 循环球式转向(基础版)

4.1 设计原理

Pitman Arm(转向垂臂)是卡车/越野车中常见的转向机构。方向盘转动通过转向器(循环球)带动 Pitman 臂摆动,再通过转向连杆推动车轮。

复制代码
方向盘 → 转向器 → Pitman 臂(绕 Z 轴旋转)
                      │
                 万向节 (Universal Joint)
                      │
                 转向连杆 (Steering Link)
                 │         │
            横拉杆左     横拉杆右
               │           │
            左转向节      右转向节

4.2 内部结构

!\[Pasted image 20260528160521.png]

4.3 关键源码解析

Initialize(创建 3 个刚体 + 3 个约束):

cpp 复制代码
// ① 转向连杆 (Steering Link)
m_link  → ChBody(连接到横拉杆)
// ② Pitman 臂 (Pitman Arm)
m_arm   → ChBody(旋转推动连杆)
// ③ 约束
m_revolute → ChLinkMotorRotationAngle (Pitman臂↔车架,由电机驱动)
m_universal → ChLinkUniversal (Pitman臂↔转向连杆)
m_revsph   → ChLinkRevoluteSpherical (转向连杆↔车架,带惰性连杆)

Synchronize:

cpp 复制代码
void ChPitmanArm::Synchronize(double time, const DriverInputs& driver_inputs) {
    // 设置旋转电机的目标角度
    auto fun = std::static_pointer_cast<ChFunctionSetpoint>(
        m_revolute->GetAngleFunction());
    fun->SetSetpoint(getMaxAngle() * driver_inputs.m_steering, time);
}

方向盘转角直接作为 Pitman 臂绕 Z 轴旋转的角度输入。

4.4 硬点(Hardpoint)设计

ChPitmanArm 使用 8 个硬点定义完整的转向机构几何:

复制代码
硬点编号       名称                    说明
─────────────────────────────────────────────────
STEERINGLINK   转向连杆 COM            转向连杆质心位置
PITMANARM      Pitman 臂 COM          垂臂质心位置
REV            旋转副位置              Pitman 臂与车架连接点
UNIV           万向节位置              Pitman 臂与转向连杆连接点
REVSPH_R       回转副位置              惰性连杆的车架端
REVSPH_S       球铰位置                惰性连杆的转向连杆端
TIEROD_PA      横拉杆 Pitman 侧        左侧横拉杆连接点
TIEROD_IA      横拉杆惰性臂侧          右侧横拉杆连接点

4.5 JSON 配置示例

json 复制代码
{
  "Name": "HMMWV Pitman Arm Steering",
  "Type": "Steering",
  "Template": "PitmanArm",
  "Steering Link": {
    "Mass": 3.681,
    "COM": [0.129, 0, 0],
    "Moments of Inertia": [0.252, 0.00233, 0.254],
    "Products of Inertia": [0, 0, 0],
    "Radius": 0.03
  },
  "Pitman Arm": {
    "Mass": 1.605,
    "COM": [0.064, 0.249, 0],
    "Moments of Inertia": [0.00638, 0.00756, 0.00150],
    "Radius": 0.02
  },
  "Revolute Joint": {
    "Location": [0, 0.249, 0],
    "Direction": [0, 0, 1],
    "Maximum Angle (deg)": 30
  },
  "Universal Joint": {
    "Location": [0.129, 0.249, 0],
    "Direction Arm": [0, 0, 1],
    "Direction Link": [1, 0, 0]
  },
  "Revolute-Spherical Joint": {
    "Location Chassis": [0, -0.325, 0],
    "Location Link": [0.129, -0.325, 0],
    "Direction": [0, 0, 1]
  },
  "Tierod Locations": {
    "Pitman Side": [0.195, 0.448, 0.035],
    "Idler Side": [0.195, -0.448, 0.035]
  }
}

五、ChPitmanArmShafts --- 带弹性转向柱的循环球式转向

5.1 设计原理

在 ChPitmanArm 的基础上增加了弹性转向柱的建模。方向盘与 Pitman 臂之间的转向柱不再是刚性连接,而是通过一组 ChShaft + 弹簧/齿轮模拟真实转向柱的扭转弹性。

5.2 转向柱内部结构

复制代码
ChShaft 传动链(全部沿 REV_AXIS 方向):

方向盘侧                        Pitman 臂侧
   │                               │
   ▼                               ▼
m_shaft_C ──▶ m_shaft_C1 ──▶ m_shaft_A1 ──▶ m_shaft_A ──▶ Pitman 臂
(固定到车架)    (电机)       (弹簧或齿轮)   (减速齿轮)    (ChShaftBodyRotation)
                                    │
                    ┌───────────────┼───────────────┐
                    │ 刚性模式       │ 弹性模式       │
                    │ ChShaftsGear  │ ChShafts-     │
                    │ (传动比=1)     │ TorsionSpring │
                    └───────────────┴───────────────┘

5.3 各 ChShaft 的职责

元素 类型 作用
m_shaft_C ChShaft (fixed) 固定端,代表方向盘侧壳体
m_shaft_C1 ChShaft 由电机驱动,代表方向盘转角输入
m_shaft_A1 ChShaft 与 m_shaft_C1 通过弹簧/刚性连接
m_shaft_A ChShaft 通过减速齿轮连接到 m_shaft_A1
m_shaft_motor ChShaftsMotorPosition 在 m_shaft_C 和 m_shaft_C1 之间施加转角
m_shaft_gear ChShaftsGear 减速齿轮比(getGearRatio > 1)
m_shaft_arm ChShaftBodyRotation 将 m_shaft_A 连接到 Pitman 臂刚体
m_rigid_connection ChShaftsGear 刚性连接(刚性转向柱模式)
m_spring_connection ChShaftsTorsionSpring 弹性连接(弹性转向柱模式)

5.4 关键源码解析

Initialize(4 个 ChShaft + 5 个 ChShaftsCouple):

cpp 复制代码
// 创建 4 个传动轴(全部绕 REV_AXIS 方向)
m_shaft_C  = make_shared<ChShaft>();  // 固定端
m_shaft_C->SetInertia(inertia);
m_shaft_C->SetFixed(true);  // 固定到车架
sys->AddShaft(m_shaft_C);

m_shaft_C1 = make_shared<ChShaft>();  // 电机输出端
m_shaft_C1->SetInertia(inertia);
sys->AddShaft(m_shaft_C1);

m_shaft_A1 = make_shared<ChShaft>();  // 齿轮输入端
m_shaft_A1->SetInertia(inertia);
sys->AddShaft(m_shaft_A1);

m_shaft_A = make_shared<ChShaft>();   // 齿轮输出端→Pitman臂
m_shaft_A->SetInertia(inertia);
sys->AddShaft(m_shaft_A);

// 电机:在 m_shaft_C 和 m_shaft_C1 之间施加转角
m_shaft_motor = make_shared<ChShaftsMotorPosition>();
m_shaft_motor->Initialize(m_shaft_C, m_shaft_C1);
// 电机的目标转角在 Synchronize 中设置

// 减速齿轮:m_shaft_A → m_shaft_A1 (减速)
m_shaft_gear = make_shared<ChShaftsGear>();
m_shaft_gear->SetTransmissionRatio(getGearRatio());  // > 1
m_shaft_gear->Initialize(m_shaft_A, m_shaft_A1);
sys->Add(m_shaft_gear);

// 连接 m_shaft_A 到 Pitman 臂刚体
m_shaft_arm = make_shared<ChShaftBodyRotation>();
m_shaft_arm->Initialize(m_shaft_A, m_arm, dirs[REV_AXIS]);
sys->Add(m_shaft_arm);

// 连接 m_shaft_A1 和 m_shaft_C1:刚性或弹性
if (m_rigid) {
    m_rigid_connection = make_shared<ChShaftsGear>();
    m_rigid_connection->SetTransmissionRatio(1.0);
    m_rigid_connection->Initialize(m_shaft_A1, m_shaft_C1);
    sys->Add(m_rigid_connection);
} else {
    m_spring_connection = make_shared<ChShaftsTorsionSpring>();
    m_spring_connection->SetTorsionalStiffness(getSteeringCompliance());
    m_spring_connection->Initialize(m_shaft_C1, m_shaft_A1);
    sys->Add(m_spring_connection);
}

Synchronize:

cpp 复制代码
void ChPitmanArmShafts::Synchronize(double time, const DriverInputs& driver_inputs) {
    auto fun = std::static_pointer_cast<ChFunctionSetpoint>(
        m_shaft_motor->GetPositionFunction());
    fun->SetSetpoint(getMaxAngle() * driver_inputs.m_steering, time);
}

5.5 弹性转向柱的效果

复制代码
刚性模式 (m_rigid = true):
  方向盘转角 = Pitman 臂转角(立即传递,无延迟)

弹性模式 (m_rigid = false):
  方向盘转角 → 扭转弹簧 → Pitman 臂转角
  效果:方向盘先转动,弹簧扭转蓄力,Pitman 臂逐渐跟随
  模拟真实车辆的"转向柱扭转弹性"和"路感"

5.6 转向刚性/弹性对比

特性 刚性列 (RigidColumn) 弹性列 (CompliantColumn)
连接方式 ChShaftsGear (ratio=1) ChShaftsTorsionSpring
传递 转角直接传递 力矩通过弹簧传递
响应 无延迟 有延迟(弹性变形)
适用 实时仿真 高保真/路感研究

六、ChRotaryArm --- 旋转臂转向

6.1 设计原理

最简单的转向形式------一个旋转臂直接推动横拉杆。常用于军用车辆和特种车辆。

复制代码
方向盘 → 旋转臂(绕 Z 轴旋转)
              │
          横拉杆
              │
          转向节 → 车轮偏转

6.2 内部结构

只有一个刚体(既是旋转臂又是转向连杆),通过旋转电机副连接到车架:

cpp 复制代码
// 唯一的刚体:m_link = 旋转臂
m_link = make_shared<ChBody>();
m_link->SetPos(0.5 * (points[ARM_L] + points[ARM_C]));

// 唯一的约束:旋转电机副
m_revolute = make_shared<ChLinkMotorRotationAngle>();
m_revolute->Initialize(chassisBody, m_link, ...);

6.3 硬点设计

只有 2 个硬点:

硬点 说明
ARM_C 旋转臂与车架的连接点(旋转副位置)
ARM_L 旋转臂与横拉杆的连接点

6.4 Synchronize

cpp 复制代码
void ChRotaryArm::Synchronize(double time, const DriverInputs& driver_inputs) {
    auto fun = std::static_pointer_cast<ChFunctionSetpoint>(
        m_revolute->GetAngleFunction());
    fun->SetSetpoint(getMaxAngle() * driver_inputs.m_steering, time);
}

与 ChPitmanArm 完全相同------设置旋转电机的目标角度。


七、转向器与悬架的连接

7.1 GetSteeringLink()

转向器与悬架的接口是通过 ChSteering::GetSteeringLink() 暴露的转向连杆刚体。

悬架的横拉杆(tierod)在初始化时获取转向连杆的句柄:

复制代码
ChRackPinion::Initialize()
  └── m_link = 齿条刚体 (ChBody)

ChWheeledVehicle::Initialize()
  └── 对每个车轴:
        m_axles[i]->m_suspension->Initialize(..., m_steering->GetSteeringLink(), ...)

悬架通过横拉杆约束(通常是 ChLinkDistance 或 ChLinkRevoluteSpherical)

将转向连杆的运动传递到转向节(spindle),最终实现车轮偏转。

7.2 转向角对车轮的实际影响

复制代码
方向盘输入 → 转向连杆位移 → 横拉杆推动 → 转向节旋转 → 车轮偏转

这个传递路径在悬架侧完成,转向器侧只负责产生转向连杆的位移/旋转。

八、四种转向模型对比

维度 RackPinion PitmanArm PitmanArmShafts RotaryArm
机构类型 齿轮齿条 循环球+垂臂 循环球+弹性柱 旋转臂
连杆运动 棱柱副平移 万向节空间运动 万向节空间运动 旋转副旋转
转向柱模型 无 无 ChShaft 弹性柱 无
刚体数量 1(齿条) 2(垂臂+连杆) 2 + 4 ChShaft 1(旋转臂)
约束数量 2(棱柱副+作动器) 3(电机+万向+回转球铰) 3 + 5 ChShaftCouple 1(电机副)
自由度 1(Y 平移) 1(垂臂旋转) 1(垂臂旋转,弹性延迟) 1(旋转)
质量惯性 齿条质量 垂臂+连杆质量 垂臂+连杆+4轴 臂质量
JSON 复杂度 简单(7 参数) 复杂(25+ 参数) 复杂 + 弹性参数 简单(5 参数)
适用场景 乘用车实时仿真 卡车/越野车 高保真卡车 特种车辆

九、API 总结

9.1 ChSteering 基类 API

API 说明
GetRelTransform() 转向器相对车架的变换矩阵
GetSteeringLink() 获取转向连杆刚体(悬架连接点)
Initialize(chassis, location, rotation) 在车架指定位置安装转向器
Synchronize(time, driver_inputs) 根据驾驶员转向输入更新状态
LogConstraintViolations() 输出约束违反情况

9.2 ChRackPinion 特有 API

API 说明
GetSteeringLinkMass() 齿条质量
GetSteeringLinkInertia() 齿条转动惯量
GetSteeringLinkCOM() 齿条质心 Y 偏置
GetPinionRadius() Pinion 齿轮半径
GetMaxAngle() 最大方向盘转角

9.3 ChPitmanArm 特有 API

API 说明
getLocation(PointId) 返回指定硬点的位置
getDirection(DirectionId) 返回指定方向向量
getSteeringLinkMass() / getPitmanArmMass() 质量
getMaxAngle() 最大旋转角度

9.4 ChPitmanArmShafts 特有 API

API 说明
getGearRatio() 转向柱减速比 (>1)
getSteeringCompliance() 转向柱扭转刚度 (N·m/rad)
getSteeringColumnInertia() 转向柱转动惯量
GetShaftInformation(...) 调试用------输出所有 ChShaft 的状态

9.5 ChRotaryArm 特有 API

API 说明
getPitmanArmMass() 旋转臂质量
getPitmanArmInertia*() 旋转臂转动惯量
getMaxAngle() 最大旋转角度

十、设计哲学总结

复制代码
Chrono 转向系统的四条核心原则:

1. "硬点驱动几何"
     所有转向机构的几何由硬点 (Hardpoint) 定义,
     派生类通过纯虚函数 getLocation()/getDirection() 提供几何数据。

2. "电机驱动转向"
     所有转向类型都使用 ChLinkMotorRotationAngle 或
     ChLinkLockLinActuator 作为驱动源,将驾驶员输入
     直接转换为约束运动,不涉及液压助力或 EPS 建模。

3. "转向器只负责转向连杆"
     转向器只生成转向连杆(m_link)的位移/旋转,
     横拉杆到车轮的传递路径在悬架侧完成。

4. "弹性可选"
     PitmanArmShafts 提供了可选的弹性转向柱建模,
     通过在方向盘和 Pitman 臂之间插入扭转弹簧实现,
     适用于需要研究转向路感的场景。
相关推荐
热金鼠3 小时前
chrono车辆仿真_09_动力总成系统详解
chrono·车辆仿真
hjjdebug1 年前
std::chrono类的简单使用实例及分析
duration·chrono·time_point·system_clock
许野平2 年前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
Black.Spider2 年前
C++计算程序运行时间
c++·chrono
会编程的大白熊3 年前
rust - 常用时间处理
rust·chrono