source/physxvehicle/ は PhysX SDK の車両シミュレーションモジュール(Vehicle2 API)の実装である。コンポーネントベースのアーキテクチャを採用し、タイヤ・サスペンション・駆動系・ステアリング・剛体力学を独立したコンポーネントとして分離している。
公開APIヘッダは include/vehicle2/ に配置され、ソース実装は source/physxvehicle/src/ に配置される。名前空間は physx::vehicle2。
Vehicle2 のコアは コンポーネントシーケンス パターンで構築される。
PxVehicleComponent — 抽象基底クラス(純粋仮想 update(dt, context))
PxVehicleComponentSequence — コンポーネントの実行順序を管理
PxVehicleComponentSequence は以下の特徴を持つ:
- リンクドリスト方式: 各要素(コンポーネントまたはサブグループ)はリンクドリスト構造で連結
- ネスト可能なサブステップ:
beginSubstepGroup(nbSubSteps)/endSubstepGroup()でサブステップグループをネスト可能(最大16グループ) - タイムステップ分割: サブグループ内のコンポーネントは
dt / (parentMultiplier * nbSteps)で呼び出される - 早期中断: コンポーネントの
update()がfalseを返すとシーケンス全体が中断される - 制限: 最大64コンポーネント、最大16サブグループ
ソースコード全体で統一されたパターン:
| 種別 | 役割 | ファイル例 |
|---|---|---|
| Functions | 外部公開の計算処理API | VhTireFunctions.cpp |
| Helpers | 内部ユーティリティ(座標変換、パラメータ変換等) | VhTireHelpers.cpp |
| Params | 不変パラメータ構造体 | PxVehicleTireParams.h |
| States | 可変状態構造体 | PxVehicleTireStates.h |
| Components | コンポーネントクラス(update関数を提供) | PxVehicleTireComponents.h |
PxVehicleArrayData<T> — AoS(Array of Structs)と AoP(Array of Pointers)の両方に対応ユーザーは自由なメモリレイアウトでデータを保持でき、setData(T*) または setData(T*const*) で指定する。Vehicle2 側はインデックスアクセスで透過的に扱う。
PxVehicleFrame — 縦(lng)・横(lat)・垂直(vrt)軸の定義(±X/±Y/±Z)
PxVehicleScale — 長さスケール倍率(1.0=メートル、100.0=センチメートル)全パラメータ構造体に transformAndScale(srcFrame, trgFrame, srcScale, trgScale) メソッドが実装されており、任意の座標系・スケール間で変換できる。デフォルトは +X=前方, +Y=横, +Z=上 のメートル系。
gravity // 重力加速度ベクトル
frame // PxVehicleFrame(座標系定義)
scale // PxVehicleScale(スケール)
tireSlipParams // タイヤスリップ安定化パラメータ
tireStickyParams // 低速時スティッキータイヤパラメータ
thresholdForwardSpeedForWheelAngleIntegration // ホイール回転角ブレンド閾値速度
pvdContext // OmniPVD(可視化デバッガ)コンテキスト基本コンテキストを継承し、PhysX固有のフィールドを追加:
physxUnitCylinderSweepMesh // 地面検出用の単位シリンダ凸メッシュ
physxScene // クエリ対象のPxScene
physxActorUpdateMode // eAPPLY_VELOCITY or eAPPLY_ACCELERATION
physxActorWakeCounterResetValue // ウェイクカウンタリセット値(デフォルト: 20 * 0.02s)
physxActorWakeCounterThreshold // リセット判定閾値ソース: src/commands/VhCommandHelpers.cpp
ヘッダ: include/vehicle2/commands/
ユーザー入力(スロットル、ブレーキ、ステア、クラッチ)を各ホイールへの応答値に変換する。
PxVehicleCommandResponseParams:
maxResponse // 最大応答値
wheelResponseMultipliers[MAX_WHEELS] // 各ホイールの応答倍率(0〜1)コマンドの応答値は command * maxResponse * wheelResponseMultipliers[wheelId] で計算される。
ソース: src/steering/VhSteeringFunctions.cpp
ヘッダ: include/vehicle2/steering/
PxVehicleSteerCommandResponseParams:
maxResponse // 最大ステア角(ラジアン)
wheelResponseMultipliers // ホイール毎の倍率
PxVehicleAckermannParams:
wheelBase // 軸距(前輪軸〜後輪軸の距離)
trackWidth // トレッド幅(左右輪間距離)
strength // 補正強度 [0, 1](0=補正なし、1=完全アッカーマン)
wheelIds[2] // 対象ホイールID(通常は左前・右前)アッカーマン補正: 旋回時に内側輪と外側輪の舵角差を幾何学的に正しく調整する。strength=1.0 で理想的なアッカーマン角度、strength=0.0 で左右等角(パラレルステア)。
ソース: src/suspension/VhSuspensionFunctions.cpp, VhSuspensionHelpers.cpp
ヘッダ: include/vehicle2/suspension/
PxVehicleSuspensionParams:
suspensionAttachment // 最大圧縮時のホイール位置(剛体ローカル座標)
suspensionTravelDir // サスペンション移動方向(単位ベクトル、通常は下方向)
suspensionTravelDist // 最大伸長距離
wheelAttachment // サスペンション座標系でのホイール位置
PxVehicleSuspensionForceParams:
stiffness // バネ定数
damping // 減衰係数
sprungMass // サスペンションで支持される質量「ジャウンス(jounce)」とは、サスペンション最大伸長位置から現在位置までの圧縮距離である。
- ホイールを最大伸長位置に配置
- レイキャスト(またはシリンダスイープ)で地面との交差を検出
- 交差距離からジャウンス値を算出
separation値で接地状態を判定:0: サスペンション範囲内で接地負値: バンプストップ(サスペンション範囲を超えた貫通)正値: 地面から離れている(空中)
力 = -stiffness * jounce - damping * jounceSpeed
伸長速度制限オプション(limitSuspensionExpansionVelocity)を有効にすると、地面検出時の大きなジャウンス変化を制限し、高周波ノイズを低減する。
ジャウンスに応じてキャンバー角・トー角・力適用点オフセットを変化させる。PxVehicleFixedSizeLookupTable<T, 3> による最大3点の区分線形補間テーブルで定義。
PxVehicleSuspensionComplianceParams:
toeAngle // ジャウンス→トー角テーブル
camberAngle // ジャウンス→キャンバー角テーブル
forceAppPoint // ジャウンス→力適用点オフセットテーブルPxVehicleAntiRollForceParams:
wheel0, wheel1 // 接続するホイールペア
stiffness // アンチロール剛性
アンチロール力 = stiffness * (jounce[wheel0] - jounce[wheel1])左右のサスペンション差分に比例したトルクを発生させ、ロール姿勢を安定化する。
ソース: src/tire/VhTireFunctions.cpp, VhTireHelpers.cpp
ヘッダ: include/vehicle2/tire/
タイヤ力の計算は3段階で行われる。
PxVehicleTireDirsUpdate():
- ホイールの回転軸(lat方向)をワールド座標に変換
- サスペンションコンプライアンス(キャンバー・トー)を適用
- 地面法線とタイヤ回転軸の外積から 縦方向(longitudinal)を算出
- 縦方向と地面法線の外積から 横方向(lateral)を算出
PxVehicleTireSlipSpeedsUpdate():
横スリップ角(lateral slip):
lateralSlip = atan(latSpeed / max(|lngSpeed|, minLatSlipDenominator))
縦スリップ(longitudinal slip):
// アクティブ時(スロットルまたはブレーキ入力あり)
longSlip = (wheelRotSpeed * radius - lngSpeed) / max(|lngSpeed|, minActiveLongSlipDenominator)
// パッシブ時(入力なし)
longSlip = (wheelRotSpeed * radius - lngSpeed) / max(|lngSpeed|, minPassiveLongSlipDenominator)
minPassiveLongSlipDenominator(デフォルト4.0)は minActiveLongSlipDenominator(デフォルト0.1)より大きく設定され、パッシブ時にホイール回転速度のゼロ付近での振動を抑制する。
PxVehicleTireForceParams:
latStiffX // 横剛性の荷重感度上限(正規化荷重)
latStiffY // 横剛性最大値(N)
longStiff // 縦剛性(N)
camberStiff // キャンバー剛性(N/rad)
frictionVsSlip // スリップ対摩擦グラフ(3点)
restLoad // 静止時タイヤ荷重
loadFilter // タイヤ荷重フィルタ(2点)摩擦スリップカーブ: frictionVsSlip[3][2] は3点の区分線形グラフ:
[0]: ゼロスリップ時の摩擦(通常〜1.0)[1]: 最大摩擦点(ピークスリップ値とピーク摩擦値)[2]: 高スリップ時の漸近摩擦値
この値は路面の摩擦係数に掛け合わされる。
荷重フィルタ: タイムステップ依存性を低減するため、正規化荷重(load/restLoad)に対してフィルタリングされた荷重を算出する。2点補間テーブル loadFilter[2][2] で定義。
低速域では数値的不安定性が問題になるため、スティッキータイヤレジームが導入されている。
PxVehicleTireAxisStickyParams:
thresholdSpeed // 速度閾値(デフォルト: 0.2 m/s)
thresholdTime // 時間閾値(デフォルト: 1.0 s)
damping // 減速率(1/s)遷移条件: タイヤの速度が thresholdSpeed 以下の状態が thresholdTime 秒間継続すると、スティッキータイヤモードに入る。
動作: スティッキーモードではタイヤ力の代わりに速度拘束(velocity constraint)を適用し、damping パラメータに従って速度をゼロに収束させる。
縦方向と横方向は独立して管理される:
- 縦方向ダンピング: デフォルト 1.0(速い収束)
- 横方向ダンピング: デフォルト 0.1(緩やかな収束)
ソース: src/wheel/VhWheelFunctions.cpp
ヘッダ: include/vehicle2/wheel/
PxVehicleWheelParams:
radius // ホイール半径
halfWidth // ホイール半幅
mass // ホイール質量
moi // 回転慣性モーメント
dampingRate // ダンピング率ホイール状態:
PxVehicleWheelRigidBody1dState:
rotationSpeed // 回転速度(rad/s)
correctedRotationSpeed // ブレンド後回転速度(低速時安定化用)
rotationAngle // 回転角度(レンダリング用)回転角度の更新: PxVehicleWheelRotationAngleUpdate() で rotationAngle += rotationSpeed * dt を積分。低速時(thresholdForwardSpeedForWheelAngleIntegration 以下)はブレーキ・スロットルが未入力の場合、路面速度と回転速度をブレンドして振動を抑制する。
ローカルポーズ計算: PxVehicleComputeWheelLocalPose() でサスペンションジャウンス、コンプライアンス(キャンバー・トー)、ステア角、回転角度を統合してホイールのローカルトランスフォームを算出。
ヘッダ: include/vehicle2/braking/
PxVehicleBrakeCommandResponseParams:
maxResponse // 最大ブレーキトルク
wheelResponseMultipliers // ホイール毎の倍率ブレーキは2系統(通常ブレーキ + ハンドブレーキ)をサポート。各系統で独立した PxVehicleBrakeCommandResponseParams を持つ。
ソース: src/drivetrain/VhDrivetrainFunctions.cpp, VhDrivetrainHelpers.cpp
ヘッダ: include/vehicle2/drivetrain/
最もシンプルな駆動モデル。エンジン・ギアボックス・クラッチなし。
PxVehicleDirectDriveUpdate():
w(t+dt) = [w(t) + (1/MOI) * (τ_brake + τ_drive + τ_tire) * dt]
/ [1 + (dampingRate / MOI) * dt]ブレーキロック判定: ブレーキ中にホイール回転速度の符号が反転する場合、回転速度をゼロに固定(ロック状態)。
完全な駆動系モデル:
エンジン(PxVehicleEngineParams):
torqueCurve // 正規化トルクカーブ(最大8点、x=正規化回転速度、y=正規化トルク)
moi // エンジン慣性モーメント
peakTorque // 最大トルク
idleOmega // アイドル回転速度
maxOmega // 最大回転速度
dampingRateFullThrottle // フルスロットル時ダンピング
dampingRateZeroThrottleClutchEngaged // スロットルゼロ・クラッチ接続時ダンピング
dampingRateZeroThrottleClutchDisengaged // スロットルゼロ・クラッチ切断時ダンピングエンジン出力トルク = throttle * peakTorque * torqueCurve.interpolate(rotationSpeed / maxOmega)
ギアボックス(PxVehicleGearboxParams):
neutralGear // ニュートラルギアのインデックス
ratios[] // ギア比配列(リバースからトップまで)
finalRatio // ファイナルギア比
switchTime // ギアチェンジ所要時間ギアチェンジ中(switchTime経過するまで)はクラッチがゼロ強度になり、駆動力が途切れる。
オートボックス(PxVehicleAutoboxParams):
upRatios[] // シフトアップ回転速度比(正規化エンジン回転速度)
downRatios[] // シフトダウン回転速度比
latency // シフト操作の遅延時間クラッチ(PxVehicleClutchParams):
accuracyMode // eESTIMATE or eBEST_POSSIBLE
estimateIterations // eESTIMATE時の反復回数クラッチトルク = clutchStrength * (1 - clutchPedal) * (engineOmega - wheelOmega * gearRatio)
eBEST_POSSIBLE モードでは LU分解ソルバ(PxVehicleMatrixNNLUSolver)で連立方程式を厳密に解く。eESTIMATE モードではガウス・ザイデル法(PxVehicleMatrixNGaussSeidelSolver)で近似する。
PxVehicleMultiWheelDriveDifferentialParams:
torqueRatios[MAX_WHEELS] // 各ホイールへのトルク配分比
aveWheelSpeedRatios[] // 平均ホイール速度の重み
PxVehicleFourWheelDriveDifferentialParams:
frontWheelIds[2], rearWheelIds[2] // 前後ホイールID
frontBias, rearBias, centerBias // 差動バイアス
frontTarget, rearTarget, centerTarget // 差動ロック目標比
rate // 差動ロック収束速度ホイール制約グループ(PxVehicleWheelConstraintGroupState)は、差動ロック時に複数ホイールの回転速度関係を制約するために使用される。各グループは constraintMultipliers で相対回転速度比を定義する。
ソース: src/rigidBody/VhRigidBodyFunctions.cpp
ヘッダ: include/vehicle2/rigidBody/
PxVehicleRigidBodyState:
pose // 位置・姿勢
linearVelocity // 線速度
angularVelocity // 角速度
previousLinearVelocity // 前フレームの線速度
previousAngularVelocity // 前フレームの角速度
externalForce // 外部力
externalTorque // 外部トルク力の統合処理:
F_total = Σ suspensionForces[i] + Σ tireForces[i] + antiRollTorque + externalForce
τ_total = Σ (r[i] × suspensionForces[i]) + Σ (r[i] × tireForces[i]) + externalTorque
オイラー積分でリジッドボディ状態を更新:
linearVelocity(t+dt) = linearVelocity(t) + (F_total / mass) * dt
angularVelocity(t+dt) = angularVelocity(t) + (I⁻¹ * τ_total) * dt
ソース: src/physxActor/VhPhysXActorFunctions.cpp, VhPhysXActorHelpers.cpp
ヘッダ: include/vehicle2/physxActor/
PxVehiclePhysXActor:
rigidBody // PxRigidBody*(PhysXリジッドボディへのポインタ)
wheelShapes // 各ホイール用PxShape*配列アクター更新モード:
eAPPLY_VELOCITY: 速度を直接設定(即座に反映)eAPPLY_ACCELERATION: 加速度として適用(次回PhysXシーン更新時に反映)
ウェイクカウンタ管理: サスペンション力やタイヤ力が働いている間、PhysXアクターがスリープ状態に入らないよう wakeCounterResetValue を設定する。
ソース: src/physxRoadGeometry/VhPhysXRoadGeometryFunctions.cpp, VhPhysXRoadGeometryHelpers.cpp
ヘッダ: include/vehicle2/physxRoadGeometry/
PhysXシーンに対するレイキャストまたはシリンダスイープで路面を検出する。
PxVehiclePhysXRoadGeometryQueryParams:
roadGeometryQueryType // eSWEEP(シリンダスイープ)or eRAYCAST(レイキャスト)
filterData // クエリフィルタデータ
filterCallback // クエリフィルタコールバックシリンダスイープの方が精度は高いが計算コストも高い。レイキャストは軽量だが、路面の傾斜や曲率が大きい場合に不正確になりうる。
ソース: src/physxConstraints/VhPhysXConstraintFunctions.cpp, VhPhysXConstraintHelpers.cpp
ヘッダ: include/vehicle2/physxConstraints/
スティッキータイヤおよびサスペンション制約をPhysXシーンの制約ソルバに反映する。
PxVehiclePhysXSuspensionLimitConstraintParams:
restitution // 反発係数
directionForSuspensionLimitConstraint // eSUSPENSION or eROAD_GEOMETRY_NORMALソース: src/pvd/VhPvdFunctions.cpp, VhPvdHelpers.cpp, VhPvdWriter.cpp
ヘッダ: include/vehicle2/pvd/
OmniPVD を通じて全パラメータ・状態をリアルタイムで可視化する。
PxVehiclePvdContext:
attributeHandles // PxVehiclePvdAttributeHandles*(属性ハンドル)
writer // OmniPvdWriter*(データ出力ライター)PVDコンポーネントは作成時に属性ハンドルを生成し、毎フレームの update() でデータを書き出す。
ユーザー入力(スロットル、ブレーキ、ステアコマンド)
│
▼
┌─────────────────────────────────┐
│ Command Component │
│ コマンド → ホイール応答値変換 │
│ アッカーマン補正適用 │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ Suspension Component │
│ 路面ジオメトリクエリ(レイキャスト/スイープ)│
│ ジャウンス計算 │
│ サスペンション力計算 │
│ コンプライアンス評価 │
│ アンチロールバー力計算 │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ Tire Component │
│ タイヤ方向計算 │
│ スリップ速度・角度計算 │
│ タイヤ力計算(摩擦モデル) │
│ スティッキータイヤ判定 │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ Wheel Component │
│ 回転速度積分 │
│ 回転角度更新 │
│ ローカルポーズ計算 │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ Drivetrain Component │
│ エンジン状態更新 │
│ ギアボックス・オートボックス │
│ クラッチ連成解法(LU/GS) │
│ 差動・ホイール制約グループ │
│ ホイールトルク計算 │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ Rigid Body Component │
│ 全力・トルクの統合 │
│ オイラー積分(速度・姿勢更新) │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ PhysX Actor Component │
│ PxRigidBody 速度/加速度適用 │
│ ウェイクカウンタ管理 │
│ ホイールシェイプ更新 │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ PhysX Constraint Component │
│ スティッキータイヤ制約反映 │
│ サスペンション制限制約反映 │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ PVD Component(オプション) │
│ パラメータ・状態のリアルタイム │
│ 可視化データ出力 │
└─────────────────────────────────┘
PxVehicleMaths.h に定義された線形代数ソルバ群:
| クラス | アルゴリズム | 用途 |
|---|---|---|
PxVehicleMatrixNNLUSolver |
LU分解(完全ピボット付き) | クラッチモデル(eBEST_POSSIBLE) |
PxVehicleMatrixNGaussSeidelSolver |
ガウス・ザイデル反復法 | クラッチモデル(eESTIMATE) |
PxVehicleMatrix33Solver |
3x3特殊ソルバ | 小規模連立方程式 |
PxVehicleVectorN |
N次元ベクトル(最大サイズ: MAX_WHEELS + 3) | ソルバ入出力 |
PxVehicleMatrixNN |
NxN行列 | ソルバ入出力 |
PxVehicleFixedSizeLookupTable<T, N>: N点以下の区分線形補間テーブル。トルクカーブ、コンプライアンステーブル等で使用。
PxVehicleLimits:
eMAX_NB_WHEELS = 20 // 最大ホイール数
eMAX_NB_AXLES = 20 // 最大アクスル数(= ホイール数)
PxVehicleComponentSequenceLimits:
eMAX_NB_SUBGROUPS = 16 // 最大サブグループ数
eMAX_NB_COMPONENTS = 64 // 最大コンポーネント数source/physxvehicle/src/
├── commands/
│ └── VhCommandHelpers.cpp # コマンド応答値変換ヘルパー
├── drivetrain/
│ ├── VhDrivetrainFunctions.cpp # 駆動系計算(ダイレクト/エンジン駆動)
│ └── VhDrivetrainHelpers.cpp # 駆動系ユーティリティ
├── physxActor/
│ ├── VhPhysXActorFunctions.cpp # PhysXアクター更新処理
│ └── VhPhysXActorHelpers.cpp # PhysXアクターユーティリティ
├── physxConstraints/
│ ├── VhPhysXConstraintFunctions.cpp # PhysX制約処理
│ └── VhPhysXConstraintHelpers.cpp # PhysX制約ユーティリティ
├── physxRoadGeometry/
│ ├── VhPhysXRoadGeometryFunctions.cpp # 路面クエリ処理
│ └── VhPhysXRoadGeometryHelpers.cpp # 路面クエリユーティリティ
├── pvd/
│ ├── VhPvdAttributeHandles.h # PVD属性ハンドル定義
│ ├── VhPvdFunctions.cpp # PVD出力処理
│ ├── VhPvdHelpers.cpp # PVDユーティリティ
│ ├── VhPvdObjectHandles.h # PVDオブジェクトハンドル定義
│ ├── VhPvdWriter.cpp # PVDデータライター実装
│ └── VhPvdWriter.h # PVDデータライターヘッダ
├── rigidBody/
│ └── VhRigidBodyFunctions.cpp # 剛体力学計算
├── steering/
│ └── VhSteeringFunctions.cpp # ステアリング計算
├── suspension/
│ ├── VhSuspensionFunctions.cpp # サスペンション力計算
│ └── VhSuspensionHelpers.cpp # サスペンションユーティリティ
├── tire/
│ ├── VhTireFunctions.cpp # タイヤ力計算
│ └── VhTireHelpers.cpp # タイヤユーティリティ
└── wheel/
└── VhWheelFunctions.cpp # ホイール回転計算
snippets/ に以下の車両関連サンプルが存在する:
| スニペット | 説明 |
|---|---|
snippetvehicledirectdrive |
ダイレクトドライブ車両 |
snippetvehiclefourwheeldrive |
4輪駆動車両 |
snippetvehicletankdrive |
タンク(無限軌道)駆動 |
snippetvehicletruck |
トラック(多軸車両) |
snippetvehiclecustomsuspension |
カスタムサスペンション |
snippetvehiclecustomtire |
カスタムタイヤモデル |
snippetvehiclemultithreading |
マルチスレッド車両シミュレーション |
snippetvehiclecommon |
車両共通ユーティリティ |