转向系统详解
一、转向系统的角色:控制行驶方向
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 臂之间插入扭转弹簧实现,
适用于需要研究转向路感的场景。