using CartActivator; using CommonUsage.Mathematics; using FundamentalLib; using MDCSToolBox.Commons; using MDCSToolBox.Commons.Controllers; using System; using System.Collections.Generic; using System.Linq; using static MDCSToolBox.Medulla.Chassis.BasicCartDefinition; namespace MedullaAdapter { public class MotorRoutine:LadderLogic { private DateTime _lastMoveTime = DateTime.Now; private DateTime _transmitterFleetDbgLastLog = DateTime.MinValue; private DateTime _transmitterFleetResetLastLog = DateTime.MinValue; private void LogTransmitterFleet(string branch, bool force = false) { var now = DateTime.Now; if (!force && (now - _transmitterFleetDbgLastLog).TotalMilliseconds < 200) return; _transmitterFleetDbgLastLog = now; DLog.Log( $"branch={branch} connected={cart.TransmitterConnected} ctrl={cart.TransmitterControlEnable} " + $"SA={cart.Transmitter_SA} SC={cart.Transmitter_SC} SB={cart.Transmitter_SB} SD={cart.Transmitter_SD} car={cart.CarNum} " + $"joyLx={cart.TransmitterLeftJoystickValX:0.000} joyRy={cart.TransmitterRightJoystickValY:0.000} joyRx={cart.TransmitterRightJoystickValX:0.000} " + $"rawLx={cart.TransmitterLeftJoystickValXRaw} rawRy={cart.TransmitterRightJoystickValYRaw} " + $"remotePanel={cart.MultiVehicleRemoteManualEnabled} outEn={cart.MultiVehicleManualEnabled} outMode={cart.MultiVehicleManualMode} " + $"outVx={cart.MultiVehicleManualVx:0.000} outVy={cart.MultiVehicleManualVy:0.000} outVth={cart.MultiVehicleManualVth:0.000} hold={cart.MultiVehicleHold}", "TransmitterFleetDbg"); } private void LogTransmitterFleetReset(string reason) { var now = DateTime.Now; if ((now - _transmitterFleetResetLastLog).TotalMilliseconds < 500) return; _transmitterFleetResetLastLog = now; DLog.Log( $"reset reason={reason} remotePanel={cart.MultiVehicleRemoteManualEnabled} beforeEn={cart.MultiVehicleManualEnabled} " + $"beforeMode={cart.MultiVehicleManualMode} beforeVx={cart.MultiVehicleManualVx:0.000} beforeVy={cart.MultiVehicleManualVy:0.000} " + $"beforeVth={cart.MultiVehicleManualVth:0.000} hold={cart.MultiVehicleHold}", "TransmitterFleetDbg"); } public override void Operation(int iteration) { void ResetMultiVehicle(string reason) { if (cart.MultiVehicleRemoteManualEnabled) { LogTransmitterFleet("reset-skipped-remote-panel"); return; } if (cart.MultiVehicleManualEnabled || cart.MultiVehicleManualVx != 0 || cart.MultiVehicleManualVy != 0 || cart.MultiVehicleManualVth != 0 || cart.MultiVehicleHold) LogTransmitterFleetReset(reason); cart.MultiVehicleManualEnabled = false; cart.MultiVehicleManualVx = 0; cart.MultiVehicleManualVy = 0; cart.MultiVehicleManualVth = 0; cart.MultiVehicleHold = false; } TriggerOnce(cart.TransmitterConnected && cart.Transmitter_SA, 700, () => { Console.WriteLine("遥控器使能!"); cart.TransmitterControlEnable = true; cart.TransmitterLastTime = DateTime.Now; LogTransmitterFleet("enable", true); }); TriggerOnce(cart.TransmitterConnected && !cart.Transmitter_SA, 700, () => { Console.WriteLine("遥控器断使能!"); cart.TransmitterControlEnable = false; LogTransmitterFleet("disable", true); }); if (cart.TransmitterControlEnable && cart.Transmitter_SC == cart.CarNum) { CartDefinition.testPriority(5, "TransmitterMode"); ResetMultiVehicle("single-car-control"); LogTransmitterFleet("single-car-control"); TransmitterChassisControl(); cart.TransmitterLastTime = DateTime.Now; cart.CarStatu = "Transmitter控制模式使能"; } else if (cart.TransmitterControlEnable && cart.Transmitter_SC == 3) { cart.CarStatu = "Transmitter双车联动模式使能"; cart.MultiVehicleManualEnabled = true; var fleetMode = 0; if (cart.Transmitter_SB == TransmitterState.Mode0) fleetMode = 0; else if (cart.Transmitter_SB == TransmitterState.Mode1) fleetMode = 1; else if (cart.Transmitter_SB == TransmitterState.Mode2) fleetMode = 2; cart.ApplyFleetManualCommand(fleetMode, -cart.TransmitterLeftJoystickValX, cart.TransmitterRightJoystickValY, 1f); // hold multi-vehicle sync, make speed 0 cart.MultiVehicleHold = cart.Transmitter_SD == TransmitterState.Mode1; LogTransmitterFleet("fleet-control"); } else { ResetMultiVehicle("idle-or-sc-mismatch"); LogTransmitterFleet("idle-or-sc-mismatch"); cart.CarStatu = "正常运行"; } cart.ClumsyControl = true; cart.LeftFrontPid.ChangeParameters(cart.DiffSteerKp, cart.DiffSteerKi, cart.DiffSteerKd, cart.DiffSteerMaxI, cart.DiffSteerDeadZone, cart.DiffSteerThresh, cart.DiffSteerSpeedAcc); cart.LeftRearPid.ChangeParameters(cart.DiffSteerKp, cart.DiffSteerKi, cart.DiffSteerKd, cart.DiffSteerMaxI, cart.DiffSteerDeadZone, cart.DiffSteerThresh, cart.DiffSteerSpeedAcc); cart.RightFrontPid.ChangeParameters(cart.DiffSteerKp, cart.DiffSteerKi, cart.DiffSteerKd, cart.DiffSteerMaxI, cart.DiffSteerDeadZone, cart.DiffSteerThresh, cart.DiffSteerSpeedAcc); cart.RightRearPid.ChangeParameters(cart.DiffSteerKp, cart.DiffSteerKi, cart.DiffSteerKd, cart.DiffSteerMaxI, cart.DiffSteerDeadZone, cart.DiffSteerThresh, cart.DiffSteerSpeedAcc); var diffLf = cart.LeftFrontPid.GetResponse(cart.ThLeftFront, false, false, "LF"); var diffRf = cart.RightFrontPid.GetResponse(cart.ThRightFront, false, false, "RF"); var diffLr = cart.LeftRearPid.GetResponse(cart.ThLeftRear, false, false, "LR"); var diffRr = cart.RightRearPid.GetResponse(cart.ThRightRear, false, false, "RR"); // Hedingben.ToastText($"LF:{diffLf:0.00},LR:{diffLr:0.00},RF:{diffRf:0.00},RR:{diffRr:0.00}", "wheel-pid"); DLog.Log($"[wheel pid] {cart.ActualThLeftFront:0.00}->{cart.ThLeftFront:0.00} diff:{CommonMath.ThDiff(cart.ThLeftFront, cart.ActualThLeftFront):0.00} pid:{diffLf:0.00}"); cart.SpeedLFL = cart.SpeedLeftFrontLeft - diffLf; cart.SpeedLFR = cart.SpeedLeftFrontRight + diffLf; cart.SpeedRFL = cart.SpeedRightFrontLeft - diffRf; cart.SpeedRFR = cart.SpeedRightFrontRight + diffRf; cart.SpeedLRL = cart.SpeedLeftRearLeft - diffLr; cart.SpeedLRR = cart.SpeedLeftRearRight + diffLr; cart.SpeedRRL = cart.SpeedRightRearLeft - diffRr; cart.SpeedRRR = cart.SpeedRightRearRight + diffRr; List wheelSpeed = new float[] { Math.Abs(cart.SpeedLFL), Math.Abs(cart.SpeedLFR), Math.Abs(cart.SpeedRFL), Math.Abs(cart.SpeedRFR), Math.Abs(cart.SpeedLRL),Math.Abs(cart.SpeedLRR), Math.Abs(cart.SpeedRRL), Math.Abs(cart.SpeedRRR) }.ToList(); var wheelMaxSpeed = wheelSpeed.Max(); var speedSign = Math.Sign(cart.ThresSpeed - cart.SendThresSpeed); var acc = Math.Abs(cart.ThresSpeed) > Math.Abs(cart.SendThresSpeed) ? cart.Chassis.AccPerSecond : cart.Chassis.DeAccPerSecond; cart.SendThresSpeed += speedSign * Math.Min(Math.Abs(cart.ThresSpeed - cart.SendThresSpeed), acc * (float)(DateTime.Now - _lastMoveTime).TotalSeconds); if (cart.ThresSpeed < wheelMaxSpeed && cart.SendThresSpeed > wheelMaxSpeed) cart.SendThresSpeed = Math.Min(cart.SendThresSpeed, wheelMaxSpeed); _lastMoveTime = DateTime.Now; //灯光控制 if (cart.AlarmLevel == 2) { //故障红灯常亮 cart.LightMode = 2; } else if (cart.ThresSpeed != 1) { //避障黄灯常亮 cart.LightMode = 3; } else if (!cart.WheelAbleState) { FlipFlop(ref cart.LightMode, 500, 0, 3); } else if (cart.Soc < cart.LowBatteryAlarmThreshold && cart.ElectricCurrent >= -10) { cart.LightMode = 3; } else if (cart.ElectricCurrent < -10) { FlipFlop(ref cart.LightMode, 500, 0, 1); } else { FlipFlop(ref cart.LightMode, 500, 0, 1); } } public void TransmitterChassisControl() { TriggerOnce(cart.Transmitter_SB == TransmitterState.Mode0, 100, () => cart.TransmitterControlMode = DiverCartDefinition.ManualControlMode.Normal); TriggerOnce(cart.Transmitter_SB == TransmitterState.Mode1, 100, () => cart.TransmitterControlMode = DiverCartDefinition.ManualControlMode.Crab); TriggerOnce(cart.Transmitter_SB == TransmitterState.Mode2, 100, () => cart.TransmitterControlMode = DiverCartDefinition.ManualControlMode.Spin); Hedingben.ToastText($"X方向速度: {cart.TransmitterLeftJoystickValX} Y方向速度: {cart.TransmitterRightJoystickValY}"); if (cart.Transmitter_SD == TransmitterState.Mode1) { if(cart.Transmitter_T3 == 1694) cart.WheelReset(); else if(cart.Transmitter_T3 == 151) cart.WheelDisable(); } if (cart.Transmitter_SD == TransmitterState.Mode1 && cart.TransmitterLeftJoystickValXRaw == 353) { TriggerOnce(cart.TransmitterRightJoystickValYRaw == 353, 100, () => cart.TransmitterSpeed += 0.1f); TriggerOnce(cart.TransmitterRightJoystickValYRaw == 1694, 100, () => cart.TransmitterSpeed -= 0.1f); } cart.TransmitterSpeed = Math.Max(Math.Min(cart.TransmitterSpeed, cart.TransmitterSpeedUpperLimit), cart.TransmitterSpeedLowerLimit); //cart.TransmitterSpeed = Math.Max(cart.TransmitterSpeed, cart.TransmitterSpeedLowerLimit); if (!cart.Transmitter_SA) { cart.ManualControl(cart.TransmitterControlMode, 0, 0, 0, cart.TransmitterSpeed, DateTime.Now - cart.TransmitterLastTime); cart.SpeedLeftArm = 0; cart.SpeedRightArm = 0; } //摇杆控制底盘 else if (cart.Transmitter_SD == TransmitterState.Mode0) { cart.ManualControl(cart.TransmitterControlMode, cart.TransmitterLeftJoystickValX, cart.TransmitterRightJoystickValY, 0, cart.TransmitterSpeed, DateTime.Now - cart.TransmitterLastTime); cart.SpeedLeftArm = 0; cart.SpeedRightArm = 0; } //右摇杆同时控制左右夹臂 else if (cart.Transmitter_SD == TransmitterState.Mode1 && cart.TransmitterLeftJoystickValX == 0) { cart.ManualControl(cart.TransmitterControlMode, 0, 0, 0, cart.TransmitterSpeed, DateTime.Now - cart.TransmitterLastTime); cart.SpeedLeftArm = cart.TransmitterRightJoystickValX * cart.ManualArmSpeedFac; cart.SpeedRightArm = cart.TransmitterRightJoystickValX * cart.ManualArmSpeedFac; } } } }