[1378] | 1 | #ifndef NX_COLLISION_NXWHEELSHAPEDESC
|
---|
| 2 | #define NX_COLLISION_NXWHEELSHAPEDESC
|
---|
| 3 | /*----------------------------------------------------------------------------*\
|
---|
| 4 | |
|
---|
| 5 | | Public Interface to NovodeX Technology
|
---|
| 6 | |
|
---|
| 7 | | www.novodex.com
|
---|
| 8 | |
|
---|
| 9 | \*----------------------------------------------------------------------------*/
|
---|
| 10 |
|
---|
| 11 |
|
---|
| 12 | #include "NxShapeDesc.h"
|
---|
| 13 | #include "NxSpringDesc.h"
|
---|
| 14 |
|
---|
| 15 |
|
---|
| 16 | /**
|
---|
| 17 | \brief Class used to describe tire properties for a #NxWheelShape
|
---|
| 18 |
|
---|
| 19 | A tire force function takes a measure for tire slip as input, (this is computed differently for lateral and longitudal directions)
|
---|
| 20 | and gives a force (or in our implementation, an impulse) as output.
|
---|
| 21 |
|
---|
| 22 | The curve is approximated by a two piece cubic Hermite spline. The first section goes from (0,0) to (extremumSlip, extremumValue), at which
|
---|
| 23 | point the curve's tangent is zero.
|
---|
| 24 |
|
---|
| 25 | The second section goes from (extremumSlip, extremumValue) to (asymptoteSlip, asymptoteValue), at which point the curve's tangent is again zero.
|
---|
| 26 |
|
---|
| 27 | \image html wheelGraph.png
|
---|
| 28 |
|
---|
| 29 |
|
---|
| 30 | <b>Platform:</b>
|
---|
| 31 | \li PC SW: Yes
|
---|
| 32 | \li PPU : No
|
---|
| 33 | \li PS3 : Yes
|
---|
| 34 | \li XB360: Yes
|
---|
| 35 |
|
---|
| 36 | See #NxWheelShape.
|
---|
| 37 | */
|
---|
| 38 |
|
---|
| 39 | /*
|
---|
| 40 | Force
|
---|
| 41 | ^ extremum
|
---|
| 42 | | _*_
|
---|
| 43 | | ~ \ asymptote
|
---|
| 44 | | / \~__*______________
|
---|
| 45 | | /
|
---|
| 46 | |/
|
---|
| 47 | ---------------------------> Slip
|
---|
| 48 | */
|
---|
| 49 | class NxTireFunctionDesc
|
---|
| 50 | {
|
---|
| 51 | public:
|
---|
| 52 | NxReal extremumSlip, extremumValue; //!< extremal point of curve. Both values must be positive.
|
---|
| 53 | NxReal asymptoteSlip, asymptoteValue; //!< point on curve at which for all x > minumumX, function equals minimumY. Both values must be positive.
|
---|
| 54 | NxReal stiffnessFactor; //!< this is an additional overall positive scaling that gets applied to the tire forces before passing them to the solver. Higher values make for better grip. If you raise the *Values above, you may need to lower this.
|
---|
| 55 | /**
|
---|
| 56 | \brief Scaling factor for tire force.
|
---|
| 57 |
|
---|
| 58 | This is an additional overall positive scaling that gets applied to the tire forces before passing
|
---|
| 59 | them to the solver. Higher values make for better grip. If you raise the *Values above, you may
|
---|
| 60 | need to lower this. A setting of zero will disable all friction in this direction.
|
---|
| 61 |
|
---|
| 62 | <b>Range:</b> (0,inf)<br>
|
---|
| 63 | <b>Default:</b> 1000000.0 (quite stiff by default)
|
---|
| 64 | */
|
---|
| 65 | //NxReal stiffnessFactor;
|
---|
| 66 |
|
---|
| 67 |
|
---|
| 68 | /**
|
---|
| 69 | constructor sets to default.
|
---|
| 70 | */
|
---|
| 71 | NX_INLINE NxTireFunctionDesc();
|
---|
| 72 | /**
|
---|
| 73 | (re)sets the structure to the default.
|
---|
| 74 | */
|
---|
| 75 | NX_INLINE virtual void setToDefault();
|
---|
| 76 | /**
|
---|
| 77 | returns true if the current settings are valid
|
---|
| 78 | */
|
---|
| 79 | NX_INLINE virtual bool isValid() const;
|
---|
| 80 |
|
---|
| 81 | /**
|
---|
| 82 | evaluates the Force(Slip) function
|
---|
| 83 | */
|
---|
| 84 | NX_INLINE NxReal hermiteEval(NxReal t) const;
|
---|
| 85 | };
|
---|
| 86 |
|
---|
| 87 | enum NxWheelShapeFlags
|
---|
| 88 | {
|
---|
| 89 | /**
|
---|
| 90 | \brief Determines whether the suspension axis or the ground contact normal is used for the suspension constraint.
|
---|
| 91 |
|
---|
| 92 | */
|
---|
| 93 | NX_WF_WHEEL_AXIS_CONTACT_NORMAL = 1 << 0,
|
---|
| 94 |
|
---|
| 95 | /**
|
---|
| 96 | \brief If set, the laterial slip velocity is used as the input to the tire function, rather than the slip angle.
|
---|
| 97 |
|
---|
| 98 | */
|
---|
| 99 | NX_WF_INPUT_LAT_SLIPVELOCITY = 1 << 1,
|
---|
| 100 |
|
---|
| 101 | /**
|
---|
| 102 | \brief If set, the longutudal slip velocity is used as the input to the tire function, rather than the slip ratio.
|
---|
| 103 |
|
---|
| 104 | */
|
---|
| 105 | NX_WF_INPUT_LNG_SLIPVELOCITY = 1 << 2,
|
---|
| 106 |
|
---|
| 107 | /**
|
---|
| 108 | \brief If set, does not factor out the suspension travel and wheel radius from the spring force computation. This is the legacy behavior from the raycast capsule approach.
|
---|
| 109 | */
|
---|
| 110 | NX_WF_UNSCALED_SPRING_BEHAVIOR = 1 << 3,
|
---|
| 111 |
|
---|
| 112 | /**
|
---|
| 113 | \brief If set, the axle speed is not computed by the simulation but is rather expected to be provided by the user every simulation step via NxWheelShape::setAxleSpeed().
|
---|
| 114 | */
|
---|
| 115 | NX_WF_AXLE_SPEED_OVERRIDE = 1 << 4,
|
---|
| 116 | };
|
---|
| 117 |
|
---|
| 118 |
|
---|
| 119 | /**
|
---|
| 120 | \brief Descriptor for an #NxWheelShape.
|
---|
| 121 |
|
---|
| 122 | <b>Platform:</b>
|
---|
| 123 | \li PC SW: Yes
|
---|
| 124 | \li PPU : No
|
---|
| 125 | \li PS3 : Yes
|
---|
| 126 | \li XB360: Yes
|
---|
| 127 |
|
---|
| 128 | @see NxWheelShape NxActor.createActor()
|
---|
| 129 | */
|
---|
| 130 | class NxWheelShapeDesc : public NxShapeDesc //TODO: this nor other desc classes can be assigned with = operator, we need to define copy ctors.
|
---|
| 131 | {
|
---|
| 132 | public:
|
---|
| 133 |
|
---|
| 134 | //geometrical constants:
|
---|
| 135 |
|
---|
| 136 | /**
|
---|
| 137 | \brief distance from wheel axle to a point on the contact surface.
|
---|
| 138 |
|
---|
| 139 | @see NxWheelShape.getRadius() NxWheelShape.setRadius()
|
---|
| 140 | */
|
---|
| 141 | NxReal radius;
|
---|
| 142 |
|
---|
| 143 | /**
|
---|
| 144 | \brief maximum extension distance of suspension along shape's -Y axis.
|
---|
| 145 |
|
---|
| 146 | The minimum extension is always 0.
|
---|
| 147 |
|
---|
| 148 | @see NxWheelShape.setSuspensionTravel() NxWheelShape.getSuspensionTravel()
|
---|
| 149 | */
|
---|
| 150 | NxReal suspensionTravel;
|
---|
| 151 |
|
---|
| 152 | //(In the old model the capsule height was the sum of the two members above.)
|
---|
| 153 | //^^^ this may be redundant together with suspension.targetValue, not sure yet.
|
---|
| 154 |
|
---|
| 155 | //simulation constants:
|
---|
| 156 |
|
---|
| 157 | /**
|
---|
| 158 | \brief data intended for car wheel suspension effects.
|
---|
| 159 |
|
---|
| 160 | targetValue must be in [0, 1], which is the rest length of the suspension along the suspensionTravel.
|
---|
| 161 | 0 is the default, which maps to the tip of the ray cast.
|
---|
| 162 |
|
---|
| 163 | @see NxSpringDesc NxWheelShape.setSuspension() NxWheelShape.getSuspension()
|
---|
| 164 | */
|
---|
| 165 | NxSpringDesc suspension;
|
---|
| 166 |
|
---|
| 167 | /**
|
---|
| 168 | \brief cubic hermite spline coefficients describing the longitudal tire force curve.
|
---|
| 169 |
|
---|
| 170 | @see NxWheelShape.getLongitudalTireForceFunction() NxWheelShape.setLongitudalTireForceFunction()
|
---|
| 171 | */
|
---|
| 172 | NxTireFunctionDesc longitudalTireForceFunction;
|
---|
| 173 |
|
---|
| 174 | /**
|
---|
| 175 | \brief cubic hermite spline coefficients describing the lateral tire force curve.
|
---|
| 176 |
|
---|
| 177 | @see NxWheelShape.getLateralTireForceFunction() NxWheelShape.setLateralTireForceFunction()
|
---|
| 178 | */
|
---|
| 179 | NxTireFunctionDesc lateralTireForceFunction;
|
---|
| 180 |
|
---|
| 181 | /**
|
---|
| 182 | \brief inverse mass of the wheel.
|
---|
| 183 |
|
---|
| 184 | Determines the wheel velocity that wheel torques can achieve.
|
---|
| 185 |
|
---|
| 186 | @see NxWheelShape.setInverseWheelMass() NxWheelShape.getInverseWheelMass()
|
---|
| 187 | */
|
---|
| 188 | NxReal inverseWheelMass;
|
---|
| 189 |
|
---|
| 190 | /**
|
---|
| 191 | \brief flags from NxWheelShapeFlags
|
---|
| 192 |
|
---|
| 193 | @see NxWheelShapeFlags NxWheelShape.getWheelFlags() NxWheelShape.setWheelFlags()
|
---|
| 194 | */
|
---|
| 195 | NxU32 wheelFlags;
|
---|
| 196 |
|
---|
| 197 | //dynamic inputs:
|
---|
| 198 |
|
---|
| 199 | /**
|
---|
| 200 | \brief Sum engine torque on the wheel axle.
|
---|
| 201 |
|
---|
| 202 | Positive or negative depending on direction.
|
---|
| 203 |
|
---|
| 204 | @see NxWheelShape.setMotorTorque() NxWheelShape.getMotorTorque() brakeTorque
|
---|
| 205 | */
|
---|
| 206 | NxReal motorTorque;
|
---|
| 207 |
|
---|
| 208 | /**
|
---|
| 209 | \brief The amount of torque applied for braking.
|
---|
| 210 |
|
---|
| 211 | Must be positive. Very large values should lock wheel but should be stable.
|
---|
| 212 |
|
---|
| 213 | @see NxWheelShape.setBrakeTorque() NxWheelShape.getBrakeTorque() motorTorque
|
---|
| 214 | */
|
---|
| 215 | NxReal brakeTorque;
|
---|
| 216 |
|
---|
| 217 | /**
|
---|
| 218 | \brief steering angle, around shape Y axis.
|
---|
| 219 |
|
---|
| 220 | @see NxWheelShape.setSteerAngle() NxWheelShape.getSteerAngle()
|
---|
| 221 | */
|
---|
| 222 | NxReal steerAngle;
|
---|
| 223 |
|
---|
| 224 |
|
---|
| 225 |
|
---|
| 226 |
|
---|
| 227 | /**
|
---|
| 228 | constructor sets to default.
|
---|
| 229 | */
|
---|
| 230 | NX_INLINE NxWheelShapeDesc();
|
---|
| 231 | /**
|
---|
| 232 | \brief (re)sets the structure to the default.
|
---|
| 233 |
|
---|
| 234 | \param[in] fromCtor Avoid redundant work if called from constructor.
|
---|
| 235 | */
|
---|
| 236 | NX_INLINE virtual void setToDefault(bool fromCtor = false);
|
---|
| 237 | /**
|
---|
| 238 | \brief returns true if the current settings are valid
|
---|
| 239 | */
|
---|
| 240 | NX_INLINE virtual bool isValid() const;
|
---|
| 241 | };
|
---|
| 242 |
|
---|
| 243 |
|
---|
| 244 | NX_INLINE NxTireFunctionDesc::NxTireFunctionDesc()
|
---|
| 245 | {
|
---|
| 246 | setToDefault();
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 | NX_INLINE void NxTireFunctionDesc::setToDefault()
|
---|
| 250 | {
|
---|
| 251 | extremumSlip = 1.0f;
|
---|
| 252 | extremumValue = 0.02f;
|
---|
| 253 | asymptoteSlip = 2.0f;
|
---|
| 254 | asymptoteValue = 0.01f;
|
---|
| 255 | stiffnessFactor = 1000000.0f; //quite stiff by default.
|
---|
| 256 | }
|
---|
| 257 |
|
---|
| 258 | NX_INLINE bool NxTireFunctionDesc::isValid() const
|
---|
| 259 | {
|
---|
| 260 | if(!(0.0f < extremumSlip)) return false;
|
---|
| 261 | if(!(extremumSlip < asymptoteSlip)) return false;
|
---|
| 262 | if(!(0.0f < extremumValue)) return false;
|
---|
| 263 | if(!(0.0f < asymptoteValue)) return false;
|
---|
| 264 | if(!(0.0f <= stiffnessFactor)) return false;
|
---|
| 265 |
|
---|
| 266 | return true;
|
---|
| 267 | }
|
---|
| 268 |
|
---|
| 269 | NX_INLINE NxReal NxTireFunctionDesc::hermiteEval(NxReal t) const
|
---|
| 270 | {
|
---|
| 271 | NxReal sign;
|
---|
| 272 | if (t < 0.0f)
|
---|
| 273 | {
|
---|
| 274 | t = -t; //function is mirrored around origin.
|
---|
| 275 | sign = -1.0f;
|
---|
| 276 | }
|
---|
| 277 | else
|
---|
| 278 | sign = 1.0f;
|
---|
| 279 |
|
---|
| 280 | //NxReal c2 = A3-A2; //not needed.
|
---|
| 281 |
|
---|
| 282 |
|
---|
| 283 |
|
---|
| 284 | if (t < extremumSlip) //first curve
|
---|
| 285 | {
|
---|
| 286 | //0 at start, with tangent = line to first control point.
|
---|
| 287 | //(x,y) at end, with tangent = 0;
|
---|
| 288 | sign *= extremumValue;
|
---|
| 289 | t /= extremumSlip;
|
---|
| 290 | NxReal A2 = t * t;
|
---|
| 291 | NxReal A3 = A2 * t;
|
---|
| 292 | NxReal c3 = -2*A3+3*A2;
|
---|
| 293 | NxReal c1 = A3-2*A2+t;
|
---|
| 294 | return (c1 + c3) * sign; //c1 has coeff = tangent == maximum, c3 has coeff maximum.
|
---|
| 295 | }
|
---|
| 296 | if (t > asymptoteSlip) //beyond minimum
|
---|
| 297 | {
|
---|
| 298 | return asymptoteValue * sign;
|
---|
| 299 | }
|
---|
| 300 | else //second curve
|
---|
| 301 | {
|
---|
| 302 | //between two points (extremumSlip,Y), minimum(X,Y), both with tangent 0.
|
---|
| 303 |
|
---|
| 304 | //remap t so that maximimX --> 0, asymptoteSlip --> 1
|
---|
| 305 |
|
---|
| 306 | t /= (asymptoteSlip - extremumSlip);
|
---|
| 307 | t -= extremumSlip;
|
---|
| 308 |
|
---|
| 309 | NxReal A2 = t * t;
|
---|
| 310 | NxReal A3 = A2 * t;
|
---|
| 311 | NxReal c3 = -2*A3+3*A2;
|
---|
| 312 | NxReal c0 = 2*A3-3*A2+1;
|
---|
| 313 | return (c0 * extremumValue + c3 * asymptoteValue) * sign;
|
---|
| 314 | }
|
---|
| 315 | }
|
---|
| 316 |
|
---|
| 317 |
|
---|
| 318 | NX_INLINE NxWheelShapeDesc::NxWheelShapeDesc() : NxShapeDesc(NX_SHAPE_WHEEL) //constructor sets to default
|
---|
| 319 | {
|
---|
| 320 | setToDefault(true);
|
---|
| 321 | }
|
---|
| 322 |
|
---|
| 323 | NX_INLINE void NxWheelShapeDesc::setToDefault(bool fromCtor)
|
---|
| 324 | {
|
---|
| 325 | NxShapeDesc::setToDefault();
|
---|
| 326 |
|
---|
| 327 | radius = 1.0f;
|
---|
| 328 | suspensionTravel = 1.0f;
|
---|
| 329 | //simulation constants:
|
---|
| 330 | inverseWheelMass = 1.0f;
|
---|
| 331 | wheelFlags = 0;
|
---|
| 332 | //dynamic inputs:
|
---|
| 333 | motorTorque = 0.0f;
|
---|
| 334 | brakeTorque = 0.0f;
|
---|
| 335 | steerAngle = 0.0f;
|
---|
| 336 |
|
---|
| 337 | if (!fromCtor)
|
---|
| 338 | {
|
---|
| 339 | suspension.setToDefault();
|
---|
| 340 | longitudalTireForceFunction.setToDefault();
|
---|
| 341 | lateralTireForceFunction.setToDefault();
|
---|
| 342 | }
|
---|
| 343 | }
|
---|
| 344 |
|
---|
| 345 | NX_INLINE bool NxWheelShapeDesc::isValid() const
|
---|
| 346 | {
|
---|
| 347 | if(!NxMath::isFinite(radius)) return false;
|
---|
| 348 | if(radius<=0.0f) return false;
|
---|
| 349 | if(!NxMath::isFinite(suspensionTravel)) return false;
|
---|
| 350 | if(suspensionTravel<0.0f) return false;
|
---|
| 351 | if(!NxMath::isFinite(inverseWheelMass)) return false;
|
---|
| 352 | if(inverseWheelMass<=0.0f) return false;
|
---|
| 353 | if(!NxMath::isFinite(motorTorque)) return false;
|
---|
| 354 | if(!NxMath::isFinite(brakeTorque)) return false;
|
---|
| 355 | if(brakeTorque<0.0f) return false;
|
---|
| 356 | if(!NxMath::isFinite(steerAngle)) return false;
|
---|
| 357 |
|
---|
| 358 | if (!suspension.isValid()) return false;
|
---|
| 359 | if ((suspension.targetValue < 0.0f) || (suspension.targetValue > 1.0f)) return false;
|
---|
| 360 | if (!longitudalTireForceFunction.isValid()) return false;
|
---|
| 361 | if (!lateralTireForceFunction.isValid()) return false;
|
---|
| 362 |
|
---|
| 363 |
|
---|
| 364 | return NxShapeDesc::isValid();
|
---|
| 365 | }
|
---|
| 366 | #endif
|
---|
| 367 |
|
---|
| 368 |
|
---|
| 369 | #if 0
|
---|
| 370 | #endif
|
---|
| 371 |
|
---|
| 372 |
|
---|
| 373 | //AGCOPYRIGHTBEGIN
|
---|
| 374 | ///////////////////////////////////////////////////////////////////////////
|
---|
| 375 | // Copyright © 2005 AGEIA Technologies.
|
---|
| 376 | // All rights reserved. www.ageia.com
|
---|
| 377 | ///////////////////////////////////////////////////////////////////////////
|
---|
| 378 | //AGCOPYRIGHTEND
|
---|
| 379 |
|
---|