public void TickControls() { bool wasActive = Active; // if (Main.GetButtonIn(JoyControls.LaneAssistance) && ButtonActive) { Active = !Active; ButtonCooldownPeriod = DateTime.Now.Add(new TimeSpan(0, 0, 0, 1)); LockedSteerAngle = Main.GetAxisIn(JoyControls.Steering); Debug.WriteLine("Setting lane assistance to: " + Active); } var currentSteerAngle = Main.GetAxisIn(JoyControls.Steering); // User overrides steering if (Active && Math.Abs(currentSteerAngle - LockedSteerAngle) > 0.05) { Active = false; Debug.WriteLine("[LA] User override steering"); } if (wasActive && !Active) { beep.Play(); } }
public void TickTelemetry(IDataMiner data) { Speed = data.Telemetry.Speed; if (Main.GetAxisIn(JoyControls.Brake) > 0.05) { Cruising = false; } // Any tracked car? if (dlDebugInfo.TrackedCar != null) { // Gap control? var distanceTarget = 20; var distanceError = distanceTarget - dlDebugInfo.TrackedCar.Distance; var speedBias = 9 * distanceError / distanceTarget; // 3m/s max decrement if (distanceError < 0) { speedBias /= 6; } var targetSpeed = dlDebugInfo.TrackedCar.Speed - speedBias; if (targetSpeed >= SpeedCruise) { targetSpeed = (float)SpeedCruise; } var speedErr = data.Telemetry.Speed - targetSpeed - 2; if (speedErr > 0) // too fast { t = 0; if (speedErr > 1.5f) { b = (float)Math.Pow(speedErr - 1.5f, 4) * 0.015f; } } else { t = -speedErr * 0.2f; b = 0; } } else { // Speed control var speedErr = data.Telemetry.Speed - (float)SpeedCruise; if (speedErr > 0) // too fast { t = 0; } else { t = -speedErr * 0.4f; b = 0; } } }
public void TickControls() { var br = Main.GetAxisIn(JoyControls.Brake); var th = Main.GetAxisIn(JoyControls.Throttle); switch (state) { case LaunchControlState.Inactive: if (Main.GetButtonIn(JoyControls.LaunchControl) && br > 0.05) { Debug.WriteLine("LC activated - waiting"); state = LaunchControlState.Waiting; } break; case LaunchControlState.Waiting: if (th > 0.1 && br > 0.05) { Debug.WriteLine("Revving up engine, waiting for brake to be released"); state = LaunchControlState.Revving; } else if (br < 0.05) { Debug.WriteLine("Brake released, stopped waiting"); state = LaunchControlState.Inactive; } break; case LaunchControlState.Revving: if (revvedUp && br < 0.05) // engine is ready & user lets go of brake { Debug.WriteLine("GO GO GO"); state = LaunchControlState.Pulling; } if (th < 0.1) // user lets go of throttle { Debug.WriteLine("Back to idle"); state = LaunchControlState.Waiting; } break; case LaunchControlState.Pulling: case LaunchControlState.Slipping: if (th < 0.1 || br > 0.05) { Debug.WriteLine("aborting"); state = LaunchControlState.Inactive; // abort } break; } }
public void TickTelemetry(IDataMiner data) { if (data.Telemetry.Speed * 3.6 > 55) { triggered = true; } if (triggered && data.Telemetry.Speed * 3.6 < 35) { clutchctrl = true; } else if (data.Telemetry.Speed * 3.6 > 35) { clutchctrl = false; } if (data.Telemetry.Speed * 3.6 < 10 && Main.GetAxisIn(JoyControls.Throttle) > 0.1) { clutchctrl = false; triggered = false; } }
public void TickTelemetry(IDataMiner data) { Enabled = true; Active = true; var f = 1.0; if (Main.Drivetrain.GearRatios != null && data.Telemetry.Gear >= 1) { f = Main.Drivetrain.GearRatios[data.Telemetry.Gear - 1] / 5.5; } var throttle = Math.Max(Main.GetAxisIn(JoyControls.Throttle), data.Telemetry.Throttle); TorqueLimit = 1; var NotGood = false; do { var wheelTorque = Main.Drivetrain.CalculateTorqueP(data.Telemetry.EngineRpm, TorqueLimit * throttle) * f; if (wheelTorque > 20000) { TorqueLimit *= 0.999f; NotGood = true; } else { NotGood = false; } if (TorqueLimit <= 0.2f) { TorqueLimit = 0.2f; break; } } while (NotGood); TorqueLimit = 1.0f; }
public void TickTelemetry(IDataMiner data) { var rpm = data.Telemetry.EngineRpm; err = calRpm - rpm; if (err > 500) { err = 500; } if (err < -500) { err = -500; } switch (state) { case TransmissionCalibratorStatus.Idle: Main.Transmission.OverruleShifts = false; // If we're stationary for a few seconds, we can apply brakes and calibrate the clutch bool wasStationary = isStationary; isStationary = Math.Abs(data.Telemetry.Speed) < 1 && Main.GetAxisIn(JoyControls.Throttle) < 0.05 && data.Telemetry.EngineRpm > 200; if (isStationary && !wasStationary) { stationary = DateTime.Now; } if (isStationary && DateTime.Now.Subtract(stationary).TotalMilliseconds > 2500) { clutch = 1.0f; // CALIBRATE state = TransmissionCalibratorStatus.IterateCalibrationCycle; } break; case TransmissionCalibratorStatus.FindThrottlePoint: throttle += err / 500000.0f; if (throttle >= 0.8) { // Cannot rev the engine } var wasRpmInRange = rpmInRange; rpmInRange = Math.Abs(err) < 5; if (!wasRpmInRange && rpmInRange) { rpmInRangeTimer = DateTime.Now; } // stable at RPM if (rpmInRange && DateTime.Now.Subtract(rpmInRangeTimer).TotalMilliseconds > 250) { // set error to 0 calRpm = rpm; state = TransmissionCalibratorStatus.FindClutchBitePoint; } break; case TransmissionCalibratorStatus.FindClutchBitePoint: if (Main.Transmission.IsShifting) { break; } if (data.Telemetry.Gear != gearTest) { Main.Transmission.Shift(data.Telemetry.Gear, gearTest, "normal"); break; } // Decrease clutch 0.25% at a time to find the bite point clutch -= 0.25f / 100.0f; if (err > 50) { // We found the clutch bite point var fs = File.AppendText("./gear-clutch"); fs.WriteLine(gearTest + "," + calRpm + "," + clutch); fs.Close(); state = TransmissionCalibratorStatus.IterateCalibrationCycle; } break; case TransmissionCalibratorStatus.IterateCalibrationCycle: clutch = 1; gearTest++; calRpm = 700.0f; // Find throttle point state = TransmissionCalibratorStatus.FindThrottlePoint; throttle = 0.001f; rpmInRange = false; break; } //abort when we give power if (Main.GetAxisIn(JoyControls.Throttle) > 0.1) { stationary = DateTime.Now; state = TransmissionCalibratorStatus.Idle; } Active = state != TransmissionCalibratorStatus.Idle; }
public void TickControls() { CameraAngle = Main.GetAxisIn(JoyControls.CameraHorizon) * 0.1 + CameraAngle * 0.9; }
public void TickTelemetry(IDataMiner data) { int idealGear = data.Telemetry.Gear; if (data.TransmissionSupportsRanges) { RangeSize = 6; } else { RangeSize = 8; } // TODO: Add generic telemetry object GameGear = data.Telemetry.Gear; if (IsShifting) { return; } if (TransmissionFrozen && !GetHomeMode) { return; } if (OverruleShifts) { return; } shiftRetry = 0; if (GetHomeMode) { if (idealGear < 1) { idealGear = 1; } var lowRpm = Main.Drivetrain.StallRpm * 1.5; var highRpm = Main.Drivetrain.StallRpm * 3; if (data.Telemetry.EngineRpm < lowRpm && idealGear > 1) { idealGear--; } if (data.Telemetry.EngineRpm > highRpm && idealGear < Main.Drivetrain.Gears) { idealGear++; } } else { if (EnableSportShiftdown) { transmissionThrottle = Math.Max(Main.GetAxisIn(JoyControls.Brake) * 8, transmissionThrottle); } transmissionThrottle = Math.Min(1, Math.Max(0, transmissionThrottle)); var lookupResult = configuration.Lookup(data.Telemetry.Speed * 3.6, transmissionThrottle); idealGear = lookupResult.Gear; ThrottleScale = GetHomeMode ? 1 : lookupResult.ThrottleScale; if (Main.Data.Active.Application == "eurotrucks2") { var ets2Miner = (Ets2DataMiner)(data); var maxGears = (int)Math.Round(Main.Drivetrain.Gears * (1 - ets2Miner.MyTelemetry.Damage.WearTransmission)); if (idealGear >= maxGears) { idealGear = maxGears; } } if (data.Telemetry.Gear == 0 && ShiftCtrlNewGear != 0) { Debug.WriteLine("Timeout"); ShiftCtrlNewGear = 0; TransmissionFreezeUntill = DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, 250)); return; } } if (InReverse) { if (GameGear != -1 && Math.Abs(data.Telemetry.Speed) < 1) { Debug.WriteLine("Shift from " + data.Telemetry.Gear + " to " + idealGear); Shift(data.Telemetry.Gear, -1, "up_1thr"); } return; } // Kickdown? // What is basically does, is making this very-anxious gearbox tone down a bit in it's aggressive shift pattern. // With kickdown we specify 2 rules to make the gear "stick" longer with varying throttle positions. if (KickdownEnable) { if (KickdownCooldown) { // We're on cooldown. Check if power/speed/rpm is able to reset this // The scheme is as follow: // if (delta of [current speed] and [speed of last shift] ) > speedReset: then reset cooldown // if ([generated power this gear] / [generated power new gear]) > 1+powerReset: then reset cooldown // if (currentRpm < [rpm * stationaryValue]) : then reset cooldown // This makes sure the gearbox shifts down if on very low revs and almost about to stall. // Note: only for speeding up if ((data.Telemetry.Speed - KickdownLockedSpeed) > KickdownSpeedReset) { Debug.WriteLine("[Kickdown] Reset on overspeed"); KickdownCooldown = false; } var maxPwr = Main.Drivetrain.CalculateMaxPower(); var engineRpmCurrentGear = Main.Drivetrain.CalculateRpmForSpeed(ShifterOldGear - 1, data.Telemetry.Speed); var pwrCurrentGear = Main.Drivetrain.CalculatePower(engineRpmCurrentGear, data.Telemetry.Throttle); var engineRpmNewGear = Main.Drivetrain.CalculateRpmForSpeed(idealGear - 1, data.Telemetry.Speed); var pwrNewGear = Main.Drivetrain.CalculatePower(engineRpmNewGear, data.Telemetry.Throttle); //Debug.WriteLine("N"+pwrCurrentGear.ToString("000") + " I:" + pwrNewGear.ToString("000")); // This makes sure the gearbox shifts down if on low revs and the user is requesting power from the engine if (pwrNewGear / pwrCurrentGear > 1 + KickdownPowerReset && pwrNewGear / maxPwr > KickdownPowerReset) { Debug.WriteLine("[Kickdown] Reset on power / " + pwrCurrentGear + " / " + pwrNewGear); KickdownCooldown = false; } // This makes sure the gearbox shifts up in decent time when reaching end of gears if (Main.Drivetrain.StallRpm * KickdownRpmReset > data.Telemetry.EngineRpm) { Debug.WriteLine("[Kickdown] Reset on stalling RPM"); KickdownCooldown = true; } } else { } } if (idealGear != data.Telemetry.Gear) { if (KickdownEnable && KickdownCooldown && !GetHomeMode) { return; } KickdownLockedSpeed = Main.Data.Telemetry.Speed; var upShift = idealGear > data.Telemetry.Gear; var fullThrottle = data.Telemetry.Throttle > 0.6; var shiftStyle = (upShift ? "up" : "down") + "_" + (fullThrottle ? "1" : "0") + "thr"; Debug.WriteLine("Shift from " + data.Telemetry.Gear + " to " + idealGear); Shift(data.Telemetry.Gear, idealGear, shiftStyle); } }
public void Shift(int fromGear, int toGear, string style) { if (IsShifting) { return; } if (EnableSportShiftdown && Main.GetAxisIn(JoyControls.Throttle) < 0.2) { KickdownTime = DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, (int)KickdownTimeout / 10)); } else { KickdownTime = DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, (int)KickdownTimeout)); } if (PowerShift) { style = "PowerShift"; } if (ShiftPatterns.ContainsKey(style)) { ActiveShiftPatternStr = style; } else { ActiveShiftPatternStr = ShiftPatterns.Keys.FirstOrDefault(); } // Copy old control to new control values ShiftCtrlOldGear = fromGear; if (ShiftCtrlOldGear == -1) { ShiftCtrlOldRange = 0; } else if (ShiftCtrlOldGear == 0) { ShiftCtrlOldRange = 0; } else if (ShiftCtrlOldGear >= 1 && ShiftCtrlOldGear <= RangeSize) { ShiftCtrlOldRange = 0; } else if (ShiftCtrlOldGear >= RangeSize + 1 && ShiftCtrlOldGear <= 2 * RangeSize) { ShiftCtrlOldRange = 1; } else if (ShiftCtrlOldGear >= 2 * RangeSize + 1 && ShiftCtrlOldGear <= 3 * RangeSize) { ShiftCtrlOldRange = 2; } ShiftCtrlOldGear -= ShiftCtrlOldRange * RangeSize; // Determine new range if (toGear == -1) { ShiftCtrlNewGear = -1; ShiftCtrlNewRange = 0; } else if (toGear == 0) { ShiftCtrlNewGear = 0; ShiftCtrlNewRange = 0; } else if (toGear >= 1 && toGear <= RangeSize) { ShiftCtrlNewGear = toGear; ShiftCtrlNewRange = 0; } else if (toGear >= RangeSize + 1 && toGear <= RangeSize * 2) { ShiftCtrlNewGear = toGear - RangeSize; ShiftCtrlNewRange = 1; } else if (toGear >= RangeSize * 2 + 1 && toGear <= RangeSize * 3) { ShiftCtrlNewGear = toGear - RangeSize * 2; ShiftCtrlNewRange = 2; } ShiftFrame = 0; IsShifting = true; powerShiftStage = 0; }
public void TickTelemetry(IDataMiner data) { bool copyTargetThr = false; /** VARIABLE SPEED CONTROL **/ var actualSpeed = data.Telemetry.Speed * 3.6; double thrP, thrI; if (data.Telemetry.Gear == -1) { SetSpeed = Main.GetAxisIn(JoyControls.VstLever) * 50; actualSpeed *= -1; thrP = 0.1; thrI = 0; } else { SetSpeed = Main.GetAxisIn(JoyControls.VstLever) * ((fast) ? 200 : 100); thrP = 0.015 + 0.15 * actualSpeed / 120; thrI = 0.02 - 0.015 * actualSpeed / 120; if (Efficiency) { thrP *= 0.5; thrI = 0.00025; } if (Efficiency != wasEfficiency) { copyTargetThr = true; staticThrError = variableThrottle - 2 * thrP * lastSpeedError; } wasEfficiency = Efficiency; } var speedErrorThr = SetSpeed - actualSpeed; staticThrError += speedErrorThr * thrI; if (staticThrError > 0.8) { staticThrError = 0.8; } if (staticThrError < -0.8) { staticThrError = -0.8; } lastSpeedError = speedErrorThr; var oldThr = variableThrottle; if (copyTargetThr) { variableThrottle = thrP * speedErrorThr; variableThrottle *= UserThrottle; // Theoratical value required to copy last throttle staticThrError = (1 - variableThrottle) / UserThrottle; //Deduce at low speeds var deductor = actualSpeed / 50; if (deductor > 1) { deductor = 1; } if (deductor < 0.01) { deductor = 0.01; } staticThrError *= deductor; // Add it. variableThrottle += staticThrError; } else { variableThrottle = thrP * speedErrorThr + staticThrError; variableThrottle *= UserThrottle; } if (variableThrottle > 1) { variableThrottle = 1; } if (variableThrottle < 0) { variableThrottle = 0; } var speedErrorBr = (actualSpeed - 3) - SetSpeed; if (speedErrorBr < 0) { speedErrorBr = 0; } if (actualSpeed < 50) { speedErrorBr *= (50 - actualSpeed) / 15 + 1; } variableBrake = 0.01 * speedErrorBr * speedErrorBr; if (variableBrake > 0.2) { variableBrake = 0.2; } if (variableBrake < 0) { variableBrake = 0; } if (variableBrake > 0.01) { variableThrottle = 0; } /** TRANSMISSION **/ if (Main.Data.Active.Application == "eurotrucks2") { var ets2 = (Ets2DataMiner)Main.Data.Active; if (ets2.MyTelemetry.Job.TrailerAttached == false && !fast) { Efficiency = true; } else { if (Efficiency) { if ((SetSpeed - actualSpeed) > 5) { Efficiency = false; } } else { if ((SetSpeed - actualSpeed) < 2) { Efficiency = true; } } } } //Efficiency = (SetSpeed - actualSpeed) < 5; if (DateTime.Now.Subtract(lastShifterTick).TotalMilliseconds > 40) { Active = ShiftingPhase == ShiftPhase.None ? false : true; lastShifterTick = DateTime.Now; switch (ShiftingPhase) { case ShiftPhase.WaitButton: if (Main.GetButtonIn(JoyControls.GearUp) == false && Main.GetButtonIn(JoyControls.GearDown) == false) { ShiftingPhase = ShiftPhase.None; } break; case ShiftPhase.None: // Reverse pressed? if (Main.GetButtonIn(JoyControls.VstChange)) { fast = !fast; ShiftingPhase = ShiftPhase.WaitButton; } if (Main.GetButtonIn(JoyControls.GearDown)) { Reverse = !Reverse; ShiftingPhase = ShiftPhase.WaitButton; } if (Reverse) { if (data.Telemetry.Gear != -1) { Gear = -1; ShiftingPhase = ShiftPhase.OffThrottle; } } else { // Do nothing if (data.Telemetry.Gear != Gear || Gear == 0) { if (Gear == 0) { Gear++; } if (Gear == -1) { Gear = 1; } ShiftingPhase = ShiftPhase.OffThrottle; } else { var curPower = Main.Drivetrain.CalculatePower(data.Telemetry.EngineRpm, data.Telemetry.Throttle); if (curPower < 1) { curPower = 1; } var curEfficiency = Main.Drivetrain.CalculateFuelConsumption(data.Telemetry.EngineRpm, data.Telemetry.Throttle) / curPower; var reqPower = curPower * (variableThrottle - 0.5) * 2; if (reqPower < 25) { reqPower = 25; } if (reqPower > 0.5 * Main.Drivetrain.CalculateMaxPower()) { reqPower = 0.5 * Main.Drivetrain.CalculateMaxPower(); } reqpower = reqPower; int maxgears = Main.Drivetrain.Gears; var calcEfficiency = Efficiency ? double.MaxValue : 0; var calcEfficiencyGear = -1; var calcThrottle = variableThrottle; var calcPower = curPower; var allStalled = true; for (int k = 0; k < maxgears; k++) { if (maxgears >= 12 && (k == 5)) { continue; } if (maxgears >= 10 && (k == 1 || k == 3)) { continue; } if (!Efficiency && k < 3) { continue; } // Always pick best efficient gear with power requirement met var rpm = Main.Drivetrain.CalculateRpmForSpeed(k, data.Telemetry.Speed); var orpm = Main.Drivetrain.CalculateRpmForSpeed(k, data.Telemetry.Speed); var estimatedPower = Main.Drivetrain.CalculatePower(rpm, variableThrottle); // RPM increase linear to throttle: rpm += estimatedPower / 1200 * 190 * variableThrottle; if (rpm < Main.Drivetrain.StallRpm && k > 0) { continue; } allStalled = false; if (orpm > Main.Drivetrain.MaximumRpm) { continue; } var thr = Main.Drivetrain.CalculateThrottleByPower(rpm, reqPower); if (thr > 1) { thr = 1; } if (thr < 0) { thr = 0; } var eff = Main.Drivetrain.CalculateFuelConsumption(rpm, thr) / reqPower; var pwr = Main.Drivetrain.CalculatePower(rpm, variableThrottle); if (Efficiency) { if (calcEfficiency > eff && eff * 1.1 < curEfficiency) { calcEfficiency = eff; calcEfficiencyGear = k; calcThrottle = thr; calcPower = pwr; } } else { if (pwr > calcEfficiency) { calcEfficiency = pwr; calcEfficiencyGear = k; calcPower = pwr; } } } if (allStalled) { if (maxgears >= 10) { Gear = 3; } else { Gear = 1; } } else if (calcEfficiencyGear >= 0 && calcEfficiencyGear + 1 != Gear) { // Hysterisis if (Math.Abs(curPower - calcPower) > 25) { Gear = calcEfficiencyGear + 1; } } if (Efficiency) { //variableThrottle = Main.Drivetrain.CalculateThrottleByPower( // data.Telemetry.EngineRpm, // reqPower); } else { // } if (Gear > 0 && Gear != data.Telemetry.Gear) { ShiftingPhase = ShiftPhase.OffThrottle; } } } break; case ShiftPhase.OffThrottle: ShiftingPhase++; break; case ShiftPhase.OnClutch: ShiftingPhase++; break; case ShiftPhase.EngageRange: ShiftingPhase++; break; case ShiftPhase.EngageGear: ShiftingPhase++; break; case ShiftPhase.Evaluate: if (Gear == data.Telemetry.Gear) { LastSeenRange = DeductRangeFromGear(Gear); ShiftingPhase++; } else { shiftingRetry++; if (shiftingRetry > 50) { if (Gear > 0) { Gear--; } else { Gear = -1; } shiftingRetry = 0; ShiftingPhase = ShiftPhase.EngageGear; } else if (shiftingRetry > 2) { LastSeenRange++; LastSeenRange = LastSeenRange % 4; ShiftingPhase = ShiftPhase.OnClutch; } else { ShiftingPhase = ShiftPhase.EngageGear; } } break; case ShiftPhase.OffClutch: ShiftingPhase++; break; case ShiftPhase.OnThrottle: shiftingRetry = 0; ShiftingPhase = ShiftPhase.Cooldown; break; case ShiftPhase.Cooldown: shiftingRetry++; if (shiftingRetry > 4) { shiftingRetry = 0; ShiftingPhase = ShiftPhase.None; } break; } } }