private void UpdateWheelInfo(WheelInfo info) { info.LeftTyreTemp.ActualQuantity = Temperature.FromCelsius(_tyreTemp - 5); info.CenterTyreTemp.ActualQuantity = Temperature.FromCelsius(_tyreTemp); info.RightTyreTemp.ActualQuantity = Temperature.FromCelsius(_tyreTemp + 5); info.TyreCoreTemperature.ActualQuantity = Temperature.FromCelsius(_tyreTemp); info.TyreType = "Slick"; info.BrakeTemperature.ActualQuantity = Temperature.FromCelsius(_brakeTemp); info.TyrePressure.ActualQuantity = Pressure.FromKiloPascals(200); }
public void UpdateSuspension(float step) { float chassisMass = 1.0f / chassisBody.InvMass; for (int w_it = 0; w_it < NumWheels; w_it++) { WheelInfo wheel_info = wheelInfo[w_it]; if (wheel_info.RaycastInfo.IsInContact) { float force; // Spring { float susp_length = wheel_info.SuspensionRestLength; float current_length = wheel_info.RaycastInfo.SuspensionLength; float length_diff = (susp_length - current_length); force = wheel_info.SuspensionStiffness * length_diff * wheel_info.ClippedInvContactDotSuspension; } // Damper { float projected_rel_vel = wheel_info.SuspensionRelativeVelocity; { float susp_damping; if (projected_rel_vel < 0.0f) { susp_damping = wheel_info.WheelsDampingCompression; } else { susp_damping = wheel_info.WheelsDampingRelaxation; } force -= susp_damping * projected_rel_vel; } } // RESULT wheel_info.WheelsSuspensionForce = force * chassisMass; if (wheel_info.WheelsSuspensionForce < 0) { wheel_info.WheelsSuspensionForce = 0; } } else { wheel_info.WheelsSuspensionForce = 0; } } }
void ResetSuspension() { for (int i = 0; i < NumWheels; i++) { WheelInfo wheel = GetWheelInfo(i); wheel.RaycastInfo.SuspensionLength = wheel.SuspensionRestLength; wheel.SuspensionRelativeVelocity = 0; wheel.RaycastInfo.ContactNormalWS = -wheel.RaycastInfo.WheelDirectionWS; //wheel.ContactFriction = 0; wheel.ClippedInvContactDotSuspension = 1; } }
private void FixedUpdate() { if (carWheels == null) { return; } /*On every physics update, update all the wheels*/ for (int i = 0; i < carWheels.Length; i++) { WheelInfo currentWheel = carWheels[i]; float currentSpeed = carRB.velocity.magnitude; //If wheels have motor or steering apply forces if (currentWheel.motor) { //Only accelerate if we are under the max speed if (currentSpeed < maxSpeed) { currentWheel.collider.motorTorque = accelerateInput * motorPower; } else { currentWheel.collider.motorTorque = 0f; } } if (currentWheel.steer) { currentWheel.collider.steerAngle = steerInput * maxSteerAngle; } //Apply rotation to the wheels and update the wheels mesh renderer const float secondsInMin = 60f; const float degreesInCircle = 360f; currentWheel.rotation = currentWheel.collider.rpm / secondsInMin * degreesInCircle * currentSpeed; if (currentWheel.meshRenderer != null) { currentWheel.meshRenderer.transform.localRotation = Quaternion.Euler(0f, currentWheel.collider.steerAngle, currentWheel.rotation); } } //Apply force to rigidbody const float forceModifier = -0.1f; Transform carTransform = transform; carRB.AddForceAtPosition(carTransform.up * (carRB.velocity.magnitude * forceModifier * wheelGrip), carTransform.position + (carTransform.rotation * carCenterOfMass)); }
private void CalculateLapsUntilHeavyWear(WheelInfo wheelInfo, SimulatorDataSet simulatorDataSet) { TimeSpan?playersPace = _paceProvider.PlayersPace; if (_wearPerMinute == 0 || !playersPace.HasValue || playersPace.Value == TimeSpan.Zero) { LapsUntilHeavyWear = 0; return; } double wearLeft = (wheelInfo.TyreWear.HeavyWearLimit - wheelInfo.TyreWear.ActualWear); double minutesLeft = wearLeft / _wearPerMinute; LapsUntilHeavyWear = (int)Math.Floor(minutesLeft / playersPace.Value.TotalMinutes); }
private Velocity ComputeSuspensionVelocity(WheelInfo wheel, Distance lastSuspTravel, Velocity lastSuspensionVelocity, double sessionTimeSeconds) { double interval = sessionTimeSeconds - _lastSessionTimeSeconds; if (interval <= 0) { wheel.SuspensionVelocity = lastSuspensionVelocity; return(lastSuspensionVelocity); } Distance distanceTraveled = wheel.SuspensionTravel - lastSuspTravel; Velocity suspensionVelocity = Velocity.FromMs(distanceTraveled.InMeters / interval); wheel.SuspensionVelocity = suspensionVelocity; return(suspensionVelocity); }
private void UpdateBrakeControl(SimulatorDataSet data) { if (data.PlayerInfo == null) { return; } WheelInfo wheel = GetWheelByPosition(data); if (wheel == null) { return; } lblBreakTemp.Text = wheel.BrakeTemperature.GetValueInUnits(TemperatureDisplayUnit).ToString("0"); lblBreakTemp.PixelOn = ComputeColor(wheel.BrakeTemperature.InCelsius, wheel.OptimalBrakeTemperature.InCelsius, wheel.OptimalBrakeWindow); }
void UpdateWheelTransformsWS(WheelInfo wheel, bool interpolatedTransform) { wheel.RaycastInfo.IsInContact = false; Matrix chassisTrans = ChassisWorldTransform; if (interpolatedTransform && RigidBody.MotionState != null) { chassisTrans = RigidBody.MotionState.WorldTransform; } wheel.RaycastInfo.HardPointWS = Vector3.TransformCoordinate(wheel.ChassisConnectionPointCS, chassisTrans); Matrix chassisTransBasis = chassisTrans.Basis; wheel.RaycastInfo.WheelDirectionWS = Vector3.TransformCoordinate(wheel.WheelDirectionCS, chassisTransBasis); wheel.RaycastInfo.WheelAxleWS = Vector3.TransformCoordinate(wheel.WheelAxleCS, chassisTransBasis); }
private void CalculateWearAtRaceEnd(WheelInfo wheelInfo, SimulatorDataSet simulatorDataSet) { if (simulatorDataSet.SessionInfo.SessionType != SessionType.Race || _wearPerMinute == 0) { WearAtRaceEnd = 0; return; } TimeSpan timeRemaining = _sessionRemainingCalculator.GetTimeRemaining(simulatorDataSet); if (timeRemaining == TimeSpan.Zero) { WearAtRaceEnd = 0; return; } WearAtRaceEnd = Math.Max(0, 100 - 100 * (wheelInfo.TyreWear.ActualWear + _wearPerMinute * timeRemaining.TotalMinutes)); }
/// <summary> /// Updates the position of the wheel according to the BRaycastVehicle's position and speed. /// </summary> private void Update() { if (robot == null) { return; } Vector3 velocity = ((RigidBody)transform.parent.GetComponent <BRigidBody>().GetCollisionObject()).GetVelocityInLocalPoint(basePoint).ToUnity(); Vector3 localVelocity = transform.parent.InverseTransformDirection(velocity); WheelInfo wheelInfo = robot.RaycastRobot.GetWheelInfo(wheelIndex); Vector3 wheelAxle = wheelInfo.WheelAxleCS.ToUnity(); transform.position = wheelInfo.WorldTransform.Origin.ToUnity(); transform.localRotation *= Quaternion.AngleAxis(-Vector3.Dot(localVelocity, Quaternion.AngleAxis(90f, Vector3.up) * wheelAxle / (Mathf.PI * radius)), axis); Debug.DrawLine(transform.position, transform.position + transform.parent.TransformDirection(wheelInfo.WheelAxleCS.ToUnity()) * 0.1f, Color.red); }
public void ApplyWheelInfo(SimulatorDataSet dataSet, WheelInfo wheelInfo) { SessionInfo sessionInfo = dataSet.SessionInfo; if (_lastCheckTime != TimeSpan.Zero && (sessionInfo.SessionTime - _lastCheckTime).TotalSeconds < 30) { return; } if (dataSet.SessionInfo.SessionType == SessionType.Na || dataSet.SessionInfo.SessionTime == TimeSpan.Zero) { return; } _lastCheckTime = sessionInfo.SessionTime; UpdateTyreWear(wheelInfo, dataSet); CalculateWearAtRaceEnd(wheelInfo, dataSet); CalculateLapsUntilHeavyWear(wheelInfo, dataSet); }
private void UpdateWheelTemp(SimulatorDataSet data) { if (data.PlayerInfo == null) { return; } WheelInfo wheel = GetWheelByPosition(data); if (wheel == null) { return; } wheelTempLeft.Text = wheel.LeftTyreTemp.GetValueInUnits(TemperatureDisplayUnit).ToString("0"); wheelTempLeft.PixelOn = ComputeColor(wheel.LeftTyreTemp.InCelsius, wheel.OptimalTyreTemperature.InCelsius, wheel.OptimalTyreWindow); wheelTempCenter.Text = wheel.CenterTyreTemp.GetValueInUnits(TemperatureDisplayUnit).ToString("0"); wheelTempCenter.PixelOn = ComputeColor(wheel.CenterTyreTemp.InCelsius, wheel.OptimalTyreTemperature.InCelsius, wheel.OptimalTyreWindow); wheelTempRight.Text = wheel.RightTyreTemp.GetValueInUnits(TemperatureDisplayUnit).ToString("0"); wheelTempRight.PixelOn = ComputeColor(wheel.RightTyreTemp.InCelsius, wheel.OptimalTyreTemperature.InCelsius, wheel.OptimalTyreWindow); }
private void UpdateTyreWearControl(SimulatorDataSet data) { if (data.PlayerInfo == null) { return; } WheelInfo wheel = GetWheelByPosition(data); if (wheel == null) { return; } double wear = wheel.TyreWear; lblTyreType.Text = wheel.TyreType; lblTyreType.Visible = wheel.TyreTypeFilled; pnlWear.Width = (int)((1 - wear) * Width); lbWear.Text = ((1 - wear) * 100).ToString("0"); }
protected void AddWheels(Vector3 halfExtents, RaycastVehicle vehicle, VehicleTuning tuning, float wheelRadius) { //The direction of the raycast, the btRaycastVehicle uses raycasts instead of simiulating the wheels with rigid bodies Vector3 wheelDirectionCS0 = new Vector3(0, -1, 0); //The axis which the wheel rotates arround Vector3 wheelAxleCS = new Vector3(-1, 0, 0); //All the wheel configuration assumes the vehicle is centered at the origin and a right handed coordinate system is used Vector4 points = contactInfoByChassis(mesh.Name); points.Y += suspensionLength + meshAxisRadius.Y - (meshRealHeight / 2f); //Adds the rear wheels Vector3 wheelConnectionPoint = new Vector3(points.X, points.Y - rearWheelsHeight, points.Z); vehicle.AddWheel(wheelConnectionPoint, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, false); vehicle.AddWheel(wheelConnectionPoint * new Vector3(-1, 1, 1), wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, false); //Adds the front wheels wheelConnectionPoint = new Vector3(points.X, points.Y - frontWheelsHeight, points.W); vehicle.AddWheel(wheelConnectionPoint * new Vector3(1, 1, -1), wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, true); vehicle.AddWheel(wheelConnectionPoint * new Vector3(-1, 1, -1), wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, true); //Configures each wheel of our vehicle, setting its friction, damping compression, etc. //For more details on what each parameter does, refer to the docs for (int i = 0; i < vehicle.NumWheels; i++) { WheelInfo wheel = vehicle.GetWheelInfo(i); wheel.MaxSuspensionForce = 700000; //wheel.MaxSuspensionTravelCm = 80; wheel.SuspensionStiffness = suspensionStiffness; wheel.WheelsDampingCompression = dampingCompression * 2 * FastMath.Sqrt(wheel.SuspensionStiffness); wheel.WheelsDampingRelaxation = dampingRelaxation * 2 * FastMath.Sqrt(wheel.SuspensionStiffness); wheel.FrictionSlip = frictionSlip; wheel.RollInfluence = rollInfluence; } }
public void Evaluate(int SpreadMax) { if (FInVehicle.PluginIO.IsConnected) { FOutTransform.SliceCount = this.FInVehicle[0].NumWheels; RaycastVehicle v = this.FInVehicle[0]; for (int i = 0; i < v.NumWheels; i++) { WheelInfo wi = v.GetWheelInfo(i); Matrix m = wi.WorldTransform; Matrix4x4 mn = new Matrix4x4(m.M11, m.M12, m.M13, m.M14, m.M21, m.M22, m.M23, m.M24, m.M31, m.M32, m.M33, m.M34, m.M41, m.M42, m.M43, m.M44); //wi.r this.FOutTransform[i] = mn; } } }
private void FillWheelIdealQuantities(WheelInfo wheel, OptimalQuantity <Pressure> optimalPressure, OptimalQuantity <Temperature> optimalTemperature) { if (optimalPressure != null) { wheel.TyrePressure.IdealQuantity.InKpa = optimalPressure.IdealQuantity.InKpa; wheel.TyrePressure.IdealQuantityWindow.InKpa = optimalPressure.IdealQuantityWindow.InKpa; } if (optimalTemperature != null) { wheel.TyreCoreTemperature.IdealQuantity.InCelsius = optimalTemperature.IdealQuantity.InCelsius; wheel.TyreCoreTemperature.IdealQuantityWindow.InCelsius = optimalTemperature.IdealQuantityWindow.InCelsius; wheel.LeftTyreTemp.IdealQuantity.InCelsius = optimalTemperature.IdealQuantity.InCelsius; wheel.LeftTyreTemp.IdealQuantityWindow.InCelsius = optimalTemperature.IdealQuantityWindow.InCelsius; wheel.CenterTyreTemp.IdealQuantity.InCelsius = optimalTemperature.IdealQuantity.InCelsius; wheel.CenterTyreTemp.IdealQuantityWindow.InCelsius = optimalTemperature.IdealQuantityWindow.InCelsius; wheel.RightTyreTemp.IdealQuantity.InCelsius = optimalTemperature.IdealQuantity.InCelsius; wheel.RightTyreTemp.IdealQuantityWindow.InCelsius = optimalTemperature.IdealQuantityWindow.InCelsius; } }
/// <summary> /// Adds a wheel to the BRaycastVehicle from the given information. /// </summary> /// <param name="connectionPoint"></param> /// <param name="axle"></param> /// <param name="suspensionRestLength"></param> /// <param name="radius"></param> /// <returns></returns> public int AddWheel(WheelType wheelType, BulletSharp.Math.Vector3 connectionPoint, BulletSharp.Math.Vector3 axle, float suspensionRestLength, float radius) { switch (wheelType) { case WheelType.MECANUM: RaycastRobot.SlidingFriction = 0.1f; axle = (Quaternion.AngleAxis((connectionPoint.X > 0 && connectionPoint.Z > 0) || (connectionPoint.X < 0 && connectionPoint.Z < 0) ? -45 : 45, Vector3.up) * axle.ToUnity()).ToBullet(); break; case WheelType.OMNI: RaycastRobot.SlidingFriction = 0.1f; break; } WheelInfo w = RaycastRobot.AddWheel(connectionPoint, -BulletSharp.Math.Vector3.UnitY, axle, suspensionRestLength, radius, vehicleTuning, false); w.RollInfluence = 0.25f; w.Brake = RollingFriction / radius; return(RaycastRobot.NumWheels - 1); }
protected override double GetXWheelValue(WheelInfo wheelInfo, TimedTelemetrySnapshot snapshot) { return(snapshot.PlayerData.CarInfo.Acceleration.ZinG); }
public void UpdateFriction(float timeStep) { //calculate the impulse, so that the wheels don't move sidewards int numWheel = NumWheels; if (numWheel == 0) { return; } Array.Resize(ref forwardWS, numWheel); Array.Resize(ref axle, numWheel); Array.Resize(ref forwardImpulse, numWheel); Array.Resize(ref sideImpulse, numWheel); int numWheelsOnGround = 0; //collapse all those loops into one! for (int i = 0; i < NumWheels; i++) { RigidBody groundObject = wheelInfo[i].RaycastInfo.GroundObject as RigidBody; if (groundObject != null) { numWheelsOnGround++; } sideImpulse[i] = 0; forwardImpulse[i] = 0; } for (int i = 0; i < NumWheels; i++) { WheelInfo wheel = wheelInfo[i]; RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody; if (groundObject != null) { Matrix wheelTrans = GetWheelTransformWS(i); axle[i] = new Vector3( wheelTrans[0, indexRightAxis], wheelTrans[1, indexRightAxis], wheelTrans[2, indexRightAxis]); Vector3 surfNormalWS = wheel.RaycastInfo.ContactNormalWS; float proj; Vector3.Dot(ref axle[i], ref surfNormalWS, out proj); axle[i] -= surfNormalWS * proj; axle[i].Normalize(); Vector3.Cross(ref surfNormalWS, ref axle[i], out forwardWS[i]); forwardWS[i].Normalize(); ResolveSingleBilateral(chassisBody, wheel.RaycastInfo.ContactPointWS, groundObject, wheel.RaycastInfo.ContactPointWS, 0, axle[i], ref sideImpulse[i], timeStep); sideImpulse[i] *= sideFrictionStiffness2; } } const float sideFactor = 1.0f; const float fwdFactor = 0.5f; bool sliding = false; for (int i = 0; i < NumWheels; i++) { WheelInfo wheel = wheelInfo[i]; RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody; float rollingFriction = 0.0f; if (groundObject != null) { if (wheel.EngineForce != 0.0f) { rollingFriction = wheel.EngineForce * timeStep; } else { float defaultRollingFrictionImpulse = 0.0f; float maxImpulse = (wheel.Brake != 0) ? wheel.Brake : defaultRollingFrictionImpulse; rollingFriction = CalcRollingFriction(chassisBody, groundObject, wheel.RaycastInfo.ContactPointWS, forwardWS[i], maxImpulse); } } //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break) forwardImpulse[i] = 0; wheelInfo[i].SkidInfo = 1.0f; if (groundObject != null) { wheelInfo[i].SkidInfo = 1.0f; float maximp = wheel.WheelsSuspensionForce * timeStep * wheel.FrictionSlip; float maximpSide = maximp; float maximpSquared = maximp * maximpSide; forwardImpulse[i] = rollingFriction;//wheel.EngineForce* timeStep; float x = forwardImpulse[i] * fwdFactor; float y = sideImpulse[i] * sideFactor; float impulseSquared = (x * x + y * y); if (impulseSquared > maximpSquared) { sliding = true; float factor = maximp / (float)Math.Sqrt(impulseSquared); wheelInfo[i].SkidInfo *= factor; } } } if (sliding) { for (int wheel = 0; wheel < NumWheels; wheel++) { if (sideImpulse[wheel] != 0) { if (wheelInfo[wheel].SkidInfo < 1.0f) { forwardImpulse[wheel] *= wheelInfo[wheel].SkidInfo; sideImpulse[wheel] *= wheelInfo[wheel].SkidInfo; } } } } // apply the impulses for (int i = 0; i < NumWheels; i++) { WheelInfo wheel = wheelInfo[i]; Vector3 rel_pos = wheel.RaycastInfo.ContactPointWS - chassisBody.CenterOfMassPosition; if (forwardImpulse[i] != 0) { chassisBody.ApplyImpulse(forwardWS[i] * forwardImpulse[i], rel_pos); } if (sideImpulse[i] != 0) { RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody; Vector3 rel_pos2 = wheel.RaycastInfo.ContactPointWS - groundObject.CenterOfMassPosition; Vector3 sideImp = axle[i] * sideImpulse[i]; #if ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT. //Vector4 vChassisWorldUp = RigidBody.CenterOfMassTransform.get_Columns(indexUpAxis); Vector3 vChassisWorldUp = new Vector3( RigidBody.CenterOfMassTransform.Row1[indexUpAxis], RigidBody.CenterOfMassTransform.Row2[indexUpAxis], RigidBody.CenterOfMassTransform.Row3[indexUpAxis]); float dot; Vector3.Dot(ref vChassisWorldUp, ref rel_pos, out dot); rel_pos -= vChassisWorldUp * (dot * (1.0f - wheel.RollInfluence)); #else rel_pos[indexUpAxis] *= wheel.RollInfluence; #endif chassisBody.ApplyImpulse(sideImp, rel_pos); //apply friction impulse on the ground groundObject.ApplyImpulse(-sideImp, rel_pos2); } } }
/// <summary> /// Updates the friction for the RaycastRobot. /// </summary> /// <param name="timeStep"></param> public void UpdateFriction(float timeStep) { //calculate the impulse, so that the wheels don't move sidewards int numWheel = NumWheels; if (numWheel == 0) { return; } Array.Resize <Vector3>(ref forwardWS, numWheel); Array.Resize <Vector3>(ref axle, numWheel); Array.Resize <float>(ref forwardImpulse, numWheel); Array.Resize <float>(ref sideImpulse, numWheel); int numWheelsOnGround = 0; //collapse all those loops into one! for (int i = 0; i < NumWheels; i++) { RigidBody groundObject = wheelInfo[i].RaycastInfo.GroundObject as RigidBody; if (groundObject != null) { numWheelsOnGround++; } sideImpulse[i] = 0; forwardImpulse[i] = 0; } for (int i = 0; i < NumWheels; i++) { RobotWheelInfo wheel = wheelInfo[i]; RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody; if (groundObject != null) { Matrix wheelTrans = GetWheelTransformWS(i); axle[i] = new Vector3( wheelTrans[0, indexRightAxis], wheelTrans[1, indexRightAxis], wheelTrans[2, indexRightAxis]); Vector3 surfNormalWS = wheel.RaycastInfo.ContactNormalWS; float proj; Vector3.Dot(ref axle[i], ref surfNormalWS, out proj); axle[i] -= surfNormalWS * proj; axle[i].Normalize(); Vector3.Cross(ref surfNormalWS, ref axle[i], out forwardWS[i]); forwardWS[i].Normalize(); ResolveSingleBilateral(RootRigidBody, wheel.RaycastInfo.ContactPointWS, groundObject, wheel.RaycastInfo.ContactPointWS, 0, axle[i], ref sideImpulse[i], timeStep); sideImpulse[i] *= wheel.SlidingFriction; } else { if (wheel.Speed > 0) { wheel.Speed = Math.Max(wheel.Speed - wheel.FreeSpinDamping, 0f); } else if (wheel.Speed < 0) { wheel.Speed = Math.Min(wheel.Speed + wheel.FreeSpinDamping, 0f); } } } bool sliding = false; for (int i = 0; i < NumWheels; i++) { RobotWheelInfo wheel = wheelInfo[i]; RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody; float rollingFriction = 0.0f; if (groundObject != null) { Vector3 velocity = chassisBody.GetVelocityInLocalPoint(wheel.ChassisConnectionPointCS); Vector3 localVelocity = Vector3.TransformNormal(velocity, Matrix.Invert(chassisBody.WorldTransform.Basis)); Vector3 forwardAxis = (UnityEngine.Quaternion.AngleAxis(90f, UnityEngine.Vector3.up) * wheel.WheelAxleCS.ToUnity() / (MathUtil.SIMD_PI * wheel.WheelsRadius)).ToBullet(); float speed = Vector3.Dot(localVelocity, forwardAxis); wheel.Speed = speed; if (wheel.EngineForce != 0.0f) { //apply torque curves float engineForce = wheel.EngineForce; if (speed * engineForce > 0) { engineForce *= 1 - (Math.Abs(speed) / MaxWheelAngularVelocity); } rollingFriction = engineForce * timeStep; if (!RootRigidBody.IsActive) { RootRigidBody.Activate(); } } else { float defaultRollingFrictionImpulse = 0.0f; float maxImpulse = (wheel.Brake != 0) ? wheel.Brake : defaultRollingFrictionImpulse; rollingFriction = CalcRollingFriction(RootRigidBody, groundObject, wheel.RaycastInfo.ContactPointWS, forwardWS[i], maxImpulse); } } //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break) forwardImpulse[i] = 0; wheelInfo[i].SkidInfo = 1.0f; if (groundObject != null) { wheelInfo[i].SkidInfo = 1.0f; float maximp = wheel.WheelsSuspensionForce * timeStep * wheel.FrictionSlip; float maximpSide = maximp; float maximpSquared = maximp * maximpSide; forwardImpulse[i] = rollingFriction; float x = forwardImpulse[i] * fwdFactor; float y = sideImpulse[i] * sideFactor; float impulseSquared = (x * x + y * y); if (impulseSquared > maximpSquared) { sliding = true; float factor = maximp / (float)System.Math.Sqrt(impulseSquared); wheelInfo[i].SkidInfo *= factor; } } } if (sliding) { for (int wheel = 0; wheel < NumWheels; wheel++) { if (sideImpulse[wheel] != 0) { if (wheelInfo[wheel].SkidInfo < 1.0f) { forwardImpulse[wheel] *= wheelInfo[wheel].SkidInfo; sideImpulse[wheel] *= wheelInfo[wheel].SkidInfo; } } } } // apply the impulses for (int i = 0; i < NumWheels; i++) { WheelInfo wheel = wheelInfo[i]; Vector3 rel_pos = wheel.RaycastInfo.ContactPointWS - chassisBody.CenterOfMassPosition; if (forwardImpulse[i] != 0) { chassisBody.ApplyImpulse(forwardWS[i] * forwardImpulse[i], rel_pos); } if (sideImpulse[i] != 0) { RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody; Vector3 rel_pos2 = wheel.RaycastInfo.ContactPointWS - groundObject.CenterOfMassPosition; Vector3 sideImp = axle[i] * sideImpulse[i]; #if ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT. //Vector4 vChassisWorldUp = RigidBody.CenterOfMassTransform.get_Columns(indexUpAxis); Vector3 vChassisWorldUp = new Vector3( RigidBody.CenterOfMassTransform.Row1[indexUpAxis], RigidBody.CenterOfMassTransform.Row2[indexUpAxis], RigidBody.CenterOfMassTransform.Row3[indexUpAxis]); float dot; Vector3.Dot(ref vChassisWorldUp, ref rel_pos, out dot); rel_pos -= vChassisWorldUp * (dot * (1.0f - wheel.RollInfluence)); #else rel_pos[indexUpAxis] *= wheel.RollInfluence; #endif chassisBody.ApplyImpulse(sideImp, rel_pos); //apply friction impulse on the ground groundObject.ApplyImpulse(-sideImp, rel_pos2); } } }
private float RayCast(WheelInfo wheel) { UpdateWheelTransformsWS(wheel, false); float depth = -1; float raylen = wheel.SuspensionRestLength + wheel.WheelsRadius; Vector3 rayvector = wheel.RaycastInfo.WheelDirectionWS * raylen; Vector3 source = wheel.RaycastInfo.HardPointWS; wheel.RaycastInfo.ContactPointWS = source + rayvector; Vector3 target = wheel.RaycastInfo.ContactPointWS; float param = 0; VehicleRaycasterResult rayResults = new VehicleRaycasterResult(); Debug.Assert(vehicleRaycaster != null); object obj = vehicleRaycaster.CastRay(ref source, ref target, rayResults); wheel.RaycastInfo.GroundObject = null; if (obj != null) { param = rayResults.DistFraction; depth = raylen * rayResults.DistFraction; wheel.RaycastInfo.ContactNormalWS = rayResults.HitNormalInWorld; wheel.RaycastInfo.IsInContact = true; wheel.RaycastInfo.GroundObject = fixedBody;///@todo for driving on dynamic/movable objects!; /////wheel.RaycastInfo.GroundObject = object; float hitDistance = param * raylen; wheel.RaycastInfo.SuspensionLength = hitDistance - wheel.WheelsRadius; //clamp on max suspension travel float minSuspensionLength = wheel.SuspensionRestLength - wheel.MaxSuspensionTravelCm * 0.01f; float maxSuspensionLength = wheel.SuspensionRestLength + wheel.MaxSuspensionTravelCm * 0.01f; if (wheel.RaycastInfo.SuspensionLength < minSuspensionLength) { wheel.RaycastInfo.SuspensionLength = minSuspensionLength; } if (wheel.RaycastInfo.SuspensionLength > maxSuspensionLength) { wheel.RaycastInfo.SuspensionLength = maxSuspensionLength; } wheel.RaycastInfo.ContactPointWS = rayResults.HitPointInWorld; float denominator = Vector3.Dot(wheel.RaycastInfo.ContactNormalWS, wheel.RaycastInfo.WheelDirectionWS); Vector3 chassis_velocity_at_contactPoint; Vector3 relpos = wheel.RaycastInfo.ContactPointWS - RigidBody.CenterOfMassPosition; chassis_velocity_at_contactPoint = RigidBody.GetVelocityInLocalPoint(relpos); float projVel = Vector3.Dot(wheel.RaycastInfo.ContactNormalWS, chassis_velocity_at_contactPoint); if (denominator >= -0.1f) { wheel.SuspensionRelativeVelocity = 0; wheel.ClippedInvContactDotSuspension = 1.0f / 0.1f; } else { float inv = -1.0f / denominator; wheel.SuspensionRelativeVelocity = projVel * inv; wheel.ClippedInvContactDotSuspension = inv; } } else { //put wheel info as in rest position wheel.RaycastInfo.SuspensionLength = wheel.SuspensionRestLength; wheel.SuspensionRelativeVelocity = 0.0f; wheel.RaycastInfo.ContactNormalWS = -wheel.RaycastInfo.WheelDirectionWS; wheel.ClippedInvContactDotSuspension = 1.0f; } return(depth); }
protected abstract double GetYWheelValue(WheelInfo wheelInfo, TimedTelemetrySnapshot snapshot);
public Physics(VehicleDemo game) { CollisionShape groundShape = new BoxShape(50, 3, 50); CollisionShapes.Add(groundShape); CollisionConf = new DefaultCollisionConfiguration(); Dispatcher = new CollisionDispatcher(CollisionConf); Solver = new SequentialImpulseConstraintSolver(); Vector3 worldMin = new Vector3(-10000, -10000, -10000); Vector3 worldMax = new Vector3(10000, 10000, 10000); Broadphase = new AxisSweep3(worldMin, worldMax); //Broadphase = new DbvtBroadphase(); World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, Solver, CollisionConf); int i; Matrix tr; Matrix vehicleTr; if (UseTrimeshGround) { const float scale = 20.0f; //create a triangle-mesh ground int vertStride = Vector3.SizeInBytes; int indexStride = 3 * sizeof(int); const int NUM_VERTS_X = 20; const int NUM_VERTS_Y = 20; const int totalVerts = NUM_VERTS_X * NUM_VERTS_Y; const int totalTriangles = 2 * (NUM_VERTS_X - 1) * (NUM_VERTS_Y - 1); TriangleIndexVertexArray vertexArray = new TriangleIndexVertexArray(); IndexedMesh mesh = new IndexedMesh(); mesh.Allocate(totalVerts, vertStride, totalTriangles, indexStride, PhyScalarType.Int32, PhyScalarType.Single); BulletSharp.DataStream data = mesh.LockVerts(); for (i = 0; i < NUM_VERTS_X; i++) { for (int j = 0; j < NUM_VERTS_Y; j++) { float wl = .2f; float height = 20.0f * (float)(Math.Sin(i * wl) * Math.Cos(j * wl)); data.Write((i - NUM_VERTS_X * 0.5f) * scale); data.Write(height); data.Write((j - NUM_VERTS_Y * 0.5f) * scale); } } int index = 0; IntArray idata = mesh.TriangleIndices; for (i = 0; i < NUM_VERTS_X - 1; i++) { for (int j = 0; j < NUM_VERTS_Y - 1; j++) { idata[index++] = j * NUM_VERTS_X + i; idata[index++] = j * NUM_VERTS_X + i + 1; idata[index++] = (j + 1) * NUM_VERTS_X + i + 1; idata[index++] = j * NUM_VERTS_X + i; idata[index++] = (j + 1) * NUM_VERTS_X + i + 1; idata[index++] = (j + 1) * NUM_VERTS_X + i; } } vertexArray.AddIndexedMesh(mesh); groundShape = new BvhTriangleMeshShape(vertexArray, true); tr = Matrix.Identity; vehicleTr = Matrix.Translation(0, -2, 0); } else { // Use HeightfieldTerrainShape int width = 40, length = 40; //int width = 128, length = 128; // Debugging is too slow for this float maxHeight = 10.0f; float heightScale = maxHeight / 256.0f; Vector3 scale = new Vector3(20.0f, maxHeight, 20.0f); //PhyScalarType scalarType = PhyScalarType.PhyUChar; //FileStream file = new FileStream(heightfieldFile, FileMode.Open, FileAccess.Read); // Use float data PhyScalarType scalarType = PhyScalarType.Single; byte[] terr = new byte[width * length * 4]; MemoryStream file = new MemoryStream(terr); BinaryWriter writer = new BinaryWriter(file); for (i = 0; i < width; i++) { for (int j = 0; j < length; j++) { writer.Write((float)((maxHeight / 2) + 4 * Math.Sin(j * 0.5f) * Math.Cos(i))); } } writer.Flush(); file.Position = 0; HeightfieldTerrainShape heightterrainShape = new HeightfieldTerrainShape(width, length, file, heightScale, 0, maxHeight, upIndex, scalarType, false); heightterrainShape.SetUseDiamondSubdivision(true); groundShape = heightterrainShape; groundShape.LocalScaling = new Vector3(scale.X, 1, scale.Z); tr = Matrix.Translation(new Vector3(-scale.X / 2, scale.Y / 2, -scale.Z / 2)); vehicleTr = Matrix.Translation(new Vector3(20, 3, -3)); // Create graphics object file.Position = 0; BinaryReader reader = new BinaryReader(file); int totalTriangles = (width - 1) * (length - 1) * 2; int totalVerts = width * length; game.groundMesh = new Mesh(game.Device, totalTriangles, totalVerts, MeshFlags.SystemMemory | MeshFlags.Use32Bit, VertexFormat.Position | VertexFormat.Normal); SlimDX.DataStream data = game.groundMesh.LockVertexBuffer(LockFlags.None); for (i = 0; i < width; i++) { for (int j = 0; j < length; j++) { float height; if (scalarType == PhyScalarType.Single) { // heightScale isn't applied internally for float data height = reader.ReadSingle(); } else if (scalarType == PhyScalarType.Byte) { height = file.ReadByte() * heightScale; } else { height = 0.0f; } data.Write((j - length * 0.5f) * scale.X); data.Write(height); data.Write((i - width * 0.5f) * scale.Z); // Normals will be calculated later data.Position += 12; } } game.groundMesh.UnlockVertexBuffer(); file.Close(); data = game.groundMesh.LockIndexBuffer(LockFlags.None); for (i = 0; i < width - 1; i++) { for (int j = 0; j < length - 1; j++) { // Using diamond subdivision if ((j + i) % 2 == 0) { data.Write(j * width + i); data.Write((j + 1) * width + i + 1); data.Write(j * width + i + 1); data.Write(j * width + i); data.Write((j + 1) * width + i); data.Write((j + 1) * width + i + 1); } else { data.Write(j * width + i); data.Write((j + 1) * width + i); data.Write(j * width + i + 1); data.Write(j * width + i + 1); data.Write((j + 1) * width + i); data.Write((j + 1) * width + i + 1); } /* * // Not using diamond subdivision * data.Write(j * width + i); * data.Write((j + 1) * width + i); * data.Write(j * width + i + 1); * * data.Write(j * width + i + 1); * data.Write((j + 1) * width + i); * data.Write((j + 1) * width + i + 1); */ } } game.groundMesh.UnlockIndexBuffer(); game.groundMesh.ComputeNormals(); } CollisionShapes.Add(groundShape); //create ground object RigidBody ground = LocalCreateRigidBody(0, tr, groundShape); ground.UserObject = "Ground"; CollisionShape chassisShape = new BoxShape(1.0f, 0.5f, 2.0f); CollisionShapes.Add(chassisShape); CompoundShape compound = new CompoundShape(); CollisionShapes.Add(compound); //localTrans effectively shifts the center of mass with respect to the chassis Matrix localTrans = Matrix.Translation(Vector3.UnitY); compound.AddChildShape(localTrans, chassisShape); RigidBody carChassis = LocalCreateRigidBody(800, Matrix.Identity, compound); carChassis.UserObject = "Chassis"; //carChassis.SetDamping(0.2f, 0.2f); //CylinderShapeX wheelShape = new CylinderShapeX(wheelWidth, wheelRadius, wheelRadius); // clientResetScene(); // create vehicle RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); IVehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(World); vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); carChassis.ActivationState = ActivationState.DisableDeactivation; World.AddAction(vehicle); float connectionHeight = 1.2f; bool isFrontWheel = true; // choose coordinate system vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); WheelInfo a = vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); isFrontWheel = false; connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); for (i = 0; i < vehicle.NumWheels; i++) { WheelInfo wheel = vehicle.GetWheelInfo(i); wheel.SuspensionStiffness = suspensionStiffness; wheel.WheelsDampingRelaxation = suspensionDamping; wheel.WheelsDampingCompression = suspensionCompression; wheel.FrictionSlip = wheelFriction; wheel.RollInfluence = rollInfluence; } vehicle.RigidBody.WorldTransform = vehicleTr; }
protected override double GetYWheelValue(WheelInfo wheelInfo, TimedTelemetrySnapshot snapshot) { return(wheelInfo.TyreLoad.GetValueInUnits(ForceUnits)); }
public void Evaluate(int SpreadMax) { IRigidBulletWorld inputWorld = this.worldInput[0]; SpreadMax = 1; if (inputWorld != null) { this.persistedList.UpdateWorld(inputWorld); if (this.chassisShape.IsConnected) { for (int i = 0; i < SpreadMax; i++) { if (this.doCreate[i]) { RigidBodyPose initialPose = this.initialPoseInput.IsConnected ? this.initialPoseInput[i] : RigidBodyPose.Default; RigidBodyProperties properties = this.initialProperties.IsConnected ? this.initialProperties[i] : RigidBodyProperties.Default; ShapeCustomData shapeData = new ShapeCustomData(); DynamicShapeDefinitionBase chassisShapeDefinition = this.chassisShape[i]; CollisionShape chassisShape = chassisShapeDefinition.GetShape(shapeData); shapeData.ShapeDef = chassisShapeDefinition; RaycastVehicle vehicle; CompoundShape compoundShape = new CompoundShape(); Matrix localTrans = Matrix.Translation(Vector3.UnitY); compoundShape.AddChildShape(localTrans, chassisShape); //Build mass for dynamic object Vector3 localInertia = Vector3.Zero; if (chassisShapeDefinition.Mass > 0.0f) { compoundShape.CalculateLocalInertia(chassisShapeDefinition.Mass, out localInertia); } Tuple <RigidBody, int> createBodyResult = inputWorld.CreateRigidBody(chassisShape, ref initialPose, ref properties, ref localInertia, chassisShapeDefinition.Mass, this.customString[i]); RigidBody carChassis = createBodyResult.Item1; RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); DefaultVehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(inputWorld.World); vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); carChassis.ActivationState = ActivationState.DisableDeactivation; inputWorld.World.AddAction(vehicle); int wheelCount = this.wheelConstruction.SliceCount; //Add wheels for (int j = 0; j < this.wheelConstruction[i].SliceCount; j++) { WheelConstructionProperties wcs = this.wheelConstruction[i][j]; Vector3 connectionPointCS0 = wcs.localPosition.ToBulletVector(); WheelInfo wheel = vehicle.AddWheel(connectionPointCS0, wcs.wheelDirection.ToBulletVector(), wcs.wheelAxis.ToBulletVector(), wcs.SuspensionRestLength, wcs.WheelRadius, tuning, wcs.isFrontWheel); } //Set Wheel Properties WheelProperties wis = this.wheelInfoSettings[i] != null ? this.wheelInfoSettings[i] : new WheelProperties(); for (int j = 0; j < vehicle.NumWheels; j++) { WheelInfo wheel = vehicle.GetWheelInfo(j); wheel.SuspensionStiffness = wis.SuspensionStiffness; wheel.WheelsDampingRelaxation = wis.WheelsDampingRelaxation; wheel.WheelsDampingCompression = wis.WheelsDampingCompression; wheel.FrictionSlip = wis.FrictionSlip; wheel.RollInfluence = wis.RollInfluence; } BodyCustomData bd = (BodyCustomData)carChassis.UserObject; bd.Vehicle = vehicle; this.persistedList.Append(createBodyResult.Item1, createBodyResult.Item2); } } List <RigidBody> bodies = this.persistedList.Bodies; this.vehicleOutput.SliceCount = bodies.Count; this.chassisOutput.SliceCount = bodies.Count; for (int i = 0; i < bodies.Count; i++) { BodyCustomData bd = (BodyCustomData)bodies[i].UserObject; this.vehicleOutput[i] = bd.Vehicle; this.chassisOutput[i] = bodies[i]; } } } else { this.vehicleOutput.SliceCount = 0; this.chassisOutput.SliceCount = 0; } }
public void UpdateVehicle(float step) { for (int i = 0; i < NumWheels; i++) { UpdateWheelTransform(i, false); } currentVehicleSpeedKmHour = 3.6f * RigidBody.LinearVelocity.Length; Matrix chassisTrans = ChassisWorldTransform; Vector3 forwardW = new Vector3( chassisTrans[0, indexForwardAxis], chassisTrans[1, indexForwardAxis], chassisTrans[2, indexForwardAxis]); if (Vector3.Dot(forwardW, RigidBody.LinearVelocity) < 0) { currentVehicleSpeedKmHour *= -1.0f; } // Simulate suspension /* * for (int i = 0; i < wheelInfo.Count; i++) * { * float depth = RayCast(wheelInfo[i]); * } */ UpdateSuspension(step); for (int i = 0; i < wheelInfo.Count; i++) { //apply suspension force WheelInfo wheel = wheelInfo[i]; float suspensionForce = wheel.WheelsSuspensionForce; if (suspensionForce > wheel.MaxSuspensionForce) { suspensionForce = wheel.MaxSuspensionForce; } Vector3 impulse = wheel.RaycastInfo.ContactNormalWS * suspensionForce * step; Vector3 relpos = wheel.RaycastInfo.ContactPointWS - RigidBody.CenterOfMassPosition; RigidBody.ApplyImpulse(impulse, relpos); } UpdateFriction(step); for (int i = 0; i < wheelInfo.Count; i++) { WheelInfo wheel = wheelInfo[i]; Vector3 relpos = wheel.RaycastInfo.HardPointWS - RigidBody.CenterOfMassPosition; Vector3 vel = RigidBody.GetVelocityInLocalPoint(relpos); if (wheel.RaycastInfo.IsInContact) { Matrix chassisWorldTransform = ChassisWorldTransform; Vector3 fwd = new Vector3( chassisWorldTransform[0, indexForwardAxis], chassisWorldTransform[1, indexForwardAxis], chassisWorldTransform[2, indexForwardAxis]); float proj = Vector3.Dot(fwd, wheel.RaycastInfo.ContactNormalWS); fwd -= wheel.RaycastInfo.ContactNormalWS * proj; float proj2; Vector3.Dot(ref fwd, ref vel, out proj2); wheel.DeltaRotation = (proj2 * step) / (wheel.WheelsRadius); wheel.Rotation += wheel.DeltaRotation; } else { wheel.Rotation += wheel.DeltaRotation; } wheel.DeltaRotation *= 0.99f;//damping of rotation when not in contact } }
private void CreateVehicle(Matrix transform) { var chassisShape = new BoxShape(1.0f, 0.5f, 2.0f); var compound = new CompoundShape(); //localTrans effectively shifts the center of mass with respect to the chassis Matrix localTrans = Matrix.Translation(Vector3.UnitY); compound.AddChildShape(localTrans, chassisShape); RigidBody carChassis = PhysicsHelper.CreateBody(800, Matrix.Identity, compound, World); carChassis.UserObject = "Chassis"; //carChassis.SetDamping(0.2f, 0.2f); var tuning = new VehicleTuning(); var vehicleRayCaster = new DefaultVehicleRaycaster(World); //vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); _vehicle = new CustomVehicle(tuning, carChassis, vehicleRayCaster); carChassis.ActivationState = ActivationState.DisableDeactivation; World.AddAction(_vehicle); const float connectionHeight = 1.2f; // choose coordinate system _vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 wheelDirection = Vector3.Zero; Vector3 wheelAxle = Vector3.Zero; wheelDirection[upIndex] = -1; wheelAxle[rightIndex] = -1; bool isFrontWheel = true; var connectionPoint = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPoint = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel); isFrontWheel = false; connectionPoint = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPoint = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel); for (int i = 0; i < _vehicle.NumWheels; i++) { WheelInfo wheel = _vehicle.GetWheelInfo(i); wheel.SuspensionStiffness = suspensionStiffness; wheel.WheelsDampingRelaxation = suspensionDamping; wheel.WheelsDampingCompression = suspensionCompression; wheel.FrictionSlip = wheelFriction; wheel.RollInfluence = rollInfluence; } _vehicle.RigidBody.WorldTransform = transform; }
private double GetTyreLoad(WheelInfo wheelInfo) { return(wheelInfo.TyreLoad.GetValueInUnits(ForceUnits)); }
public override void Evaluate(int SpreadMax) { for (int i = 0; i < SpreadMax; i++) { if (this.CanCreate(i)) { wheelRadius = FwheelRadius[0]; wheelWidth = FwheelWidth[0]; CUBE_HALF_EXTENTS = FwheelDistance[0]; RaycastVehicle vehicle; AbstractRigidShapeDefinition shapedef = this.FShapes[i]; ShapeCustomData sc = new ShapeCustomData(); sc.ShapeDef = shapedef; CompoundShape compound = new CompoundShape(); CollisionShape chassisShape = shapedef.GetShape(sc); Matrix localTrans = Matrix.Translation(Vector3.UnitY); compound.AddChildShape(localTrans, chassisShape); float mass = shapedef.Mass; bool isDynamic = (mass != 0.0f); isFrontWheel = true; Vector3 localInertia = Vector3.Zero; if (isDynamic) { chassisShape.CalculateLocalInertia(mass, out localInertia); } Vector3D pos = this.FPosition[i]; Vector4D rot = this.FRotation[i]; DefaultMotionState ms = BulletUtils.CreateMotionState(pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, rot.w); RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, ms, compound, localInertia); RigidBody carChassis = new RigidBody(rbInfo); BodyCustomData bd = new BodyCustomData(); carChassis.UserObject = bd; bd.Id = this.FWorld[0].GetNewBodyId(); bd.Custom = this.FCustom[i]; this.FWorld[0].Register(carChassis); RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); VehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(this.FWorld[0].World); vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); carChassis.ActivationState = ActivationState.DisableDeactivation; this.FWorld[0].World.AddAction(vehicle); // choose coordinate system vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), FconnectionHeight[0], 2 * CUBE_HALF_EXTENTS - wheelRadius); WheelInfo a = vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), FconnectionHeight[0], 2 * CUBE_HALF_EXTENTS - wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel); isFrontWheel = false; connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), FconnectionHeight[0], -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), FconnectionHeight[0], -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel); for (i = 0; i < vehicle.NumWheels; i++) { WheelInfo wheel = vehicle.GetWheelInfo(i); wheel.SuspensionStiffness = FsuspensionStiffness[0]; wheel.WheelDampingRelaxation = FDampingRelaxation[0]; wheel.WheelDampingCompression = FDampingCompression[0]; wheel.FrictionSlip = FwheelFriction[0]; wheel.RollInfluence = FrollInfluence[0]; wheel.MaxSuspensionTravelCm = FmaxSuspensionTravelCm[0]; wheel.MaxSuspensionForce = FmaxSuspensionForce[0]; } FOutVehicle.SliceCount = 1; FOutVehicle[0] = vehicle; } } }
protected override double GetYWheelValue(WheelInfo wheelInfo, TimedTelemetrySnapshot snapshot) { return(wheelInfo.RideHeight.GetByUnit(DistanceUnitsSmall)); }