1 | /* |
2 | * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. |
3 | * |
4 | * NVIDIA CORPORATION and its licensors retain all intellectual property |
5 | * and proprietary rights in and to this software, related documentation |
6 | * and any modifications thereto. Any use, reproduction, disclosure or |
7 | * distribution of this software and related documentation without an express |
8 | * license agreement from NVIDIA CORPORATION is strictly prohibited. |
9 | */ |
10 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
11 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
12 | |
13 | #ifndef PX_VEHICLE_CORE_COMPONENTS_H |
14 | #define PX_VEHICLE_CORE_COMPONENTS_H |
15 | /** \addtogroup vehicle |
16 | @{ |
17 | */ |
18 | |
19 | #include "foundation/PxMemory.h" |
20 | #include "foundation/PxVec3.h" |
21 | #include "common/PxCoreUtilityTypes.h" |
22 | #include "PxVehicleSDK.h" |
23 | #include "common/PxTypeInfo.h" |
24 | #include "foundation/PxIO.h" |
25 | |
26 | #ifndef PX_DOXYGEN |
27 | namespace physx |
28 | { |
29 | #endif |
30 | |
31 | class PxVehicleChassisData |
32 | { |
33 | public: |
34 | |
35 | friend class PxVehicleDriveSimData4W; |
36 | |
37 | PxVehicleChassisData() |
38 | : mMOI(PxVec3(0,0,0)), |
39 | mMass(1500), |
40 | mCMOffset(PxVec3(0,0,0)) |
41 | { |
42 | } |
43 | |
44 | /** |
45 | \brief Moment of inertia of vehicle rigid body actor. |
46 | |
47 | \note Specified in kilograms metres-squared (kg m^2). |
48 | */ |
49 | PxVec3 mMOI; |
50 | |
51 | /** |
52 | \brief Mass of vehicle rigid body actor. |
53 | |
54 | \note Specified in kilograms (kg). |
55 | */ |
56 | PxReal mMass; |
57 | |
58 | /** |
59 | \brief Center of mass offset of vehicle rigid body actor. |
60 | |
61 | \note Specified in metres (m). |
62 | */ |
63 | PxVec3 mCMOffset; |
64 | |
65 | private: |
66 | |
67 | PxReal pad; |
68 | |
69 | bool isValid() const; |
70 | }; |
71 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleChassisData)& 0x0f)); |
72 | |
73 | class PxVehicleEngineData |
74 | { |
75 | public: |
76 | |
77 | friend class PxVehicleDriveSimData; |
78 | |
79 | enum |
80 | { |
81 | eMAX_NB_ENGINE_TORQUE_CURVE_ENTRIES = 8 |
82 | }; |
83 | |
84 | PxVehicleEngineData() |
85 | : mMOI(1.0f), |
86 | mPeakTorque(500.0f), |
87 | mMaxOmega(600.0f), |
88 | mDampingRateFullThrottle(0.15f), |
89 | mDampingRateZeroThrottleClutchEngaged(2.0f), |
90 | mDampingRateZeroThrottleClutchDisengaged(0.35f) |
91 | { |
92 | mTorqueCurve.addPair(0.0f, 0.8f); |
93 | mTorqueCurve.addPair(0.33f, 1.0f); |
94 | mTorqueCurve.addPair(1.0f, 0.8f); |
95 | |
96 | mRecipMOI=1.0f/mMOI; |
97 | mRecipMaxOmega=1.0f/mMaxOmega; |
98 | } |
99 | |
100 | /** |
101 | \brief Graph of normalized torque (torque/mPeakTorque) against normalized engine speed ( engineRotationSpeed / mMaxOmega ). |
102 | |
103 | \note The normalized engine speed is the x-axis of the graph, while the normalized torque is the y-axis of the graph. |
104 | */ |
105 | PxFixedSizeLookupTable<eMAX_NB_ENGINE_TORQUE_CURVE_ENTRIES> mTorqueCurve; |
106 | |
107 | /** |
108 | \brief Moment of inertia of the engine around the axis of rotation. |
109 | |
110 | \note Specified in kilograms metres-squared (kg m^2) |
111 | */ |
112 | PxReal mMOI; |
113 | |
114 | /** |
115 | \brief Maximum torque available to apply to the engine when the accelerator pedal is at maximum. |
116 | |
117 | \note The torque available is the value of the accelerator pedal (in range [0, 1]) multiplied by the normalized torque as computed from mTorqueCurve multiplied by mPeakTorque. |
118 | |
119 | \note Specified in kilograms metres-squared per second-squared (kg m^2 s^-2). |
120 | |
121 | <b>Range:</b> [0, PX_MAX_F32)<br> |
122 | */ |
123 | PxReal mPeakTorque; |
124 | |
125 | /** |
126 | \brief Maximum rotation speed of the engine. |
127 | |
128 | \note Specified in radians per second (s^-1). |
129 | |
130 | <b>Range:</b> [0, PX_MAX_F32)<br> |
131 | */ |
132 | PxReal mMaxOmega; |
133 | |
134 | /** |
135 | \brief Damping rate of engine when full throttle is applied. |
136 | |
137 | \note If the clutch is engaged (any gear except neutral) then the damping rate applied at run-time is an interpolation |
138 | between mDampingRateZeroThrottleClutchEngaged and mDampingRateFullThrottle: |
139 | mDampingRateZeroThrottleClutchEngaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchEngaged)*acceleratorPedal; |
140 | |
141 | \note If the clutch is disengaged (in neutral gear) the damping rate applied at run-time is an interpolation |
142 | between mDampingRateZeroThrottleClutchDisengaged and mDampingRateFullThrottle: |
143 | mDampingRateZeroThrottleClutchDisengaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchDisengaged)*acceleratorPedal; |
144 | |
145 | \note Specified in kilograms metres-squared per second (kg m^2 s^-1). |
146 | |
147 | <b>Range:</b> [0, PX_MAX_F32)<br> |
148 | */ |
149 | PxReal mDampingRateFullThrottle; |
150 | |
151 | |
152 | /** |
153 | \brief Damping rate of engine when full throttle is applied. |
154 | |
155 | \note If the clutch is engaged (any gear except neutral) then the damping rate applied at run-time is an interpolation |
156 | between mDampingRateZeroThrottleClutchEngaged and mDampingRateFullThrottle: |
157 | mDampingRateZeroThrottleClutchEngaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchEngaged)*acceleratorPedal; |
158 | |
159 | \note If the clutch is disengaged (in neutral gear) the damping rate applied at run-time is an interpolation |
160 | between mDampingRateZeroThrottleClutchDisengaged and mDampingRateFullThrottle: |
161 | mDampingRateZeroThrottleClutchDisengaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchDisengaged)*acceleratorPedal; |
162 | |
163 | \note Specified in kilograms metres-squared per second (kg m^2 s^-1). |
164 | |
165 | <b>Range:</b> [0, PX_MAX_F32)<br> |
166 | */ |
167 | PxReal mDampingRateZeroThrottleClutchEngaged; |
168 | |
169 | /** |
170 | \brief Damping rate of engine when full throttle is applied. |
171 | |
172 | \note If the clutch is engaged (any gear except neutral) then the damping rate applied at run-time is an interpolation |
173 | between mDampingRateZeroThrottleClutchEngaged and mDampingRateFullThrottle: |
174 | mDampingRateZeroThrottleClutchEngaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchEngaged)*acceleratorPedal; |
175 | |
176 | \note If the clutch is disengaged (in neutral gear) the damping rate applied at run-time is an interpolation |
177 | between mDampingRateZeroThrottleClutchDisengaged and mDampingRateFullThrottle: |
178 | mDampingRateZeroThrottleClutchDisengaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchDisengaged)*acceleratorPedal; |
179 | |
180 | \note Specified in kilograms metres-squared per second (kg m^2 s^-1). |
181 | |
182 | <b>Range:</b> [0, PX_MAX_F32)<br> |
183 | */ |
184 | PxReal mDampingRateZeroThrottleClutchDisengaged; |
185 | |
186 | /** |
187 | \brief Return value of mRecipMOI(=1.0f/mMOI) that is automatically set by PxVehicleDriveSimData::setEngineData |
188 | */ |
189 | PX_FORCE_INLINE PxReal getRecipMOI() const {return mRecipMOI;} |
190 | |
191 | /** |
192 | \brief Return value of mRecipMaxOmega( = 1.0f / mMaxOmega ) that is automatically set by PxVehicleDriveSimData::setEngineData |
193 | */ |
194 | PX_FORCE_INLINE PxReal getRecipMaxOmega() const {return mRecipMaxOmega;} |
195 | |
196 | private: |
197 | |
198 | /** |
199 | \brief Reciprocal of the engine moment of inertia. |
200 | |
201 | \note Not necessary to set this value because it is set by PxVehicleDriveSimData::setEngineData |
202 | |
203 | <b>Range:</b> [0, PX_MAX_F32)<br> |
204 | */ |
205 | PxReal mRecipMOI; |
206 | |
207 | /** |
208 | \brief Reciprocal of the maximum rotation speed of the engine. |
209 | |
210 | \note Not necessary to set this value because it is set by PxVehicleDriveSimData::setEngineData |
211 | |
212 | <b>Range:</b> [0, PX_MAX_F32)<br> |
213 | */ |
214 | PxReal mRecipMaxOmega; |
215 | |
216 | bool isValid() const; |
217 | |
218 | |
219 | //serialization |
220 | public: |
221 | PxVehicleEngineData(const PxEMPTY&) : mTorqueCurve(PxEmpty) {} |
222 | //~serialization |
223 | }; |
224 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleEngineData)& 0x0f)); |
225 | |
226 | class PxVehicleGearsData |
227 | { |
228 | public: |
229 | |
230 | friend class PxVehicleDriveSimData; |
231 | |
232 | enum Enum |
233 | { |
234 | eREVERSE=0, |
235 | eNEUTRAL, |
236 | eFIRST, |
237 | eSECOND, |
238 | eTHIRD, |
239 | eFOURTH, |
240 | eFIFTH, |
241 | eSIXTH, |
242 | eSEVENTH, |
243 | eEIGHTH, |
244 | eNINTH, |
245 | eTENTH, |
246 | eELEVENTH, |
247 | eTWELFTH, |
248 | eTHIRTEENTH, |
249 | eFOURTEENTH, |
250 | eFIFTEENTH, |
251 | eSIXTEENTH, |
252 | eSEVENTEENTH, |
253 | eEIGHTEENTH, |
254 | eNINETEENTH, |
255 | eTWENTIETH, |
256 | eTWENTYFIRST, |
257 | eTWENTYSECOND, |
258 | eTWENTYTHIRD, |
259 | eTWENTYFOURTH, |
260 | eTWENTYFIFTH, |
261 | eTWENTYSIXTH, |
262 | eTWENTYSEVENTH, |
263 | eTWENTYEIGHTH, |
264 | eTWENTYNINTH, |
265 | eTHIRTIETH, |
266 | eGEARSRATIO_COUNT |
267 | }; |
268 | |
269 | PxVehicleGearsData() |
270 | : mFinalRatio(4.0f), |
271 | mNbRatios(7), |
272 | mSwitchTime(0.5f) |
273 | { |
274 | mRatios[PxVehicleGearsData::eREVERSE]=-4.0f; |
275 | mRatios[PxVehicleGearsData::eNEUTRAL]=0.0f; |
276 | mRatios[PxVehicleGearsData::eFIRST]=4.0f; |
277 | mRatios[PxVehicleGearsData::eSECOND]=2.0f; |
278 | mRatios[PxVehicleGearsData::eTHIRD]=1.5f; |
279 | mRatios[PxVehicleGearsData::eFOURTH]=1.1f; |
280 | mRatios[PxVehicleGearsData::eFIFTH]=1.0f; |
281 | |
282 | for(PxU32 i = PxVehicleGearsData::eSIXTH; i < PxVehicleGearsData::eGEARSRATIO_COUNT; ++i) |
283 | mRatios[i]=0.f; |
284 | } |
285 | |
286 | /** |
287 | \brief Gear ratios |
288 | |
289 | <b>Range:</b> [0, PX_MAX_F32)<br> |
290 | */ |
291 | PxReal mRatios[PxVehicleGearsData::eGEARSRATIO_COUNT]; |
292 | |
293 | /** |
294 | \brief Gear ratio applied is mRatios[currentGear]*finalRatio |
295 | |
296 | <b>Range:</b> [0, PX_MAX_F32)<br> |
297 | */ |
298 | PxReal mFinalRatio; |
299 | |
300 | /** |
301 | \brief Number of gears (including reverse and neutral). |
302 | |
303 | <b>Range:</b> (0, MAX_NB_GEAR_RATIOS)<br> |
304 | */ |
305 | PxU32 mNbRatios; |
306 | |
307 | /** |
308 | \brief Time it takes to switch gear. |
309 | |
310 | \note Specified in seconds (s). |
311 | |
312 | <b>Range:</b> [0, MAX_NB_GEAR_RATIOS)<br> |
313 | */ |
314 | PxReal mSwitchTime; |
315 | |
316 | private: |
317 | |
318 | PxReal mPad; |
319 | |
320 | bool isValid() const; |
321 | |
322 | //serialization |
323 | public: |
324 | PxVehicleGearsData(const PxEMPTY&) {} |
325 | PxReal getGearRatio(PxVehicleGearsData::Enum a) const {return mRatios[a];} |
326 | void setGearRatio(PxVehicleGearsData::Enum a, PxReal ratio) { mRatios[a] = ratio;} |
327 | //~serialization |
328 | }; |
329 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleGearsData)& 0x0f)); |
330 | |
331 | class PxVehicleAutoBoxData |
332 | { |
333 | public: |
334 | |
335 | friend class PxVehicleDriveSimData; |
336 | |
337 | PxVehicleAutoBoxData() |
338 | { |
339 | for(PxU32 i=0;i<PxVehicleGearsData::eGEARSRATIO_COUNT;i++) |
340 | { |
341 | mUpRatios[i]=0.65f; |
342 | mDownRatios[i]=0.50f; |
343 | } |
344 | //Not sure how important this is but we want to kick out of neutral very quickly. |
345 | mUpRatios[PxVehicleGearsData::eNEUTRAL]=0.15f; |
346 | //Set the latency time in an unused element of one of the arrays. |
347 | mDownRatios[PxVehicleGearsData::eREVERSE]=2.0f; |
348 | } |
349 | |
350 | /** |
351 | \brief Value of ( engineRotationSpeed / PxVehicleEngineData::mMaxOmega ) that is high enough to increment gear. |
352 | |
353 | \note When ( engineRotationSpeed / PxVehicleEngineData::mMaxOmega ) > mUpRatios[currentGear] the autobox will begin |
354 | a transition to currentGear+1 unless currentGear is the highest possible gear or neutral or reverse. |
355 | |
356 | <b>Range:</b> [0, 1]<br> |
357 | */ |
358 | PxReal mUpRatios[PxVehicleGearsData::eGEARSRATIO_COUNT]; |
359 | |
360 | /** |
361 | \brief Value of engineRevs/maxEngineRevs that is low enough to decrement gear. |
362 | |
363 | \note When ( engineRotationSpeed / PxVehicleEngineData::mMaxOmega ) < mDownRatios[currentGear] the autobox will begin |
364 | a transition to currentGear-1 unless currentGear is first gear or neutral or reverse. |
365 | |
366 | <b>Range:</b> [0, 1]<br> |
367 | */ |
368 | PxReal mDownRatios[PxVehicleGearsData::eGEARSRATIO_COUNT]; |
369 | |
370 | /** |
371 | \brief Set the latency time of the autobox. |
372 | |
373 | \note Latency time is the minimum time that must pass between each gear change that is initiated by the autobox. |
374 | The auto-box will only attempt to initiate another gear change up or down if the simulation time that has passed since the most recent |
375 | automated gear change is greater than the specified latency. |
376 | |
377 | \note Specified in seconds (s). |
378 | |
379 | @see getLatency |
380 | */ |
381 | void setLatency(const PxReal latency) |
382 | { |
383 | mDownRatios[PxVehicleGearsData::eREVERSE]=latency; |
384 | } |
385 | |
386 | /** |
387 | \brief Get the latency time of the autobox. |
388 | |
389 | \note Specified in seconds (s). |
390 | |
391 | @see setLatency |
392 | */ |
393 | PxReal getLatency() const |
394 | { |
395 | return mDownRatios[PxVehicleGearsData::eREVERSE]; |
396 | } |
397 | |
398 | private: |
399 | bool isValid() const; |
400 | |
401 | //serialization |
402 | public: |
403 | PxVehicleAutoBoxData(const PxEMPTY&) {} |
404 | |
405 | PxReal getUpRatios(PxVehicleGearsData::Enum a) const {return mUpRatios[a];} |
406 | void setUpRatios(PxVehicleGearsData::Enum a, PxReal ratio) { mUpRatios[a] = ratio;} |
407 | |
408 | PxReal getDownRatios(PxVehicleGearsData::Enum a) const {return mDownRatios[a];} |
409 | void setDownRatios(PxVehicleGearsData::Enum a, PxReal ratio) { mDownRatios[a] = ratio;} |
410 | //~serialization |
411 | }; |
412 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleAutoBoxData)& 0x0f)); |
413 | |
414 | class PxVehicleDifferential4WData |
415 | { |
416 | public: |
417 | |
418 | friend class PxVehicleDriveSimData4W; |
419 | |
420 | enum Enum |
421 | { |
422 | eDIFF_TYPE_LS_4WD, //limited slip differential for car with 4 driven wheels |
423 | eDIFF_TYPE_LS_FRONTWD, //limited slip differential for car with front-wheel drive |
424 | eDIFF_TYPE_LS_REARWD, //limited slip differential for car with rear-wheel drive |
425 | eDIFF_TYPE_OPEN_4WD, //open differential for car with 4 driven wheels |
426 | eDIFF_TYPE_OPEN_FRONTWD, //open differential for car with front-wheel drive |
427 | eDIFF_TYPE_OPEN_REARWD, //open differential for car with rear-wheel drive |
428 | eMAX_NB_DIFF_TYPES |
429 | }; |
430 | |
431 | PxVehicleDifferential4WData() |
432 | : mFrontRearSplit(0.45f), |
433 | mFrontLeftRightSplit(0.5f), |
434 | mRearLeftRightSplit(0.5f), |
435 | mCentreBias(1.3f), |
436 | mFrontBias(1.3f), |
437 | mRearBias(1.3f), |
438 | mType(PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD) |
439 | { |
440 | } |
441 | |
442 | /** |
443 | \brief Ratio of torque split between front and rear (>0.5 means more to front, <0.5 means more to rear). |
444 | |
445 | \note Only applied to DIFF_TYPE_LS_4WD and eDIFF_TYPE_OPEN_4WD |
446 | |
447 | <b>Range:</b> [0, 1]<br> |
448 | */ |
449 | PxReal mFrontRearSplit; |
450 | |
451 | /** |
452 | \brief Ratio of torque split between front-left and front-right (>0.5 means more to front-left, <0.5 means more to front-right). |
453 | |
454 | \note Only applied to DIFF_TYPE_LS_4WD and eDIFF_TYPE_OPEN_4WD and eDIFF_TYPE_LS_FRONTWD |
455 | |
456 | <b>Range:</b> [0, 1]<br> |
457 | */ |
458 | PxReal mFrontLeftRightSplit; |
459 | |
460 | /** |
461 | \brief Ratio of torque split between rear-left and rear-right (>0.5 means more to rear-left, <0.5 means more to rear-right). |
462 | |
463 | \note Only applied to DIFF_TYPE_LS_4WD and eDIFF_TYPE_OPEN_4WD and eDIFF_TYPE_LS_REARWD |
464 | |
465 | <b>Range:</b> [0, 1]<br> |
466 | */ |
467 | PxReal mRearLeftRightSplit; |
468 | |
469 | /** |
470 | \brief Maximum allowed ratio of average front wheel rotation speed and rear wheel rotation speeds |
471 | The differential will divert more torque to the slower wheels when the bias is exceeded. |
472 | |
473 | \note Only applied to DIFF_TYPE_LS_4WD |
474 | |
475 | <b>Range:</b> [1, PX_MAX_F32)<br> |
476 | */ |
477 | PxReal mCentreBias; |
478 | |
479 | /** |
480 | \brief Maximum allowed ratio of front-left and front-right wheel rotation speeds. |
481 | The differential will divert more torque to the slower wheel when the bias is exceeded. |
482 | |
483 | \note Only applied to DIFF_TYPE_LS_4WD and DIFF_TYPE_LS_FRONTWD |
484 | |
485 | <b>Range:</b> [1, PX_MAX_F32)<br> |
486 | */ |
487 | PxReal mFrontBias; |
488 | |
489 | /** |
490 | \brief Maximum allowed ratio of rear-left and rear-right wheel rotation speeds. |
491 | The differential will divert more torque to the slower wheel when the bias is exceeded. |
492 | |
493 | \note Only applied to DIFF_TYPE_LS_4WD and DIFF_TYPE_LS_REARWD |
494 | |
495 | <b>Range:</b> [1, PX_MAX_F32)<br> |
496 | */ |
497 | PxReal mRearBias; |
498 | |
499 | /** |
500 | \brief Type of differential. |
501 | |
502 | <b>Range:</b> [DIFF_TYPE_LS_4WD, DIFF_TYPE_OPEN_FRONTWD]<br> |
503 | */ |
504 | PxVehicleDifferential4WData::Enum mType; |
505 | |
506 | private: |
507 | |
508 | PxReal mPad[1]; |
509 | |
510 | bool isValid() const; |
511 | |
512 | //serialization |
513 | public: |
514 | PxVehicleDifferential4WData(const PxEMPTY&) {} |
515 | //~serialization |
516 | }; |
517 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDifferential4WData)& 0x0f)); |
518 | |
519 | class PxVehicleDifferentialNWData |
520 | { |
521 | public: |
522 | |
523 | friend class PxVehicleDriveSimDataNW; |
524 | friend class PxVehicleUpdate; |
525 | |
526 | PxVehicleDifferentialNWData() |
527 | { |
528 | PxMemSet(mBitmapBuffer, 0, sizeof(PxU32) * (((PX_MAX_NB_WHEELS + 31) & ~31) >> 5)); |
529 | mNbDrivenWheels=0; |
530 | mInvNbDrivenWheels=0.0f; |
531 | } |
532 | |
533 | /** |
534 | \brief Set a specific wheel to be driven or non-driven by the differential. |
535 | |
536 | \note The available drive torque will be split equally between all driven wheels. |
537 | Zero torque will be applied to non-driven wheels. |
538 | The default state of each wheel is to be uncoupled to the differential. |
539 | */ |
540 | void setDrivenWheel(const PxU32 wheelId, const bool drivenState); |
541 | |
542 | /** |
543 | \brief Test if a specific wheel has been configured as a driven or non-driven wheel. |
544 | */ |
545 | bool getIsDrivenWheel(const PxU32 wheelId) const; |
546 | |
547 | private: |
548 | |
549 | PxU32 mBitmapBuffer[((PX_MAX_NB_WHEELS + 31) & ~31) >> 5]; |
550 | PxU32 mNbDrivenWheels; |
551 | PxReal mInvNbDrivenWheels; |
552 | PxU32 mPad; |
553 | |
554 | bool isValid() const; |
555 | |
556 | //serialization |
557 | public: |
558 | PxVehicleDifferentialNWData(const PxEMPTY&) {} |
559 | PxU32 getDrivenWheelStatus() const; |
560 | void setDrivenWheelStatus(PxU32 status); |
561 | //~serialization |
562 | }; |
563 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDifferentialNWData)& 0x0f)); |
564 | |
565 | |
566 | class PxVehicleAckermannGeometryData |
567 | { |
568 | public: |
569 | |
570 | friend class PxVehicleDriveSimData4W; |
571 | |
572 | PxVehicleAckermannGeometryData() |
573 | : mAccuracy(1.0f), |
574 | mFrontWidth(0.0f), //Must be filled out |
575 | mRearWidth(0.0f), //Must be filled out |
576 | mAxleSeparation(0.0f) //Must be filled out |
577 | { |
578 | } |
579 | |
580 | /** |
581 | \brief Accuracy of Ackermann steer calculation. |
582 | |
583 | \note Accuracy with value 0.0 results in no Ackermann steer-correction, while |
584 | accuracy with value 1.0 results in perfect Ackermann steer-correction. |
585 | |
586 | \note Perfect Ackermann steer correction modifies the steer angles applied to the front-left and |
587 | front-right wheels so that the perpendiculars to the wheels' longitudinal directions cross the |
588 | extended vector of the rear axle at the same point. It is also applied to any steer angle applied |
589 | to the the rear wheels but instead using the extended vector of the front axle. |
590 | |
591 | \note In general, more steer correction produces better cornering behavior. |
592 | |
593 | <b>Range:</b> [0, 1]<br> |
594 | */ |
595 | PxReal mAccuracy; |
596 | |
597 | /** |
598 | \brief Distance between center-point of the two front wheels. |
599 | |
600 | \note Specified in metres (m). |
601 | |
602 | <b>Range:</b> [0, PX_MAX_F32)<br> |
603 | */ |
604 | PxReal mFrontWidth; |
605 | |
606 | /** |
607 | \brief Distance between center-point of the two rear wheels. |
608 | |
609 | \note Specified in metres (m). |
610 | |
611 | <b>Range:</b> [0, PX_MAX_F32)<br> |
612 | */ |
613 | PxReal mRearWidth; |
614 | |
615 | /** |
616 | \brief Distance between center of front axle and center of rear axle. |
617 | |
618 | \note Specified in metres (m). |
619 | |
620 | <b>Range:</b> [0, PX_MAX_F32)<br> |
621 | */ |
622 | PxReal mAxleSeparation; |
623 | |
624 | private: |
625 | |
626 | bool isValid() const; |
627 | |
628 | //serialization |
629 | public: |
630 | PxVehicleAckermannGeometryData(const PxEMPTY&) {} |
631 | //~serialization |
632 | }; |
633 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleAckermannGeometryData)& 0x0f)); |
634 | |
635 | /** |
636 | \brief Choose between a potentially more expensive but more accurate solution to the clutch model or a potentially cheaper but less accurate solution. |
637 | @see PxVehicleClutchData |
638 | */ |
639 | struct PxVehicleClutchAccuracyMode |
640 | { |
641 | enum Enum |
642 | { |
643 | eESTIMATE = 0, |
644 | eBEST_POSSIBLE |
645 | }; |
646 | }; |
647 | |
648 | class PxVehicleClutchData |
649 | { |
650 | public: |
651 | |
652 | friend class PxVehicleDriveSimData; |
653 | |
654 | PxVehicleClutchData() |
655 | : mStrength(10.0f), |
656 | mAccuracyMode(PxVehicleClutchAccuracyMode::eBEST_POSSIBLE), |
657 | mEstimateIterations(5) |
658 | { |
659 | } |
660 | |
661 | /** |
662 | \brief Strength of clutch. |
663 | |
664 | \note The clutch is the mechanism that couples the engine to the wheels. |
665 | A stronger clutch more strongly couples the engine to the wheels, while a |
666 | clutch of strength zero completely decouples the engine from the wheels. |
667 | Stronger clutches more quickly bring the wheels and engine into equilibrium, while weaker |
668 | clutches take longer, resulting in periods of clutch slip and delays in power transmission |
669 | from the engine to the wheels. |
670 | The torque generated by the clutch is proportional to the clutch strength and |
671 | the velocity difference between the engine's rotational speed and the rotational speed of the |
672 | driven wheels after accounting for the gear ratio. |
673 | The torque at the clutch is applied negatively to the engine and positively to the driven wheels. |
674 | |
675 | \note Specified in kilograms metres-squared per second (kg m^2 s^-1) |
676 | |
677 | <b>Range:</b> (0,MAX_NB_GEAR_RATIOS)<br> |
678 | */ |
679 | PxReal mStrength; |
680 | |
681 | /** |
682 | \brief The engine and wheel rotation speeds that are coupled through the clutch can be updated by choosing |
683 | one of two modes: eESTIMATE and eBEST_POSSIBLE. |
684 | |
685 | \note If eESTIMATE is chosen the vehicle sdk will update the wheel and engine rotation speeds |
686 | with estimated values to the implemented clutch model. |
687 | |
688 | \note If eBEST_POSSIBLE is chosen the vehicle sdk will compute the best possible |
689 | solution (within floating point tolerance) to the implemented clutch model. |
690 | This is the recommended mode. |
691 | |
692 | \note The clutch model remains the same if either eESTIMATE or eBEST_POSSIBLE is chosen but the accuracy and |
693 | computational cost of the solution to the model can be tuned as required. |
694 | */ |
695 | PxVehicleClutchAccuracyMode::Enum mAccuracyMode; |
696 | |
697 | /** |
698 | \brief Tune the mathematical accuracy and computational cost of the computed estimate to the wheel and |
699 | engine rotation speeds if eESTIMATE is chosen. |
700 | |
701 | \note As mEstimateIterations increases the computational cost of the clutch also increases and the solution |
702 | approaches the solution that would be computed if eBEST_POSSIBLE was chosen instead. |
703 | |
704 | \note This has no effect if eBEST_POSSIBLE is chosen as the accuracy mode. |
705 | |
706 | \note A value of zero is not allowed if eESTIMATE is chosen as the accuracy mode. |
707 | */ |
708 | PxU32 mEstimateIterations; |
709 | |
710 | private: |
711 | |
712 | PxU8 mPad[4]; |
713 | |
714 | bool isValid() const; |
715 | |
716 | //serialization |
717 | public: |
718 | PxVehicleClutchData(const PxEMPTY&) {} |
719 | //~serialization |
720 | }; |
721 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleClutchData)& 0x0f)); |
722 | |
723 | |
724 | /** |
725 | \brief Tire load variation can be strongly dependent on the time-step so it is a good idea to filter it |
726 | to give less jerky handling behavior. |
727 | |
728 | \note The x-axis of the graph is normalized tire load, while the y-axis is the filtered normalized tire load. |
729 | |
730 | \note The normalized load is the force acting downwards on the tire divided by the force experienced by the tire when the car is at rest on the ground. |
731 | |
732 | \note The rest load is approximately the product of the value of gravitational acceleration and PxVehicleSuspensionData::mSprungMass. |
733 | |
734 | \note The minimum possible normalized load is zero. |
735 | |
736 | \note There are two points on the graph: (mMinNormalisedLoad, mMinNormalisedFilteredLoad) and (mMaxNormalisedLoad, mMaxFilteredNormalisedLoad). |
737 | |
738 | \note Normalized loads less than mMinNormalisedLoad have filtered normalized load = mMinNormalisedFilteredLoad. |
739 | |
740 | \note Normalized loads greater than mMaxNormalisedLoad have filtered normalized load = mMaxFilteredNormalisedLoad. |
741 | |
742 | \note Normalized loads in-between are linearly interpolated between mMinNormalisedFilteredLoad and mMaxFilteredNormalisedLoad. |
743 | |
744 | \note The tire load applied as input to the tire force computation is the filtered normalized load multiplied by the rest load. |
745 | */ |
746 | class PxVehicleTireLoadFilterData |
747 | { |
748 | public: |
749 | |
750 | friend class PxVehicleWheelsSimData; |
751 | |
752 | PxVehicleTireLoadFilterData() |
753 | : mMinNormalisedLoad(0), |
754 | mMinFilteredNormalisedLoad(0.2308f), |
755 | mMaxNormalisedLoad(3.0f), |
756 | mMaxFilteredNormalisedLoad(3.0f) |
757 | { |
758 | mDenominator=1.0f/(mMaxNormalisedLoad - mMinNormalisedLoad); |
759 | } |
760 | |
761 | /** |
762 | \brief Graph point (mMinNormalisedLoad,mMinFilteredNormalisedLoad) |
763 | */ |
764 | PxReal mMinNormalisedLoad; |
765 | |
766 | /** |
767 | \brief Graph point (mMinNormalisedLoad,mMinFilteredNormalisedLoad) |
768 | */ |
769 | PxReal mMinFilteredNormalisedLoad; |
770 | |
771 | /** |
772 | \brief Graph point (mMaxNormalisedLoad,mMaxFilteredNormalisedLoad) |
773 | */ |
774 | PxReal mMaxNormalisedLoad; |
775 | |
776 | /** |
777 | \brief Graph point (mMaxNormalisedLoad,mMaxFilteredNormalisedLoad) |
778 | */ |
779 | PxReal mMaxFilteredNormalisedLoad; |
780 | |
781 | PX_FORCE_INLINE PxReal getDenominator() const {return mDenominator;} |
782 | |
783 | private: |
784 | |
785 | /** |
786 | \brief Not necessary to set this value. |
787 | */ |
788 | //1.0f/(mMaxNormalisedLoad-mMinNormalisedLoad) for quick calculations |
789 | PxReal mDenominator; |
790 | |
791 | PxU32 mPad[3]; |
792 | |
793 | bool isValid() const; |
794 | |
795 | //serialization |
796 | public: |
797 | PxVehicleTireLoadFilterData(const PxEMPTY&) {} |
798 | //~serialization |
799 | }; |
800 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleTireLoadFilterData)& 0x0f)); |
801 | |
802 | class PxVehicleWheelData |
803 | { |
804 | public: |
805 | |
806 | friend class PxVehicleWheels4SimData; |
807 | |
808 | PxVehicleWheelData() |
809 | : mRadius(0.0f), //Must be filled out |
810 | mWidth(0.0f), |
811 | mMass(20.0f), |
812 | mMOI(0.0f), //Must be filled out |
813 | mDampingRate(0.25f), |
814 | mMaxBrakeTorque(1500.0f), |
815 | mMaxHandBrakeTorque(0.0f), |
816 | mMaxSteer(0.0f), |
817 | mToeAngle(0.0f), |
818 | mRecipRadius(0.0f), //Must be filled out |
819 | mRecipMOI(0.0f) //Must be filled out |
820 | { |
821 | } |
822 | |
823 | /** |
824 | \brief Radius of unit that includes metal wheel plus rubber tire. |
825 | |
826 | \note Specified in metres (m). |
827 | |
828 | <b>Range:</b> [0, PX_MAX_F32)<br> |
829 | */ |
830 | PxReal mRadius; |
831 | |
832 | /** |
833 | \brief Maximum width of unit that includes wheel plus tire. |
834 | |
835 | \note Specified in metres (m). |
836 | |
837 | <b>Range:</b> [0, PX_MAX_F32)<br> |
838 | */ |
839 | PxReal mWidth; |
840 | |
841 | /** |
842 | \brief Mass of unit that includes wheel plus tire. |
843 | |
844 | \note Specified in kilograms (kg). |
845 | |
846 | <b>Range:</b> [0, PX_MAX_F32)<br> |
847 | */ |
848 | PxReal mMass; |
849 | |
850 | /** |
851 | \brief Moment of inertia of unit that includes wheel plus tire about the rolling axis. |
852 | |
853 | \note Specified in kilograms metres-squared (kg m^2). |
854 | |
855 | <b>Range:</b> [0, PX_MAX_F32)<br> |
856 | */ |
857 | PxReal mMOI; |
858 | |
859 | /** |
860 | \brief Damping rate applied to wheel. |
861 | |
862 | \note Specified in kilograms metres-squared per second (kg m^2 s^-1). |
863 | |
864 | <b>Range:</b> [0, PX_MAX_F32)<br> |
865 | */ |
866 | PxReal mDampingRate; |
867 | |
868 | /** |
869 | \brief Max brake torque that can be applied to wheel. |
870 | |
871 | \note Specified in kilograms metres-squared per second-squared (kg m^2 s^-2) |
872 | |
873 | <b>Range:</b> [0, PX_MAX_F32)<br> |
874 | */ |
875 | PxReal mMaxBrakeTorque; |
876 | |
877 | /** |
878 | \brief Max handbrake torque that can be applied to wheel. |
879 | |
880 | \note Specified in kilograms metres-squared per second-squared (kg m^2 s^-2) |
881 | |
882 | <b>Range:</b> [0, PX_MAX_F32)<br> |
883 | */ |
884 | PxReal mMaxHandBrakeTorque; |
885 | |
886 | /** |
887 | \brief Max steer angle that can be achieved by the wheel. |
888 | |
889 | \note Specified in radians. |
890 | |
891 | <b>Range:</b> [0, PX_MAX_F32)<br> |
892 | */ |
893 | PxReal mMaxSteer; |
894 | |
895 | /** |
896 | \brief Wheel toe angle. This value is ignored by PxVehicleDriveTank and PxVehicleNoDrive. |
897 | |
898 | \note Specified in radians. |
899 | |
900 | <b>Range:</b> [0, Pi/2]<br> |
901 | */ |
902 | PxReal mToeAngle;//in radians |
903 | |
904 | /** |
905 | \brief Return value equal to 1.0f/mRadius |
906 | |
907 | @see PxVehicleWheelsSimData::setWheelData |
908 | */ |
909 | PX_FORCE_INLINE PxReal getRecipRadius() const {return mRecipRadius;} |
910 | |
911 | /** |
912 | \brief Return value equal to 1.0f/mRecipMOI |
913 | |
914 | @see PxVehicleWheelsSimData::setWheelData |
915 | */ |
916 | PX_FORCE_INLINE PxReal getRecipMOI() const {return mRecipMOI;} |
917 | |
918 | private: |
919 | |
920 | /** |
921 | \brief Reciprocal of radius of unit that includes metal wheel plus rubber tire. |
922 | |
923 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setWheelData |
924 | |
925 | <b>Range:</b> [0, PX_MAX_F32)<br> |
926 | */ |
927 | PxReal mRecipRadius; |
928 | |
929 | /** |
930 | \brief Reciprocal of moment of inertia of unit that includes wheel plus tire about single allowed axis of rotation. |
931 | |
932 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setWheelData |
933 | |
934 | <b>Range:</b> [0, PX_MAX_F32)<br> |
935 | */ |
936 | PxReal mRecipMOI; |
937 | |
938 | PxReal mPad[1]; |
939 | |
940 | bool isValid() const; |
941 | }; |
942 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleWheelData)& 0x0f)); |
943 | |
944 | class PxVehicleSuspensionData |
945 | { |
946 | public: |
947 | |
948 | friend class PxVehicleWheels4SimData; |
949 | |
950 | PxVehicleSuspensionData() |
951 | : mSpringStrength(0.0f), |
952 | mSpringDamperRate(0.0f), |
953 | mMaxCompression(0.3f), |
954 | mMaxDroop(0.1f), |
955 | mSprungMass(0.0f), |
956 | mCamberAtRest(0.0f), |
957 | mCamberAtMaxCompression(0.0f), |
958 | mCamberAtMaxDroop(0.0f), |
959 | mRecipMaxCompression(1.0f), |
960 | mRecipMaxDroop(1.0f) |
961 | { |
962 | } |
963 | |
964 | /** |
965 | \brief Spring strength of suspension unit. |
966 | |
967 | \note Specified in kilograms per second-squared (kg s^-2). |
968 | |
969 | <b>Range:</b> [0, PX_MAX_F32)<br> |
970 | */ |
971 | PxReal mSpringStrength; |
972 | |
973 | /** |
974 | \brief Spring damper rate of suspension unit. |
975 | |
976 | \note Specified in kilograms per second (kg s^-1). |
977 | |
978 | <b>Range:</b> [0, PX_MAX_F32)<br> |
979 | */ |
980 | PxReal mSpringDamperRate; |
981 | |
982 | /** |
983 | \brief Maximum compression allowed by suspension spring. |
984 | |
985 | \note Specified in metres (m). |
986 | |
987 | <b>Range:</b> [0, PX_MAX_F32)<br> |
988 | */ |
989 | PxReal mMaxCompression; |
990 | |
991 | /** |
992 | \brief Maximum elongation allowed by suspension spring. |
993 | |
994 | \note Specified in metres (m). |
995 | |
996 | <b>Range:</b> [0, PX_MAX_F32)<br> |
997 | */ |
998 | PxReal mMaxDroop; |
999 | |
1000 | /** |
1001 | \brief Mass of vehicle that is supported by suspension spring. |
1002 | |
1003 | \note Specified in kilograms (kg). |
1004 | |
1005 | \note Each suspension is guaranteed to generate an upwards force of |gravity|*mSprungMass along the suspension direction when the wheel is perfectly |
1006 | at rest and sitting at the rest pose defined by the wheel centre offset. |
1007 | |
1008 | \note The sum of the sprung masses of all suspensions of a vehicle should match the mass of the PxRigidDynamic associated with the vehicle. |
1009 | When this condition is satisfied for a vehicle on a horizontal plane the wheels of the vehicle are guaranteed to sit at the rest pose |
1010 | defined by the wheel centre offset. The mass matching condition is not enforced. |
1011 | |
1012 | \note As the wheel compresses or elongates along the suspension direction the force generated by the spring is |
1013 | F = |gravity|*mSprungMass + deltaX*mSpringStrength + deltaXDot*mSpringDamperRate |
1014 | where deltaX is the deviation from the defined rest pose and deltaXDot is the velocity of the sprung mass along the suspension direction. |
1015 | In practice, deltaXDot is computed by comparing the current and previous deviation from the rest pose and dividing the difference |
1016 | by the simulation timestep. |
1017 | |
1018 | \note If a single suspension spring is hanging in the air and generates zero force the remaining springs of the vehicle will necessarily |
1019 | sit in a compressed configuration. In summary, the sum of the remaining suspension forces cannot balance the downwards gravitational force |
1020 | acting on the vehicle without extra force arising from the deltaX*mSpringStrength force term. |
1021 | |
1022 | \note Theoretically, a suspension spring should generate zero force at maximum elongation and increase linearly as the suspension approaches the rest pose. |
1023 | PxVehicleSuspensionData will only enforce this physical law if the spring is configured so that |gravity|*mSprungMass == mMaxDroop*mSpringStrength. |
1024 | To help decouple vehicle handling from visual wheel positioning this condition is not enforced. |
1025 | In practice, the value of |gravity|*mSprungMass + deltaX*mSpringStrength is clamped at zero to ensure it never falls negative. |
1026 | |
1027 | @see PxVehicleComputeSprungMasses, PxVehicleWheelsSimData::setWheelCentreOffset, PxVehicleSuspensionData::mSpringStrength, PxVehicleSuspensionData::mSpringDamperRate, PxVehicleSuspensionData::mMaxDroop |
1028 | |
1029 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1030 | */ |
1031 | PxReal mSprungMass; |
1032 | |
1033 | /** |
1034 | \brief Camber angle (in radians) of wheel when the suspension is at its rest position. |
1035 | |
1036 | \note Specified in radians. |
1037 | |
1038 | <b>Range:</b> [-pi/2, pi/2]<br> |
1039 | |
1040 | */ |
1041 | PxReal mCamberAtRest; |
1042 | |
1043 | /** |
1044 | \brief Camber angle (in radians) of wheel when the suspension is at maximum compression. |
1045 | |
1046 | \note For compressed suspensions the camber angle is a linear interpolation of |
1047 | mCamberAngleAtRest and mCamberAtMaxCompression |
1048 | |
1049 | \note Specified in radians. |
1050 | |
1051 | <b>Range:</b> [-pi/2, pi/2]<br> |
1052 | */ |
1053 | PxReal mCamberAtMaxCompression; |
1054 | |
1055 | /** |
1056 | \brief Camber angle (in radians) of wheel when the suspension is at maximum droop. |
1057 | |
1058 | \note For extended suspensions the camber angle is linearly interpolation of |
1059 | mCamberAngleAtRest and mCamberAtMaxDroop |
1060 | |
1061 | \note Specified in radians. |
1062 | |
1063 | <b>Range:</b> [-pi/2, pi/2]<br> |
1064 | */ |
1065 | PxReal mCamberAtMaxDroop; |
1066 | |
1067 | /** |
1068 | \brief Reciprocal of maximum compression. |
1069 | |
1070 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setSuspensionData |
1071 | |
1072 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1073 | */ |
1074 | PX_FORCE_INLINE PxReal getRecipMaxCompression() const {return mRecipMaxCompression;} |
1075 | |
1076 | /** |
1077 | \brief Reciprocal of maximum droop. |
1078 | |
1079 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setSuspensionData |
1080 | |
1081 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1082 | */ |
1083 | PX_FORCE_INLINE PxReal getRecipMaxDroop() const {return mRecipMaxDroop;} |
1084 | |
1085 | /** |
1086 | \brief Set a new sprung mass for the suspension and modify the spring strength so that the natural frequency |
1087 | of the spring is preserved. |
1088 | \param[in] newSprungMass is the new mass that the suspension spring will support. |
1089 | */ |
1090 | void setMassAndPreserveNaturalFrequency(const PxReal newSprungMass) |
1091 | { |
1092 | const PxF32 oldStrength = mSpringStrength; |
1093 | const PxF32 oldSprungMass = mSprungMass; |
1094 | const PxF32 newStrength = oldStrength * (newSprungMass / oldSprungMass); |
1095 | mSpringStrength = newStrength; |
1096 | mSprungMass = newSprungMass; |
1097 | } |
1098 | |
1099 | private: |
1100 | |
1101 | /** |
1102 | \brief Cached value of 1.0f/mMaxCompression |
1103 | |
1104 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setSuspensionData |
1105 | */ |
1106 | PxReal mRecipMaxCompression; |
1107 | |
1108 | /** |
1109 | \brief Cached value of 1.0f/mMaxDroop |
1110 | |
1111 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setSuspensionData |
1112 | */ |
1113 | PxReal mRecipMaxDroop; |
1114 | |
1115 | //padding |
1116 | PxReal mPad[2]; |
1117 | |
1118 | bool isValid() const; |
1119 | }; |
1120 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleSuspensionData)& 0x0f)); |
1121 | |
1122 | class PxVehicleTireData |
1123 | { |
1124 | public: |
1125 | friend class PxVehicleWheels4SimData; |
1126 | |
1127 | PxVehicleTireData() |
1128 | : mLatStiffX(2.0f), |
1129 | mLatStiffY(0.3125f*(180.0f / PxPi)), |
1130 | mLongitudinalStiffnessPerUnitGravity(1000.0f), |
1131 | mCamberStiffnessPerUnitGravity(0.1f*(180.0f / PxPi)), |
1132 | mType(0) |
1133 | { |
1134 | mFrictionVsSlipGraph[0][0]=0.0f; |
1135 | mFrictionVsSlipGraph[0][1]=1.0f; |
1136 | mFrictionVsSlipGraph[1][0]=0.1f; |
1137 | mFrictionVsSlipGraph[1][1]=1.0f; |
1138 | mFrictionVsSlipGraph[2][0]=1.0f; |
1139 | mFrictionVsSlipGraph[2][1]=1.0f; |
1140 | |
1141 | mRecipLongitudinalStiffnessPerUnitGravity=1.0f/mLongitudinalStiffnessPerUnitGravity; |
1142 | |
1143 | mFrictionVsSlipGraphRecipx1Minusx0=1.0f/(mFrictionVsSlipGraph[1][0]-mFrictionVsSlipGraph[0][0]); |
1144 | mFrictionVsSlipGraphRecipx2Minusx1=1.0f/(mFrictionVsSlipGraph[2][0]-mFrictionVsSlipGraph[1][0]); |
1145 | } |
1146 | |
1147 | /** |
1148 | \brief Tire lateral stiffness is a graph of tire load that has linear behavior near zero load and |
1149 | flattens at large loads. mLatStiffX describes the minimum normalized load (load/restLoad) that gives a |
1150 | flat lateral stiffness response to load. |
1151 | |
1152 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1153 | */ |
1154 | PxReal mLatStiffX; |
1155 | |
1156 | /** |
1157 | \brief Tire lateral stiffness is a graph of tire load that has linear behavior near zero load and |
1158 | flattens at large loads. mLatStiffY describes the maximum possible value of lateralStiffness/restLoad that occurs |
1159 | when (load/restLoad)>= mLatStiffX. |
1160 | |
1161 | \note If load/restLoad is greater than mLatStiffX then the lateral stiffness is mLatStiffY*restLoad. |
1162 | |
1163 | \note If load/restLoad is less than mLatStiffX then the lateral stiffness is mLastStiffY*(load/mLatStiffX) |
1164 | |
1165 | \note Lateral force can be approximated as lateralStiffness * lateralSlip. |
1166 | |
1167 | \note Specified in per radian. |
1168 | |
1169 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1170 | */ |
1171 | PxReal mLatStiffY; |
1172 | |
1173 | /** |
1174 | \brief Tire Longitudinal stiffness per unit gravitational acceleration. |
1175 | |
1176 | \note Longitudinal stiffness of the tire is calculated as gravitationalAcceleration*mLongitudinalStiffnessPerUnitGravity. |
1177 | |
1178 | \note Longitudinal force can be approximated as gravitationalAcceleration*mLongitudinalStiffnessPerUnitGravity*longitudinalSlip. |
1179 | |
1180 | \note Specified in kilograms per radian. |
1181 | |
1182 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1183 | */ |
1184 | PxReal mLongitudinalStiffnessPerUnitGravity; |
1185 | |
1186 | /** |
1187 | \brief tire Tire camber stiffness per unity gravitational acceleration. |
1188 | |
1189 | \note Camber stiffness of the tire is calculated as gravitationalAcceleration*mCamberStiffnessPerUnitGravity |
1190 | |
1191 | \note Camber force can be approximated as gravitationalAcceleration*mCamberStiffnessPerUnitGravity*camberAngle. |
1192 | |
1193 | \note Specified in kilograms per radian. |
1194 | |
1195 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1196 | */ |
1197 | PxReal mCamberStiffnessPerUnitGravity; |
1198 | |
1199 | /** |
1200 | \brief Graph of friction vs longitudinal slip with 3 points. |
1201 | |
1202 | \note mFrictionVsSlipGraph[0][0] is always zero. |
1203 | |
1204 | \note mFrictionVsSlipGraph[0][1] is the friction available at zero longitudinal slip. |
1205 | |
1206 | \note mFrictionVsSlipGraph[1][0] is the value of longitudinal slip with maximum friction. |
1207 | |
1208 | \note mFrictionVsSlipGraph[1][1] is the maximum friction. |
1209 | |
1210 | \note mFrictionVsSlipGraph[2][0] is the end point of the graph. |
1211 | |
1212 | \note mFrictionVsSlipGraph[2][1] is the value of friction for slips greater than mFrictionVsSlipGraph[2][0]. |
1213 | |
1214 | \note The friction value computed from the friction vs longitudinal slip graph is used to scale the friction |
1215 | value for the combination of material and tire type (PxVehicleDrivableSurfaceToTireFrictionPairs). |
1216 | |
1217 | \note mFrictionVsSlipGraph[2][0] > mFrictionVsSlipGraph[1][0] > mFrictionVsSlipGraph[0][0] |
1218 | |
1219 | \note mFrictionVsSlipGraph[1][1] is typically greater than mFrictionVsSlipGraph[0][1] |
1220 | |
1221 | \note mFrictionVsSlipGraph[2][1] is typically smaller than mFrictionVsSlipGraph[1][1] |
1222 | |
1223 | \note longitudinal slips > mFrictionVsSlipGraph[2][0] use friction multiplier mFrictionVsSlipGraph[2][1] |
1224 | |
1225 | \note The final friction value used by the tire model is the value returned by PxVehicleDrivableSurfaceToTireFrictionPairs |
1226 | multiplied by the value computed from mFrictionVsSlipGraph. |
1227 | |
1228 | @see PxVehicleDrivableSurfaceToTireFrictionPairs, PxVehicleComputeTireForce |
1229 | |
1230 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1231 | */ |
1232 | PxReal mFrictionVsSlipGraph[3][2]; |
1233 | |
1234 | /** |
1235 | \brief Tire type denoting slicks, wets, snow, winter, summer, all-terrain, mud etc. |
1236 | |
1237 | @see PxVehicleDrivableSurfaceToTireFrictionPairs |
1238 | |
1239 | <b>Range:</b> [0, PX_MAX_F32)<br> |
1240 | */ |
1241 | PxU32 mType; |
1242 | |
1243 | /** |
1244 | \brief Return Cached value of 1.0/mLongitudinalStiffnessPerUnitGravity |
1245 | |
1246 | @see PxVehicleWheelsSimData::setTireData |
1247 | */ |
1248 | PX_FORCE_INLINE PxReal getRecipLongitudinalStiffnessPerUnitGravity() const {return mRecipLongitudinalStiffnessPerUnitGravity;} |
1249 | |
1250 | /** |
1251 | \brief Return Cached value of 1.0f/(mFrictionVsSlipGraph[1][0]-mFrictionVsSlipGraph[0][0]) |
1252 | |
1253 | @see PxVehicleWheelsSimData::setTireData |
1254 | */ |
1255 | PX_FORCE_INLINE PxReal getFrictionVsSlipGraphRecipx1Minusx0() const {return mFrictionVsSlipGraphRecipx1Minusx0;} |
1256 | |
1257 | /** |
1258 | \brief Return Cached value of 1.0f/(mFrictionVsSlipGraph[2][0]-mFrictionVsSlipGraph[1][0]) |
1259 | |
1260 | @see PxVehicleWheelsSimData::setTireData |
1261 | */ |
1262 | PX_FORCE_INLINE PxReal getFrictionVsSlipGraphRecipx2Minusx1() const {return mFrictionVsSlipGraphRecipx2Minusx1;} |
1263 | |
1264 | private: |
1265 | |
1266 | /** |
1267 | \brief Cached value of 1.0/mLongitudinalStiffnessPerUnitGravity. |
1268 | |
1269 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setTireData |
1270 | |
1271 | @see PxVehicleWheelsSimData::setTireData |
1272 | */ |
1273 | PxReal mRecipLongitudinalStiffnessPerUnitGravity; |
1274 | |
1275 | /** |
1276 | \brief Cached value of 1.0f/(mFrictionVsSlipGraph[1][0]-mFrictionVsSlipGraph[0][0]) |
1277 | |
1278 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setTireData |
1279 | |
1280 | @see PxVehicleWheelsSimData::setTireData |
1281 | */ |
1282 | PxReal mFrictionVsSlipGraphRecipx1Minusx0; |
1283 | |
1284 | /** |
1285 | \brief Cached value of 1.0f/(mFrictionVsSlipGraph[2][0]-mFrictionVsSlipGraph[1][0]) |
1286 | |
1287 | \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setTireData |
1288 | |
1289 | @see PxVehicleWheelsSimData::setTireData |
1290 | */ |
1291 | PxReal mFrictionVsSlipGraphRecipx2Minusx1; |
1292 | |
1293 | PxReal mPad[2]; |
1294 | |
1295 | bool isValid() const; |
1296 | }; |
1297 | PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleTireData)& 0x0f)); |
1298 | #ifndef PX_DOXYGEN |
1299 | } // namespace physx |
1300 | #endif |
1301 | |
1302 | /** @} */ |
1303 | #endif //PX_VEHICLE_CORE_COMPONENTS_H |
1304 | |