commit a420e9ae749f24f0cba1408db564d54136340c10 Author: shuai.li <1248399577@qq.com> Date: Tue Jul 21 11:11:01 2026 +0800 update diff --git a/.vs/ParkingRobot/v17/.wsuo b/.vs/ParkingRobot/v17/.wsuo new file mode 100644 index 0000000..0461c04 Binary files /dev/null and b/.vs/ParkingRobot/v17/.wsuo differ diff --git a/.vs/ParkingRobot/v17/DocumentLayout.backup.json b/.vs/ParkingRobot/v17/DocumentLayout.backup.json new file mode 100644 index 0000000..5e43650 --- /dev/null +++ b/.vs/ParkingRobot/v17/DocumentLayout.backup.json @@ -0,0 +1,63 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": -1, + "Children": [ + { + "$type": "Bookmark", + "Name": "ST:132:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:133:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:134:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:135:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:136:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:137:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{3ae79031-e1bc-11d0-8f78-00a0c9110057}" + }, + { + "$type": "Bookmark", + "Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:130:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:131:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{1c64b9c2-e352-428e-a56d-0ace190b99a6}" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/.vs/ParkingRobot/v17/DocumentLayout.json b/.vs/ParkingRobot/v17/DocumentLayout.json new file mode 100644 index 0000000..5e43650 --- /dev/null +++ b/.vs/ParkingRobot/v17/DocumentLayout.json @@ -0,0 +1,63 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": -1, + "Children": [ + { + "$type": "Bookmark", + "Name": "ST:132:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:133:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:134:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:135:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:136:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:137:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{3ae79031-e1bc-11d0-8f78-00a0c9110057}" + }, + { + "$type": "Bookmark", + "Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:130:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:131:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{1c64b9c2-e352-428e-a56d-0ace190b99a6}" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..f8b4888 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..6b61141 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,6 @@ +{ + "ExpandedNodes": [ + "" + ], + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..2a6406f Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/ClumsyPilot/AGV.cs b/ClumsyPilot/AGV.cs new file mode 100644 index 0000000..b0c86c0 --- /dev/null +++ b/ClumsyPilot/AGV.cs @@ -0,0 +1,534 @@ +using ClumsyCore; +using ClumsyCore.Interfaces; +using ClumsyCore.Sensors; +using CommonUsage.Chassis; +using CommonUsage.Mathematics; +using FundamentalLib; +using MDCSToolBox.Clumsy.AgvInterfaces; +using MDCSToolBox.Clumsy.Calibration; +using MDCSToolBox.Clumsy.MotionControllers; +using MDCSToolBox.Clumsy.Tracks; +using MDCSToolBox.Commons.Controllers; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Numerics; +using System.Security.Cryptography; +using System.Threading; +using System.Threading.Tasks; +using static ClumsyCore.DTools.Painter; + +namespace MultiWheelC +{ + public class SetLocationRes + { + public float x, y, th; + public int l_step; + public long tick; + public string error; + } + public class AGV : MultiWheelInterface + { + public override AbstractGeometricController GetController() + { + return new ChassisController().Get(); + } + + public override MultiWheelMagTracker GetMagController() + { + return new MultiWheelMagTracker(); + } + + public override NaiveMagnetController GetNaiveMagnetController() + { + return new NaiveMagnetController(); + } + + public void Sleep(float s) + { + new DriveTask(new Sleep() { Second = s }.Get()).Wait(); + } + + public void ControlChargePort(bool open) + { + DLog.Log($"call ControlChargePort({open})"); + PilotDefinition.Self.OpenChargeByClumsy = open; + } + + public void SwitchLidarArea(int area) + { + DLog.Log($"call SwitchLidarArea({area})"); + PilotDefinition.Self.AreaChoose = area; + } + + public void SwitchIoArea(int area) + { + if (area != -1) + { + PilotDefinition.Self.IOObstacleArea = area; + } + } + public void RotateToTarget(float target) + { + //if (!needrotate) return; + var dl = new DriveTask(new MultiWheelRotateInPlace() + { + AngleTarget = target, + PidparamsRead = () => new PIDParams() + { + Kp = PilotDefinition.Conf.TireFollowingThkp, + Ki = PilotDefinition.Conf.TireFollowingThki, + Kd = PilotDefinition.Conf.TireFollowingThkd, + DeadZone = PilotDefinition.Conf.TireFollowingThDeadZone, + SpeedAccPerSec = PilotDefinition.Conf.TireFollowingThSpeedAccPerSec, + OutputUpperThreshold = PilotDefinition.Conf.TireFollowingThThresh, + MaxI = PilotDefinition.Conf.TireFollowingThMaxI, + } + }.Get()); + dl.Wait(); + } + + //参数1:tireNum 需要钻过的轮胎对数量 + //参数2:frontLidarDetect true:前雷达识别 false:后雷达识别 + public void TireFollowing(int tireNum, bool frontLidarDetect, int srcId, int dstId) + { + while (!TryLock(dstId)) + { + Thread.Sleep(50); + } + DLog.Log($"锁点{dstId}完成", "TireFollowing"); + var lidarName = frontLidarDetect ? "前雷达" : "后雷达"; + DLog.Log($"开始钻车动作,通过{lidarName}识别结果钻{tireNum}对轮胎", "TireFollowing"); + if (tireNum != 1 && tireNum != 2) + { + DLog.Log($"TireNum必须是1或2 (当前输入:{tireNum})", "TireFollowing"); + return; + } + + if (PilotDefinition.Self.GhostMode) + { + while (!TryLock(dstId)) + { + Console.WriteLine("等待锁取货点中..."); + Thread.Sleep(200); + } + Console.WriteLine($"锁点{dstId}完成"); + Thread.Sleep(1000); + Console.WriteLine($"开始钻车动作,通过{lidarName}识别结果钻{tireNum}对轮胎"); + Thread.Sleep(1000); + Leave(srcId); + Console.WriteLine($"开始第一段盲走,此时释放预取货点{srcId}"); + Thread.Sleep(2000); + //Leave(dstId); + //Console.WriteLine($"结束第一段盲走,此时释放取货点{dstId}"); + Thread.Sleep(2000); + Console.WriteLine($"结束钻车动作"); + return; + } + + var detectors = new List() + { + new TireFollowing.DetectorDefinition() + { + DetectFunction = (_, lastDetectX, filters) => TireDetect.Detect(lastDetectX, filters, frontLidarDetect), + StartGuessingX = frontLidarDetect ? PilotDefinition.Conf.TireFollowingStage1GuessX : -PilotDefinition.Conf.TireFollowingStage1GuessX, + StartGuessingY = 0, + SwitchWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindSwitchingDistance, + FinishWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindFinishDistance, + PathTransformation = new Tuple( + frontLidarDetect ? PilotDefinition.Conf.TireFollowingFrontLidarPathTransformationX : PilotDefinition.Conf.TireFollowingBackLidarPathTransformationX, + frontLidarDetect ? PilotDefinition.Conf.TireFollowingFrontLidarPathTransformationY : PilotDefinition.Conf.TireFollowingBackLidarPathTransformationY, + 0), + LeaveSrcFunction = Leave, + SrcId = srcId, + DstId = dstId, + }, + new TireFollowing.DetectorDefinition() + { + DetectFunction = (_, lastDetectX, filters) => TireDetect.Detect(lastDetectX, filters, frontLidarDetect), + StartGuessingX = frontLidarDetect ? PilotDefinition.Conf.TireFollowingStage2GuessX : -PilotDefinition.Conf.TireFollowingStage2GuessX, + StartGuessingY = 0, + SwitchWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindSwitchingDistance, + FinishWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindFinishDistance, + PathTransformation = new Tuple( + frontLidarDetect ? PilotDefinition.Conf.TireFollowingFrontLidarPathTransformationX : PilotDefinition.Conf.TireFollowingBackLidarPathTransformationX, + frontLidarDetect ? PilotDefinition.Conf.TireFollowingFrontLidarPathTransformationY : PilotDefinition.Conf.TireFollowingBackLidarPathTransformationY, + 0) + }, + }; + DLog.Log($"钻胎为{tireNum}", "TireFollowing"); + var following = new TireFollowing() + { + GetController = () => new ChassisController().Get(), + GuessRangeX = PilotDefinition.Conf.TireFilterLength / 2, + GuessRangeY = PilotDefinition.Conf.TireFilterWidth / 2, + detectors = detectors, + SlowDistance = PilotDefinition.Conf.TireFollowingSlowDistance, + MaxSpeed = PilotDefinition.Conf.TireFollowingMaxSpeed, + TireNum = tireNum, + CarDirection = frontLidarDetect ? 0f : 180f, + WalkBlindTh = frontLidarDetect ? PilotDefinition.Conf.TireFollowingFrontLidarWalkBlindTh : PilotDefinition.Conf.TireFollowingBackLidarWalkBlindTh, + }; + var _dt = new DriveTask(following.Get()); + _dt.Wait(); + DLog.Log("钻车动作结束", "TireFollowing"); + } + + //离车一定是后雷达识别一个轮胎 + public void LeaveCar(int srcId, float srcX, float srcY, int dstId, float dstX, float dstY) + { + while (!TryLock(dstId)) + { + Thread.Sleep(50); + } + DLog.Log($"锁点{dstId}完成", "TireFollowing"); + DLog.Log($"开始钻车动作,通过后雷达识别结果钻1对轮胎", "TireFollowing"); + var chassis = (MultiWheelChassis)PilotDefinition.Chassis; + chassis.SetOriginBias(0, 0, 0); + var following = new TireFollowing() + { + GetController = () => new ChassisController().Get(), + GuessRangeX = PilotDefinition.Conf.TireFilterLength / 2, + GuessRangeY = PilotDefinition.Conf.TireFilterWidth / 2, + detectors = new List() + { + new TireFollowing.DetectorDefinition() + { + DetectFunction = (_, lastDetectX, filters) => TireDetect.Detect(lastDetectX, filters, false), + StartGuessingX = -PilotDefinition.Conf.TireFollowingStage2GuessX, + StartGuessingY = 0, + SwitchWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingLeaveCarWalkBlindSwitchingDistance, + FinishWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindFinishDistance, + PathTransformation = new Tuple( + PilotDefinition.Conf.TireFollowingLeaveCarBackLidarPathTransformationX, + PilotDefinition.Conf.TireFollowingBackLidarPathTransformationY, + 0), + LeaveSrcFunction = Leave, + SrcId = srcId, + DstId = dstId, + }, + }, + CarDirection = 180f, + SlowDistance = PilotDefinition.Conf.TireFollowingSlowDistance, + MaxSpeed = 0.25f, + EnableHandover = true, + HandoverDistance = 200f, + HandoverSpeed = 0.3f, + WalkBlindTh = 0, + TireNum = 1 + }; + + IEnumerable LeaveThenFollow() + { + foreach (var running in following.Get()) + { + if (!running) break; + yield return true; + } + DLog.Log($"释放锁点{srcId}完成", "TireFollowing"); + DLog.Log("离车TireFollowing结束,开始DstTracker", "TireFollowing"); + + foreach (var running in new DstTracker() + { + Src = new Vector2(srcX, srcY), + Dst = new Vector2(dstX, dstY), + CarDirectionBias = 180f, + InitialSendSpeed = 0.3f + }.Get()) + { + if (!running) break; + yield return true; + } + + yield return false; + } + + var _dt = new DriveTask(LeaveThenFollow()); + _dt.Wait(); + DLog.Log("离车动作1结束", "TireFollowing"); + } + + public void LineTracking(int srcId, float srcX, float srcY, int dstId, float dstX, float dstY) + { + while (!TryLock(dstId)) + { + Thread.Sleep(50); + } + var chassis = (MultiWheelChassis)PilotDefinition.Chassis; + chassis.SetOriginBias(0, 0, 0); + DLog.Log($"锁点{dstId}完成", "TireFollowing"); + IEnumerable TrackThenFollow() + { + foreach (var running in new LineTracking() + { + Target = PilotDefinition.Conf.LineTrackDistance + (PilotDefinition.Self.LFLActualPos + PilotDefinition.Self.LFRActualPos) / 2, + LeaveSrcFunction = Leave, + SrcId = srcId, + EnableHandover = true, + HandoverDistance = 200, + HandoverSpeed = 0.3f, + }.Get()) + { + if (!running) break; + yield return true; + } + DLog.Log($"释放锁点{srcId}完成", "TireFollowing"); + DLog.Log("离车LineTracking结束,开始DstTracker", "TireFollowing"); + while (!TryLock(426)) + { + Thread.Sleep(20); + } + Leave(dstId); + DLog.Log($"释放锁点{dstId}完成", "TireFollowing"); + foreach (var running in new DstTracker() + { + Src = new Vector2(srcX, srcY), + Dst = new Vector2(dstX, dstY), + InitialSendSpeed = 0.3f + }.Get()) + { + if (!running) break; + yield return true; + } + yield return false; + } + var _dt = new DriveTask(TrackThenFollow()); + _dt.Wait(); + DLog.Log("离车动作2结束", "TireFollowing"); + } + + //驱动器上使能 + public void DriverAble() + { + var dl = new DriveTask(new DriverAble() { }.Get()); + dl.Wait(); + DLog.Log("驱动器上使能完成", "TireFollowing"); + } + + //驱动器下使能 + public void DriverDisable() + { + var dl = new DriveTask(new DriverDisable() { }.Get()); + dl.Wait(); + DLog.Log("驱动器下使能完成", "TireFollowing"); + } + + // 夹抱:close 为 true 时关闭夹抱,否则打开夹抱。 + public void ClamptoTarget(bool close) + { + if (PilotDefinition.Self.GhostMode) + { + Thread.Sleep(2000); + Console.WriteLine("夹抱完成"); + return; + } + new DriveTask(new ClampToTarget() + { + LeftClampTarget = close ? PilotDefinition.Self.LeftArmUpperPos : PilotDefinition.Self.LeftArmLowerPos, + RightClampTarget = close ? PilotDefinition.Self.RightArmUpperPos : PilotDefinition.Self.RightArmLowerPos + }.Get()).Wait(); + } + // Fleet crab walk: convert scheduler src/dst into the same relative crab-walk path used by MovementTest. + public void FleetCrabWalk(float srcX, float srcY, int srcId, float dstX, float dstY, int dstId, + float speed) + { + var dx = dstX - srcX; + var dy = dstY - srcY; + var pathLength = (float)Math.Sqrt(dx * dx + dy * dy); + + if (pathLength <= 1f) + { + DLog.Log("FleetCrabWalk abort: path length is too short.", "FleetCrabDbg"); + return; + } + + var self = PilotDefinition.Self; + if (!self.TryGetFleetCenterFromMembers(out var centerX, out var centerY, out var centerTh) && + !self.TryGetFleetCenterFromSlam(out centerX, out centerY, out centerTh)) + { + DLog.Log("FleetCrabWalk abort: failed to read fleet center.", "FleetCrabDbg"); + Hedingben.ToastText("FleetCrab requires master localization", "FleetCrab"); + return; + } + + var pathAngle = (float)CommonMath.RoundTh((float)(Math.Atan2(dy, dx) / Math.PI * 180.0)); + var crabAngle = (float)CommonMath.ThDiff(pathAngle, centerTh); + var targetBodyWorldHeading = (float)CommonMath.RoundTh(PilotDefinition.Conf.FleetCrabBodyWorldHeadingDeg); + var bodyToPathAngle = (float)CommonMath.ThDiff(pathAngle, targetBodyWorldHeading); + DLog.Log( + $"call FleetCrabWalk(src=({srcX:0},{srcY:0},id:{srcId}), dst=({dstX:0},{dstY:0},id:{dstId}), " + + $"len={pathLength:0.0}, speed={speed:0.000}, pathAngle={pathAngle:0.0}, " + + $"center=({centerX:0},{centerY:0},{centerTh:0.0}), crabAngle={crabAngle:0.0}, " + + $"targetBodyWorld={targetBodyWorldHeading:0.0}, bodyToPath={bodyToPathAngle:0.0})", + "FleetCrabDbg"); + + if (dstId != -1) + { + while (!TryLock(dstId)) + { + Thread.Sleep(50); + } + DLog.Log($"锁点{dstId}完成", "FleetCrabDbg"); + } + + var action = new MultiWheelC.FleetCrabWalk + { + CrabAngleDeg = crabAngle, + BodyToPathAngleDeg = bodyToPathAngle, + CrabLengthMm = pathLength, + CrabSpeed = speed, + FleetCrabAccel = PilotDefinition.Conf.FleetCrabAccel, + FleetCrabStartAccel = PilotDefinition.Conf.FleetCrabStartAccel, + FleetCrabSlowDistance = PilotDefinition.Conf.FleetCrabSlowDistance, + FleetCrabFinishDistance = PilotDefinition.Conf.FleetCrabFinishDistance, + FleetCrabFinishSpeed = PilotDefinition.Conf.FleetCrabFinishSpeed, + FleetCrabSlowingPow = PilotDefinition.Conf.FleetCrabSlowingPow, + GcpThetaThreshold = PilotDefinition.Conf.FleetCrabGcpThetaThreshold + }; + + try + { + new DriveTask(action.Get()).Wait(); + } + finally + { + if (srcId != -1) + { + Leave(srcId); + DLog.Log($"释放放车点{srcId}", "FleetCrabDbg"); + } + } + } + + public void FleetCurveWalk(float srcX, float srcY, int srcId, float dstX, float dstY, int dstId, + float speed, params float[] trackTypeInfo) + { + if (trackTypeInfo == null || trackTypeInfo.Length < 2) + { + DLog.Log("FleetCurveWalk abort: invalid trackTypeInfo, expected Bezier type info.", "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve invalid trackTypeInfo", "FleetCurve"); + return; + } + + var trackType = (int)trackTypeInfo[0]; + if (trackType != 2) + { + DLog.Log($"FleetCurveWalk abort: unsupported trackType={trackType}, only Bezier(type=2) is supported.", + "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve only supports Bezier trackType=2", "FleetCurve"); + return; + } + + var controlPointNum = (int)trackTypeInfo[1]; + var expectedLength = 2 + controlPointNum * 2; + if (controlPointNum < 3 || trackTypeInfo.Length < expectedLength) + { + DLog.Log( + $"FleetCurveWalk abort: invalid Bezier trackTypeInfo. controlPointNum={controlPointNum}, " + + $"length={trackTypeInfo.Length}, expected>={expectedLength}.", + "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve invalid Bezier trackTypeInfo", "FleetCurve"); + return; + } + + BezierTrack track; + try + { + track = ProcessTrackTypeInfo(srcX, srcY, dstX, dstY, trackTypeInfo) as BezierTrack; + } + catch (Exception ex) + { + DLog.Log($"FleetCurveWalk abort: failed to process trackTypeInfo. {ex.Message}", "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve failed to process track", "FleetCurve"); + return; + } + + if (track == null) + { + DLog.Log("FleetCurveWalk abort: ProcessTrackTypeInfo did not return BezierTrack.", "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve requires BezierTrack", "FleetCurve"); + return; + } + + track.Speed = speed; + track.CarDirectionBias = 0f; + + DLog.Log( + $"call FleetCurveWalk(src=({srcX:0},{srcY:0},id:{srcId}), dst=({dstX:0},{dstY:0},id:{dstId}), " + + $"speed={speed:0.000}, trackType={trackType}, controls={controlPointNum}, track={track.GetType().Name}, " + + $"carDirectionBias=0.0)", + "FleetCurveDbg"); + + if (dstId != -1) + { + while (!TryLock(dstId)) + { + Thread.Sleep(50); + } + DLog.Log($"閿佺偣{dstId}瀹屾垚", "FleetCurveDbg"); + } + + var action = new MultiWheelC.FleetCurveWalk + { + Track = track, + CurveSpeed = speed, + CarDirectionBias = 0f, + SlowDistance = PilotDefinition.Conf.FleetCurveSlowDistance, + FinishDistance = PilotDefinition.Conf.FleetCurveFinishDistance, + FinishSpeed = PilotDefinition.Conf.FleetCurveFinishSpeed, + SlowingPow = PilotDefinition.Conf.FleetCurveSlowingPow, + GcpThetaThreshold = PilotDefinition.Conf.FleetCrabGcpThetaThreshold, + StartSyncTimeoutSec = PilotDefinition.Conf.FleetCrabStartSyncTimeoutSec + }; + + try + { + new DriveTask(action.Get()).Wait(); + } + finally + { + if (srcId != -1) + { + Leave(srcId); + DLog.Log($"release srcId={srcId}", "FleetCurveDbg"); + } + } + } + + public void ChangeAvoidanceDistance(float stopDistance, float slowDistance) + { + DLog.Log($"call ChangeAvoidanceDistance({stopDistance},{slowDistance})"); + PilotDefinition.Self.SlowDistance = slowDistance; + PilotDefinition.Self.StopDistance = stopDistance; + } + public void ChangeAvoidanceParam(float length = -1, float width = -1) + { + + PilotDefinition.Self.CarLength = length; + PilotDefinition.Self.CarWidth = width; + + } + public void SetLocation(float x, float y, float th) + { + DLog.Log($"call SetLocation({x},{y},{th})"); + Console.WriteLine($"call SetLocation({x},{y},{th})"); + Queue(() => + { + while (true) + { + var str1 = new HttpClient() + .GetStringAsync( + $"http://127.0.0.1:4321/setLocation?x={x}&y={y}&th={th}") + .Result; + Thread.Sleep(500); + Console.WriteLine($"SetLocation str={str1}"); + var setLocationRes = JsonConvert.DeserializeObject(str1); + Console.WriteLine(setLocationRes.l_step); + if (setLocationRes != null && setLocationRes.l_step == 2) break; + } + }); + } + public float baseSpeed = 0; + } +} diff --git a/ClumsyPilot/ChassisController.cs b/ClumsyPilot/ChassisController.cs new file mode 100644 index 0000000..c041b2a --- /dev/null +++ b/ClumsyPilot/ChassisController.cs @@ -0,0 +1,100 @@ +using System; +using System.Numerics; +using ClumsyCore; +using ClumsyCore.Interfaces; +using ClumsyCore.Pilot; +using FundamentalLib; +using MDCSToolBox.Clumsy.MotionControllers; +using MDCSToolBox.Clumsy.Movements; +using MDCSToolBox.Clumsy.Pilot; + +namespace MultiWheelC; + +public class ChassisController : MovementDefinition +{ + public float BaseSpeed = Configuration.conf.basicSpeed; + + private DateTime _sendMotionDbgLast = DateTime.MinValue; + + public override MultiWheelGeometricController Get() + { + return new MultiWheelGeometricController + { + Chassis = BasicPilotBase.Chassis, + BaseSpeed = BaseSpeed, + SlowDistance = PilotDefinition.Conf.SlowDistance, + SlowingPow = PilotDefinition.Conf.SlowingPow, + FinishDistance = PilotDefinition.Conf.FinishDistance, + FinishSpeed = PilotDefinition.Conf.FinishSpeed, + FirstThAccuracy = PilotDefinition.Conf.FirstThAccuracy, + FirstRotateSpeedFac = PilotDefinition.Conf.FirstRotateSpeedFac, + FirstRotateMaxSpeed = PilotDefinition.Conf.FirstRotateMaxSpeed, + NotContinuousAngle = PilotDefinition.Conf.NotContinuousAngle, + DebugMode = PilotDefinition.Conf.MotionDebugPrint, + DebugCurvature = PilotDefinition.Conf.DebugCurvature, + PowerSteeringLookAhead = PilotDefinition.Conf.PowerSteeringLookAhead, + SpeedLookAhead = PilotDefinition.Conf.SpeedLookAhead, + SpeedLookAheadCurveDiff = PilotDefinition.Conf.SpeedLookAheadCurveDiff, + SpeedLookBackCurveDiff = PilotDefinition.Conf.SpeedLookBackCurveDiff, + SpeedLimitCurveDiffMin = PilotDefinition.Conf.SpeedLimitCurveDiffMin, + SpeedLimitCurveMin = PilotDefinition.Conf.SpeedLimitCurveMin, + MaxRotateSpeed = PilotDefinition.Conf.MaxRotateSpeedCurveLimit, + MaxRotateAcc = PilotDefinition.Conf.MaxRotateAccCurveLimit, + GcpThetaThreshold = PilotDefinition.Conf.GcpThetaThreshold, + DthLinearFac = PilotDefinition.Conf.DthLinearFac, + DthLinearThreshold = PilotDefinition.Conf.DthLinearThreshold, + BiasFac = PilotDefinition.Conf.BiasFac, + BiasThreshold = PilotDefinition.Conf.BiasThreshold, + + MultiVehicleSendMotion = (speed, frontTh, rearTh, idealPos, idealAngle) => + { + var self = PilotDefinition.Self; + self.MultiVehicleAutoEnabled = true; + // A: 鐢ㄥ浐瀹氶攣瀵硅薄锛堜笉鍐嶉攣浼氳鏇挎崲鐨勫瓧娈靛紩鐢級銆 + int fleetCnt; + lock (self.FleetLock) + fleetCnt = self.MultiVehicleFleet.Count; + + // 璇婃柇锛堣妭娴 ~300ms锛夛細纭鍥炶皟琚皟鐢ㄣ佺紪闃熸槸鍚﹀氨缁佹槸鍚﹀洜鏁伴噺涓嶇鎻愬墠 return锛堝鑷翠笉涓嬪彂閫熷害锛夈 + if ((DateTime.Now - _sendMotionDbgLast).TotalMilliseconds >= 300) + { + _sendMotionDbgLast = DateTime.Now; + DLog.Log( + $"SENDMOTION speed={speed:0.000} fTh={frontTh:0.0} rTh={rearTh:0.0} " + + $"ideal=({idealPos.X:0},{idealPos.Y:0},{idealAngle:0.0}) " + + $"editCnt={fleetCnt}/{PilotDefinition.Conf.MultiVehicleFleetNum} " + + $"earlyReturn={fleetCnt != PilotDefinition.Conf.MultiVehicleFleetNum}", + "FleetCrabDbg"); + } + + if (fleetCnt != PilotDefinition.Conf.MultiVehicleFleetNum) + return; + + self.MultiVehicleAutoVx = speed; + self.MultiVehicleAutoFrontTh = frontTh; + self.MultiVehicleAutoRearTh = rearTh; + // D: 閫忎紶璺緞鎺у埗鍣ㄧ畻鍑虹殑鐞嗘兂杞﹂槦涓績浣嶅Э锛堟鍓嶈涓㈠純锛夛紝渚涘悇杞︽寜 layout 鍋氬墠棣堛 + self.MultiVehicleAutoIdealX = idealPos.X; + self.MultiVehicleAutoIdealY = idealPos.Y; + self.MultiVehicleAutoIdealTh = idealAngle; + self.MultiVehicleAutoHasIdeal = true; + // B: 鏍囪鍛戒护鏂伴矞搴︺傝矾寰勭粨鏉/鏃╅/鍗¢】涓嶅啀鍒锋柊姝ゆ椂鍒 鈫 涓昏溅瓒呮椂鍚庢竻闆堕熷害锛岄伩鍏嶆粦琛屻 + self.MultiVehicleAutoCmdTime = DateTime.Now; + }, + + // G: 璇诲彇杞﹂槦涓績鍘熷瓙蹇収锛岄伩鍏嶈法绾跨▼璇诲埌鎾曡鐨 x/y/th 缁勫悎銆 + MultiVehicleGetFleetPos = () => + { + var snap = PilotDefinition.Self.GetFleetCenterSnapshot(); + return new Location + { + x = snap.X, + y = snap.Y, + th = snap.Th, + l_step = 1, + tick = DateTime.Now.Ticks + }; + } + }; + } +} diff --git a/ClumsyPilot/ClumsyPilot.csproj b/ClumsyPilot/ClumsyPilot.csproj new file mode 100644 index 0000000..b1f5d37 --- /dev/null +++ b/ClumsyPilot/ClumsyPilot.csproj @@ -0,0 +1,41 @@ +锘 + + + netstandard2.0 + 10 + true + false + ..\..\build\Clumsy\ + + + + + + + + + + ref\CommonUsage.dll + + + ref\LessokajiWeaverUtilities.dll + + + ref\MDCSToolBox.dll + + + ref\RefClumsyCore.dll + + + ref\RefClumsyDance.dll + + + ref\RefFundamentalLib.dll + + + + + + + + diff --git a/ClumsyPilot/FleetCrabWalk.cs b/ClumsyPilot/FleetCrabWalk.cs new file mode 100644 index 0000000..c75333d --- /dev/null +++ b/ClumsyPilot/FleetCrabWalk.cs @@ -0,0 +1,526 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using ClumsyCore; +using ClumsyCore.Interfaces; +using ClumsyCore.Pilot; +using FundamentalLib; +using CommonUsage.Chassis; +using CommonUsage.Mathematics; +using MDCSToolBox.Clumsy.Movements; +using MDCSToolBox.Clumsy.Pilot; + +namespace MultiWheelC; + +// ===== 杞﹂槦鑱斿姩-鑷姩锜硅鍔ㄤ綔 ===== +// 浠ュ綋鍓嶈溅闃熶腑蹇冧负璧风偣锛屾瀯閫犳寚瀹氭柟鍚戝拰闀垮害鐨勭洿绾胯矾寰勶紱 +// 鎵ц渚х洿鎺ュ啓 MultiVehicleAuto...锛岀敱 TickMultiVehicle 鑷姩鍒嗘敮缁熶竴涓嬪彂銆 +// +// 鎺у埗鎬濊矾鍙傝 MDCSToolbox 鍑犱綍鎺у埗鍣紝浣嗗疄鐜版敹鍦 MultiWheelC 鍐咃細 +// 1) 璇诲彇涓昏溅 Detour 鍙嶆帹杞﹂槦涓績锛岃绠楁部鐩寸嚎鐨勮繘搴︺佹í鍚戝亸宸拰杞﹁韩鐩爣鏈濆悜鍋忓樊锛 +// 2) 鏍规嵁妯悜鍋忓樊缁欏墠鍚 GCP 鍚屽悜淇锛屾牴鎹溅韬洰鏍囨湞鍚戝亸宸粰鍓嶅悗 GCP 鍙嶅悜淇锛 +// 3) 鏍规嵁缁堢偣璺濈鍑忛燂紝骞跺彂甯 ideal fleet center 缁欎粠杞﹀仛鍓嶉銆 +// +// 鍓嶆彁锛氬湪涓昏溅(MultiVehicleMasterEndpoint=="/")杩愯锛屼笖涓昏溅鏈 Detour 瀹氫綅銆 +public class FleetCrabWalk : MovementDefinition +{ + /// 璺緞鏂瑰悜鐩稿鍚姩鏃惰溅闃熸湞鍚戠殑澶硅(deg锛岄嗘椂閽堜负姝)銆 + public float CrabAngleDeg = 45f; + + /// 璺緞鏂瑰悜鐩稿杞﹁韩鐩爣鏈濆悜鐨勫す瑙(deg锛岄嗘椂閽堜负姝)銆侻ovementTest 浼氳涓 CrabAngleDeg锛屼互淇濇寔鍚姩鏃惰溅韬湞鍚戙 + public float BodyToPathAngleDeg = 45f; + + /// 璺緞闀垮害(mm)銆 + public float CrabLengthMm = 2000f; + + /// 琛岄┒閫熷害(m/s)銆 + public float CrabSpeed = 0.2f; + + /// 閫熷害鍛戒护鍔犻熷害闄愬埗(m/s^2)锛屽皬浜庣瓑浜 0 琛ㄧず涓嶉檺鍒躲 + public float FleetCrabAccel = 0.2f; + + /// 棰勫榻愬悗姝e紡涓嬪彂閫熷害鍓 5 绉掑姞閫熷害闄愬埗(m/s^2)锛屽皬浜庣瓑浜 0 琛ㄧず涓嶉檺鍒躲 + public float FleetCrabStartAccel = 0.01f; + + /// 鏈寮濮嬪噺閫熻窛绂(mm)銆 + public float FleetCrabSlowDistance = 2000f; + + /// 瀹屾垚璺濈(mm)锛屼綆浜庤鍓╀綑璺濈缁撴潫鍔ㄤ綔銆 + public float FleetCrabFinishDistance = 20f; + + /// 鏈鏈浣庨熷害(m/s)銆 + public float FleetCrabFinishSpeed = 0.02f; + + /// 鏈鍑忛熸洸绾挎寚鏁般 + public float FleetCrabSlowingPow = 0.8f; + + /// 鍓嶅悗 GCP 鑸佃淇涓婇檺(deg)銆 + public float GcpThetaThreshold = 95f; + + private bool _stopping; + + private void Cleanup() + { + var self = PilotDefinition.Self; + self.MultiVehicleScriptVx = 0; + self.MultiVehicleScriptVy = 0; + self.MultiVehicleScriptVth = 0; + self.MultiVehicleScriptMode = 0; + self.MultiVehicleScriptEnabled = false; + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoFrontTh = 0; + self.MultiVehicleAutoRearTh = 0; + self.MultiVehicleAutoHasIdeal = false; + self.MultiVehicleAutoEnabled = false; + } + + public void Stop() + { + _stopping = true; + Cleanup(); + } + + private static float Clamp(float value, float min, float max) + { + if (value < min) return min; + if (value > max) return max; + return value; + } + + private static float ClampAbs(float value, float limit) + { + var absLimit = Math.Abs(limit); + if (absLimit <= 0) return value; + if (value > absLimit) return absLimit; + if (value < -absLimit) return -absLimit; + return value; + } + + private static float Slew(float current, float target, float maxDelta) + { + if (maxDelta <= 0) return target; + if (target > current + maxDelta) return current + maxDelta; + if (target < current - maxDelta) return current - maxDelta; + return target; + } + + private static float AverageAngle(float frontTh, float rearTh) + { + var diff = (float)CommonMath.ThDiff(frontTh, rearTh); + return (float)CommonMath.RoundTh(rearTh + diff / 2f); + } + + private static void ResolveCrabDriveEquivalent(float speed, float rawFrontTh, float rawRearTh, float steerLimit, + out float driveSpeed, out float frontTh, out float rearTh, out bool reverseEquivalent, out float rawBaseTh) + { + var limit = Math.Min(179f, Math.Max(1f, Math.Abs(steerLimit))); + rawBaseTh = AverageAngle(rawFrontTh, rawRearTh); + driveSpeed = speed; + frontTh = rawFrontTh; + rearTh = rawRearTh; + reverseEquivalent = false; + + if (rawBaseTh > limit) + { + frontTh = (float)CommonMath.RoundTh(frontTh - 180f); + rearTh = (float)CommonMath.RoundTh(rearTh - 180f); + driveSpeed = -driveSpeed; + reverseEquivalent = true; + } + else if (rawBaseTh < -limit) + { + frontTh = (float)CommonMath.RoundTh(frontTh + 180f); + rearTh = (float)CommonMath.RoundTh(rearTh + 180f); + driveSpeed = -driveSpeed; + reverseEquivalent = true; + } + + frontTh = ClampAbs(frontTh, limit); + rearTh = ClampAbs(rearTh, limit); + } + + private static float ProbeSpeed(float speed) + { + return Math.Abs(speed) > 1e-4f ? speed : 1f; + } + + private static bool TryGetMotionYawSign(float frontTh, float rearTh, float driveSpeed, float controlRadius, + out float yawSign) + { + yawSign = 0f; + if (Math.Abs(CommonMath.ThDiff(frontTh, rearTh)) <= 1e-3f) + return false; + + var radius = Math.Max(1f, Math.Abs(controlRadius)); + Vector2 pFront = new(radius, 0), pRear = new(-radius, 0), + normFront = CommonMath.Transform2D(pFront, frontTh + 90f, Vector2.UnitX), + normRear = CommonMath.Transform2D(pRear, rearTh + 90f, Vector2.UnitX); + var (intersect, center) = CommonMath.TwoLinesIntersection(pFront, normFront, pRear, normRear); + if (!intersect) + return false; + + // Match MultiWheelChassis.SendMotion: the tangent side is selected by + // rotCenter.Y > 1, and reverse-equivalent motion flips the yaw direction. + var tangentSign = center.Y > 1f ? 1f : -1f; + var speedSign = driveSpeed >= 0f ? 1f : -1f; + yawSign = speedSign * tangentSign; + return true; + } + + private static float GetYawSplitSign(float baseTh, float speed, float steerLimit, float controlRadius) + { + const float probeDth = 1f; + ResolveCrabDriveEquivalent(ProbeSpeed(speed), baseTh + probeDth, baseTh - probeDth, steerLimit, + out var probeSpeed, out var probeFrontTh, out var probeRearTh, out _, out _); + return TryGetMotionYawSign(probeFrontTh, probeRearTh, probeSpeed, controlRadius, out var yawSign) + ? yawSign + : 1f; + } + + private static float EstimateLateralVelocity(float bodyTh, float frontTh, float rearTh, float driveSpeed, + Vector2 pathLeft) + { + var motionTh = (float)CommonMath.RoundTh(bodyTh + AverageAngle(frontTh, rearTh)); + var rad = motionTh / 180f * Math.PI; + var dir = new Vector2((float)Math.Cos(rad), (float)Math.Sin(rad)); + if (driveSpeed < 0f) + dir = -dir; + return Vector2.Dot(dir, pathLeft); + } + + private static float ScoreBiasSign(float baseTh, float bodyTh, float speed, float steerLimit, Vector2 pathLeft, + float lateral, float biasProbe) + { + ResolveCrabDriveEquivalent(ProbeSpeed(speed), baseTh + biasProbe, baseTh + biasProbe, steerLimit, + out var probeSpeed, out var probeFrontTh, out var probeRearTh, out _, out _); + var lateralVelocity = EstimateLateralVelocity(bodyTh, probeFrontTh, probeRearTh, probeSpeed, pathLeft); + return -Math.Sign(lateral) * lateralVelocity; + } + + private static float GetLateralBiasSign(float baseTh, float bodyTh, float speed, float steerLimit, Vector2 pathLeft, + float lateral) + { + if (Math.Abs(lateral) <= 1e-3f) + return 1f; + + const float probeBias = 1f; + var positiveScore = ScoreBiasSign(baseTh, bodyTh, speed, steerLimit, pathLeft, lateral, probeBias); + var negativeScore = ScoreBiasSign(baseTh, bodyTh, speed, steerLimit, pathLeft, lateral, -probeBias); + return positiveScore >= negativeScore ? 1f : -1f; + } + + private static bool TryGetControlFleetCenter(PilotDefinition self, out float centerX, out float centerY, + out float centerTh, out string source) + { + if (self.TryGetFleetCenterFromMembers(out centerX, out centerY, out centerTh)) + { + source = "fleet"; + return true; + } + + if (self.TryGetFleetCenterFromSlam(out centerX, out centerY, out centerTh)) + { + source = "slam"; + return true; + } + + source = "none"; + return false; + } + + public override IEnumerable Get() + { + var self = PilotDefinition.Self; + var conf = PilotDefinition.Conf; + var chassis = BasicPilotBase.Chassis as MultiWheelChassis; + if (chassis == null) + { + DLog.Log("ABORT: FleetCrabWalk requires MultiWheelChassis.", "FleetCrabDbg"); + yield break; + } + _stopping = false; + + DLog.Log( + $"ENTER master?={conf.MultiVehicleMasterEndpoint == "/"} endpoint={conf.MultiVehicleMasterEndpoint} " + + $"fleetNum={conf.MultiVehicleFleetNum} useDetect={conf.MultiVehicleUseDetect} " + + $"syncUseDetour={conf.MultiVehicleSyncUseDetour} useIdealCenter={conf.MultiVehicleAutoUseIdealCenter} " + + $"autoFields=true pathMode=relative pathAngle={CrabAngleDeg:0.0} " + + $"bodyToPath={BodyToPathAngleDeg:0.0} gcpLimit={GcpThetaThreshold:0.0} " + + $"biasFac={conf.BiasFac:0.00} fleetCrabDthFac={conf.FleetCrabDthLinearFac:0.00}", + "FleetCrabDbg"); + + if (conf.MultiVehicleMasterEndpoint != "/") + { + DLog.Log($"ABORT: 闈炰富杞 (endpoint={conf.MultiVehicleMasterEndpoint})", "FleetCrabDbg"); + Hedingben.ToastText("杞﹂槦锜硅闇鍦ㄤ富杞(涓昏溅绔偣=\"/\")杩愯", "FleetCrab"); + yield break; + } + + // 娉ㄦ剰锛歡etCartLocation() 鍦ㄦ棤鏈夋晥 Detour 瀹氫綅鏃朵細闃诲鈥斺旇嫢鍗″湪杩欓噷涓斿悗闈㈢湅涓嶅埌 CENTER 鏃ュ織锛屽嵆瀹氫綅鏈氨缁 + DLog.Log("涓昏溅鏍¢獙閫氳繃锛屽紑濮嬭鍙栬溅闃熶腑蹇 (getCartLocation 鏃犲畾浣嶄細闃诲)鈥", "FleetCrabDbg"); + if (!TryGetControlFleetCenter(self, out var x0, out var y0, out var theta, out var initialCenterSource)) + { + DLog.Log("ABORT: TryGetFleetCenterFromSlam 杩斿洖 false (鏃犲畾浣)", "FleetCrabDbg"); + Hedingben.ToastText("杞﹂槦锜硅闇瑕佷富杞 Detour 瀹氫綅", "FleetCrab"); + yield break; + } + DLog.Log($"CENTER 杞﹂槦涓績=({x0:0},{y0:0},{theta:0.0})", "FleetCrabDbg"); + + DLog.Log($"CENTER_SOURCE source={initialCenterSource} center=({x0:0},{y0:0},{theta:0.0})", "FleetCrabDbg"); + + var pathStart = new Vector2(x0, y0); + var pathLengthMm = CrabLengthMm; + var phi = CommonMath.RoundTh(theta + CrabAngleDeg); + var dst = CommonMath.Transform2D(pathStart, phi, new Vector2(pathLengthMm, 0)); + var targetBodyTh = CommonMath.RoundTh(phi - BodyToPathAngleDeg); + var phiRad = phi / 180.0 * Math.PI; + var pathDir = new Vector2((float)Math.Cos(phiRad), (float)Math.Sin(phiRad)); + var pathLeft = new Vector2(-pathDir.Y, pathDir.X); + + DLog.Log( + $"START center=({x0:0},{y0:0},{theta:0.0}) pathMode=relative " + + $"src=({pathStart.X:0},{pathStart.Y:0}) pathAngle={CrabAngleDeg:0.0} bodyToPath={BodyToPathAngleDeg:0.0} " + + $"phi={phi:0.0} targetBody={targetBodyTh:0.0} " + + $"len={pathLengthMm:0} dst=({dst.X:0},{dst.Y:0}) speed={CrabSpeed:0.000} startAccel={FleetCrabStartAccel:0.000} accel={FleetCrabAccel:0.000} " + + $"slow={FleetCrabSlowDistance:0} finishDist={FleetCrabFinishDistance:0} " + + $"finishSpeed={FleetCrabFinishSpeed:0.000} slowingPow={FleetCrabSlowingPow:0.00}", + "FleetCrabDbg"); + + var gcpLimit = Math.Max(1f, Math.Abs(GcpThetaThreshold)); + var controlRadius = Math.Max(1f, Math.Abs(conf.TestCarSyncDistance) / 2f); + ResolveCrabDriveEquivalent(0f, (float)CommonMath.ThDiff(phi, theta), + (float)CommonMath.ThDiff(phi, theta), gcpLimit, out _, out var holdFrontTh, out var holdRearTh, + out _, out _); + var warmStart = DateTime.Now; + var warmSeqBaseline = self.BeginFleetMotionWarmup(); + + self.MultiVehicleScriptEnabled = false; + self.MultiVehicleScriptMode = 0; + self.MultiVehicleScriptVx = 0; + self.MultiVehicleScriptVy = 0; + self.MultiVehicleScriptVth = 0; + self.MultiVehicleAutoEnabled = true; + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoFrontTh = holdFrontTh; + self.MultiVehicleAutoRearTh = holdRearTh; + self.MultiVehicleAutoIdealX = pathStart.X; + self.MultiVehicleAutoIdealY = pathStart.Y; + self.MultiVehicleAutoIdealTh = targetBodyTh; + self.MultiVehicleAutoHasIdeal = true; + self.MultiVehicleAutoCmdTime = DateTime.Now; + self.PrimeMasterAutoFromSlam(); + DLog.Log( + $"WARMUP auto fields enabled, waiting for fleet startup sync seqBase={warmSeqBaseline} " + + $"hold=({holdFrontTh:0.00},{holdRearTh:0.00})", + "FleetCrabDbg"); + + var warmEnd = warmStart.AddSeconds(Math.Max(1.0f, conf.FleetCrabStartSyncTimeoutSec)); + var warmIter = 0; + var warmReady = false; + var warmDetail = ""; + while (!_stopping && DateTime.Now < warmEnd) + { + warmIter++; + self.MultiVehicleScriptEnabled = false; + self.MultiVehicleScriptMode = 0; + self.MultiVehicleAutoEnabled = true; + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoFrontTh = holdFrontTh; + self.MultiVehicleAutoRearTh = holdRearTh; + self.MultiVehicleAutoIdealX = pathStart.X; + self.MultiVehicleAutoIdealY = pathStart.Y; + self.MultiVehicleAutoIdealTh = targetBodyTh; + self.MultiVehicleAutoHasIdeal = true; + self.MultiVehicleAutoCmdTime = DateTime.Now; + self.PrimeMasterAutoFromSlam(); + var snap = self.GetFleetCenterSnapshot(); + int cnt; + lock (self.FleetLock) cnt = self.MultiVehicleFleet.Count; + if (warmIter % 5 == 0) + DLog.Log( + $"WARMUP#{warmIter} 蹇収=({snap.X:0},{snap.Y:0},{snap.Th:0.0}) tick={snap.Tick} " + + $"autoEn={self.MultiVehicleAutoEnabled} scriptEn={self.MultiVehicleScriptEnabled} cnt={cnt}/{conf.MultiVehicleFleetNum} " + + $"detail={warmDetail}", + "FleetCrabDbg"); + if (self.IsFleetMotionWarmupReady(warmStart, warmSeqBaseline, + conf.TestCarSyncTh, conf.TestCarSyncDistance, out warmDetail)) + { + warmReady = true; + DLog.Log( + $"WARMUP done iter={warmIter} 蹇収=({snap.X:0},{snap.Y:0},{snap.Th:0.0}) cnt={cnt} detail={warmDetail}", + "FleetCrabDbg"); + break; + } + yield return true; + } + if (!warmReady) + { + DLog.Log($"WARMUP timeout: fleet startup sync failed, abort action. detail={warmDetail}", + "FleetCrabDbg"); + Hedingben.ToastText("杞﹂槦锜硅鍚姩鍚屾瓒呮椂锛屽凡鍙栨秷", "FleetCrab"); + Cleanup(); + yield break; + } + + Hedingben.ToastText($"杞﹂槦锜硅 璺緞{phi:0.0}掳 杞﹁韩澶硅{BodyToPathAngleDeg:0.0}掳 闀垮害{pathLengthMm:0}mm", "FleetCrab"); + + if (warmReady && self.TryGetFleetCenterFromMembers(out var warmX, out var warmY, out var warmTh)) + { + x0 = warmX; + y0 = warmY; + theta = warmTh; + pathStart = new Vector2(x0, y0); + phi = CommonMath.RoundTh(theta + CrabAngleDeg); + dst = CommonMath.Transform2D(pathStart, phi, new Vector2(pathLengthMm, 0)); + targetBodyTh = CommonMath.RoundTh(phi - BodyToPathAngleDeg); + phiRad = phi / 180.0 * Math.PI; + pathDir = new Vector2((float)Math.Cos(phiRad), (float)Math.Sin(phiRad)); + pathLeft = new Vector2(-pathDir.Y, pathDir.X); + self.MultiVehicleAutoIdealX = pathStart.X; + self.MultiVehicleAutoIdealY = pathStart.Y; + self.MultiVehicleAutoIdealTh = targetBodyTh; + self.MultiVehicleAutoCmdTime = DateTime.Now; + DLog.Log( + $"WARMUP_REBASE source=fleet center=({x0:0},{y0:0},{theta:0.0}) phi={phi:0.0} targetBody={targetBodyTh:0.0} dst=({dst.X:0},{dst.Y:0})", + "FleetCrabDbg"); + } + + var iter = 0; + var lastLog = DateTime.MinValue; + var finishDistance = Math.Max(0f, FleetCrabFinishDistance); + var slowDistance = Math.Max(finishDistance + 1f, FleetCrabSlowDistance); + var baseSpeed = Math.Abs(CrabSpeed); + var finishSpeed = Math.Min(baseSpeed, Math.Abs(FleetCrabFinishSpeed)); + var slowingPow = Math.Max(0.01f, FleetCrabSlowingPow); + var accel = Math.Abs(FleetCrabAccel); + var startAccel = Math.Abs(FleetCrabStartAccel); + var cmdSpeed = 0f; + var lastTick = DateTime.Now; + var speedRampStart = DateTime.Now; + var stopReason = "done"; + + while (!_stopping) + { + iter++; + + if (!TryGetControlFleetCenter(self, out var cx, out var cy, out var cth, out var centerSource)) + { + stopReason = "fleet center invalid"; + DLog.Log("ABORT: TryGetControlFleetCenter returned false during auto crab.", "FleetCrabDbg"); + break; + } + var delta = new Vector2(cx - pathStart.X, cy - pathStart.Y); + var along = Vector2.Dot(delta, pathDir); + var lateral = Vector2.Dot(delta, pathLeft); + var remain = pathLengthMm - along; + if (remain <= finishDistance) + break; + + var targetSpeed = baseSpeed; + var slowRatio = 1f; + if (remain < slowDistance) + { + slowRatio = (float)Math.Pow(Clamp(Math.Max(0, remain) / slowDistance, 0f, 1f), slowingPow); + targetSpeed = slowRatio * (baseSpeed - finishSpeed) + finishSpeed; + } + var now = DateTime.Now; + var dt = Math.Max(0.001f, (float)(now - lastTick).TotalSeconds); + lastTick = now; + var rampElapsed = (now - speedRampStart).TotalSeconds; + var activeAccel = rampElapsed < 5.0 ? startAccel : accel; + var speed = activeAccel > 0 ? Slew(cmdSpeed, targetSpeed, activeAccel * dt) : targetSpeed; + cmdSpeed = speed; + + var baseCrabTh = (float)CommonMath.ThDiff(phi, cth); + var headingErr = (float)CommonMath.ThDiff(targetBodyTh, cth); + var headingErrReverse = (float)CommonMath.ThDiff(cth, targetBodyTh); + var targetBodyToPath = (float)CommonMath.ThDiff(phi, targetBodyTh); + var rawBiasMagnitude = (float)(Math.Atan(conf.BiasFac * Math.Abs(lateral) / 1000f / + Math.Max(speed, 0.3f)) / Math.PI * 180.0); + var biasSign = GetLateralBiasSign(baseCrabTh, cth, speed, gcpLimit, pathLeft, lateral); + var rawBiasItem = rawBiasMagnitude * biasSign; + var biasItem = ClampAbs(rawBiasItem, conf.BiasThreshold); + var yawSplitSign = GetYawSplitSign(baseCrabTh + biasItem, speed, gcpLimit, controlRadius); + var rawDthItem = conf.FleetCrabDthLinearFac * headingErr * yawSplitSign; + var dthItem = ClampAbs(rawDthItem, conf.FleetCrabDthLinearThreshold); + var rawFrontTh = baseCrabTh + biasItem + dthItem; + var rawRearTh = baseCrabTh + biasItem - dthItem; + ResolveCrabDriveEquivalent(speed, rawFrontTh, rawRearTh, gcpLimit, out var driveSpeed, + out var frontTh, out var rearTh, out var reverseEquivalent, out var rawBaseTh); + holdFrontTh = frontTh; + holdRearTh = rearTh; + var idealAlong = Clamp(along, 0f, pathLengthMm); + var ideal = pathStart + pathDir * idealAlong; + + self.MultiVehicleScriptEnabled = false; + self.MultiVehicleScriptMode = 0; + self.MultiVehicleScriptVx = 0; + self.MultiVehicleScriptVy = 0; + self.MultiVehicleScriptVth = 0; + self.MultiVehicleAutoEnabled = true; + self.MultiVehicleAutoVx = driveSpeed; + self.MultiVehicleAutoFrontTh = frontTh; + self.MultiVehicleAutoRearTh = rearTh; + self.MultiVehicleAutoIdealX = ideal.X; + self.MultiVehicleAutoIdealY = ideal.Y; + self.MultiVehicleAutoIdealTh = targetBodyTh; + self.MultiVehicleAutoHasIdeal = true; + self.MultiVehicleAutoCmdTime = DateTime.Now; + + if ((DateTime.Now - lastLog).TotalMilliseconds >= 300) + { + lastLog = DateTime.Now; + var snap = self.GetFleetCenterSnapshot(); + int fleetCnt; + lock (self.FleetLock) fleetCnt = self.MultiVehicleFleet.Count; + DLog.Log( + $"ITER#{iter} centerSrc={centerSource} center=({cx:0},{cy:0},{cth:0.0}) snap=({snap.X:0},{snap.Y:0},{snap.Th:0.0}) " + + $"along={along:0} lateral={lateral:0} remain={remain:0} headingErr={headingErr:0.0} " + + $"baseTh={baseCrabTh:0.0} bias={biasItem:0.0} dth={dthItem:0.0} " + + $"slowRatio={slowRatio:0.000} targetV={targetSpeed:0.000} rampT={rampElapsed:0.0} accel={activeAccel:0.000} auto=(vx:{driveSpeed:0.000},fTh:{frontTh:0.0},rTh:{rearTh:0.0}) " + + $"ideal=({ideal.X:0},{ideal.Y:0},{targetBodyTh:0.0}) scriptEn={self.MultiVehicleScriptEnabled} " + + $"cnt={fleetCnt}/{conf.MultiVehicleFleetNum}", + "FleetCrabDbg"); + DLog.Log( + $"CTRL iter={iter} centerSrc:{centerSource} phi:{phi:0.00} targetBody:{targetBodyTh:0.00} startTheta:{theta:0.00} " + + $"cth:{cth:0.00} crabAngle:{CrabAngleDeg:0.00} bodyToPathCfg:{BodyToPathAngleDeg:0.00} " + + $"targetBodyToPath:{targetBodyToPath:0.00} bodyToPathNow:{baseCrabTh:0.00} " + + $"headingErr(target-current):{headingErr:0.00} reverse(current-target):{headingErrReverse:0.00} yawSign:{yawSplitSign:0} " + + $"fleetCrabDthFac:{conf.FleetCrabDthLinearFac:0.000} rawDth:{rawDthItem:0.00} dth:{dthItem:0.00} dthLimit:{conf.FleetCrabDthLinearThreshold:0.00} " + + $"lateral:{lateral:0.0} biasFac:{conf.BiasFac:0.000} biasSign:{biasSign:0} rawBias:{rawBiasItem:0.00} bias:{biasItem:0.00} biasLimit:{conf.BiasThreshold:0.00} " + + $"baseTh:{baseCrabTh:0.00} rawBase:{rawBaseTh:0.00} rawOut(f:{rawFrontTh:0.00},r:{rawRearTh:0.00}) " + + $"out(f:{frontTh:0.00},r:{rearTh:0.00}) gcpLimit:{gcpLimit:0.00} revEq:{reverseEquivalent} " + + $"speedRaw:{speed:0.000} speed:{driveSpeed:0.000} rampT:{rampElapsed:0.0} accel:{activeAccel:0.000} along:{along:0.0} remain:{remain:0.0} ideal=({ideal.X:0.0},{ideal.Y:0.0},{targetBodyTh:0.00})", + "FleetCrabHeadingDbg"); + } + yield return true; + } + + if (_stopping) + stopReason = "stop"; + + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoFrontTh = holdFrontTh; + self.MultiVehicleAutoRearTh = holdRearTh; + self.MultiVehicleAutoCmdTime = DateTime.Now; + DLog.Log( + $"STOP_HOLD iter={iter} reason={stopReason} hold=(fTh:{holdFrontTh:0.0},rTh:{holdRearTh:0.0}) cmdSpeed={cmdSpeed:0.000}", + "FleetCrabDbg"); + var settleEnd = DateTime.Now.AddMilliseconds(Math.Max(100, conf.MultiVehicleSyncInterval * 3)); + while (!_stopping && DateTime.Now < settleEnd) + { + self.MultiVehicleScriptEnabled = false; + self.MultiVehicleScriptMode = 0; + self.MultiVehicleAutoEnabled = true; + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoFrontTh = holdFrontTh; + self.MultiVehicleAutoRearTh = holdRearTh; + self.MultiVehicleAutoCmdTime = DateTime.Now; + yield return true; + } + + Cleanup(); + Hedingben.ToastText("杞﹂槦锜硅瀹屾垚", "FleetCrab"); + DLog.Log($"DONE iter={iter} reason={stopReason}", "FleetCrabDbg"); + } +} diff --git a/ClumsyPilot/FleetCurveWalk.cs b/ClumsyPilot/FleetCurveWalk.cs new file mode 100644 index 0000000..c5b2e2e --- /dev/null +++ b/ClumsyPilot/FleetCurveWalk.cs @@ -0,0 +1,411 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Numerics; +using ClumsyCore; +using ClumsyCore.Interfaces; +using ClumsyCore.Pilot; +using FundamentalLib; +using CommonUsage.Chassis; +using CommonUsage.Mathematics; +using MDCSToolBox.Clumsy.MotionControllers; +using MDCSToolBox.Clumsy.Movements; +using MDCSToolBox.Clumsy.Pilot; +using MDCSToolBox.Clumsy.Tracks; + +namespace MultiWheelC; + +public class FleetCurveWalk : MovementDefinition +{ + public BezierTrack Track; + public List ControlPoints = new(); + public float CurveSpeed = 0.2f; + public float CarDirectionBias = 0f; + public int BezierResolution = 100; + public float SlowDistance = 2000f; + public float FinishDistance = 20f; + public float FinishSpeed = 0.02f; + public float SlowingPow = 0.8f; + public float GcpThetaThreshold = 95f; + public float StartSyncTimeoutSec = 8f; + + private bool _stopping; + private MultiWheelGeometricController _controller; + private MultiWheelChassis _chassis; + private bool _savedControlPoints; + private float _savedControlRadius; + private Vector2 _savedGcp0; + private Vector2 _savedGcp1; + + public void Stop() + { + _stopping = true; + if (_controller != null) + _controller.BreakAndHold = true; + Cleanup(); + } + + public static bool TryParsePointList(string text, out List points, out string error) + { + points = new List(); + error = ""; + if (string.IsNullOrWhiteSpace(text)) + { + error = "empty control point list"; + return false; + } + + var segments = text.Split(new[] { ';', '|' }, StringSplitOptions.RemoveEmptyEntries); + for (var i = 0; i < segments.Length; i++) + { + var pair = segments[i].Split(new[] { ',', ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + if (pair.Length != 2) + { + error = $"invalid point #{i + 1}: {segments[i]}"; + return false; + } + + if (!TryParseFloat(pair[0], out var x) || !TryParseFloat(pair[1], out var y)) + { + error = $"invalid number in point #{i + 1}: {segments[i]}"; + return false; + } + points.Add(new Vector2(x, y)); + } + + if (points.Count < 3) + { + error = "Bezier curve requires at least 3 control points"; + return false; + } + + return true; + } + + public static List BuildRelativeControlPoints(Vector2 start, float startTh, List relativePoints) + { + var source = relativePoints ?? new List(); + var normalized = new List(); + if (source.Count == 0 || Vector2.Distance(source[0], Vector2.Zero) > 1f) + normalized.Add(Vector2.Zero); + for (var i = 0; i < source.Count; i++) + normalized.Add(source[i]); + if (normalized.Count < 2) + normalized.Add(new Vector2(1000f, 0f)); + if (normalized.Count < 3) + normalized.Add(new Vector2(2000f, 0f)); + + var result = new List(); + for (var i = 0; i < normalized.Count; i++) + result.Add(CommonMath.Transform2D(start, startTh, normalized[i])); + return result; + } + + public static List BuildAgvControlPoints(float srcX, float srcY, float dstX, float dstY, + params float[] controlPointCoords) + { + var src = new Vector2(srcX, srcY); + var dst = new Vector2(dstX, dstY); + var result = new List(); + if (controlPointCoords == null || controlPointCoords.Length == 0) + { + result.Add(src); + result.Add((src + dst) / 2f); + result.Add(dst); + return result; + } + + if (controlPointCoords.Length % 2 != 0) + throw new ArgumentException("FleetCurve controlPointCoords must contain x,y pairs."); + + var supplied = new List(); + for (var i = 0; i < controlPointCoords.Length; i += 2) + supplied.Add(new Vector2(controlPointCoords[i], controlPointCoords[i + 1])); + + if (supplied.Count >= 3 && + Vector2.Distance(supplied[0], src) <= 10f && + Vector2.Distance(supplied[supplied.Count - 1], dst) <= 10f) + return supplied; + + result.Add(src); + for (var i = 0; i < supplied.Count; i++) + result.Add(supplied[i]); + result.Add(dst); + if (result.Count < 3) + result.Insert(1, (src + dst) / 2f); + return result; + } + + private static bool TryParseFloat(string text, out float value) + { + return float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value) || + float.TryParse(text, out value); + } + + private static float ClampAbs(float value, float limit) + { + var absLimit = Math.Abs(limit); + if (absLimit <= 0) return value; + if (value > absLimit) return absLimit; + if (value < -absLimit) return -absLimit; + return value; + } + + private static bool TryGetControlFleetCenter(PilotDefinition self, out float centerX, out float centerY, + out float centerTh, out string source) + { + if (self.TryGetFleetCenterFromMembers(out centerX, out centerY, out centerTh)) + { + source = "fleet"; + return true; + } + + if (self.TryGetFleetCenterFromSlam(out centerX, out centerY, out centerTh)) + { + source = "slam"; + return true; + } + + source = "none"; + return false; + } + + private void Cleanup() + { + var self = PilotDefinition.Self; + self.MultiVehicleScriptVx = 0; + self.MultiVehicleScriptVy = 0; + self.MultiVehicleScriptVth = 0; + self.MultiVehicleScriptMode = 0; + self.MultiVehicleScriptEnabled = false; + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoFrontTh = 0; + self.MultiVehicleAutoRearTh = 0; + self.MultiVehicleAutoHasIdeal = false; + self.MultiVehicleAutoEnabled = false; + RestoreControlPointRadius(); + } + + private void ApplyFleetControlPointRadius(MultiWheelChassis chassis, float radius) + { + if (!_savedControlPoints) + { + _chassis = chassis; + _savedControlRadius = chassis.ControlPointRadius; + var gcps = chassis.GetGeometricControlPoints(); + if (gcps.Count >= 2) + { + _savedGcp0 = gcps[0].Position; + _savedGcp1 = gcps[1].Position; + } + _savedControlPoints = true; + } + + chassis.ControlPointRadius = radius; + var points = chassis.GetGeometricControlPoints(); + if (points.Count >= 2) + { + points[0].Position = new Vector2(radius, 0); + points[1].Position = new Vector2(-radius, 0); + } + } + + private void RestoreControlPointRadius() + { + if (!_savedControlPoints || _chassis == null) + return; + + _chassis.ControlPointRadius = _savedControlRadius; + var points = _chassis.GetGeometricControlPoints(); + if (points.Count >= 2) + { + points[0].Position = _savedGcp0; + points[1].Position = _savedGcp1; + } + _savedControlPoints = false; + } + + private static void WriteWarmupAuto(PilotDefinition self, Vector2 idealPos, float idealTh, + float frontTh, float rearTh) + { + self.MultiVehicleScriptEnabled = false; + self.MultiVehicleScriptMode = 0; + self.MultiVehicleScriptVx = 0; + self.MultiVehicleScriptVy = 0; + self.MultiVehicleScriptVth = 0; + self.MultiVehicleAutoEnabled = true; + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoFrontTh = frontTh; + self.MultiVehicleAutoRearTh = rearTh; + self.MultiVehicleAutoIdealX = idealPos.X; + self.MultiVehicleAutoIdealY = idealPos.Y; + self.MultiVehicleAutoIdealTh = idealTh; + self.MultiVehicleAutoHasIdeal = true; + self.MultiVehicleAutoCmdTime = DateTime.Now; + } + + public override IEnumerable Get() + { + var self = PilotDefinition.Self; + var conf = PilotDefinition.Conf; + var chassis = BasicPilotBase.Chassis as MultiWheelChassis; + _stopping = false; + + if (chassis == null) + { + DLog.Log("ABORT: FleetCurveWalk requires MultiWheelChassis.", "FleetCurveDbg"); + yield break; + } + + if (conf.MultiVehicleMasterEndpoint != "/") + { + DLog.Log($"ABORT: FleetCurveWalk must run on master endpoint, endpoint={conf.MultiVehicleMasterEndpoint}", + "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve requires master vehicle", "FleetCurve"); + yield break; + } + + if (Track == null && (ControlPoints == null || ControlPoints.Count < 3)) + { + DLog.Log("ABORT: FleetCurveWalk requires a BezierTrack or at least 3 control points.", "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve requires track or >=3 control points", "FleetCurve"); + yield break; + } + + if (!TryGetControlFleetCenter(self, out var x0, out var y0, out var theta, out var initialCenterSource)) + { + DLog.Log("ABORT: FleetCurveWalk failed to read fleet center.", "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve requires master localization", "FleetCurve"); + yield break; + } + + var baseSpeed = Math.Abs(CurveSpeed); + if (baseSpeed <= 1e-4f) + { + DLog.Log("ABORT: FleetCurveWalk speed is zero.", "FleetCurveDbg"); + yield break; + } + + var resolution = Math.Max(2, BezierResolution); + var speedFinish = Math.Min(baseSpeed, Math.Abs(FinishSpeed)); + var gcpLimit = Math.Max(1f, Math.Abs(GcpThetaThreshold)); + var controlRadius = Math.Max(1f, Math.Abs(conf.TestCarSyncDistance) / 2f); + + ApplyFleetControlPointRadius(chassis, controlRadius); + + try + { + var track = Track; + var trackSource = "external"; + if (track == null) + { + var points = new List(ControlPoints); + track = new BezierTrack(points, resolution); + trackSource = "controlPoints"; + } + track.CarDirectionBias = CarDirectionBias; + track.Speed = baseSpeed; + + var center = new Vector2(x0, y0); + var (idealPos, idealAngle, bias, pd) = track.QueryTangentPoint(center); + var carDirection = (float)CommonMath.ThDiff(theta, CarDirectionBias); + var holdTh = ClampAbs((float)CommonMath.ThDiff(idealAngle, carDirection), gcpLimit); + var targetBodyTh = (float)CommonMath.RoundTh(idealAngle + CarDirectionBias); + + DLog.Log( + $"START center=({x0:0},{y0:0},{theta:0.0}) source={initialCenterSource} " + + $"track={track.GetType().Name} trackSource={trackSource} controls={ControlPoints?.Count ?? 0} " + + $"len={track.Length():0} speed={baseSpeed:0.000} bias={CarDirectionBias:0.0} " + + $"query=({idealPos.X:0},{idealPos.Y:0}) tangent={idealAngle:0.0} targetBody={targetBodyTh:0.0} " + + $"pathBias={bias:0.0} pd={pd:0.0} hold={holdTh:0.0} radius={controlRadius:0}", + "FleetCurveDbg"); + + var warmStart = DateTime.Now; + var warmSeqBaseline = self.BeginFleetMotionWarmup(); + WriteWarmupAuto(self, idealPos, targetBodyTh, holdTh, holdTh); + self.PrimeMasterAutoFromSlam(); + + var warmEnd = warmStart.AddSeconds(Math.Max(1.0f, StartSyncTimeoutSec)); + var warmIter = 0; + var warmReady = false; + var warmDetail = ""; + while (!_stopping && DateTime.Now < warmEnd) + { + warmIter++; + WriteWarmupAuto(self, idealPos, targetBodyTh, holdTh, holdTh); + self.PrimeMasterAutoFromSlam(); + + if (warmIter % 5 == 0) + { + var snap = self.GetFleetCenterSnapshot(); + int cnt; + lock (self.FleetLock) cnt = self.MultiVehicleFleet.Count; + DLog.Log( + $"WARMUP#{warmIter} snap=({snap.X:0},{snap.Y:0},{snap.Th:0.0}) " + + $"cnt={cnt}/{conf.MultiVehicleFleetNum} detail={warmDetail}", + "FleetCurveDbg"); + } + + if (self.IsFleetMotionWarmupReady(warmStart, warmSeqBaseline, + conf.TestCarSyncTh, conf.TestCarSyncDistance, out warmDetail)) + { + warmReady = true; + DLog.Log($"WARMUP done iter={warmIter} detail={warmDetail}", "FleetCurveDbg"); + break; + } + yield return true; + } + + if (!warmReady) + { + DLog.Log($"WARMUP timeout: fleet startup sync failed, abort curve action. detail={warmDetail}", + "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve startup sync timeout", "FleetCurve"); + Cleanup(); + yield break; + } + + _controller = new ChassisController { BaseSpeed = baseSpeed }.Get(); + _controller.MultiVehicleSync = true; + _controller.BaseSpeed = baseSpeed; + _controller.SlowDistance = Math.Max(FinishDistance + 1f, SlowDistance); + _controller.FinishDistance = Math.Max(0f, FinishDistance); + _controller.FinishSpeed = speedFinish; + _controller.SlowingPow = Math.Max(0.01f, SlowingPow); + _controller.GcpThetaThreshold = gcpLimit; + _controller.AddTrack(track, "FleetCurve"); + + Hedingben.ToastText($"FleetCurve len {track.Length():0}mm speed {baseSpeed:0.00}", "FleetCurve"); + + foreach (var running in _controller.Track()) + { + if (_stopping) + break; + if (!running) + break; + yield return true; + } + + if (!_stopping) + { + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoCmdTime = DateTime.Now; + var settleEnd = DateTime.Now.AddMilliseconds(Math.Max(100, conf.MultiVehicleSyncInterval * 3)); + while (!_stopping && DateTime.Now < settleEnd) + { + self.MultiVehicleAutoEnabled = true; + self.MultiVehicleAutoVx = 0; + self.MultiVehicleAutoCmdTime = DateTime.Now; + yield return true; + } + } + + DLog.Log($"DONE stopping={_stopping}", "FleetCurveDbg"); + } + finally + { + Cleanup(); + _controller = null; + } + } +} diff --git a/ClumsyPilot/MovementTests.TireFollowing.cs b/ClumsyPilot/MovementTests.TireFollowing.cs new file mode 100644 index 0000000..ff3598e --- /dev/null +++ b/ClumsyPilot/MovementTests.TireFollowing.cs @@ -0,0 +1,606 @@ +锘縰sing ClumsyCore; +using ClumsyCore.DTools; +using ClumsyCore.Interfaces; +using ClumsyCore.Pilot; +using ClumsyCore.Utilities; +using ClumsyDance.ClumsyDance.Detectors; +using ClumsyDance.ClumsyWalk.Detectors; +using CommonUsage.Chassis; +using CommonUsage.Mathematics; +using FundamentalLib; +using MDCSToolBox.Clumsy.Calibration; +using MDCSToolBox.Clumsy.Tracks; +using MDCSToolBox.Commons.Controllers; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Numerics; +using System.Security.Cryptography; +using System.Threading; +using LineSegment = ClumsyCore.Utilities.LineSegment; + +namespace MultiWheelC +{ + [MovementTest(name = "杞儙妫娴")] + public class TireDetect : MovementTest + { + public override void TestStop() + { + _running = false; + } + + public override void Test() + { + _painter = UI.GetPainter("TwoLegDetectTest", false); + _painter.Clear(); + + var frontlidar = UI.GetInput("1鏄敤鍓嶉浄杈捐瘑鍒紝2鏄敤鍚庨浄杈捐瘑鍒"); + var result = int.Parse(frontlidar.ToString()); + var lastDetectX = result == 1 ? PilotDefinition.Conf.TireFollowingStage1GuessX : -PilotDefinition.Conf.TireFollowingStage1GuessX; + var lastDetectY = 0f; + while (_running) + { + var ld = Detect(lastDetectX, SetFilters(lastDetectX, lastDetectY), result == 1 ? true : false); + if(ld == null) + { + //Console.WriteLine("ld == null"); + continue; + } + _painter.Clear(); + var center = (ld.Src + ld.Dst) / 2; + var distanceToCarOrigin = Vector2.Distance(Vector2.Zero, center); + var distanceLabelPos = center / 2; + _painter.DrawLine(Color.Cyan, Vector2.Zero, center, width: 2); + _painter.DrawText(Color.Yellow, $"{distanceToCarOrigin:F3}", distanceLabelPos.X, distanceLabelPos.Y); + lastDetectX = center.X; + lastDetectY = center.Y; + Thread.Sleep(100); + } + } + + public static LineSegment Detect(float guessX, List filters, bool frontlidar) + { + return new Lidar2dDetect2LegTray() + { + BlobDist = frontlidar ? PilotDefinition.Conf.TireFrontTwoLegBlobDist : PilotDefinition.Conf.TireBackTwoLegBlobDist, + BlobPtCount = frontlidar ? PilotDefinition.Conf.TireTwoLegBlobPtCount : PilotDefinition.Conf.TireTwoLegBlobPtCount, + BlobSize = frontlidar ? PilotDefinition.Conf.TireFrontTwoLegBlobSize : PilotDefinition.Conf.TireBackTwoLegBlobSize, + CenterChange = Tuple.Create(frontlidar ? PilotDefinition.Conf.TireFrontTwoLegCenterChangeX : PilotDefinition.Conf.TireBackTwoLegCenterChangeX, 0f, 0f), + LegWidth = PilotDefinition.Conf.TireTwoLegWidth, + LegWidthErr = frontlidar ? PilotDefinition.Conf.TireTwoLegWidthErr : PilotDefinition.Conf.TireTwoLegWidthErr, + Padding = frontlidar ? PilotDefinition.Conf.TireFrontPadding : PilotDefinition.Conf.TireBackPadding, + PillarFindingScope = frontlidar ? PilotDefinition.Conf.TireFrontTwoLegPillarFindingScope : PilotDefinition.Conf.TireBackTwoLegPillarFindingScope, + SgnDir = PilotDefinition.Conf.TwoLegSgnDir, + }.DetectWithGuess(frontlidar ? "frontlidar" : "leftlidar,rightlidar", new LineSegment(new Vector2(guessX, 0), Vector2.Zero), + guessCoordinateSystem: CoordinateSystem.Car2D, outCoordinateSystem: CoordinateSystem.Car2D, filters); + } + + private List SetFilters(float guessCenterX, float guessCenterY) + { + var painter = UI.GetPainter("GeneralFollowing.SetFilters", false); + painter.Clear(); + painter.Clear(3000); + + var box = new Vector2[] + { + new (guessCenterX - PilotDefinition.Conf.TireFilterLength / 2, guessCenterY - PilotDefinition.Conf.TireFilterWidth / 2), + new (guessCenterX + PilotDefinition.Conf.TireFilterLength / 2, guessCenterY - PilotDefinition.Conf.TireFilterWidth / 2), + new (guessCenterX + PilotDefinition.Conf.TireFilterLength / 2, guessCenterY + PilotDefinition.Conf.TireFilterWidth / 2), + new (guessCenterX - PilotDefinition.Conf.TireFilterLength / 2, guessCenterY + PilotDefinition.Conf.TireFilterWidth / 2), + }; + + for (var i = 0; i < box.Length; ++i) + painter.DrawLine(Color.DarkOliveGreen, box[i], box[(i + 1) % 4]); + + // PC filter in car coordinate frame + return new List() + { + new(CoordinateSystem.Car2D, + p => LessMath.IsPointInPolygon4( + box.Select(v => new PointF(v.X, v.Y)).ToArray(), new PointF(p.X, p.Y))), + }; + } + + private Painter _painter; + private bool _running = true; + } + + [MovementTest(name = "閽昏溅娴嬭瘯")] + public class FollowTire : MovementTest + { + public override void TestStop() + { + _dt?.Stop(); + } + + public override void Test() + { + var front = UI.GetInput("1鏄敤鍓嶉浄杈捐瘑鍒紝2鏄敤鍚庨浄杈捐瘑鍒"); + var result = int.Parse(front.ToString()); + var lidarname = result == 1 ? "鍓嶉浄杈" : "鍚庨浄杈"; + DLog.Log($"寮濮嬮捇杞︽祴璇曪紝鐢▄lidarname}璇嗗埆", "TireFollowing"); + + var following = new TireFollowing() + { + GetController = () => new ChassisController().Get(), + GuessRangeX = PilotDefinition.Conf.TireFilterLength / 2, + GuessRangeY = PilotDefinition.Conf.TireFilterWidth / 2, + detectors = new List() + { + new TireFollowing.DetectorDefinition() + { + DetectFunction = (_, lastDetectX, filters) => TireDetect.Detect(lastDetectX, filters, result == 1 ? true : false), + StartGuessingX = result == 1 ? PilotDefinition.Conf.TireFollowingStage1GuessX : -PilotDefinition.Conf.TireFollowingStage1GuessX, + StartGuessingY = 0, + SwitchWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindSwitchingDistance, + FinishWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindFinishDistance, + PathTransformation = new Tuple( + result == 1 ? PilotDefinition.Conf.TireFollowingFrontLidarPathTransformationX : PilotDefinition.Conf.TireFollowingBackLidarPathTransformationX, + result == 1 ? PilotDefinition.Conf.TireFollowingFrontLidarPathTransformationY : PilotDefinition.Conf.TireFollowingBackLidarPathTransformationY, + 0) + }, + new TireFollowing.DetectorDefinition() + { + DetectFunction = (_, lastDetectX, filters) => TireDetect.Detect(lastDetectX, filters, result == 1 ? true : false), + StartGuessingX = result == 1 ? PilotDefinition.Conf.TireFollowingStage2GuessX : -PilotDefinition.Conf.TireFollowingStage2GuessX, + StartGuessingY = 0, + SwitchWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindSwitchingDistance, + FinishWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindFinishDistance, + PathTransformation = new Tuple( + result == 1 ? PilotDefinition.Conf.TireFollowingFrontLidarPathTransformationX : PilotDefinition.Conf.TireFollowingBackLidarPathTransformationX, + result == 1 ? PilotDefinition.Conf.TireFollowingFrontLidarPathTransformationY : PilotDefinition.Conf.TireFollowingBackLidarPathTransformationY, + 0) + }, + }, + CarDirection = result == 1 ? 0f : 180f, + SlowDistance = PilotDefinition.Conf.TireFollowingSlowDistance, + MaxSpeed = PilotDefinition.Conf.TireFollowingMaxSpeed, + TireNum = PilotDefinition.Conf.TireFollowingTireNum, + WalkBlindTh = result == 1 ? PilotDefinition.Conf.TireFollowingFrontLidarWalkBlindTh : PilotDefinition.Conf.TireFollowingBackLidarWalkBlindTh, + }; + _dt = new DriveTask(following.Get()); + _dt.Wait(); + DLog.Log($"缁撴潫閽昏溅娴嬭瘯", "TireFollowing"); + } + private DriveTask _dt; + } + + [MovementTest(name = "绂昏溅娴嬭瘯")] + public class LeaveCar : MovementTest + { + public override void TestStop() + { + _dt?.Stop(); + } + + public override void Test() + { + DLog.Log($"寮濮嬬杞︽祴璇曪紝鐢ㄥ悗闆疯揪璇嗗埆", "TireFollowing"); + var following = new TireFollowing() + { + GetController = () => new ChassisController().Get(), + GuessRangeX = PilotDefinition.Conf.TireFilterLength / 2, + GuessRangeY = PilotDefinition.Conf.TireFilterWidth / 2, + detectors = new List() + { + new TireFollowing.DetectorDefinition() + { + DetectFunction = (_, lastDetectX, filters) => TireDetect.Detect(lastDetectX, filters, false), + StartGuessingX = -PilotDefinition.Conf.TireFollowingStage2GuessX, + StartGuessingY = 0, + SwitchWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingLeaveCarWalkBlindSwitchingDistance, + FinishWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindFinishDistance, + PathTransformation = new Tuple( + PilotDefinition.Conf.TireFollowingLeaveCarBackLidarPathTransformationX, + PilotDefinition.Conf.TireFollowingBackLidarPathTransformationY, + 0) + }, + }, + CarDirection = 180f, + SlowDistance = PilotDefinition.Conf.TireFollowingSlowDistance, + MaxSpeed = PilotDefinition.Conf.TireFollowingMaxSpeed, + WalkBlindTh = 0, + TireNum = 1 + }; + _dt = new DriveTask(following.Get()); + _dt.Wait(); + DLog.Log($"缁撴潫绂昏溅娴嬭瘯", "TireFollowing"); + } + private DriveTask _dt; + } + + [MovementTest(name = "鎶卞す鍏抽棴")] + public class ClampTest1 : MovementTest + { + public override void TestStop() + { + _dt?.Stop(); + PilotDefinition.Self.SpeedLeftArm = 0; + PilotDefinition.Self.SpeedRightArm = 0; + } + + public override void Test() + { + _dt = new DriveTask(new ClampToTarget() + { + LeftClampTarget = PilotDefinition.Self.LeftArmUpperPos, + RightClampTarget = PilotDefinition.Self.RightArmUpperPos + }.Get()); + _dt.Wait(); + } + + private DriveTask _dt; + } + + [MovementTest(name = "鎶卞す鎵撳紑")] + public class ClampTest2 : MovementTest + { + public override void TestStop() + { + _dt?.Stop(); + PilotDefinition.Self.SpeedLeftArm = 0; + PilotDefinition.Self.SpeedRightArm = 0; + } + + public override void Test() + { + _dt = new DriveTask(new ClampToTarget() + { + LeftClampTarget = PilotDefinition.Self.LeftArmLowerPos, + RightClampTarget = PilotDefinition.Self.RightArmLowerPos + }.Get()); + _dt.Wait(); + } + + private DriveTask _dt; + } + + [MovementTest(name = "娴嬭瘯鍓嶈繘鍩轰簬杞噷绋")] + public class LineTrackingTest : MovementTest + { + public override void TestStop() + { + _dt?.Stop(); + } + public override void Test() + { + _dt = new DriveTask(new LineTracking() + { + Target = PilotDefinition.Conf.LineTrackDistance + (PilotDefinition.Self.LFLActualPos + PilotDefinition.Self.LFRActualPos) / 2, + }.Get()); + _dt.Wait(); + } + private DriveTask _dt; + } + + [MovementTest(name = "娴嬭瘯鍚庨鍩轰簬杞噷绋")] + public class ReverseLineTrackingTest : MovementTest + { + public override void TestStop() + { + _dt?.Stop(); + } + public override void Test() + { + _dt = new DriveTask(new LineTracking() + { + Target = -PilotDefinition.Conf.LineTrackDistance + (PilotDefinition.Self.LFLActualPos + PilotDefinition.Self.LFRActualPos) / 2, + }.Get()); + _dt.Wait(); + } + private DriveTask _dt; + } + + [MovementTest(name = "娴嬭瘯缁堢偣璺熻釜鍔ㄤ綔-鍓嶈繘")] + public class DstTrackerForward : MovementTest + { + public bool UseInteractivePick = true; + public float srcX; + public float srcY; + public float dstX; + public float dstY; + public float carDirectionBias = 0f; + private readonly Painter _painter = UI.GetPainter("DstTrackerTest"); + + public override void TestStop() + { + _dt?.Stop(); + _painter?.Clear(); + } + public override void Test() + { + var p1 = UI.GetPoint("point1"); + var p2 = UI.GetPoint("point2"); + + _painter.Clear(); + _dt = new DriveTask(new DstTracker() + { + Src = p1, + Dst = p2, + CarDirectionBias = carDirectionBias, + }.Get()); + _dt.Wait(); + } + + private DriveTask _dt; + } + + [MovementTest(name = "娴嬭瘯缁堢偣璺熻釜鍔ㄤ綔-鍚庨")] + public class DstTrackerhoutui : MovementTest + { + public bool UseInteractivePick = true; + public float srcX; + public float srcY; + public float dstX; + public float dstY; + public float carDirectionBias = 180f; + private readonly Painter _painter = UI.GetPainter("DstTrackerTest"); + + public override void TestStop() + { + _dt?.Stop(); + _painter?.Clear(); + } + public override void Test() + { + var p1 = UI.GetPoint("point1"); + var p2 = UI.GetPoint("point2"); + + _painter.Clear(); + _dt = new DriveTask(new DstTracker() + { + Src = p1, + Dst = p2, + CarDirectionBias = carDirectionBias, + }.Get()); + _dt.Wait(); + } + + private DriveTask _dt; + } + + [MovementTest(name = "娴嬭瘯鍏堢洿琛屽啀缁堢偣璺熻釜")] + public class LineTrackThenDstTrackerTest : MovementTest + { + public float carDirectionBias = 0f; + private readonly Painter _painter = UI.GetPainter("LineTrackThenDstTrackerTest"); + public override void TestStop() + { + _dt?.Stop(); + _painter?.Clear(); + } + public override void Test() + { + var src = UI.GetPoint("璇峰湪涓婁綅鏈洪夋嫨璧风偣(src)"); + var dst = UI.GetPoint("璇峰湪涓婁綅鏈洪夋嫨缁堢偣(dst)"); + _painter.Clear(); + _painter.DrawLine(Color.Cyan, src.X, src.Y, dst.X, dst.Y, width: 3); + _painter.DrawCircle(Color.LimeGreen, src.X, src.Y, 80f); + _painter.DrawCircle(Color.OrangeRed, dst.X, dst.Y, 80f); + _painter.DrawText(Color.LimeGreen, "src", src.X + 80f, src.Y + 80f); + _painter.DrawText(Color.OrangeRed, "dst", dst.X + 80f, dst.Y + 80f); + IEnumerable TrackThenFollow() + { + foreach (var running in new LineTracking() + { + Target = PilotDefinition.Conf.LineTrackDistance + (PilotDefinition.Self.LFLActualPos + PilotDefinition.Self.LFRActualPos) / 2, + EnableHandover = true, + HandoverDistance = 200f, + HandoverSpeed = 0.3f, + }.Get()) + { + if (!running) break; + yield return true; + } + foreach (var running in new DstTracker() + { + Src = src, + Dst = dst, + CarDirectionBias = carDirectionBias, + InitialSendSpeed = 0.3f + }.Get()) + { + if (!running) break; + yield return true; + } + yield return false; + } + _dt = new DriveTask(TrackThenFollow()); + _dt.Wait(); + } + private DriveTask _dt; + } + + [MovementTest(name = "娴嬭瘯鍏堢杞﹀啀缁堢偣璺熻釜")] + public class LeaveCarThenDstTrackerTest : MovementTest + { + private readonly Painter _painter = UI.GetPainter("LeaveCarThenDstTrackerTest"); + + public override void TestStop() + { + _dt?.Stop(); + _painter?.Clear(); + } + + public override void Test() + { + var src = UI.GetPoint("璇峰湪涓婁綅鏈洪夋嫨绂昏溅鍚庤捣鐐(src)"); + var dst = UI.GetPoint("璇峰湪涓婁綅鏈洪夋嫨缁堢偣(dst)"); + + _painter.Clear(); + _painter.DrawLine(Color.Cyan, src.X, src.Y, dst.X, dst.Y, width: 3); + _painter.DrawCircle(Color.LimeGreen, src.X, src.Y, 80f); + _painter.DrawCircle(Color.OrangeRed, dst.X, dst.Y, 80f); + _painter.DrawText(Color.LimeGreen, "src", src.X + 80f, src.Y + 80f); + _painter.DrawText(Color.OrangeRed, "dst", dst.X + 80f, dst.Y + 80f); + + IEnumerable LeaveThenFollow() + { + var following = new TireFollowing() + { + GetController = () => new ChassisController().Get(), + GuessRangeX = PilotDefinition.Conf.TireFilterLength / 2, + GuessRangeY = PilotDefinition.Conf.TireFilterWidth / 2, + detectors = new List() + { + new TireFollowing.DetectorDefinition() + { + DetectFunction = (_, lastDetectX, filters) => TireDetect.Detect(lastDetectX, filters, false), + StartGuessingX = -PilotDefinition.Conf.TireFollowingStage2GuessX, + StartGuessingY = 0, + SwitchWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindSwitchingDistance, + FinishWalkBlindCondition = rd => rd <= PilotDefinition.Conf.TireFollowingWalkBlindFinishDistance, + PathTransformation = new Tuple( + PilotDefinition.Conf.TireFollowingLeaveCarBackLidarPathTransformationX, + PilotDefinition.Conf.TireFollowingBackLidarPathTransformationY, + 0), + }, + }, + CarDirection = 180f, + SlowDistance = PilotDefinition.Conf.TireFollowingSlowDistance, + MaxSpeed = PilotDefinition.Conf.TireFollowingMaxSpeed, + WalkBlindTh = 0, + TireNum = 1 + }; + + foreach (var running in following.Get()) + { + if (!running) break; + yield return true; + } + + foreach (var running in new DstTracker() + { + Src = src, + Dst = dst, + CarDirectionBias = 180f, + }.Get()) + { + if (!running) break; + yield return true; + } + + yield return false; + } + + _dt = new DriveTask(LeaveThenFollow()); + _dt.Wait(); + } + + private DriveTask _dt; + } + + + [MovementTest(name = "椹卞姩鍣ㄤ笅浣胯兘娴嬭瘯")] + public class DriverDisableTest : MovementTest + { + public override void TestStop() + { + throw new NotImplementedException(); + } + + public override void Test() + { + new DriveTask(new DriverDisable(){ }.Get()).Wait(); + } + } + + [MovementTest(name = "椹卞姩鍣ㄥ浣嶆祴璇")] + public class DriverAbleTest : MovementTest + { + public override void TestStop() + { + throw new NotImplementedException(); + } + + public override void Test() + { + new DriveTask(new DriverAble(){ }.Get()).Wait(); + } + } + + [MovementTest(name = "搴曠洏鏃嬭浆娴嬭瘯")] + public class RotateToAngleTest : MovementTest + { + public override void TestStop() + { + throw new NotImplementedException(); + } + + public override void Test() + { + var target = UI.GetInput("杈撳叆鏃嬭浆瑙掑害锛"); + var chassis = (MultiWheelChassis)PilotDefinition.Chassis; + new DriveTask(new MultiWheelRotateInPlace() + { + AngleTarget = float.Parse(target), + PidparamsRead = () => new PIDParams() + { + Kp = PilotDefinition.Conf.TireFollowingThkp, + Ki = PilotDefinition.Conf.TireFollowingThki, + Kd = PilotDefinition.Conf.TireFollowingThkd, + DeadZone = PilotDefinition.Conf.TireFollowingThDeadZone, + SpeedAccPerSec = PilotDefinition.Conf.TireFollowingThSpeedAccPerSec, + OutputUpperThreshold = PilotDefinition.Conf.TireFollowingThThresh, + MaxI = PilotDefinition.Conf.TireFollowingThMaxI, + } + }.Get()).Wait(); + } + } + + public class utils + { + public static List<(float x, float y, float th)> RemoveOutliers(List<(float x, float y, float th)> data, float threshold = 2.0f) + { + var means = CalculateMean(data); + var stdDevs = CalculateStandardDeviation(data, means); + + return data.Where(point => + Math.Abs(point.x - means.x) <= threshold * stdDevs.x && + Math.Abs(point.y - means.y) <= threshold * stdDevs.y && + AngularDistance(point.th, means.th) <= threshold * stdDevs.th + ).ToList(); + } + + public static (float x, float y, float th) CalculateMean(List<(float x, float y, float th)> data) + { + float meanX = data.Average(point => point.x); + float meanY = data.Average(point => point.y); + float sinSum = data.Sum(point => (float)Math.Sin(DegreeToRadian(point.th))); + float cosSum = data.Sum(point => (float)Math.Cos(DegreeToRadian(point.th))); + float meanTh = RadianToDegree((float)Math.Atan2(sinSum, cosSum)); + + return (meanX, meanY, meanTh); + } + + public static (float x, float y, float th) CalculateStandardDeviation(List<(float x, float y, float th)> data, (float x, float y, float th) means) + { + float varianceX = data.Average(point => (point.x - means.x) * (point.x - means.x)); + float varianceY = data.Average(point => (point.y - means.y) * (point.y - means.y)); + + // 璁$畻瑙掑害鐨勬柟宸 + float varianceTh = data.Average(point => AngularDistance(point.th, means.th) * AngularDistance(point.th, means.th)); + + return ((float)Math.Sqrt(varianceX), (float)Math.Sqrt(varianceY), (float)Math.Sqrt(varianceTh)); + } + + public static float DegreeToRadian(float degree) + { + return (float)(degree * Math.PI / 180.0); + } + + public static float RadianToDegree(float radian) + { + return (float)(radian * 180.0 / Math.PI); + } + + public static float AngularDistance(float angle1, float angle2) + { + return CommonMath.ThDiff(angle1, angle2); + } + } + +} + + diff --git a/ClumsyPilot/MovementTests.TwoLegDetect.cs b/ClumsyPilot/MovementTests.TwoLegDetect.cs new file mode 100644 index 0000000..c0a4f57 --- /dev/null +++ b/ClumsyPilot/MovementTests.TwoLegDetect.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Numerics; +using System.Threading; +using ClumsyCore; +using ClumsyCore.DTools; +using ClumsyCore.Pilot; +using ClumsyCore.Utilities; +using ClumsyDance.ClumsyDance.Detectors; +using ClumsyDance.ClumsyWalk.Detectors; +using FundamentalLib; +using LineSegment = ClumsyCore.Utilities.LineSegment; + +namespace MultiWheelC; + +/// +/// 2鑵挎娴嬶細鐢ㄥ崟绾挎縺鍏夐浄杈捐瘑鍒袱鑵挎墭鐩/杞儙锛屾寜涓婁竴甯х粨鏋滀綔涓轰笅涓甯х寽娴嬪仛闂幆妫娴嬨 +/// 浠 StandardMultiWheelLifter 绉绘锛涘弬鏁板叏閮ㄨ蛋 PilotConfig锛團ields 闈㈡澘锛夛紝闆疯揪閫夋嫨鏀逛负閰嶇疆椤硅岄潪闃诲杈撳叆銆 +/// +[MovementTest(name = "澶氳埖杞-2鑵挎娴")] +public class TwoLegDetect : MovementTest +{ + private Painter _painter; + private bool _running = true; + + public override void TestStop() => _running = false; + + public override void Test() + { + _running = true; + _painter = UI.GetPainter("MultiWheelTwoLegDetect", false); + _painter.Clear(); + + var lidar = PilotDefinition.Conf.TwoLegLidarName; + var lastDetectX = PilotDefinition.Conf.TwoLegGuessX; + var lastDetectY = 0f; + + while (_running) + { + var ld = Detect(lidar, lastDetectX, SetFilters(lastDetectX, lastDetectY)); + if (ld == null) + { + Thread.Sleep(100); + continue; + } + + var center = (ld.Src + ld.Dst) / 2; + var distanceToCarOrigin = Vector2.Distance(Vector2.Zero, center); + + _painter.Clear(); + _painter.DrawLine(Color.Cyan, Vector2.Zero, center, width: 2); + _painter.DrawText(Color.Yellow, $"{distanceToCarOrigin:F1}", center.X / 2, center.Y / 2); + + Hedingben.ToastText( + $"[Test妫娴媇 lidar:{lidar} guess x:{lastDetectX:F0} y:{lastDetectY:F0} | " + + $"涓績 x:{center.X:F0} y:{center.Y:F0} dist:{distanceToCarOrigin:F0}", + "MultiWheelTwoLegDetect-test"); + + // 鐢ㄦ湰甯т腑蹇冧綔涓轰笅涓甯х寽娴嬶紝瀹炵幇闂幆璺熻釜 + lastDetectX = center.X; + lastDetectY = center.Y; + Thread.Sleep(100); + } + + _painter.Clear(); + } + + /// 鍦ㄨ溅浣撳潗鏍囩郴涓嬶紝鎸夌寽娴嬩綅缃娴嬩袱鑵匡紝杩斿洖杩炴帴涓よ吙鐨勭嚎娈碉紙杞︿綋绯伙級銆 + public static LineSegment Detect(string lidarName, float guessX, List filters) + { + var conf = PilotDefinition.Conf; +#pragma warning disable CS0612, CS0618 + var detector = new Lidar2dDetect2LegTray + { + BlobDist = conf.TwoLegBlobDist, + BlobPtCount = conf.TwoLegBlobPtCount, + BlobSize = conf.TwoLegBlobSize, + CenterChange = Tuple.Create(conf.TwoLegCenterChangeX, 0f, 0f), + LegWidth = conf.TwoLegWidth, + LegWidthErr = conf.TwoLegWidthErr, + Padding = conf.TwoLegPadding, + PillarFindingScope = conf.TwoLegPillarFindingScope, + SgnDir = conf.TwoLegSgnDir, + }; +#pragma warning restore CS0612, CS0618 + + var result = detector.DetectWithGuess( + lidarName, + new LineSegment(new Vector2(guessX, 0), Vector2.Zero), + guessCoordinateSystem: CoordinateSystem.Car2D, + outCoordinateSystem: CoordinateSystem.Car2D, + filters); + return ApplyOutputBias(result); + } + + private static LineSegment ApplyOutputBias(LineSegment result) + { + if (result == null) return null; + + var conf = PilotDefinition.Conf; + if (Math.Abs(conf.TwoLegOutputBiasX) < 1e-6f && Math.Abs(conf.TwoLegOutputBiasY) < 1e-6f) + return result; + + var bias = new Vector2(conf.TwoLegOutputBiasX, conf.TwoLegOutputBiasY); + return new LineSegment(result.Src + bias, result.Dst + bias); + } + + /// 鍦ㄧ寽娴嬩腑蹇冨懆鍥存瀯閫犱竴涓煩褰 ROI锛岃繃婊ゆ帀妗嗗鐐逛簯锛岄檷浣庤璇嗗埆銆 + public static List SetFilters(float guessCenterX, float guessCenterY) + { + var conf = PilotDefinition.Conf; + var painter = UI.GetPainter("MultiWheelTwoLegDetect.Filter", false); + painter.Clear(); + + var box = new[] + { + new Vector2(guessCenterX - conf.TwoLegFilterLength / 2, guessCenterY - conf.TwoLegFilterWidth / 2), + new Vector2(guessCenterX + conf.TwoLegFilterLength / 2, guessCenterY - conf.TwoLegFilterWidth / 2), + new Vector2(guessCenterX + conf.TwoLegFilterLength / 2, guessCenterY + conf.TwoLegFilterWidth / 2), + new Vector2(guessCenterX - conf.TwoLegFilterLength / 2, guessCenterY + conf.TwoLegFilterWidth / 2), + }; + + for (var i = 0; i < box.Length; ++i) + painter.DrawLine(Color.DarkOliveGreen, box[i], box[(i + 1) % 4]); + + // 鐐逛簯婊ゆ尝鍦ㄨ溅浣撳潗鏍囩郴涓嬭繘琛 + return new List + { + new(CoordinateSystem.Car2D, + p => LessMath.IsPointInPolygon4( + box.Select(v => new PointF(v.X, v.Y)).ToArray(), new PointF(p.X, p.Y))), + }; + } +} diff --git a/ClumsyPilot/MovementTests.cs b/ClumsyPilot/MovementTests.cs new file mode 100644 index 0000000..3d6322d --- /dev/null +++ b/ClumsyPilot/MovementTests.cs @@ -0,0 +1,608 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using ClumsyCore; +using ClumsyCore.Interfaces; +using ClumsyCore.Pilot; +using FundamentalLib; +using CommonUsage.Chassis; +using CommonUsage.Mathematics; +using MDCSToolBox.Clumsy.Movements; +using MDCSToolBox.Clumsy.Pilot; +using MDCSToolBox.Clumsy.Tracks; + +namespace MultiWheelC; + +public class MultiForwardTest : MovementDefinition +{ + public float Speed = 0.2f; + public float DurationSeconds = 2f; + + public override IEnumerable Get() + { + var chassis = (MultiWheelChassis)BasicPilotBase.Chassis; + chassis.SetOriginBias(0, 0, 0); + var end = DateTime.Now.AddSeconds(DurationSeconds); + while (DateTime.Now < end) + { + chassis.SendMotion(Speed, 0, 0); + yield return true; + } + + chassis.SendMotion(0, 0, 0); + } +} + +// 鍘熷湴鏃嬭浆鍒版寚瀹氫笘鐣屽潗鏍囩郴鏈濆悜锛氬厛鎶婅埖杞墦鍒版棆杞墍闇瑙掑害锛屽榻愬悗鍐嶆棆杞紝鎸夌洰鏍囪搴﹀仠姝紙闈炲浐瀹氭椂闀匡級銆 +public class MultiRotateToWorldAngle : MovementDefinition +{ + /// 鐩爣鏈濆悜锛堜笘鐣屽潗鏍囩郴锛屽崟浣 deg锛夈 + public float TargetWorldDeg; + + /// 鏃嬭浆瑙掗熷害锛坉eg/s锛岄嗘椂閽堜负姝o級銆 + public float RotSpeed = 30f; + + /// 鍒颁綅瑙掑害绮惧害锛坉eg锛夈 + public float ArriveDeg = 1f; + + /// 璧疯浆鍓嶈埖杞榻愮簿搴︼紙deg锛夈 + public float WheelAlignDeg = 2f; + + public override IEnumerable Get() + { + var chassis = (MultiWheelChassis)BasicPilotBase.Chassis; + chassis.SetOriginBias(0, 0, 0); + + // 闃舵涓锛氫粎鎶婅埖杞墦鍒板師鍦版棆杞墍闇瑙掑害锛堜笅鍙 0 閫熷害锛屽彧瀵归綈涓嶆棆杞級銆 + while (true) + { + chassis.SendRotateMotion(0); + if (WheelsAligned(chassis, WheelAlignDeg)) break; + yield return true; + } + + // 闃舵浜岋細鏃嬭浆鍒扮洰鏍囦笘鐣屾湞鍚戯紝鍒颁綅鍗冲仠銆 + var target = CommonMath.RoundTh(TargetWorldDeg); + while (true) + { + var cur = CommonMath.RoundTh((float)DetourInterface.getCartLocation().th); + var diff = CommonMath.ThDiff(target, cur); // 閫嗘椂閽堜负姝 + if (Math.Abs(diff) <= ArriveDeg) break; + chassis.SendRotateMotion(Math.Sign(diff) * RotSpeed); + yield return true; + } + + chassis.PredefinedDriveStop(); + } + + private static bool WheelsAligned(MultiWheelChassis chassis, float tolDeg) + { +#pragma warning disable CS0612, CS0618 + var wheels = chassis.GetSteerWheels(); +#pragma warning restore CS0612, CS0618 + foreach (var sw in wheels) + if (Math.Abs(CommonMath.ThDiff(sw.ReadAngle(), sw.GetSendAngle())) > tolDeg) + return false; + return true; + } +} + +[MovementTest(name = "澶氳埖杞-鍓嶈繘2绉")] +public class MultiForwardMovementTest : MovementTest +{ + private DriveTask _task; + + public override void Test() + { + _task = new DriveTask(new MultiForwardTest().Get()); + _task.Wait(); + } + + public override void TestStop() => _task?.Stop(); +} + +[MovementTest(name = "澶氳埖杞-鍘熷湴鏃嬭浆鍒扮洰鏍囪搴")] +public class MultiRotateMovementTest : MovementTest +{ + private DriveTask _task; + + public override void Test() + { + _task = new DriveTask(new MultiRotateToWorldAngle + { + TargetWorldDeg = PilotDefinition.Conf.InPlaceRotateTargetWorldDeg, + RotSpeed = PilotDefinition.Conf.InPlaceRotateSpeed, + ArriveDeg = PilotDefinition.Conf.InPlaceRotateArriveDeg, + WheelAlignDeg = PilotDefinition.Conf.InPlaceRotateWheelAlignDeg + }.Get()); + _task.Wait(); + } + + public override void TestStop() + { + _task?.Stop(); + ((MultiWheelChassis)BasicPilotBase.Chassis).PredefinedDriveStop(); + } +} + +// ===== 杞﹂槦鑱斿姩-鍘熷湴鏃嬭浆鍔ㄤ綔 ===== +// 绛変环浜 FleetRemote 鐨勩屽師鍦版棆杞嶆ā寮忥紙宸插疄娴嬪彲鐢級锛欶leetRemote 閫氳繃 Medulla 鎵嬪姩 IO +// (MultiVehicleManualEnabled + Mode=2 + Vth) 椹卞姩 PilotDefinition.TickMultiVehicle 缁曡溅闃熶腑蹇冩棆杞 +// 鎵嬪姩 IO 鏄 [AsLowerIO]锛圡edulla鈫扖lumsy锛屾瘡鍛ㄦ湡鍥炲啓锛夛紝Clumsy 渚у姩浣滅洿鎺ュ啓浼氳瑕嗙洊锛 +// 鍥犳鏈姩浣滄敼鐢 Clumsy 鍐呴儴鑴氭湰瀛楁 MultiVehicleScript*锛圱ickMultiVehicle 宸插皢鍏朵綔涓烘墜鍔ㄧ瓑浠疯緭鍏ワ級锛 +// 涓嶅啓涓琛屽簳鐩樻寚浠も斺斿疄闄呯殑 SendRotateMotion + PI 绾犲亸 + 鍚戜粠杞﹀箍鎾潎鐢 TickMultiVehicle 瀹屾垚銆 +// +// 鍓嶆彁锛氬湪銆屼富杞︺(MultiVehicleMasterEndpoint == "/") 鐨 Clumsy 涓婅繍琛岋紝涓斾粠杞﹀凡娉ㄥ唽(缂栭槦灏辩华)銆 +// 鍋滄鏉′欢锛氫富杞 SLAM 鏈濆悜绱杞繃 |TargetDeltaDeg|锛堝垰浣撳師鍦版棆杞紝鏁磋溅鏈濆悜鍙樺寲閲 == 杞﹂槦杞锛夛紱 +// 鏃犲畾浣嶆椂閫鍖栦负鎸 |TargetDeltaDeg| / |Omega| 浼扮畻鏃堕暱锛涘苟甯﹀畨鍏ㄨ秴鏃躲 +public class FleetRotateInPlace : MovementDefinition +{ + /// 瑙掗熷害澶у皬(deg/s)锛涘疄闄呮柟鍚戠敱 TargetDeltaDeg 鐨勭鍙峰喅瀹氥 + public float Omega = 15f; + + /// 鐩爣鐩稿杞(deg锛屽甫绗﹀彿锛+ 涓洪嗘椂閽)銆 + public float TargetDeltaDeg = 90f; + + /// 鍒颁綅瑙掑害绮惧害(deg)銆 + public float ArriveDeg = 1.5f; + + /// 鍑忛熷尯瀹藉害(deg)锛氬墿浣欒搴﹀皬浜庢鍊兼椂锛岃閫熷害鎸夊墿浣欐瘮渚嬬嚎鎬ч檷鍒 MinOmega锛屾姂鍒舵儻鎬ц秴璋冦 + public float SlowDeg = 25f; + + /// 鍑忛熷尯鏈鏈灏忚閫熷害(deg/s)锛氶伩鍏嶈秺鎺ヨ繎鐩爣瓒婃參銆侀暱灏惧仠涓嶄笅/鍒颁笉浜嗕綅銆 + public float MinOmega = 3f; + + /// 缂撳惎鍔ㄨ鍔犻熷害(deg/s虏)锛氳捣姝ユ椂瑙掗熷害浠 0 鎸夋鏂滅巼鐖崌鍒板贰鑸硷紝鎶戝埗璧锋鎶栧姩/闃熷舰楠ゅ亸銆備粎浣滅敤浜庤捣姝ュ姞閫燂紝<=0 鍏抽棴缂撳惎鍔紙闃惰穬璧锋锛夈 + public float AccelDegPerSec2 = 20f; + + /// + /// 鏄惁鐢 Detour 涓昏溅鑸悜闂幆鍒ゅ仠锛堣 getCartLocation().th 绱瀹為檯杞锛屽埌 |TargetDeltaDeg| 鍋滐級銆 + /// 涓 MultiVehicleSyncUseDetour 瑙h︼細杞埌鎸囧畾瑙掑害闇瑕佽搴﹀弽棣堬紝鏁呴粯璁 true銆 + /// false 鏃堕鍖栦负鎸変及绠楁椂闀垮紑鐜仠姝紙瀹為檯杞熲墵鎸囦护鏃朵笉绮剧‘锛夈傛敞鎰 true 鏃惰嫢鏃犳湁鏁堝叏灞瀹氫綅锛 + /// getCartLocation() 浼氶樆濉烇紙涓庡崟杞 MultiRotateToWorldAngle 琛屼负涓鑷达級銆 + /// + public bool UseDetourHeading = true; + + // 娉細涓嶈瓒呮椂涓婇檺鈥斺旀棆杞寔缁埌鍒颁綅锛堟垨鏃犲畾浣嶆椂鎸変及绠楁椂闀跨粨鏉燂級锛屾垨琚 Stop()/TestStop() 涓诲姩涓銆 + + /// 鍒颁綅鍚庝繚鎸佽剼鏈娇鑳姐佽閫熷害褰掗浂鐨勫畨瀹氭椂闀(s)锛岃绾犲亸鎶婇槦褰㈢ǔ浣忓啀鎾ょ銆 + public float SettleSec = 0.5f; + + private void ClearScript() + { + var self = PilotDefinition.Self; + self.MultiVehicleScriptVx = 0; + self.MultiVehicleScriptVy = 0; + self.MultiVehicleScriptVth = 0; + self.MultiVehicleScriptEnabled = false; + } + + public void Stop() => ClearScript(); + + public override IEnumerable Get() + { + var self = PilotDefinition.Self; + var conf = PilotDefinition.Conf; + + if (conf.MultiVehicleMasterEndpoint != "/") + { + Hedingben.ToastText("杞﹂槦鍘熷湴鏃嬭浆闇鍦ㄤ富杞(涓昏溅绔偣=\"/\")杩愯", "FleetRotate"); + yield break; + } + + var dir = Math.Sign(TargetDeltaDeg); + if (dir == 0) dir = 1; + var maxOmega = Math.Abs(Omega); + var minOmega = Math.Min(Math.Abs(MinOmega), maxOmega); // 鏈灏忎笉瓒呰繃鏈澶 + var slowDeg = Math.Max(1e-3f, SlowDeg); // 鍑忛熷尯瀹藉害 + var accel = AccelDegPerSec2; // 缂撳惎鍔ㄨ鍔犻熷害锛屼粎浣滅敤浜庤捣姝ワ紝<=0 鍏抽棴 + var targetMag = Math.Abs(TargetDeltaDeg); + + var hasPos = UseDetourHeading; + var prevTh = hasPos ? (float)DetourInterface.getCartLocation().th : 0f; + var startTh = prevTh; + var accumulated = 0f; // 绱甯︾鍙疯浆瑙(deg) + var start = DateTime.Now; + var lastTime = start; + var lastLog = DateTime.MinValue; + var lastCenterLog = DateTime.MinValue; + var cmdMag = 0f; // 褰撳墠瀹為檯涓嬪彂瑙掗熷害澶у皬(deg/s)锛岀紦鍚姩浠 0 鏂滃潯鐖崌 + var centerTracking = false; + float centerStartX = 0, centerStartY = 0, centerStartTh = 0; + float centerLastX = 0, centerLastY = 0, centerLastTh = 0, centerMaxDrift = 0; + // 鏃犲畾浣嶆寜鏃堕暱浼扮畻鏃讹紝琛ヤ笂缂撳惎鍔ㄦ枩鍧″皯杞殑绛夋晥鏃堕棿(鈮 maxOmega/(2路accel))锛屼娇鏃堕暱鏇存帴杩戠洰鏍囪銆 + var estDuration = maxOmega > 1e-3 ? targetMag / maxOmega : 0; + if (accel > 1e-3) estDuration += maxOmega / (2 * accel); + + DLog.Log( + $"REQUEST target={TargetDeltaDeg:0.0} dir={dir} omega={maxOmega:0.0} accel={accel:0.0} " + + $"slowDeg={slowDeg:0.0} minOmega={minOmega:0.0} useDetourHeading={hasPos} startTh={startTh:0.00} " + + $"estDuration={estDuration:0.00}s syncUseDetour={conf.MultiVehicleSyncUseDetour}", + "FleetRotateDbg"); + + // 浣胯兘鑴氭湰椹卞姩鐨勫師鍦版棆杞紙mode2锛夈俆ickMultiVehicle 鍚庡彴寰幆鎹鎵ц鏃嬭浆骞跺箍鎾粰浠庤溅銆 + // 璧锋浠 0 瑙掗熷害寮濮嬶紝鐢辩紦鍚姩鏂滃潯鐖崌锛岄伩鍏嶉樁璺冧笅鍙戝鑷撮槦褰㈤鍋/鎶栧姩銆 + self.MultiVehicleScriptVx = 0; + self.MultiVehicleScriptVy = 0; + self.MultiVehicleScriptMode = 2; + self.MultiVehicleScriptVth = 0; + self.MultiVehicleScriptEnabled = true; + self.MultiVehicleRotateWheelsReady = false; + self.MultiVehicleRotateFleetReady = false; + + DLog.Log("WAIT_ALIGN fleet rotate wheels", "FleetRotateDbg"); + while (!self.MultiVehicleRotateFleetReady) + { + self.MultiVehicleScriptVx = 0; + self.MultiVehicleScriptVy = 0; + self.MultiVehicleScriptMode = 2; + self.MultiVehicleScriptVth = 0; + self.MultiVehicleScriptEnabled = true; + Hedingben.ToastText("杞﹂槦鍘熷湴鏃嬭浆鑸佃疆棰勫榻愪腑", "FleetRotate"); + yield return true; + } + + float centerStartCarX = 0, centerStartCarY = 0, centerStartCarTh = 0; + if (hasPos) + { + var startPos = DetourInterface.getCartLocation(); + centerStartCarX = (float)startPos.x; + centerStartCarY = (float)startPos.y; + centerStartCarTh = (float)startPos.th; + prevTh = centerStartCarTh; + startTh = prevTh; + if (self.TryGetFleetCenterFromPose(centerStartCarX, centerStartCarY, centerStartCarTh, + out centerStartX, out centerStartY, out centerStartTh)) + { + centerLastX = centerStartX; + centerLastY = centerStartY; + centerLastTh = centerStartTh; + centerMaxDrift = 0; + centerTracking = true; + } + } + accumulated = 0f; + start = DateTime.Now; + lastTime = start; + lastLog = DateTime.MinValue; + lastCenterLog = DateTime.MinValue; + cmdMag = 0f; + DLog.Log( + $"START target={TargetDeltaDeg:0.0} dir={dir} omega={maxOmega:0.0} startTh={startTh:0.00} " + + $"fleetAligned={self.MultiVehicleRotateFleetReady}", + "FleetRotateDbg"); + if (centerTracking) + { + DLog.Log( + $"START center=({centerStartX:0.0},{centerStartY:0.0},{centerStartTh:0.00}) " + + $"car=({centerStartCarX:0.0},{centerStartCarY:0.0},{centerStartCarTh:0.00}) " + + $"target={TargetDeltaDeg:0.0} omega={maxOmega:0.0}", + "FleetRotateCenterDbg"); + } + + var stopReason = "stop()"; + while (true) + { + var now = DateTime.Now; + var dt = (float)Math.Min(0.2, Math.Max(0, (now - lastTime).TotalSeconds)); + lastTime = now; + var elapsed = (now - start).TotalSeconds; + + float desiredMag; + float curTh = 0f, remaining = 0f, actualRate = 0f; + if (hasPos) + { + var carPos = DetourInterface.getCartLocation(); + curTh = (float)carPos.th; + var step = (float)CommonMath.ThDiff(curTh, prevTh); // 鏈抚瀹為檯杞(閫嗘椂閽堜负姝) + accumulated += step; + actualRate = dt > 1e-3 ? step / dt : 0f; // 瀹為檯瑙掗熺巼(deg/s)锛岀敤浜庡姣旀寚浠 + prevTh = curTh; + + remaining = targetMag - Math.Abs(accumulated); + if (remaining <= ArriveDeg) { stopReason = "arrived"; break; } + + // 鍑忛熷尯锛氬墿浣欒搴 < SlowDeg 鏃讹紝鐩爣瑙掗熷害鎸夊墿浣欐瘮渚嬬嚎鎬ч檷鍒 MinOmega锛 + // 浣垮垏鏂寚浠ょ灛闂存畫浣欏姩閲忚冻澶熷皬锛屾姂鍒舵儻鎬ф粦琛岄犳垚鐨勮秴璋冦傚搴︾洿瑙傘佷究浜庣幇鍦鸿皟璇曘 + desiredMag = remaining < slowDeg + ? Math.Max(minOmega, maxOmega * (remaining / slowDeg)) + : maxOmega; + + if (centerTracking && + self.TryGetFleetCenterFromPose((float)carPos.x, (float)carPos.y, (float)carPos.th, + out centerLastX, out centerLastY, out centerLastTh)) + { + var centerDx = centerLastX - centerStartX; + var centerDy = centerLastY - centerStartY; + var centerDrift = (float)Math.Sqrt(centerDx * centerDx + centerDy * centerDy); + centerMaxDrift = Math.Max(centerMaxDrift, centerDrift); + var centerDth = (float)CommonMath.ThDiff(centerLastTh, centerStartTh); + if ((now - lastCenterLog).TotalMilliseconds >= 250) + { + lastCenterLog = now; + DLog.Log( + $"ACTION t={elapsed:0.00}s center=({centerLastX:0.0},{centerLastY:0.0},{centerLastTh:0.00}) " + + $"start=({centerStartX:0.0},{centerStartY:0.0},{centerStartTh:0.00}) " + + $"drift=({centerDx:0.0},{centerDy:0.0}) dist={centerDrift:0.0} max={centerMaxDrift:0.0} dth={centerDth:0.00} " + + $"cmdW={dir * cmdMag:0.000} actualW={actualRate:0.000} acc={accumulated:0.0} remain={remaining:0.0} " + + $"wheelReady={self.MultiVehicleRotateWheelsReady} fleetReady={self.MultiVehicleRotateFleetReady}", + "FleetRotateCenterDbg"); + } + } + } + else + { + // 鏃犲畾浣嶏細鎸夋椂闀夸及绠楋紝鏃犳硶娴嬭锛岀洰鏍囩淮鎸佸贰鑸熷害鍒颁及绠楁椂闀匡紙浠呯紦鍚姩鏁村舰锛夈 + desiredMag = maxOmega; + if (elapsed >= estDuration) { stopReason = "estDuration"; break; } + } + + // 缂撳惎鍔細鍙鈥滃姞閫(鐩爣>褰撳墠)鈥濇寜瑙掑姞閫熷害闄愭枩鐜囷紝璁╄捣姝ュ钩婊戠埇鍗囷紱 + // 鈥滃噺閫(鐩爣<褰撳墠)鈥濊窡闅忎笂闈㈢殑鍑忛熸洸绾跨珛鍗充笅璋冿紝淇濊瘉鍙婃椂鍒硅溅涓嶈秴璋冦 + if (accel > 1e-3 && desiredMag > cmdMag) + cmdMag = Math.Min(desiredMag, cmdMag + accel * dt); + else + cmdMag = desiredMag; + + self.MultiVehicleScriptVth = dir * cmdMag; + + // 钀界洏璇婃柇(鑺傛祦~150ms)锛氬疄闄呰埅鍚/绱杞/瀹為檯瑙掗熺巼 vs 鎸囦护瑙掗熺巼锛屽畾浣"寮鐜浆閫熶笉瓒"銆 + if ((now - lastLog).TotalMilliseconds >= 150) + { + lastLog = now; + DLog.Log( + hasPos + ? $"t={elapsed:0.00}s curTh={curTh:0.00} acc={accumulated:0.0} remain={remaining:0.0} " + + $"cmdW={dir * cmdMag:0.0} actualW={actualRate:0.0} (瀹為檯/鎸囦护={(Math.Abs(cmdMag) > 1e-3 ? actualRate / (dir * cmdMag) : 0):0.00})" + : $"t={elapsed:0.00}s/{estDuration:0.00}s (鏃犺埅鍚戝弽棣,寮鐜寜鏃堕暱) cmdW={dir * cmdMag:0.0}", + "FleetRotateDbg"); + } + + Hedingben.ToastText( + hasPos + ? $"杞﹂槦鍘熷湴鏃嬭浆 鐩爣{TargetDeltaDeg:0.0}掳 宸茶浆{accumulated:0.0}掳 浣檣targetMag - Math.Abs(accumulated):0.0}掳 蠅={cmdMag:0.0}" + : $"杞﹂槦鍘熷湴鏃嬭浆(鏃犲畾浣,鎸夋椂闀) {elapsed:0.0}/{estDuration:0.0}s 蠅={cmdMag:0.0}", + "FleetRotate"); + + yield return true; + } + + // 鍒颁綅锛氳閫熷害鍏堝綊闆讹紝淇濇寔鑴氭湰浣胯兘璁 TickMultiVehicle 鐨 PI 鎶婇槦褰㈢ǔ浣忎竴灏忔鏃堕棿鍐嶆挙绂汇 + self.MultiVehicleScriptVth = 0; + var settleEnd = DateTime.Now.AddSeconds(Math.Max(0, SettleSec)); + while (DateTime.Now < settleEnd) + yield return true; + + ClearScript(); + DLog.Log( + $"DONE reason={stopReason} 绱杞={accumulated:0.0}掳 鐩爣={TargetDeltaDeg:0.0}掳 " + + $"鐢ㄦ椂={(DateTime.Now - start).TotalSeconds:0.00}s useDetourHeading={hasPos}", + "FleetRotateDbg"); + if (centerTracking) + { + var centerDx = centerLastX - centerStartX; + var centerDy = centerLastY - centerStartY; + var centerDrift = (float)Math.Sqrt(centerDx * centerDx + centerDy * centerDy); + var centerDth = (float)CommonMath.ThDiff(centerLastTh, centerStartTh); + DLog.Log( + $"DONE reason={stopReason} center=({centerLastX:0.0},{centerLastY:0.0},{centerLastTh:0.00}) " + + $"start=({centerStartX:0.0},{centerStartY:0.0},{centerStartTh:0.00}) " + + $"drift=({centerDx:0.0},{centerDy:0.0}) dist={centerDrift:0.0} max={centerMaxDrift:0.0} dth={centerDth:0.00} " + + $"acc={accumulated:0.0} target={TargetDeltaDeg:0.0}", + "FleetRotateCenterDbg"); + } + Hedingben.ToastText($"杞﹂槦鍘熷湴鏃嬭浆瀹屾垚({stopReason}) 绱{accumulated:0.0}掳", "FleetRotate"); + } +} + +[MovementTest(name = "杞﹂槦鑱斿姩-鍘熷湴鏃嬭浆")] +public class FleetRotateInPlaceTest : MovementTest +{ + private FleetRotateInPlace _proc; + private DriveTask _task; + + public override void Test() + { + _proc = new FleetRotateInPlace + { + Omega = PilotDefinition.Conf.FleetRotateOmega, + TargetDeltaDeg = PilotDefinition.Conf.FleetRotateTargetDeltaDeg, + ArriveDeg = PilotDefinition.Conf.FleetRotateArriveDeg, + SlowDeg = PilotDefinition.Conf.FleetRotateSlowDeg, + MinOmega = PilotDefinition.Conf.FleetRotateMinOmega, + AccelDegPerSec2 = PilotDefinition.Conf.FleetRotateAccel, + SettleSec = PilotDefinition.Conf.FleetRotateSettleSec, + UseDetourHeading = PilotDefinition.Conf.FleetRotateUseDetourHeading + }; + _task = new DriveTask(_proc.Get()); + _task.Wait(); + } + + public override void TestStop() + { + _proc?.Stop(); + _task?.Stop(); + } +} + +[MovementTest(name = "杞﹂槦鑱斿姩-鏇茬嚎琛岃蛋")] +public class FleetCurveWalkTest : MovementTest +{ + private FleetCurveWalk _proc; + private DriveTask _task; + + public override void Test() + { + var self = PilotDefinition.Self; + if (!self.TryGetFleetCenterFromMembers(out var x, out var y, out var th) && + !self.TryGetFleetCenterFromSlam(out x, out y, out th)) + { + DLog.Log("FleetCurveWalkTest abort: failed to read fleet center.", "FleetCurveDbg"); + Hedingben.ToastText("FleetCurve requires master localization", "FleetCurve"); + return; + } + + var pointCount = Math.Max(3, PilotDefinition.Conf.FleetCurveTestControlPointCount); + var controlPoints = new List(); + for (var i = 0; i < pointCount; i++) + controlPoints.Add(UI.GetPoint($"FleetCurve point {i + 1}/{pointCount}")); + var fleetCenter = new Vector2(x, y); + if (Vector2.Distance(fleetCenter, controlPoints[0]) > + Vector2.Distance(fleetCenter, controlPoints[controlPoints.Count - 1])) + controlPoints.Reverse(); + var track = new BezierTrack(controlPoints) + { + Speed = PilotDefinition.Conf.FleetCurveSpeed, + CarDirectionBias = 0f + }; + + _proc = new FleetCurveWalk + { + Track = track, + CurveSpeed = PilotDefinition.Conf.FleetCurveSpeed, + CarDirectionBias = 0f, + SlowDistance = PilotDefinition.Conf.FleetCurveSlowDistance, + FinishDistance = PilotDefinition.Conf.FleetCurveFinishDistance, + FinishSpeed = PilotDefinition.Conf.FleetCurveFinishSpeed, + SlowingPow = PilotDefinition.Conf.FleetCurveSlowingPow, + GcpThetaThreshold = PilotDefinition.Conf.FleetCrabGcpThetaThreshold, + StartSyncTimeoutSec = PilotDefinition.Conf.FleetCrabStartSyncTimeoutSec + }; + _task = new DriveTask(_proc.Get()); + _task.Wait(); + } + + public override void TestStop() + { + _proc?.Stop(); + _task?.Stop(); + } +} + +[MovementTest(name = "杞﹂槦鑱斿姩-鑷姩锜硅")] +public class FleetCrabWalkTest : MovementTest +{ + private FleetCrabWalk _proc; + private DriveTask _task; + + public override void Test() + { + _proc = new FleetCrabWalk + { + CrabAngleDeg = PilotDefinition.Conf.FleetCrabAngleDeg, + BodyToPathAngleDeg = PilotDefinition.Conf.FleetCrabAngleDeg, + CrabLengthMm = PilotDefinition.Conf.FleetCrabLengthMm, + CrabSpeed = PilotDefinition.Conf.FleetCrabSpeed, + FleetCrabAccel = PilotDefinition.Conf.FleetCrabAccel, + FleetCrabStartAccel = PilotDefinition.Conf.FleetCrabStartAccel, + FleetCrabSlowDistance = PilotDefinition.Conf.FleetCrabSlowDistance, + FleetCrabFinishDistance = PilotDefinition.Conf.FleetCrabFinishDistance, + FleetCrabFinishSpeed = PilotDefinition.Conf.FleetCrabFinishSpeed, + FleetCrabSlowingPow = PilotDefinition.Conf.FleetCrabSlowingPow, + GcpThetaThreshold = PilotDefinition.Conf.FleetCrabGcpThetaThreshold + }; + _task = new DriveTask(_proc.Get()); + _task.Wait(); + } + + public override void TestStop() + { + _proc?.Stop(); + _task?.Stop(); + } +} + +// ===== 璋冪敤 Playground WebAPI 鐬Щ灏忚溅锛堝墠绉 / 宸︾Щ / 鏃嬭浆锛===== +// 骞崇Щ/鏃嬭浆閲忓湪 Fields 闈㈡澘閰嶇疆锛歐ebApiTranslateMm锛堥粯璁100mm锛夈乄ebApiRotateDeg锛堥粯璁5搴︼級銆 + +[MovementTest(name = "澶氳埖杞-WebAPI鍓嶇Щ")] +public class WebApiForwardMoveTest : MovementTest +{ + public override void Test() + { + var url = PilotDefinition.Conf.PlaygroundWebApiUrl; + var name = PilotDefinition.Conf.PlaygroundRobotName; + var d = PilotDefinition.Conf.WebApiTranslateMm; + + var pose = PlaygroundWebApi.GetPose(url, name); + // 杞︿綋绯诲墠鍚 (d, 0) 鍙樻崲鍒颁笘鐣岀郴锛氳溅澶存柟鍚戝嵆鏈濆悜 yaw + var dst = CommonMath.Transform2D(new Vector2(pose.X, pose.Y), pose.YawDeg, new Vector2(d, 0)); + PlaygroundWebApi.Move(url, name, dst.X, dst.Y, pose.YawDeg); + Hedingben.ToastText($"鍓嶇Щ {d:f0}mm -> ({dst.X:f0},{dst.Y:f0})", "WebApiForward"); + } + + public override void TestStop() + { + } +} + +[MovementTest(name = "澶氳埖杞-WebAPI宸︾Щ")] +public class WebApiLeftMoveTest : MovementTest +{ + public override void Test() + { + var url = PilotDefinition.Conf.PlaygroundWebApiUrl; + var name = PilotDefinition.Conf.PlaygroundRobotName; + var d = PilotDefinition.Conf.WebApiTranslateMm; + + var pose = PlaygroundWebApi.GetPose(url, name); + // 杞︿綋绯诲乏鍚 (0, d) 鍙樻崲鍒颁笘鐣岀郴锛堣溅浣 +Y 鍗冲乏渚э級 + var dst = CommonMath.Transform2D(new Vector2(pose.X, pose.Y), pose.YawDeg, new Vector2(0, d)); + PlaygroundWebApi.Move(url, name, dst.X, dst.Y, pose.YawDeg); + Hedingben.ToastText($"宸︾Щ {d:f0}mm -> ({dst.X:f0},{dst.Y:f0})", "WebApiLeft"); + } + + public override void TestStop() + { + } +} + +[MovementTest(name = "澶氳埖杞-WebAPI鏃嬭浆")] +public class WebApiRotateTest : MovementTest +{ + public override void Test() + { + var url = PilotDefinition.Conf.PlaygroundWebApiUrl; + var name = PilotDefinition.Conf.PlaygroundRobotName; + var deg = PilotDefinition.Conf.WebApiRotateDeg; + + var pose = PlaygroundWebApi.GetPose(url, name); + var ny = pose.YawDeg + deg; // 閫嗘椂閽堜负姝 + PlaygroundWebApi.Move(url, name, pose.X, pose.Y, ny); + Hedingben.ToastText($"鏃嬭浆 {deg:f1}掳 -> {ny:f1}掳", "WebApiRotate"); + } + + public override void TestStop() + { + } +} + +[MovementTest(name = "澶氳埖杞-WebAPI鎭㈠杩愬姩")] +public class WebApiMotionResumeTest : MovementTest +{ + public override void Test() + { + var url = PilotDefinition.Conf.PlaygroundWebApiUrl; + PlaygroundWebApi.ResumeMotion(url); + Hedingben.ToastText("宸叉仮澶嶈溅杈嗚繍鍔", "WebApiMotion"); + } + + public override void TestStop() + { + } +} + +[MovementTest(name = "澶氳埖杞-WebAPI鏆傚仠杩愬姩")] +public class WebApiMotionPauseTest : MovementTest +{ + public override void Test() + { + var url = PilotDefinition.Conf.PlaygroundWebApiUrl; + PlaygroundWebApi.PauseMotion(url); // 榛樿 zero 妯″紡锛氬弽棣堝綊闆 + Hedingben.ToastText("宸叉殏鍋滆溅杈嗚繍鍔 (zero)", "WebApiMotion"); + } + + public override void TestStop() + { + } +} diff --git a/ClumsyPilot/Movements.cs b/ClumsyPilot/Movements.cs new file mode 100644 index 0000000..6dd4a7c --- /dev/null +++ b/ClumsyPilot/Movements.cs @@ -0,0 +1,326 @@ +锘縰sing ClumsyCore; +using ClumsyCore.DTools; +using ClumsyCore.Interfaces; +using ClumsyCore.Pilot; +using ClumsyCore.Sensors; +using ClumsyCore.Utilities; +using ClumsyDance.ClumsyWalk.Detectors; +using ClumsyDance.Sensors; +using CommonUsage.Chassis; +using FundamentalLib; +using MDCSToolBox.Clumsy.Calibration; +using MDCSToolBox.Clumsy.HighLevelSecurity; +using MDCSToolBox.Clumsy.Movements; +using MDCSToolBox.Clumsy.Pilot; +using MDCSToolBox.Clumsy.Tracks; +using MDCSToolBox.Commons; +using MDCSToolBox.Commons.Controllers; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Net.Http; +using System.Numerics; +using System.Reflection; +using System.Text; +using System.Threading; +using static ClumsyCore.DTools.Painter; + +namespace MultiWheelC +{ + public class MultiWheelRotateInPlace : MovementDefinition + { + /// + /// 鏃嬭浆鐩爣瑙掑害 + /// + public float AngleTarget; + + public float MaxSpeed; + + public Func ThetaReader = () => (float)DetourInterface.getCartLocation().th; + + public MultiWheelChassis Chassis = (MultiWheelChassis)PilotDefinition.Chassis; + + public Func PidparamsRead = () => new PIDParams() { }; + + public PIDController thPid; + + private static float RangeAngle(float theta) + { + return (float)(theta - Math.Round(theta / 360.0f) * 360); + } + + public override IEnumerable Get() + { + var targetAngle = RangeAngle(AngleTarget); + var p = PidparamsRead(); + thPid = new PIDController(ThetaReader, p.Kp); + thPid.ChangeParameters(p.Kp, p.Ki, p.Kd, p.MaxI, p.DeadZone, p.OutputUpperThreshold, p.SpeedAccPerSec); + + DateTime lastTime = DateTime.Now; + while (true) + { + var s = thPid.GetResponse(targetAngle, true); + Console.WriteLine($"s:{s} AngleTarget:{AngleTarget}"); + Chassis.SendXYThSpeed(0, 0, s); + lastTime = DateTime.Now; + if (thPid.IsArrived()) break; + yield return true; + } + Chassis.SendXYThSpeed(0, 0, 0); + Console.WriteLine($"final rotate to {targetAngle}"); + } + } + + + public class ClampToTarget : MovementDefinition + { + public float LeftClampTarget; + public float RightClampTarget; + + public float MaxClampSpeed = PilotDefinition.Conf.MaxClampSpeed; + public float ClampKp = PilotDefinition.Conf.ClampControlKp; + public float ClampKi = PilotDefinition.Conf.ClampControlKi; + public float ClampKd = PilotDefinition.Conf.ClampControlKd; + public float ClampMaxI = PilotDefinition.Conf.ClampControlMaxI; + public float ClampSpeedAcc = PilotDefinition.Conf.ClampControlSpeedAcc; + public float ClampDeadZone = PilotDefinition.Conf.ClampControlDeadZone; + private PIDController leftpid, rightpid; + + public override IEnumerable Get() + { + leftpid = new PIDController(() => PilotDefinition.Self.ActualPosLeftArm, ClampKp, ClampKi, ClampKd, + ClampMaxI, ClampDeadZone, MaxClampSpeed) + { SpeedAccPerSec = ClampSpeedAcc }; + + rightpid = new PIDController(() => PilotDefinition.Self.ActualPosRightArm, ClampKp, ClampKi, ClampKd, + ClampMaxI, ClampDeadZone, MaxClampSpeed) + { SpeedAccPerSec = ClampSpeedAcc }; + + while (true) + { + var leftspeed = leftpid.GetResponse(LeftClampTarget); + var rightspeed = rightpid.GetResponse(RightClampTarget); + Console.WriteLine($"left arm speed:{leftspeed} right arm speed:{rightspeed}"); + PilotDefinition.Self.SpeedLeftArm = leftspeed; + PilotDefinition.Self.SpeedRightArm = rightspeed; + if (leftpid.IsArrived()) PilotDefinition.Self.SpeedLeftArm = 0; + if (rightpid.IsArrived()) PilotDefinition.Self.SpeedRightArm = 0; + + if (leftpid.IsArrived() && rightpid.IsArrived()) break; + yield return true; + } + + PilotDefinition.Self.SpeedLeftArm = 0; + PilotDefinition.Self.SpeedRightArm = 0; + Console.WriteLine($"left clamp to target:{LeftClampTarget} right clamp to target:{RightClampTarget}"); + } + } + + public class Sleep : MovementDefinition + { + public float Second = 2; + public override IEnumerable Get() + { + var start = DateTime.Now; + while ((DateTime.Now-start).TotalSeconds LeaveSrcFunction = null; + public Painter painter = UI.GetPainter("Line", false); + public override IEnumerable Get() + { + var curpose = DetourInterface.getCartLocation(); + Console.WriteLine($"curpose.th:{curpose.th}"); + var src = new Vector2((float)curpose.x, (float)curpose.y); + var dst = new Vector2((float)curpose.x + LineDistance * (float)Math.Cos(curpose.th), + (float)curpose.y + LineDistance * (float)Math.Sin(curpose.th)); + Console.WriteLine($"src:{src.X} {src.Y}"); + Console.WriteLine($"dst:{dst.X} {dst.Y}"); + painter.DrawLine(Color.Green, src.X, src.Y, dst.X, dst.Y, width: 3); + + var tracker = new ChassisController().Get(); + var linePath = new LineTrack(src, dst) { CarDirectionBias = LineDistance > 0 ? 0 : 180 }; + tracker.AddTrack(linePath); + var _dt = new DriveTask(tracker.Track()); + _dt.Wait(); + if (SrcId != -1 && LeaveSrcFunction != null) + { + LeaveSrcFunction(SrcId); + DLog.Log($"閲婃斁鏀捐溅鐐箋SrcId}", "TireFollowing"); + } + yield return false; + } + } + + //鍦ㄤ笘鐣屽潗鏍囩郴涓嬶紝浠庤矾寰勮捣鐐硅拷韪埌缁堢偣骞跺仠杞 + public class DstTracker : MovementDefinition + { + public Vector2 Src; + public Vector2 Dst; + public float CarDirectionBias = 0f; + public Painter Painter = UI.GetPainter("DstTracker"); + + public float InitialSendSpeed = 0; + + public override IEnumerable Get() + { + Console.WriteLine($"DstTracker src:({Src.X:F2}, {Src.Y:F2}) dst:({Dst.X:F2}, {Dst.Y:F2})"); + Painter.DrawLine(Color.Cyan, Src.X, Src.Y, Dst.X, Dst.Y, width: 3); + + var tracker = new ChassisController().Get(); + + if (InitialSendSpeed != 0) + { + tracker.SkipInitialRotate = true; + tracker.InitialSendSpeed = InitialSendSpeed; + } + + var linePath = new LineTrack(Src, Dst) { CarDirectionBias = CarDirectionBias, Speed = PilotDefinition.Conf.DstTrackerMaxSpeed }; + tracker.AddTrack(linePath); + var task = new DriveTask(tracker.Track()); + task.Wait(); + + // 鍒扮偣鍚庡厹搴曞仠杞 + var chassis = (MultiWheelChassis)PilotDefinition.Chassis; + chassis.SendXYThSpeed(0f, 0f, 0f); + yield return false; + } + } + + //鐩寸嚎琛岃蛋鍩轰簬杞噷绋 + public class LineTracking : MovementDefinition + { + public float Target; + public float MaxSpeed = PilotDefinition.Conf.LineTrackMaxSpeed; + public float Kp = PilotDefinition.Conf.LineTrackKp; + public float Ki = PilotDefinition.Conf.LineTrackKi; + public float Kd = PilotDefinition.Conf.LineTrackKd; + public float DeadZone = PilotDefinition.Conf.LineTrackDeadZone; + public int SrcId = -1; + public int DstId = -1; + public Action LeaveSrcFunction = null; + private PIDController pid; + // 鏈琛旀帴锛氭帴杩戠洰鏍囧悗涓嶅啀璁 PID 鎶婇熷害闄嶅埌 0锛屼繚鐣欎竴涓帴鍔涢熷害缁欏悗缁姩浣滄帴绠 + public bool EnableHandover = false; + public float HandoverDistance = 80f; // mm + public float HandoverSpeed = 0.15f; // m/s + + public override IEnumerable Get() + { + + pid = new PIDController(() => + (PilotDefinition.Self.LFLActualPos + PilotDefinition.Self.LFRActualPos) / 2, + Kp, Ki, Kd, 0, DeadZone, MaxSpeed) + { SpeedAccPerSec = MaxSpeed / 2f }; + + var chassis = (MultiWheelChassis)PilotDefinition.Chassis; + //chassis.SetOriginBias(0, 0, 0); + DLog.Log($"鐩寸嚎琛岄┒璺濈:{Target}", "TireFollowing"); + while (true) + { + var current = (PilotDefinition.Self.LFLActualPos + PilotDefinition.Self.LFRActualPos) / 2; + var remain = Target - current; + if (EnableHandover && Math.Abs(remain) <= Math.Max(1f, HandoverDistance)) + { + var handoverSign = Math.Sign(remain); + if (handoverSign == 0) handoverSign = 1; + var handoverSpeed = Math.Abs(HandoverSpeed) * handoverSign; + Console.WriteLine($"handover speed: {handoverSpeed:F3}, remain: {remain:F2}"); + chassis.SendXYThSpeed(handoverSpeed, 0, 0); + // 淇濈暀涓鎷嶆帴鍔涢熷害锛岃鍚庣画 DstTracker 鏃犵紳鎺ョ + yield return true; + break; + } + var speed = pid.GetResponse(Target); + Console.WriteLine($"output: {speed} current: {(PilotDefinition.Self.LFLActualPos + PilotDefinition.Self.LFRActualPos) / 2}"); + + chassis.SendXYThSpeed(speed, 0, 0); + + if (pid.IsArrived()) break; + yield return true; + } + if (SrcId != -1 && LeaveSrcFunction != null) + { + LeaveSrcFunction(SrcId); + DLog.Log($"閲婃斁鏀捐溅鐐箋SrcId}", "TireFollowing"); + } + yield return false; + } + } + + public class DriverAble : MovementDefinition + { + public int WaitTimeoutMs = 2000; + public int PollIntervalMs = 50; + + public override IEnumerable Get() + { + Console.WriteLine("椹卞姩鍣ㄤ笂浣胯兘"); + PilotDefinition.Self.ResetFromC = true; + + var start = DateTime.Now; + var timeoutMs = Math.Max(0, WaitTimeoutMs); + var pollMs = Math.Max(1, PollIntervalMs); + var success = PilotDefinition.Self.WheelAbleState; + while (!success && (DateTime.Now - start).TotalMilliseconds < timeoutMs) + { + Thread.Sleep(pollMs); + success = PilotDefinition.Self.WheelAbleState; + if (!success) yield return true; + } + + PilotDefinition.Self.ResetFromC = false; + if (success) + Console.WriteLine($"椹卞姩鍣ㄤ笂浣胯兘瀹屾垚锛學heelAbleState={PilotDefinition.Self.WheelAbleState}"); + else + Console.WriteLine($"椹卞姩鍣ㄤ笂浣胯兘瓒呮椂锛學heelAbleState={PilotDefinition.Self.WheelAbleState}锛岀瓑寰厈timeoutMs}ms"); + yield return false; + } + } + + public class DriverDisable : MovementDefinition + { + public int WaitTimeoutMs = 3000; + public int PollIntervalMs = 20; + + public override IEnumerable Get() + { + Console.WriteLine("椹卞姩鍣ㄤ笅浣胯兘"); + PilotDefinition.Self.DisableFromC = true; + + var start = DateTime.Now; + var timeoutMs = Math.Max(0, WaitTimeoutMs); + var pollMs = Math.Max(1, PollIntervalMs); + var success = !PilotDefinition.Self.WheelAbleState; + while (!success && (DateTime.Now - start).TotalMilliseconds < timeoutMs) + { + Thread.Sleep(pollMs); + success = !PilotDefinition.Self.WheelAbleState; + if (!success) yield return true; + } + + PilotDefinition.Self.DisableFromC = false; + if (success) + Console.WriteLine($"椹卞姩鍣ㄤ笅浣胯兘瀹屾垚锛學heelAbleState={PilotDefinition.Self.WheelAbleState}"); + else + Console.WriteLine($"椹卞姩鍣ㄤ笅浣胯兘瓒呮椂锛學heelAbleState={PilotDefinition.Self.WheelAbleState}锛岀瓑寰厈timeoutMs}ms"); + yield return false; + } + } +} diff --git a/ClumsyPilot/PilotConfig.cs b/ClumsyPilot/PilotConfig.cs new file mode 100644 index 0000000..57dab71 --- /dev/null +++ b/ClumsyPilot/PilotConfig.cs @@ -0,0 +1,334 @@ +using ClumsyCore; +using MDCSToolBox.Clumsy.Pilot.MultiWheel; +using Newtonsoft.Json; + +namespace MultiWheelC; + +public class PilotConfig : MultiWheelPilotConfig +{ + [FieldMember(desc = "[sync] steering angle acceleration(deg/s^2)")] public float SyncThAccPerSec = 30f; + [FieldMember(desc = "[sync] fleet member distance(mm)")] public float TestCarSyncDistance = 2400f; + [FieldMember(desc = "[sync] fleet layout bias angle(deg)")] public float TestCarSyncTh = 0f; + // Fleet manual remote IO values are normalized joystick ratios. Keep all speed/angle scaling here. + [FieldMember(desc = "[sync] fleet manual max linear speed(m/s)")] public float FleetManualMaxSpeed = 0.3f; + [FieldMember(desc = "[sync] fleet manual normal-mode full-stick steering angle(deg)")] public float FleetManualMaxSteerAngleDeg = 45f; + [FieldMember(desc = "[sync] fleet manual crab-mode full-stick steering angle(deg)")] public float FleetManualMaxCrabAngleDeg = 60f; + [FieldMember(desc = "[sync] fleet manual rotate-mode full-stick angular speed(deg/s)")] public float FleetManualMaxRotateOmegaDegPerSec = 45f; + [FieldMember(desc = "[sync] 锜硅鑸佃涓婇檺(deg锛屽簲涓嶮edulla鑸佃疆瑙掑害闄愬埗鍖归厤锛岄粯璁120)")] public float MultiVehicleCrabSteerLimitDeg = 120f; + [FieldMember(desc = "[sync] 妫娴嬩腑蹇冨亸绉(mm)")] public float DeltaDetectCenter = 350f; + // 浠呮帶鍒"杞﹂槦鍐呭Э鎬佺籂姝"(POS 琛ュ伩)鏄惁浣跨敤 Detour 鐨 SLAM 浣嶅Э锛屼笉褰卞搷"鏁翠釜杞﹂槦濮挎佺殑璁$畻"銆 + // 榛樿 false锛氬畾浣嶄笉鍙備笌杞﹂槦鍐呭Э鎬佺籂姝o紙鍚勮溅鎸夌紪闃熷嚑浣/浜掕瘑鍒繚鎸侀槦褰紝涓嶅仛 SLAM 閫愯溅绾犲亸锛夈 + // 涓 true锛氶澶栫敤 getCartLocation() 鍙嶆帹姣忓彴杞︾浉瀵圭紪闃熶腑蹇冪殑鍋忓樊骞跺仛 POS 琛ュ伩銆 + // 娉ㄦ剰锛氭棤璁鸿寮鍏冲浣曪紝鑷姩妯″紡涓嬫暣闃熷Э鎬(鍙嶆帹/骞挎挱杞﹂槦涓績銆丼LAM 闂磋窛銆佽嚜鍔ㄥ畨鍏ㄩ棬)濮嬬粓渚濊禆 Detour 鍏ㄥ眬瀹氫綅锛 + // 涓昏溅鑷姩妯″紡蹇呰皟鐢 getCartLocation()锛岃嫢鏃犳湁鏁堝叏灞瀹氫綅璇ヨ皟鐢ㄤ細闃诲 鈫 鑱斿姩绾跨▼闃诲涓嶄笅鍙戦熷害锛堝畨鍏ㄥ仠杞︼級銆 + [FieldMember(desc = "[sync] 瀹氫綅鏄惁鍙備笌杞﹂槦鍐呭Э鎬佺籂姝(涓嶅奖鍝嶆暣闃熷Э鎬佽绠)")] public bool MultiVehicleSyncUseDetour = false; + // 鎵嬪姩澶栭儴閬ユ帶鑱斿姩榛樿鍙蛋 2 鑵挎娴/鍑犱綍鍚屾锛岄伩鍏 Detour getCartLocation 闃诲瀵艰嚧閬ユ帶鍜屾娴嬪彲瑙嗗寲鍙樻參銆 + [FieldMember(desc = "[sync] 鎵嬪姩鑱斿姩鏄惁鍚敤瀹氫綅濮挎佺籂姝(榛樿鍏抽棴)")] public bool MultiVehicleManualUseDetourCorrection = false; + + [FieldMember(desc = "澶氳溅鑱斿姩锛氭昏溅鏁")] public int MultiVehicleFleetNum = 2; + [FieldMember(desc = "鑱斿姩绾跨▼鍛ㄦ湡(ms)")] public int MultiVehicleSyncInterval = 50; + [FieldMember(desc = "澶氳溅鑱斿姩锛氫富杞︾鐐 ip:port锛/ 琛ㄧず鏈溅涓轰富杞")] public string MultiVehicleMasterEndpoint = "/"; + [FieldMember(desc = "澶氳溅鑱斿姩锛氭湰杞﹀悓姝 IP")] public string SimpleIp = "127.0.0.1"; + + [FieldMember(desc = "澶氳溅鑱斿姩锛氭湰杞﹀洖杩炵鐐 ip:port锛屼緵涓昏溅 notify 鍥炶繛锛岀┖=127.0.0.1:鏈溅port")] public string MultiVehicleSelfEndpoint = ""; + + [JsonProperty("MultiVehicleMasterIp")] + private string LegacyMasterIpSetter + { + set + { + if (string.IsNullOrEmpty(value) || value == "/") return; + if (MultiVehicleMasterEndpoint == "/") + MultiVehicleMasterEndpoint = value.Contains(":") ? value : $"{value}:8008"; + } + } + + [FieldMember(desc = "澶氳溅鑱斿姩锛氬惎鐢ㄤ簰璇嗗埆绾犳")] public bool MultiVehicleUseDetect = false; + + // B: 鑷姩閫熷害鍛戒护鏂伴矞搴(ms)銆備富杞﹁秴杩囨鏃堕暱鏈粠璺緞鎺у埗鍣ㄦ敹鍒版柊閫熷害鍛戒护(璺緞缁撴潫/鏃╅/鍗¢】)锛 + // 鍗宠涓哄け鏁堝苟娓呴浂涓嬪彂閫熷害锛岄伩鍏嶈溅闃熸寜鏈熷害婊戣銆0 琛ㄧず鑷姩鍙 max(200, interval*4)銆 + [FieldMember(desc = "澶氳溅鑱斿姩锛氳嚜鍔ㄩ熷害鍛戒护瓒呮椂(ms锛0=auto)")] public int MultiVehicleAutoCmdTimeoutMs = 0; + // C: fleet 鎴愬憳瀛樻椿 TTL(ms)銆備富杞﹀墧闄よ秴杩囨鏃堕暱鏈 register/鍒锋柊鐨勪粠杞︼紱缂栭槦灏辩华瑕佹眰鎵鏈夋垚鍛樻柊椴溿 + // 0 琛ㄧず鑷姩鍙 max(500, interval*6)銆 + [FieldMember(desc = "澶氳溅鑱斿姩锛氭垚鍛樺瓨娲籘TL(ms锛0=auto)")] public int MultiVehicleMemberTtlMs = 0; + // D: 鑷姩妯″紡涓嬬敤涓昏溅璺緞鎺у埗鍣ㄧ殑鐞嗘兂杞﹂槦涓績(idealPos/idealAngle)浣滀负鍚勮溅 layout 鐩爣锛 + // 寮х嚎璺緞涓婂仛 per-car 鍓嶉鑰岄潪浠呭叡鐢 frontTh/rearTh 浜嬪悗绾犲亸銆 + [FieldMember(desc = "澶氳溅鑱斿姩锛氳嚜鍔ㄦā寮忔寜鐞嗘兂涓績鍓嶉(寮х嚎)")] public bool MultiVehicleAutoUseIdealCenter = true; + // H: 鑷姩妯″紡蹇呴』鏈夋湁鏁堣溅闃熶腑蹇(SLAM 鍙弽鎺)锛屽叏绋嬪畾浣嶄涪澶辨椂鍋滆溅锛岄伩鍏嶇函 SLAM 涓嬬洸璺戙 + [FieldMember(desc = "澶氳溅鑱斿姩锛氳嚜鍔ㄦā寮忚姹傛湁鏁堣溅闃熶腑蹇")] public bool MultiVehicleAutoRequireFleetCenter = true; + [FieldMember(desc = "澶氳溅鑱斿姩锛歋LAM X琛ュ伩绯绘暟")] public float MultiVehiclePosBiasXFac = 0.5f; + [FieldMember(desc = "澶氳溅鑱斿姩锛歋LAM Y琛ュ伩绯绘暟")] public float MultiVehiclePosBiasYFac = 0.5f; + [FieldMember(desc = "澶氳溅鑱斿姩锛歋LAM Th琛ュ伩绯绘暟")] public float MultiVehiclePosBiasThFac = 0.5f; + [FieldMember(desc = "澶氳溅鑱斿姩锛歑琛ュ伩闃堝(mm)")] public float MultiVehiclePosBiasXThreshold = 50f; + [FieldMember(desc = "澶氳溅鑱斿姩锛歒琛ュ伩闃堝(mm)")] public float MultiVehiclePosBiasYThreshold = 50f; + [FieldMember(desc = "澶氳溅鑱斿姩锛歍h琛ュ伩闃堝(deg)")] public float MultiVehiclePosBiasThThreshold = 5f; + + [FieldMember(desc = "澶氳溅鑱斿姩锛氫簰璇嗗埆 X琛ュ伩绯绘暟")] public float MultiVehicleDetectBiasXFac = 0.5f; + [FieldMember(desc = "澶氳溅鑱斿姩锛氫簰璇嗗埆 Y琛ュ伩绯绘暟")] public float MultiVehicleDetectBiasYFac = 0.5f; + [FieldMember(desc = "澶氳溅鑱斿姩锛氫簰璇嗗埆 Th琛ュ伩绯绘暟")] public float MultiVehicleDetectBiasThFac = 0.5f; + [FieldMember(desc = "澶氳溅鑱斿姩锛氫簰璇嗗埆 X琛ュ伩闃堝(mm)")] public float MultiVehicleDetectBiasXThreshold = 50f; + [FieldMember(desc = "澶氳溅鑱斿姩锛氫簰璇嗗埆 Y琛ュ伩闃堝(mm)")] public float MultiVehicleDetectBiasYThreshold = 50f; + [FieldMember(desc = "澶氳溅鑱斿姩锛氫簰璇嗗埆 Th琛ュ伩闃堝(deg)")] public float MultiVehicleDetectBiasThThreshold = 5f; + + // 鍘熷湴鏃嬭浆(mode2)闂幆绾犲亸(PI)锛氭妸"鏈溅搴旂Щ鍔ㄥ埌鐨勪綅缃(dx,dy,mm)/搴旇浆瑙(dth,deg)"浣滀负璇樊锛 + // 鐢 PI 鎺у埗鍣ㄦ崲绠楁垚杞︿綋绯讳慨姝i熷害鍙犲姞鍒扮粫闃熷績鏃嬭浆涓娿傜函 P 瀵规姉鎭掑畾妯悜婊戠Щ鎵板姩鏈夌ǔ鎬佹畫宸紝 + // 鍔犵Н鍒嗛」鎶婄ǔ鎬佽宸媺鍒 0锛涚Н鍒嗗甫闄愬箙(鎶 windup)锛屾昏緭鍑洪檺骞呭湪 Max 鍐呴槻杩囧啿/鎸崱銆 + // Fac=姣斾緥澧炵泭(mm/s per mm銆乨eg/s per deg)锛汭Fac=绉垎澧炵泭(mm/s per mm路s銆乨eg/s per deg路s)锛汳ax=鎬昏緭鍑轰笂闄愩 + [FieldMember(desc = "鍘熷湴鏃嬭浆绾犲亸锛氬钩绉绘瘮渚嬪鐩奝(mm/s per mm)")] public float MultiVehicleRotateCompXyFac = 1.2f; + [FieldMember(desc = "鍘熷湴鏃嬭浆绾犲亸锛氬钩绉荤Н鍒嗗鐩奍(mm/s per mm路s)")] public float MultiVehicleRotateCompXyIFac = 0.8f; + [FieldMember(desc = "鍘熷湴鏃嬭浆绾犲亸锛氬钩绉婚熷害涓婇檺(mm/s)")] public float MultiVehicleRotateCompXyMax = 150f; + [FieldMember(desc = "鍘熷湴鏃嬭浆绾犲亸锛氳浆鍚戞瘮渚嬪鐩奝(deg/s per deg)")] public float MultiVehicleRotateCompThFac = 0.8f; + [FieldMember(desc = "鍘熷湴鏃嬭浆绾犲亸锛氳浆鍚戠Н鍒嗗鐩奍(deg/s per deg路s)")] public float MultiVehicleRotateCompThIFac = 0.8f; + [FieldMember(desc = "鍘熷湴鏃嬭浆绾犲亸锛氳浆鍚戦熷害涓婇檺(deg/s)")] public float MultiVehicleRotateCompThMax = 15f; + // 浠呭綋杞﹂槦瀹為檯琚寚浠ゆ棆杞(|fleetOmega|瓒呰繃姝ら槇鍊)鏃舵墠杩愯绾犲亸 PI锛涘惁鍒欐竻闆跺苟澶嶄綅绉垎锛 + // 閬垮厤鏉惧紑鎽囨潌鍚庣Н鍒嗘畫鐣欐寔缁┍鍔ㄨ溅杈"鑷鏃嬭浆鍋滀笉涓嬫潵"銆 + [FieldMember(desc = "鍘熷湴鏃嬭浆绾犲亸锛氱敓鏁堢殑鏈灏忚閫熷害闃堝(deg/s)")] public float MultiVehicleRotateActiveOmega = 0.5f; + // 瀹夊叏缃戯細姣忚疆绾犲亸閫熷害骞呭 <= 璇ユ瘮渚 * 鏈疆鏃嬭浆鍒囧悜閫熷害锛岄檺鍒跺悎閫熷害鐩稿绾垏鍚戠殑鏈澶у亸瑙掋 + // 鏃ч厤缃嫢浠嶄负 <0锛岃繍琛屾椂鎸夊畨鍏ㄩ粯璁 0.10 澶勭悊锛涚‘闇鏀惧鏃跺彲鍦ㄤ富杞︽樉寮忚皟澶у苟鍚屾缁欎粠杞︺ + [FieldMember(desc = "鍘熷湴鏃嬭浆绾犲亸锛氱籂鍋/鏃嬭浆鍒囧悜姣斾緥纭笂闄愶紝<0浣跨敤瀹夊叏榛樿0.10")] public float MultiVehicleRotateCompTangentFrac = 0.10f; + + [FieldMember(desc = "鍗曡溅鍚屾 xy 绮惧害(mm)")] public float SingleCarSyncPrecisionXy = 10f; + [FieldMember(desc = "鍗曡溅鍚屾 th 绮惧害(deg)")] public float SingleCarSyncPrecisionTh = 0.2f; + + [FieldMember(desc = "Playground WebAPI 鍩哄湴鍧")] + public string PlaygroundWebApiUrl = "http://localhost:18090"; + + [FieldMember(desc = "MultiVehicle rotate pose WebAPI diagnostics (simulation only)")] + public bool MultiVehicleRotatePoseWebApiDiagEnabled = false; + + [FieldMember(desc = "Playground 灏忚溅鍚嶇О锛堝満鏅 robots[].name锛")] + public string PlaygroundRobotName = "agv_multi_1"; + + [FieldMember(desc = "Playground 閭昏溅鍚嶇О锛堜粎涓昏溅鐢ㄤ簬鍘熷湴鏃嬭浆浣嶅Э璇婃柇锛")] + public string PlaygroundNeighborRobotName = "agv_multi_2"; + + [FieldMember(desc = "WebAPI 骞崇Щ娴嬭瘯锛氬钩绉昏窛绂(mm)")] + public float WebApiTranslateMm = 100f; + + [FieldMember(desc = "WebAPI 鏃嬭浆娴嬭瘯锛氭棆杞搴(deg)")] + public float WebApiRotateDeg = 5f; + + [FieldMember(desc = "鍘熷湴鏃嬭浆锛氱洰鏍囨湞鍚(涓栫晫鍧愭爣绯, deg)")] + public float InPlaceRotateTargetWorldDeg = 90f; + + [FieldMember(desc = "鍘熷湴鏃嬭浆锛氭棆杞閫熷害(deg/s)")] + public float InPlaceRotateSpeed = 30f; + + [FieldMember(desc = "鍘熷湴鏃嬭浆锛氬埌浣嶈搴︾簿搴(deg)")] + public float InPlaceRotateArriveDeg = 1f; + + [FieldMember(desc = "鍘熷湴鏃嬭浆锛氳捣杞墠鑸佃疆瀵归綈绮惧害(deg)")] + public float InPlaceRotateWheelAlignDeg = 2f; + + [FieldMember(desc = "鍘熷湴鏃嬭浆锛氭棆杞繃绋嬩腑鑸佃疆鍋忓樊閲嶅榻愰槇鍊(deg)")] + public float InPlaceRotateActiveWheelAlignDeg = 10f; + + // ===== 杞﹂槦鑱斿姩-鍘熷湴鏃嬭浆鍔ㄤ綔锛團leetRotateInPlace / 瀵瑰簲 FleetRemote 鍘熷湴鏃嬭浆妯″紡锛===== + // 閫氳繃 Clumsy 鍐呴儴鑴氭湰瀛楁椹卞姩 TickMultiVehicle 鐨 mode2 鏃嬭浆锛堢粫杞﹂槦涓績 + PI 绾犲亸锛夛紝闇涓昏溅杩愯銆 + [FieldMember(desc = "杞﹂槦鍘熷湴鏃嬭浆锛氳閫熷害澶у皬(deg/s锛屾柟鍚戠敱鐩爣瑙掔鍙峰喅瀹)")] + public float FleetRotateOmega = 15f; + + [FieldMember(desc = "杞﹂槦鍘熷湴鏃嬭浆锛氱洰鏍囩浉瀵硅浆瑙(deg锛+閫嗘椂閽)")] + public float FleetRotateTargetDeltaDeg = 90f; + + [FieldMember(desc = "杞﹂槦鍘熷湴鏃嬭浆锛氬埌浣嶈搴︾簿搴(deg)")] + public float FleetRotateArriveDeg = 1.5f; + + [FieldMember(desc = "杞﹂槦鍘熷湴鏃嬭浆锛氬噺閫熷尯瀹藉害(deg)锛屾姂鍒舵敹灏炬儻鎬ц秴璋")] + public float FleetRotateSlowDeg = 25f; + + [FieldMember(desc = "杞﹂槦鍘熷湴鏃嬭浆锛氬噺閫熷尯鏈鏈灏忚閫熷害(deg/s)")] + public float FleetRotateMinOmega = 3f; + + [FieldMember(desc = "杞﹂槦鍘熷湴鏃嬭浆锛氳捣姝ョ紦鍚姩瑙掑姞閫熷害(deg/s虏锛<=0鍏抽棴)")] + public float FleetRotateAccel = 20f; + + [FieldMember(desc = "杞﹂槦鍘熷湴鏃嬭浆锛氬埌浣嶅悗瀹夊畾鏃堕暱(s)")] + public float FleetRotateSettleSec = 0.5f; + + // 涓 MultiVehicleSyncUseDetour 瑙h︼細杞埌鎸囧畾瑙掑害闇鑸悜鍙嶉锛岄粯璁 true 璇讳富杞 SLAM 鑸悜闂幆鍒ゅ仠銆 + // false 鏃堕鍖栦负鎸変及绠楁椂闀垮紑鐜仠姝紙瀹為檯杞熲墵鎸囦护鏃朵笉绮剧‘锛屾槗鍑虹幇"娌¤浆鍒扮洰鏍囧氨鍋"锛夈 + [FieldMember(desc = "杞﹂槦鍘熷湴鏃嬭浆锛氱敤Detour涓昏溅鑸悜闂幆鍒ゅ仠(榛樿true锛宖alse=鎸夋椂闀垮紑鐜)")] + public bool FleetRotateUseDetourHeading = true; + + // ===== 杞﹂槦鑱斿姩-鑷姩锜硅锛團leetCrabWalk锛===== + // 浠ュ綋鍓嶈溅闃熶腑蹇冧负璧风偣锛屾瀯閫犱竴鏉$洿绾胯矾寰勶紱MovementTest 涓溅韬繚鎸佸惎鍔ㄦ湞鍚戣拷韪璺緞銆 + // 鍔ㄤ綔渚у弬鑰冨嚑浣曟帶鍒跺櫒鐨勮矾寰勮窡韪濊矾锛岀洿鎺ュ啓鍏 MultiVehicleAuto... 瀛楁锛屼笉鍐嶅鐢ㄨ剼鏈墜鍔ㄩ摼璺 + [FieldMember(desc = "杞﹂槦锜硅锛氳矾寰勬柟鍚戠浉瀵瑰惎鍔ㄦ椂杞﹂槦鏈濆悜澶硅(deg锛岄嗘椂閽堜负姝o紱璺緞鍦ㄨ溅鍙充晶x搴︽椂濉-x)")] + public float FleetCrabAngleDeg = 45f; + + [FieldMember(desc = "杞﹂槦锜硅锛欰GV鍏ュ彛浣跨敤鐨勮溅闃熶笘鐣岀郴鐩爣鏈濆悜(deg)")] + public float FleetCrabBodyWorldHeadingDeg = 0f; + + [FieldMember(desc = "杞﹂槦锜硅锛氳矾寰勯暱搴(mm)")] + public float FleetCrabLengthMm = 2000f; + + [FieldMember(desc = "杞﹂槦锜硅锛氳椹堕熷害(m/s)")] + public float FleetCrabSpeed = 0.2f; + + [FieldMember(desc = "杞﹂槦锜硅锛氶熷害鍛戒护鍔犻熷害闄愬埗(m/s^2锛<=0琛ㄧず涓嶉檺鍒)")] + public float FleetCrabAccel = 0.2f; + + [FieldMember(desc = "杞﹂槦锜硅锛氶瀵归綈鍚庢寮忎笅鍙戦熷害鍓5绉掑姞閫熷害(m/s^2锛<=0琛ㄧず涓嶉檺鍒)")] + public float FleetCrabStartAccel = 0.01f; + + [FieldMember(desc = "杞﹂槦锜硅锛氭湯绔紑濮嬪噺閫熻窛绂(mm)")] + public float FleetCrabSlowDistance = 2000f; + + [FieldMember(desc = "杞﹂槦锜硅锛氬畬鎴愯窛绂(mm)锛屼綆浜庤鍓╀綑璺濈缁撴潫鍔ㄤ綔")] + public float FleetCrabFinishDistance = 20f; + + [FieldMember(desc = "杞﹂槦锜硅锛氭湯绔渶浣庨熷害(m/s)")] + public float FleetCrabFinishSpeed = 0.02f; + + [FieldMember(desc = "杞﹂槦锜硅锛氭湯绔噺閫熸洸绾挎寚鏁")] + public float FleetCrabSlowingPow = 0.8f; + + [FieldMember(desc = "杞﹂槦锜硅锛欸CP鑸佃淇涓婇檺(deg)")] + public float FleetCrabGcpThetaThreshold = 95f; + + [FieldMember(desc = "杞﹂槦锜硅锛歨eadingErr瑙掑害绾犲亸姣斾緥绯绘暟")] + public float FleetCrabDthLinearFac = 1f; + + [FieldMember(desc = "杞﹂槦锜硅锛歨eadingErr瑙掑害绾犲亸鑸佃闄愬箙(deg)")] + public float FleetCrabDthLinearThreshold = 10f; + + [FieldMember(desc = "FleetCrab startup sync timeout(s)")] + public float FleetCrabStartSyncTimeoutSec = 8f; + + [FieldMember(desc = "FleetCrab startup wheel alignment tolerance(deg)")] + public float FleetCrabStartWheelAlignDeg = 2f; + + // ===== Fleet linked Bezier curve walk ===== + [FieldMember(desc = "FleetCurve MovementTest Bezier control point count")] + public int FleetCurveTestControlPointCount = 4; + + [FieldMember(desc = "FleetCurve speed(m/s)")] + public float FleetCurveSpeed = 0.2f; + + [FieldMember(desc = "FleetCurve slow distance(mm)")] + public float FleetCurveSlowDistance = 2000f; + + [FieldMember(desc = "FleetCurve finish distance(mm)")] + public float FleetCurveFinishDistance = 20f; + + [FieldMember(desc = "FleetCurve finish speed(m/s)")] + public float FleetCurveFinishSpeed = 0.02f; + + [FieldMember(desc = "FleetCurve slowing curve exponent")] + public float FleetCurveSlowingPow = 0.8f; + + // ===== 2鑵挎娴嬶紙鍗曠嚎闆疯揪璇嗗埆涓よ吙鎵樼洏 / 杞儙锛===== + [FieldMember(desc = "2鑵挎娴嬶細闆疯揪鍚嶏紙閫楀彿鍒嗛殧鍙涓級")] + public string TwoLegLidarName = "rear_left_lidar_1,rear_right_lidar_1"; + + [FieldMember(desc = "2鑵挎娴嬶細鍒濆鐚滄祴X(mm, 杞︿綋鍧愭爣绯)")] + public float TwoLegGuessX = 2000f; + + [FieldMember(desc = "2鑵挎娴嬶細涓よ吙闂磋窛(mm)")] + public float TwoLegWidth = 800f; + + [FieldMember(desc = "2鑵挎娴嬶細涓よ吙闂磋窛鍏佽璇樊(mm)")] + public float TwoLegWidthErr = 100f; + + [FieldMember(desc = "2鑵挎娴嬶細鑱氱被鐐归棿璺(mm)")] + public float TwoLegBlobDist = 100f; + + [FieldMember(desc = "2鑵挎娴嬶細鑱氱被灏哄(mm)")] + public float TwoLegBlobSize = 200f; + + [FieldMember(desc = "2鑵挎娴嬶細鑱氱被鏈灏忕偣鏁")] + public int TwoLegBlobPtCount = 5; + + [FieldMember(desc = "2鑵挎娴嬶細鑱氱被 padding")] + public int TwoLegPadding = 5; + + [FieldMember(desc = "2鑵挎娴嬶細鑵挎煴鎼滅储鑼冨洿")] + public int TwoLegPillarFindingScope = 20; + + [FieldMember(desc = "2鑵挎娴嬶細鏂瑰悜绗﹀彿(卤1)")] + public int TwoLegSgnDir = 1; + + [FieldMember(desc = "2鑵挎娴嬶細涓績X鍋忕Щ(mm)")] + public float TwoLegCenterChangeX = 0f; + + [FieldMember(desc = "2鑵挎娴嬶細杈撳嚭X琛ュ伩(mm)")] + public float TwoLegOutputBiasX = 0f; + + [FieldMember(desc = "2鑵挎娴嬶細杈撳嚭Y琛ュ伩(mm)")] + public float TwoLegOutputBiasY = 0f; + + [FieldMember(desc = "2鑵挎娴嬶細ROI婊ゆ尝妗嗛暱(mm)")] + public float TwoLegFilterLength = 1800f; + + [FieldMember(desc = "2鑵挎娴嬶細ROI婊ゆ尝妗嗗(mm)")] + public float TwoLegFilterWidth = 600f; + + #region + [FieldMember(desc = "杞儙璇嗗埆:璇嗗埆妗嗛暱")] public float TireFilterLength = 1800f; + [FieldMember(desc = "杞儙璇嗗埆:璇嗗埆妗嗗")] public float TireFilterWidth = 600f; + [FieldMember(desc = "杞儙璇嗗埆:杞儙闂磋窛")] public float TireTwoLegWidth = 800f; + [FieldMember(desc = "杞儙璇嗗埆:杞儙璇嗗埆鍏佽璇樊")] public float TireTwoLegWidthErr = 100f; + [FieldMember(desc = "杞儙璇嗗埆:杞儙鑱氱被鏈灏忕偣浜戞暟")] public int TireTwoLegBlobPtCount = 15; + + [FieldMember(desc = "杞儙璇嗗埆:鍓嶉浄杈惧弬鏁")] public float TireFrontTwoLegBlobDist = 100f; + [FieldMember(desc = "杞儙璇嗗埆:鍓嶉浄杈惧弬鏁")] public float TireFrontTwoLegBlobSize = 200f; + [FieldMember(desc = "杞儙璇嗗埆:鍓嶉浄杈惧弬鏁")] public int TireFrontPadding = 5; + [FieldMember(desc = "杞儙璇嗗埆:鍓嶉浄杈惧弬鏁")] public int TireFrontTwoLegPillarFindingScope = 20; + [FieldMember(desc = "杞儙璇嗗埆:鍓嶉浄杈惧弬鏁")] public int TireFrontTwoLegSgnDir = 1; + [FieldMember(desc = "杞儙璇嗗埆:鍓嶉浄杈惧弬鏁")] public float TireFrontTwoLegCenterChangeX = 0; + [FieldMember(desc = "杞儙璇嗗埆:鍚庨浄杈惧弬鏁")] public float TireBackTwoLegBlobDist = 100f; + [FieldMember(desc = "杞儙璇嗗埆:鍚庨浄杈惧弬鏁")] public float TireBackTwoLegBlobSize = 200f; + [FieldMember(desc = "杞儙璇嗗埆:鍚庨浄杈惧弬鏁")] public int TireBackPadding = 5; + [FieldMember(desc = "杞儙璇嗗埆:鍚庨浄杈惧弬鏁")] public int TireBackTwoLegPillarFindingScope = 20; + [FieldMember(desc = "杞儙璇嗗埆:鍚庨浄杈惧弬鏁")] public int TireBackTwoLegSgnDir = 1; + [FieldMember(desc = "杞儙璇嗗埆:鍚庨浄杈惧弬鏁")] public float TireBackTwoLegCenterChangeX = 0; + + [FieldMember(desc = "鎶卞す鎺у埗pid:Kp")] public float ClampControlKp = 0.1f; + [FieldMember(desc = "鎶卞す鎺у埗pid:Ki")] public float ClampControlKi = 0f; + [FieldMember(desc = "鎶卞す鎺у埗pid:Kd")] public float ClampControlKd = 0f; + [FieldMember(desc = "鎶卞す鎺у埗pid:MaxI")] public float ClampControlMaxI = 0f; + [FieldMember(desc = "鎶卞す鎺у埗pid:Acc")] public float ClampControlSpeedAcc = 1f; + [FieldMember(desc = "鎶卞す鎺у埗pid:Thresh")] public float ClampControlThresh = 0.2f; + [FieldMember(desc = "鎶卞す鎺у埗pid:DeadZone")] public float ClampControlDeadZone = 5f; + [FieldMember(desc = "鎶卞す鏈澶ч熷害")] public float MaxClampSpeed = 1.5f; + + [FieldMember(desc = "鐩寸嚎琛岃蛋璺濈")] public float LineTrackDistance = 1000f; + [FieldMember(desc = "鐩寸嚎琛岃蛋鏈澶ч熷害")] public float LineTrackMaxSpeed = 0.3f; + [FieldMember(desc = "鐩寸嚎琛岃蛋Kp")] public float LineTrackKp = 0.2f; + [FieldMember(desc = "鐩寸嚎琛岃蛋Ki")] public float LineTrackKi = 0f; + [FieldMember(desc = "鐩寸嚎琛岃蛋Kd")] public float LineTrackKd = 0f; + [FieldMember(desc = "鐩寸嚎琛岃蛋DeadZone")] public float LineTrackDeadZone = 50f; + + [FieldMember(desc = "杞儙璺熻釜:鍒囨崲鑷崇洸璧拌窛绂")] public float TireFollowingWalkBlindSwitchingDistance = 1200f; + [FieldMember(desc = "杞儙璺熻釜:璇嗗埆绗竴瀵硅疆鑳庣殑鍒濆璺濈")] public float TireFollowingStage1GuessX = 2000f; + [FieldMember(desc = "杞儙璺熻釜:璇嗗埆绗簩瀵硅疆鑳庣殑鍒濆璺濈")] public float TireFollowingStage2GuessX = 2475f; + [FieldMember(desc = "杞儙璺熻釜:鐩茶蛋鍋滄璺濈")] public float TireFollowingWalkBlindFinishDistance = 10f; + [FieldMember(desc = "杞儙璺熻釜:鍑忛熻窛绂")] public float TireFollowingSlowDistance = 200f; + [FieldMember(desc = "杞儙璺熻釜:鏈澶ч熷害")] public float TireFollowingMaxSpeed = 0.2f; + [FieldMember(desc = "杞儙璺熻釜:鍓嶉浄杈捐瘑鍒矾寰勫亸绉籜")] public float TireFollowingFrontLidarPathTransformationX = 253f; + [FieldMember(desc = "杞儙璺熻釜:鍓嶉浄杈捐瘑鍒矾寰勫亸绉籝")] public float TireFollowingFrontLidarPathTransformationY = 13f; + [FieldMember(desc = "杞儙璺熻釜:鍓嶉浄杈捐瘑鍒矾寰勫亸绉籘h")] public float TireFollowingFrontLidarWalkBlindTh = -1f; + [FieldMember(desc = "杞儙璺熻釜:鍚庨浄杈捐瘑鍒矾寰勫亸绉籜")] public float TireFollowingBackLidarPathTransformationX = 148f; + [FieldMember(desc = "杞儙璺熻釜:鍚庨浄杈捐瘑鍒矾寰勫亸绉籝")] public float TireFollowingBackLidarPathTransformationY = 2f; + [FieldMember(desc = "杞儙璺熻釜:鍚庨浄杈捐瘑鍒矾寰勫亸绉籘h")] public float TireFollowingBackLidarWalkBlindTh = 0f; + [FieldMember(desc = "杞儙璺熻釜:绂昏溅鏃跺悗闆疯揪璇嗗埆璺緞鍋忕ЩX")] public float TireFollowingLeaveCarBackLidarPathTransformationX = 1500f; + [FieldMember(desc = "杞儙璺熻釜:绂昏溅鏃跺垏鎹㈣嚦鐩茶蛋璺濈")] public float TireFollowingLeaveCarWalkBlindSwitchingDistance = 1200f; + + [FieldMember(desc = "杞儙璺熻釜:娴嬭瘯閽昏疆鑳庢暟閲")] public int TireFollowingTireNum = 1; + [FieldMember(desc = "杞儙璺熻釜:杩囪繎璺濈")] public float TireFollowingCloseDistance = 1400; + [FieldMember(desc = "杞儙璺熻釜:璺濈杩囪繎瑙掑害蹇界暐闃堝")] public float TireFollowingAngleIgnoreThr = 0.2f; + [FieldMember(desc = "杞儙璺熻釜:Y鏈澶у钩鍧囨暟")] public int TireFollowingYAverageFrameCount = 5; + + [FieldMember(desc = "缁堢偣璺熻釜:閫熷害")] public float DstTrackerMaxSpeed = 0.3f; + [FieldMember(desc = "杞儙璺熻釜:閲婃斁閿佺偣璺濈")] public float TireFollowingReleaseDistance = 1600; + #endregion + + [FieldMember(desc = "杞儙璺熻釜:瑙掑害璋冩暣kp")] public float TireFollowingThkp = 0.05f; + [FieldMember(desc = "杞儙璺熻釜:瑙掑害璋冩暣ki")] public float TireFollowingThki = 0.01f; + [FieldMember(desc = "杞儙璺熻釜:瑙掑害璋冩暣kd")] public float TireFollowingThkd = 0f; + [FieldMember(desc = "杞儙璺熻釜:瑙掑害璋冩暣SpeedAcc")] public float TireFollowingThSpeedAccPerSec = 1f; + [FieldMember(desc = "杞儙璺熻釜:瑙掑害璋冩暣Thresh")] public float TireFollowingThThresh = 0.1f; + [FieldMember(desc = "杞儙璺熻釜:瑙掑害璋冩暣DeadZone")] public float TireFollowingThDeadZone = 5f; + [FieldMember(desc = "杞儙璺熻釜:瑙掑害璋冩暣MaxI")] public float TireFollowingThMaxI = 0.01f; +} diff --git a/ClumsyPilot/PilotDefinition.cs b/ClumsyPilot/PilotDefinition.cs new file mode 100644 index 0000000..3352b6e --- /dev/null +++ b/ClumsyPilot/PilotDefinition.cs @@ -0,0 +1,2128 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Net.Http; +using System.Numerics; +using System.Threading; +using System.Threading.Tasks; +using ClumsyCore; +using ClumsyCore.DTools; +using ClumsyCore.Interfaces; +using ClumsyCore.Pilot; +using ClumsyCore.Utilities; +using CommonUsage; +using CommonUsage.Chassis; +using CommonUsage.Mathematics; +using FundamentalLib; +using FundamentalLib.Utilities; +using MDCSToolBox.Clumsy.Pilot.MultiWheel; +using Vector = ClumsyCore.Utilities.Vector; + +namespace MultiWheelC; + +public class PilotDefinition : MultiWheelPilotDefinition +{ + public new float CarLength = 1472f; + public new float CarWidth = 948f; + + public override void StandardInit() + { + InitMultiVehicleCoordination(); + } + + #region MultiVehicleCoordination (浠 MDCSToolBox 鍐呰仈鍥 Tutorial) + + [AsLowerIO(desc = "鍚敤锛堟墜鍔級澶氳溅鑱斿姩")] public bool MultiVehicleManualEnabled; + [AsLowerIO(desc = "锛堟墜鍔級澶氳溅鑱斿姩妯″紡")] public int MultiVehicleManualMode; + [FieldMember(desc = "澶氳溅鑱斿姩宸插悓姝")] public bool MultiVehicleAligned; + + [AsLowerIO(desc = "澶氳溅鑱斿姩锛氶仴鎺у櫒Vx姣斾緥")] public float MultiVehicleManualVx; + [AsLowerIO(desc = "澶氳溅鑱斿姩锛氶仴鎺у櫒Vy姣斾緥")] public float MultiVehicleManualVy; + [AsLowerIO(desc = "澶氳溅鑱斿姩锛氶仴鎺у櫒Vth姣斾緥")] public float MultiVehicleManualVth; + [AsLowerIO(desc = "澶氳溅鑱斿姩锛氶仴鎺ф殏鍋")] public bool MultiVehicleHold; + + // ===== Clumsy 渚ц剼鏈/鍔ㄤ綔椹卞姩鐨勬墜鍔ㄧ瓑浠疯緭鍏ワ紙涓嶈蛋 Medulla IO锛屼笉浼氳 IO 鍚屾瑕嗙洊锛===== + // 鎵嬪姩 IO 瀛楁鏄 [AsLowerIO]锛圡edulla鈫扖lumsy锛孧edulla 姣忓懆鏈熷洖鍐欙級锛孋lumsy 渚 MovementTest 鍐欏畠浠細琚鐩栥 + // 鍥犳鎻愪緵杩欑粍鍐呴儴瀛楁锛岃 Clumsy 渚у姩浣滐紙濡 FleetRotateInPlace锛夎兘鍍 FleetRemote 涓鏍烽┍鍔ㄨ溅闃熻仈鍔ㄣ + // ScriptEnabled=浣胯兘锛汳ode 0=甯歌 1=锜硅 2=鍘熷湴鏃嬭浆銆 + // 娉ㄦ剰锛歁edulla 閬ユ帶 IO 鏄綊涓鍖栨憞鏉嗘瘮渚嬶紱鑴氭湰瀛楁淇濇寔鐗╃悊閲忥紝閬垮厤鍔ㄤ綔鍙傛暟鍐嶈 FleetManual* 浜屾缂╂斁銆 + // Mode0: Vx=m/s, Vth=鐩爣鑸佃deg锛汳ode1: Vx=m/s, Vy=锜硅鑸佃deg锛汳ode2: Vth=瑙掗熷害deg/s銆 + [FieldMember(desc = "澶氳溅鑱斿姩锛氳剼鏈┍鍔ㄤ娇鑳")] public bool MultiVehicleScriptEnabled; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳剼鏈┍鍔ㄦā寮")] public int MultiVehicleScriptMode; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳剼鏈┍鍔╒x")] public float MultiVehicleScriptVx; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳剼鏈┍鍔╒y")] public float MultiVehicleScriptVy; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳剼鏈┍鍔╒th")] public float MultiVehicleScriptVth; + + [AsUpperIO(desc = "澶氳溅鑱斿姩锛氳嚜鍔ㄩ┚椹", timeOutReset = true)] public bool MultiVehicleAutoEnabled; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳嚜鍔ㄩ┚椹禫x")] public float MultiVehicleAutoVx; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳嚜鍔ㄩ┚椹禙rontTh")] public float MultiVehicleAutoFrontTh; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳嚜鍔ㄩ┚椹禦earTh")] public float MultiVehicleAutoRearTh; + + public Dictionary MultiVehicleFleet = new(); + public VehicleSyncNotification MultiVehicleNotification; + + // A: 浜掓枼閿佸浐瀹氫负鐙珛 readonly 瀵硅薄锛岀粷涓嶉殢 MultiVehicleFleet 瀛楁琚暣浣撴浛鎹㈣屽け鏁堛 + // 鎵鏈夊 MultiVehicleFleet / _multiVehicleFleetSeen 鐨勮鍐欓兘蹇呴』 lock(FleetLock)銆 + public readonly object FleetLock = new(); + + // C: 鍚 fleet 鎴愬憳鏈杩戜竴娆¤ register/notify 鍒锋柊鐨勬湰鍦版椂鍒伙紙鐢ㄦ湰鍦版椂閽燂紝閬垮厤杩滅鏃堕挓鍋忓樊锛夈 + // 涓昏溅 Tick 鎹鍓旈櫎鎺夌嚎鎴愬憳锛涚紪闃熷氨缁姹傛墍鏈夋垚鍛樻柊椴溿 + private readonly Dictionary _multiVehicleFleetSeen = new(); + + [FieldMember(desc = "澶氳溅鑱斿姩锛氳溅闃熷Э鎬亁")] public float CenterX; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳溅闃熷Э鎬亂")] public float CenterY; + [FieldMember(desc = "澶氳溅鑱斿姩锛氳溅闃熷Э鎬乼h")] public float CenterTh; + + // G: 杞﹂槦涓績鍘熷瓙蹇収銆備笁涓 float 鏃犳硶鏁翠綋鍘熷瓙鍐欙紝鏀逛负鏁翠綋鏂板缓瀵硅薄鍚庡紩鐢ㄨ祴鍊硷紙寮曠敤璧嬪煎師瀛愶級锛 + // 璺緞鎺у埗鍣ㄧ嚎绋嬪彧璇绘渶杩戜竴娆″畬鏁村揩鐓э紝閬垮厤璇诲埌 x 鏂 / y,th 鏃х殑鎾曡缁勫悎銆 + public sealed class FleetCenterSnapshot + { + public float X, Y, Th; + public long Tick; + } + private volatile FleetCenterSnapshot _fleetCenter = new(); + public FleetCenterSnapshot GetFleetCenterSnapshot() => _fleetCenter; + private void PublishFleetCenter(float x, float y, float th) + { + CenterX = x; + CenterY = y; + CenterTh = th; + _fleetCenter = new FleetCenterSnapshot { X = x, Y = y, Th = th, Tick = DateTime.Now.Ticks }; + } + + // B: 璺緞鎺у埗鍣ㄦ渶杩戜竴娆″啓鍏ヨ嚜鍔ㄩ熷害鍛戒护鐨勬椂鍒伙紱瓒呮椂鍗宠涓哄け鏁堬紙璺緞缁撴潫/鏃╅/鍗¢】锛夛紝娓呴浂涓嬪彂銆 + public DateTime MultiVehicleAutoCmdTime = DateTime.MinValue; + // D: 璺緞鎺у埗鍣ㄩ忎紶鐨勭悊鎯宠溅闃熶腑蹇冧綅濮匡紙涓栫晫绯伙級锛岀敱 idealPos/idealAngle 鍐欏叆銆 + public bool MultiVehicleAutoHasIdeal; + public float MultiVehicleAutoIdealX, MultiVehicleAutoIdealY, MultiVehicleAutoIdealTh; + + // F: notify 搴忓垪鍙凤紙涓昏溅鍗曡皟閫掑锛変笌浠庤溅宸插簲鐢ㄧ殑鏈澶у簭鍒楀彿锛堜涪寮冧贡搴忔棫鍖咃級銆 + private long _multiVehicleNotifySeq; + private long _multiVehicleAppliedSeq = -1; + + [AsLowerIO(desc = "杞﹀彿")] public int CarNum = 1; + [FieldMember(desc = "澶氳溅鑱斿姩锛氬師鍦版棆杞湰杞﹁埖杞凡瀵归綈")] + public bool MultiVehicleRotateWheelsReady = true; + [FieldMember(desc = "澶氳溅鑱斿姩锛氬師鍦版棆杞暣闃熻埖杞凡瀵归綈")] + public bool MultiVehicleRotateFleetReady = true; + + #region 澶硅噦鍙橀噺 + [AsUpperIO(desc = "宸﹀す鑷備笅鍙戦熷害")] public float SpeedLeftArm; + + [AsUpperIO(desc = "鍙冲す鑷備笅鍙戦熷害")] public float SpeedRightArm; + + [AsLowerIO(desc = "宸﹀す鑷傚疄闄呬綅缃")] public float ActualPosLeftArm; + + [AsLowerIO(desc = "鍙冲す鑷傚疄闄呬綅缃")] public float ActualPosRightArm; + + [AsUpperIO(desc = "澶硅噦涓嶅悓姝ユ姤璀")] public bool ClampOutOfSync = false; + #endregion + + [AsLowerIO(desc = "宸﹀墠宸﹁疆瀹為檯浣嶇疆")] public float LFLActualPos; + [AsLowerIO(desc = "宸﹀墠鍙宠疆瀹為檯浣嶇疆")] public float LFRActualPos; + [AsLowerIO(desc = "鍙冲墠宸﹁疆瀹為檯浣嶇疆")] public float RFLActualPos; + [AsLowerIO(desc = "鍙冲墠鍙宠疆瀹為檯浣嶇疆")] public float RFRActualPos; + [AsLowerIO(desc = "宸﹀悗宸﹁疆瀹為檯浣嶇疆")] public float LRLActualPos; + [AsLowerIO(desc = "宸﹀悗鍙宠疆瀹為檯浣嶇疆")] public float LRRActualPos; + [AsLowerIO(desc = "鍙冲悗宸﹁疆瀹為檯浣嶇疆")] public float RRLActualPos; + [AsLowerIO(desc = "鍙冲悗鍙宠疆瀹為檯浣嶇疆")] public float RRRActualPos; + + [AsLowerIO(desc = "宸﹀す鑷備綆闄愪綅")] public float LeftArmLowerPos; + [AsLowerIO(desc = "宸﹀す鑷傞珮闄愪綅")] public float LeftArmUpperPos; + [AsLowerIO(desc = "鍙冲す鑷備綆闄愪綅")] public float RightArmLowerPos; + [AsLowerIO(desc = "鍙冲す鑷傞珮闄愪綅")] public float RightArmUpperPos; + + [AsUpperIO(desc = "浠嶤寰椹卞姩鍣ㄤ笅浣胯兘")] public bool DisableFromC = false; + [AsUpperIO(desc = "浠嶤涓婂浣")] public bool ResetFromC = false; + [AsLowerIO(desc = "椹卞姩杞娇鑳界姸鎬")] public bool WheelAbleState = true; + + private float _multiVehicleAccumulateTh; + private DateTime _multiVehicleLastThTime = DateTime.Now; + private readonly object _multiVehicleNotificationLock = new(); + private DateTime _multiVehicleLastNotifyTime = DateTime.MinValue; + private bool _multiVehicleSyncInitialized; + private bool _multiVehicleWasActive; + private bool _multiVehicleMotionFeasible = true; + private string _multiVehicleMotionInfeasibleReason = ""; + private DateTime _multiVehicleStopLastLog = DateTime.MinValue; + private bool _multiVehicleRotateModeActive; + private float _multiVehicleRotateDirectionHint = 1f; + private string _multiVehicleRotateAlignDetail = ""; + private DateTime _multiVehicleRotateAlignLastLog = DateTime.MinValue; + private const float DefaultRotateCompTangentFrac = 0.10f; + + private struct RotateControlParams + { + public float ActiveOmega; + public float CompXyFac; + public float CompXyIFac; + public float CompXyMax; + public float CompThFac; + public float CompThIFac; + public float CompThMax; + public float CompTangentFrac; + public float StartWheelAlignDeg; + public float ActiveWheelAlignDeg; + } + + // 璇婃柇鏃ュ織锛氳妭娴佽鏃 + 鏈杩戜竴娆℃娴嬪嚑浣曪紙涓績/鏈濆悜/璺濈锛夛紝鐢ㄤ簬瀹氫綅鍓х儓杩愬姩鏉ユ簮 + private DateTime _mvDbgLastLog = DateTime.MinValue; + private float _mvLastDetCenterX, _mvLastDetCenterY, _mvLastDetDir, _mvLastDetDist; + // 鍘熷湴鏃嬭浆(mode2)瀹為檯鍙犲姞鐨勮溅浣撶郴绾犲亸鏃嬮噺(mm/s, mm/s, deg/s)锛屼粎鐢ㄤ簬璇婃柇鏃ュ織銆 + private float _mvRotCompVx, _mvRotCompVy, _mvRotCompOmega; + private DateTime _mvRotateCompLimitLastLog = DateTime.MinValue; + private bool _mvRotateCenterDriftActive; + private float _mvRotateCenterStartX, _mvRotateCenterStartY, _mvRotateCenterStartTh, _mvRotateCenterMaxDrift; + private DateTime _mvRotateCenterLastLog = DateTime.MinValue; + // 鍘熷湴鏃嬭浆绾犲亸 PI 鎺у埗鍣ㄧ殑绉垎绱姞鍣(mm路s, mm路s, deg路s)涓庝笂娆¤绠楁椂鍒汇 + private float _rotIntegX, _rotIntegY, _rotIntegTh; + private float _rotOmegaPeak; // 鏈鏃嬭浆杩囩▼涓娴嬪埌鐨勬寚浠よ閫熷害宄板(deg/s)锛岀敤浜庣籂鍋忛殢杞熺缉鏀 + private DateTime _rotPiLastTime = DateTime.MinValue; + + // 鍘熷湴鏃嬭浆鈥滀袱杞﹀疄闄 sim 浣嶅Э鈥濊瘖鏂噰鏍风姸鎬侊紙浠呬富杞︼紝閫氳繃 Playground WebAPI 璇诲彇锛夈 + private DateTime _rotPoseLastLog = DateTime.MinValue; + private DateTime _rotPosePrevTime = DateTime.MinValue; + private float _rotPosePrevYaw1, _rotPosePrevYaw2; + private bool _rotPoseEpisode; // 鏈鏃嬭浆鐗囨鏄惁宸叉崟鑾峰弬鑰冮噺 + private float _rotPoseMid0X, _rotPoseMid0Y; // 璧疯浆鐬棿杞﹂槦鍑犱綍涓績(涓栫晫绯)锛岀敤浜庡害閲忔暣浣撳钩绉绘紓绉 + + // 鍐欑洏璇婃柇鏃ュ織锛圕lumsy 渚э級銆傛敼鐢 DLog 钀界洏锛氬悓涓 topic 鐨勬棩蹇椾細褰掑埌浠 topic 鍛藉悕鐨勬枃浠跺す锛 + // 鐢 DLog 缁熶竴绠$悊钀界偣/婊氬姩锛屾棤闇鑷缁存姢鏂囦欢鍙ユ焺涓 session 娓呯┖閫昏緫銆 + private DateTime _mvDiskLastLog = DateTime.MinValue; + private void FleetDiag(string msg) + { + DLog.Log($"car{CarNum} {msg}", "FleetDiagClumsy"); + } + + // 浜掕瘑鍒細閭昏溅涓よ吙妫娴嬬殑婊戝姩绐楀彛锛堟渶杩 1s锛屾渶澶 10 甯э級锛岀敤浜庡钩婊戞姈鍔 + private DateTime _mvRemoteInputLastLog = DateTime.MinValue; + private DateTime _mvRemoteDecisionLastLog = DateTime.MinValue; + private DateTime _mvNotifyApplyLastLog = DateTime.MinValue; + private DateTime _mvRotateWheelOutputLastLog = DateTime.MinValue; + + private void LogMultiVehicleRemoteInput(bool isMaster, bool scriptOn, bool manualEnabled, bool autoEnabled, + int manualMode, float manualVx, float manualVy, float manualVth) + { + var now = DateTime.Now; + if ((now - _mvRemoteInputLastLog).TotalMilliseconds < 200) return; + _mvRemoteInputLastLog = now; + + int fleetCnt; + lock (FleetLock) fleetCnt = MultiVehicleFleet.Count; + var notifAgeMs = _multiVehicleLastNotifyTime == DateTime.MinValue + ? -1 + : (now - _multiVehicleLastNotifyTime).TotalMilliseconds; + var notifFresh = notifAgeMs >= 0 && notifAgeMs < Math.Max(300, Conf.MultiVehicleSyncInterval * 5); + + DLog.Log( + $"INPUT master={isMaster} endpoint={Conf.MultiVehicleMasterEndpoint} selfEndpoint={Conf.MultiVehicleSelfEndpoint} car={CarNum} " + + $"rawEn={MultiVehicleManualEnabled} rawHold={MultiVehicleHold} rawMode={MultiVehicleManualMode} rawVx={MultiVehicleManualVx:0.000} rawVy={MultiVehicleManualVy:0.000} rawVth={MultiVehicleManualVth:0.000} " + + $"scriptOn={scriptOn} effEn={manualEnabled} effMode={manualMode} effVx={manualVx:0.000} effVy={manualVy:0.000} effVth={manualVth:0.000} " + + $"auto={autoEnabled} notifFresh={notifFresh} notifAgeMs={notifAgeMs:0} fleetCnt={fleetCnt}/{Conf.MultiVehicleFleetNum}", + "MultiVehicleRemoteDbg"); + } + + private void LogMultiVehicleRemoteDecision(string msg, bool force = false) + { + var now = DateTime.Now; + if (!force && (now - _mvRemoteDecisionLastLog).TotalMilliseconds < 200) return; + _mvRemoteDecisionLastLog = now; + DLog.Log($"car{CarNum} {msg}", "MultiVehicleRemoteDbg"); + } + + private void LogRotateWheelOutputs(MultiWheelChassis chassis, string phase, float omega, bool force = false) + { + var now = DateTime.Now; + if (!force && (now - _mvRotateWheelOutputLastLog).TotalMilliseconds < 300) return; + _mvRotateWheelOutputLastLog = now; + +#pragma warning disable CS0612, CS0618 + var wheels = chassis.GetSteerWheels(); +#pragma warning restore CS0612, CS0618 + var parts = new List(); + for (var i = 0; i < wheels.Count; i++) + { + var wheel = wheels[i]; + if (wheel is DiffSteerWheel diff) + { + parts.Add( + $"w{i}:tgt={diff.GetSendAngle():0.0} read={diff.ReadAngle():0.0} " + + $"L={diff.GetLeftSendSpeed():0.000} R={diff.GetRightSendSpeed():0.000}"); + } + else + { + parts.Add( + $"w{i}:tgt={wheel.GetSendAngle():0.0} read={wheel.ReadAngle():0.0} " + + $"v={wheel.GetSendSpeed():0.000}"); + } + } + + DLog.Log( + $"car{CarNum} phase={phase} omega={omega:0.000} " + string.Join(" | ", parts), + "MultiVehicleRotateWheelOutput"); + } + + private void SetMultiVehicleMotionFeasible(bool feasible, string reason = "") + { + _multiVehicleMotionFeasible = feasible; + _multiVehicleMotionInfeasibleReason = feasible ? "" : (reason ?? ""); + } + + private static float ClampFloat(float value, float min, float max) + { + if (value < min) return min; + if (value > max) return max; + return value; + } + + private void UpdateMultiVehicleRotateModeState(int fleetMode, bool active, float requestedOmega, + RotateControlParams rotateParams) + { + var rotateActive = active && fleetMode == 2; + if (!rotateActive) + { + _multiVehicleRotateModeActive = false; + if (!active) + { + MultiVehicleRotateWheelsReady = true; + _multiVehicleRotateAlignDetail = ""; + } + MultiVehicleRotateFleetReady = true; + _multiVehicleRotateDirectionHint = 1f; + return; + } + + if (!_multiVehicleRotateModeActive) + { + MultiVehicleRotateWheelsReady = false; + MultiVehicleRotateFleetReady = false; + _multiVehicleRotateAlignDetail = "rotate mode just entered"; + } + + _multiVehicleRotateModeActive = true; + if (Math.Abs(requestedOmega) > rotateParams.ActiveOmega) + _multiVehicleRotateDirectionHint = Math.Sign(requestedOmega); + } + + private bool PrepareMultiVehicleRotateWheels(MultiWheelChassis chassis, float requestedOmega, + RotateControlParams rotateParams, + float localCompensateX = 0f, float localCompensateY = 0f, float localCompensateTh = 0f, + bool rampStop = true) + { + var hint = Math.Abs(requestedOmega) > rotateParams.ActiveOmega + ? Math.Sign(requestedOmega) + : Math.Sign(_multiVehicleRotateDirectionHint); + if (hint == 0) hint = 1; + _multiVehicleRotateDirectionHint = hint; + + // Reuse SendRotateMotion's decomposition and angle-limit checks, but keep wheel speed at zero. + if (rampStop) + chassis.RampStop(); + var alignOmega = Math.Abs(requestedOmega) > rotateParams.ActiveOmega + ? requestedOmega + : 0.01f * hint; + var motionOk = chassis.SendRotateMotion(alignOmega, TimeSpan.Zero, + localCompensateX: localCompensateX, localCompensateY: localCompensateY, + localCompensateTh: localCompensateTh); + var wheelAligned = TryCheckRotateWheelAlignment(chassis, rotateParams.StartWheelAlignDeg, + out var alignDetail); + var aligned = motionOk && wheelAligned; + if (!motionOk) + alignDetail = string.IsNullOrWhiteSpace(chassis.LastMotionDecomposeFailureReason) + ? alignDetail + : chassis.LastMotionDecomposeFailureReason; + + MultiVehicleRotateWheelsReady = aligned; + _multiVehicleRotateAlignDetail = alignDetail; + + var now = DateTime.Now; + if ((now - _multiVehicleRotateAlignLastLog).TotalMilliseconds >= 200) + { + _multiVehicleRotateAlignLastLog = now; + DLog.Log( + $"car{CarNum} ROTATE_PREPARE omegaReq={requestedOmega:0.000} alignOmega={alignOmega:0.000} " + + $"hint={hint} comp=({localCompensateX:0.0},{localCompensateY:0.0},{localCompensateTh:0.000}) " + + $"rampStop={rampStop} startTol={rotateParams.StartWheelAlignDeg:0.0} ok={motionOk} aligned={aligned} detail={alignDetail} " + + $"chassisReason={chassis.LastMotionDecomposeFailureReason}", + "MultiVehicleRemoteDbg"); + FleetDiag( + $"ROTATE_PREPARE omegaReq={requestedOmega:0.000} alignOmega={alignOmega:0.000} hint={hint} " + + $"comp=({localCompensateX:0.0},{localCompensateY:0.0},{localCompensateTh:0.000}) " + + $"startTol={rotateParams.StartWheelAlignDeg:0.0} ok={motionOk} aligned={aligned} detail={alignDetail}"); + } + + Hedingben.ToastText( + aligned ? "杞﹂槦鍘熷湴鏃嬭浆鑸佃疆宸插榻" : $"杞﹂槦鍘熷湴鏃嬭浆鑸佃疆棰勫榻愪腑 {alignDetail}", + $"MultiVehicle{CarNum}-rotate-align"); + + return motionOk; + } + + private static bool TryCheckRotateWheelAlignment(MultiWheelChassis chassis, float toleranceDeg, out string detail) + { + try + { +#pragma warning disable CS0612, CS0618 + var wheels = chassis.GetSteerWheels(); +#pragma warning restore CS0612, CS0618 + var maxDth = 0f; + var parts = new List(); + for (var i = 0; i < wheels.Count; i++) + { + var sw = wheels[i]; + var dth = Math.Abs(CommonMath.ThDiff(sw.ReadAngle(), sw.GetSendAngle())); + maxDth = Math.Max(maxDth, dth); + parts.Add($"w{i}:{dth:0.0}"); + } + + detail = $"maxDth={maxDth:0.0} tol={toleranceDeg:0.0} {string.Join(",", parts)}"; + return maxDth <= toleranceDeg; + } + catch (Exception e) + { + detail = $"read alignment failed: {e.Message}"; + return chassis.LastRotateAligned; + } + } + + private void LogMultiVehicleStop(string reason, bool force = false) + { + var now = DateTime.Now; + if (!force && (now - _multiVehicleStopLastLog).TotalMilliseconds < 500) return; + _multiVehicleStopLastLog = now; + var msg = $"FLEET_STOP car={CarNum} reason={reason}"; + DLog.Log(msg, "MultiVehicleSafety"); + FleetDiag(msg); + Hedingben.ToastText($"Fleet stop: {reason}", $"MultiVehicle{CarNum}-stop"); + } + + private readonly object _neighborDetectLock = new(); + private readonly List<(DateTime Time, Vector2 Src, Vector2 Dst)> _neighborDetects = new(); + + // 浜掕瘑鍒細涓婁竴甯ф娴嬩腑蹇冿紝鐢ㄤ綔涓嬩竴甯х寽娴嬶紙闂幆璺熻釜锛夛紝涓庛屽鑸佃疆-2鑵挎娴嬨峂ovementTest 涓鑷 + private Vector2 _neighborGuess; + private bool _neighborGuessValid; + private DateTime _neighborGuessTime = DateTime.MinValue; + + /// + /// 浜掕瘑鍒挬瀛愶細鐢ㄥ崟绾块浄杈捐瘑鍒偦杞︾殑涓よ吙/涓よ疆锛屾崲绠楁垚鏈溅浣撳潗鏍囩郴涓嬬浉瀵光滅悊搴斿榻愬弬鑰冪偣鈥濈殑鍋忓樊銆 + /// 鍏ㄥ榻愭椂杩斿洖 (true, 0, 0, 0)锛涙湭妫娴嬪埌鏃惰繑鍥 (false, ...)銆 + /// detectDistance = 缂栭槦杞﹂棿璺 - 妫娴嬩腑蹇冨亸绉伙紙鍗抽偦杞︽娴嬩腑蹇冨埌鏈溅鍘熺偣鐨勬爣绉拌窛绂伙紝鎭掍负姝e硷紝鏂瑰悜鐢 TwoLegGuessX 绗﹀彿鍐冲畾锛夈 + /// + private (bool Valid, float Dx, float Dy, float Dth, float NeighborDist) DetectNeighborBias(float detectDistance) + { + // 妫娴嬬寽娴嬬偣涓庛屽鑸佃疆-2鑵挎娴嬨峂ovementTest 瀹屽叏涓鑷达細棣栧抚 / 璺熶涪鍥炶惤閮界敤 Conf.TwoLegGuessX + // 锛堟柟鍚戜笌璺濈閮界敱瀹冧竴澶勫喅瀹氾級锛岃窡鍒板悗鐢ㄤ笂涓甯т腑蹇冮棴鐜窡韪 + // detectDistance 鍙敤浜庤绠楃紪闃熷榻愬亸宸/闂磋窛锛屼笉鍙備笌鈥滃幓鍝噷鎵鹃偦杞︹濓紝閬垮厤鐚滄祴鐐瑰亸绂诲鑷 ROI 妗嗘紡鎺夌湡瀹為偦杞︺ + var nominal = new Vector2(Conf.TwoLegGuessX, 0f); + + var now = DateTime.Now; + // 闂幆璺熻釜锛1s 鍐呮鍒拌繃灏辩敤涓婁竴甯т腑蹇冧綔鐚滄祴锛屼娇缁胯壊 ROI 妗嗘敹鏁涘埌鐪熷疄閭昏溅锛堜笌 MovementTest 琛屼负涓鑷达級锛 + // 璺熶涪瓒呮椂鍒欏洖钀藉埌缂栭槦鏍囩О浣嶇疆锛岄伩鍏嶆婕傝蛋銆 + var guess = (_neighborGuessValid && (now - _neighborGuessTime).TotalSeconds < 1) ? _neighborGuess : nominal; + var seg = TwoLegDetect.Detect(Conf.TwoLegLidarName, guess.X, TwoLegDetect.SetFilters(guess.X, guess.Y)); + + Vector2 avgSrc, avgDst; + lock (_neighborDetectLock) + { + if (seg != null) + { + _neighborDetects.Add((now, seg.Src, seg.Dst)); + _neighborGuess = (seg.Src + seg.Dst) / 2f; + _neighborGuessValid = true; + _neighborGuessTime = now; + } + _neighborDetects.RemoveAll(r => (now - r.Time).TotalSeconds > 1); + + var cnt = _neighborDetects.Count; + if (cnt == 0) + { + _neighborGuessValid = false; + Hedingben.ToastText($"閭昏溅鏈鍒 (guess x:{guess.X:F0} y:{guess.Y:F0})", $"MultiVehicle{CarNum}-detect"); + return (false, 0f, 0f, 0f, 0f); + } + if (cnt > 10) _neighborDetects.RemoveRange(0, cnt - 10); + + avgSrc = new Vector2(_neighborDetects.Average(r => r.Src.X), _neighborDetects.Average(r => r.Src.Y)); + avgDst = new Vector2(_neighborDetects.Average(r => r.Dst.X), _neighborDetects.Average(r => r.Dst.Y)); + } + + // 涓よ吙杩炵嚎涓偣涓洪偦杞︽娴嬩腑蹇冿紱杩炵嚎鐨勫瀭绾挎柟鍚戝嵆閭昏溅鏈濆悜 + var dirVec = avgDst - avgSrc; + var center = (avgSrc + avgDst) / 2f; + var dir = (float)LessMath.RoundTh(Math.Atan2(dirVec.Y, dirVec.X) / Math.PI * 180 + 90); + + // 浠庢娴嬩腑蹇冩部閭昏溅鏈濆悜澶栨帹 detectDistance锛屽緱鍒扳滄湰杞︾悊搴旀墍鍦ㄧ殑鍙傝冪偣鈥濓紙杞︿綋绯伙級 + var target = LessMath.Transform2D(center, dir, detectDistance, 0); + + var dx = target.X; + var dy = target.Y; + var dth = (float)LessMath.ThDiff(dir, 0); + var neighborDist = center.Length(); + + _mvLastDetCenterX = center.X; + _mvLastDetCenterY = center.Y; + _mvLastDetDir = dir; + _mvLastDetDist = neighborDist; + + var painter = UI.GetPainter("MultiVehicleDetectBias", false); + painter.Clear(); + painter.DrawLine(Color.DeepPink, center, target, width: 2); + painter.DrawText(Color.Yellow, $"dx:{dx:F0} dy:{dy:F0} dth:{dth:F2}", center.X, center.Y); + + Hedingben.ToastText( + $"[鑱斿姩妫娴媇 lidar:{Conf.TwoLegLidarName} guess x:{guess.X:F0} y:{guess.Y:F0} | " + + $"涓績 x:{center.X:F0} y:{center.Y:F0} dir:{dir:F1} dist:{neighborDist:F0} | 鍋忓樊 dx:{dx:F0} dy:{dy:F0} dth:{dth:F2}", + $"MultiVehicle{CarNum}-detect"); + + return (true, dx, dy, dth, neighborDist); + } + + private void InitMultiVehicleCoordination() + { + if (_multiVehicleSyncInitialized) return; + _multiVehicleSyncInitialized = true; + + var hc = new HttpClient { Timeout = TimeSpan.FromSeconds(2) }; + + PicoHttpServer.AddPostByteHandler("/multi-vehicle-register-bin", body => + { + try + { + var (carNum, info) = VehicleSyncBinaryCodec.DecodeRegister(body); + ApplyVehicleSyncRegister(carNum, info); + return "ok"; + } + catch (Exception e) + { + DLog.Log($"/multi-vehicle-register-bin error: {e.FormatEx()}", "MultiVehicle"); + throw; + } + }); + + PicoHttpServer.AddPostByteHandler("/multi-vehicle-notify-bin", body => + { + try + { + var notification = VehicleSyncBinaryCodec.DecodeNotification(body); + return ApplyVehicleSyncNotification(notification); + } + catch (Exception e) + { + DLog.Log($"/multi-vehicle-notify-bin error: {e.FormatEx()}", "MultiVehicle"); + throw; + } + }); + + DLog.Log("MultiVehicle coordination initialized, starting loop thread", "MultiVehicle"); + Console.WriteLine("[MultiVehicle] coordination initialized, starting loop thread"); + new Thread(() => MultiVehicleLoop(hc)) { Name = "MultiVehicle", IsBackground = true }.Start(); + } + + private void ApplyVehicleSyncRegister(int carNum, VehicleSyncInfo info) + { + lock (FleetLock) + { + MultiVehicleFleet[carNum] = info; + _multiVehicleFleetSeen[carNum] = DateTime.Now; + } + } + + private string ApplyVehicleSyncNotification(VehicleSyncNotification notification) + { + // Keep the same stale-packet semantics as the previous transport. + if (notification.Seq != 0 && notification.Seq <= _multiVehicleAppliedSeq && + notification.Seq > _multiVehicleAppliedSeq - 100) + return "stale"; + _multiVehicleAppliedSeq = notification.Seq; + + MultiVehicleAligned = notification.Aligned; + lock (FleetLock) + { + MultiVehicleFleet = notification.Fleet ?? new Dictionary(); + var nowSeen = DateTime.Now; + foreach (var key in MultiVehicleFleet.Keys) + _multiVehicleFleetSeen[key] = nowSeen; + } + + lock (_multiVehicleNotificationLock) + { + MultiVehicleNotification = notification; + _multiVehicleLastNotifyTime = DateTime.Now; + } + + var applyNow = DateTime.Now; + if ((applyNow - _mvNotifyApplyLastLog).TotalMilliseconds >= 200) + { + _mvNotifyApplyLastLog = applyNow; + DLog.Log( + $"car{CarNum} NOTIFY_APPLY seq={notification.Seq} mode={notification.Mode} " + + $"omega={notification.FleetOmega:0.000} reqOmega={notification.RequestedFleetOmega:0.000} " + + $"released={notification.FleetMotionReleased} stop={notification.FleetStopActive} " + + $"reason={notification.FleetStopReason} useDetourCorr={notification.UseDetourCorrection} " + + $"rotParam(valid={notification.RotateParamsValid} xyP={notification.RotateCompXyFac:0.###} " + + $"xyI={notification.RotateCompXyIFac:0.###} xyMax={notification.RotateCompXyMax:0.#} " + + $"thP={notification.RotateCompThFac:0.###} thI={notification.RotateCompThIFac:0.###} " + + $"thMax={notification.RotateCompThMax:0.#} frac={notification.RotateCompTangentFrac:0.###} " + + $"startTol={notification.RotateStartWheelAlignDeg:0.#} activeTol={notification.RotateActiveWheelAlignDeg:0.#})", + "MultiVehicleRemoteDbg"); + } + + return "ok"; + } + + private void MultiVehicleLoop(HttpClient hc) + { + var carLength = CarLength; + var carWidth = CarWidth; + var contour = new List + { + new(carLength / 2f, carWidth / 2f), + new(-carLength / 2f, carWidth / 2f), + new(-carLength / 2f, -carWidth / 2f), + new(carLength / 2f, -carWidth / 2f), + }; + var chassis = (MultiWheelChassis)Chassis; + var sendMotionPainter = UI.GetPainter("MultiWheelChassis-SendMotionVis", false); + chassis.SendMotionVisualizer = new Visualizer + { + LineAction = (color, src, dst, startArrow, endArrow, width) => + sendMotionPainter.DrawLine(color, src, dst, startArrow, endArrow, width), + TextAction = (color, str, pos) => sendMotionPainter.DrawText(color, str, pos), + Clear = () => sendMotionPainter.Clear() + }; + + DLog.Log("MultiVehicleLoop thread running", "MultiVehicle"); + Console.WriteLine("[MultiVehicle] loop thread running"); + var loopCount = 0L; + while (true) + { + try + { + TickMultiVehicle(hc, chassis, contour, sendMotionPainter); + } + catch (Exception e) + { + DLog.Log($"MultiVehicle loop error: {e.FormatEx()}", "MultiVehicle"); + } + + // 姣 ~5s 鎵撲竴鏉″績璺筹紝纭寰幆纭疄鍦ㄨ窇锛堢敤浜庡尯鍒嗏滃惊鐜病璺戔濅笌鈥滃啓鐩樺け璐モ濓級 + if (loopCount++ % Math.Max(1, 5000 / Math.Max(1, Conf.MultiVehicleSyncInterval)) == 0) + DLog.Log($"MultiVehicleLoop heartbeat #{loopCount}", "MultiVehicle"); + + Thread.Sleep(Conf.MultiVehicleSyncInterval); + } + } + + private void TickMultiVehicle(HttpClient hc, MultiWheelChassis chassis, List contour, Painter sendMotionPainter) + { + var isMaster = IsMultiVehicleMaster(); + var autoEnabled = false; + // 鎵嬪姩绛変环杈撳叆 = Medulla 閬ユ帶(IO) 鎴 Clumsy 鑴氭湰/鍔ㄤ綔椹卞姩锛堜簩鑰呮嫨涓锛岃剼鏈紭鍏堬級銆 + var scriptOn = MultiVehicleScriptEnabled; + var manualEnabled = MultiVehicleManualEnabled || scriptOn; + // 涓昏溅瀹為檯鐢熸晥鐨勬墜鍔ㄦā寮忎笌閫熷害锛氳剼鏈娇鑳芥椂鍙栬剼鏈瓧娈碉紝鍚﹀垯鍙 Medulla 鎵嬪姩 IO 瀛楁銆 + var manualMode = scriptOn ? MultiVehicleScriptMode : MultiVehicleManualMode; + var manualVx = scriptOn ? MultiVehicleScriptVx : MultiVehicleManualVx; + var manualVy = scriptOn ? MultiVehicleScriptVy : MultiVehicleManualVy; + var manualVth = scriptOn ? MultiVehicleScriptVth : MultiVehicleManualVth; + var manualHold = !scriptOn && MultiVehicleHold; + VehicleSyncNotification activeNotification = null; + + if (isMaster) + autoEnabled = MultiVehicleAutoEnabled; + else + { + // 浠庤溅锛氳嚜鍔/鎵嬪姩鑱斿姩鍧囧彲鐢变富杞﹀箍鎾В閿侊紙鏃犻渶鍚勮嚜鍐嶆嫧寮鍏筹級銆 + // 浠呭湪 notification 鏂伴矞鏃惰璐︼紝涓昏溅鍋滃彂鍚庤秴鏃跺嵆鑷姩鍋滆溅锛岄伩鍏嶇敤鏃ф寚浠よ窇椋炪 + lock (_multiVehicleNotificationLock) + { + var fresh = (DateTime.Now - _multiVehicleLastNotifyTime).TotalMilliseconds < + Math.Max(300, Conf.MultiVehicleSyncInterval * 5); + if (fresh && MultiVehicleNotification != null) + { + activeNotification = MultiVehicleNotification; + autoEnabled = MultiVehicleNotification.AutoEnabled; + manualEnabled = manualEnabled || MultiVehicleNotification.ManualEnabled; + } + } + } + var rotateParams = BuildRotateControlParams(isMaster ? null : activeNotification); + + // 鍏ュ彛璇婃柇锛堣妭娴 ~300ms锛夛細璁板綍浠 Medulla 鏀跺埌鐨勫師濮 IO 鍊间笌闂ㄦ帶鍒ゅ畾锛 + // 鐢ㄤ簬纭閬ユ帶鎸囦护鏄惁鐪熺殑浼犲埌浜 Clumsy锛屼互鍙婁负浣曟彁鍓 return銆 + LogMultiVehicleRemoteInput(isMaster, scriptOn, manualEnabled, autoEnabled, + manualMode, manualVx, manualVy, manualVth); + + if ((DateTime.Now - _mvDiskLastLog).TotalMilliseconds >= 300) + { + _mvDiskLastLog = DateTime.Now; + int fleetCnt; + lock (FleetLock) fleetCnt = MultiVehicleFleet.Count; + var notifFresh = (DateTime.Now - _multiVehicleLastNotifyTime).TotalMilliseconds < + Math.Max(300, Conf.MultiVehicleSyncInterval * 5); + FleetDiag( + $"ENTRY master={isMaster} | IO: ManualEn={MultiVehicleManualEnabled} Mode={MultiVehicleManualMode} " + + $"Hold={MultiVehicleHold} Vx={MultiVehicleManualVx:0.000} Vy={MultiVehicleManualVy:0.000} Vth={MultiVehicleManualVth:0.0} AutoEn(IO)={MultiVehicleAutoEnabled} " + + $"| SCRIPT en={MultiVehicleScriptEnabled} mode={MultiVehicleScriptMode} Vx={MultiVehicleScriptVx:0.000} Vy={MultiVehicleScriptVy:0.000} Vth={MultiVehicleScriptVth:0.0} " + + $"| gate: manualEnabled={manualEnabled} autoEnabled={autoEnabled} notifFresh={notifFresh} " + + $"notifManualEn={(MultiVehicleNotification != null ? MultiVehicleNotification.ManualEnabled.ToString() : "null")} " + + $"fleetCnt={fleetCnt}/{Conf.MultiVehicleFleetNum} useDetect={Conf.MultiVehicleUseDetect} " + + $"useDetour={Conf.MultiVehicleSyncUseDetour} manualDetour={Conf.MultiVehicleManualUseDetourCorrection}"); + } + + if (!manualEnabled && !autoEnabled) + { + if (_multiVehicleWasActive) + { + chassis.RampStop(); + SetMultiVehicleMotionFeasible(true); + LogMultiVehicleStop("fleet control disabled; ramp stop previous fleet command", true); + } + _multiVehicleWasActive = false; + UpdateMultiVehicleRotateModeState(0, false, 0, rotateParams); + ResetMultiVehicleRotateCenterDrift(); + LogMultiVehicleRemoteDecision( + $"RETURN_IDLE master={isMaster} rawEn={MultiVehicleManualEnabled} scriptOn={scriptOn} auto={autoEnabled} " + + $"rawHold={MultiVehicleHold} rawMode={MultiVehicleManualMode} rawVx={MultiVehicleManualVx:0.000} rawVy={MultiVehicleManualVy:0.000} rawVth={MultiVehicleManualVth:0.000}"); + UI.GetPainter("MultiVehicleFleet-vis", false).Clear(); + sendMotionPainter.Clear(); + lock (FleetLock) + { + MultiVehicleFleet.Clear(); + _multiVehicleFleetSeen.Clear(); + } + MultiVehicleAutoEnabled = false; + MultiVehicleAutoHasIdeal = false; + _multiVehicleAppliedSeq = -1; + _multiVehicleAccumulateTh = 0f; + _multiVehicleLastThTime = DateTime.Now; + + if (!isMaster) + FireAndForgetRegister(hc, BuildSelfInfo(false, false, 0, 0, 0, 0, 0, 0, false)); + + return; + } + _multiVehicleWasActive = true; + + // 鑷姩妯″紡鏁撮槦濮挎佷緷璧 Detour 鍏ㄥ眬瀹氫綅锛堜笌 MultiVehicleSyncUseDetour 鏃犲叧锛夛細瑕佹眰缂栭槦鑷冲皯涓鍙拌溅鏈夊畾浣嶃 + if (isMaster && autoEnabled && !manualEnabled && !FleetHasPosAvailable()) + { + MultiVehicleAutoEnabled = false; + chassis.RampStop(); + SetMultiVehicleMotionFeasible(true); + LogMultiVehicleStop("auto mode requires at least one Detour-positioned fleet member", true); + Hedingben.ToastText("鑷姩澶氳溅鑱斿姩闇瑕佽嚦灏戜竴鍙拌溅鏈 Detour 瀹氫綅", "MultiVehicle-auto-gate"); + return; + } + + // 涓ょ被鐢ㄩ旇В鑰︼紙鍏抽敭璇箟锛夛細 + // - useDetourCorrection (= MultiVehicleSyncUseDetour)锛氭槸鍚︾敤 SLAM 浣嶅Э鍋"杞﹂槦鍐呭Э鎬佺籂姝"(POS 琛ュ伩)銆 + // false 浠呰〃绀"瀹氫綅涓嶅弬涓庤溅闃熷唴濮挎佺籂姝"锛屼笉褰卞搷涓嬮潰鏁撮槦濮挎佽绠椼 + // - slamRead锛氭湰杞︽湰杞槸鍚﹁鍙 Detour 鍏ㄥ眬浣嶅Э銆"鏁翠釜杞﹂槦濮挎佺殑璁$畻"(涓昏溅鍙嶆帹/骞挎挱杞﹂槦涓績銆 + // SLAM 闂磋窛銆佽嚜鍔ㄦā寮忓畨鍏ㄩ棬)濮嬬粓渚濊禆鍏ㄥ眬瀹氫綅 鈥斺 鏁呰嚜鍔ㄦā寮忎笅涓昏溅蹇呰锛屼笌寮鍏虫棤鍏筹紱 + // 鎵嬪姩澶栭儴閬ユ帶榛樿涓嶈 Detour锛岄伩鍏 getCartLocation 闃诲鎷栨參 2 鑵挎娴嬶紱鑴氭湰鑷姩鍘熷湴鏃嬭浆 + // (FleetRotateInPlace) 宸茬粡渚濊禆 Detour 鍒ゅ仠锛屽洜姝ゆ樉寮忔墦寮 POS 绾犲亸浠ヤ繚鎸佹棆杞腑蹇冦 + var autoMode = autoEnabled && !manualEnabled; + var scriptRotateDetourCorrection = isMaster && scriptOn && manualMode == 2 && Conf.FleetRotateUseDetourHeading; + var notificationDetourCorrection = !isMaster && activeNotification != null && + activeNotification.UseDetourCorrection; + var manualDetourCorrection = manualEnabled && + (Conf.MultiVehicleManualUseDetourCorrection || + scriptRotateDetourCorrection || + notificationDetourCorrection); + var useDetourCorrection = Conf.MultiVehicleSyncUseDetour && (!manualEnabled || manualDetourCorrection); + var slamRead = useDetourCorrection || (isMaster && autoMode); + float selfX = 0, selfY = 0, selfTh = 0; + if (slamRead) + { + var carPos = DetourInterface.getCartLocation(); + selfX = (float)carPos.x; + selfY = (float)carPos.y; + selfTh = (float)carPos.th; + } + // fleetPosValid锛氭暣闃熷叏灞濮挎佹槸鍚﹀凡鐭ャ備富杞=鑷韩璇诲埌 SLAM锛涗粠杞=涓昏溅骞挎挱鏍囧織锛堜笅鏂硅鐩栵級銆 + var fleetPosValid = slamRead; + + var syncTh = Conf.TestCarSyncTh; + var syncDistance = Conf.TestCarSyncDistance; + var deltaDetectCenter = Conf.DeltaDetectCenter; + float fleetVx = 0, fleetFrontTh = 0, fleetRearTh = 0, fleetOmega = 0; + var fleetMode = 0; // 0=甯歌 1=锜硅 2=鍘熷湴鏃嬭浆 + var autoCommandTimedOut = false; + var notificationStopActive = false; + var notificationStopReason = ""; + var notificationStopSourceCar = 0; + var notificationRequestedFleetOmega = 0f; + var notificationMotionReleased = true; + float crabInputVx = 0, crabInputVy = 0, crabRawAngle = 0; + float crabSteerLimit = 0; + var crabReverseEquivalent = false; + + if (isMaster) + { + if (manualEnabled) + { + syncTh = 0; + fleetMode = manualMode; + var remoteRatioInput = !scriptOn; + if (fleetMode == 2) + { + // 澶栭儴閬ユ帶: Vth 涓烘憞鏉嗘瘮渚嬶紱鍐呴儴鑴氭湰: Vth 涓哄疄闄呰閫熷害(deg/s)銆 + fleetOmega = remoteRatioInput + ? ClampFloat(manualVth, -1f, 1f) * Math.Max(0f, Conf.FleetManualMaxRotateOmegaDegPerSec) + : manualVth; + fleetVx = 0; + fleetFrontTh = 0; + fleetRearTh = 0; + _multiVehicleAccumulateTh = 0f; + _multiVehicleLastThTime = DateTime.Now; + } + else if (fleetMode == 1) + { + // 澶栭儴閬ユ帶: Vx/Vy 涓烘憞鏉嗘瘮渚嬶紱鍐呴儴鑴氭湰: Vx 涓虹嚎閫熷害(m/s), Vy 涓鸿煿琛岃埖瑙(deg)銆 + var speed = remoteRatioInput + ? ClampFloat(manualVx, -1f, 1f) * Math.Max(0f, Conf.FleetManualMaxSpeed) + : manualVx; + var crabRatio = remoteRatioInput ? ClampFloat(manualVy, -1f, 1f) : 0f; + var crabAngle = remoteRatioInput + ? crabRatio * Math.Abs(Conf.FleetManualMaxCrabAngleDeg) + : manualVy; + crabInputVx = speed; + crabInputVy = remoteRatioInput ? crabRatio : crabAngle; + crabRawAngle = crabAngle; + crabSteerLimit = Math.Min(179f, Math.Max(1f, Math.Abs(Conf.MultiVehicleCrabSteerLimitDeg))); + + if (crabAngle > crabSteerLimit) { crabAngle -= 180f; speed = -speed; crabReverseEquivalent = true; } + else if (crabAngle < -crabSteerLimit) { crabAngle += 180f; speed = -speed; crabReverseEquivalent = true; } + fleetVx = speed; + fleetFrontTh = crabAngle; + fleetRearTh = crabAngle; + _multiVehicleAccumulateTh = 0f; + _multiVehicleLastThTime = DateTime.Now; + } + else + { + // 澶栭儴閬ユ帶: Vx/Vth 涓烘憞鏉嗘瘮渚嬶紱鍐呴儴鑴氭湰: Vx 涓虹嚎閫熷害(m/s), Vth 涓虹洰鏍囪埖瑙(deg)銆 + fleetVx = remoteRatioInput + ? ClampFloat(manualVx, -1f, 1f) * Math.Max(0f, Conf.FleetManualMaxSpeed) + : manualVx; + var targetTh = remoteRatioInput + ? ClampFloat(manualVth, -1f, 1f) * Math.Abs(Conf.FleetManualMaxSteerAngleDeg) + : manualVth; + var now = DateTime.Now; + var dt = (float)Math.Min(0.2, Math.Max(0, (now - _multiVehicleLastThTime).TotalSeconds)); + _multiVehicleLastThTime = now; + var sign = Math.Sign(targetTh - _multiVehicleAccumulateTh); + _multiVehicleAccumulateTh += sign * Math.Min(Math.Abs(targetTh - _multiVehicleAccumulateTh), + Conf.SyncThAccPerSec * dt); + fleetFrontTh = _multiVehicleAccumulateTh; + fleetRearTh = -fleetFrontTh; + } + + if (manualHold) + { + fleetMode = 0; + fleetVx = 0; + fleetFrontTh = 0; + fleetRearTh = 0; + fleetOmega = 0; + _multiVehicleAccumulateTh = 0f; + _multiVehicleLastThTime = DateTime.Now; + } + } + else + { + // B: 鑷姩妯″紡閫熷害鍛戒护鏂伴矞搴﹂棬鎺с傝矾寰勭粨鏉/鍥炶皟鏃╅/鍗¢】鍚庯紝鎺у埗鍣ㄤ笉鍐嶅埛鏂 AutoCmdTime锛 + // 瓒呮椂鍗宠涓哄け鏁堬細娓呴浂涓嬪彂閫熷害涓 idealPos锛屽叧闂 AutoEnabled锛岄伩鍏嶈溅闃熸寜鏈熷害婊戣銆 + var autoTimeoutMs = Conf.MultiVehicleAutoCmdTimeoutMs > 0 + ? Conf.MultiVehicleAutoCmdTimeoutMs + : Math.Max(200, Conf.MultiVehicleSyncInterval * 4); + var autoFresh = (DateTime.Now - MultiVehicleAutoCmdTime).TotalMilliseconds < autoTimeoutMs; + if (autoFresh) + { + fleetVx = MultiVehicleAutoVx; + fleetFrontTh = MultiVehicleAutoFrontTh; + fleetRearTh = MultiVehicleAutoRearTh; + } + else + { + autoCommandTimedOut = true; + fleetVx = fleetFrontTh = fleetRearTh = 0; + MultiVehicleAutoVx = MultiVehicleAutoFrontTh = MultiVehicleAutoRearTh = 0; + MultiVehicleAutoHasIdeal = false; + MultiVehicleAutoEnabled = false; + Hedingben.ToastText("鑷姩閫熷害鍛戒护瓒呮椂锛屽凡鍋滆溅锛堣矾寰勭粨鏉/鎺у埗鍣ㄥ仠鍙戯級", "MultiVehicle-auto-timeout"); + } + } + } + else if (activeNotification != null) + { + var notification = activeNotification; + + syncTh = notification.SyncTh; + syncDistance = notification.SyncDistance; + deltaDetectCenter = notification.DeltaDetectCenter; + PublishFleetCenter(notification.CenterX, notification.CenterY, notification.CenterTh); + // 浠庤溅鏁撮槦濮挎佹潵鑷富杞﹀箍鎾細浠ュ箍鎾爣蹇椾綔涓 fleetPosValid锛堣嚜韬 slamRead 浠呭喅瀹氭槸鍚﹀仛鏈溅绾犲亸锛夈 + fleetPosValid = notification.PosAvailable; + MultiVehicleAutoEnabled = notification.AutoEnabled; + fleetVx = notification.FleetVx; + fleetFrontTh = notification.FleetFrontTh; + fleetRearTh = notification.FleetRearTh; + fleetMode = notification.Mode; + fleetOmega = notification.FleetOmega; + notificationRequestedFleetOmega = notification.RequestedFleetOmega; + notificationMotionReleased = notification.FleetMotionReleased; + notificationStopActive = notification.FleetStopActive; + notificationStopReason = notification.FleetStopReason ?? ""; + notificationStopSourceCar = notification.FleetStopSourceCar; + // D: 浠庤溅閲囩敤涓昏溅骞挎挱鐨勭悊鎯宠溅闃熶腑蹇冿紙寮х嚎鏃剁敱 idealPos/idealAngle 鑰屾潵锛夊仛鍓嶉鐩爣銆 + MultiVehicleAutoHasIdeal = notification.HasIdeal; + MultiVehicleAutoIdealX = notification.IdealX; + MultiVehicleAutoIdealY = notification.IdealY; + MultiVehicleAutoIdealTh = notification.IdealTh; + } + + var requestedFleetOmega = !isMaster && fleetMode == 2 + ? ((Math.Abs(notificationRequestedFleetOmega) > 1e-6f || !notificationMotionReleased) + ? notificationRequestedFleetOmega + : fleetOmega) + : fleetOmega; + UpdateMultiVehicleRotateModeState(fleetMode, manualEnabled || autoEnabled, requestedFleetOmega, rotateParams); + + var (layoutX, layoutY, layoutTh) = GetLayoutPose(syncTh, syncDistance); + var inferredFleetCenterValid = false; + float inferredFleetCenterX = 0, inferredFleetCenterY = 0, inferredFleetCenterTh = 0; + Tuple supposedPosForDiag = null; + + if (isMaster) + { + lock (FleetLock) + { + MultiVehicleFleet[CarNum] = BuildSelfInfo(true, slamRead, selfX, selfY, selfTh, + layoutX, layoutY, layoutTh, true); + _multiVehicleFleetSeen[CarNum] = DateTime.Now; // 涓昏溅鑷韩鎭掓柊椴 + PruneStaleFleetMembers(); // C: 鍓旈櫎鎺夌嚎浠庤溅 + } + + if (TryInferFleetCenter(out var cx, out var cy, out var cth)) + { + inferredFleetCenterValid = true; + inferredFleetCenterX = cx; + inferredFleetCenterY = cy; + inferredFleetCenterTh = cth; + PublishFleetCenter(cx, cy, cth); + } + + // D: 鑷姩妯″紡锛堥潪鎵嬪姩锛変笅锛岃嫢鎺у埗鍣ㄧ粰鍑虹悊鎯宠溅闃熶腑蹇冿紝鍒欎互鐞嗘兂浣嶅Э浣滀负鍚勮溅 layout 鐩爣锛 + // 浣垮姬绾胯矾寰勪笂浠庤溅鎸夊悇鑷浉瀵规洸鐜囦腑蹇冧綅缃墠棣堬紝鑰岄潪浠呴潬浜嬪悗妫娴/SLAM 绾犲亸銆 + if (!manualEnabled && MultiVehicleAutoEnabled && + Conf.MultiVehicleAutoUseIdealCenter && MultiVehicleAutoHasIdeal) + PublishFleetCenter(MultiVehicleAutoIdealX, MultiVehicleAutoIdealY, MultiVehicleAutoIdealTh); + } + + var selfAligned = !Conf.MultiVehicleUseDetect; + var detectValid = false; + float detectDx = 0, detectDy = 0, detectDth = 0; + var currentSpacing = float.NaN; + if (Conf.MultiVehicleUseDetect) + { + var (valid, dx, dy, dth, neighborDist) = DetectNeighborBias(syncDistance - deltaDetectCenter); + detectValid = valid; + if (valid) + { + detectDx = dx; + detectDy = dy; + detectDth = dth; + // 妫娴嬩腑蹇冨埌鏈溅鍘熺偣璺濈 + 妫娴嬩腑蹇冨亸绉 = 涓よ溅鍙傝冪偣褰撳墠闂磋窛 + currentSpacing = neighborDist + deltaDetectCenter; + selfAligned = Math.Abs(dx) < Conf.SingleCarSyncPrecisionXy && + Math.Abs(dy) < Conf.SingleCarSyncPrecisionXy && + Math.Abs(dth) < Conf.SingleCarSyncPrecisionTh; + } + else selfAligned = false; + } + + // 妫娴嬩笉鍙敤锛堝叧闂/璺熶涪锛夋椂鍥炶惤鍒 SLAM 涓栫晫鍧愭爣璁$畻闂磋窛锛堥渶鏈溅宸茶鍒板叏灞瀹氫綅锛 + if (float.IsNaN(currentSpacing) && slamRead) + currentSpacing = TryGetSlamSpacing(selfX, selfY); + + if (float.IsNaN(currentSpacing)) + Hedingben.ToastText($"闂磋窛 褰撳墠:N/A 鐩爣:{syncDistance:F0}mm", $"MultiVehicle{CarNum}-spacing"); + else + Hedingben.ToastText( + $"闂磋窛 褰撳墠:{currentSpacing:F0}mm 鐩爣:{syncDistance:F0}mm 宸:{currentSpacing - syncDistance:F0}mm", + $"MultiVehicle{CarNum}-spacing"); + + lock (FleetLock) + { + MultiVehicleAligned = MultiVehicleFleet.Count == Conf.MultiVehicleFleetNum && + MultiVehicleFleet.Values.All(v => v.Aligned); + } + + var fleetReady = false; + var fleetCount = 0; + lock (FleetLock) + { + fleetCount = MultiVehicleFleet.Count; + fleetReady = fleetCount == Conf.MultiVehicleFleetNum; + } + + // 瀹夊叏闂細寮鍚簰璇嗗埆鏃讹紝鏈溅鎴栦换涓鍏跺畠杞︽娴嬩笉鍒伴偦杞﹀垯鏁撮槦鍋滆溅锛堥熷害缃浂锛夈 + // ownDetectOk 鏄湰杞柊椴滃硷紱鍏跺畠杞︾殑 DetectOk 鏉ヨ嚜鍏朵笂鎶/涓昏溅涓嬪彂锛堟粦鍔ㄧ獥鍙e凡缁 1s 鍘绘姈锛夈 + var ownDetectOk = !Conf.MultiVehicleUseDetect || detectValid; + bool othersDetectOk; + string otherDetectLostCars; + List> motionInfeasibleMembers; + List> rotateUnalignedMembers; + lock (FleetLock) + { + othersDetectOk = MultiVehicleFleet.Where(kv => kv.Key != CarNum).All(kv => kv.Value.DetectOk); + otherDetectLostCars = string.Join(",", MultiVehicleFleet + .Where(kv => kv.Key != CarNum && !kv.Value.DetectOk) + .Select(kv => kv.Key.ToString())); + motionInfeasibleMembers = MultiVehicleFleet + .Where(kv => kv.Key != CarNum && !kv.Value.MotionFeasible) + .ToList(); + rotateUnalignedMembers = MultiVehicleFleet + .Where(kv => !kv.Value.RotateWheelsAligned) + .ToList(); + } + if (!MultiVehicleRotateWheelsReady && rotateUnalignedMembers.All(kv => kv.Key != CarNum)) + { + rotateUnalignedMembers.Add(new KeyValuePair(CarNum, new VehicleSyncInfo + { + RotateWheelsAligned = false, + RotateWheelAlignDetail = _multiVehicleRotateAlignDetail + })); + } + var rotateUnalignedCars = string.Join(",", rotateUnalignedMembers.Select(kv => kv.Key.ToString())); + var rotateFleetWheelsAligned = fleetMode != 2 || (fleetReady && rotateUnalignedMembers.Count == 0); + MultiVehicleRotateFleetReady = rotateFleetWheelsAligned; + + var fleetStopActive = false; + var fleetStopReason = ""; + var fleetStopSourceCar = 0; + void AddFleetStop(string reason, int sourceCar = 0) + { + if (string.IsNullOrWhiteSpace(reason)) return; + if (!fleetStopActive) + { + fleetStopReason = reason; + fleetStopSourceCar = sourceCar; + } + else + { + fleetStopReason += " | " + reason; + if (fleetStopSourceCar == 0) fleetStopSourceCar = sourceCar; + } + fleetStopActive = true; + } + + if (!fleetReady) + AddFleetStop($"member not ready/stale fleetCnt={fleetCount}/{Conf.MultiVehicleFleetNum}"); + if (autoCommandTimedOut) + AddFleetStop("auto command timeout"); + if (Conf.MultiVehicleUseDetect && !ownDetectOk) + AddFleetStop("own two-leg detection lost", CarNum); + if (Conf.MultiVehicleUseDetect && !othersDetectOk) + AddFleetStop($"other two-leg detection lost cars=[{otherDetectLostCars}]"); + if (notificationStopActive) + AddFleetStop($"master stop from car{notificationStopSourceCar}: {notificationStopReason}", + notificationStopSourceCar); + if (!_multiVehicleMotionFeasible) + AddFleetStop($"car{CarNum} motion infeasible: {_multiVehicleMotionInfeasibleReason}", CarNum); + foreach (var kv in motionInfeasibleMembers) + AddFleetStop($"car{kv.Key} motion infeasible: {kv.Value.MotionInfeasibleReason}", kv.Key); + + var canMove = !fleetStopActive; + + // H: 鑷姩妯″紡锛堥潪鎵嬪姩锛夊繀椤绘湁鏈夋晥杞﹂槦涓績鈥斺斾富杞︾敱 SLAM 鍙嶆帹銆佷粠杞︿緷璧栦富杞﹀箍鎾 fleetPosValid銆 + // 鑷姩妯″紡鏁撮槦濮挎佸缁堜緷璧 Detour锛堜笌 MultiVehicleSyncUseDetour 鏃犲叧锛夛細瀹氫綅鍏ㄧ▼涓㈠け鏃跺己鍒跺仠杞︺ + // 锛堢敤 Detour 鏃惰嫢瀹氫綅涓㈠け锛実etCartLocation() 宸插厛琛岄樆濉烇紝姝ゅ鍐嶅厹搴曡姹傛湁鏁堣溅闃熶腑蹇冦傦級 + // 鎵嬪姩妯″紡涓嶅彈闄愶紙鍏佽浠呴潬浜掕瘑鍒/閬ユ帶琛岄┒锛夈 + if (canMove && autoMode && Conf.MultiVehicleAutoRequireFleetCenter) + { + var fleetCenterValid = fleetPosValid && (!isMaster || TryInferFleetCenter(out _, out _, out _)); + if (!fleetCenterValid) + { + AddFleetStop("auto fleet center invalid/localization lost", CarNum); + canMove = false; + Hedingben.ToastText("鑷姩妯″紡鏃犳湁鏁堣溅闃熶腑蹇冿紙瀹氫綅涓㈠け锛夛紝宸插仠杞", $"MultiVehicle{CarNum}-autostop"); + } + } + + if (!canMove) + { + fleetVx = 0; + fleetFrontTh = 0; + fleetRearTh = 0; + fleetOmega = 0; + Hedingben.ToastText( + $"杞﹂槦鍋滆溅锛歿(!ownDetectOk ? "鏈溅" : "鍏跺畠杞")}2鑵挎娴嬩涪澶憋紙閫熷害宸茬疆闆讹級", + $"MultiVehicle{CarNum}-stop"); + } + else + { + Hedingben.ToastText("杞﹂槦妫娴嬫甯", $"MultiVehicle{CarNum}-stop"); + } + + var rotateHoldForAlignment = false; + if (fleetMode == 2 && fleetReady && !fleetStopActive && !notificationMotionReleased) + { + rotateHoldForAlignment = true; + fleetOmega = 0; + Hedingben.ToastText("杞﹂槦鍘熷湴鏃嬭浆绛夊緟涓昏溅閲婃斁閫熷害", $"MultiVehicle{CarNum}-rotate-align"); + LogMultiVehicleRemoteDecision( + $"ROTATE_HOLD_RELEASE master={isMaster} manual={manualEnabled} auto={autoEnabled} " + + $"requestedOmega={requestedFleetOmega:0.000}", true); + } + else if (fleetMode == 2 && fleetReady && !fleetStopActive && !rotateFleetWheelsAligned) + { + rotateHoldForAlignment = true; + fleetOmega = 0; + Hedingben.ToastText($"杞﹂槦鍘熷湴鏃嬭浆鑸佃疆棰勫榻愪腑 car=[{rotateUnalignedCars}]", $"MultiVehicle{CarNum}-rotate-align"); + LogMultiVehicleRemoteDecision( + $"ROTATE_HOLD_ALIGN master={isMaster} manual={manualEnabled} auto={autoEnabled} " + + $"requestedOmega={requestedFleetOmega:0.000} unalignedCars=[{rotateUnalignedCars}]", true); + } + + if (fleetStopActive) + LogMultiVehicleStop(fleetStopReason); + + VisualizeFleet(contour, layoutX, layoutY, layoutTh); + + // 琛ュ伩閲忔彁鍒板潡澶栵紝渚夸簬璇婃柇鏃ュ織缁熶竴璁板綍涓夌被鏉ユ簮锛堟娴/SLAM锛夌殑璐$尞銆 + float xDetectCompensate = 0, yDetectCompensate = 0, thDetectCompensate = 0; + float xPosCompensate = 0, yPosCompensate = 0, thPosCompensate = 0; + float posBiasX = 0, posBiasY = 0, posBiasTh = 0; + + if (!fleetReady) + LogMultiVehicleRemoteDecision( + $"NO_SEND_NOT_READY master={isMaster} manual={manualEnabled} auto={autoEnabled} " + + $"fleetCnt={fleetCount}/{Conf.MultiVehicleFleetNum} canMove={canMove} mode={fleetMode} " + + $"cmdVx={fleetVx:0.000} cmdFTh={fleetFrontTh:0.00} cmdRTh={fleetRearTh:0.00} omega={fleetOmega:0.000}"); + + if (fleetStopActive) + { + chassis.RampStop(); + SetMultiVehicleMotionFeasible(true); + if (fleetMode == 2) + { + MultiVehicleRotateWheelsReady = false; + MultiVehicleRotateFleetReady = false; + _multiVehicleRotateAlignDetail = $"fleet stop: {fleetStopReason}"; + } + LogMultiVehicleRemoteDecision( + $"RAMP_STOP master={isMaster} manual={manualEnabled} auto={autoEnabled} ready={fleetReady} " + + $"reason={fleetStopReason}", true); + } + + if (fleetReady && !fleetStopActive) + { + chassis.SetOriginBias(layoutX, layoutY, layoutTh); + // E: 缁熶竴鎺у埗鐐瑰崐寰勶紝鍙 syncDistance/2锛屼笌缂栭槦鍑犱綍涓鑷淬 + var controlRadius = syncDistance / 2f; + chassis.ControlPointRadius = controlRadius; + // #1 绾犲亸闅忔棆杞缉鏀撅細鎶婃瘡杞籂鍋忛挸鍒版棆杞垏鍚戠殑姣斾緥锛屽噺閫熸湯娈靛垏鍚戝彉灏忔椂绾犲亸鍚屾缂╁皬锛屾潨缁濊疆鍚戜贡鎽嗐 + chassis.RotateCompTangentFrac = rotateParams.CompTangentFrac; + + if (canMove && Conf.MultiVehicleUseDetect) + { + xDetectCompensate = Math.Abs(detectDx) > Conf.SingleCarSyncPrecisionXy + ? detectDx * Conf.MultiVehicleDetectBiasXFac : 0; + yDetectCompensate = Math.Abs(detectDy) > Conf.SingleCarSyncPrecisionXy + ? detectDy * Conf.MultiVehicleDetectBiasYFac : 0; + thDetectCompensate = Math.Abs(detectDth) > Conf.SingleCarSyncPrecisionTh + ? detectDth * Conf.MultiVehicleDetectBiasThFac : 0; + + xDetectCompensate = ClampBias(xDetectCompensate, Conf.MultiVehicleDetectBiasXThreshold); + yDetectCompensate = ClampBias(yDetectCompensate, Conf.MultiVehicleDetectBiasYThreshold); + thDetectCompensate = ClampBias(thDetectCompensate, Conf.MultiVehicleDetectBiasThThreshold); + } + + // 杞﹂槦鍐呭Э鎬佺籂姝(POS 琛ュ伩)锛氫粎褰 useDetourCorrection 寮鍚笖鏈溅璇诲埌鍏ㄥ眬瀹氫綅鏃舵柦鍔犮 + // 杩欐槸"瀹氫綅鍙備笌杞﹂槦鍐呭Э鎬佺籂姝"鐨勫敮涓寮鍏崇偣鈥斺斿叧闂畠涓嶅奖鍝嶄笂闈㈢殑鏁撮槦濮挎佽绠/瀹夊叏闂ㄣ + if (canMove && useDetourCorrection && slamRead && TryInferFleetCenter(out _, out _, out _)) + { + var supposedPos = LessMath.Transform2D( + Tuple.Create(CenterX, CenterY, CenterTh), + Tuple.Create(layoutX, layoutY, layoutTh)); + supposedPosForDiag = supposedPos; + var posBias = LessMath.SolveTransform2D(Tuple.Create(selfX, selfY, selfTh), supposedPos); + posBiasX = (float)posBias.Item1; + posBiasY = (float)posBias.Item2; + posBiasTh = (float)posBias.Item3; + + xPosCompensate = Math.Abs(posBias.Item1) > Conf.SingleCarSyncPrecisionXy + ? ClampBias(posBias.Item1 * Conf.MultiVehiclePosBiasXFac, Conf.MultiVehiclePosBiasXThreshold) + : 0; + yPosCompensate = Math.Abs(posBias.Item2) > Conf.SingleCarSyncPrecisionXy + ? ClampBias(posBias.Item2 * Conf.MultiVehiclePosBiasYFac, Conf.MultiVehiclePosBiasYThreshold) + : 0; + thPosCompensate = Math.Abs(posBias.Item3) > Conf.SingleCarSyncPrecisionTh + ? ClampBias(posBias.Item3 * Conf.MultiVehiclePosBiasThFac, Conf.MultiVehiclePosBiasThThreshold) + : 0; + } + + sendMotionPainter.Clear(); + if (fleetMode == 2) + { + // 鍘熷湴鏃嬭浆锛氬簳鐩樺師鐐瑰凡鍋忕疆鍒拌溅闃熶腑蹇冿紝缁曢槦涓績鏃嬭浆锛屽苟鍙犲姞 PI 闂幆绾犲亸缁存寔闃熷舰銆 + // detect/pos 鍋忓樊(dx,dy,dth) 鏈韩灏辨槸"鏈溅鍙傝冪偣搴斿湪杞︿綋绯荤Щ鍔ㄥ埌鐨勪綅缃/搴旇浆鐨勮"锛屼綔涓鸿宸杺缁 PI銆 + // 绾 P 瀵规姉鎭掑畾妯悜婊戠Щ鏈夌ǔ鎬佹畫宸紝绉垎椤规秷闄や箣銆傛娴嬩涪澶(canMove=false)鏃朵笉绾犲亸骞舵竻绌虹Н鍒嗐 + float rotCompVx = 0, rotCompVy = 0, rotCompOmega = 0; + var now = DateTime.Now; + // dt 闄愬箙锛岄伩鍏嶉甯/鍗¢】瀵艰嚧绉垎绐佽烦 + var dt = _rotPiLastTime == DateTime.MinValue ? 0f + : (float)Math.Min(0.2, Math.Max(0, (now - _rotPiLastTime).TotalSeconds)); + _rotPiLastTime = now; + + // 浠呭湪"琚寚浠ゆ棆杞"鏃舵墠绾犲亸锛氭澗寮鎽囨潌(fleetOmega鈮0)鏃剁粷涓嶅啀涓嬪彂琛ュ伩锛 + // 鍚﹀垯绉垎娈嬬暀浼氭寔缁┍鍔ㄨ溅杈嗗钩绉/鏃嬭浆锛岃〃鐜颁负"鏉炬潌鍚庤疆瀛愭潵鍥炴墦銆佽嚜杞仠涓嶄笅鏉"銆 + var rotating = Math.Abs(fleetOmega) > rotateParams.ActiveOmega; + if (canMove && rotating) + { + // #3 鎶楅ケ鍜岋細涓婁竴鎷嶈埖杞湭瀵归綈(gate=0銆佽溅娌$湡姝h浆鍔)鏃跺喕缁撶Н鍒嗭紝閬垮厤鍗℃鏃剁Н鍒嗚秺绉秺澶с + var allowInteg = chassis.LastRotateAligned && + MultiVehicleRotateWheelsReady && + MultiVehicleRotateFleetReady && + !rotateHoldForAlignment; + var errX = detectDx + posBiasX; // mm锛岃溅浣撶郴锛氭湰杞︾旱鍚(鍓+)搴旂Щ鍔ㄩ噺 + var errY = detectDy + posBiasY; // mm锛岃溅浣撶郴锛氭湰杞︽í鍚(宸+)搴旂Щ鍔ㄩ噺 + var errTh = detectDth + posBiasTh; // deg锛屾湰杞﹀簲杞 + rotCompVx = RotatePiTerm(errX, ref _rotIntegX, Conf.SingleCarSyncPrecisionXy, + rotateParams.CompXyFac, rotateParams.CompXyIFac, + rotateParams.CompXyMax, dt, allowInteg); + rotCompVy = RotatePiTerm(errY, ref _rotIntegY, Conf.SingleCarSyncPrecisionXy, + rotateParams.CompXyFac, rotateParams.CompXyIFac, + rotateParams.CompXyMax, dt, allowInteg); + rotCompOmega = RotatePiTerm(errTh, ref _rotIntegTh, Conf.SingleCarSyncPrecisionTh, + rotateParams.CompThFac, rotateParams.CompThIFac, + rotateParams.CompThMax, dt, allowInteg); + + // #1 绾犲亸闅忔棆杞寚浠ょ缉鏀撅細comp 脳= |fleetOmega| / 鏈宄板笺 + // 鍔犻+鍖閫熸宄板尖増褰撳墠 鈫 绯绘暟鈮1锛堝叏鍔涚籂鍋忥紝涓嶅墛寮憋級锛涘噺閫熸褰撳墠<宄板 鈫 绯绘暟闅忚浆閫熷悓姝ヤ笅闄嶃 + // 鍏抽敭锛氭棆杞垏鍚戜篃鈭濊浆閫燂紝鏁"绾犲亸:鍒囧悜"姣斾緥鍏ㄧ▼鎭掑畾=鍖閫熸姣斾緥锛堣繙<1锛夛紝鏃㈡潨缁濇湯娈佃疆瀛愪贡鎵撴柟鍚戯紝 + // 鍙堜笉鍍忔寜鍒囧悜閽充綅閭f牱鍦ㄥ寑閫熸灏卞墛寮辩籂鍋忋 + var absOmega = Math.Abs(fleetOmega); + _rotOmegaPeak = Math.Max(_rotOmegaPeak, absOmega); + if (_rotOmegaPeak > 1e-3f) + { + var compScale = Math.Min(1f, absOmega / _rotOmegaPeak); + rotCompVx *= compScale; + rotCompVy *= compScale; + rotCompOmega *= compScale; + } + LimitRotateCompensation(ref rotCompVx, ref rotCompVy, ref rotCompOmega, + absOmega, controlRadius, rotateParams.CompTangentFrac); + } + else + { + // 妫娴嬩涪澶辨垨鏈寚浠ゆ棆杞細娓呴浂琛ュ伩骞跺浣嶇Н鍒/璁℃椂/宄板硷紝鍋滄鏃朵笉鍐嶆湁娈嬬暀椹卞姩銆 + _rotIntegX = _rotIntegY = _rotIntegTh = 0; + _rotPiLastTime = DateTime.MinValue; + _rotOmegaPeak = 0; + } + + _mvRotCompVx = rotCompVx; + _mvRotCompVy = rotCompVy; + _mvRotCompOmega = rotCompOmega; + + bool motionOk; + if (rotateHoldForAlignment) + { + motionOk = PrepareMultiVehicleRotateWheels(chassis, requestedFleetOmega, rotateParams, + rotCompVx, rotCompVy, rotCompOmega); + } + else if (rotating) + { + // Preparation calls SendRotateMotion with zero delta; after release it would starve the speed ramp. + if (!MultiVehicleRotateWheelsReady) + { + motionOk = PrepareMultiVehicleRotateWheels(chassis, requestedFleetOmega, rotateParams, + rotCompVx, rotCompVy, rotCompOmega, rampStop: false); + rotateHoldForAlignment = true; + fleetOmega = 0; + chassis.RampStop(); + if (!motionOk || !MultiVehicleRotateWheelsReady) + { + LogMultiVehicleRemoteDecision( + $"ROTATE_HOLD_LOCAL_ALIGN master={isMaster} manual={manualEnabled} auto={autoEnabled} " + + $"requestedOmega={requestedFleetOmega:0.000} align={_multiVehicleRotateAlignDetail}", true); + } + else + { + LogMultiVehicleRemoteDecision( + $"ROTATE_HOLD_LOCAL_READY master={isMaster} manual={manualEnabled} auto={autoEnabled} " + + $"requestedOmega={requestedFleetOmega:0.000} align={_multiVehicleRotateAlignDetail}", true); + } + } + else + { + motionOk = chassis.SendRotateMotion(fleetOmega, + localCompensateX: rotCompVx, localCompensateY: rotCompVy, + localCompensateTh: rotCompOmega); + var activeWheelAlignDeg = rotateParams.ActiveWheelAlignDeg; + var activeAligned = TryCheckRotateWheelAlignment(chassis, + activeWheelAlignDeg, out _multiVehicleRotateAlignDetail); + if (!motionOk) + MultiVehicleRotateWheelsReady = false; + if (motionOk && !activeAligned) + { + MultiVehicleRotateWheelsReady = false; + MultiVehicleRotateFleetReady = false; + rotateHoldForAlignment = true; + fleetOmega = 0; + _rotIntegX = _rotIntegY = _rotIntegTh = 0; + _rotPiLastTime = DateTime.MinValue; + _rotOmegaPeak = 0; + rotCompVx = rotCompVy = rotCompOmega = 0; + _mvRotCompVx = _mvRotCompVy = _mvRotCompOmega = 0; + motionOk = PrepareMultiVehicleRotateWheels(chassis, requestedFleetOmega, rotateParams); + LogMultiVehicleRemoteDecision( + $"ROTATE_ACTIVE_REHOLD master={isMaster} manual={manualEnabled} auto={autoEnabled} " + + $"requestedOmega={requestedFleetOmega:0.000} activeTol={activeWheelAlignDeg:0.0} " + + $"align={_multiVehicleRotateAlignDetail}", true); + } + } + } + else + { + motionOk = chassis.SendRotateMotion(fleetOmega, + localCompensateX: rotCompVx, localCompensateY: rotCompVy, + localCompensateTh: rotCompOmega); + MultiVehicleRotateWheelsReady = motionOk && + TryCheckRotateWheelAlignment(chassis, rotateParams.StartWheelAlignDeg, + out _multiVehicleRotateAlignDetail); + } + SetMultiVehicleMotionFeasible(motionOk, motionOk ? "" : chassis.LastMotionDecomposeFailureReason); + if (!motionOk) + { + AddFleetStop($"car{CarNum} chassis rotate infeasible: {chassis.LastMotionDecomposeFailureReason}", + CarNum); + canMove = false; + LogMultiVehicleStop(fleetStopReason, true); + } + LogRotateWheelOutputs(chassis, rotateHoldForAlignment ? "hold-align" : (rotating ? "rotate" : "idle"), + fleetOmega); + if (fleetPosValid) + LogMultiVehicleRotateCenterDrift(isMaster, manualEnabled, autoEnabled, fleetReady, canMove, rotating, + CenterX, CenterY, CenterTh, requestedFleetOmega, fleetOmega, + rotCompVx, rotCompVy, rotCompOmega); + else + ResetMultiVehicleRotateCenterDrift(); + LogMultiVehicleRemoteDecision( + $"SEND_ROTATE master={isMaster} manual={manualEnabled} canMove={canMove} ready={fleetReady} ok={motionOk} " + + $"holdAlign={rotateHoldForAlignment} wheelReady={MultiVehicleRotateWheelsReady} fleetReady={MultiVehicleRotateFleetReady} " + + $"mode={fleetMode} omegaReq={requestedFleetOmega:0.000} omega={fleetOmega:0.000} " + + $"comp=({rotCompVx:0.0},{rotCompVy:0.0},{rotCompOmega:0.000}) align={_multiVehicleRotateAlignDetail} " + + $"rotParam(xyP={rotateParams.CompXyFac:0.###} xyI={rotateParams.CompXyIFac:0.###} " + + $"xyMax={rotateParams.CompXyMax:0.#} thP={rotateParams.CompThFac:0.###} " + + $"thI={rotateParams.CompThIFac:0.###} thMax={rotateParams.CompThMax:0.#} " + + $"frac={rotateParams.CompTangentFrac:0.###} activeOmega={rotateParams.ActiveOmega:0.###} " + + $"startTol={rotateParams.StartWheelAlignDeg:0.#} activeTol={rotateParams.ActiveWheelAlignDeg:0.#}) " + + $"fleetCnt={fleetCount}/{Conf.MultiVehicleFleetNum}"); + + // 浠呬富杞︼細璇诲彇涓よ溅瀹為檯 sim 浣嶅Э锛岄噺鍖"寮鐜í鍚戞粦绉"鏉ユ簮锛堣妭娴 ~200ms锛夈 + if (isMaster && Conf.MultiVehicleRotatePoseWebApiDiagEnabled) + LogRotatePoseSample(); + } + else + { + _mvRotCompVx = 0; + _mvRotCompVy = 0; + _mvRotCompOmega = 0; + MultiVehicleRotateFleetReady = true; + // Reset rotate-only PI state outside rotate mode. + _rotIntegX = _rotIntegY = _rotIntegTh = 0; + _rotPiLastTime = DateTime.MinValue; + _rotPoseEpisode = false; + _rotPosePrevTime = DateTime.MinValue; + ResetMultiVehicleRotateCenterDrift(); + // 甯歌/锜硅锛氳煿琛屾椂 frontTh==rearTh锛堝洓杞悓鍚戯級鍗充负骞崇Щ锛屼笌甯歌鍏辩敤鍚屼竴涓嬪彂璺緞銆 + var motionOk = chassis.SendMotion(fleetVx, fleetFrontTh, fleetRearTh, localControlRadius: controlRadius, + localCompensateX: xDetectCompensate + xPosCompensate, + localCompensateY: yDetectCompensate + yPosCompensate, + localCompensateTh: thDetectCompensate + thPosCompensate); + if (motionOk) + MultiVehicleRotateWheelsReady = TryCheckRotateWheelAlignment(chassis, + Math.Max(0.1f, Conf.FleetCrabStartWheelAlignDeg), out _multiVehicleRotateAlignDetail); + else + { + MultiVehicleRotateWheelsReady = false; + _multiVehicleRotateAlignDetail = chassis.LastMotionDecomposeFailureReason; + } + MultiVehicleRotateFleetReady = true; + SetMultiVehicleMotionFeasible(motionOk, motionOk ? "" : chassis.LastMotionDecomposeFailureReason); + if (!motionOk) + { + AddFleetStop($"car{CarNum} chassis motion infeasible: {chassis.LastMotionDecomposeFailureReason}", + CarNum); + canMove = false; + LogMultiVehicleStop(fleetStopReason, true); + } + LogMultiVehicleRemoteDecision( + $"SEND_MOTION master={isMaster} manual={manualEnabled} canMove={canMove} ready={fleetReady} ok={motionOk} " + + $"mode={fleetMode} vx={fleetVx:0.000} fTh={fleetFrontTh:0.00} rTh={fleetRearTh:0.00} " + + $"comp=({xDetectCompensate + xPosCompensate:0.0},{yDetectCompensate + yPosCompensate:0.0},{thDetectCompensate + thPosCompensate:0.000}) " + + $"wheelReady={MultiVehicleRotateWheelsReady} align={_multiVehicleRotateAlignDetail} " + + $"fleetCnt={fleetCount}/{Conf.MultiVehicleFleetNum}"); + } + } + + // === 璇婃柇鏃ュ織锛堣妭娴 ~300ms锛=== + // 鐢ㄤ簬瀹氫綅鈥滃墽鐑堣繍鍔ㄢ濇潵婧愶細BASE=閬ユ帶鍩虹閫熷害锛汥ETECT=2鑵挎娴嬭ˉ鍋匡紱POS=SLAM缂栭槦琛ュ伩锛汼END=鏈缁堜笅鍙戙 + // 鑻 BASE鈮0 浣 SEND 鎸佺画闈為浂锛岃鏄庢槸琛ュ伩鍦ㄩ┍鍔紱鍐嶇湅 DETECT/POS 鍝竴璺殑 comp 鎸佺画闈為浂鍗冲畾浣嶅埌鏉ユ簮銆 + // 鍚屾椂钀 DLog(tag MultiVehicleDbg) 涓庡睆骞 ToastText(tag MultiVehicle{CarNum}-dbg)锛屽悗鑰呮棤闇寮鍚鐩樿浆鍌ㄥ嵆鍙洿鎺ヨ瀵熴 + if ((DateTime.Now - _mvDbgLastLog).TotalMilliseconds >= 300) + { + _mvDbgLastLog = DateTime.Now; + var spacingStr = float.IsNaN(currentSpacing) ? "NaN" : currentSpacing.ToString("F0"); + var cx = xDetectCompensate + xPosCompensate; + var cy = yDetectCompensate + yPosCompensate; + var cth = thDetectCompensate + thPosCompensate; + var actualCenterThForDiag = inferredFleetCenterValid ? inferredFleetCenterTh : CenterTh; + var idealHeadingErr = (float)CommonMath.ThDiff(MultiVehicleAutoIdealTh, actualCenterThForDiag); + var idealHeadingErrReverse = (float)CommonMath.ThDiff(actualCenterThForDiag, MultiVehicleAutoIdealTh); + var frontRearDiff = (float)CommonMath.ThDiff(fleetFrontTh, fleetRearTh); + var commandHeadingSplit = frontRearDiff / 2f; + var commandBaseTh = (float)CommonMath.RoundTh(fleetRearTh + commandHeadingSplit); + var supposedPosText = supposedPosForDiag == null + ? "N/A" + : $"({supposedPosForDiag.Item1:0},{supposedPosForDiag.Item2:0},{supposedPosForDiag.Item3:0.0})"; + var crabDbg = isMaster && manualEnabled && fleetMode == 1 + ? $"| CRAB speed:{crabInputVx:F3} steerRatio:{crabInputVy:F3} raw:{crabRawAngle:F2} limit:{crabSteerLimit:F1} rev:{crabReverseEquivalent} " + : ""; + + var dbg = + $"car{CarNum} master:{isMaster} manual:{manualEnabled} auto:{autoEnabled} slam:{slamRead} corr:{useDetourCorrection} fleetPos:{fleetPosValid} " + + $"ready:{fleetReady}({fleetCount}/{Conf.MultiVehicleFleetNum}) canMove:{canMove} stop:{fleetStopActive} stopReason:{fleetStopReason} useDetect:{Conf.MultiVehicleUseDetect} " + + $"| BASE vx:{fleetVx:F3} fTh:{fleetFrontTh:F2} rTh:{fleetRearTh:F2} " + + crabDbg + + $"| DETECT valid:{detectValid} center({_mvLastDetCenterX:F0},{_mvLastDetCenterY:F0}) dir:{_mvLastDetDir:F1} ndist:{_mvLastDetDist:F0} " + + $"dx:{detectDx:F0} dy:{detectDy:F0} dth:{detectDth:F2} spacing:{spacingStr}/{syncDistance:F0} delta:{deltaDetectCenter:F0} guessX:{Conf.TwoLegGuessX:F0} outBias({Conf.TwoLegOutputBiasX:F0},{Conf.TwoLegOutputBiasY:F0}) " + + $"-> comp x:{xDetectCompensate:F1} y:{yDetectCompensate:F1} th:{thDetectCompensate:F2} " + + $"fac({Conf.MultiVehicleDetectBiasXFac:F2},{Conf.MultiVehicleDetectBiasYFac:F2},{Conf.MultiVehicleDetectBiasThFac:F2}) " + + $"lim({Conf.MultiVehicleDetectBiasXThreshold:F1},{Conf.MultiVehicleDetectBiasYThreshold:F1},{Conf.MultiVehicleDetectBiasThThreshold:F1}) " + + $"| POS self({selfX:F0},{selfY:F0},{selfTh:F1}) center({CenterX:F0},{CenterY:F0},{CenterTh:F1}) " + + $"bias({posBiasX:F0},{posBiasY:F0},{posBiasTh:F1}) -> comp x:{xPosCompensate:F1} y:{yPosCompensate:F1} th:{thPosCompensate:F2} " + + $"fac({Conf.MultiVehiclePosBiasXFac:F2},{Conf.MultiVehiclePosBiasYFac:F2},{Conf.MultiVehiclePosBiasThFac:F2}) " + + $"lim({Conf.MultiVehiclePosBiasXThreshold:F1},{Conf.MultiVehiclePosBiasYThreshold:F1},{Conf.MultiVehiclePosBiasThThreshold:F1}) " + + $"| LAYOUT({layoutX:F0},{layoutY:F0},{layoutTh:F0}) R:{syncDistance / 2f:F0} " + + $"| SEND mode:{fleetMode} omega:{fleetOmega:F1} vx:{fleetVx:F3} fTh:{fleetFrontTh:F2} rTh:{fleetRearTh:F2} cx:{cx:F1} cy:{cy:F1} cth:{cth:F2} " + + $"rotComp(vx:{_mvRotCompVx:F1} vy:{_mvRotCompVy:F1} om:{_mvRotCompOmega:F2}) " + + $"| ROT_ALIGN hold:{rotateHoldForAlignment} wheelReady:{MultiVehicleRotateWheelsReady} fleetReady:{MultiVehicleRotateFleetReady} " + + $"unaligned:[{rotateUnalignedCars}] reqOmega:{requestedFleetOmega:F1} detail:{_multiVehicleRotateAlignDetail}"; + + DLog.Log(dbg, "MultiVehicleDbg"); + FleetDiag(dbg); + + if (autoMode || autoEnabled || MultiVehicleAutoEnabled) + DLog.Log( + $"APPLY car{CarNum} master:{isMaster} autoMode:{autoMode} manual:{manualEnabled} " + + $"cmd(vx:{fleetVx:0.000},f:{fleetFrontTh:0.00},r:{fleetRearTh:0.00},base:{commandBaseTh:0.00},split:{commandHeadingSplit:0.00},f-r:{frontRearDiff:0.00}) " + + $"ideal(has:{MultiVehicleAutoHasIdeal},x:{MultiVehicleAutoIdealX:0},y:{MultiVehicleAutoIdealY:0},th:{MultiVehicleAutoIdealTh:0.00}) " + + $"centerPublished({CenterX:0},{CenterY:0},{CenterTh:0.00}) " + + $"centerInferred(valid:{inferredFleetCenterValid},x:{inferredFleetCenterX:0},y:{inferredFleetCenterY:0},th:{inferredFleetCenterTh:0.00}) " + + $"idealHeadingErr(target-actual):{idealHeadingErr:0.00} reverse(actual-target):{idealHeadingErrReverse:0.00} " + + $"layout({layoutX:0},{layoutY:0},{layoutTh:0.00}) self({selfX:0},{selfY:0},{selfTh:0.00}) supposed:{supposedPosText} " + + $"detectDth:{detectDth:0.00}->comp:{thDetectCompensate:0.00} " + + $"posBiasTh:{posBiasTh:0.00}->comp:{thPosCompensate:0.00} " + + $"totalLocalComp(x:{cx:0.0},y:{cy:0.0},th:{cth:0.00}) " + + $"useDetourCorr:{useDetourCorrection} slam:{slamRead} fleetPos:{fleetPosValid} ready:{fleetReady}", + "FleetCrabHeadingDbg"); + + // 灞忓箷鍒嗕袱琛屾樉绀猴紝渚夸簬鐩存帴瑙傚療锛堟棤闇寮鍚 DLog 纾佺洏杞偍锛 + Hedingben.ToastText( + $"BASE vx{fleetVx:F3} fTh{fleetFrontTh:F1} | SEND vx{fleetVx:F3} c({cx:F0},{cy:F0},{cth:F1}) " + + $"| ready{fleetReady} canMove{canMove} stop{fleetStopActive}", + $"MultiVehicle{CarNum}-dbg"); + Hedingben.ToastText( + $"DET v{detectValid} dx{detectDx:F0} dy{detectDy:F0} dth{detectDth:F1} cmp({xDetectCompensate:F0},{yDetectCompensate:F0},{thDetectCompensate:F1}) " + + $"| POS bias({posBiasX:F0},{posBiasY:F0},{posBiasTh:F1}) cmp({xPosCompensate:F0},{yPosCompensate:F0},{thPosCompensate:F1})", + $"MultiVehicle{CarNum}-dbg2"); + } + + if (isMaster) + { + lock (FleetLock) + { + MultiVehicleFleet[CarNum] = BuildSelfInfo(true, slamRead, selfX, selfY, selfTh, + layoutX, layoutY, layoutTh, selfAligned, ownDetectOk); + } + + if (fleetReady || fleetStopActive) + { + VehicleSyncNotification notification; + lock (FleetLock) + { + notification = new VehicleSyncNotification + { + // 骞挎挱"鏁撮槦濮挎佹湁鏁"锛氫富杞﹁鍒板叏灞瀹氫綅鍗充负鐪燂紝浠庤溅鎹鏀捐鑷姩妯″紡瀹夊叏闂ㄣ + PosAvailable = slamRead, + CenterX = CenterX, + CenterY = CenterY, + CenterTh = CenterTh, + Aligned = MultiVehicleAligned, + Fleet = new Dictionary(MultiVehicleFleet), + FleetVx = fleetStopActive ? 0 : fleetVx, + FleetFrontTh = fleetStopActive ? 0 : fleetFrontTh, + FleetRearTh = fleetStopActive ? 0 : fleetRearTh, + Mode = fleetMode, + FleetOmega = fleetStopActive ? 0 : fleetOmega, + RequestedFleetOmega = fleetMode == 2 && !fleetStopActive ? requestedFleetOmega : 0, + FleetMotionReleased = !fleetStopActive && !(fleetMode == 2 && rotateHoldForAlignment), + FleetStopActive = fleetStopActive, + FleetStopReason = fleetStopReason, + FleetStopSourceCar = fleetStopSourceCar, + AutoEnabled = MultiVehicleAutoEnabled, + // 鑴氭湰椹卞姩绛変环浜庢墜鍔ㄨ仈鍔紝骞挎挱涓 ManualEnabled 璁╀粠杞﹁В閿佽窡闅忋 + ManualEnabled = manualEnabled, + UseDetourCorrection = useDetourCorrection, + SyncTh = syncTh, + SyncDistance = syncDistance, + DeltaDetectCenter = deltaDetectCenter, + // F: 鍗曡皟閫掑搴忓垪鍙凤紙浠 1 璧凤級锛屼粠杞︽嵁姝や涪寮冧贡搴忔棫鍖呫 + Seq = ++_multiVehicleNotifySeq, + // D: 閫忎紶鐞嗘兂杞﹂槦涓績锛堜粎鑷姩妯″紡涓旀帶鍒跺櫒缁欏嚭鏃舵湁鏁堬級銆 + HasIdeal = !manualEnabled && MultiVehicleAutoEnabled && + Conf.MultiVehicleAutoUseIdealCenter && MultiVehicleAutoHasIdeal, + IdealX = MultiVehicleAutoIdealX, + IdealY = MultiVehicleAutoIdealY, + IdealTh = MultiVehicleAutoIdealTh + }; + FillRotateNotificationParams(notification, rotateParams); + } + + LogMultiVehicleRemoteDecision( + $"NOTIFY_SEND seq={notification.Seq} mode={notification.Mode} " + + $"omega={notification.FleetOmega:0.000} reqOmega={notification.RequestedFleetOmega:0.000} " + + $"released={notification.FleetMotionReleased} stop={notification.FleetStopActive} " + + $"reason={notification.FleetStopReason} useDetourCorr={notification.UseDetourCorrection} " + + $"fleetCnt={notification.Fleet.Count}/{Conf.MultiVehicleFleetNum} " + + $"rotParam(valid={notification.RotateParamsValid} xyP={notification.RotateCompXyFac:0.###} " + + $"xyI={notification.RotateCompXyIFac:0.###} xyMax={notification.RotateCompXyMax:0.#} " + + $"thP={notification.RotateCompThFac:0.###} thI={notification.RotateCompThIFac:0.###} " + + $"thMax={notification.RotateCompThMax:0.#} frac={notification.RotateCompTangentFrac:0.###} " + + $"startTol={notification.RotateStartWheelAlignDeg:0.#} activeTol={notification.RotateActiveWheelAlignDeg:0.#})"); + + foreach (var kv in notification.Fleet) + { + var ip = kv.Value.Ip; + var port = kv.Value.Port > 0 ? kv.Value.Port : WebAPI.port; + if (string.IsNullOrWhiteSpace(ip) || kv.Key == CarNum) + continue; + FireAndForgetNotify(hc, ip, port, notification); + } + } + } + else + { + FireAndForgetRegister(hc, BuildSelfInfo(false, slamRead, selfX, selfY, selfTh, + layoutX, layoutY, layoutTh, selfAligned, ownDetectOk)); + } + } + + private bool IsMultiVehicleMaster() => Conf.MultiVehicleMasterEndpoint == "/"; + + /// + /// C: 鍓旈櫎瓒呰繃 TTL 鏈埛鏂帮紙register/notify锛夌殑 fleet 鎴愬憳銆傝皟鐢ㄦ柟椤诲凡鎸佹湁 FleetLock銆 + /// 浠庤溅宕╂簝/鏂綉鍚庡叾鏉$洰杩囨湡琚垹闄わ紝浣 fleetReady(鏁伴噺==鎬绘暟) 鍚屾椂钑村惈"鍏ㄩ儴鎴愬憳鍦ㄧ嚎涓旀柊椴"锛 + /// 涓昏溅涓嶅啀鍩轰簬杩囨湡 layout/DetectOk 缁х画 SendMotion+notify銆 + /// + private void PruneStaleFleetMembers() + { + var ttlMs = Conf.MultiVehicleMemberTtlMs > 0 + ? Conf.MultiVehicleMemberTtlMs + : Math.Max(500, Conf.MultiVehicleSyncInterval * 6); + var now = DateTime.Now; + var stale = MultiVehicleFleet.Keys + .Where(k => k != CarNum && + (!_multiVehicleFleetSeen.TryGetValue(k, out var seen) || + (now - seen).TotalMilliseconds > ttlMs)) + .ToList(); + foreach (var k in stale) + { + MultiVehicleFleet.Remove(k); + _multiVehicleFleetSeen.Remove(k); + Hedingben.ToastText($"鍓旈櫎鎺夌嚎鎴愬憳 car{k}锛坽ttlMs:F0}ms 鏈埛鏂帮級", $"MultiVehicle{CarNum}-prune"); + } + } + + private bool FleetHasPosAvailable() + { + lock (FleetLock) + return MultiVehicleFleet.Values.Any(v => v.PosAvailable); + } + + // 鍩轰簬 SLAM 涓栫晫鍧愭爣鐨勬渶杩戦偦杞﹂棿璺濓紙mm锛夛紱鏃犲彲鐢ㄥ畾浣嶉偦杞︽椂杩斿洖 NaN銆 + private float TryGetSlamSpacing(float selfX, float selfY) + { + List others; + lock (FleetLock) + others = MultiVehicleFleet + .Where(kv => kv.Key != CarNum && kv.Value.PosAvailable) + .Select(kv => kv.Value).ToList(); + + if (others.Count == 0) return float.NaN; + return others.Min(o => (float)Math.Sqrt((o.X - selfX) * (o.X - selfX) + (o.Y - selfY) * (o.Y - selfY))); + } + + private bool TryInferFleetCenter(out float centerX, out float centerY, out float centerTh) + { + centerX = centerY = centerTh = 0; + List positioned; + lock (FleetLock) + positioned = MultiVehicleFleet.Values.Where(v => v.PosAvailable).ToList(); + + if (positioned.Count == 0) return false; + + var centers = positioned.Select(InferFleetCenterFromCar).ToList(); + centerX = centers.Average(c => c.Item1); + centerY = centers.Average(c => c.Item2); + var avgSin = centers.Average(c => Math.Sin(c.Item3 * Math.PI / 180.0)); + var avgCos = centers.Average(c => Math.Cos(c.Item3 * Math.PI / 180.0)); + centerTh = (float)(Math.Atan2(avgSin, avgCos) * 180.0 / Math.PI); + return true; + } + + public bool TryGetFleetCenterFromMembers(out float centerX, out float centerY, out float centerTh) + { + return TryInferFleetCenter(out centerX, out centerY, out centerTh); + } + + private static (float, float, float) InferFleetCenterFromCar(VehicleSyncInfo car) + { + // 鐢 carWorld = Transform2D(center, layout) 鍙嶆帹 center = carWorld 鈭 layout鈦宦广 + // 娉ㄦ剰 layout鈦宦 鏄湡姝g殑 SE(2) 閫嗭紝鑰岄潪閫愬垎閲忓彇璐 (-layout)锛 + // 褰 layoutTh鈮0锛堝浠庤溅 180掳锛夋椂锛岄愬垎閲忓彇璐熶細鎶婂钩绉绘柟鍚戠畻閿欙紝瀵艰嚧杞﹂槦涓績鍋忕Щ 鈫 浣嶅Э琛ュ伩璺戦銆 + var layout = Tuple.Create((double)car.LayoutX, (double)car.LayoutY, (double)car.LayoutTh); + var layoutInv = LessMath.SolveTransform2D(layout, Tuple.Create(0.0, 0.0, 0.0)); + var center = LessMath.Transform2D( + Tuple.Create((double)car.X, (double)car.Y, (double)car.Th), + layoutInv); + return ((float)center.Item1, (float)center.Item2, (float)center.Item3); + } + + /// + /// 鐢辨湰杞︼紙閫氬父涓轰富杞︼級褰撳墠 Detour SLAM 浣嶅Э鍙嶆帹杞﹂槦涓績浣嶅Э锛堜笘鐣岀郴锛夈 + /// 澶嶇敤 GetLayoutPose + InferFleetCenterFromCar 鐨勫悓娆 SE(2) 鍙嶆帹锛坈enter = carWorld 鈭 layout鈦宦癸級锛 + /// 淇濊瘉涓庤嚜鍔ㄦā寮忚溅闃熶腑蹇冭绠椾竴鑷淬備緵鍔ㄤ綔锛堝 FleetCrabWalk锛夊彇璺緞璧风偣鐢紱鏃犳湁鏁堝畾浣嶆椂杩斿洖 false銆 + /// + public bool TryGetFleetCenterFromSlam(out float centerX, out float centerY, out float centerTh) + { + centerX = centerY = centerTh = 0; + var carPos = DetourInterface.getCartLocation(); + return TryGetFleetCenterFromPose((float)carPos.x, (float)carPos.y, (float)carPos.th, + out centerX, out centerY, out centerTh); + } + + public bool TryGetFleetCenterFromPose(float carX, float carY, float carTh, + out float centerX, out float centerY, out float centerTh) + { + centerX = centerY = centerTh = 0; + var (layoutX, layoutY, layoutTh) = GetLayoutPose(Conf.TestCarSyncTh, Conf.TestCarSyncDistance); + var self = new VehicleSyncInfo + { + X = carX, + Y = carY, + Th = carTh, + LayoutX = layoutX, + LayoutY = layoutY, + LayoutTh = layoutTh + }; + var (cx, cy, cth) = InferFleetCenterFromCar(self); + centerX = cx; + centerY = cy; + centerTh = cth; + return true; + } + + /// + /// 棰勭儹锛氱敤涓昏溅 SLAM 浣嶅Э锛岀珛鍗(1) 瀵瑰鍙戝竷鏈夋晥"杞﹂槦涓績蹇収"锛(2) 鎶婁富杞﹁嚜韬互 posAvailable=true + /// 鍐欏叆 fleet 琛ㄣ備緵 FleetCrabWalk 绛夊姩浣滃湪鍚姩鎺у埗鍣 Track() 鍓嶈皟鐢紝瑙e喅涓や釜鍚姩鏈熼棶棰橈細 + /// - 鎺у埗鍣ㄩ甯ч氳繃 MultiVehicleGetFleetPos 璇诲埌 (0,0,0) 鈫 璇垽宸插埌缁堢偣銆佺珛鍗崇粨鏉燂紱 + /// - 鑷姩鑱斿姩寰幆鐨勫畨鍏ㄩ棬 FleetHasPosAvailable锛圥ilotDefinition.cs ~402锛夊湪鍐峰惎鍔(鏃犺溅涓婃姤瀹氫綅)鏃 + /// 浼氭妸 AutoEnabled 鍏虫帀銆佸惊鐜棤娉曞彂甯冪湡瀹炰腑蹇冦傛挱绉嶄富杞 posAvailable 鏉$洰鍗冲彲瓒婅繃璇ラ棬锛屼娇寰幆姝e父鎺ョ銆 + /// 闇鍦ㄤ富杞︿笂璋冪敤锛沢etCartLocation() 鏃犲畾浣嶆椂浼氶樆濉烇紙涓庤嚜鍔ㄦā寮忎竴鑷达級銆 + /// + public bool PrimeMasterAutoFromSlam() + { + var carPos = DetourInterface.getCartLocation(); + var (lx, ly, lth) = GetLayoutPose(Conf.TestCarSyncTh, Conf.TestCarSyncDistance); + var info = BuildSelfInfo(true, true, (float)carPos.x, (float)carPos.y, (float)carPos.th, + lx, ly, lth, false); + var (cx, cy, cth) = InferFleetCenterFromCar(info); + PublishFleetCenter(cx, cy, cth); + lock (FleetLock) + { + MultiVehicleFleet[CarNum] = info; + _multiVehicleFleetSeen[CarNum] = DateTime.Now; + } + return true; + } + + public long BeginFleetMotionWarmup() + { + MultiVehicleRotateWheelsReady = false; + MultiVehicleRotateFleetReady = false; + _multiVehicleRotateAlignDetail = "fleet motion warmup pending"; + return Interlocked.Read(ref _multiVehicleNotifySeq); + } + + public bool IsFleetMotionWarmupReady(DateTime warmStartTime, long notificationSeqBaseline, + float syncTh, float syncDistance, out string detail) + { + var pending = new List(); + var requiredCount = Math.Max(1, Conf.MultiVehicleFleetNum); + lock (FleetLock) + { + if (MultiVehicleFleet.Count != requiredCount) + pending.Add($"fleetCnt={MultiVehicleFleet.Count}/{requiredCount}"); + + foreach (var kv in MultiVehicleFleet.OrderBy(k => k.Key)) + { + var carNum = kv.Key; + var info = kv.Value; + if (!_multiVehicleFleetSeen.TryGetValue(carNum, out var seen) || seen < warmStartTime) + pending.Add($"car{carNum}:notFresh"); + + var (layoutX, layoutY, layoutTh) = GetLayoutPoseForCar(carNum, syncTh, syncDistance); + if (Math.Abs(info.LayoutX - layoutX) > 1f || + Math.Abs(info.LayoutY - layoutY) > 1f || + Math.Abs(CommonMath.ThDiff(info.LayoutTh, layoutTh)) > 1f) + pending.Add( + $"car{carNum}:layout=({info.LayoutX:0},{info.LayoutY:0},{info.LayoutTh:0.0})"); + + if (!info.MotionFeasible) + pending.Add($"car{carNum}:motion={info.MotionInfeasibleReason}"); + if (!info.RotateWheelsAligned) + pending.Add($"car{carNum}:wheel={info.RotateWheelAlignDetail}"); + if (carNum != CarNum && info.AppliedNotificationSeq <= notificationSeqBaseline) + pending.Add($"car{carNum}:seq={info.AppliedNotificationSeq}<={notificationSeqBaseline}"); + } + } + + detail = pending.Count == 0 + ? $"ready seqBase={notificationSeqBaseline}" + : string.Join("; ", pending); + return pending.Count == 0; + } + + private (float, float, float) GetLayoutPose(float syncTh, float syncDistance) + => GetLayoutPoseForCar(CarNum, syncTh, syncDistance); + + private static (float, float, float) GetLayoutPoseForCar(int carNum, float syncTh, float syncDistance) + { + // Two-car layout: members are mirrored around the fleet center; car2 faces 180 deg away. + var rad = syncTh / 180f * Math.PI; + var sign = carNum == 1 ? 1f : -1f; + var xx = (float)(Math.Cos(rad) * syncDistance / 2 * sign); + var yy = (float)(Math.Sin(rad) * syncDistance / 2 * sign); + return (xx, yy, syncTh + (carNum == 1 ? 0 : 180)); + } + + private VehicleSyncInfo BuildSelfInfo(bool master, bool posAvailable, float x, float y, float th, + float layoutX, float layoutY, float layoutTh, bool aligned, bool detectOk = true) + { + ResolveMultiVehicleSelfEndpoint(out var selfIp, out var selfPort); + + return new VehicleSyncInfo + { + Master = master, + Ip = selfIp, + Port = selfPort, + PosAvailable = posAvailable, + X = x, + Y = y, + Th = th, + LayoutX = layoutX, + LayoutY = layoutY, + LayoutTh = layoutTh, + Aligned = aligned, + DetectOk = detectOk, + MotionFeasible = _multiVehicleMotionFeasible, + MotionInfeasibleReason = _multiVehicleMotionInfeasibleReason, + RotateWheelsAligned = MultiVehicleRotateWheelsReady, + RotateWheelAlignDetail = _multiVehicleRotateAlignDetail, + AppliedNotificationSeq = _multiVehicleAppliedSeq + }; + } + + private void VisualizeFleet(List contour, float egoLayoutX, float egoLayoutY, float egoLayoutTh) + { + // 鐢诲湪鏈溅杞︿綋绯伙細global=false锛屾覆鏌撴椂鐢 ClumsyLite 鍙犲姞鏈溅鐪熷疄浣嶅Э銆 + // 姣忎釜鎴愬憳鎸夆滅浉瀵规湰杞 layout 鐨勪綅濮库濈粯鍒讹紙memberInEgo = egoLayout鈦宦 鈭 memberLayout锛夛紝 + // 杩欐牱鎵嬪姩妯″紡鏃 SLAM 瀹氫綅涔熻兘姝g‘鏄剧ず缂栭槦鐩稿鍏崇郴锛涢伩鍏嶄箣鍓嶇敤杞﹂槦绯 layout 鍧愭爣鍙犲姞鏈溅浣嶅Э閫犳垚鐨勬暣浣撳钩绉汇 + var fleetPainter = UI.GetPainter("MultiVehicleFleet-vis", false); + Dictionary fleet; + lock (FleetLock) + fleet = new Dictionary(MultiVehicleFleet); + + var egoLayout = Tuple.Create((double)egoLayoutX, (double)egoLayoutY, (double)egoLayoutTh); + + Tuple MemberInEgo(float mx, float my, float mth) + => LessMath.SolveTransform2D(egoLayout, Tuple.Create((double)mx, (double)my, (double)mth)); + + void DrawContour(Color color, Tuple rel) + { + var transformed = contour + .Select(pp => LessMath.Transform2D((float)rel.Item1, (float)rel.Item2, (float)rel.Item3, pp)) + .ToList(); + for (var i = 0; i < 4; ++i) + fleetPainter.DrawLine(color, transformed[i], transformed[(i + 1) % 4]); + // 瀵硅绾夸究浜庤鲸璁ゆ湞鍚 + fleetPainter.DrawLine(color, transformed[0], transformed[2]); + fleetPainter.DrawLine(color, transformed[1], transformed[3]); + } + + fleetPainter.Clear(); + foreach (var kvp in fleet) + { + var color = kvp.Value.Master ? Color.Red : Color.Orange; + var rel = MemberInEgo(kvp.Value.LayoutX, kvp.Value.LayoutY, kvp.Value.LayoutTh); + DrawContour(color, rel); + fleetPainter.DrawText(color, $"{kvp.Key}", new Vector((float)rel.Item1, (float)rel.Item2)); + } + } + + private void FireAndForgetRegister(HttpClient hc, VehicleSyncInfo info) + { + try + { + ParseMasterEndpoint(out var masterIp, out var masterPort); + var payload = VehicleSyncBinaryCodec.EncodeRegister(CarNum, info); + var url = $"http://{masterIp}:{masterPort}/multi-vehicle-register-bin"; + _ = PostBinaryAsync(hc, url, payload, "register"); + } + catch (Exception e) + { + DLog.Log($"register binary encode failed: {e.GetBaseException().Message}", "MultiVehicle"); + } + } + + private void FireAndForgetNotify(HttpClient hc, string ip, int port, VehicleSyncNotification notification) + { + try + { + var payload = VehicleSyncBinaryCodec.EncodeNotification(notification); + var url = $"http://{ip}:{port}/multi-vehicle-notify-bin"; + _ = PostBinaryAsync(hc, url, payload, $"notify {ip}:{port}"); + } + catch (Exception e) + { + DLog.Log($"notify {ip}:{port} binary encode failed: {e.GetBaseException().Message}", "MultiVehicle"); + } + } + + private static async Task PostBinaryAsync(HttpClient hc, string url, byte[] payload, string description) + { + try + { + using var content = new ByteArrayContent(payload); + content.Headers.ContentType = + new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); + using var response = await hc.PostAsync(url, content).ConfigureAwait(false); + if (response.IsSuccessStatusCode) + return; + + DLog.Log( + $"{description} binary failed: HTTP {(int)response.StatusCode} {response.ReasonPhrase}", + "MultiVehicle"); + } + catch (Exception e) + { + DLog.Log($"{description} binary failed: {e.GetBaseException().Message}", "MultiVehicle"); + } + } + + private void ResolveMultiVehicleSelfEndpoint(out string ip, out int port) + { + ip = "127.0.0.1"; + port = WebAPI.port > 0 ? WebAPI.port : 8008; + + var endpoint = Conf.MultiVehicleSelfEndpoint; + if (string.IsNullOrWhiteSpace(endpoint)) return; + + var parts = endpoint.Trim().Split(':'); + if (parts.Length >= 1 && !string.IsNullOrWhiteSpace(parts[0])) + ip = parts[0].Trim(); + if (parts.Length >= 2 && int.TryParse(parts[1], out var p) && p > 0) + port = p; + } + + private void ParseMasterEndpoint(out string ip, out int port) + { + ip = "127.0.0.1"; + port = 8008; + var endpoint = Conf.MultiVehicleMasterEndpoint ?? "/"; + if (endpoint == "/") return; + var parts = endpoint.Split(':'); + if (parts.Length >= 1 && !string.IsNullOrWhiteSpace(parts[0])) + ip = parts[0]; + if (parts.Length >= 2 && int.TryParse(parts[1], out var p)) + port = p; + } + + private static float ClampBias(float value, float threshold) + => Math.Sign(value) * Math.Min(Math.Abs(value), threshold); + + private RotateControlParams BuildRotateControlParams(VehicleSyncNotification notification) + { + var parameters = new RotateControlParams + { + ActiveOmega = Conf.MultiVehicleRotateActiveOmega, + CompXyFac = Conf.MultiVehicleRotateCompXyFac, + CompXyIFac = Conf.MultiVehicleRotateCompXyIFac, + CompXyMax = Conf.MultiVehicleRotateCompXyMax, + CompThFac = Conf.MultiVehicleRotateCompThFac, + CompThIFac = Conf.MultiVehicleRotateCompThIFac, + CompThMax = Conf.MultiVehicleRotateCompThMax, + CompTangentFrac = NormalizeRotateCompTangentFrac(Conf.MultiVehicleRotateCompTangentFrac), + StartWheelAlignDeg = Conf.InPlaceRotateWheelAlignDeg, + ActiveWheelAlignDeg = NormalizeRotateWheelAlignDeg(Conf.InPlaceRotateActiveWheelAlignDeg, + Conf.InPlaceRotateWheelAlignDeg) + }; + + if (notification == null || !notification.RotateParamsValid) + return parameters; + + parameters.ActiveOmega = notification.RotateActiveOmega; + parameters.CompXyFac = notification.RotateCompXyFac; + parameters.CompXyIFac = notification.RotateCompXyIFac; + parameters.CompXyMax = notification.RotateCompXyMax; + parameters.CompThFac = notification.RotateCompThFac; + parameters.CompThIFac = notification.RotateCompThIFac; + parameters.CompThMax = notification.RotateCompThMax; + parameters.CompTangentFrac = NormalizeRotateCompTangentFrac(notification.RotateCompTangentFrac); + parameters.StartWheelAlignDeg = NormalizeRotateWheelAlignDeg(notification.RotateStartWheelAlignDeg, + Conf.InPlaceRotateWheelAlignDeg); + parameters.ActiveWheelAlignDeg = NormalizeRotateWheelAlignDeg(notification.RotateActiveWheelAlignDeg, + parameters.StartWheelAlignDeg); + return parameters; + } + + private static void FillRotateNotificationParams(VehicleSyncNotification notification, RotateControlParams parameters) + { + notification.RotateParamsValid = true; + notification.RotateActiveOmega = parameters.ActiveOmega; + notification.RotateCompXyFac = parameters.CompXyFac; + notification.RotateCompXyIFac = parameters.CompXyIFac; + notification.RotateCompXyMax = parameters.CompXyMax; + notification.RotateCompThFac = parameters.CompThFac; + notification.RotateCompThIFac = parameters.CompThIFac; + notification.RotateCompThMax = parameters.CompThMax; + notification.RotateCompTangentFrac = parameters.CompTangentFrac; + notification.RotateStartWheelAlignDeg = parameters.StartWheelAlignDeg; + notification.RotateActiveWheelAlignDeg = parameters.ActiveWheelAlignDeg; + } + + private static float NormalizeRotateWheelAlignDeg(float value, float fallback) + { + if (float.IsNaN(value) || float.IsInfinity(value) || value <= 0) + return fallback; + return value; + } + + private static float NormalizeRotateCompTangentFrac(float frac) + { + if (float.IsNaN(frac) || float.IsInfinity(frac) || frac < 0) + return DefaultRotateCompTangentFrac; + return frac; + } + + private void LimitRotateCompensation(ref float compVx, ref float compVy, ref float compOmega, + float absOmega, float controlRadius, float tangentFrac) + { + var frac = NormalizeRotateCompTangentFrac(tangentFrac); + if (frac < 0 || absOmega <= 1e-6f) return; + + var rawVx = compVx; + var rawVy = compVy; + var rawOmega = compOmega; + var tangentMmps = absOmega / 180f * (float)Math.PI * Math.Max(1f, Math.Abs(controlRadius)); + var xyLimit = tangentMmps * frac; + var xyMag = (float)Math.Sqrt(compVx * compVx + compVy * compVy); + if (xyMag > xyLimit && xyMag > 1e-6f) + { + var scale = xyLimit / xyMag; + compVx *= scale; + compVy *= scale; + } + + var omegaLimit = absOmega * frac; + compOmega = ClampBias(compOmega, omegaLimit); + + var changed = Math.Abs(rawVx - compVx) > 1e-3f || + Math.Abs(rawVy - compVy) > 1e-3f || + Math.Abs(rawOmega - compOmega) > 1e-3f; + var now = DateTime.Now; + if (changed && (now - _mvRotateCompLimitLastLog).TotalMilliseconds >= 200) + { + _mvRotateCompLimitLastLog = now; + DLog.Log( + $"car{CarNum} ROTATE_COMP_LIMIT frac={frac:0.00} omega={absOmega:0.000} radius={controlRadius:0} " + + $"tan={tangentMmps:0.0} xyLimit={xyLimit:0.0} omLimit={omegaLimit:0.000} " + + $"raw=({rawVx:0.0},{rawVy:0.0},{rawOmega:0.000}) " + + $"limited=({compVx:0.0},{compVy:0.0},{compOmega:0.000})", + "MultiVehicleRemoteDbg"); + } + } + + private void ResetMultiVehicleRotateCenterDrift() + { + _mvRotateCenterDriftActive = false; + _mvRotateCenterMaxDrift = 0; + _mvRotateCenterLastLog = DateTime.MinValue; + } + + private void LogMultiVehicleRotateCenterDrift(bool isMaster, bool manualEnabled, bool autoEnabled, + bool fleetReady, bool canMove, bool rotating, float centerX, float centerY, float centerTh, + float requestedOmega, float fleetOmega, float compVx, float compVy, float compOmega) + { + if (!_mvRotateCenterDriftActive) + { + _mvRotateCenterDriftActive = true; + _mvRotateCenterStartX = centerX; + _mvRotateCenterStartY = centerY; + _mvRotateCenterStartTh = centerTh; + _mvRotateCenterMaxDrift = 0; + _mvRotateCenterLastLog = DateTime.MinValue; + } + + var dx = centerX - _mvRotateCenterStartX; + var dy = centerY - _mvRotateCenterStartY; + var drift = (float)Math.Sqrt(dx * dx + dy * dy); + _mvRotateCenterMaxDrift = Math.Max(_mvRotateCenterMaxDrift, drift); + var dth = (float)CommonMath.ThDiff(centerTh, _mvRotateCenterStartTh); + var now = DateTime.Now; + if ((now - _mvRotateCenterLastLog).TotalMilliseconds < 250) + return; + + _mvRotateCenterLastLog = now; + DLog.Log( + $"car{CarNum} CTRL master={isMaster} manual={manualEnabled} auto={autoEnabled} " + + $"ready={fleetReady} canMove={canMove} rotating={rotating} " + + $"center=({centerX:0.0},{centerY:0.0},{centerTh:0.00}) " + + $"start=({_mvRotateCenterStartX:0.0},{_mvRotateCenterStartY:0.0},{_mvRotateCenterStartTh:0.00}) " + + $"drift=({dx:0.0},{dy:0.0}) dist={drift:0.0} max={_mvRotateCenterMaxDrift:0.0} dth={dth:0.00} " + + $"omegaReq={requestedOmega:0.000} omega={fleetOmega:0.000} comp=({compVx:0.0},{compVy:0.0},{compOmega:0.000})", + "FleetRotateCenterDbg"); + } + + /// + /// 鍘熷湴鏃嬭浆绾犲亸鍗曡酱 PI 鎺у埗鍣ㄣ俥rr 涓鸿溅浣撶郴鍋忓樊(mm 鎴 deg)锛岃緭鍑轰负淇閫熷害(mm/s 鎴 deg/s)锛 + /// 甯︽鍖恒佺Н鍒嗘姉楗卞拰(闄愬埗绉垎璐$尞鍦 卤max 鍐)涓庢昏緭鍑洪檺骞呫傛鍖哄唴鍐荤粨绉垎(淇濈暀绋虫佷慨姝d互鎶垫秷鎭掑畾鎵板姩)銆 + /// + private static float RotatePiTerm(float err, ref float integ, float deadband, + float pFac, float iFac, float max, float dt, bool allowIntegrate = true) + { + // 姝诲尯鍐咃細涓嶅啀绱姞璇樊锛屼粎杈撳嚭宸茬Н绱殑绉垎椤(缁存寔瀵规亽瀹氭壈鍔ㄧ殑绋虫佽ˉ鍋)銆 + if (Math.Abs(err) < deadband) + return ClampBias(integ * iFac, max); + + // 鏉′欢绉垎(鎶 windup)锛氫粎褰 (a) 鍏佽绉垎(鑸佃疆宸插榻愩佽溅鍦ㄧ湡姝h浆鍔) 涓 + // (b) 鎬昏緭鍑烘湭鍦ㄥ悓鍚戦ケ鍜 鏃舵墠绱姞璇樊銆 + // allowIntegrate=false锛氫笂涓鎷嶈埖杞湭瀵归綈(gate=0銆佽溅娌″姩)锛屾鏃剁Н鍒嗚宸槸绾 windup锛 + // 浼氳绾犲亸瓒婄Н瓒婂ぇ銆佽埖杞洿瀵逛笉榻 鈫 鍘熷湴鍗℃锛涙晠鍐荤粨绉垎(淇濈暀宸叉湁鍊硷紝浠呰緭鍑 P+宸茬Н鍒)銆 + // 鍚屽悜楗卞拰鍋滅Н鍒嗭細璧锋澶ц宸 P 椤舵弧 max 鏃剁户缁Н鍒嗕細椤舵弧绉垎鍣紝璇樊鍙嶅悜鍚庢硠鏀炬參銆侀犳垚杩囧啿鍥炴媺銆 + var unclamped = err * pFac + integ * iFac; + var saturatedSameSign = Math.Abs(unclamped) >= max && Math.Sign(unclamped) == Math.Sign(err); + if (allowIntegrate && !saturatedSameSign) + integ += err * dt; + + var iTerm = integ * iFac; + // 鎶楃Н鍒嗛ケ鍜岋細鎶婄Н鍒嗚础鐚檺鍒跺湪 卤max锛屽苟鍙嶇畻鍥炲啓绉垎鍣紝閬垮厤 windup銆 + if (iFac > 1e-9f) + { + var iLimit = max / iFac; + if (integ > iLimit) integ = iLimit; + else if (integ < -iLimit) integ = -iLimit; + iTerm = integ * iFac; + } + + return ClampBias(err * pFac + iTerm, max); + } + + /// + /// 涓昏溅涓撶敤锛氶氳繃 Playground WebAPI 璇诲彇鏈溅涓庨偦杞︾殑鐪熷疄 sim 浣嶅Э锛岃惤 RotatePoseDbg 鏃ュ織銆 + /// 閲忓寲"寮鐜í鍚戞粦绉"鏉ユ簮锛 + /// - w1/w2/dw锛氫袱杞﹀疄闄呭亸鑸閫熺巼(deg/s)銆俤w 鎸佺画闈為浂 鈬 涓讳粠杞熶笉涓鑷(鐩稿鏃嬭浆)銆 + /// - rel_in1(x,y,dyaw)锛氶偦杞﹀湪鏈溅浣撶郴涓嬬殑鐪熷疄鐩稿浣嶅Э锛沝yaw=瀹為檯鐩稿鏈濆悜鈭180掳銆 + /// dyaw鈮0 浣 y 鎸佺画婕 鈬 绾í鍚戝钩绉绘粦绉(闈炶搴︽粸鍚庯紝鍗拌瘉 B 鏃犵敤)銆 + /// - midDrift锛氳溅闃熷嚑浣曚腑蹇(涓栫晫绯)鐩稿璧疯浆鐬棿鐨勪綅绉 鈬 鏁翠綋骞崇Щ婕傜Щ閲忋 + /// 鑺傛祦 ~200ms锛沇ebAPI 寮傚父鏃堕潤榛樿烦杩囷紝涓嶅奖鍝嶆帶鍒剁幆銆 + /// + private void LogRotatePoseSample() + { + if (!Conf.MultiVehicleRotatePoseWebApiDiagEnabled) return; + + var now = DateTime.Now; + if ((now - _rotPoseLastLog).TotalMilliseconds < 200) return; + _rotPoseLastLog = now; + + var neighbor = Conf.PlaygroundNeighborRobotName; + if (string.IsNullOrWhiteSpace(neighbor) || neighbor == Conf.PlaygroundRobotName) return; + + try + { + var p1 = PlaygroundWebApi.GetPose(Conf.PlaygroundWebApiUrl, Conf.PlaygroundRobotName); + var p2 = PlaygroundWebApi.GetPose(Conf.PlaygroundWebApiUrl, neighbor); + + // 閭昏溅鍦ㄦ湰杞(car1)浣撶郴涓嬬殑鐩稿浣嶅Э锛歳el = R(-yaw1)路(p2-p1) + var ddx = p2.X - p1.X; + var ddy = p2.Y - p1.Y; + var th1 = p1.YawDeg * (float)Math.PI / 180f; + var c = (float)Math.Cos(th1); + var s = (float)Math.Sin(th1); + var relX = ddx * c + ddy * s; + var relY = -ddx * s + ddy * c; + var relYaw = (float)LessMath.ThDiff(p2.YawDeg - p1.YawDeg, 180f); // 瀹為檯鐩稿鏈濆悜鍋忕 180掳 鐨勯噺 + var dist = (float)Math.Sqrt(ddx * ddx + ddy * ddy); + + var midX = (p1.X + p2.X) / 2f; + var midY = (p1.Y + p2.Y) / 2f; + if (!_rotPoseEpisode) + { + _rotPoseEpisode = true; + _rotPoseMid0X = midX; + _rotPoseMid0Y = midY; + } + var midDx = midX - _rotPoseMid0X; + var midDy = midY - _rotPoseMid0Y; + + // 瀹為檯鍋忚埅瑙掗熺巼锛堟暟鍊煎井鍒嗭級 + float w1 = 0, w2 = 0, dw = 0; + if (_rotPosePrevTime != DateTime.MinValue) + { + var dt = (float)(now - _rotPosePrevTime).TotalSeconds; + if (dt > 1e-3) + { + w1 = (float)LessMath.ThDiff(p1.YawDeg, _rotPosePrevYaw1) / dt; + w2 = (float)LessMath.ThDiff(p2.YawDeg, _rotPosePrevYaw2) / dt; + dw = w1 - w2; + } + } + _rotPosePrevTime = now; + _rotPosePrevYaw1 = p1.YawDeg; + _rotPosePrevYaw2 = p2.YawDeg; + + DLog.Log( + $"car1({p1.X:F0},{p1.Y:F0},{p1.YawDeg:F2}) car2({p2.X:F0},{p2.Y:F0},{p2.YawDeg:F2}) " + + $"| rel_in1(x:{relX:F0} y:{relY:F0} dyaw:{relYaw:F2}) dist:{dist:F0} " + + $"| mid({midX:F0},{midY:F0}) midDrift(dx:{midDx:F0} dy:{midDy:F0} |d|:{Math.Sqrt(midDx * midDx + midDy * midDy):F0}) " + + $"| w1:{w1:F2} w2:{w2:F2} dw:{dw:F2}", + "RotatePoseDbg"); + } + catch (Exception e) + { + // 璇婃柇鐢ㄩ旓紝WebAPI 涓嶉氭椂闈欓粯锛堜粎鍋跺彂鎻愮ず锛夛紝涓嶆墦鏂帶鍒剁幆銆 + Hedingben.ToastText($"RotatePose WebAPI err: {e.Message}", $"MultiVehicle{CarNum}-rotpose"); + } + } + + #endregion +} diff --git a/ClumsyPilot/PlaygroundWebApi.cs b/ClumsyPilot/PlaygroundWebApi.cs new file mode 100644 index 0000000..03ace8e --- /dev/null +++ b/ClumsyPilot/PlaygroundWebApi.cs @@ -0,0 +1,81 @@ +using System; +using System.Net.Http; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MultiWheelC; + +/// +/// Playground 浠跨湡鍣 HTTP Web API 杞婚噺瀹㈡埛绔細鏌ヨ灏忚溅浣嶅Э銆佺灛绉诲皬杞︺ +/// 鏈嶅姟绔疄鐜拌 Playground/Web/PlaygroundWebApi.cs锛岄粯璁ょ洃鍚 http://localhost:18090銆 +/// 鍧愭爣鍗曚綅 mm锛屾湞鍚 yawDeg 鍗曚綅涓哄害锛屼笘鐣屽潗鏍囩郴涓庡満鏅 JSON 涓鑷淬 +/// +public static class PlaygroundWebApi +{ + // 绂佺敤绯荤粺浠g悊锛氭湰鏈 Playground 璧 localhost锛岃嫢缁忕郴缁熶唬鐞(濡 127.0.0.1:7890)浼氳繛鎺ュけ璐ャ + private static readonly HttpClient Http = new HttpClient(new HttpClientHandler { UseProxy = false }) + { + Timeout = TimeSpan.FromSeconds(3) + }; + + public struct Pose + { + public float X; + public float Y; + public float YawDeg; + } + + /// 鏌ヨ鍗曞彴灏忚溅鐨勪笘鐣屼綅濮裤侴ET /api/robots/{name}銆 + public static Pose GetPose(string baseUrl, string robotName) + { + var url = $"{baseUrl.TrimEnd('/')}/api/robots/{Uri.EscapeDataString(robotName)}"; + var json = Http.GetStringAsync(url).GetAwaiter().GetResult(); + var o = JObject.Parse(json); + return new Pose + { + X = o.Value("x"), + Y = o.Value("y"), + YawDeg = o.Value("yawDeg") + }; + } + + /// 灏嗗皬杞︾灛绉诲埌鐩爣涓栫晫浣嶅Э銆侾OST /api/robots/{name}/move銆 + public static void Move(string baseUrl, string robotName, float x, float y, float yawDeg) + { + var url = $"{baseUrl.TrimEnd('/')}/api/robots/{Uri.EscapeDataString(robotName)}/move"; + var body = JsonConvert.SerializeObject(new { x, y, yaw = yawDeg, stop = true }); + using var content = new StringContent(body, Encoding.UTF8, "application/json"); + var resp = Http.PostAsync(url, content).GetAwaiter().GetResult(); + resp.EnsureSuccessStatusCode(); + } + + /// 鏌ヨ杞﹁締杩愬姩鏄惁鍚敤锛堟殏鍋滄椂涓 false锛夈侴ET /api/motion銆 + public static bool MotionEnabled(string baseUrl) + { + var url = $"{baseUrl.TrimEnd('/')}/api/motion"; + var json = Http.GetStringAsync(url).GetAwaiter().GetResult(); + return JObject.Parse(json).Value("motionEnabled"); + } + + /// 鎭㈠杞﹁締杩愬姩銆侾OST /api/motion/resume銆 + public static void ResumeMotion(string baseUrl) + { + var url = $"{baseUrl.TrimEnd('/')}/api/motion/resume"; + var resp = Http.PostAsync(url, null).GetAwaiter().GetResult(); + resp.EnsureSuccessStatusCode(); + } + + /// + /// 鏆傚仠杞﹁締杩愬姩锛堜粎鍐荤粨杩愬姩锛屼笉鍋滄浠跨湡锛涗紶鎰熷櫒缁х画鎵弿锛夈侾OST /api/motion/pause銆 + /// feedback: "zero"(榛樿,鍙嶉褰掗浂) / "none"(涓嶄笂鎶) / "hold"(淇濈暀鏆傚仠鐬棿鍊)銆 + /// + public static void PauseMotion(string baseUrl, string feedback = "zero") + { + var url = $"{baseUrl.TrimEnd('/')}/api/motion/pause"; + var body = JsonConvert.SerializeObject(new { feedback }); + using var content = new StringContent(body, Encoding.UTF8, "application/json"); + var resp = Http.PostAsync(url, content).GetAwaiter().GetResult(); + resp.EnsureSuccessStatusCode(); + } +} diff --git a/ClumsyPilot/TireFollowing.cs b/ClumsyPilot/TireFollowing.cs new file mode 100644 index 0000000..049d572 --- /dev/null +++ b/ClumsyPilot/TireFollowing.cs @@ -0,0 +1,511 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Numerics; +using System.Reflection; +using System.Text; +using System.Threading; +using ClumsyCore; +using ClumsyCore.DTools; +using ClumsyCore.Interfaces; +using ClumsyCore.Pilot; +using ClumsyCore.Utilities; +using ClumsyDance.ClumsyWalk.Detectors; +using CommonUsage.Chassis; +using FundamentalLib; +using MDCSToolBox; +using MDCSToolBox.Clumsy.Calibration; +using MDCSToolBox.Clumsy.MotionControllers; +using MDCSToolBox.Clumsy.Movements; +using MDCSToolBox.Clumsy.Pilot; +using MDCSToolBox.Clumsy.Tracks; +using MDCSToolBox.Commons.Controllers; +using static ClumsyCore.DTools.Painter; +using LineSegment = ClumsyCore.Utilities.LineSegment; + +namespace MultiWheelC +{ + public class TireFollowing : MovementDefinition + { + public Func GetController; + + /// + /// 杞﹁締鏂瑰悜 + /// + public float CarDirection = 0; + + /// + /// 鍋滄璺濈 + /// + //public float FinishDistance = 1000; + + /// + /// 鍑忛熻窛绂 + /// + public float SlowDistance = 1000; + + /// + /// 鏈澶ч熷害 + /// + public float MaxSpeed = 0.3f; + + // 鏈琛旀帴锛氭帴杩戠洸璧扮粓鐐规椂缁欓潪闆堕熷害锛屼緵鍚庣画鍔ㄤ綔杩炵画鎺ョ + public bool EnableHandover = false; + public float HandoverDistance = 200f; // mm + public float HandoverSpeed = 0.2f; // m/s + + /// + /// 閽昏疆鑳庢暟閲 + /// + public int TireNum = 1; + + /// + /// 鐩茶蛋瑙掑害鍋忕Щ + /// + public float WalkBlindTh = -1f; + + /// + /// 鏄惁妫娴嬪埌鐩爣 + /// + public bool NoTarget = false; + + public float GuessRangeX; + + public float GuessRangeY; + + /// + /// 妫娴嬪櫒瀹氫箟 + /// + public class DetectorDefinition + { + /// + /// 寮濮嬫娴嬭窛绂 + /// + public float StartGuessingX; + + /// + /// 寮濮嬫娴嬭窛绂 + /// + public float StartGuessingY; + + /// + /// 妫娴嬪嚱鏁 + /// + public Func, LineSegment> DetectFunction = null; + + public Action LeaveSrcFunction = null; + + public int SrcId = -1; + public int DstId = -1; + + /// + /// 璺緞鍋忕Щ + /// + public Tuple PathTransformation = Tuple.Create(0f, 0f, 0f); + + public float PathTransformationAnchorDistance = 0f; + + /// + /// 鍒囨崲鏉′欢 + /// + public Func SwitchWalkBlindCondition = null; + + /// + /// 鐩茶蛋鍋滄璺濈 + /// + public Func FinishWalkBlindCondition = null; + } + + public Func FinishCondition; + + /// + /// 澶氫釜妫娴嬪櫒鍒楄〃 + /// + public List detectors = null; + + private Painter _painter; + private List _remainDistanceList = new List(); + private List _remainAngleList = new List(); + private List _targetYList = new List(); + + private List SetFilters(float guessCenterX, float guessCenterY) + { + var painter = UI.GetPainter("GeneralFollowing.SetFilters", false); + painter.Clear(); + painter.Clear(3000); + + var box = new Vector2[] + { + new (guessCenterX - GuessRangeX, guessCenterY - GuessRangeY), + new (guessCenterX + GuessRangeX, guessCenterY - GuessRangeY), + new (guessCenterX + GuessRangeX, guessCenterY + GuessRangeY), + new (guessCenterX - GuessRangeX, guessCenterY + GuessRangeY), + }; + + for (var i = 0; i < box.Length; ++i) + painter.DrawLine(Color.DarkOliveGreen, box[i], box[(i + 1) % 4]); + + // PC filter in car coordinate frame + return new List() + { + new(CoordinateSystem.Car2D, + p => LessMath.IsPointInPolygon4( + box.Select(v => new PointF(v.X, v.Y)).ToArray(), new PointF(p.X, p.Y))), + }; + } + + public void Stop() + { + _dt?.Stop(); + } + + /// + ///璁$畻杞︿綋涓績鐨勪綅绉诲拰瑙掑害澧為噺 + /// + /// a杞湪杞︿綋鍧愭爣绯讳笅浣嶇疆 + /// a杞湪杞︿綋鍧愭爣绯讳笅浣嶇Щ澧為噺 + /// b杞湪杞︿綋鍧愭爣绯讳笅浣嶇疆 + /// b杞湪杞︿綋鍧愭爣绯讳笅浣嶇Щ澧為噺 + /// + private static (float, float, float) CenterMoveFromPoints(Vector2 a, + Vector2 aDelta, + Vector2 b, + Vector2 bDelta) + { + float th_x = 0, th_y = 0, th = 0, x = 0, y = 0; + var eps = 0.0000001; + if (Math.Abs(a.Y - b.Y) > eps) + { + th_x = (aDelta.X - bDelta.X) / (b.Y - a.Y); + } + if (Math.Abs(a.X - b.X) > eps) + { + th_y = (aDelta.Y - bDelta.Y) / (a.X - b.X); + } + th = th_x == 0 ? th_y : th_x; + + x = (aDelta.X + bDelta.X) / 2f - (a.Y - b.Y) / 2f * th; + + y = (aDelta.Y + bDelta.Y) / 2f + (a.X - b.X) / 2f * th; + + return (x, y, th); + } + + + public override IEnumerable Get() + { + _painter = UI.GetPainter("GeneralFollowing", false); + var lastDetectX = detectors[0].StartGuessingX; + var lastDetectY = detectors[0].StartGuessingY; + var detectorIndex = 0; + + var controller = (MultiWheelGeometricController)GetController.Invoke(); + controller.BaseSpeed = MaxSpeed; + controller.FinishDistance = float.MinValue; + controller.FirstThAccuracy = 999; + _dt = new DriveTask(controller.Track(true, CoordinateSystem.Car2D)); + void HardStop() + { + _dt?.Stop(); + ((MultiWheelChassis)PilotDefinition.Chassis).DriveStop(); + DLog.Log($"Hard Stop!", "TireFollowing"); + } + float WalkBlindCarPathDstX = -1f, WalkBlindCarPathDstY = -1f, WalkBlindCarPathDstTh = -1f; + bool WalkBlindStage1 = false, WalkBlindStage2 = false; + var angle2target = -1f; + float _lastLFLEncoder = -1, _lastLFREncoder = -1, _lastRFLEncoder = -1, _lastRFREncoder = -1; + float _lastLRLEncoder = -1, _lastLRREncoder = -1, _lastRRLEncoder = -1, _lastRRREncoder = -1; + + (float, float, float) GetCurrentPos2Dst(float lastX, float lastY, float lastTh) + { + // Read current encoders + var curLFLEncoder = PilotDefinition.Self.LFLActualPos; + var curLFREncoder = PilotDefinition.Self.LFRActualPos; + var curRFLEncoder = PilotDefinition.Self.RFLActualPos; + var curRFREncoder = PilotDefinition.Self.RFRActualPos; + var curLRLEncoder = PilotDefinition.Self.LRLActualPos; + var curLRREncoder = PilotDefinition.Self.LRRActualPos; + var curRRLEncoder = PilotDefinition.Self.RRLActualPos; + var curRRREncoder = PilotDefinition.Self.RRRActualPos; + + // Average delta per wheel pair (LF, LR, RF, RR) + var lfDelta = (curLFLEncoder - _lastLFLEncoder + curLFREncoder - _lastLFREncoder) / 2f; + var lrDelta = (curLRLEncoder - _lastLRLEncoder + curLRREncoder - _lastLRREncoder) / 2f; + var rfDelta = (curRFLEncoder - _lastRFLEncoder + curRFREncoder - _lastRFREncoder) / 2f; + var rrDelta = (curRRLEncoder - _lastRRLEncoder + curRRREncoder - _lastRRREncoder) / 2f; + var deltaList = new List { lfDelta, lrDelta, rfDelta, rrDelta }; + + var xs = new List(); + var ys = new List(); + var ths = new List(); + var chassis = (MultiWheelChassis)BasicPilotBase.Chassis; + var steerWheels = chassis.GetSteerWheels(); + for (var i = 0; i < steerWheels.Count; ++i) + { + var sw1 = steerWheels[i]; + var a = sw1.Position; + var tha = sw1.ReadAngle() / 180f * (float)Math.PI; + var deltaa = deltaList[i]; + var va = new Vector2(deltaa * (float)Math.Cos(tha), deltaa * (float)Math.Sin(tha)); + for (var j = i + 1; j < steerWheels.Count; ++j) + { + var sw2 = steerWheels[j]; + var b = sw2.Position; + var thb = sw2.ReadAngle() / 180f * (float)Math.PI; + var deltab = deltaList[j]; + var vb = new Vector2(deltab * (float)Math.Cos(thb), deltab * (float)Math.Sin(thb)); + var (tempx, tempy, tempth) = CenterMoveFromPoints(a, va, b, vb); + Hedingben.ToastText($"{tempx:f2} {tempy:f2} {tempth / Math.PI * 180f:f2} ", $"{i}_{j}"); + xs.Add(tempx); + ys.Add(tempy); + ths.Add(tempth); + } + } + var x = xs.Average(); + var y = ys.Average(); + var Th = ths.Average() / (float)Math.PI * 180; + var moveTup = Tuple.Create(x, y, Th); + var moved = MathTools.SolveTransform2D(MathTools.SolveTransform2D(Tuple.Create(lastX, lastY, lastTh), moveTup), Tuple.Create(0f, 0f, 0f)); + + _lastLFLEncoder = curLFLEncoder; + _lastLFREncoder = curLFREncoder; + _lastRFLEncoder = curRFLEncoder; + _lastRFREncoder = curRFREncoder; + _lastLRLEncoder = curLRLEncoder; + _lastLRREncoder = curLRREncoder; + _lastRRLEncoder = curRRLEncoder; + _lastRRREncoder = curRRREncoder; + return (moved.Item1, moved.Item2, moved.Item3); + } + + while (true) + { + if (detectorIndex > detectors.Count - 1) + throw new Exception("detector index out of range!"); + + _painter.Clear(); + if (WalkBlindStage1 || WalkBlindStage2) + { + //绗簩娆$洸璧版椂鎴栧彧閽讳竴涓疆鑳庢椂 + if (WalkBlindStage2 || detectors.Count == 1 || TireNum == 1) + { + //controller.FinishDistance = 10f; + controller.SlowDistance = SlowDistance; + controller.SlowingPow = 0.7f; + } + if (EnableHandover) + { + controller.SlowDistance = float.MinValue; + controller.FinishSpeed = 0.2f; + controller.FinishDistance = 50; + } + (WalkBlindCarPathDstX, WalkBlindCarPathDstY, WalkBlindCarPathDstTh) = GetCurrentPos2Dst(WalkBlindCarPathDstX, WalkBlindCarPathDstY, WalkBlindCarPathDstTh); + var walkBlindPathEnd = Tuple.Create(WalkBlindCarPathDstX, WalkBlindCarPathDstY, WalkBlindCarPathDstTh); + var walkBlindPathStart = LessMath.Transform2D(walkBlindPathEnd, Tuple.Create(CarDirection == 0 ? -3000f : 3000f, 0f, 0f)); + var walkBlindPathDst = new Vector2(WalkBlindCarPathDstX, WalkBlindCarPathDstY); + var walkBlindPathSrc = new Vector2(walkBlindPathStart.Item1, walkBlindPathStart.Item2); + var walkBlindPath = new LineSegment(walkBlindPathSrc, walkBlindPathDst); + + DLog.Log($"鐩茶蛋鐩爣鐐:{walkBlindPath.Src.X:F2} {walkBlindPath.Src.Y:F2} {walkBlindPath.Dst.X:F2} {walkBlindPath.Dst.Y:F2}", "TireFollowing"); + _painter.DrawDot(Color.Purple, walkBlindPathDst, sz: 3); + _painter.DrawLine(Color.GreenYellow, walkBlindPath.Src, walkBlindPath.Dst, endArrow: true, width: 2); + + var track = new LineTrack(walkBlindPath.Src, walkBlindPath.Dst); + track.CarDirectionBias = CarDirection; + controller.UpdateTracks(new List { track }); + var rd = (float)LessMath.PerpendicularPosition(0, 0, walkBlindPath.Dst.X, walkBlindPath.Dst.Y, + walkBlindPath.Src.X, walkBlindPath.Src.Y); + _remainDistanceList.Add(rd); + while (_remainDistanceList.Count > 3) _remainDistanceList.RemoveAt(0); + rd = _remainDistanceList.Average(); + DLog.Log($"鐩茶蛋鎶曞奖鐐瑰墿浣欒窛绂:{rd:0.0} ", "TireFollowing"); + // 妫鏌ユ槸鍚﹁揪鍒扮洸璧扮粨鏉熸潯浠 + if (detectors[detectorIndex].FinishWalkBlindCondition(rd)) + { + if (WalkBlindStage1) + { + DLog.Log("杈惧埌绗竴娆$洸璧板仠姝㈣窛绂伙紝鍋滀笅鎴栧紑濮嬮捇绗簩瀵硅疆鑳", "TireFollowing"); + //if (detectors[detectorIndex].DstId != -1 && detectors[detectorIndex].LeaveSrcFunction != null) + //{ + // detectors[detectorIndex].LeaveSrcFunction(detectors[detectorIndex].DstId); + // DLog.Log($"閲婃斁鍙栬溅鐐箋detectors[detectorIndex].DstId}", "TireFollowing"); + //} + WalkBlindStage1 = false; + _remainAngleList.Clear(); + _remainDistanceList.Clear(); + detectorIndex++; + if ((detectors.Count == 1 || TireNum == 1) && !EnableHandover) + { + HardStop(); + yield return false; + } + } + else if (WalkBlindStage2) + { + DLog.Log("杈惧埌绗簩瀵硅疆鑳庡锛屽仠姝㈢Щ鍔", "TireFollowing"); + if (!EnableHandover) + { + HardStop(); + } + yield return false; + } + } + yield return true; + continue; + } + + var target = detectors[detectorIndex].DetectFunction(CarDirection, lastDetectX, + SetFilters(lastDetectX, lastDetectY)); + + if (target == null) + { + DLog.Log("鏃犵洰鏍囷紝绛夊緟涓嬩竴甯", "TireFollowing"); + controller.FirstRotateMaxSpeed = 0; + yield return true; + continue; + } + else controller.FirstRotateMaxSpeed = 5; + + var targetAngle = CalculateAngle2YAxis(target.Src, target.Dst); + var targetPos = new Vector2((target.Src.X + target.Dst.X) / 2f, (target.Src.Y + target.Dst.Y) / 2f); + var dis2target = (float)Math.Sqrt(Math.Pow(targetPos.X, 2) + Math.Pow(targetPos.Y, 2)); + //璺濈杈冭繎浠ュ悗瑙掑害瀹规槗璺冲彉 + if (dis2target < PilotDefinition.Conf.TireFollowingCloseDistance && Math.Abs(targetAngle) > PilotDefinition.Conf.TireFollowingAngleIgnoreThr) + { + yield return true; + continue; + } + else _remainAngleList.Add(targetAngle); + while (_remainAngleList.Count > 10) _remainAngleList.RemoveAt(0); + angle2target = _remainAngleList.Average(); + var distanceLabelPos = targetPos / 2f; + _painter.DrawLine(Color.Cyan, Vector2.Zero, targetPos, width: 2); + _painter.DrawText(Color.Yellow, $"{dis2target:F3}", distanceLabelPos.X, distanceLabelPos.Y); + + var path = DetectorHelper.GetApproachPath(target, CoordinateSystem.Car2D, pathLen: 3000, + bias: detectors[detectorIndex].PathTransformation, + biasAnchorDistance: detectors[detectorIndex].PathTransformationAnchorDistance); + + if (path == null) + { + DLog.Log("no path!", "TireFollowing"); + NoTarget = true; + } + else + { + lastDetectX = ((target.Src + target.Dst) / 2f).X; + lastDetectY = ((target.Src + target.Dst) / 2f).Y; + + var currentY = path.CarPath.Dst.Y; + if (Math.Abs(targetAngle) < PilotDefinition.Conf.TireFollowingAngleIgnoreThr && + dis2target < PilotDefinition.Conf.TireFollowingCloseDistance) + { + _targetYList.Add(currentY); + while (_targetYList.Count > PilotDefinition.Conf.TireFollowingYAverageFrameCount) _targetYList.RemoveAt(0); + } + + var trackDstY = _targetYList.Count > 0 ? _targetYList.Average() : currentY; + Hedingben.ToastText($"target Y:{_targetYList.Count} {trackDstY}", "target Y"); + + var trackDst = new Vector2(path.CarPath.Dst.X, trackDstY); + _painter.DrawLine(Color.GreenYellow, path.CarPath.Src, trackDst, endArrow: true); + + var rd = (float)LessMath.PerpendicularPosition(0, 0, trackDst.X, trackDst.Y, + path.CarPath.Src.X, path.CarPath.Src.Y); + _remainDistanceList.Add(rd); + while (_remainDistanceList.Count > 3) _remainDistanceList.RemoveAt(0); + rd = _remainDistanceList.Average(); + _painter.DrawText(Color.Green, $"{rd:F3}", distanceLabelPos.X, distanceLabelPos.Y - 200); + if(rd < PilotDefinition.Conf.TireFollowingReleaseDistance) + { + if (detectors[detectorIndex].SrcId != -1 && detectors[detectorIndex].LeaveSrcFunction != null) + { + detectors[detectorIndex].LeaveSrcFunction(detectors[detectorIndex].SrcId); + DLog.Log($"閲婃斁棰勫彇杞︾偣{detectors[detectorIndex].SrcId}", "TireFollowing"); + } + } + + if (detectorIndex < detectors.Count - 1) + { + controller.SlowDistance = 1; + if (detectors[detectorIndex].SwitchWalkBlindCondition(rd)) + { + WalkBlindStage1 = true; + //if (detectors[detectorIndex].SrcId != -1 && detectors[detectorIndex].LeaveSrcFunction != null) + //{ + // detectors[detectorIndex].LeaveSrcFunction(detectors[detectorIndex].SrcId); + // DLog.Log($"閲婃斁棰勫彇杞︾偣{detectors[detectorIndex].SrcId}", "TireFollowing"); + //} + WalkBlindCarPathDstX = trackDst.X; + WalkBlindCarPathDstY = trackDst.Y; + WalkBlindCarPathDstTh = angle2target + WalkBlindTh; + DLog.Log($"鍒囨崲鑷崇涓娆$洸璧版椂鍒荤洰鏍囩偣:{WalkBlindCarPathDstX:F2} " + + $"{WalkBlindCarPathDstY:F2} " + + $"{WalkBlindCarPathDstTh:F2}", "TireFollowing"); + _lastLFLEncoder = PilotDefinition.Self.LFLActualPos; + _lastLFREncoder = PilotDefinition.Self.LFRActualPos; + _lastRFLEncoder = PilotDefinition.Self.RFLActualPos; + _lastRFREncoder = PilotDefinition.Self.RFRActualPos; + _lastLRLEncoder = PilotDefinition.Self.LRLActualPos; + _lastLRREncoder = PilotDefinition.Self.LRRActualPos; + _lastRRLEncoder = PilotDefinition.Self.RRLActualPos; + _lastRRREncoder = PilotDefinition.Self.RRRActualPos; + _remainDistanceList.Clear(); + _targetYList.Clear(); + lastDetectX = detectors[detectorIndex + 1].StartGuessingX; + lastDetectY = detectors[detectorIndex + 1].StartGuessingY; + continue; + } + } + else if (detectorIndex == detectors.Count - 1) + { + if (detectors[detectorIndex].SwitchWalkBlindCondition(rd)) + { + WalkBlindStage2 = true; + WalkBlindCarPathDstX = trackDst.X; + WalkBlindCarPathDstY = trackDst.Y; + WalkBlindCarPathDstTh = angle2target + WalkBlindTh; + DLog.Log($"鍒囨崲鑷虫渶鍚庝竴娆$洸璧版椂鍒荤洰鏍囩偣:{WalkBlindCarPathDstX:F2} " + + $"{WalkBlindCarPathDstY:F2} " + + $"{WalkBlindCarPathDstTh:F2}", "TireFollowing"); + if (detectors.Count == 1) + { + if (detectors[detectorIndex].SrcId != -1 && detectors[detectorIndex].LeaveSrcFunction != null) + { + detectors[detectorIndex].LeaveSrcFunction(detectors[detectorIndex].SrcId); + DLog.Log($"閲婃斁棰勫彇杞︾偣{detectors[detectorIndex].SrcId}", "TireFollowing"); + } + } + + _lastLFLEncoder = PilotDefinition.Self.LFLActualPos; + _lastLFREncoder = PilotDefinition.Self.LFRActualPos; + _lastRFLEncoder = PilotDefinition.Self.RFLActualPos; + _lastRFREncoder = PilotDefinition.Self.RFRActualPos; + _lastLRLEncoder = PilotDefinition.Self.LRLActualPos; + _lastLRREncoder = PilotDefinition.Self.LRRActualPos; + _lastRRLEncoder = PilotDefinition.Self.RRLActualPos; + _lastRRREncoder = PilotDefinition.Self.RRRActualPos; + _remainDistanceList.Clear(); + _targetYList.Clear(); + continue; + } + } + DLog.Log($"鎶曞奖鐐瑰墿浣欒窛绂:{rd:F2}", "TireFollowing"); + var track = new LineTrack(path.CarPath.Src, trackDst); + track.CarDirectionBias = CarDirection; + controller.UpdateTracks(new List { track }); + NoTarget = false; + } + yield return true; + } + } + + private static float CalculateAngle2YAxis(Vector2 point1, Vector2 point2) + { + return -(float)(Math.Atan((point1.X - point2.X) / (point1.Y - point2.Y)) * 180 / Math.PI); + } + + private DriveTask _dt; + } +} diff --git a/ClumsyPilot/VehicleSyncBinaryCodec.cs b/ClumsyPilot/VehicleSyncBinaryCodec.cs new file mode 100644 index 0000000..e7bd154 --- /dev/null +++ b/ClumsyPilot/VehicleSyncBinaryCodec.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace MultiWheelC; + +internal static class VehicleSyncBinaryCodec +{ + private const byte Version = 2; + private const byte RegisterType = 1; + private const byte NotificationType = 2; + private static readonly byte[] Magic = Encoding.ASCII.GetBytes("MVS1"); + + public static byte[] EncodeRegister(int carNum, VehicleSyncInfo info) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream, Encoding.UTF8); + WriteHeader(writer, RegisterType); + writer.Write(carNum); + WriteInfo(writer, info); + writer.Flush(); + return stream.ToArray(); + } + + public static (int CarNum, VehicleSyncInfo Info) DecodeRegister(byte[] payload) + { + using var stream = new MemoryStream(payload ?? throw new ArgumentNullException(nameof(payload))); + using var reader = new BinaryReader(stream, Encoding.UTF8); + var version = ReadHeader(reader, RegisterType); + var carNum = reader.ReadInt32(); + var info = ReadInfo(reader, version); + EnsureFullyRead(stream); + return (carNum, info); + } + + public static byte[] EncodeNotification(VehicleSyncNotification notification) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream, Encoding.UTF8); + WriteHeader(writer, NotificationType); + + writer.Write(notification.Seq); + writer.Write(BuildNotificationFlags(notification)); + writer.Write(notification.Mode); + writer.Write(notification.FleetStopSourceCar); + writer.Write(notification.CenterX); + writer.Write(notification.CenterY); + writer.Write(notification.CenterTh); + writer.Write(notification.FleetVx); + writer.Write(notification.FleetFrontTh); + writer.Write(notification.FleetRearTh); + writer.Write(notification.FleetOmega); + writer.Write(notification.RequestedFleetOmega); + writer.Write(notification.SyncTh); + writer.Write(notification.SyncDistance); + writer.Write(notification.DeltaDetectCenter); + writer.Write(notification.RotateActiveOmega); + writer.Write(notification.RotateCompXyFac); + writer.Write(notification.RotateCompXyIFac); + writer.Write(notification.RotateCompXyMax); + writer.Write(notification.RotateCompThFac); + writer.Write(notification.RotateCompThIFac); + writer.Write(notification.RotateCompThMax); + writer.Write(notification.RotateCompTangentFrac); + writer.Write(notification.RotateStartWheelAlignDeg); + writer.Write(notification.RotateActiveWheelAlignDeg); + writer.Write(notification.IdealX); + writer.Write(notification.IdealY); + writer.Write(notification.IdealTh); + WriteString(writer, notification.FleetStopReason); + + var fleet = notification.Fleet ?? new Dictionary(); + if (fleet.Count > ushort.MaxValue) + throw new InvalidOperationException($"Fleet count {fleet.Count} exceeds binary protocol limit."); + writer.Write((ushort)fleet.Count); + foreach (var kv in fleet) + { + writer.Write(kv.Key); + WriteInfo(writer, kv.Value); + } + + writer.Flush(); + return stream.ToArray(); + } + + public static VehicleSyncNotification DecodeNotification(byte[] payload) + { + using var stream = new MemoryStream(payload ?? throw new ArgumentNullException(nameof(payload))); + using var reader = new BinaryReader(stream, Encoding.UTF8); + var version = ReadHeader(reader, NotificationType); + + var notification = new VehicleSyncNotification + { + Seq = reader.ReadInt64() + }; + + ApplyNotificationFlags(notification, reader.ReadUInt16()); + notification.Mode = reader.ReadInt32(); + notification.FleetStopSourceCar = reader.ReadInt32(); + notification.CenterX = reader.ReadSingle(); + notification.CenterY = reader.ReadSingle(); + notification.CenterTh = reader.ReadSingle(); + notification.FleetVx = reader.ReadSingle(); + notification.FleetFrontTh = reader.ReadSingle(); + notification.FleetRearTh = reader.ReadSingle(); + notification.FleetOmega = reader.ReadSingle(); + notification.RequestedFleetOmega = reader.ReadSingle(); + notification.SyncTh = reader.ReadSingle(); + notification.SyncDistance = reader.ReadSingle(); + notification.DeltaDetectCenter = reader.ReadSingle(); + notification.RotateActiveOmega = reader.ReadSingle(); + notification.RotateCompXyFac = reader.ReadSingle(); + notification.RotateCompXyIFac = reader.ReadSingle(); + notification.RotateCompXyMax = reader.ReadSingle(); + notification.RotateCompThFac = reader.ReadSingle(); + notification.RotateCompThIFac = reader.ReadSingle(); + notification.RotateCompThMax = reader.ReadSingle(); + notification.RotateCompTangentFrac = reader.ReadSingle(); + notification.RotateStartWheelAlignDeg = reader.ReadSingle(); + notification.RotateActiveWheelAlignDeg = reader.ReadSingle(); + notification.IdealX = reader.ReadSingle(); + notification.IdealY = reader.ReadSingle(); + notification.IdealTh = reader.ReadSingle(); + notification.FleetStopReason = ReadString(reader); + + var fleetCount = reader.ReadUInt16(); + notification.Fleet = new Dictionary(fleetCount); + for (var i = 0; i < fleetCount; ++i) + { + var carNum = reader.ReadInt32(); + notification.Fleet[carNum] = ReadInfo(reader, version); + } + + EnsureFullyRead(stream); + return notification; + } + + private static void WriteHeader(BinaryWriter writer, byte type) + { + writer.Write(Magic); + writer.Write(Version); + writer.Write(type); + writer.Write((ushort)0); + } + + private static byte ReadHeader(BinaryReader reader, byte expectedType) + { + for (var i = 0; i < Magic.Length; ++i) + { + if (reader.ReadByte() != Magic[i]) + throw new InvalidDataException("Invalid multi-vehicle sync binary magic."); + } + + var version = reader.ReadByte(); + if (version < 1 || version > Version) + throw new InvalidDataException($"Unsupported multi-vehicle sync binary version {version}."); + + var type = reader.ReadByte(); + if (type != expectedType) + throw new InvalidDataException($"Unexpected multi-vehicle sync packet type {type}."); + + var reserved = reader.ReadUInt16(); + if (reserved != 0) + throw new InvalidDataException("Invalid multi-vehicle sync binary reserved field."); + + return version; + } + + private static void WriteInfo(BinaryWriter writer, VehicleSyncInfo info) + { + writer.Write(BuildInfoFlags(info)); + WriteString(writer, info.Ip); + writer.Write(info.Port); + writer.Write(info.X); + writer.Write(info.Y); + writer.Write(info.Th); + writer.Write(info.LayoutX); + writer.Write(info.LayoutY); + writer.Write(info.LayoutTh); + WriteString(writer, info.MotionInfeasibleReason); + WriteString(writer, info.RotateWheelAlignDetail); + writer.Write(info.AppliedNotificationSeq); + } + + private static VehicleSyncInfo ReadInfo(BinaryReader reader, byte version) + { + var info = new VehicleSyncInfo(); + ApplyInfoFlags(info, reader.ReadUInt16()); + info.Ip = ReadString(reader); + info.Port = reader.ReadInt32(); + info.X = reader.ReadSingle(); + info.Y = reader.ReadSingle(); + info.Th = reader.ReadSingle(); + info.LayoutX = reader.ReadSingle(); + info.LayoutY = reader.ReadSingle(); + info.LayoutTh = reader.ReadSingle(); + info.MotionInfeasibleReason = ReadString(reader); + info.RotateWheelAlignDetail = ReadString(reader); + info.AppliedNotificationSeq = version >= 2 ? reader.ReadInt64() : -1; + return info; + } + + private static ushort BuildInfoFlags(VehicleSyncInfo info) + { + ushort flags = 0; + if (info.Master) flags |= 1 << 0; + if (info.PosAvailable) flags |= 1 << 1; + if (info.Aligned) flags |= 1 << 2; + if (info.DetectOk) flags |= 1 << 3; + if (info.MotionFeasible) flags |= 1 << 4; + if (info.RotateWheelsAligned) flags |= 1 << 5; + return flags; + } + + private static void ApplyInfoFlags(VehicleSyncInfo info, ushort flags) + { + info.Master = (flags & (1 << 0)) != 0; + info.PosAvailable = (flags & (1 << 1)) != 0; + info.Aligned = (flags & (1 << 2)) != 0; + info.DetectOk = (flags & (1 << 3)) != 0; + info.MotionFeasible = (flags & (1 << 4)) != 0; + info.RotateWheelsAligned = (flags & (1 << 5)) != 0; + } + + private static ushort BuildNotificationFlags(VehicleSyncNotification notification) + { + ushort flags = 0; + if (notification.PosAvailable) flags |= 1 << 0; + if (notification.Aligned) flags |= 1 << 1; + if (notification.FleetMotionReleased) flags |= 1 << 2; + if (notification.FleetStopActive) flags |= 1 << 3; + if (notification.AutoEnabled) flags |= 1 << 4; + if (notification.ManualEnabled) flags |= 1 << 5; + if (notification.HasIdeal) flags |= 1 << 6; + if (notification.RotateParamsValid) flags |= 1 << 7; + if (notification.UseDetourCorrection) flags |= 1 << 8; + return flags; + } + + private static void ApplyNotificationFlags(VehicleSyncNotification notification, ushort flags) + { + notification.PosAvailable = (flags & (1 << 0)) != 0; + notification.Aligned = (flags & (1 << 1)) != 0; + notification.FleetMotionReleased = (flags & (1 << 2)) != 0; + notification.FleetStopActive = (flags & (1 << 3)) != 0; + notification.AutoEnabled = (flags & (1 << 4)) != 0; + notification.ManualEnabled = (flags & (1 << 5)) != 0; + notification.HasIdeal = (flags & (1 << 6)) != 0; + notification.RotateParamsValid = (flags & (1 << 7)) != 0; + notification.UseDetourCorrection = (flags & (1 << 8)) != 0; + } + + private static void WriteString(BinaryWriter writer, string value) + { + var bytes = Encoding.UTF8.GetBytes(value ?? ""); + if (bytes.Length > ushort.MaxValue) + throw new InvalidOperationException($"String payload length {bytes.Length} exceeds binary protocol limit."); + writer.Write((ushort)bytes.Length); + writer.Write(bytes); + } + + private static string ReadString(BinaryReader reader) + { + var length = reader.ReadUInt16(); + var bytes = reader.ReadBytes(length); + if (bytes.Length != length) + throw new EndOfStreamException("Truncated multi-vehicle sync string payload."); + return Encoding.UTF8.GetString(bytes); + } + + private static void EnsureFullyRead(MemoryStream stream) + { + if (stream.Position != stream.Length) + throw new InvalidDataException("Unexpected trailing bytes in multi-vehicle sync packet."); + } +} diff --git a/ClumsyPilot/VehicleSyncModels.cs b/ClumsyPilot/VehicleSyncModels.cs new file mode 100644 index 0000000..1c21428 --- /dev/null +++ b/ClumsyPilot/VehicleSyncModels.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using ClumsyCore; +using Newtonsoft.Json; + +namespace MultiWheelC; + +public class VehicleSyncInfo +{ + [JsonProperty("Master")] public bool Master { get; set; } + [JsonProperty("Ip")] public string Ip { get; set; } = ""; + [JsonProperty("Port")] public int Port { get; set; } = 8008; + [JsonProperty("PosAvailable")] public bool PosAvailable { get; set; } + [JsonProperty("X")] public float X { get; set; } + [JsonProperty("Y")] public float Y { get; set; } + [JsonProperty("Th")] public float Th { get; set; } + [JsonProperty("LayoutX")] public float LayoutX { get; set; } + [JsonProperty("LayoutY")] public float LayoutY { get; set; } + [JsonProperty("LayoutTh")] public float LayoutTh { get; set; } + [JsonProperty("Aligned")] public bool Aligned { get; set; } + // 鏈溅鏈疆鏄惁鎴愬姛璇嗗埆鍒伴偦杞︼紙鍏抽棴浜掕瘑鍒椂鎭掍负 true锛夈備换涓杞︿负 false 鍒欐暣闃熷仠杞︺ + [JsonProperty("DetectOk")] public bool DetectOk { get; set; } + [JsonProperty("MotionFeasible")] public bool MotionFeasible { get; set; } = true; + [JsonProperty("MotionInfeasibleReason")] public string MotionInfeasibleReason { get; set; } = ""; + [JsonProperty("RotateWheelsAligned")] public bool RotateWheelsAligned { get; set; } = true; + [JsonProperty("RotateWheelAlignDetail")] public string RotateWheelAlignDetail { get; set; } = ""; + [JsonProperty("AppliedNotificationSeq")] public long AppliedNotificationSeq { get; set; } = -1; +} + +public class VehicleSyncNotification +{ + [JsonProperty("PosAvailable")] public bool PosAvailable { get; set; } + [JsonProperty("CenterX")] public float CenterX { get; set; } + [JsonProperty("CenterY")] public float CenterY { get; set; } + [JsonProperty("CenterTh")] public float CenterTh { get; set; } + [JsonProperty("Aligned")] public bool Aligned { get; set; } + [JsonProperty("Fleet")] public Dictionary Fleet { get; set; } = new(); + [JsonProperty("FleetVx")] public float FleetVx { get; set; } + [JsonProperty("FleetFrontTh")] public float FleetFrontTh { get; set; } + [JsonProperty("FleetRearTh")] public float FleetRearTh { get; set; } + // 鑱斿姩杩愬姩妯″紡锛0=甯歌(鍓嶈繘+杞悜) 1=锜硅(鍥涜疆鍚屽悜骞崇Щ) 2=鍘熷湴鏃嬭浆(缁曡溅闃熶腑蹇) + [JsonProperty("Mode")] public int Mode { get; set; } + // 鍘熷湴鏃嬭浆瑙掗熷害(deg/s锛岄嗘椂閽堜负姝)锛屼粎 Mode==2 鏈夋晥 + [JsonProperty("FleetOmega")] public float FleetOmega { get; set; } + [JsonProperty("RequestedFleetOmega")] public float RequestedFleetOmega { get; set; } + [JsonProperty("FleetMotionReleased")] public bool FleetMotionReleased { get; set; } = true; + [JsonProperty("FleetStopActive")] public bool FleetStopActive { get; set; } + [JsonProperty("FleetStopReason")] public string FleetStopReason { get; set; } = ""; + [JsonProperty("FleetStopSourceCar")] public int FleetStopSourceCar { get; set; } + [JsonProperty("AutoEnabled")] public bool AutoEnabled { get; set; } + [JsonProperty("ManualEnabled")] public bool ManualEnabled { get; set; } + [JsonProperty("UseDetourCorrection")] public bool UseDetourCorrection { get; set; } + [JsonProperty("SyncTh")] public float SyncTh { get; set; } + [JsonProperty("SyncDistance")] public float SyncDistance { get; set; } + [JsonProperty("DeltaDetectCenter")] public float DeltaDetectCenter { get; set; } + // 鍘熷湴鏃嬭浆绾犲亸鍙傛暟鐢变富杞﹀箍鎾紝浠庤溅杩愯鏃朵娇鐢ㄥ悓涓濂楀鐩/闄愬箙锛岄伩鍏嶄富浠庤ˉ鍋垮己搴︿笉涓鑷淬 + [JsonProperty("RotateParamsValid")] public bool RotateParamsValid { get; set; } + [JsonProperty("RotateActiveOmega")] public float RotateActiveOmega { get; set; } + [JsonProperty("RotateCompXyFac")] public float RotateCompXyFac { get; set; } + [JsonProperty("RotateCompXyIFac")] public float RotateCompXyIFac { get; set; } + [JsonProperty("RotateCompXyMax")] public float RotateCompXyMax { get; set; } + [JsonProperty("RotateCompThFac")] public float RotateCompThFac { get; set; } + [JsonProperty("RotateCompThIFac")] public float RotateCompThIFac { get; set; } + [JsonProperty("RotateCompThMax")] public float RotateCompThMax { get; set; } + [JsonProperty("RotateCompTangentFrac")] public float RotateCompTangentFrac { get; set; } + [JsonProperty("RotateStartWheelAlignDeg")] public float RotateStartWheelAlignDeg { get; set; } + [JsonProperty("RotateActiveWheelAlignDeg")] public float RotateActiveWheelAlignDeg { get; set; } + // F: 鍗曡皟閫掑搴忓垪鍙凤紝浠庤溅鎹涓㈠純涔卞簭鍒拌揪鐨勬棫 notify 鍖呫 + [JsonProperty("Seq")] public long Seq { get; set; } + // D: 鑷姩妯″紡涓嬩富杞﹁矾寰勬帶鍒跺櫒绠楀嚭鐨勮溅闃熶腑蹇冪悊鎯充綅濮匡紙涓栫晫绯伙級锛岀敱 idealPos/idealAngle 閫忎紶鑰屾潵銆 + // HasIdeal=true 鏃跺悇浠庤溅鎸夊悇鑷 layout 鎺ㄧ畻 per-car 鐩爣浣嶅Э鍋氬墠棣+琛ュ伩锛屽姬绾胯矾寰勪笉鍐嶅彧闈犱簨鍚庣籂鍋忋 + [JsonProperty("HasIdeal")] public bool HasIdeal { get; set; } + [JsonProperty("IdealX")] public float IdealX { get; set; } + [JsonProperty("IdealY")] public float IdealY { get; set; } + [JsonProperty("IdealTh")] public float IdealTh { get; set; } +} diff --git a/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.dgspec.json b/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.dgspec.json new file mode 100644 index 0000000..b4f63b4 --- /dev/null +++ b/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.dgspec.json @@ -0,0 +1,84 @@ +{ + "format": 1, + "restore": { + "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\ClumsyPilot.csproj": {} + }, + "projects": { + "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\ClumsyPilot.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\ClumsyPilot.csproj", + "projectName": "ClumsyPilot", + "projectPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\ClumsyPilot.csproj", + "packagesPath": "C:\\Users\\Fairyland\\.nuget\\packages\\", + "outputPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "D:\\VS2022\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\Fairyland\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "netstandard2.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netstandard2.0": { + "targetAlias": "netstandard2.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "netstandard2.0": { + "targetAlias": "netstandard2.0", + "dependencies": { + "NETStandard.Library": { + "suppressParent": "All", + "target": "Package", + "version": "[2.0.3, )", + "autoReferenced": true + }, + "Newtonsoft.Json": { + "target": "Package", + "version": "[13.0.4, )" + }, + "System.Numerics.Vectors": { + "target": "Package", + "version": "[4.6.1, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.308\\RuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.g.props b/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.g.props new file mode 100644 index 0000000..88c0201 --- /dev/null +++ b/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.g.props @@ -0,0 +1,16 @@ +锘 + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + $(UserProfile)\.nuget\packages\ + C:\Users\Fairyland\.nuget\packages\;D:\VS2022\Shared\NuGetPackages + PackageReference + 6.14.2 + + + + + + \ No newline at end of file diff --git a/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.g.targets b/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.g.targets new file mode 100644 index 0000000..868c101 --- /dev/null +++ b/ClumsyPilot/obj/ClumsyPilot.csproj.nuget.g.targets @@ -0,0 +1,6 @@ +锘 + + + + + \ No newline at end of file diff --git a/ClumsyPilot/obj/Debug/.NETStandard,Version=v2.0.AssemblyAttributes.cs b/ClumsyPilot/obj/Debug/.NETStandard,Version=v2.0.AssemblyAttributes.cs new file mode 100644 index 0000000..8bf3a42 --- /dev/null +++ b/ClumsyPilot/obj/Debug/.NETStandard,Version=v2.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs new file mode 100644 index 0000000..4f4d0a5 --- /dev/null +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// 姝や唬鐮佺敱宸ュ叿鐢熸垚銆 +// 杩愯鏃剁増鏈:4.0.30319.42000 +// +// 瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋 +// 閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便 +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("ClumsyPilot")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("ClumsyPilot")] +[assembly: System.Reflection.AssemblyTitleAttribute("ClumsyPilot")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// 鐢 MSBuild WriteCodeFragment 绫荤敓鎴愩 + diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache new file mode 100644 index 0000000..8fb9fb2 --- /dev/null +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +5d77794fa0720c6591db5b06ac60427413c18989a6f7b64420ccb07d122d85bc diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig b/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..051b204 --- /dev/null +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,8 @@ +is_global = true +build_property.RootNamespace = ClumsyPilot +build_property.ProjectDir = D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.CsWinRTUseWindowsUIXamlProjections = false +build_property.EffectiveAnalysisLevelStyle = +build_property.EnableCodeStyleSeverity = diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.assets.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.assets.cache new file mode 100644 index 0000000..465ef3b Binary files /dev/null and b/ClumsyPilot/obj/Debug/ClumsyPilot.assets.cache differ diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.AssemblyReference.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.AssemblyReference.cache new file mode 100644 index 0000000..c1c77f9 Binary files /dev/null and b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.AssemblyReference.cache differ diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.CoreCompileInputs.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..6428c04 --- /dev/null +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +622a214d5f25f6580d0c98fb28e188cba923d74f280b70d75d03c4009c18c55b diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.FileListAbsolute.txt b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..d2f0839 --- /dev/null +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.FileListAbsolute.txt @@ -0,0 +1,11 @@ +D:\@FariyLandTask\@FRLD-GitProject\build\Clumsy\ClumsyPilot.deps.json +D:\@FariyLandTask\@FRLD-GitProject\build\Clumsy\ClumsyPilot.dll +D:\@FariyLandTask\@FRLD-GitProject\build\Clumsy\ClumsyPilot.pdb +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\ClumsyPilot.csproj.AssemblyReference.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\ClumsyPilot.AssemblyInfoInputs.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\ClumsyPilot.AssemblyInfo.cs +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\ClumsyPilot.csproj.CoreCompileInputs.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\ClumsyPi.5EF10E9F.Up2Date +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\ClumsyPilot.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\ClumsyPilot.pdb diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.dll b/ClumsyPilot/obj/Debug/ClumsyPilot.dll new file mode 100644 index 0000000..51c3bbc Binary files /dev/null and b/ClumsyPilot/obj/Debug/ClumsyPilot.dll differ diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.pdb b/ClumsyPilot/obj/Debug/ClumsyPilot.pdb new file mode 100644 index 0000000..b4645ec Binary files /dev/null and b/ClumsyPilot/obj/Debug/ClumsyPilot.pdb differ diff --git a/ClumsyPilot/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs b/ClumsyPilot/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs new file mode 100644 index 0000000..8bf3a42 --- /dev/null +++ b/ClumsyPilot/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] diff --git a/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.AssemblyInfo.cs b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.AssemblyInfo.cs new file mode 100644 index 0000000..4f4d0a5 --- /dev/null +++ b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// 姝や唬鐮佺敱宸ュ叿鐢熸垚銆 +// 杩愯鏃剁増鏈:4.0.30319.42000 +// +// 瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋 +// 閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便 +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("ClumsyPilot")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("ClumsyPilot")] +[assembly: System.Reflection.AssemblyTitleAttribute("ClumsyPilot")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// 鐢 MSBuild WriteCodeFragment 绫荤敓鎴愩 + diff --git a/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.AssemblyInfoInputs.cache b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.AssemblyInfoInputs.cache new file mode 100644 index 0000000..8fb9fb2 --- /dev/null +++ b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +5d77794fa0720c6591db5b06ac60427413c18989a6f7b64420ccb07d122d85bc diff --git a/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..051b204 --- /dev/null +++ b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,8 @@ +is_global = true +build_property.RootNamespace = ClumsyPilot +build_property.ProjectDir = D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.CsWinRTUseWindowsUIXamlProjections = false +build_property.EffectiveAnalysisLevelStyle = +build_property.EnableCodeStyleSeverity = diff --git a/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.assets.cache b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.assets.cache new file mode 100644 index 0000000..bb4c9f9 Binary files /dev/null and b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.assets.cache differ diff --git a/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.AssemblyReference.cache b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.AssemblyReference.cache new file mode 100644 index 0000000..c1c77f9 Binary files /dev/null and b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.AssemblyReference.cache differ diff --git a/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.CoreCompileInputs.cache b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..caf5b8a --- /dev/null +++ b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +66346c5ecc38869ab6b6f447e1f54c24aba69f81ee10b5736dee140cd5a474b8 diff --git a/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.FileListAbsolute.txt b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..b672dc2 --- /dev/null +++ b/ClumsyPilot/obj/Debug/netstandard2.0/ClumsyPilot.csproj.FileListAbsolute.txt @@ -0,0 +1,5 @@ +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\netstandard2.0\ClumsyPilot.csproj.AssemblyReference.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\netstandard2.0\ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\netstandard2.0\ClumsyPilot.AssemblyInfoInputs.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\netstandard2.0\ClumsyPilot.AssemblyInfo.cs +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\ClumsyPilot\obj\Debug\netstandard2.0\ClumsyPilot.csproj.CoreCompileInputs.cache diff --git a/ClumsyPilot/obj/project.assets.json b/ClumsyPilot/obj/project.assets.json new file mode 100644 index 0000000..66160f0 --- /dev/null +++ b/ClumsyPilot/obj/project.assets.json @@ -0,0 +1,341 @@ +{ + "version": 3, + "targets": { + ".NETStandard,Version=v2.0": { + "Microsoft.NETCore.Platforms/1.1.0": { + "type": "package", + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "NETStandard.Library/2.0.3": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + }, + "build": { + "build/netstandard2.0/NETStandard.Library.targets": {} + } + }, + "Newtonsoft.Json/13.0.4": { + "type": "package", + "compile": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + } + }, + "System.Numerics.Vectors/4.6.1": { + "type": "package", + "compile": { + "lib/netstandard2.0/System.Numerics.Vectors.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Numerics.Vectors.dll": { + "related": ".xml" + } + } + } + } + }, + "libraries": { + "Microsoft.NETCore.Platforms/1.1.0": { + "sha512": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", + "type": "package", + "path": "microsoft.netcore.platforms/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.0/_._", + "microsoft.netcore.platforms.1.1.0.nupkg.sha512", + "microsoft.netcore.platforms.nuspec", + "runtime.json" + ] + }, + "NETStandard.Library/2.0.3": { + "sha512": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", + "type": "package", + "path": "netstandard.library/2.0.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "build/netstandard2.0/NETStandard.Library.targets", + "build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll", + "build/netstandard2.0/ref/System.AppContext.dll", + "build/netstandard2.0/ref/System.Collections.Concurrent.dll", + "build/netstandard2.0/ref/System.Collections.NonGeneric.dll", + "build/netstandard2.0/ref/System.Collections.Specialized.dll", + "build/netstandard2.0/ref/System.Collections.dll", + "build/netstandard2.0/ref/System.ComponentModel.Composition.dll", + "build/netstandard2.0/ref/System.ComponentModel.EventBasedAsync.dll", + "build/netstandard2.0/ref/System.ComponentModel.Primitives.dll", + "build/netstandard2.0/ref/System.ComponentModel.TypeConverter.dll", + "build/netstandard2.0/ref/System.ComponentModel.dll", + "build/netstandard2.0/ref/System.Console.dll", + "build/netstandard2.0/ref/System.Core.dll", + "build/netstandard2.0/ref/System.Data.Common.dll", + "build/netstandard2.0/ref/System.Data.dll", + "build/netstandard2.0/ref/System.Diagnostics.Contracts.dll", + "build/netstandard2.0/ref/System.Diagnostics.Debug.dll", + "build/netstandard2.0/ref/System.Diagnostics.FileVersionInfo.dll", + "build/netstandard2.0/ref/System.Diagnostics.Process.dll", + "build/netstandard2.0/ref/System.Diagnostics.StackTrace.dll", + "build/netstandard2.0/ref/System.Diagnostics.TextWriterTraceListener.dll", + "build/netstandard2.0/ref/System.Diagnostics.Tools.dll", + "build/netstandard2.0/ref/System.Diagnostics.TraceSource.dll", + "build/netstandard2.0/ref/System.Diagnostics.Tracing.dll", + "build/netstandard2.0/ref/System.Drawing.Primitives.dll", + "build/netstandard2.0/ref/System.Drawing.dll", + "build/netstandard2.0/ref/System.Dynamic.Runtime.dll", + "build/netstandard2.0/ref/System.Globalization.Calendars.dll", + "build/netstandard2.0/ref/System.Globalization.Extensions.dll", + "build/netstandard2.0/ref/System.Globalization.dll", + "build/netstandard2.0/ref/System.IO.Compression.FileSystem.dll", + "build/netstandard2.0/ref/System.IO.Compression.ZipFile.dll", + "build/netstandard2.0/ref/System.IO.Compression.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.DriveInfo.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.Primitives.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.Watcher.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.dll", + "build/netstandard2.0/ref/System.IO.IsolatedStorage.dll", + "build/netstandard2.0/ref/System.IO.MemoryMappedFiles.dll", + "build/netstandard2.0/ref/System.IO.Pipes.dll", + "build/netstandard2.0/ref/System.IO.UnmanagedMemoryStream.dll", + "build/netstandard2.0/ref/System.IO.dll", + "build/netstandard2.0/ref/System.Linq.Expressions.dll", + "build/netstandard2.0/ref/System.Linq.Parallel.dll", + "build/netstandard2.0/ref/System.Linq.Queryable.dll", + "build/netstandard2.0/ref/System.Linq.dll", + "build/netstandard2.0/ref/System.Net.Http.dll", + "build/netstandard2.0/ref/System.Net.NameResolution.dll", + "build/netstandard2.0/ref/System.Net.NetworkInformation.dll", + "build/netstandard2.0/ref/System.Net.Ping.dll", + "build/netstandard2.0/ref/System.Net.Primitives.dll", + "build/netstandard2.0/ref/System.Net.Requests.dll", + "build/netstandard2.0/ref/System.Net.Security.dll", + "build/netstandard2.0/ref/System.Net.Sockets.dll", + "build/netstandard2.0/ref/System.Net.WebHeaderCollection.dll", + "build/netstandard2.0/ref/System.Net.WebSockets.Client.dll", + "build/netstandard2.0/ref/System.Net.WebSockets.dll", + "build/netstandard2.0/ref/System.Net.dll", + "build/netstandard2.0/ref/System.Numerics.dll", + "build/netstandard2.0/ref/System.ObjectModel.dll", + "build/netstandard2.0/ref/System.Reflection.Extensions.dll", + "build/netstandard2.0/ref/System.Reflection.Primitives.dll", + "build/netstandard2.0/ref/System.Reflection.dll", + "build/netstandard2.0/ref/System.Resources.Reader.dll", + "build/netstandard2.0/ref/System.Resources.ResourceManager.dll", + "build/netstandard2.0/ref/System.Resources.Writer.dll", + "build/netstandard2.0/ref/System.Runtime.CompilerServices.VisualC.dll", + "build/netstandard2.0/ref/System.Runtime.Extensions.dll", + "build/netstandard2.0/ref/System.Runtime.Handles.dll", + "build/netstandard2.0/ref/System.Runtime.InteropServices.RuntimeInformation.dll", + "build/netstandard2.0/ref/System.Runtime.InteropServices.dll", + "build/netstandard2.0/ref/System.Runtime.Numerics.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Formatters.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Json.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Primitives.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Xml.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.dll", + "build/netstandard2.0/ref/System.Runtime.dll", + "build/netstandard2.0/ref/System.Security.Claims.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Algorithms.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Csp.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Encoding.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Primitives.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.X509Certificates.dll", + "build/netstandard2.0/ref/System.Security.Principal.dll", + "build/netstandard2.0/ref/System.Security.SecureString.dll", + "build/netstandard2.0/ref/System.ServiceModel.Web.dll", + "build/netstandard2.0/ref/System.Text.Encoding.Extensions.dll", + "build/netstandard2.0/ref/System.Text.Encoding.dll", + "build/netstandard2.0/ref/System.Text.RegularExpressions.dll", + "build/netstandard2.0/ref/System.Threading.Overlapped.dll", + "build/netstandard2.0/ref/System.Threading.Tasks.Parallel.dll", + "build/netstandard2.0/ref/System.Threading.Tasks.dll", + "build/netstandard2.0/ref/System.Threading.Thread.dll", + "build/netstandard2.0/ref/System.Threading.ThreadPool.dll", + "build/netstandard2.0/ref/System.Threading.Timer.dll", + "build/netstandard2.0/ref/System.Threading.dll", + "build/netstandard2.0/ref/System.Transactions.dll", + "build/netstandard2.0/ref/System.ValueTuple.dll", + "build/netstandard2.0/ref/System.Web.dll", + "build/netstandard2.0/ref/System.Windows.dll", + "build/netstandard2.0/ref/System.Xml.Linq.dll", + "build/netstandard2.0/ref/System.Xml.ReaderWriter.dll", + "build/netstandard2.0/ref/System.Xml.Serialization.dll", + "build/netstandard2.0/ref/System.Xml.XDocument.dll", + "build/netstandard2.0/ref/System.Xml.XPath.XDocument.dll", + "build/netstandard2.0/ref/System.Xml.XPath.dll", + "build/netstandard2.0/ref/System.Xml.XmlDocument.dll", + "build/netstandard2.0/ref/System.Xml.XmlSerializer.dll", + "build/netstandard2.0/ref/System.Xml.dll", + "build/netstandard2.0/ref/System.dll", + "build/netstandard2.0/ref/mscorlib.dll", + "build/netstandard2.0/ref/netstandard.dll", + "build/netstandard2.0/ref/netstandard.xml", + "lib/netstandard1.0/_._", + "netstandard.library.2.0.3.nupkg.sha512", + "netstandard.library.nuspec" + ] + }, + "Newtonsoft.Json/13.0.4": { + "sha512": "pdgNNMai3zv51W5aq268sujXUyx7SNdE2bj1wZcWjAQrKMFZV260lbqYop1d2GM67JI1huLRwxo9ZqnfF/lC6A==", + "type": "package", + "path": "newtonsoft.json/13.0.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.md", + "README.md", + "lib/net20/Newtonsoft.Json.dll", + "lib/net20/Newtonsoft.Json.xml", + "lib/net35/Newtonsoft.Json.dll", + "lib/net35/Newtonsoft.Json.xml", + "lib/net40/Newtonsoft.Json.dll", + "lib/net40/Newtonsoft.Json.xml", + "lib/net45/Newtonsoft.Json.dll", + "lib/net45/Newtonsoft.Json.xml", + "lib/net6.0/Newtonsoft.Json.dll", + "lib/net6.0/Newtonsoft.Json.xml", + "lib/netstandard1.0/Newtonsoft.Json.dll", + "lib/netstandard1.0/Newtonsoft.Json.xml", + "lib/netstandard1.3/Newtonsoft.Json.dll", + "lib/netstandard1.3/Newtonsoft.Json.xml", + "lib/netstandard2.0/Newtonsoft.Json.dll", + "lib/netstandard2.0/Newtonsoft.Json.xml", + "newtonsoft.json.13.0.4.nupkg.sha512", + "newtonsoft.json.nuspec", + "packageIcon.png" + ] + }, + "System.Numerics.Vectors/4.6.1": { + "sha512": "sQxefTnhagrhoq2ReR0D/6K0zJcr9Hrd6kikeXsA1I8kOCboTavcUC4r7TSfpKFeE163uMuxZcyfO1mGO3EN8Q==", + "type": "package", + "path": "system.numerics.vectors/4.6.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "buildTransitive/net461/System.Numerics.Vectors.targets", + "buildTransitive/net462/_._", + "lib/net462/System.Numerics.Vectors.dll", + "lib/net462/System.Numerics.Vectors.xml", + "lib/netcoreapp2.0/_._", + "lib/netstandard2.0/System.Numerics.Vectors.dll", + "lib/netstandard2.0/System.Numerics.Vectors.xml", + "lib/netstandard2.1/_._", + "system.numerics.vectors.4.6.1.nupkg.sha512", + "system.numerics.vectors.nuspec" + ] + } + }, + "projectFileDependencyGroups": { + ".NETStandard,Version=v2.0": [ + "NETStandard.Library >= 2.0.3", + "Newtonsoft.Json >= 13.0.4", + "System.Numerics.Vectors >= 4.6.1" + ] + }, + "packageFolders": { + "C:\\Users\\Fairyland\\.nuget\\packages\\": {}, + "D:\\VS2022\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\ClumsyPilot.csproj", + "projectName": "ClumsyPilot", + "projectPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\ClumsyPilot.csproj", + "packagesPath": "C:\\Users\\Fairyland\\.nuget\\packages\\", + "outputPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "D:\\VS2022\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\Fairyland\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "netstandard2.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netstandard2.0": { + "targetAlias": "netstandard2.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "netstandard2.0": { + "targetAlias": "netstandard2.0", + "dependencies": { + "NETStandard.Library": { + "suppressParent": "All", + "target": "Package", + "version": "[2.0.3, )", + "autoReferenced": true + }, + "Newtonsoft.Json": { + "target": "Package", + "version": "[13.0.4, )" + }, + "System.Numerics.Vectors": { + "target": "Package", + "version": "[4.6.1, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.308\\RuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/ClumsyPilot/obj/project.nuget.cache b/ClumsyPilot/obj/project.nuget.cache new file mode 100644 index 0000000..5767952 --- /dev/null +++ b/ClumsyPilot/obj/project.nuget.cache @@ -0,0 +1,13 @@ +{ + "version": 2, + "dgSpecHash": "gHGYwM2i+So=", + "success": true, + "projectFilePath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\ClumsyPilot\\ClumsyPilot.csproj", + "expectedPackageFiles": [ + "C:\\Users\\Fairyland\\.nuget\\packages\\microsoft.netcore.platforms\\1.1.0\\microsoft.netcore.platforms.1.1.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\netstandard.library\\2.0.3\\netstandard.library.2.0.3.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\newtonsoft.json\\13.0.4\\newtonsoft.json.13.0.4.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\system.numerics.vectors\\4.6.1\\system.numerics.vectors.4.6.1.nupkg.sha512" + ], + "logs": [] +} \ No newline at end of file diff --git a/ClumsyPilot/ref/CommonUsage.dll b/ClumsyPilot/ref/CommonUsage.dll new file mode 100644 index 0000000..effb81e Binary files /dev/null and b/ClumsyPilot/ref/CommonUsage.dll differ diff --git a/ClumsyPilot/ref/LessokajiWeaverUtilities.dll b/ClumsyPilot/ref/LessokajiWeaverUtilities.dll new file mode 100644 index 0000000..7ca4e8f Binary files /dev/null and b/ClumsyPilot/ref/LessokajiWeaverUtilities.dll differ diff --git a/ClumsyPilot/ref/MDCSToolBox.dll b/ClumsyPilot/ref/MDCSToolBox.dll new file mode 100644 index 0000000..091a9bb Binary files /dev/null and b/ClumsyPilot/ref/MDCSToolBox.dll differ diff --git a/ClumsyPilot/ref/RefClumsyCore.dll b/ClumsyPilot/ref/RefClumsyCore.dll new file mode 100644 index 0000000..ed36470 Binary files /dev/null and b/ClumsyPilot/ref/RefClumsyCore.dll differ diff --git a/ClumsyPilot/ref/RefClumsyDance.dll b/ClumsyPilot/ref/RefClumsyDance.dll new file mode 100644 index 0000000..7e191a1 Binary files /dev/null and b/ClumsyPilot/ref/RefClumsyDance.dll differ diff --git a/ClumsyPilot/ref/RefFundamentalLib.dll b/ClumsyPilot/ref/RefFundamentalLib.dll new file mode 100644 index 0000000..2b8ba30 Binary files /dev/null and b/ClumsyPilot/ref/RefFundamentalLib.dll differ diff --git a/MedullaAdapter/AlarmRoutine.cs b/MedullaAdapter/AlarmRoutine.cs new file mode 100644 index 0000000..d6d2dc3 --- /dev/null +++ b/MedullaAdapter/AlarmRoutine.cs @@ -0,0 +1,21 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using CartActivator; +using FundamentalLib; +using MDCSToolBox.Medulla.Chassis; +using MDCSToolBox.Medulla.Chassis.MultiWheel; + +namespace MedullaAdapter +{ + public class AlarmRoutine : MultiWheelAlarmRoutine + { + public override void SetOtherAlarms() + { + AddAlarm("宸﹀す鑷傞┍鍔ㄦ姤璀", 2, () => cart.LeftArmErrorCode != 0); + AddAlarm("鍙冲す鑷傞┍鍔ㄦ姤璀", 2, () => cart.RightArmErrorCode != 0); + //AddAlarm("澶硅噦涓嶅悓姝ユ姤璀", 2, () => cart.ClampOutOfSync); + } + } +} diff --git a/MedullaAdapter/DiverCartDefinition.cs b/MedullaAdapter/DiverCartDefinition.cs new file mode 100644 index 0000000..2f2657b --- /dev/null +++ b/MedullaAdapter/DiverCartDefinition.cs @@ -0,0 +1,278 @@ +锘縰sing CartActivator; +using MCUSerialBridgeCLR; +using MDCSToolBox.Medulla.Chassis.MultiWheel; +using Medulla.Types; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; + + +namespace MedullaAdapter +{ + [UseLadderLogic(logic = typeof(AlarmRoutine), scanInterval = 50)] + [UseLadderLogic(logic = typeof(MotorRoutine), scanInterval = 50)] + [UseLadderLogic(logic = typeof(MCURoutine), scanInterval = 20)] + [UseManualController(manualController = typeof(Remote))] + public partial class DiverCartDefinition : MultiWheelCartDefinition + { + public DiverCommunication Embedded; + public MCUSerialBridge Bridge; + [AsUpperIO(desc = "杞集鍗婂緞")] public float Radius; + #region MultiVehicleCoordination + + [AsInitParam(desc = "閬ユ帶鍣ㄦ渶澶х嚎閫熷害")] + public float MaxManualSpeed = 0.3f; + + [AsInitParam(desc = "閬ユ帶鍣ㄦ渶澶ц閫熷害")] + public float MaxManualAngularSpeed = 45f; + + + [AsLowerIO(desc = "鍚敤锛堟墜鍔級澶氳溅鑱斿姩")] public bool MultiVehicleManualEnabled = false; + [AsLowerIO(desc = "锛堟墜鍔級澶氳溅鑱斿姩妯″紡")] public int MultiVehicleManualMode = 0; + + [AsUpperIO(desc = "澶氳溅鑱斿姩锛氬0鍏夊悓姝ワ紝-1鏈惎鍔紝0鐏紝1浜")] public int MultiVehicleLightSync = -1; + + [AsLowerIO(desc = "澶氳溅鑱斿姩妯″紡-鏆傚仠")] public bool MultiVehicleHold = false; + + [AsLowerIO(desc = "澶氳溅鑱斿姩锛氶仴鎺у櫒Vx")] public float MultiVehicleManualVx = 0f; + [AsLowerIO(desc = "澶氳溅鑱斿姩锛氳煿琛屾柟鍚戞瘮渚")] public float MultiVehicleManualVy = 0f; + [AsLowerIO(desc = "澶氳溅鑱斿姩锛氶仴鎺у櫒Vth")] public float MultiVehicleManualVth = 0f; + + #endregion + [IOObjectMonitor(desc = "宸﹀墠宸﹁疆涓嬪彂閫熷害")] public float SpeedLFL; + [IOObjectMonitor(desc = "宸﹀墠鍙宠疆涓嬪彂閫熷害")] public float SpeedLFR; + [IOObjectMonitor(desc = "鍙冲墠宸﹁疆涓嬪彂閫熷害")] public float SpeedRFL; + [IOObjectMonitor(desc = "鍙冲墠鍙宠疆涓嬪彂閫熷害")] public float SpeedRFR; + [IOObjectMonitor(desc = "宸﹀悗宸﹁疆涓嬪彂閫熷害")] public float SpeedLRL; + [IOObjectMonitor(desc = "宸﹀悗鍙宠疆涓嬪彂閫熷害")] public float SpeedLRR; + [IOObjectMonitor(desc = "鍙冲悗宸﹁疆涓嬪彂閫熷害")] public float SpeedRRL; + [IOObjectMonitor(desc = "鍙冲悗鍙宠疆涓嬪彂閫熷害")] public float SpeedRRR; + //[AsUpperIO(desc = "宸﹀墠宸﹁疆涓嬪彂閫熷害", timeOutReset = true)] public float SpeedLFL; + //[AsUpperIO(desc = "宸﹀墠鍙宠疆涓嬪彂閫熷害", timeOutReset = true)] public float SpeedLFR; + //[AsUpperIO(desc = "鍙冲墠宸﹁疆涓嬪彂閫熷害", timeOutReset = true)] public float SpeedRFL; + //[AsUpperIO(desc = "鍙冲墠鍙宠疆涓嬪彂閫熷害", timeOutReset = true)] public float SpeedRFR; + //[AsUpperIO(desc = "宸﹀悗宸﹁疆涓嬪彂閫熷害", timeOutReset = true)] public float SpeedLRL; + //[AsUpperIO(desc = "宸﹀悗鍙宠疆涓嬪彂閫熷害", timeOutReset = true)] public float SpeedLRR; + //[AsUpperIO(desc = "鍙冲悗宸﹁疆涓嬪彂閫熷害", timeOutReset = true)] public float SpeedRRL; + //[AsUpperIO(desc = "鍙冲悗鍙宠疆涓嬪彂閫熷害", timeOutReset = true)] public float SpeedRRR; + + [AsLowerIO(desc = "宸﹀墠宸﹁疆瀹為檯浣嶇疆")] public float LFLActualPos; + [AsLowerIO(desc = "宸﹀墠鍙宠疆瀹為檯浣嶇疆")] public float LFRActualPos; + [AsLowerIO(desc = "鍙冲墠宸﹁疆瀹為檯浣嶇疆")] public float RFLActualPos; + [AsLowerIO(desc = "鍙冲墠鍙宠疆瀹為檯浣嶇疆")] public float RFRActualPos; + [AsLowerIO(desc = "宸﹀悗宸﹁疆瀹為檯浣嶇疆")] public float LRLActualPos; + [AsLowerIO(desc = "宸﹀悗鍙宠疆瀹為檯浣嶇疆")] public float LRRActualPos; + [AsLowerIO(desc = "鍙冲悗宸﹁疆瀹為檯浣嶇疆")] public float RRLActualPos; + [AsLowerIO(desc = "鍙冲悗鍙宠疆瀹為檯浣嶇疆")] public float RRRActualPos; + + [AsUpperIO(desc = "宸﹀す鑷備笅鍙戦熷害", timeOutReset = true)] public float SpeedLeftArm; + [AsUpperIO(desc = "鍙冲す鑷備笅鍙戦熷害", timeOutReset = true)] public float SpeedRightArm; + [AsUpperIO(desc = "宸﹀す鑷傚疄闄呴熷害")] public float ActualSpeedLeftArm; + [AsUpperIO(desc = "鍙冲す鑷傚疄闄呴熷害")] public float ActualSpeedRightArm; + [AsLowerIO(desc = "宸﹀す鑷傜姸鎬佸瓧")] public int LeftArmStateCode; + [AsLowerIO(desc = "鍙冲す鑷傜姸鎬佸瓧")] public int RightArmStateCode; + [AsLowerIO(desc = "宸﹀す鑷傞敊璇瓧")] public int LeftArmErrorCode; + [AsLowerIO(desc = "鍙冲す鑷傞敊璇瓧")] public int RightArmErrorCode; + [AsLowerIO(desc = "宸﹀す鑷傜數娴")] public float LeftArmElectric; + [AsLowerIO(desc = "鍙冲す鑷傜數娴")] public float RightArmElectric; + [AsLowerIO(desc = "宸﹀す鑷傚疄闄呬綅缃")] public float ActualPosLeftArm; + [AsLowerIO(desc = "鍙冲す鑷傚疄闄呬綅缃")] public float ActualPosRightArm; + [AsLowerIO(desc = "test")] public float test; + [AsLowerIO(desc = "test1")] public byte test1; + [AsLowerIO(desc = "test2")] public byte test2; + [AsInitParam(desc = "test3")] public int test3=24; + [IOObjectMonitor(desc = "鐏厜妯″紡")] public int LightMode = 0; + [AsInitParam(desc = "瑙﹀彂妯″紡")] public int trigger = 0; + + [AsInitParam(desc = "鎵嬪姩鎺у埗澶硅噦閫熷害绯绘暟")] public float ManualArmSpeedFac = 1.0f; + [AsInitParam(desc = "杞﹀彿")][AsLowerIO] public int CarNum = 1; + [AsInitParam(desc = "鍒濆闊抽噺")] public int MusicVolume = 5; + + [AsInitParam(desc = "宸﹀す鑷備綆闄愪綅")][AsLowerIO] public int LeftArmLowerPos = -10000; + [AsInitParam(desc = "宸﹀す鑷傞珮闄愪綅")][AsLowerIO] public int LeftArmUpperPos = 5927610; + [AsInitParam(desc = "鍙冲す鑷備綆闄愪綅")][AsLowerIO] public int RightArmLowerPos = -17295; + [AsInitParam(desc = "鍙冲す鑷傞珮闄愪綅")][AsLowerIO] public int RightArmUpperPos = 5927610; + + [AsInitParam(desc = "MCU绔彛鍙")] public string MCUPort = "COM4"; + + [AsLowerIO(desc = "闄铻轰华瑙掑害")] public float GyrosTh; + [AsLowerIO(desc = "鐢垫睜鍋ュ悍鐘舵")] public float SOH; + + [AsLowerIO(desc = "宸﹀墠宸﹂┍鍔ㄥ櫒杩滅▼甯701")] public byte LFLRemoteCode = 0; + [AsLowerIO(desc = "宸﹀墠鍙抽┍鍔ㄥ櫒杩滅▼甯702")] public byte LFRRemoteCode = 0; + [AsLowerIO(desc = "鍙冲墠宸﹂┍鍔ㄥ櫒杩滅▼甯703")] public byte RFLRemoteCode = 0; + [AsLowerIO(desc = "鍙冲墠鍙抽┍鍔ㄥ櫒杩滅▼甯704")] public byte RFRRemoteCode = 0; + [AsLowerIO(desc = "宸﹀悗宸﹂┍鍔ㄥ櫒杩滅▼甯705")] public byte LRLRemoteCode = 0; + [AsLowerIO(desc = "宸﹀悗鍙抽┍鍔ㄥ櫒杩滅▼甯706")] public byte LRRRemoteCode = 0; + [AsLowerIO(desc = "鍙冲悗宸﹂┍鍔ㄥ櫒杩滅▼甯707")] public byte RRLRemoteCode = 0; + [AsLowerIO(desc = "鍙冲悗鍙抽┍鍔ㄥ櫒杩滅▼甯708")] public byte RRRRemoteCode = 0; + [AsLowerIO(desc = "宸﹀す鑷傞┍鍔ㄥ櫒杩滅▼甯709")] public byte LArmRemoteCode = 0; + [AsLowerIO(desc = "鍙冲す鑷傞┍鍔ㄥ櫒杩滅▼甯70A")] public byte RArmRemoteCode = 0; + [AsUpperIO(desc = "浠嶮涓婂浣")] public bool ResetFromM; + [AsUpperIO(desc = "浠嶮灏嗛┍鍔ㄨ疆涓嬩娇鑳")] public bool DisableFromM; + [AsUpperIO(desc = "浠嶤涓婂浣")] public bool ResetFromC; + [AsUpperIO(desc = "浠嶤灏嗛┍鍔ㄨ疆涓嬩娇鑳")] public bool DisableFromC; + [AsUpperIO(desc = "澶硅噦涓嶅悓姝ユ姤璀")] public bool ClampOutOfSync; + + internal ManualControlMode TransmitterControlMode = ManualControlMode.Normal; + + [IOObjectMonitor] public float TransmitterSpeed = 0.3f; + [AsLowerIO(desc = "椹卞姩杞娇鑳界姸鎬")] public bool WheelAbleState = true; + + [AsInitParam(desc = "閬ユ帶鍣ㄩ熷害涓婇檺")] public float TransmitterSpeedUpperLimit = 1.0f; + [AsInitParam(desc = "閬ユ帶鍣ㄩ熷害涓嬮檺")] public float TransmitterSpeedLowerLimit = 0.0f; + internal DateTime TransmitterLastTime; + + [IOObjectUtility] + public void WheelReset() + { + ResetFromM = true; + } + + [IOObjectUtility] + public void WheelDisable() + { + DisableFromM = true; + } + + public override void CommunicationInit() + { + if (GhostMode) return; + + Bridge = new MCUSerialBridge(); + //Step1:鎵撳紑鎸囧畾涓插彛杩炴帴 + var err = Bridge.Open(MCUPort, 1000000u); + if (err != MCUSerialBridgeError.OK) + { + Console.WriteLine("MCU Open FAILED: {0}", err.ToDescription()); + return; + } + else + { + Console.WriteLine("MCU Open OK"); + } + + //Step2:杩滅▼澶嶄綅MCU + err = Bridge.Reset(); + if (err != MCUSerialBridgeError.OK) + { + Console.WriteLine("MCU Reset FAILED: {0}", err.ToDescription()); + return; + } + else + { + Thread.Sleep(500); + Console.WriteLine("MCU Reset OK"); + } + + //Step3:GetVersion + err = Bridge.GetVersion(out var version, 100); + if (err != MCUSerialBridgeError.OK) + { + Console.WriteLine("MCU GetVersion FAILED: {0}", err.ToDescription()); + return; + } + else + { + Console.WriteLine("MCU GetVersion OK: {0}", version.ToString()); + } + + //Step4:GetState + err = Bridge.GetState(out var state, 100); + if (err != MCUSerialBridgeError.OK) + { + Console.WriteLine("MCU GetState FAILED: {0}", err.ToDescription()); + return; + } + else + { + Console.WriteLine("MCU GetState OK: {0}", state.ToString()); + } + + //Step5:涓插彛/CAN閰嶇疆 + try + { + var ports = new List(); + for (int i = 0; i < 1; i++) + ports.Add(new CANPortConfig(500000, 10)); + for (int i = 0; i < 3; i++) + ports.Add(new SerialPortConfig(9600, 10)); + Console.WriteLine("=== Port Configuration ==="); + for (int i = 0; i < ports.Count; i++) + { + if (ports[i] is SerialPortConfig s) + Console.WriteLine("Port {0}: Serial, Baud={1}, ReceiveFrameMs={2}", + i, + s.Baud, + s.ReceiveFrameMs); + else if (ports[i] is CANPortConfig c) + Console.WriteLine("Port {0}: CAN, Baud={1}, RetryTimeMs={2}", i, c.Baud, c.RetryTimeMs); + } + + var ret = Bridge.Configure(ports, 200); + if (ret != MCUSerialBridgeError.OK) + { + Console.WriteLine("MCU Configure FAILED: {0}", ret.ToDescription()); + return; + } + else + { + Console.WriteLine("MCU Configure OK"); + } + Console.WriteLine("MCU Configure {0}", ret == MCUSerialBridgeError.OK ? "OK" : $"FAILED: 0x{(uint)ret:X8}"); + } + catch (Exception ex) + { + Console.WriteLine("Configure Exception: {0}", ex.Message); + } + //MCUInterface.Start(this); + State = 0; + } + + internal void ManualControl(ManualControlMode mode, float x, float y, float frontDirection, + float speedThreshold, TimeSpan? interval = null) + { + if (Chassis == null) return; + + var speed = speedThreshold * y; + var thPow = (float)Math.Pow(Math.Abs(x), ManualThetaPow) * Math.Sign(x); + var frontTh = -thPow * MaxManualTheta; + var rearTh = thPow * MaxManualTheta; + switch (mode) + { + case ManualControlMode.Normal: + ManualMode = 0; + Chassis.DirectionAngle = frontDirection; + Chassis.SendMotion(speed, frontTh, rearTh, interval); + break; + + case ManualControlMode.Sway: + ManualMode = 1; + Chassis.DirectionAngle = frontDirection; + Chassis.SendMotion(speed, frontTh, -rearTh, interval); + break; + + case ManualControlMode.Crab: + ManualMode = 2; + Chassis.DirectionAngle = 90; + Chassis.SendMotion(speed, frontTh, rearTh, interval); + break; + + case ManualControlMode.Spin: + ManualMode = 3; + Chassis.SendRotateMotion(speed * MaxAngularSpeed, interval); + break; + } + } + + internal enum ManualControlMode + { + Normal = 0, + Spin = 1, + Crab = 2, + Sway = 3 + } + } +} diff --git a/MedullaAdapter/DiverCommunication.cs b/MedullaAdapter/DiverCommunication.cs new file mode 100644 index 0000000..de6df6f --- /dev/null +++ b/MedullaAdapter/DiverCommunication.cs @@ -0,0 +1,144 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Text; +using System.Threading; +using FundamentalLib; + + +namespace MedullaAdapter +{ + public class DiverCommunication + { + private byte[] _receiveBytes ; + private SerialPort _port; + private int _state = 0; + private List _receiveList = new List(); + private int _length = 0; + + private MCUInterface _interface; + + public DiverCommunication(string name, int baudRate) + { + _interface = new MCUInterface(); + _port = new SerialPort(); + _port.PortName = name; // 鏍规嵁浣犵殑瀹為檯涓插彛鍚嶇О淇敼 + _port.BaudRate = baudRate; + _port.Parity = Parity.None; + _port.DataBits = 8; + _port.StopBits = StopBits.One; + _port.Handshake = Handshake.None; + _port.Open(); + Console.WriteLine($"buffer:{_port.ReadBufferSize}"); + //_port.DataReceived += OnDataReceived; + new Thread(() => + { + while (true) + { + Thread.Sleep(10); + try + { + int bytesToRead = _port.BytesToRead; + if (bytesToRead > 0) + { + var readBuffer = new byte[bytesToRead]; + var start = DateTime.Now; + _port.Read(readBuffer, 0, bytesToRead); + var time1 = DateTime.Now - start; + ProcessBuffer(readBuffer); + var time2 = DateTime.Now - start; + Hedingben.ToastText($"total time:{time2.TotalMilliseconds},read time:{time1},read count:{bytesToRead}", "timeDebug"); + } + } + catch (Exception exception) + { + Console.WriteLine(exception); + } + } + }).Start(); + } + + private void ProcessBuffer(byte[] buffer) + { + for (int i = 0; i < buffer.Length; i++) + { + var newByte = buffer[i]; + switch (_state) + { + case 0: + _receiveList.Clear(); + if (newByte == 0xBB) + { + _receiveList.Add(newByte); + _state = 1; + } + break; + case 1: + if (newByte == 0xAA) + { + _receiveList.Add(newByte); + _state = 2; + } + else + { + _state = 0; + } + break; + case 2: + _receiveList.Add(newByte); + if (_receiveList.Count >= 4) + { + _length = BitConverter.ToUInt16(_receiveList.ToArray(), 2); + } + + if (_receiveList.Count == _length + 7) + { + _state = 0; + if (_receiveList[_receiveList.Count - 1] == 0xEE) + { + _receiveBytes = _receiveList.ToArray(); + Hedingben.ToastText($"receive from mcu:{BitConverter.ToString(_receiveBytes)}","DiverReceive"); + if (_receiveBytes[5] == 0xA0) + { + var dataLength1 = BitConverter.ToUInt32(_receiveBytes, 6); + var data1 = new byte[dataLength1]; + Array.Copy(_receiveBytes, 14, data1, 0, dataLength1); + MCUInterface.NotifyLowerData("default", data1); + var logBytes = new byte[BitConverter.ToInt32(_receiveBytes, 10)]; + var memorySize = BitConverter.ToInt32(_receiveBytes, 6); + if (logBytes.Length > 0) + { + Array.Copy(_receiveBytes, 14 + memorySize, logBytes, 0, logBytes.Length); + string log = System.Text.Encoding.ASCII.GetString(logBytes); + string[] result = log.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None); + for (int j = 0; j < result.Length; j++) + { + Hedingben.ToastText(result[j], $"mcuLog" + j); + } + } + } + } + else + { + _state = 0; + Hedingben.ToastText($"mcu date error,should end with 0xEE , actual {_receiveList[_receiveList.Count - 1]}","DiverError"); + } + } + break; + default:break; + } + } + } + + public void SendMessage(byte[] data) + { + Hedingben.ToastText($"send to mcu:{BitConverter.ToString(data)}", "DiverSend"); + _port.Write(data, 0, data.Length); + } + + public byte[] GetMessage() + { + return _receiveBytes; + } + } +} diff --git a/MedullaAdapter/EmbeddedCommunication.cs b/MedullaAdapter/EmbeddedCommunication.cs new file mode 100644 index 0000000..87d02ef --- /dev/null +++ b/MedullaAdapter/EmbeddedCommunication.cs @@ -0,0 +1,181 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Linq; +using System.Threading; +using FundamentalLib; +using Medulla; + +namespace MedullaAdapter +{ + public class EmbeddedCommunication + { + private SerialPort _port; + + private byte[] _receiveBytes; + + private byte[] _receiveData; + + private const int BufferThreshold = 300; // 缂撳啿鍖哄ぇ灏忛槇鍊 + + private List _buffer = new List(); // 缂撳瓨鎺ユ敹鍒扮殑鏁版嵁 + + public bool CommunicationError = false; + + private DateTime _lastTime = DateTime.Now; + + private MCUInterface _interface; + + public EmbeddedCommunication(string name, int baudRate) + { + _interface = new MCUInterface(); + _port = new SerialPort(); + _port.PortName = name; // 鏍规嵁浣犵殑瀹為檯涓插彛鍚嶇О淇敼 + _port.BaudRate = baudRate; + _port.Parity = Parity.None; + _port.DataBits = 8; + _port.StopBits = StopBits.One; + _port.Handshake = Handshake.None; + _port.Open(); + _port.DataReceived += OnDataReceived; + } + + public void SendMessage(byte[] data) + { + Hedingben.ToastText($"send to mcu:{BitConverter.ToString(data)}","DiverSend"); + _port.Write(data, 0, data.Length); + } + + public byte[] GetMessage() + { + return _receiveBytes; + } + + private void OnDataReceived(object sender, SerialDataReceivedEventArgs e) + { + try + { + int bytesToRead = _port.BytesToRead; + byte[] buffer = new byte[bytesToRead]; + var startRead = DateTime.Now; + _port.Read(buffer, 0, bytesToRead); + var time = DateTime.Now - startRead; + // 灏嗘柊鎺ユ敹鍒扮殑鏁版嵁娣诲姞鍒扮紦鍐插尯 + startRead = DateTime.Now; + _buffer.AddRange(buffer); + var time2 = DateTime.Now - startRead; + Hedingben.ToastText($"buffer length:{_buffer.Count}","bufferDebug"); + DLog.Log($"buffer length:{_buffer.Count}"); + //if (_buffer.Count > BufferThreshold) + //{ + // _buffer.Clear(); + // return; + //} + + // 灏濊瘯瑙f瀽缂撳啿鍖轰腑鐨勬姤鏂 + var parseTime = DateTime.Now; + ParseBuffer(); + var time3 = DateTime.Now - parseTime; + Hedingben.ToastText( + $"璇诲彇鎶ユ枃鏃堕棿:{time.TotalMilliseconds},澧炲姞鍒扮紦瀛樺尯:{time2.TotalMilliseconds},澶勭悊鏃堕棿:{time3.TotalMilliseconds}", + "timeDebug1"); + } + catch (Exception ex) + { + Console.WriteLine($"璇诲彇涓插彛鏁版嵁鏃跺彂鐢熼敊璇: {ex.Message}"+ex.StackTrace); + } + } + private void ParseBuffer() + { + while (_buffer.Count >= 7) // 鎶ユ枃鐨勬渶灏忛暱搴︽槸 7 + { + // 鏌ユ壘鎶ユ枃澶撮儴 + var findTime = DateTime.Now; + int startIndex = _buffer.FindIndex(0, b => b == 0xBB); + var time1 = DateTime.Now - findTime; + if (startIndex == -1) + { + // 濡傛灉娌℃湁鎵惧埌澶撮儴鎴栧墿浣欓暱搴︿笉瓒虫渶灏忔姤鏂囬暱搴︼紝缁撴潫瑙f瀽 + _buffer.Clear(); + return; + } + + // 纭繚澶撮儴鍚庤繕鏈夎嚦灏 6 涓瓧鑺 + if (startIndex + 1 >= _buffer.Count || _buffer[startIndex + 1] != 0xAA) + { + // 濡傛灉绗簩瀛楄妭涓嶆槸 0xAA锛屼涪寮冩棤鏁堝瓧鑺 + _buffer.RemoveAt(startIndex); + continue; + } + + // 妫鏌ユ暟鎹闀垮害 + if (startIndex + 4 >= _buffer.Count) break; // 鏁版嵁涓嶈冻锛岀瓑寰呬笅娆℃帴鏀 + int dataLength = _buffer[startIndex + 2] | (_buffer[startIndex + 3] << 8); + + // 璁$畻鎶ユ枃鎬婚暱搴 + int totalLength = dataLength + 7; + + // 妫鏌ユ婚暱搴︽槸鍚﹁冻澶 + if (startIndex + totalLength > _buffer.Count) break; // 鏁版嵁涓嶈冻锛岀瓑寰呬笅娆℃帴鏀 + + // 妫鏌ュ熬閮ㄦ槸鍚︽槸 0xCC 0xEE + if (_buffer[startIndex + totalLength - 2] == 0xCC && _buffer[startIndex + totalLength - 1] == 0xEE) + { + var time2 = DateTime.Now - findTime; + var copyTime = DateTime.Now; + // 鎻愬彇瀹屾暣鎶ユ枃 + _receiveBytes = _buffer.Skip(startIndex).Take(totalLength).ToArray(); + var time3 = DateTime.Now - copyTime; + if (_receiveBytes[5] == 0xA0) + { + var dataLength1 = BitConverter.ToUInt32(_receiveBytes, 6); + var data1 = new byte[dataLength1]; + Array.Copy(_receiveBytes, 14, data1, 0, dataLength1); + var notifyTime = DateTime.Now; + MCUInterface.NotifyLowerData("default", data1); + var time4 = DateTime.Now - notifyTime; + var logBytes = new byte[BitConverter.ToInt32(_receiveBytes, 10)]; + var memorySize = BitConverter.ToInt32(_receiveBytes, 6); + if (logBytes.Length > 0) + { + Array.Copy(_receiveBytes, 14 + memorySize, logBytes, 0, logBytes.Length); + string log = System.Text.Encoding.ASCII.GetString(logBytes); + string[] result = log.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None); + for (int i = 0; i < result.Length; i++) + { + Hedingben.ToastText(result[i], $"mcuLog" + i); + } + } + + Hedingben.ToastText( + $"find head time:{time1.TotalMilliseconds},find total time:{time2.TotalMilliseconds},copy time:{time3.TotalMilliseconds},notify time:{time4.TotalMilliseconds}","timeDebug2"); + } + + Hedingben.ToastText( + $"receive from mcu:{BitConverter.ToString(_receiveBytes)},time:{(DateTime.Now - _lastTime).TotalMilliseconds}", + "DiverReceive"); + if ((DateTime.Now - _lastTime).TotalMilliseconds > 200) + { + Hedingben.ToastText($"{(DateTime.Now - _lastTime).TotalMilliseconds}ms no message from diver","DiverTimeout"); + } + _lastTime = DateTime.Now; + // 浠庣紦鍐插尯涓Щ闄ゅ凡瑙f瀽鐨勬姤鏂 + _buffer.RemoveRange(0, startIndex + totalLength); + return; // 鎴愬姛瑙f瀽涓鏉℃姤鏂囧悗閫鍑烘湰杞В鏋 + + } + else + { + // 濡傛灉灏鹃儴鏃犳晥锛屼涪寮冨ご閮ㄥ苟缁х画瑙f瀽 + DLog.Log("DIVER鎶ユ枃鏃犳晥"); + Console.WriteLine("DIVER鎶ユ枃鏃犳晥"); + var errorBytes = _buffer.Skip(startIndex).Take(totalLength).ToArray(); + DLog.Log("閿欒鎶ユ枃"+string.Join(" ",errorBytes.Select(p=>$"{p:X2}"))); + _buffer.RemoveAt(startIndex); + } + + } + } + + } +} diff --git a/MedullaAdapter/FleetRemote.cs b/MedullaAdapter/FleetRemote.cs new file mode 100644 index 0000000..4a67e8d --- /dev/null +++ b/MedullaAdapter/FleetRemote.cs @@ -0,0 +1,246 @@ +锘縰sing System; +using CartActivator; +using CycleGUI; +using CycleGUI.API; +using FundamentalLib; +using Medulla.Types; + +namespace MedullaAdapter +{ + public partial class DiverCartDefinition + { + private bool _fleetRemoteActive; + private DateTime _fleetDiagLastStick = DateTime.MinValue; + + private void FleetDiag(string msg) + { + DLog.Log($"car{CarNum} {msg}", "FleetDiagMedulla"); + } + + private void ZeroFleetManualFields() + { + MultiVehicleManualEnabled = false; + MultiVehicleManualMode = 0; + MultiVehicleManualVx = 0; + MultiVehicleManualVy = 0; + MultiVehicleManualVth = 0; + } + + public float ApplyFleetManualCommand(int mode, float px, float py, float speedRatio) + { + var ratio = Clamp(speedRatio, 0, 1); + px = Clamp(px, -1, 1); + py = Clamp(py, -1, 1); + + if (mode < 0 || mode > 2) mode = 0; + MultiVehicleManualMode = mode; + + if (mode == 2) + { + MultiVehicleManualVx = 0; + MultiVehicleManualVy = 0; + MultiVehicleManualVth = px * MaxManualAngularSpeed * ratio; + } + else if (mode == 1) + { + MultiVehicleManualVx = py * MaxManualSpeed * ratio; + MultiVehicleManualVy = px * MaxManualSpeed * ratio; + MultiVehicleManualVth = 0; + } + else + { + MultiVehicleManualVx = py * MaxManualSpeed * ratio; + MultiVehicleManualVy = 0; + MultiVehicleManualVth = px * MaxManualAngularSpeed * ratio; + } + + return ratio; + } + + [IOObjectUtility] + public void FleetRemote() + { + if (_fleetRemoteActive) + { + return; + } + + _fleetRemoteActive = true; + var fleetOn = false; + var crabOn = false; + var rotateOn = false; + var speedRatio = 1f; + UseGesture manip = null; + + int CurrentMode() + { + if (crabOn) return 1; + if (rotateOn) return 2; + return 0; + } + + void ApplyMode() + { + MultiVehicleManualMode = fleetOn ? CurrentMode() : 0; + } + + void CleanupFleetRemote() + { + if (manip != null) + { + manip.End(); + manip = null; + } + + fleetOn = false; + crabOn = false; + rotateOn = false; + ZeroFleetManualFields(); + _fleetRemoteActive = false; + } + + manip = new UseGesture(); + + manip.AddWidget(new UseGesture.StickWidget + { + name = "fleet_stick", + text = "閫熷害鎽囨潌", + position = "37.5%+10px, 18%+10px", + size = "37.5%-10px, 32%-10px", + bounceBack = true, + keyboard = "Up,Down,Left,Right", + joystick = "Axis0,Axis1", + OnValue = (pos, manipulating) => + { + if (!fleetOn) + { + MultiVehicleManualVx = 0; + MultiVehicleManualVy = 0; + MultiVehicleManualVth = 0; + if ((DateTime.Now - _fleetDiagLastStick).TotalMilliseconds >= 200) + { + _fleetDiagLastStick = DateTime.Now; + FleetDiag($"STICK(ignored,fleetOff) pos=({pos.X:0.00},{pos.Y:0.00}) manip={manipulating}"); + } + return; + } + + var mode = CurrentMode(); + var ratio = ApplyFleetManualCommand(mode, pos.X, pos.Y, speedRatio); + + if ((DateTime.Now - _fleetDiagLastStick).TotalMilliseconds >= 200) + { + _fleetDiagLastStick = DateTime.Now; + FleetDiag($"STICK mode={mode} pos=({pos.X:0.00},{pos.Y:0.00}) manip={manipulating} ratio={ratio:0.00} " + + $"-> Vx={MultiVehicleManualVx:0.000} Vy={MultiVehicleManualVy:0.000} Vth={MultiVehicleManualVth:0.0} en={MultiVehicleManualEnabled}"); + } + } + }); + + manip.AddWidget(new UseGesture.ToggleWidget + { + name = "fleet_crab", + text = "妯Щ妯″紡", + position = "12.5%+10px, 52%+10px", + size = "37.5%-10px, 10%-10px", + OnValue = b => + { + crabOn = b; + ApplyMode(); + FleetDiag($"TOGGLE crab={b} -> mode={MultiVehicleManualMode}"); + } + }); + + manip.AddWidget(new UseGesture.ToggleWidget + { + name = "fleet_rotate", + text = "鍘熷湴鏃嬭浆", + position = "50%+10px, 52%+10px", + size = "37.5%-10px, 10%-10px", + OnValue = b => + { + rotateOn = b; + ApplyMode(); + FleetDiag($"TOGGLE rotate={b} -> mode={MultiVehicleManualMode}"); + } + }); + + manip.AddWidget(new UseGesture.ToggleWidget + { + name = "fleet_enable", + text = "杞﹂槦鑱斿姩", + position = "12.5%+10px, 64%+10px", + size = "37.5%-10px, 10%-10px", + OnValue = b => + { + fleetOn = b; + MultiVehicleManualEnabled = b; + ApplyMode(); + if (!b) ZeroFleetManualFields(); + FleetDiag($"TOGGLE fleetOn={b} -> ManualEnabled={MultiVehicleManualEnabled} mode={MultiVehicleManualMode}"); + } + }); + + manip.AddWidget(new UseGesture.ThrottleWidget + { + name = "fleet_speed_ratio", + text = "閫熷害姣斾緥", + position = "50%+10px, 64%+10px", + size = "37.5%-10px, 10%-10px", + bounceBack = false, + OnValue = (val, _) => speedRatio = Clamp(val, 0, 1) + }); + + manip.AddWidget(new UseGesture.ButtonWidget + { + name = "fleet_stop", + text = "鎬ュ仠/褰掗浂", + position = "31.25%+10px, 76%+10px", + size = "37.5%-10px, 10%-10px", + OnPressed = pressed => + { + if (!pressed) return; + MultiVehicleManualVx = 0; + MultiVehicleManualVy = 0; + MultiVehicleManualVth = 0; + FleetDiag("BUTTON stop/zero"); + } + }); + + manip.ChangeState(new SetAppearance { drawGuizmo = false }); + manip.Start(); + + GUI.PromptOrBringToFront(pb => + { + if (pb.Closing()) + { + CleanupFleetRemote(); + pb.Panel.Exit(); + return; + } + + pb.Panel.TopMost(true) + .SetDefaultDocking(Panel.Docking.None) + .ShowTitle("杞﹂槦鑱斿姩閬ユ帶") + .InitSize(340, 190) + .InitPos(false, -32, 32, 1, 0, 1, 0); + + pb.SeparatorText("鐘舵"); + var modeName = MultiVehicleManualMode == 2 ? "鍘熷湴鏃嬭浆" : MultiVehicleManualMode == 1 ? "妯Щ" : "甯歌"; + pb.Label($"杞﹂槦鑱斿姩: {MultiVehicleManualEnabled} 妯″紡: {modeName}"); + pb.Label($"閫熷害姣斾緥: {speedRatio:0.00}"); + pb.Label($"Vx={MultiVehicleManualVx:0.000} Vy={MultiVehicleManualVy:0.000} m/s, Vth={MultiVehicleManualVth:0.0}"); + pb.Label($"浼樺厛绾: {CartActivator.CartDefinition.currentPriority} ({CartActivator.CartDefinition.currentPriorityDesc})"); + pb.Label("璇峰嬁鍚屾椂鎵撳紑鎵嬪姩鎺у埗闈㈡澘"); + pb.Panel.Repaint(); + }, instancingObject: this); + } + + private static float Clamp(float value, float min, float max) + { + if (value < min) return min; + if (value > max) return max; + return value; + } + } +} diff --git a/MedullaAdapter/FodyWeavers.xml b/MedullaAdapter/FodyWeavers.xml new file mode 100644 index 0000000..dfbedd9 --- /dev/null +++ b/MedullaAdapter/FodyWeavers.xml @@ -0,0 +1,3 @@ +锘 + + \ No newline at end of file diff --git a/MedullaAdapter/FodyWeavers.xsd b/MedullaAdapter/FodyWeavers.xsd new file mode 100644 index 0000000..ccaeb4a --- /dev/null +++ b/MedullaAdapter/FodyWeavers.xsd @@ -0,0 +1,26 @@ +锘 + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/MedullaAdapter/MCUInterface.cs b/MedullaAdapter/MCUInterface.cs new file mode 100644 index 0000000..8786892 --- /dev/null +++ b/MedullaAdapter/MCUInterface.cs @@ -0,0 +1,291 @@ +锘縰sing CartActivator; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using Newtonsoft.Json; +using FundamentalLib; + + +namespace MedullaAdapter +{ + // todo: currently use this ladderlogic to act interaction with Medulla. + // todo: directly integrate into CartActivator. + + // MCU->Medulla is intervally exchanged information. + public class MCUInterface : LadderLogic where T : DiverCartDefinition + { + + /// ////////////////////////////// IMPLEMENT THESE //////////////////////////////////////////// + + public static void SetMCUProgram(string mcu_device_url, byte[] program) + { + List SplitArrayIntoChunks(byte[] array, int chunkSize) + { + List chunks = new List(); + + for (int i = 0; i < array.Length; i += chunkSize) + { + int currentChunkSize = Math.Min(chunkSize, array.Length - i); + byte[] chunk = new byte[currentChunkSize]; + Array.Copy(array, i, chunk, 0, currentChunkSize); + chunks.Add(chunk); + } + return chunks; + } + //todo: modify this. + var codeList = SplitArrayIntoChunks(program, 1024); + int i = 0; + foreach (var codePack in codeList) + { + var downloadCode = + new DownloadCodePack(program.Length, 1024 * i, codePack.Length, codePack).GetPack(); + Console.WriteLine(string.Join(" ", downloadCode.Select(p => $"{p:X2}"))); + cart.Embedded.SendMessage(downloadCode); + Console.WriteLine($"send bytes length:{downloadCode.Length}"); + i++; + Thread.Sleep(50); + //while (true) + //{ + // var receive = cart.Embedded.GetMessage(); + // if (receive == null) continue; + // if (receive[5] == 0x90 && (receive[6] == 0x05 || receive[6]==0x06)) break; + //} + } + var controlPack2 = new ControlPack(0x01).GetPack(); + cart.Embedded.SendMessage(controlPack2); + Console.WriteLine("涓嬪彂浠g爜"); + //MCUTestRunner.DebugSetMCUProgram(program, (bs) => NotifyLowerData("default", bs)); + } + + public static void SendUpperData(string mcu_device_url, byte[] data) + { + //todo: this is for VM data exchange, contains upperIO/lowerIO modifications. + var upperPack = new UpperIOPack(data, data.Length).GetPack(); + cart.Embedded.SendMessage(upperPack); + //MCUTestRunner.DebugSendUpper(data); + } + + + /// ////////////////////////////// INTERFACES //////////////////////////////////////////// + + public static void NotifyPrint(string mcu_device_url, string message) + { + Console.WriteLine($"{mcu_device_url}:{message}"); + } + + // whenever a lower io data is uploaded, call this. + public static void NotifyLowerData(string mcu_device_url, byte[] lowerIOData) + { + using var ms = new MemoryStream(lowerIOData); + using var br = new BinaryReader(ms); + if (mcu_logics.TryGetValue(mcu_device_url, out var tup)) + { + Hedingben.ToastText($"recv iter {br.ReadInt32()} lowerIO data from {mcu_device_url}, operation {tup.name}", $"DIVER-{tup.name}"); + while (ms.Position < lowerIOData.Length) + { + var cid = br.ReadInt16(); + if (cid < 0 || cid > tup.fields.Length) throw new Exception("invalid Cartfield id!"); + // if it's upperio skip, otherwise write data. + var typeid = br.ReadByte(); + if (tup.fields[cid].typeid != typeid) + throw new Exception($"??? typeid not match for {tup.fields[cid].field}({cid}), expected {tup.fields[cid].typeid} got {typeid}"); + + object value; + switch (tup.fields[cid].typeid) + { + case 0: + value = br.ReadBoolean(); + break; + case 1: + value = br.ReadByte(); + break; + case 2: + value = br.ReadSByte(); + break; + case 3: + value = br.ReadChar(); + break; + case 4: + value = br.ReadInt16(); + break; + case 5: + value = br.ReadUInt16(); + break; + case 6: + value = br.ReadInt32(); + break; + case 7: + value = br.ReadUInt32(); + break; + case 8: + value = br.ReadSingle(); + break; + default: + throw new Exception($"Unsupported type ID: {tup.fields[cid].typeid}"); + } + + if (tup.fields[cid].isUpper) continue; + tup.fields[cid].fi.SetValue(cart, value); + } + + // ok to send current data. + using var sends = new MemoryStream(); + using var bw = new BinaryWriter(sends); + bw.Write(tup.iterations++); + for (var cid = 0; cid < tup.fields.Length; cid++) + { + bw.Write((short)cid); + bw.Write((byte)tup.fields[cid].typeid); + var val = tup.fields[cid].fi.GetValue(cart); + switch (tup.fields[cid].typeid) + { + case 0: + bw.Write((bool)val); + break; + case 1: + bw.Write((byte)val); + break; + case 2: + bw.Write((sbyte)val); + break; + case 3: + bw.Write((char)val); + break; + case 4: + bw.Write((short)val); + break; + case 5: + bw.Write((ushort)val); + break; + case 6: + bw.Write((int)val); + break; + case 7: + bw.Write((uint)val); + break; + case 8: + bw.Write((float)val); + break; + } + } + + SendUpperData(mcu_device_url, sends.ToArray()); + } + else + { + Hedingben.ToastText($"warning: {mcu_device_url} received lowerIOData but not registered","DIVERWarning"); + } + } + + public static void Start(T c) + { + cart = c; + + var logics = typeof(T).Assembly.GetTypes() + .Where(p => p.GetCustomAttribute() != null).ToArray(); + foreach (var logic in logics) + { + var attr = logic.GetCustomAttribute(); + Console.WriteLine($"Set logic {logic.Name} to run on MCU-VM @ device {attr.mcu_url}"); + + byte[] ReadAllBytes(Stream stream) + { + using (var ms = new MemoryStream()) + { + stream.CopyTo(ms); + return ms.ToArray(); + } + } + var bytes = ReadAllBytes(Assembly.GetExecutingAssembly().GetManifestResourceStream($"{logic.Name}.bin")); + SetMCUProgram(attr.mcu_url, bytes); + var json = UTF8Encoding.UTF8.GetString(ReadAllBytes(Assembly.GetExecutingAssembly() + .GetManifestResourceStream($"{logic.Name}.bin.json"))); + Console.WriteLine(json); + var fields = JsonConvert.DeserializeObject(json); + if (mcu_logics.ContainsKey(attr.mcu_url)) + throw new Exception($"Already have logic for {attr.mcu_url}: LadderLogic {logic.Name}"); + mcu_logics[attr.mcu_url] = new LogicInfo() { fields = fields, name = logic.Name }; + foreach (var pField in fields) + { + pField.fi = typeof(T).GetField(pField.field); + if (pField.fi == null) + throw new Exception($"field {pField.field} doesn't exist in cart object?"); + pField.isUpper = pField.fi.IsDefined(typeof(AsUpperIO)); + // todo: check type. + } + } + } + + /// ///////////////////////////////// DONT CARE ///////////////////////////////////// + private static T cart; + + class PField + { + public string field; + public FieldInfo fi; + public bool isUpper; + public int typeid, offset; + } + + class LogicInfo + { + public string name; + public PField[] fields; + public int iterations; + } + private static Dictionary mcu_logics = new(); + public override void Operation(int iteration) + { + // just send LIO. + } + } + + //unsafe class MCUTestRunner + //{ + + // public delegate void NotifyLowerDelegate(byte* changedStates, int length); + // [DllImport("MCURuntime.dll", CallingConvention = CallingConvention.Cdecl)] + // public static extern void set_lowerio_cb(NotifyLowerDelegate callback); + + // private static NotifyLowerDelegate DNotifyStateChanged = StateChanged; + + // [DllImport("MCURuntime.dll")] + // static extern void test(byte* bin, int len); + // [DllImport("MCURuntime.dll")] + // static extern void put_upper(byte* bin, int len); + + // private static Action lo_notifier; + // private static void StateChanged(byte* changedstates, int length) + // { + // byte[] byteArray = new byte[length]; + // Marshal.Copy((IntPtr)changedstates, byteArray, 0, length); + // lo_notifier(byteArray); + // } + + // public static void DebugSendUpper(byte[] data) + // { + // fixed (byte* ptr = data) + // { + // put_upper(ptr, data.Length); + // } + // } + // public static void DebugSetMCUProgram(byte[] program, Action notifier) + // { + // lo_notifier = notifier; + // set_lowerio_cb(DNotifyStateChanged); + // new Thread(() => + // { + // var allb = new byte[10240]; //10K runtime + // Array.Copy(program, allb, program.Length); + // fixed (byte* ptr = allb) + // { + // test(ptr, 10240); + // } + // }).Start(); + // } + //} +} diff --git a/MedullaAdapter/MCURoutine.cs b/MedullaAdapter/MCURoutine.cs new file mode 100644 index 0000000..1160658 --- /dev/null +++ b/MedullaAdapter/MCURoutine.cs @@ -0,0 +1,879 @@ +锘縰sing CartActivator; +using FundamentalLib; +using MCUSerialBridgeCLR; +using System; +using System.Collections.Generic; + +namespace MedullaAdapter +{ + //[LogicRunOnMCU(scanInterval = 20)] + public class MCURoutine:LadderLogic + { + private int _lastIteration = 0; + private int _count = 0; + private int _operationTime = 0; + private bool _driversDisabled; + private bool _canCallbackRegistered; + private bool _serialCallbackRegistered; + private byte _resetCode = 0x86; + private byte _enableCode1 = 0x06; + private byte _enableCode2 = 0x07; + private byte _enableCode3 = 0x0F; + private bool io_bit0 = false;//缁х數鍣 + private bool io_bit1 = false;//鎶遍椄 + private bool io_bit2 = false;//绾㈢伅 + private bool io_bit3 = false;//缁跨伅 + private bool io_bit4 = false;//榛勭伅 + private const byte BatteryPortIndex = 3; + private static readonly byte[] BatteryRequest = BuildBatteryRequest(); + + private static float ConvertMps2Rpm(float mps) + { + return (float)(mps / (Math.PI * 85f) * 10.5f * 60f * 1000f); + } + private static float ConvertRpm2Mps(float rpm) + { + return (float)(rpm / 10.5f / 60f * Math.PI * 85f / 1000f); + } + private float ConvertR2MM(float r) + { + return (float)(r / 10.5f * Math.PI * 85); + } + private static float DecodeRpmFromPayload(byte[] payload, int offset = 4) + { + return BitConverter.ToInt32(payload, offset) * 1875f / 512f / 10000f; + } + public override void Operation(int iteration) + { + if (_lastIteration != iteration) + { + _lastIteration = iteration; + _count = 0; + } + else + { + _count++; + } + if (_count >= 15) + { + cart.AlarmLevel = 2; + Console.WriteLine("mcu lost connection \n"); + } + + if (_count >= 30) + { + return; + } + if (cart?.Bridge == null) + { + return; + } + //娉ㄥ唽CAN鍥炶皟 + EnsureCanCallbacksRegistered(); + //娉ㄥ唽涓插彛鍥炶皟 + EnsureSerialCallbacksRegistered(); + PollBatterySerial(iteration); + + #region io閮ㄥ垎 + var ioReadBuffer = new byte[4]; + var readInputErr = cart.Bridge.ReadInput(out ioReadBuffer, 20); + if (readInputErr == MCUSerialBridgeError.OK) + { + cart.test = ioReadBuffer[0]; + cart.Start = (ioReadBuffer[0] & (1 << 0)) != 0; + cart.ResetPressed = (ioReadBuffer[0] & (1 << 1)) != 0; + cart.ChassisMode = ((ioReadBuffer[0] & (1 << 2)) == 0) ? 0 : 1; + cart.BrakeEnable = (ioReadBuffer[0] & (1 << 3)) != 0; + if ((ioReadBuffer[0] & (1 << 4)) == 0) + { + cart.EmergencyPressed = 1; + } + } + else + { + Console.WriteLine("IO Read FAILED"); + } + + var ioWriteBuffer = new byte[4]; + io_bit0 = cart.ChargePort ? true : false; + io_bit1 = cart.EmergencyPressed == 1 ? false : true; + if (cart.MultiVehicleLightSync == 0) + { + io_bit2 = false; + io_bit3 = false; + io_bit4 = false; + } + else if (cart.MultiVehicleLightSync == 1) + { + io_bit2 = false; + io_bit3 = true; + io_bit4 = false; + } + else + { + if (cart.LightMode == 2) + { + io_bit2 = true;//绾 + io_bit3 = false;//缁 + io_bit4 = false;//榛 + } + else if (cart.LightMode == 3) + { + io_bit2 = false; + io_bit3 = false; + io_bit4 = true; + } + else if (cart.LightMode == 1) + { + io_bit2 = false; + io_bit3 = true; + io_bit4 = false; + } + else + { + io_bit2 = false; + io_bit3 = false; + io_bit4 = false; + } + } + + ioWriteBuffer[0] = (byte)((io_bit0 ? 1 << 0 : 0) | //缁х數鍣 + (io_bit1 ? 1 << 1 : 0) | //鎶遍椄 + (io_bit2 ? 1 << 2 : 0) | //绾㈢伅 + (io_bit3 ? 1 << 3 : 0) | //缁跨伅 + (io_bit4 ? 1 << 4 : 0)); //榛勭伅 + if (cart.Bridge.WriteOutput(ioWriteBuffer, 20) != MCUSerialBridgeError.OK) + { + Console.WriteLine("IO Write FAILED"); + } + #endregion + + #region 椹卞姩閮ㄥ垎 + cart.ActualSpeedLeftFront = (cart.ActualSpeedLeftFrontLeft + cart.ActualSpeedLeftFrontRight) / 2; + cart.ActualSpeedLeftRear = (cart.ActualSpeedLeftRearLeft + cart.ActualSpeedLeftRearRight) / 2; + cart.ActualSpeedRightFront = (cart.ActualSpeedRightFrontLeft + cart.ActualSpeedRightFrontRight) / 2; + cart.ActualSpeedRightRear = (cart.ActualSpeedRightRearLeft + cart.ActualSpeedRightRearRight) / 2; + MCUSerialBridgeError SendCan(byte port, ushort standardId, byte[] payload, bool RTR = false, uint timeout = 2) + { + var canSend = new CANMessage + { + ID = standardId, + RTR = RTR, + DLC = !RTR ? (byte)8 : (byte)0, + Payload = payload ?? new byte[] { } + }; + return cart.Bridge.WriteCAN(port, canSend, timeout); + } + + var resetPayload = new byte[8] { 0xFD, _resetCode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + var enable1Payload = new byte[8] { 0xFD, _enableCode1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + var enable2Payload = new byte[8] { 0xFD, _enableCode2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + var enable3Payload = new byte[8] { 0xFD, _enableCode3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + Hedingben.ToastText($"_operationTime:{_operationTime}", "OperationTime"); + if (_operationTime == 0) + { + SendCan(0, 0x00, new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); + _operationTime++; + return; + } + else if (_operationTime == 1) + { + if (cart.LeftFrontLeftErrorCode != 0) + { + SendCan(0, 0x201, enable1Payload); + SendCan(0, 0x201, resetPayload); + } + if (cart.LeftFrontRightErrorCode != 0) + { + SendCan(0, 0x202, enable1Payload); + SendCan(0, 0x202, resetPayload); + } + if (cart.RightFrontLeftErrorCode != 0) + { + SendCan(0, 0x203, enable1Payload); + SendCan(0, 0x203, resetPayload); + } + if (cart.RightFrontRightErrorCode != 0) + { + SendCan(0, 0x204, enable1Payload); + SendCan(0, 0x204, resetPayload); + } + if (cart.LeftRearLeftErrorCode != 0) + { + SendCan(0, 0x205, enable1Payload); + SendCan(0, 0x205, resetPayload); + } + if (cart.LeftRearRightErrorCode != 0) + { + SendCan(0, 0x206, enable1Payload); + SendCan(0, 0x206, resetPayload); + } + if (cart.RightRearLeftErrorCode != 0) + { + SendCan(0, 0x207, enable1Payload); + SendCan(0, 0x207, resetPayload); + } + if (cart.RightRearRightErrorCode != 0) + { + SendCan(0, 0x208, enable1Payload); + SendCan(0, 0x208, resetPayload); + } + if (cart.LeftArmErrorCode != 0) + { + SendCan(0, 0x209, enable1Payload); + SendCan(0, 0x209, resetPayload); + } + if (cart.RightArmErrorCode != 0) + { + SendCan(0, 0x20A, enable1Payload); + SendCan(0, 0x20A, resetPayload); + } + _operationTime++; + return; + } + else if (_operationTime == 2) + { + //SendNodeGuardRequests(SendCan); + //if (AreAllNodesOperational()) + //{ + // _operationTime++; + //} + _operationTime++; + return; + } + //妫鏌ラ敊璇槸鍚﹁娑堥櫎 鑻ユ病琚秷闄ゅ氨寰楅噸鏂拌繑鍥炰笂涓姝ュ彂澶嶄綅 鑻ユ秷闄や簡灏辩户缁線涓 + else if (_operationTime == 3) + { + if (cart.LeftFrontLeftErrorCode != 0 || cart.LeftFrontRightErrorCode != 0 || + cart.LeftRearLeftErrorCode != 0 || cart.LeftRearRightErrorCode != 0 + || cart.RightFrontLeftErrorCode != 0 || cart.RightFrontRightErrorCode != 0 || + cart.RightRearLeftErrorCode != 0 || cart.RightRearRightErrorCode != 0 || + cart.LeftArmErrorCode != 0 || cart.RightArmErrorCode != 0) + { + _operationTime = 1; + return; + } + else + { + _operationTime++; + return; + } + } + // 娌℃湁閿欒 娌℃湁鑺傜偣淇濇姢 灏卞彂06 07 0F浣胯兘 + else if (_operationTime == 4) + { + SendCan(0, 0x201, enable1Payload); + SendCan(0, 0x202, enable1Payload); + SendCan(0, 0x203, enable1Payload); + SendCan(0, 0x204, enable1Payload); + SendCan(0, 0x205, enable1Payload); + SendCan(0, 0x206, enable1Payload); + SendCan(0, 0x207, enable1Payload); + SendCan(0, 0x208, enable1Payload); + SendCan(0, 0x209, enable1Payload); + SendCan(0, 0x20A, enable1Payload); + _operationTime++; + return; + } + else if (_operationTime == 5) + { + SendCan(0, 0x201, enable2Payload); + SendCan(0, 0x202, enable2Payload); + SendCan(0, 0x203, enable2Payload); + SendCan(0, 0x204, enable2Payload); + SendCan(0, 0x205, enable2Payload); + SendCan(0, 0x206, enable2Payload); + SendCan(0, 0x207, enable2Payload); + SendCan(0, 0x208, enable2Payload); + SendCan(0, 0x209, enable2Payload); + SendCan(0, 0x20A, enable2Payload); + _operationTime++; + return; + } + else if (_operationTime == 6) + { + SendCan(0, 0x201, enable3Payload); + SendCan(0, 0x202, enable3Payload); + SendCan(0, 0x203, enable3Payload); + SendCan(0, 0x204, enable3Payload); + SendCan(0, 0x205, enable3Payload); + SendCan(0, 0x206, enable3Payload); + SendCan(0, 0x207, enable3Payload); + SendCan(0, 0x208, enable3Payload); + SendCan(0, 0x209, enable3Payload); + SendCan(0, 0x20A, enable3Payload); + if (cart.LeftFrontLeftErrorCode != 0 || cart.LeftFrontRightErrorCode != 0 || + cart.LeftRearLeftErrorCode != 0 || cart.LeftRearRightErrorCode != 0 + || cart.RightFrontLeftErrorCode != 0 || cart.RightFrontRightErrorCode != 0 || + cart.RightRearLeftErrorCode != 0 || cart.RightRearRightErrorCode != 0 || + cart.LeftArmErrorCode != 0 || cart.RightArmErrorCode != 0) + { + _operationTime = 1; + return; + } + else + { + _operationTime++; + return; + } + } + + if (cart.ResetPressed || cart.ResetFromM || cart.ResetFromC) + { + cart.AlarmLevel = -1; + cart.EmergencyPressed = 0; + _count = 0; + _operationTime = 0; + _driversDisabled = false; + cart.WheelAbleState = true; + cart.ResetFromM = false; + } + + if (cart.DisableFromM || cart.DisableFromC) + { + _driversDisabled = true; + cart.WheelAbleState = false; + cart.DisableFromM = false; + } + + var lfl = Math.Sign(cart.SpeedLFL) * Math.Min(Math.Max(0, cart.SendThresSpeed), Math.Abs(cart.SpeedLFL)); + var lfr = Math.Sign(cart.SpeedLFR) * Math.Min(Math.Max(0, cart.SendThresSpeed), Math.Abs(cart.SpeedLFR)); + var rfl = Math.Sign(cart.SpeedRFL) * Math.Min(Math.Max(0, cart.SendThresSpeed), Math.Abs(cart.SpeedRFL)); + var rfr = Math.Sign(cart.SpeedRFR) * Math.Min(Math.Max(0, cart.SendThresSpeed), Math.Abs(cart.SpeedRFR)); + var lrl = Math.Sign(cart.SpeedLRL) * Math.Min(Math.Max(0, cart.SendThresSpeed), Math.Abs(cart.SpeedLRL)); + var lrr = Math.Sign(cart.SpeedLRR) * Math.Min(Math.Max(0, cart.SendThresSpeed), Math.Abs(cart.SpeedLRR)); + var rrl = Math.Sign(cart.SpeedRRL) * Math.Min(Math.Max(0, cart.SendThresSpeed), Math.Abs(cart.SpeedRRL)); + var rrr = Math.Sign(cart.SpeedRRR) * Math.Min(Math.Max(0, cart.SendThresSpeed), Math.Abs(cart.SpeedRRR)); + + var v1 = ConvertMps2Rpm(lfl); + var v2 = ConvertMps2Rpm(-lfr); + var v3 = ConvertMps2Rpm(rfl); + var v4 = ConvertMps2Rpm(-rfr); + var v5 = ConvertMps2Rpm(lrl); + var v6 = ConvertMps2Rpm(-lrr); + var v7 = ConvertMps2Rpm(rrl); + var v8 = ConvertMps2Rpm(-rrr); + var v9 = ConvertMps2Rpm(cart.SpeedLeftArm); + var v10 = ConvertMps2Rpm(cart.SpeedRightArm); + if (cart.AlarmLevel == 2 || cart.WaitStart || cart.PreparaStart) + { + v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = v10 = 0; + } + if ((cart.ActualPosLeftArm <= cart.LeftArmLowerPos && cart.SpeedLeftArm < 0) || (cart.ActualPosLeftArm >= cart.LeftArmUpperPos && cart.SpeedLeftArm > 0)) + { + v9 = 0; + } + if ((cart.ActualPosRightArm <= cart.RightArmLowerPos && cart.SpeedRightArm < 0) || (cart.ActualPosRightArm >= cart.RightArmUpperPos && cart.SpeedRightArm > 0)) + { + v10 = 0; + } + + var sendLFL = BitConverter.GetBytes((int)Math.Round(v1 * 512f * 10000f / 1875f)); + var sendLFR = BitConverter.GetBytes((int)Math.Round(v2 * 512f * 10000f / 1875f)); + var sendRFL = BitConverter.GetBytes((int)Math.Round(v3 * 512f * 10000f / 1875f)); + var sendRFR = BitConverter.GetBytes((int)Math.Round(v4 * 512f * 10000f / 1875f)); + var sendLRL = BitConverter.GetBytes((int)Math.Round(v5 * 512f * 10000f / 1875f)); + var sendLRR = BitConverter.GetBytes((int)Math.Round(v6 * 512f * 10000f / 1875f)); + var sendRRL = BitConverter.GetBytes((int)Math.Round(v7 * 512f * 10000f / 1875f)); + var sendRRR = BitConverter.GetBytes((int)Math.Round(v8 * 512f * 10000f / 1875f)); + var sendLArm = BitConverter.GetBytes((int)Math.Round(v9 * 512f * 10000f / 1875f)); + var sendRArm = BitConverter.GetBytes((int)Math.Round(v10 * 512f * 10000f / 1875f)); + + if (iteration % 2 == 0) + { + //SendNodeGuardRequests(SendCan); + } + + if (_driversDisabled) + { + SendCan(0, 0x201, enable1Payload); + SendCan(0, 0x202, enable1Payload); + SendCan(0, 0x203, enable1Payload); + SendCan(0, 0x204, enable1Payload); + SendCan(0, 0x205, enable1Payload); + SendCan(0, 0x206, enable1Payload); + SendCan(0, 0x207, enable1Payload); + SendCan(0, 0x208, enable1Payload); + } + else + { + SendCan(0, 0x201, new byte[] { 0xFD, _enableCode3, 0x00, sendLFL[0], sendLFL[1], sendLFL[2], sendLFL[3], 0x00 }); + SendCan(0, 0x202, new byte[] { 0xFD, _enableCode3, 0x00, sendLFR[0], sendLFR[1], sendLFR[2], sendLFR[3], 0x00 }); + SendCan(0, 0x203, new byte[] { 0xFD, _enableCode3, 0x00, sendRFL[0], sendRFL[1], sendRFL[2], sendRFL[3], 0x00 }); + SendCan(0, 0x204, new byte[] { 0xFD, _enableCode3, 0x00, sendRFR[0], sendRFR[1], sendRFR[2], sendRFR[3], 0x00 }); + SendCan(0, 0x205, new byte[] { 0xFD, _enableCode3, 0x00, sendLRL[0], sendLRL[1], sendLRL[2], sendLRL[3], 0x00 }); + SendCan(0, 0x206, new byte[] { 0xFD, _enableCode3, 0x00, sendLRR[0], sendLRR[1], sendLRR[2], sendLRR[3], 0x00 }); + SendCan(0, 0x207, new byte[] { 0xFD, _enableCode3, 0x00, sendRRL[0], sendRRL[1], sendRRL[2], sendRRL[3], 0x00 }); + SendCan(0, 0x208, new byte[] { 0xFD, _enableCode3, 0x00, sendRRR[0], sendRRR[1], sendRRR[2], sendRRR[3], 0x00 }); + } + SendCan(0, 0x209, new byte[] { 0xFD, _enableCode3, 0x00, sendLArm[0], sendLArm[1], sendLArm[2], sendLArm[3], 0x00 }); + SendCan(0, 0x20A, new byte[] { 0xFD, _enableCode3, 0x00, sendRArm[0], sendRArm[1], sendRArm[2], sendRArm[3], 0x00 }); + + if (cart.LeftFrontLeftErrorCode != 0 || cart.LeftFrontRightErrorCode != 0 || + cart.LeftRearLeftErrorCode != 0 || cart.LeftRearRightErrorCode != 0 + || cart.RightFrontLeftErrorCode != 0 || cart.RightFrontRightErrorCode != 0 || + cart.RightRearLeftErrorCode != 0 || cart.RightRearRightErrorCode != 0) + { + //_errorCount++; + } + + #endregion + + } + + private static bool IsNodeOperational(byte remoteCode) + { + return remoteCode == 5 || remoteCode == 133; + } + + private bool AreAllNodesOperational() + { + return IsNodeOperational(cart.LFLRemoteCode) + && IsNodeOperational(cart.LFRRemoteCode) + && IsNodeOperational(cart.RFLRemoteCode) + && IsNodeOperational(cart.RFRRemoteCode) + && IsNodeOperational(cart.LRLRemoteCode) + && IsNodeOperational(cart.LRRRemoteCode) + && IsNodeOperational(cart.RRLRemoteCode) + && IsNodeOperational(cart.RRRRemoteCode) + && IsNodeOperational(cart.LArmRemoteCode) + && IsNodeOperational(cart.RArmRemoteCode); + } + + private static void SendNodeGuardRequests(Func sendCan) + { + sendCan(0, 0x709, Array.Empty(), true, 2); + sendCan(0, 0x70A, Array.Empty(), true, 2); + sendCan(0, 0x701, Array.Empty(), true, 2); + sendCan(0, 0x702, Array.Empty(), true, 2); + sendCan(0, 0x703, Array.Empty(), true, 2); + sendCan(0, 0x704, Array.Empty(), true, 2); + sendCan(0, 0x705, Array.Empty(), true, 2); + sendCan(0, 0x706, Array.Empty(), true, 2); + sendCan(0, 0x707, Array.Empty(), true, 2); + sendCan(0, 0x708, Array.Empty(), true, 2); + } + + private void EnsureCanCallbacksRegistered() + { + if (_canCallbackRegistered) + { + return; + } + if (cart?.Bridge == null) + { + return; + } + var dispatch = BuildCanDispatchTable(); + + var err0 = cart.Bridge.RegisterCANPortCallback(0, msg => + { + if (msg == null) return; + if (dispatch.TryGetValue(msg.ID, out var handler)) + { + handler(msg); + } + }); + _canCallbackRegistered = true; + } + + private void EnsureSerialCallbacksRegistered() + { + if (_serialCallbackRegistered) + { + return; + } + if (cart?.Bridge == null) + { + return; + } + var err1 = cart.Bridge.RegisterSerialPortCallback(1, msg => + { + if (msg == null) return; + Hedingben.ToastText($"Callback Serial 1 Callback Received: {BitConverter.ToString(msg)}", "Serial 1"); + }); + Hedingben.ToastText($"Register Serial 1: {err1}", "Register Serial"); + _serialCallbackRegistered = err1 == MCUSerialBridgeError.OK; + } + + private void PollBatterySerial(int iteration) + { + if (cart?.Bridge == null) return; + if (iteration % 20 != 0) return; + + var writeErr = cart.Bridge.WriteSerial(BatteryPortIndex, BatteryRequest, 60); + if (writeErr != MCUSerialBridgeError.OK) + { + Hedingben.ToastText($"Battery write err: {writeErr}", "Serial 2"); + return; + } + + var readErr = cart.Bridge.ReadSerial(BatteryPortIndex, out var msg, 40); + if (readErr == MCUSerialBridgeError.NoData) return; + if (readErr != MCUSerialBridgeError.OK) + { + Hedingben.ToastText($"Battery read err: {readErr}", "Serial 2"); + return; + } + if (msg == null || msg.Length == 0) return; + + Hedingben.ToastText($"Serial 2 RX: {BitConverter.ToString(msg)}", "Serial 2"); + TryUpdateBatteryData(msg); + } + + private void TryUpdateBatteryData(byte[] msg) + { + // Modbus RTU response: [id,03,08,data(8),crc(2)] + if (msg.Length < 13 || msg[0] != 0x01 || msg[1] != 0x03 || msg[2] < 8) return; + ushort calc = ComputeModbusCrc(msg, msg.Length - 2); + ushort recv = (ushort)(msg[msg.Length - 2] | (msg[msg.Length - 1] << 8)); + if (calc != recv) return; + + cart.Voltage = ReadInt16BE(msg, 3) * 0.1f; + cart.Soc = ReadUInt16BE(msg, 5); + cart.SOH = ReadUInt16BE(msg, 7); + cart.ElectricCurrent = -ReadInt16BE(msg, 9) * 0.1f; + } + + private static byte[] BuildBatteryRequest() + { + // 01 03 00 03 00 04 CRC (璇诲彇瀵勫瓨鍣 03~06) + byte[] req = new byte[] { 0x01, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00 }; + ushort crc = ComputeModbusCrc(req, 6); + req[6] = (byte)(crc & 0xFF); + req[7] = (byte)((crc >> 8) & 0xFF); + return req; + } + + private static ushort ComputeModbusCrc(byte[] data, int length) + { + ushort crc = 0xFFFF; + for (int i = 0; i < length; i++) + { + crc ^= data[i]; + for (int j = 0; j < 8; j++) + { + bool lsb = (crc & 0x0001) != 0; + crc >>= 1; + if (lsb) crc ^= 0xA001; + } + } + return crc; + } + + private static short ReadInt16BE(byte[] data, int offset) + { + return (short)((data[offset] << 8) | data[offset + 1]); + } + + private static ushort ReadUInt16BE(byte[] data, int offset) + { + return (ushort)((data[offset] << 8) | data[offset + 1]); + } + + private Dictionary> BuildCanDispatchTable() + { + return new Dictionary> + { + // 閫熷害/浣嶇疆鍙嶉 0x281~0x28A + [0x281] = (msg) => + { + //Console.WriteLine("Received 0x281 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedLeftFrontLeft = ConvertRpm2Mps(rpm); + cart.LFLActualPos = ConvertR2MM(BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x282] = (msg) => + { + //Console.WriteLine("Received 0x282 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedLeftFrontRight = -ConvertRpm2Mps(rpm); + cart.LFRActualPos = ConvertR2MM(-BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x283] = (msg) => + { + //Console.WriteLine("Received 0x283 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedRightFrontLeft = ConvertRpm2Mps(rpm); + cart.RFLActualPos = ConvertR2MM(BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x284] = (msg) => + { + //Console.WriteLine("Received 0x284 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedRightFrontRight = -ConvertRpm2Mps(rpm); + cart.RFRActualPos = ConvertR2MM(-BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x285] = (msg) => + { + //Console.WriteLine("Received 0x285 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedLeftRearLeft = ConvertRpm2Mps(rpm); + cart.LRLActualPos = ConvertR2MM(BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x286] = (msg) => + { + //Console.WriteLine("Received 0x286 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedLeftRearRight = -ConvertRpm2Mps(rpm); + cart.LRRActualPos = ConvertR2MM(-BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x287] = (msg) => + { + //Console.WriteLine("Received 0x287 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedRightRearLeft = ConvertRpm2Mps(rpm); + cart.RRLActualPos = ConvertR2MM(BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x288] = (msg) => + { + //Console.WriteLine("Received 0x288 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedRightRearRight = -ConvertRpm2Mps(rpm); + cart.RRRActualPos = ConvertR2MM(-BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x289] = (msg) => + { + //Console.WriteLine("Received 0x289 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedLeftArm = ConvertRpm2Mps(rpm); + cart.ActualPosLeftArm = ConvertR2MM(BitConverter.ToInt32(payload, 0) / 10000f); + }, + [0x28A] = (msg) => + { + //Console.WriteLine("Received 0x28A CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 8) return; + var rpm = DecodeRpmFromPayload(payload); + cart.ActualSpeedRightArm = ConvertRpm2Mps(rpm); + cart.ActualPosRightArm = ConvertR2MM(BitConverter.ToInt32(payload, 0) / 10000f); + }, + // 鐘舵/閿欒鐮 0x181~0x18A + [0x181] = (msg) => + { + //Console.WriteLine("Received 0x181 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.LeftFrontLeftStateCode = BitConverter.ToInt16(payload, 0); + cart.LeftFrontLeftErrorCode = BitConverter.ToInt16(payload, 2); + cart.LeftFrontLeftElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x182] = (msg) => + { + //Console.WriteLine("Received 0x182 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.LeftFrontRightStateCode = BitConverter.ToInt16(payload, 0); + cart.LeftFrontRightErrorCode = BitConverter.ToInt16(payload, 2); + cart.LeftFrontRightElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x183] = (msg) => + { + //Console.WriteLine("Received 0x183 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.RightFrontLeftStateCode = BitConverter.ToInt16(payload, 0); + cart.RightFrontLeftErrorCode = BitConverter.ToInt16(payload, 2); + cart.RightFrontLeftElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x184] = (msg) => + { + //Console.WriteLine("Received 0x184 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.RightFrontRightStateCode = BitConverter.ToInt16(payload, 0); + cart.RightFrontRightErrorCode = BitConverter.ToInt16(payload, 2); + cart.RightFrontRightElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x185] = (msg) => + { + //Console.WriteLine("Received 0x185 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.LeftRearLeftStateCode = BitConverter.ToInt16(payload, 0); + cart.LeftRearLeftErrorCode = BitConverter.ToInt16(payload, 2); + cart.LeftRearLeftElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x186] = (msg) => + { + //Console.WriteLine("Received 0x186 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.LeftRearRightStateCode = BitConverter.ToInt16(payload, 0); + cart.LeftRearRightErrorCode = BitConverter.ToInt16(payload, 2); + cart.LeftRearRightElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x187] = (msg) => + { + //Console.WriteLine("Received 0x187 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.RightRearLeftStateCode = BitConverter.ToInt16(payload, 0); + cart.RightRearLeftErrorCode = BitConverter.ToInt16(payload, 2); + cart.RightRearLeftElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x188] = (msg) => + { + //Console.WriteLine("Received 0x188 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.RightRearRightStateCode = BitConverter.ToInt16(payload, 0); + cart.RightRearRightErrorCode = BitConverter.ToInt16(payload, 2); + cart.RightRearRightElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x189] = (msg) => + { + //Console.WriteLine("Received 0x189 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.LeftArmStateCode = BitConverter.ToInt16(payload, 0); + cart.LeftArmErrorCode = BitConverter.ToInt16(payload, 2); + cart.LeftArmElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + [0x18A] = (msg) => + { + //Console.WriteLine("Received 0x18A CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.RightArmStateCode = BitConverter.ToInt16(payload, 0); + cart.RightArmErrorCode = BitConverter.ToInt16(payload, 2); + cart.RightArmElectric = BitConverter.ToInt16(payload, 5) * 0.001f; + }, + + // 鑸佃 0x18B~0x18E + [0x18B] = (msg) => + { + //Console.WriteLine("Received 0x18B CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.ActualThLeftFront = BitConverter.ToInt32(payload, 0); + cart.ActualThLeftFront = cart.ActualThLeftFront >= 16384 + ? (cart.ActualThLeftFront - 98303) / 4096f / 5f * 360 - cart.ThBiasLeftFront + : cart.ActualThLeftFront / 4096f / 5f * 360 - cart.ThBiasLeftFront; + }, + [0x18C] = (msg) => + { + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + var raw = BitConverter.ToInt32(payload, 0); + cart.ActualThRightFront = raw >= 16384 + ? (raw - 98303) / 4096f / 5f * 360 - cart.ThBiasRightFront + : raw / 4096f / 5f * 360 - cart.ThBiasRightFront; + //DLog.Log($"RF raw=0x{raw:X8}({raw}) angle={cart.ActualThRightFront:F2}", "0x18C"); + }, + [0x18D] = (msg) => + { + //Console.WriteLine($"Received 0x18D CAN Message {DateTime.Now:yyyy-MM-dd HH:mm:ss.ffffff}"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.ActualThLeftRear = BitConverter.ToInt32(payload, 0); + cart.ActualThLeftRear = cart.ActualThLeftRear >= 16384 + ? (cart.ActualThLeftRear - 98303) / 4096f / 5f * 360 - cart.ThBiasLeftRear + : cart.ActualThLeftRear / 4096f / 5f * 360 - cart.ThBiasLeftRear; + }, + [0x18E] = (msg) => + { + //Console.WriteLine("Received 0x18E CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 4) return; + cart.ActualThRightRear = BitConverter.ToInt32(payload, 0); + cart.ActualThRightRear = cart.ActualThRightRear >= 16384 + ? (cart.ActualThRightRear - 98303) / 4096f / 5f * 360 - cart.ThBiasRightRear + : cart.ActualThRightRear / 4096f / 5f * 360 - cart.ThBiasRightRear; + }, + + // 杩滅▼甯 + [0x701] = (msg) => + { + //Console.WriteLine("Received 0x701 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.LFLRemoteCode = payload[0]; + }, + [0x702] = (msg) => + { + //Console.WriteLine("Received 0x702 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.LFRRemoteCode = payload[0]; + }, + [0x703] = (msg) => + { + //Console.WriteLine("Received 0x703 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.RFLRemoteCode = payload[0]; + }, + [0x704] = (msg) => + { + //Console.WriteLine("Received 0x704 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.RFRRemoteCode = payload[0]; + }, + [0x705] = (msg) => + { + //Console.WriteLine("Received 0x705 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.LRLRemoteCode = payload[0]; + }, + [0x706] = (msg) => + { + //Console.WriteLine("Received 0x706 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.LRRRemoteCode = payload[0]; + }, + [0x707] = (msg) => + { + //Console.WriteLine("Received 0x707 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.RRLRemoteCode = payload[0]; + }, + [0x708] = (msg) => + { + //Console.WriteLine("Received 0x708 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.RRRRemoteCode = payload[0]; + }, + [0x709] = (msg) => + { + //Console.WriteLine("Received 0x709 CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.LArmRemoteCode = payload[0]; + }, + [0x70A] = (msg) => + { + //Console.WriteLine("Received 0x70A CAN Message"); + var payload = msg.Payload; + if (payload == null || payload.Length < 1) return; + cart.RArmRemoteCode = payload[0]; + }, + }; + } + + } +} diff --git a/MedullaAdapter/MCUSerialBridgeCLR.cs b/MedullaAdapter/MCUSerialBridgeCLR.cs new file mode 100644 index 0000000..b65a13f --- /dev/null +++ b/MedullaAdapter/MCUSerialBridgeCLR.cs @@ -0,0 +1,884 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace MCUSerialBridgeCLR +{ + /// + /// 杈呭姪鏂规硶涓庡唴閮 C 缁撴瀯浣撳皝瑁咃紝鐢ㄤ簬 P/Invoke 浜や簰 + /// + internal static class PortStructHelper + { + /// + /// 灏嗕换鎰忕粨鏋勪綋搴忓垪鍖栦负瀛楄妭鏁扮粍 + /// + /// 缁撴瀯浣撶被鍨 + /// 瑕佸簭鍒楀寲鐨勭粨鏋勪綋 + /// 杩斿洖缁撴瀯浣撳搴旂殑瀛楄妭鏁扮粍 + /// 浣跨敤 Marshal 鍒嗛厤鍐呭瓨骞跺鍒跺唴瀹 + public static byte[] StructToBytes(T str) + where T : struct + { + int size = Marshal.SizeOf(); + byte[] arr = new byte[size]; + IntPtr ptr = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(str, ptr, false); + Marshal.Copy(ptr, arr, 0, size); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + return arr; + } + + /// + /// 涓插彛绔彛閰嶇疆鐨勫師鐢熺粨鏋勪綋锛堜笌 MCU C 灞傚搴旓級 + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct SerialPortConfigC + { + /// 绔彛绫诲瀷锛0x01 = Serial锛 + public byte port_type; + + /// 娉㈢壒鐜 + public uint baud; + + /// 鎺ユ敹甯ф椂闂撮棿闅 + public uint receive_frame_ms; + + /// 淇濈暀瀛楄妭锛屽~ 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] + public byte[] reserved; + } + + /// + /// CAN 绔彛閰嶇疆鐨勫師鐢熺粨鏋勪綋锛堜笌 MCU C 灞傚搴旓級 + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct CANPortConfigC + { + /// 绔彛绫诲瀷锛0x02 = CAN锛 + public byte port_type; + + /// 娉㈢壒鐜 + public uint baud; + + /// 鏈澶ч噸鍙戞椂闂 + public uint retry_time_ms; + + /// 淇濈暀瀛楄妭锛屽~ 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] + public byte[] reserved; + } + } + + /// + /// MCU 鍥轰欢鐗堟湰淇℃伅缁撴瀯浣 + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct VersionInfo + { + /// 浜у搧鍨嬪彿 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string ProductionName; + + /// Git 鏍囩 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string GitTag; + + /// Git commit 鍝堝笇鍊 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string GitCommit; + + /// 缂栬瘧鏃堕棿锛堝瓧绗︿覆锛 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)] + public string BuildTime; + + /// + /// 杞崲涓哄彲璇诲瓧绗︿覆 + /// + /// 杩斿洖鍖呭惈浜у搧銆乀ag銆丆ommit銆丅uildTime 鐨勫瓧绗︿覆 + public override string ToString() + { + return $"Product: {ProductionName}, Tag: {GitTag}, Commit: {GitCommit}, Built: {BuildTime}"; + } + } + + /// + /// MCU 褰撳墠杩愯鐘舵 + /// + [StructLayout(LayoutKind.Explicit)] + public struct MCUState + { + /// 鍘熷 32 浣嶇姸鎬佸 + [FieldOffset(0)] + public uint RawValue; + + /// 鐘舵佸瓙瀛楁 0 + [FieldOffset(0)] + public byte Substate0; + + /// 鐘舵佸瓙瀛楁 1 + [FieldOffset(1)] + public byte Substate1; + + /// 鐘舵佸瓙瀛楁 2 + [FieldOffset(2)] + public byte Substate2; + + /// 楂樺瓧鑺傛ā寮忔爣蹇 + [FieldOffset(3)] + public byte Mode; + + /// 鏄惁澶勪簬 Bridge 妯″紡 + public bool IsBridge => (Mode & 0x80) == 0; + + /// 鏄惁澶勪簬 DIVER 妯″紡 + public bool IsDIVER => (Mode & 0x80) != 0; + + /// + /// 杩斿洖鍙鐨勭姸鎬佸瓧绗︿覆 + /// + /// 渚嬪 "Bridge: Running" 鎴 "DIVER: Error" + public override string ToString() + { + string modeStr = IsBridge ? "Bridge" : "DIVER"; + uint substate = (uint)(Substate0 | (Substate1 << 8) | (Substate2 << 16)); + + string subStr = substate switch + { + 0x00000000 => "Idle", + 0x0000000F => "Running", + 0x000000FF => "Error", + 0x00000001 => "Configured", // DIVER specific + 0x8000000F => "Running", + 0x800000FF => "Error", + _ => $"Unknown (0x{substate:X6})", + }; + + return $"{modeStr}: {subStr}"; + } + } + + /// + /// 鎶借薄绔彛閰嶇疆鍩虹被 + /// + public abstract class PortConfig + { + /// 绔彛绫诲瀷锛堢敱瀛愮被瀹炵幇锛 + public abstract byte PortType { get; } + + /// 搴忓垪鍖栫鍙i厤缃负瀛楄妭鏁扮粍锛堜緵 P/Invoke 浣跨敤锛 + /// 杩斿洖鍥哄畾闀垮害瀛楄妭鏁扮粍锛16 bytes锛 + public abstract byte[] ToBytes(); + } + + /// + /// 涓插彛閰嶇疆 + /// + /// + /// 鏋勯犲嚱鏁 + /// + /// 娉㈢壒鐜 + /// 鎺ユ敹甯ч棿闅 + public class SerialPortConfig(uint baud, uint receiveFrameMs) : PortConfig + { + /// Serial 绫诲瀷 + public override byte PortType => 0x01; + + /// 娉㈢壒鐜 + public uint Baud { get; set; } = baud; + + /// 鎺ユ敹甯ч棿闅 + public uint ReceiveFrameMs { get; set; } = receiveFrameMs; + + /// + /// 杞崲涓哄瓧鑺傛暟缁 + /// + /// 16 瀛楄妭鏁扮粍 + public override byte[] ToBytes() + { + var c = new PortStructHelper.SerialPortConfigC + { + port_type = PortType, + baud = Baud, + receive_frame_ms = ReceiveFrameMs, + reserved = new byte[7], + }; + return PortStructHelper.StructToBytes(c); + } + } + + /// + /// CAN 绔彛閰嶇疆 + /// + /// + /// 鏋勯犲嚱鏁 + /// + /// 娉㈢壒鐜 + /// 閲嶅彂闂撮殧 + public class CANPortConfig(uint baud, uint retryTimeMs) : PortConfig + { + /// CAN 绫诲瀷 + public override byte PortType => 0x02; + + /// 娉㈢壒鐜 + public uint Baud { get; set; } = baud; + + /// 閲嶅彂闂撮殧 + public uint RetryTimeMs { get; set; } = retryTimeMs; + + /// + /// 杞崲涓哄瓧鑺傛暟缁 + /// + /// 16 瀛楄妭鏁扮粍 + public override byte[] ToBytes() + { + var c = new PortStructHelper.CANPortConfigC + { + port_type = PortType, + baud = Baud, + retry_time_ms = RetryTimeMs, + reserved = new byte[7], + }; + return PortStructHelper.StructToBytes(c); + } + } + + /// + /// CAN 甯х粨鏋勶紙鏍囧噯甯 11-bit ID + 1-bit RTR + 4-bit DLC + Payload锛 + /// + public class CANMessage + { + /// 鏍囧噯甯 ID锛0~0x7FF锛11 浣嶏級 + public ushort ID { get; set; } + + /// 杩滅▼甯ф爣蹇楋細false = 鏁版嵁甯э紝true = 杩滅▼甯 + public bool RTR { get; set; } + + /// 鏁版嵁闀垮害鐮侊細0~8 + public byte DLC { get; set; } + + /// 鏁版嵁璐熻浇锛岄暱搴﹀繀椤讳弗鏍肩瓑浜 DLC锛圖LC=0 鏃跺彲涓 null锛 + public byte[] Payload { get; set; } + + /// + /// 搴忓垪鍖栦负 MCU 鍗忚瀛楄妭娴 + /// + /// 杩斿洖瀛楄妭鏁扮粍锛2 bytes header + Payload + /// 濡傛灉 DLC > 8 + /// 濡傛灉 Payload 闀垮害 != DLC + public byte[] ToBytes() + { + if (DLC > 8) + throw new ArgumentOutOfRangeException(nameof(DLC), "DLC must be 0-8"); + if (DLC > 0 && (Payload == null || Payload.Length != DLC)) + throw new ArgumentException("Payload length must equal DLC"); + + // 鏋勯 2 瀛楄妭 header + ushort header = 0; + header |= (ushort)(ID & 0x7FF); // bits 0-10 + if (RTR) + header |= (1 << 11); // bit 11 + header |= (ushort)((DLC & 0xF) << 12); // bits 12-15 + + byte[] result = new byte[2 + DLC]; + byte[] headerBytes = BitConverter.GetBytes(header); // 灏忕搴 + result[0] = headerBytes[0]; + result[1] = headerBytes[1]; + + if (DLC > 0) + Buffer.BlockCopy(Payload, 0, result, 2, DLC); + return result; + } + + /// + /// 鍙嶅簭鍒楀寲 MCU 鍗忚瀛楄妭娴佷负 CANMessage + /// + /// 鍘熷瀛楄妭鏁扮粍 + /// 瀹為檯鏈夋晥闀垮害 + /// CANMessage 瀹炰緥 + /// 鏁版嵁闀垮害閿欒 + public static CANMessage FromBytes(byte[] data, uint length) + { + if (data == null || length > data.Length || length < 2) + throw new ArgumentException("Data must be at least 2 bytes"); + + ushort header = BitConverter.ToUInt16(data, 0); + + var msg = new CANMessage + { + ID = (ushort)(header & 0x7FF), + RTR = (header & (1 << 11)) != 0, + DLC = (byte)((header >> 12) & 0xF), + }; + + if (msg.DLC > 0) + { + if (length < 2 + msg.DLC) + throw new ArgumentException("Data length less than DLC"); + msg.Payload = new byte[msg.DLC]; + Buffer.BlockCopy(data, 2, msg.Payload, 0, msg.DLC); + } + else + { + msg.Payload = Array.Empty(); + } + + return msg; + } + + public override string ToString() + { + string payloadStr = + (Payload == null || Payload.Length == 0) + ? "[]" + : "0x[" + string.Join(" ", Payload.Select(b => $"{b:X2}")) + "]"; + + return $"CANMessage(ID=0x{ID:X3}, RTR={RTR}, DLC={DLC}, Payload={payloadStr})"; + } + } + + /// + /// 鍐呴儴 P/Invoke 灞傦紝鐩存帴鏄犲皠 C DLL 鍑芥暟 + /// + internal static class MCUSerialBridgeCoreAPI + { + private const string DLL = @"mcu_serial_bridge.dll"; + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_open( + out IntPtr handle, + [MarshalAs(UnmanagedType.LPStr)] string port, + uint baud + ); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_close(IntPtr handle); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_reset(IntPtr handle, uint timeout_ms); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + public static extern MCUSerialBridgeError msb_version( + IntPtr handle, + out VersionInfo version, + uint timeout_ms + ); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + public static extern MCUSerialBridgeError mcu_state( + IntPtr handle, + out MCUState state, + uint timeout + ); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_configure( + IntPtr handle, + uint num_ports, + IntPtr ports, + uint timeout + ); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_read_input( + IntPtr handle, + [Out] byte[] inputs, + uint timeout_ms + ); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_write_output( + IntPtr handle, + [In] byte[] outputs, + uint timeout_ms + ); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_read_port( + IntPtr handle, + byte port_index, + [Out] byte[] dst_data, + uint dst_capacity, + out uint out_length, + uint timeout_ms + ); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void msb_on_port_data_callback_function_t( + IntPtr dst_data, + uint dst_data_size, + IntPtr user_ctx + ); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_register_port_data_callback( + IntPtr handle, + byte port_index, + msb_on_port_data_callback_function_t callback, + IntPtr user_ctx + ); + + [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] + internal static extern MCUSerialBridgeError msb_write_port( + IntPtr handle, + byte port_index, + [In] byte[] src_data, + uint src_data_len, + uint timeout_ms + ); + } + + /// + /// MCU 涓插彛/绔彛鎿嶄綔鎵樼灏佽绫 + /// 瀹炵幇 IDisposable 绠$悊搴曞眰鍙ユ焺鐢熷懡鍛ㄦ湡 + /// + public class MCUSerialBridge : IDisposable + { + public static uint MaxPortNumber = 16; + + private IntPtr nativeHandle = IntPtr.Zero; + + /// 鍒ゆ柇鏄惁宸叉墦寮 + public bool IsOpen => nativeHandle != IntPtr.Zero; + + /// 鏋勯犲嚱鏁帮紝鍒濆鍖栧璞 + public MCUSerialBridge() + { + nativeHandle = IntPtr.Zero; + } + + /// 鏋愭瀯鍑芥暟 + ~MCUSerialBridge() + { + Dispose(false); + } + + /// 鏄惧紡閲婃斁璧勬簮 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// 鍐呴儴閲婃斁璧勬簮鏂规硶 + /// true 琛ㄧず鎵嬪姩閲婃斁锛宖alse 琛ㄧず鏋愭瀯閲婃斁 + private void Dispose(bool disposing) + { + if (nativeHandle != IntPtr.Zero) + { + MCUSerialBridgeCoreAPI.msb_close(nativeHandle); + nativeHandle = IntPtr.Zero; + } + } + + /// 鎵撳紑涓插彛 + /// 涓插彛鍚嶏紝濡 "COM3" + /// 娉㈢壒鐜 + /// 閿欒鐮 + public MCUSerialBridgeError Open(string portName, uint baud) + { + return MCUSerialBridgeCoreAPI.msb_open(out nativeHandle, portName, baud); + } + + /// 鍏抽棴涓插彛 + /// 閿欒鐮 + public MCUSerialBridgeError Close() + { + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + MCUSerialBridgeError error = MCUSerialBridgeCoreAPI.msb_close(nativeHandle); + nativeHandle = IntPtr.Zero; + return error; + } + + /// MCU 澶嶄綅 + /// 閿欒鐮 + public MCUSerialBridgeError Reset(uint timeout = 200) + { + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + return MCUSerialBridgeCoreAPI.msb_reset(nativeHandle, timeout); + } + + /// 鑾峰彇鍥轰欢鐗堟湰 + /// 杈撳嚭鐗堟湰淇℃伅 + /// 瓒呮椂鏃堕棿锛坢s锛 + /// 閿欒鐮 + public MCUSerialBridgeError GetVersion(out VersionInfo version, uint timeout = 200) + { + version = new VersionInfo(); + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + return MCUSerialBridgeCoreAPI.msb_version(nativeHandle, out version, timeout); + } + + /// 鑾峰彇 MCU 褰撳墠鐘舵 + /// 杈撳嚭鐘舵 + /// 瓒呮椂鏃堕棿锛坢s锛 + /// 閿欒鐮 + public MCUSerialBridgeError GetState(out MCUState state, uint timeout = 200) + { + state = new MCUState(); + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + return MCUSerialBridgeCoreAPI.mcu_state(nativeHandle, out state, timeout); + } + + /// 閰嶇疆绔彛 + /// 绔彛闆嗗悎 + /// 瓒呮椂鏃堕棿锛坢s锛 + /// 閿欒鐮 + public MCUSerialBridgeError Configure(IEnumerable ports, uint timeout = 200) + { + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + if (ports == null) + return MCUSerialBridgeError.Win_InvalidParam; + + // 杞崲鎴愭暟缁 + PortConfig[] portArray = ports as PortConfig[] ?? ports.ToArray(); + int count = portArray.Length; + + // 鍒嗛厤杩炵画鍘熺敓鍐呭瓨 + int structSize = 16; // 姣忎釜 PortConfig 鍥哄畾 16 瀛楄妭 + IntPtr nativePorts = Marshal.AllocHGlobal(structSize * count); + + try + { + for (int i = 0; i < count; i++) + { + byte[] bytes = portArray[i].ToBytes(); + if (bytes.Length != structSize) + return MCUSerialBridgeError.Win_InvalidParam; + + Marshal.Copy(bytes, 0, nativePorts + i * structSize, structSize); + } + + // 璋冪敤搴曞眰 API + return MCUSerialBridgeCoreAPI.msb_configure( + nativeHandle, + (uint)count, + nativePorts, + timeout + ); + } + catch + { + return MCUSerialBridgeError.Win_InvalidParam; + } + finally + { + Marshal.FreeHGlobal(nativePorts); + } + } + + /// 璇诲彇杈撳叆锛4 瀛楄妭锛 + /// 杈撳嚭鏁扮粍 + /// 瓒呮椂锛坢s锛 + /// 閿欒鐮 + public MCUSerialBridgeError ReadInput(out byte[] inputs, uint timeout = 100) + { + inputs = new byte[4]; + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + return MCUSerialBridgeCoreAPI.msb_read_input(nativeHandle, inputs, timeout); + } + + /// 鍐欒緭鍑猴紙4 瀛楄妭锛 + /// 鏁版嵁鏁扮粍 + /// 瓒呮椂锛坢s锛 + /// 閿欒鐮 + public MCUSerialBridgeError WriteOutput(byte[] outputs, uint timeout = 100) + { + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + return MCUSerialBridgeCoreAPI.msb_write_output(nativeHandle, outputs, timeout); + } + + /// + /// 璇诲彇 Serial 绔彛鐨勪竴甯ф暟鎹 + /// Serial 涓婃姤鐨勬暟鎹寜甯у叆闃燂紱鏈帴鍙f瘡娆¤皟鐢ㄦ渶澶氳鍙栦竴甯с + /// 娉ㄦ剰锛屽鏋滀笉鍙婃椂璋冪敤璇ユ帴鍙o紝鏁版嵁鍙兘浼氫涪澶便 + /// + /// Serial 绔彛绱㈠紩 + /// 鎺ユ敹鍒扮殑鏁版嵁 + /// + /// 瓒呮椂鏃堕棿锛堟绉掞級 + /// - 0锛氫笉绛夊緟锛屾湁鏁版嵁绔嬪嵆杩斿洖锛屾病鏈夋暟鎹珛鍗宠繑鍥 MSB_Error_NoData + /// - >0锛氳嫢褰撳墠鏃犳暟鎹紝鏈澶氱瓑寰 timeout锛屾湡闂存湁鏂板抚鍒拌揪鍒欑珛鍗宠繑鍥 + /// + /// + /// 濡傛灉宸茬粡娉ㄥ唽鍥炶皟锛屾湰鍑芥暟灏嗗缁堣繑鍥 MSB_Error_NoData + /// + /// + /// 閿欒鐮 MCUSerialBridgeError + /// - OK 鎴愬姛璇诲彇涓甯 + /// - NoData 褰撳墠鏃犲彲璇绘暟鎹紙浠呭湪 timeout == 0 鎴栫瓑寰呰秴鏃讹級 + /// - Win_InvalidParam 鍙傛暟閿欒 + /// + public MCUSerialBridgeError ReadSerial(byte portIndex, out byte[] buffer, uint timeout) + { + buffer = Array.Empty(); + + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + const int MAX_PORT_FRAME = 2048; + byte[] tmp = new byte[MAX_PORT_FRAME]; + + var err = MCUSerialBridgeCoreAPI.msb_read_port( + nativeHandle, + portIndex, + tmp, + (uint)tmp.Length, + out uint outLen, + timeout + ); + + if (err != MCUSerialBridgeError.OK) + return err; + + buffer = new byte[outLen]; + Buffer.BlockCopy(tmp, 0, buffer, 0, (int)outLen); + + return MCUSerialBridgeError.OK; + } + + /// + /// 鍐 Serial 绔彛鏁版嵁銆 + /// 娉ㄦ剰锛氬浜庡崟涓猄erial绔彛锛屼笉鏀寔澶氱嚎绋嬪苟琛屽彂閫侊紝涓嶈鍦ㄤ笂涓鏉℃暟鎹病鏈夊彂閫佸畬鎴愪箣鍓嶈皟鐢ㄨ鍑芥暟锛屽惁鍒欐湁鍙兘瀵艰嚧鏁版嵁閿欒銆 + /// 娉ㄦ剰锛氳秴鏃舵椂闂翠竴瀹氳澶т簬娉㈢壒鐜囧拰鏁版嵁闀垮害缁煎悎寰楀嚭鐨勫抚鏃堕棿 + /// + /// Serial 绔彛绱㈠紩 + /// 寰呭彂閫佹暟鎹 + /// 瓒呮椂鏃堕棿锛堟绉掞級 + /// + /// 閿欒鐮 MCUSerialBridgeError + /// - OK 鎴愬姛鍙戦 + /// - 鍏朵粬閿欒璇锋煡鐪 MCUSerialBridgeError + /// + public MCUSerialBridgeError WriteSerial(byte portIndex, byte[] data, uint timeout) + { + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + if (data == null || data.Length == 0) + return MCUSerialBridgeError.Win_InvalidParam; + + return MCUSerialBridgeCoreAPI.msb_write_port( + nativeHandle, + portIndex, + data, + (uint)data.Length, + timeout + ); + } + + /// + /// 璇诲彇 CAN 绔彛鐨勪竴甯ф暟鎹 + /// CAN 涓婃姤鐨勬暟鎹寜甯у叆闃燂紱鏈帴鍙f瘡娆¤皟鐢ㄦ渶澶氳鍙栦竴甯с + /// 娉ㄦ剰锛屽鏋滀笉鍙婃椂璋冪敤璇ユ帴鍙o紝鏁版嵁鍙兘浼氫涪澶便 + /// + /// CAN 绔彛绱㈠紩 + /// 杈撳嚭 CAN 娑堟伅瀵硅薄 + /// 瓒呮椂鏃堕棿锛堟绉掞級 + /// + /// 濡傛灉宸茬粡娉ㄥ唽鍥炶皟锛屾湰鍑芥暟灏嗗缁堣繑鍥 MSB_Error_NoData + /// + /// + /// 閿欒鐮 MCUSerialBridgeError + /// - OK 鎴愬姛璇诲彇涓甯 + /// - NoData 褰撳墠鏃犲彲璇绘暟鎹紙浠呭湪 timeout == 0 鎴栫瓑寰呰秴鏃讹級 + /// - Win_InvalidParam 鍙傛暟閿欒 + /// - CAN_DataError CAN鏁版嵁閿欒 + /// - Win_HandleNotFound 鍙ユ焺鏃犳晥 + /// + public MCUSerialBridgeError ReadCAN(byte portIndex, out CANMessage message, uint timeout) + { + message = null; + + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + + const int MAX_FRAME = 16; + byte[] tmp = new byte[MAX_FRAME]; + + var err = MCUSerialBridgeCoreAPI.msb_read_port( + nativeHandle, + portIndex, + tmp, + (uint)tmp.Length, + out uint outLen, + timeout + ); + if (err != MCUSerialBridgeError.OK) + return err; + + try + { + message = CANMessage.FromBytes(tmp, outLen); + } + catch + { + return MCUSerialBridgeError.CAN_DataError; + } + return MCUSerialBridgeError.OK; + } + + /// + /// 鍐 CAN 绔彛鏁版嵁銆 + /// 娉ㄦ剰锛欳AN 鏀寔澶氱嚎绋嬪彂閫侊紝鏈澶氬彲鍚屾椂鍙戦 16 涓秷鎭 + /// 浣嗘槸锛屽涓狢AN娑堟伅浼氳繘鍏ユ帓闃熼槦鍒楃瓑寰呭彂閫侊紝濡傛灉娑堟伅澶锛屽彲鑳藉紩璧疯秴鏃躲 + /// + /// CAN 绔彛绱㈠紩 + /// 寰呭彂閫 CAN 娑堟伅瀵硅薄 + /// 瓒呮椂鏃堕棿锛堟绉掞級锛岄粯璁 500ms + /// + /// 閿欒鐮 MCUSerialBridgeError + /// - OK 鎴愬姛鍙戦 + /// - Win_InvalidParam 鍙傛暟閿欒 + /// - CAN_DataError CAN 鏁版嵁閿欒 + /// - Win_HandleNotFound 鍙ユ焺鏃犳晥 + /// + public MCUSerialBridgeError WriteCAN(byte portIndex, CANMessage message, uint timeout) + { + if (nativeHandle == IntPtr.Zero) + return MCUSerialBridgeError.Win_HandleNotFound; + if (message == null) + return MCUSerialBridgeError.Win_InvalidParam; + try + { + byte[] buffer = message.ToBytes(); + return MCUSerialBridgeCoreAPI.msb_write_port( + nativeHandle, + portIndex, + buffer, + (uint)buffer.Length, + timeout + ); + } + catch + { + return MCUSerialBridgeError.CAN_DataError; + } + } + + private readonly Dictionary< + byte, + MCUSerialBridgeCoreAPI.msb_on_port_data_callback_function_t + > _portCallbacks = []; + + /// + /// 娉ㄥ唽鎸囧畾绔彛(Serial)鐨勫洖璋冨嚱鏁 + /// + /// 绔彛绱㈠紩 + /// 鎺ユ敹鏁版嵁鍥炶皟锛宐yte[] 涓烘帴鏀跺埌鐨勫師濮嬫暟鎹 + /// 閿欒鐮 + /// + /// 娉ㄦ剰浜嬮」锛 + /// 1. 鍥炶皟浼氬湪搴曞眰 C 灞傜嚎绋嬩腑鐩存帴璋冪敤锛岃**涓嶈鍦ㄥ洖璋冨唴闃诲**锛屼緥濡傜瓑寰 I/O 鎴 Sleep銆 + /// 2. 鍥炶皟鍐**涓嶈兘璋冪敤 WriteSerial/WriteCAN 绛夊彂閫佸嚱鏁**锛屽惁鍒欏彲鑳藉鑷存閿佹垨涓㈠抚銆 + /// 3. 鍥炶皟鍐呭彧鑳藉仛杞婚噺绾ф搷浣滐紝渚嬪绠鍗曡В鏋愩佺粺璁℃垨鎵撴爣璁般 + /// 4. 鑻ラ渶瑕佸鏉傚鐞嗭紙渚嬪闀挎椂闂磋В鏋愩佽В鐮併佸瓨鍌ㄦ暟鎹簱绛夛級锛岃**灏嗘暟鎹叆闃熷埌鍙︿竴涓嚎绋**锛屽啀鍦ㄥ悗鍙板鐞嗐 + /// 5. 鏁版嵁鍙兘闅忔椂鍒版潵锛岃淇濊瘉鍥炶皟灏藉揩杩斿洖锛岄伩鍏嶅奖鍝嶅悗缁抚鎺ユ敹銆 + /// 6. 涓嶈鎶婂叾浠栫被鍨嬬殑绔彛娉ㄥ唽鍒拌繖涓帴鍙o紝鎺ュ彛涓嶅 portIndex 鍋氱被鍨嬫鏌ャ + /// + public MCUSerialBridgeError RegisterSerialPortCallback( + byte portIndex, + Action callback + ) + { + if (callback == null) + return MCUSerialBridgeError.Win_InvalidParam; + + if (portIndex > MaxPortNumber) + return MCUSerialBridgeError.Config_PortNumOver; + + // 鍖呰 C# 鍥炶皟涓 P/Invoke 濮旀墭 + void del(IntPtr dst_data, uint dst_data_size, IntPtr user_ctx) + { + byte[] data = new byte[dst_data_size]; + Marshal.Copy(dst_data, data, 0, (int)dst_data_size); + callback(data); + } + + // 淇濆瓨寮曠敤锛岄槻姝 GC 鍥炴敹 + _portCallbacks[portIndex] = del; + + // 璋冪敤 C 灞傛敞鍐 + return MCUSerialBridgeCoreAPI.msb_register_port_data_callback( + nativeHandle, + portIndex, + _portCallbacks[portIndex], + IntPtr.Zero + ); + } + + /// + /// 娉ㄥ唽鎸囧畾绔彛(CAN)鐨勫洖璋冨嚱鏁 + /// + /// 绔彛绱㈠紩 + /// 鎺ユ敹鏁版嵁鍥炶皟锛孋ANMessage 涓烘帴鏀跺埌鐨勫師濮嬫暟鎹 + /// 閿欒鐮 + /// + /// 娉ㄦ剰浜嬮」锛 + /// 1. 鍥炶皟浼氬湪搴曞眰 C 灞傜嚎绋嬩腑鐩存帴璋冪敤锛岃**涓嶈鍦ㄥ洖璋冨唴闃诲**锛屼緥濡傜瓑寰 I/O 鎴 Sleep銆 + /// 2. 鍥炶皟鍐**涓嶈兘璋冪敤 WriteSerial/WriteCAN 绛夊彂閫佸嚱鏁**锛屽惁鍒欏彲鑳藉鑷存閿佹垨涓㈠抚銆 + /// 3. 鍥炶皟鍐呭彧鑳藉仛杞婚噺绾ф搷浣滐紝渚嬪绠鍗曡В鏋愩佺粺璁℃垨鎵撴爣璁般 + /// 4. 鑻ラ渶瑕佸鏉傚鐞嗭紙渚嬪闀挎椂闂磋В鏋愩佽В鐮併佸瓨鍌ㄦ暟鎹簱绛夛級锛岃**灏嗘暟鎹叆闃熷埌鍙︿竴涓嚎绋**锛屽啀鍦ㄥ悗鍙板鐞嗐 + /// 5. 鏁版嵁鍙兘闅忔椂鍒版潵锛岃淇濊瘉鍥炶皟灏藉揩杩斿洖锛岄伩鍏嶅奖鍝嶅悗缁抚鎺ユ敹銆 + /// 6. 涓嶈鎶婂叾浠栫被鍨嬬殑绔彛娉ㄥ唽鍒拌繖涓帴鍙o紝鎺ュ彛涓嶅 portIndex 鍋氱被鍨嬫鏌ャ + /// + public MCUSerialBridgeError RegisterCANPortCallback( + byte portIndex, + Action callback + ) + { + if (callback == null) + return MCUSerialBridgeError.Win_InvalidParam; + + if (portIndex > MaxPortNumber) + return MCUSerialBridgeError.Config_PortNumOver; + + // 鍖呰 C# 鍥炶皟涓 P/Invoke 濮旀墭 + void del(IntPtr dst_data, uint dst_data_size, IntPtr user_ctx) + { + try + { + byte[] data = new byte[dst_data_size]; + Marshal.Copy(dst_data, data, 0, (int)dst_data_size); + CANMessage msg = CANMessage.FromBytes(data, dst_data_size); + callback(msg); + } + catch + { + // 瑙f瀽澶辫触鐩存帴蹇界暐锛屼繚璇佸洖璋冧笉浼氭姏寮傚父闃诲 C 灞傜嚎绋 + } + } + + // 淇濆瓨寮曠敤锛岄槻姝 GC 鍥炴敹 + _portCallbacks[portIndex] = del; + + // 璋冪敤 C 灞傛敞鍐 + return MCUSerialBridgeCoreAPI.msb_register_port_data_callback( + nativeHandle, + portIndex, + _portCallbacks[portIndex], + IntPtr.Zero + ); + } + } +} diff --git a/MedullaAdapter/MCUSerialBridgeError.cs b/MedullaAdapter/MCUSerialBridgeError.cs new file mode 100644 index 0000000..00ec446 --- /dev/null +++ b/MedullaAdapter/MCUSerialBridgeError.cs @@ -0,0 +1,97 @@ +using System; + +namespace MCUSerialBridgeCLR +{ + public enum MCUSerialBridgeError : uint + { + OK = 0x00000000, // Success + NoData = 0x00000001, // Port no new data + Win_Unknown = 0x80000001, // Unknown Windows error + Win_InvalidParam = 0x80000002, // Invalid parameter + Win_AllocFail = 0x80000003, // Memory allocation failed + Win_HandleNotFound = 0x80000004, // Handle not found + Win_ResourceBusy = 0x80000005, // Resource busy + Win_BufferFull = 0x80000006, // Buffer is full + Win_UserBufferTooSmall = 0x80000007, // Buffer is too small + Win_CannotOpenPort = 0x80000010, // Cannot open port + Win_CannotGetCommState = 0x80000011, // Cannot get comm state + Win_CannotSetCommState = 0x80000012, // Cannot set comm state + Win_CannotCreateThread = 0x80000013, // Cannot create thread + Proto_Invalid = 0xE0000001, // Protocol invalid + Proto_Checksum = 0xE0000002, // CRC check failed + Proto_Timeout = 0xE0000003, // Protocol timeout + Proto_FrameTooLong = 0xE0000004, // Frame too long + Proto_UnknownCommand = 0xE0000005, // Unknown command + Proto_InvalidPayload = 0xE0000006, // Invalid payload + State_NotRunning = 0xF0000000, // Not running, configure + State_Running = 0xF0000001, // Can not configure, already running + Config_PortNumOver = 0xC0000000, // Port number over + Config_SerialNumOver = 0xC0000001, // Serial port number over + Config_CANNumOver = 0xC0000002, // CAN number over + Config_UnknownPortType = 0xC0000010, // Unknown Port Type + Serial_OpenFail = 0x01000001, // Serial open failed + Serial_NotOpen = 0x01000002, // Serial not open + Serial_ReadFail = 0x01000003, // Serial read failed + Serial_WriteFail = 0x01000004, // Serial write failed + Serial_Busy = 0x01000005, // Serial is busy + CAN_DataError = 0x02000000, // CAN data error + CAN_SendFail = 0x02000001, // CAN send failed + CAN_RecvFail = 0x02000002, // CAN receive failed + CAN_BufferFull = 0x02000003, // CAN buffer full + CAN_NotInit = 0x02000004, // CAN not initialized + Port_WriteBusy = 0x10000001, // Port is busy now + MCU_Unknown = 0x00010001, // MCU unknown error + MCU_IOSizeError = 0x00010002, // IO Should be 4 bytes + MCU_OverTemperature = 0x00010010, // MCU over temperature + } + + public static class MCUSerialBridgeErrorExtensions + { + public static string ToDescription(this MCUSerialBridgeError err) + { + return err switch + { + MCUSerialBridgeError.OK => "OK|Success", + MCUSerialBridgeError.NoData => "NoData|Port no new data", + MCUSerialBridgeError.Win_Unknown => "Win_Unknown|Unknown Windows error", + MCUSerialBridgeError.Win_InvalidParam => "Win_InvalidParam|Invalid parameter", + MCUSerialBridgeError.Win_AllocFail => "Win_AllocFail|Memory allocation failed", + MCUSerialBridgeError.Win_HandleNotFound => "Win_HandleNotFound|Handle not found", + MCUSerialBridgeError.Win_ResourceBusy => "Win_ResourceBusy|Resource busy", + MCUSerialBridgeError.Win_BufferFull => "Win_BufferFull|Buffer is full", + MCUSerialBridgeError.Win_UserBufferTooSmall => "Win_UserBufferTooSmall|Buffer is too small", + MCUSerialBridgeError.Win_CannotOpenPort => "Win_CannotOpenPort|Cannot open port", + MCUSerialBridgeError.Win_CannotGetCommState => "Win_CannotGetCommState|Cannot get comm state", + MCUSerialBridgeError.Win_CannotSetCommState => "Win_CannotSetCommState|Cannot set comm state", + MCUSerialBridgeError.Win_CannotCreateThread => "Win_CannotCreateThread|Cannot create thread", + MCUSerialBridgeError.Proto_Invalid => "Proto_Invalid|Protocol invalid", + MCUSerialBridgeError.Proto_Checksum => "Proto_Checksum|CRC check failed", + MCUSerialBridgeError.Proto_Timeout => "Proto_Timeout|Protocol timeout", + MCUSerialBridgeError.Proto_FrameTooLong => "Proto_FrameTooLong|Frame too long", + MCUSerialBridgeError.Proto_UnknownCommand => "Proto_UnknownCommand|Unknown command", + MCUSerialBridgeError.Proto_InvalidPayload => "Proto_InvalidPayload|Invalid payload", + MCUSerialBridgeError.State_NotRunning => "State_NotRunning|Not running, configure", + MCUSerialBridgeError.State_Running => "State_Running|Can not configure, already running", + MCUSerialBridgeError.Config_PortNumOver => "Config_PortNumOver|Port number over", + MCUSerialBridgeError.Config_SerialNumOver => "Config_SerialNumOver|Serial port number over", + MCUSerialBridgeError.Config_CANNumOver => "Config_CANNumOver|CAN number over", + MCUSerialBridgeError.Config_UnknownPortType => "Config_UnknownPortType|Unknown Port Type", + MCUSerialBridgeError.Serial_OpenFail => "Serial_OpenFail|Serial open failed", + MCUSerialBridgeError.Serial_NotOpen => "Serial_NotOpen|Serial not open", + MCUSerialBridgeError.Serial_ReadFail => "Serial_ReadFail|Serial read failed", + MCUSerialBridgeError.Serial_WriteFail => "Serial_WriteFail|Serial write failed", + MCUSerialBridgeError.Serial_Busy => "Serial_Busy|Serial is busy", + MCUSerialBridgeError.CAN_DataError => "CAN_DataError|CAN data error", + MCUSerialBridgeError.CAN_SendFail => "CAN_SendFail|CAN send failed", + MCUSerialBridgeError.CAN_RecvFail => "CAN_RecvFail|CAN receive failed", + MCUSerialBridgeError.CAN_BufferFull => "CAN_BufferFull|CAN buffer full", + MCUSerialBridgeError.CAN_NotInit => "CAN_NotInit|CAN not initialized", + MCUSerialBridgeError.Port_WriteBusy => "Port_WriteBusy|Port is busy now", + MCUSerialBridgeError.MCU_Unknown => "MCU_Unknown|MCU unknown error", + MCUSerialBridgeError.MCU_IOSizeError => "MCU_IOSizeError|IO Should be 4 bytes", + MCUSerialBridgeError.MCU_OverTemperature => "MCU_OverTemperature|MCU over temperature", + _ => "Unknown Error", + }; + } + } +} diff --git a/MedullaAdapter/MedullaAdapter.csproj b/MedullaAdapter/MedullaAdapter.csproj new file mode 100644 index 0000000..e658198 --- /dev/null +++ b/MedullaAdapter/MedullaAdapter.csproj @@ -0,0 +1,44 @@ +锘 + + + netstandard2.0 + latest + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + ref\CommonUsage.dll + + + ref\CycleGUI.dll + + + ref\MDCSToolBox.dll + + + ref\RefCartActivator.dll + + + ref\RefFundamentalLib.dll + + + ref\RefMedullaCore.dll + + + + + + diff --git a/MedullaAdapter/MotorRoutine.cs b/MedullaAdapter/MotorRoutine.cs new file mode 100644 index 0000000..b31a128 --- /dev/null +++ b/MedullaAdapter/MotorRoutine.cs @@ -0,0 +1,233 @@ +锘縰sing 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 = "姝e父杩愯"; + } + + 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; + } + } + } +} diff --git a/MedullaAdapter/PackageStruct.cs b/MedullaAdapter/PackageStruct.cs new file mode 100644 index 0000000..0626b69 --- /dev/null +++ b/MedullaAdapter/PackageStruct.cs @@ -0,0 +1,168 @@ +锘縰sing System; + +namespace MedullaAdapter +{ + public class BasePack + { + private static ushort CalculateCRC16(byte[] data) + { + const ushort polynomial = 0xA001; // CRC-16-IBM澶氶」寮 + ushort crc = 0xFFFF; // 鍒濆鍊 + + foreach (byte b in data) + { + crc ^= b; // 灏嗘暟鎹瓧鑺備笌CRC瀵勫瓨鍣ㄦ寜浣嶅紓鎴 + + for (int i = 0; i < 8; i++) + { + if ((crc & 0x0001) != 0) + { + crc >>= 1; + crc ^= polynomial; + } + else + { + crc >>= 1; + } + } + } + return crc; + } + + private byte[] _data; + + public void SetData(byte[] data) + { + _data = data; + } + + public byte[] GetPack() + { + var pack = new byte[_data.Length+7]; + pack[0] = 0xBB; + pack[1] = 0xAA; + var length = BitConverter.GetBytes(_data.Length); + pack[2] = length[0]; + pack[3] = length[1]; + for (int i = 0; i < _data.Length; i++) + { + pack[4+i] = _data[i]; + } + + var crcByes = new byte[pack.Length - 5]; + Array.Copy(pack,2,crcByes,0,crcByes.Length); + var crc = BitConverter.GetBytes(CalculateCRC16(crcByes)); + pack[pack.Length-1] = 0xEE; + pack[pack.Length-2] = crc[1]; + pack[pack.Length-3] = crc[0]; + return pack; + } + } + + public class ControlPack : BasePack + { + public ControlPack(byte controlCode) + { + byte[] controlData = new byte[3]{0x01,0x00,controlCode}; + SetData(controlData); + } + } + + public class SetConfigPack : BasePack + { + public SetConfigPack(int can1BaudRate, int can2BaudRate,int modbus0BaudRate, int modbus1BaudRate, int modbus2BaudRate, + int serialBaudRate,int upperSize = 1024,int lowerSize =1024 ) + { + var upper = BitConverter.GetBytes(upperSize); + var lower = BitConverter.GetBytes(lowerSize); + var can = BitConverter.GetBytes(can1BaudRate); + var can2 = BitConverter.GetBytes(can2BaudRate); + var modbus0 = BitConverter.GetBytes(modbus0BaudRate); + var modbus1 = BitConverter.GetBytes(modbus1BaudRate); + var modbus2 = BitConverter.GetBytes(modbus2BaudRate); + var serial = BitConverter.GetBytes(serialBaudRate); + var canBuffer = BitConverter.GetBytes(128); + var mbBuffer = BitConverter.GetBytes(512); + var serialBuffer = BitConverter.GetBytes(1024); + byte[] configData = new byte[] + { + 0x01, 0x10, 0x02, upper[0], upper[1], upper[2], upper[3], lower[0], lower[1], + lower[2], lower[3], 0x06, 0x00, 0x00, can[0], can[1], can[2], can[3], canBuffer[0], canBuffer[1], 0x00, + can2[0], can2[1], can2[2], can2[3], canBuffer[0], canBuffer[1], 0x10, modbus0[0], + modbus0[1], modbus0[2], modbus0[3], mbBuffer[0], mbBuffer[1], 0x10, modbus1[0], + modbus1[1], modbus1[2], modbus1[3], mbBuffer[0], mbBuffer[1], 0x10, modbus2[0], + modbus2[1], modbus2[2], modbus2[3], mbBuffer[0], mbBuffer[1], 0x20, serial[0], serial[1], serial[2], + serial[3], serialBuffer[0], serialBuffer[1] + }; + SetData(configData); + } + } + + public class ReadConfigPack : BasePack + { + public ReadConfigPack() + { + var readConfigData = new byte[] { 0x01, 0x10, 0x00 }; + SetData(readConfigData); + } + } + + public class DownloadCodePack : BasePack + { + public DownloadCodePack(int totalLength, int offset, int currentLength, byte[] codeBytes) + { + var codeData = new byte[12 + codeBytes.Length]; + codeData[0] = 0x01; + codeData[1] = 0x11; + var totalLengthBytes = BitConverter.GetBytes(totalLength); + for (int i = 0; i < 4; i++) + { + codeData[2 + i] = totalLengthBytes[i]; + } + var offsetBytes = BitConverter.GetBytes(offset); + for (int i = 0; i < 4; i++) + { + codeData[6 + i] = offsetBytes[i]; + } + var curLengthBytes = BitConverter.GetBytes(currentLength); + for (int i = 0; i < 2; i++) + { + codeData[10 + i] = curLengthBytes[i]; + } + + for (int i = 0; i < codeBytes.Length; i++) + { + codeData[12+i] = codeBytes[i]; + } + SetData(codeData); + } + + } + + public class HeartBeatPack : BasePack + { + public HeartBeatPack(int state, int error) + { + var errorBytes = BitConverter.GetBytes(error); + var heartBearData = new byte[] { 0x01, 0xF0, (byte)state, errorBytes[0], errorBytes[1] }; + SetData(heartBearData); + } + } + + public class UpperIOPack : BasePack + { + public UpperIOPack(byte[] data,int size) + { + byte[] UpperData = new byte[6 + size]; + UpperData[0] = 0x01; + UpperData[1] = 0x20; + var length = BitConverter.GetBytes(size); + for (int i = 0; i < 4; i++) + { + UpperData[2+i] = length[i]; + } + Array.Copy(data,0,UpperData,6,size); + SetData(UpperData); + } + } +} diff --git a/MedullaAdapter/Remote.cs b/MedullaAdapter/Remote.cs new file mode 100644 index 0000000..ee7bacd --- /dev/null +++ b/MedullaAdapter/Remote.cs @@ -0,0 +1,47 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Text; +using CartActivator; +using MDCSToolBox.Medulla.Chassis.MultiWheel; + +namespace MedullaAdapter +{ + public class Remote:MultiWheelRemote + { + [AsControlItem(name = "澶规姳閫熷害", LayoutRow = 0, LayoutCol = 4)] + public Throttle ArmSpeed; + + [AsControlItem(name = "澶规姳鎵撳紑", LayoutRow = 1, LayoutCol = 0)] + public Button Open; + + [AsControlItem(name = "澶规姳鍏抽棴", LayoutRow = 1, LayoutCol = 2)] + public Button Close; + + public override void MultiVehicleModeChassisLogic() + { + // cart.MultiVehicleRemoteManualEnabled = true; + // cart.MultiVehicleManualEnabled = true; + // cart.MultiVehicleManualVx = SpeedPad.y * SpeedThreshold.val; + // cart.MultiVehicleManualVth = -(float)Math.Pow(Math.Abs(SpeedPad.x), cart.ManualThetaPow) * Math.Sign(SpeedPad.x); + } + + public override void CustomOperation() + { + if (Open.pressed) + { + cart.SpeedLeftArm = -ArmSpeed.val * cart.ManualArmSpeedFac; + cart.SpeedRightArm = -ArmSpeed.val * cart.ManualArmSpeedFac; + } + else if (Close.pressed) + { + cart.SpeedLeftArm = ArmSpeed.val * cart.ManualArmSpeedFac; + cart.SpeedRightArm = ArmSpeed.val * cart.ManualArmSpeedFac; + } + else + { + cart.SpeedLeftArm = 0; + cart.SpeedRightArm = 0; + } + } + } +} diff --git a/MedullaAdapter/RunOnMCU.cs b/MedullaAdapter/RunOnMCU.cs new file mode 100644 index 0000000..5421c53 --- /dev/null +++ b/MedullaAdapter/RunOnMCU.cs @@ -0,0 +1,47 @@ +锘縰sing System; +using System.Collections.Generic; + +namespace CartActivator +{ + public class LogicRunOnMCUAttribute:Attribute + { + public string mcu_url = "default"; + public int scanInterval = 50; + } + + public class RunOnMCU + { + // if return null: not data, or return payload data excluding CRC + public static byte[] ReadEvent(int port, int event_id) => default; + + public static void WriteEvent(byte[] payload, int port, int event_id) { } + + // if return null: not data. + public static byte[] ReadStream(int port) => default; + + public static void WriteStream(byte[] payload, int port){} + + // always have the same sized data. + public static byte[] ReadSnapshot() => default; + + public static void WriteSnapshot(byte[] payload) + { + } + + public static T BytesToStruct() where T: struct => default; + + public static byte[] StructToBytes(T what) where T : struct => default; + + public static int GetMillisFromStart() => default; + + public static T Iterate(IEnumerable ie) => default; + } + + public class MCUManager + { + public static void Use() + { + + } + } +} diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/CommonUsage.dll b/MedullaAdapter/bin/Debug/netstandard2.0/CommonUsage.dll new file mode 100644 index 0000000..65e32b6 Binary files /dev/null and b/MedullaAdapter/bin/Debug/netstandard2.0/CommonUsage.dll differ diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/CycleGUI.dll b/MedullaAdapter/bin/Debug/netstandard2.0/CycleGUI.dll new file mode 100644 index 0000000..92e6ca7 Binary files /dev/null and b/MedullaAdapter/bin/Debug/netstandard2.0/CycleGUI.dll differ diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/MDCSToolBox.dll b/MedullaAdapter/bin/Debug/netstandard2.0/MDCSToolBox.dll new file mode 100644 index 0000000..d9cc740 Binary files /dev/null and b/MedullaAdapter/bin/Debug/netstandard2.0/MDCSToolBox.dll differ diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.deps.json b/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.deps.json new file mode 100644 index 0000000..ddb6d99 --- /dev/null +++ b/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.deps.json @@ -0,0 +1,352 @@ +{ + "runtimeTarget": { + "name": ".NETStandard,Version=v2.0/", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETStandard,Version=v2.0": {}, + ".NETStandard,Version=v2.0/": { + "MedullaAdapter/1.0.0": { + "dependencies": { + "Fody": "6.9.3", + "NETStandard.Library": "2.0.3", + "Newtonsoft.Json": "13.0.4", + "System.IO.Ports": "6.0.0", + "CommonUsage": "1.0.0.0", + "CycleGUI": "1.0.0.0", + "MDCSToolBox": "1.0.0.0", + "RefCartActivator": "1.0.0.0", + "RefFundamentalLib": "0.0.0.0", + "RefMedullaCore": "1.0.0.0" + }, + "runtime": { + "MedullaAdapter.dll": {} + } + }, + "Fody/6.9.3": {}, + "Microsoft.NETCore.Platforms/1.1.0": {}, + "Microsoft.Win32.Registry/5.0.0": { + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Win32.Registry.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "NETStandard.Library/2.0.3": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + } + }, + "Newtonsoft.Json/13.0.4": { + "runtime": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "assemblyVersion": "13.0.0.0", + "fileVersion": "13.0.4.30916" + } + } + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/6.0.0": {}, + "runtime.linux-arm64.runtime.native.System.IO.Ports/6.0.0": {}, + "runtime.linux-x64.runtime.native.System.IO.Ports/6.0.0": {}, + "runtime.native.System.IO.Ports/6.0.0": { + "dependencies": { + "runtime.linux-arm.runtime.native.System.IO.Ports": "6.0.0", + "runtime.linux-arm64.runtime.native.System.IO.Ports": "6.0.0", + "runtime.linux-x64.runtime.native.System.IO.Ports": "6.0.0", + "runtime.osx-arm64.runtime.native.System.IO.Ports": "6.0.0", + "runtime.osx-x64.runtime.native.System.IO.Ports": "6.0.0" + } + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/6.0.0": {}, + "runtime.osx-x64.runtime.native.System.IO.Ports/6.0.0": {}, + "System.Buffers/4.5.1": { + "runtime": { + "lib/netstandard2.0/System.Buffers.dll": { + "assemblyVersion": "4.0.3.0", + "fileVersion": "4.6.28619.1" + } + } + }, + "System.IO.Ports/6.0.0": { + "dependencies": { + "Microsoft.Win32.Registry": "5.0.0", + "System.Memory": "4.5.4", + "runtime.native.System.IO.Ports": "6.0.0" + }, + "runtime": { + "lib/netstandard2.0/System.IO.Ports.dll": { + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + } + }, + "System.Memory/4.5.4": { + "dependencies": { + "System.Buffers": "4.5.1", + "System.Numerics.Vectors": "4.4.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3" + }, + "runtime": { + "lib/netstandard2.0/System.Memory.dll": { + "assemblyVersion": "4.0.1.1", + "fileVersion": "4.6.28619.1" + } + } + }, + "System.Numerics.Vectors/4.4.0": { + "runtime": { + "lib/netstandard2.0/System.Numerics.Vectors.dll": { + "assemblyVersion": "4.1.3.0", + "fileVersion": "4.6.25519.3" + } + } + }, + "System.Runtime.CompilerServices.Unsafe/4.5.3": { + "runtime": { + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll": { + "assemblyVersion": "4.0.4.1", + "fileVersion": "4.6.28619.1" + } + } + }, + "System.Security.AccessControl/5.0.0": { + "dependencies": { + "System.Security.Principal.Windows": "5.0.0" + }, + "runtime": { + "lib/netstandard2.0/System.Security.AccessControl.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "System.Security.Principal.Windows/5.0.0": { + "runtime": { + "lib/netstandard2.0/System.Security.Principal.Windows.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "CommonUsage/1.0.0.0": { + "runtime": { + "CommonUsage.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "CycleGUI/1.0.0.0": { + "runtime": { + "CycleGUI.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "MDCSToolBox/1.0.0.0": { + "runtime": { + "MDCSToolBox.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "RefCartActivator/1.0.0.0": { + "runtime": { + "RefCartActivator.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "RefFundamentalLib/0.0.0.0": { + "runtime": { + "RefFundamentalLib.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "RefMedullaCore/1.0.0.0": { + "runtime": { + "RefMedullaCore.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "0.0.0.0" + } + } + } + } + }, + "libraries": { + "MedullaAdapter/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Fody/6.9.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1CUGgFdyECDKgi5HaUBhdv6k+VG9Iy4OCforGfHyar3xQXAJypZkzymgKtWj/4SPd6nSG0Qi7NH71qHrDSZLaA==", + "path": "fody/6.9.3", + "hashPath": "fody.6.9.3.nupkg.sha512" + }, + "Microsoft.NETCore.Platforms/1.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", + "path": "microsoft.netcore.platforms/1.1.0", + "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512" + }, + "Microsoft.Win32.Registry/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "path": "microsoft.win32.registry/5.0.0", + "hashPath": "microsoft.win32.registry.5.0.0.nupkg.sha512" + }, + "NETStandard.Library/2.0.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", + "path": "netstandard.library/2.0.3", + "hashPath": "netstandard.library.2.0.3.nupkg.sha512" + }, + "Newtonsoft.Json/13.0.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-pdgNNMai3zv51W5aq268sujXUyx7SNdE2bj1wZcWjAQrKMFZV260lbqYop1d2GM67JI1huLRwxo9ZqnfF/lC6A==", + "path": "newtonsoft.json/13.0.4", + "hashPath": "newtonsoft.json.13.0.4.nupkg.sha512" + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-75q52H7CSpgIoIDwXb9o833EvBZIXJ0mdPhz1E6jSisEXUBlSCPalC29cj3EXsjpuDwr0dj1LRXZepIQH/oL4Q==", + "path": "runtime.linux-arm.runtime.native.system.io.ports/6.0.0", + "hashPath": "runtime.linux-arm.runtime.native.system.io.ports.6.0.0.nupkg.sha512" + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-xn2bMThmXr3CsvOYmS8ex2Yz1xo+kcnhVg2iVhS9PlmqjZPAkrEo/I40wjrBZH/tU4kvH0s1AE8opAvQ3KIS8g==", + "path": "runtime.linux-arm64.runtime.native.system.io.ports/6.0.0", + "hashPath": "runtime.linux-arm64.runtime.native.system.io.ports.6.0.0.nupkg.sha512" + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-16nbNXwv0sC+gLGIuecri0skjuh6R1maIJggsaNP7MQBcbVcEfWFUOkEnsnvoLEjy0XerfibuRptfQ8AmdIcWA==", + "path": "runtime.linux-x64.runtime.native.system.io.ports/6.0.0", + "hashPath": "runtime.linux-x64.runtime.native.system.io.ports.6.0.0.nupkg.sha512" + }, + "runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KaaXlpOcuZjMdmyF5wzzx3b+PRKIzt6A5Ax9dKenPDQbVJAFpev+casD0BIig1pBcbs3zx7CqWemzUJKAeHdSQ==", + "path": "runtime.native.system.io.ports/6.0.0", + "hashPath": "runtime.native.system.io.ports.6.0.0.nupkg.sha512" + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-fXG12NodG1QrCdoaeSQ1gVnk/koi4WYY4jZtarMkZeQMyReBm1nZlSRoPnUjLr2ZR36TiMjpcGnQfxymieUe7w==", + "path": "runtime.osx-arm64.runtime.native.system.io.ports/6.0.0", + "hashPath": "runtime.osx-arm64.runtime.native.system.io.ports.6.0.0.nupkg.sha512" + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/As+zPY49+dSUXkh+fTUbyPhqrdGN//evLxo4Vue88pfh1BHZgF7q4kMblTkxYvwR6Vi03zSYxysSFktO8/SDQ==", + "path": "runtime.osx-x64.runtime.native.system.io.ports/6.0.0", + "hashPath": "runtime.osx-x64.runtime.native.system.io.ports.6.0.0.nupkg.sha512" + }, + "System.Buffers/4.5.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==", + "path": "system.buffers/4.5.1", + "hashPath": "system.buffers.4.5.1.nupkg.sha512" + }, + "System.IO.Ports/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-dRyGI7fUESar5ZLIpiBOaaNLW7YyOBGftjj5Of+xcduC/Rjl7RjhEnWDvvNBmHuF3d0tdXoqdVI/yrVA8f00XA==", + "path": "system.io.ports/6.0.0", + "hashPath": "system.io.ports.6.0.0.nupkg.sha512" + }, + "System.Memory/4.5.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "path": "system.memory/4.5.4", + "hashPath": "system.memory.4.5.4.nupkg.sha512" + }, + "System.Numerics.Vectors/4.4.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==", + "path": "system.numerics.vectors/4.4.0", + "hashPath": "system.numerics.vectors.4.4.0.nupkg.sha512" + }, + "System.Runtime.CompilerServices.Unsafe/4.5.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw==", + "path": "system.runtime.compilerservices.unsafe/4.5.3", + "hashPath": "system.runtime.compilerservices.unsafe.4.5.3.nupkg.sha512" + }, + "System.Security.AccessControl/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", + "path": "system.security.accesscontrol/5.0.0", + "hashPath": "system.security.accesscontrol.5.0.0.nupkg.sha512" + }, + "System.Security.Principal.Windows/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==", + "path": "system.security.principal.windows/5.0.0", + "hashPath": "system.security.principal.windows.5.0.0.nupkg.sha512" + }, + "CommonUsage/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "CycleGUI/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "MDCSToolBox/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "RefCartActivator/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "RefFundamentalLib/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "RefMedullaCore/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + } + } +} \ No newline at end of file diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.dll b/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.dll new file mode 100644 index 0000000..2a6d338 Binary files /dev/null and b/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.dll differ diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.pdb b/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.pdb new file mode 100644 index 0000000..c129906 Binary files /dev/null and b/MedullaAdapter/bin/Debug/netstandard2.0/MedullaAdapter.pdb differ diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/RefCartActivator.dll b/MedullaAdapter/bin/Debug/netstandard2.0/RefCartActivator.dll new file mode 100644 index 0000000..a43584d Binary files /dev/null and b/MedullaAdapter/bin/Debug/netstandard2.0/RefCartActivator.dll differ diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/RefFundamentalLib.dll b/MedullaAdapter/bin/Debug/netstandard2.0/RefFundamentalLib.dll new file mode 100644 index 0000000..cdebe2e Binary files /dev/null and b/MedullaAdapter/bin/Debug/netstandard2.0/RefFundamentalLib.dll differ diff --git a/MedullaAdapter/bin/Debug/netstandard2.0/RefMedullaCore.dll b/MedullaAdapter/bin/Debug/netstandard2.0/RefMedullaCore.dll new file mode 100644 index 0000000..7ede8c7 Binary files /dev/null and b/MedullaAdapter/bin/Debug/netstandard2.0/RefMedullaCore.dll differ diff --git a/MedullaAdapter/build/Clumsy/ClumsyLite.deps.json b/MedullaAdapter/build/Clumsy/ClumsyLite.deps.json new file mode 100644 index 0000000..72a39f6 --- /dev/null +++ b/MedullaAdapter/build/Clumsy/ClumsyLite.deps.json @@ -0,0 +1,1944 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v8.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v8.0": { + "ClumsyLite/1.0.0": { + "dependencies": { + "ClumsyCore": "1.0.0", + "ClumsyDance": "1.0.0", + "Costura.Fody": "5.7.0", + "Fody": "6.6.4", + "CycleGUI": "1.0.0.0", + "LessokajiWeaverUtilities": "1.0.0.0", + "RefFundamentalLib": "0.0.0.0", + "RefLessokajiProtect": "1.2.9365.10902" + }, + "runtime": { + "ClumsyLite.dll": {} + } + }, + "Costura.Fody/5.7.0": { + "dependencies": { + "Fody": "6.6.4", + "NETStandard.Library": "1.6.1" + } + }, + "Fody/6.6.4": {}, + "MethodBoundaryAspect.Fody/2.0.148": { + "dependencies": { + "Fody": "6.6.4" + }, + "runtime": { + "lib/netstandard2.0/MethodBoundaryAspect.dll": { + "assemblyVersion": "2.0.148.0", + "fileVersion": "2.0.148.0" + } + } + }, + "Microsoft.Bcl.AsyncInterfaces/1.1.0": { + "runtime": { + "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "Microsoft.CodeAnalysis.Analyzers/3.3.3": {}, + "Microsoft.CodeAnalysis.Common/4.3.1": { + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "6.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.CodeAnalysis.dll": { + "assemblyVersion": "4.3.0.0", + "fileVersion": "4.300.122.47918" + } + }, + "resources": { + "lib/netcoreapp3.1/cs/Microsoft.CodeAnalysis.resources.dll": { + "locale": "cs" + }, + "lib/netcoreapp3.1/de/Microsoft.CodeAnalysis.resources.dll": { + "locale": "de" + }, + "lib/netcoreapp3.1/es/Microsoft.CodeAnalysis.resources.dll": { + "locale": "es" + }, + "lib/netcoreapp3.1/fr/Microsoft.CodeAnalysis.resources.dll": { + "locale": "fr" + }, + "lib/netcoreapp3.1/it/Microsoft.CodeAnalysis.resources.dll": { + "locale": "it" + }, + "lib/netcoreapp3.1/ja/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ja" + }, + "lib/netcoreapp3.1/ko/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ko" + }, + "lib/netcoreapp3.1/pl/Microsoft.CodeAnalysis.resources.dll": { + "locale": "pl" + }, + "lib/netcoreapp3.1/pt-BR/Microsoft.CodeAnalysis.resources.dll": { + "locale": "pt-BR" + }, + "lib/netcoreapp3.1/ru/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ru" + }, + "lib/netcoreapp3.1/tr/Microsoft.CodeAnalysis.resources.dll": { + "locale": "tr" + }, + "lib/netcoreapp3.1/zh-Hans/Microsoft.CodeAnalysis.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netcoreapp3.1/zh-Hant/Microsoft.CodeAnalysis.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.CSharp/4.3.1": { + "dependencies": { + "Microsoft.CodeAnalysis.Common": "4.3.1" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.CodeAnalysis.CSharp.dll": { + "assemblyVersion": "4.3.0.0", + "fileVersion": "4.300.122.47918" + } + }, + "resources": { + "lib/netcoreapp3.1/cs/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "cs" + }, + "lib/netcoreapp3.1/de/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "de" + }, + "lib/netcoreapp3.1/es/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "es" + }, + "lib/netcoreapp3.1/fr/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "fr" + }, + "lib/netcoreapp3.1/it/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "it" + }, + "lib/netcoreapp3.1/ja/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ja" + }, + "lib/netcoreapp3.1/ko/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ko" + }, + "lib/netcoreapp3.1/pl/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "pl" + }, + "lib/netcoreapp3.1/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "pt-BR" + }, + "lib/netcoreapp3.1/ru/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ru" + }, + "lib/netcoreapp3.1/tr/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "tr" + }, + "lib/netcoreapp3.1/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netcoreapp3.1/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.CSharp.Scripting/4.3.1": { + "dependencies": { + "Microsoft.CSharp": "4.7.0", + "Microsoft.CodeAnalysis.CSharp": "4.3.1", + "Microsoft.CodeAnalysis.Common": "4.3.1", + "Microsoft.CodeAnalysis.Scripting.Common": "4.3.1" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.CodeAnalysis.CSharp.Scripting.dll": { + "assemblyVersion": "4.3.0.0", + "fileVersion": "4.300.122.47918" + } + }, + "resources": { + "lib/netcoreapp3.1/cs/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "cs" + }, + "lib/netcoreapp3.1/de/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "de" + }, + "lib/netcoreapp3.1/es/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "es" + }, + "lib/netcoreapp3.1/fr/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "fr" + }, + "lib/netcoreapp3.1/it/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "it" + }, + "lib/netcoreapp3.1/ja/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "ja" + }, + "lib/netcoreapp3.1/ko/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "ko" + }, + "lib/netcoreapp3.1/pl/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "pl" + }, + "lib/netcoreapp3.1/pt-BR/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "pt-BR" + }, + "lib/netcoreapp3.1/ru/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "ru" + }, + "lib/netcoreapp3.1/tr/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "tr" + }, + "lib/netcoreapp3.1/zh-Hans/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netcoreapp3.1/zh-Hant/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.Scripting.Common/4.3.1": { + "dependencies": { + "Microsoft.CodeAnalysis.Common": "4.3.1" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.CodeAnalysis.Scripting.dll": { + "assemblyVersion": "4.3.0.0", + "fileVersion": "4.300.122.47918" + } + }, + "resources": { + "lib/netcoreapp3.1/cs/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "cs" + }, + "lib/netcoreapp3.1/de/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "de" + }, + "lib/netcoreapp3.1/es/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "es" + }, + "lib/netcoreapp3.1/fr/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "fr" + }, + "lib/netcoreapp3.1/it/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "it" + }, + "lib/netcoreapp3.1/ja/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "ja" + }, + "lib/netcoreapp3.1/ko/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "ko" + }, + "lib/netcoreapp3.1/pl/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "pl" + }, + "lib/netcoreapp3.1/pt-BR/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "pt-BR" + }, + "lib/netcoreapp3.1/ru/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "ru" + }, + "lib/netcoreapp3.1/tr/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "tr" + }, + "lib/netcoreapp3.1/zh-Hans/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netcoreapp3.1/zh-Hant/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CSharp/4.7.0": {}, + "Microsoft.Diagnostics.NETCore.Client/0.2.251802": { + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.0", + "Microsoft.Extensions.Logging": "2.1.1" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.Diagnostics.NETCore.Client.dll": { + "assemblyVersion": "0.2.5.1802", + "fileVersion": "0.2.5.1802" + } + } + }, + "Microsoft.Diagnostics.Runtime/2.2.343001": { + "dependencies": { + "Microsoft.Diagnostics.NETCore.Client": "0.2.251802", + "System.Collections.Immutable": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "runtime": { + "lib/net6.0/Microsoft.Diagnostics.Runtime.dll": { + "assemblyVersion": "2.2.6.43001", + "fileVersion": "2.2.6.43001" + } + } + }, + "Microsoft.Extensions.Configuration/2.1.1": { + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Configuration.Abstractions/2.1.1": { + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Configuration.Binder/2.1.1": { + "dependencies": { + "Microsoft.Extensions.Configuration": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/2.1.1": { + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Logging/2.1.1": { + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "2.1.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Logging.Abstractions/2.1.1": { + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Options/2.1.1": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Primitives": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Options.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Primitives/2.1.1": { + "dependencies": { + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.NETCore.Platforms/1.1.0": {}, + "Microsoft.NETCore.Targets/1.1.0": {}, + "Microsoft.Win32.Primitives/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.SystemEvents/6.0.0": { + "runtime": { + "lib/net6.0/Microsoft.Win32.SystemEvents.dll": { + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + }, + "runtimeTargets": { + "runtimes/win/lib/net6.0/Microsoft.Win32.SystemEvents.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + } + }, + "NETStandard.Library/1.6.1": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json/13.0.1": { + "runtime": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "assemblyVersion": "13.0.0.0", + "fileVersion": "13.0.1.25517" + } + } + }, + "OpenCvSharp4/4.5.3.20210817": { + "dependencies": { + "System.Drawing.Common": "6.0.0", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "runtime": { + "lib/netcoreapp2.1/OpenCvSharp.Extensions.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + }, + "lib/netcoreapp2.1/OpenCvSharp.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.native.System/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple/4.3.0": { + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple/4.3.0": {}, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "System.AppContext/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers/4.3.0": { + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable/6.0.0": { + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Console/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Diagnostics.Tools/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common/6.0.0": { + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + }, + "runtime": { + "lib/net6.0/System.Drawing.Common.dll": { + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/net6.0/System.Drawing.Common.dll": { + "rid": "unix", + "assetType": "runtime", + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + }, + "runtimes/win/lib/net6.0/System.Drawing.Common.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + } + }, + "System.Globalization/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile/4.3.0": { + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Linq/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Memory/4.5.4": {}, + "System.Net.Http/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Numerics.Vectors/4.5.0": {}, + "System.ObjectModel/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reflection/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit/4.3.0": { + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata/5.0.0": {}, + "System.Reflection.Primitives/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": {}, + "System.Runtime.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics/4.3.0": { + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives/4.3.0": { + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages/6.0.0": { + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Encoding.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Tasks/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions/4.5.4": {}, + "System.Threading.Timer/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "System.Xml.XDocument/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "ClumsyCore/1.0.0": { + "dependencies": { + "MethodBoundaryAspect.Fody": "2.0.148", + "Microsoft.CodeAnalysis.CSharp": "4.3.1", + "Microsoft.CodeAnalysis.CSharp.Scripting": "4.3.1", + "Microsoft.Diagnostics.Runtime": "2.2.343001", + "Newtonsoft.Json": "13.0.1", + "OpenCvSharp4": "4.5.3.20210817", + "System.Drawing.Common": "6.0.0", + "System.Numerics.Vectors": "4.5.0", + "System.Reflection.Metadata": "5.0.0" + }, + "runtime": { + "ClumsyCore.dll": { + "assemblyVersion": "1.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "ClumsyDance/1.0.0": { + "dependencies": { + "ClumsyCore": "1.0.0", + "MethodBoundaryAspect.Fody": "2.0.148" + }, + "runtime": { + "ClumsyDance.dll": { + "assemblyVersion": "1.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "CycleGUI/1.0.0.0": { + "runtime": { + "CycleGUI.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "LessokajiWeaverUtilities/1.0.0.0": { + "runtime": { + "LessokajiWeaverUtilities.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "RefFundamentalLib/0.0.0.0": { + "runtime": { + "RefFundamentalLib.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "RefLessokajiProtect/1.2.9365.10902": { + "runtime": { + "RefLessokajiProtect.dll": { + "assemblyVersion": "1.2.9365.10902", + "fileVersion": "0.0.0.0" + } + } + } + } + }, + "libraries": { + "ClumsyLite/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Costura.Fody/5.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-MmL28WOOnJEBWORXj6bfSxfWaZW8gWSXEJTdrjB9AQi4COX6RXr2xdGL9HsxpWwn6f5Io0NmNuwFJe94w1YmQA==", + "path": "costura.fody/5.7.0", + "hashPath": "costura.fody.5.7.0.nupkg.sha512" + }, + "Fody/6.6.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vLZS+oa+ndUHYPlx/8n9bBTT3dHkCF0riml4paKq4D663+cZd47x1uagQo32D/gKFZ/sfmV1oqKaLmH0elxq4A==", + "path": "fody/6.6.4", + "hashPath": "fody.6.6.4.nupkg.sha512" + }, + "MethodBoundaryAspect.Fody/2.0.148": { + "type": "package", + "serviceable": true, + "sha512": "sha512-QFZOs5SRehBbRYmuPvdsgr3PhqkoERO9YT0jxW4JzmWIZmk2nlMz4uokz+HiWtK9n+2e0eAZ0pX7om+yMbserw==", + "path": "methodboundaryaspect.fody/2.0.148", + "hashPath": "methodboundaryaspect.fody.2.0.148.nupkg.sha512" + }, + "Microsoft.Bcl.AsyncInterfaces/1.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==", + "path": "microsoft.bcl.asyncinterfaces/1.1.0", + "hashPath": "microsoft.bcl.asyncinterfaces.1.1.0.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.Analyzers/3.3.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==", + "path": "microsoft.codeanalysis.analyzers/3.3.3", + "hashPath": "microsoft.codeanalysis.analyzers.3.3.3.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.Common/4.3.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-wexpJffSEEwptwe6UTMxRDZCCtz+XubI4Qewl4JECnNhcQrtb0anhSUEV9Nz7WkoNfWkx1fptR8xh1egoxYrqw==", + "path": "microsoft.codeanalysis.common/4.3.1", + "hashPath": "microsoft.codeanalysis.common.4.3.1.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.CSharp/4.3.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5C9VHvahL98tumlyaT/loB5rW+K/6q0UU7uLyT1Dv15YjZraRkqML9u2t2e8GaO7XqEOtBVqK/SlxXOPqwzxog==", + "path": "microsoft.codeanalysis.csharp/4.3.1", + "hashPath": "microsoft.codeanalysis.csharp.4.3.1.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.CSharp.Scripting/4.3.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ts1O6eSjqy0B6FfiVUAE24h6Mq5Z9r3hmmXQlu+6Egt/zf5v1p0OkTJCd6PHmb1DcD5GKz/vR/+C8xuvoXUPkg==", + "path": "microsoft.codeanalysis.csharp.scripting/4.3.1", + "hashPath": "microsoft.codeanalysis.csharp.scripting.4.3.1.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.Scripting.Common/4.3.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-WRX2GecORKhED3VoyYsbjFFBvV3D41BF3N4SDpbdM02Hm3rPdPqsxIQaF6xxHZ9iX0+m/YgT9mV6TiHjQL3qOw==", + "path": "microsoft.codeanalysis.scripting.common/4.3.1", + "hashPath": "microsoft.codeanalysis.scripting.common.4.3.1.nupkg.sha512" + }, + "Microsoft.CSharp/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==", + "path": "microsoft.csharp/4.7.0", + "hashPath": "microsoft.csharp.4.7.0.nupkg.sha512" + }, + "Microsoft.Diagnostics.NETCore.Client/0.2.251802": { + "type": "package", + "serviceable": true, + "sha512": "sha512-bqnYl6AdSeboeN4v25hSukK6Odm6/54E3Y2B8rBvgqvAW0mF8fo7XNRVE2DMOG7Rk0fiuA079QIH28+V+W1Zdg==", + "path": "microsoft.diagnostics.netcore.client/0.2.251802", + "hashPath": "microsoft.diagnostics.netcore.client.0.2.251802.nupkg.sha512" + }, + "Microsoft.Diagnostics.Runtime/2.2.343001": { + "type": "package", + "serviceable": true, + "sha512": "sha512-nVwXLEJiXbnnNkQPcWy64DMWNBvMg9XKWpfBBNMVs1gbEJ9HUVTcAA862mOjgyKryAtvGVKkeQ/9cW6pK8YAiA==", + "path": "microsoft.diagnostics.runtime/2.2.343001", + "hashPath": "microsoft.diagnostics.runtime.2.2.343001.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-LjVKO6P2y52c5ZhTLX/w8zc5H4Y3J/LJsgqTBj49TtFq/hAtVNue/WA0F6/7GMY90xhD7K0MDZ4qpOeWXbLvzg==", + "path": "microsoft.extensions.configuration/2.1.1", + "hashPath": "microsoft.extensions.configuration.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.Abstractions/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-VfuZJNa0WUshZ/+8BFZAhwFKiKuu/qOUCFntfdLpHj7vcRnsGHqd3G2Hse78DM+pgozczGM63lGPRLmy+uhUOA==", + "path": "microsoft.extensions.configuration.abstractions/2.1.1", + "hashPath": "microsoft.extensions.configuration.abstractions.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.Binder/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-fcLCTS03poWE4v9tSNBr3pWn0QwGgAn1vzqHXlXgvqZeOc7LvQNzaWcKRQZTdEc3+YhQKwMsOtm3VKSA2aWQ8w==", + "path": "microsoft.extensions.configuration.binder/2.1.1", + "hashPath": "microsoft.extensions.configuration.binder.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA==", + "path": "microsoft.extensions.dependencyinjection.abstractions/2.1.1", + "hashPath": "microsoft.extensions.dependencyinjection.abstractions.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Logging/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==", + "path": "microsoft.extensions.logging/2.1.1", + "hashPath": "microsoft.extensions.logging.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.Abstractions/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA==", + "path": "microsoft.extensions.logging.abstractions/2.1.1", + "hashPath": "microsoft.extensions.logging.abstractions.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Options/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==", + "path": "microsoft.extensions.options/2.1.1", + "hashPath": "microsoft.extensions.options.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Primitives/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg==", + "path": "microsoft.extensions.primitives/2.1.1", + "hashPath": "microsoft.extensions.primitives.2.1.1.nupkg.sha512" + }, + "Microsoft.NETCore.Platforms/1.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", + "path": "microsoft.netcore.platforms/1.1.0", + "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512" + }, + "Microsoft.NETCore.Targets/1.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==", + "path": "microsoft.netcore.targets/1.1.0", + "hashPath": "microsoft.netcore.targets.1.1.0.nupkg.sha512" + }, + "Microsoft.Win32.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "path": "microsoft.win32.primitives/4.3.0", + "hashPath": "microsoft.win32.primitives.4.3.0.nupkg.sha512" + }, + "Microsoft.Win32.SystemEvents/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==", + "path": "microsoft.win32.systemevents/6.0.0", + "hashPath": "microsoft.win32.systemevents.6.0.0.nupkg.sha512" + }, + "NETStandard.Library/1.6.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "path": "netstandard.library/1.6.1", + "hashPath": "netstandard.library.1.6.1.nupkg.sha512" + }, + "Newtonsoft.Json/13.0.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==", + "path": "newtonsoft.json/13.0.1", + "hashPath": "newtonsoft.json.13.0.1.nupkg.sha512" + }, + "OpenCvSharp4/4.5.3.20210817": { + "type": "package", + "serviceable": true, + "sha512": "sha512-LeTZ9634aGRTWhJxz75Xciq05aS2HxC25ECEQXNd0T7FROCI8GDDp5xAQ4XPmW5mwLWjRqd9h05XmN8bqju06A==", + "path": "opencvsharp4/4.5.3.20210817", + "hashPath": "opencvsharp4.4.5.3.20210817.nupkg.sha512" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==", + "path": "runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==", + "path": "runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==", + "path": "runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.native.System/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "path": "runtime.native.system/4.3.0", + "hashPath": "runtime.native.system.4.3.0.nupkg.sha512" + }, + "runtime.native.System.IO.Compression/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "path": "runtime.native.system.io.compression/4.3.0", + "hashPath": "runtime.native.system.io.compression.4.3.0.nupkg.sha512" + }, + "runtime.native.System.Net.Http/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "path": "runtime.native.system.net.http/4.3.0", + "hashPath": "runtime.native.system.net.http.4.3.0.nupkg.sha512" + }, + "runtime.native.System.Security.Cryptography.Apple/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "path": "runtime.native.system.security.cryptography.apple/4.3.0", + "hashPath": "runtime.native.system.security.cryptography.apple.4.3.0.nupkg.sha512" + }, + "runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "path": "runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==", + "path": "runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==", + "path": "runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==", + "path": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple/4.3.0", + "hashPath": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.4.3.0.nupkg.sha512" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==", + "path": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==", + "path": "runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==", + "path": "runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==", + "path": "runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==", + "path": "runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "System.AppContext/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "path": "system.appcontext/4.3.0", + "hashPath": "system.appcontext.4.3.0.nupkg.sha512" + }, + "System.Buffers/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", + "path": "system.buffers/4.3.0", + "hashPath": "system.buffers.4.3.0.nupkg.sha512" + }, + "System.Collections/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "path": "system.collections/4.3.0", + "hashPath": "system.collections.4.3.0.nupkg.sha512" + }, + "System.Collections.Concurrent/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "path": "system.collections.concurrent/4.3.0", + "hashPath": "system.collections.concurrent.4.3.0.nupkg.sha512" + }, + "System.Collections.Immutable/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "path": "system.collections.immutable/6.0.0", + "hashPath": "system.collections.immutable.6.0.0.nupkg.sha512" + }, + "System.Console/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "path": "system.console/4.3.0", + "hashPath": "system.console.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.Debug/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "path": "system.diagnostics.debug/4.3.0", + "hashPath": "system.diagnostics.debug.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.DiagnosticSource/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", + "path": "system.diagnostics.diagnosticsource/4.3.0", + "hashPath": "system.diagnostics.diagnosticsource.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.Tools/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "path": "system.diagnostics.tools/4.3.0", + "hashPath": "system.diagnostics.tools.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.Tracing/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "path": "system.diagnostics.tracing/4.3.0", + "hashPath": "system.diagnostics.tracing.4.3.0.nupkg.sha512" + }, + "System.Drawing.Common/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "path": "system.drawing.common/6.0.0", + "hashPath": "system.drawing.common.6.0.0.nupkg.sha512" + }, + "System.Globalization/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "path": "system.globalization/4.3.0", + "hashPath": "system.globalization.4.3.0.nupkg.sha512" + }, + "System.Globalization.Calendars/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "path": "system.globalization.calendars/4.3.0", + "hashPath": "system.globalization.calendars.4.3.0.nupkg.sha512" + }, + "System.Globalization.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "path": "system.globalization.extensions/4.3.0", + "hashPath": "system.globalization.extensions.4.3.0.nupkg.sha512" + }, + "System.IO/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "path": "system.io/4.3.0", + "hashPath": "system.io.4.3.0.nupkg.sha512" + }, + "System.IO.Compression/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "path": "system.io.compression/4.3.0", + "hashPath": "system.io.compression.4.3.0.nupkg.sha512" + }, + "System.IO.Compression.ZipFile/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "path": "system.io.compression.zipfile/4.3.0", + "hashPath": "system.io.compression.zipfile.4.3.0.nupkg.sha512" + }, + "System.IO.FileSystem/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "path": "system.io.filesystem/4.3.0", + "hashPath": "system.io.filesystem.4.3.0.nupkg.sha512" + }, + "System.IO.FileSystem.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "path": "system.io.filesystem.primitives/4.3.0", + "hashPath": "system.io.filesystem.primitives.4.3.0.nupkg.sha512" + }, + "System.Linq/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "path": "system.linq/4.3.0", + "hashPath": "system.linq.4.3.0.nupkg.sha512" + }, + "System.Linq.Expressions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "path": "system.linq.expressions/4.3.0", + "hashPath": "system.linq.expressions.4.3.0.nupkg.sha512" + }, + "System.Memory/4.5.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "path": "system.memory/4.5.4", + "hashPath": "system.memory.4.5.4.nupkg.sha512" + }, + "System.Net.Http/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "path": "system.net.http/4.3.0", + "hashPath": "system.net.http.4.3.0.nupkg.sha512" + }, + "System.Net.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "path": "system.net.primitives/4.3.0", + "hashPath": "system.net.primitives.4.3.0.nupkg.sha512" + }, + "System.Net.Sockets/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "path": "system.net.sockets/4.3.0", + "hashPath": "system.net.sockets.4.3.0.nupkg.sha512" + }, + "System.Numerics.Vectors/4.5.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==", + "path": "system.numerics.vectors/4.5.0", + "hashPath": "system.numerics.vectors.4.5.0.nupkg.sha512" + }, + "System.ObjectModel/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "path": "system.objectmodel/4.3.0", + "hashPath": "system.objectmodel.4.3.0.nupkg.sha512" + }, + "System.Reflection/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "path": "system.reflection/4.3.0", + "hashPath": "system.reflection.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "path": "system.reflection.emit/4.3.0", + "hashPath": "system.reflection.emit.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit.ILGeneration/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "path": "system.reflection.emit.ilgeneration/4.3.0", + "hashPath": "system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit.Lightweight/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "path": "system.reflection.emit.lightweight/4.3.0", + "hashPath": "system.reflection.emit.lightweight.4.3.0.nupkg.sha512" + }, + "System.Reflection.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "path": "system.reflection.extensions/4.3.0", + "hashPath": "system.reflection.extensions.4.3.0.nupkg.sha512" + }, + "System.Reflection.Metadata/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==", + "path": "system.reflection.metadata/5.0.0", + "hashPath": "system.reflection.metadata.5.0.0.nupkg.sha512" + }, + "System.Reflection.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "path": "system.reflection.primitives/4.3.0", + "hashPath": "system.reflection.primitives.4.3.0.nupkg.sha512" + }, + "System.Reflection.TypeExtensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "path": "system.reflection.typeextensions/4.3.0", + "hashPath": "system.reflection.typeextensions.4.3.0.nupkg.sha512" + }, + "System.Resources.ResourceManager/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "path": "system.resources.resourcemanager/4.3.0", + "hashPath": "system.resources.resourcemanager.4.3.0.nupkg.sha512" + }, + "System.Runtime/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "path": "system.runtime/4.3.0", + "hashPath": "system.runtime.4.3.0.nupkg.sha512" + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==", + "path": "system.runtime.compilerservices.unsafe/6.0.0", + "hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512" + }, + "System.Runtime.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "path": "system.runtime.extensions/4.3.0", + "hashPath": "system.runtime.extensions.4.3.0.nupkg.sha512" + }, + "System.Runtime.Handles/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "path": "system.runtime.handles/4.3.0", + "hashPath": "system.runtime.handles.4.3.0.nupkg.sha512" + }, + "System.Runtime.InteropServices/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "path": "system.runtime.interopservices/4.3.0", + "hashPath": "system.runtime.interopservices.4.3.0.nupkg.sha512" + }, + "System.Runtime.InteropServices.RuntimeInformation/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "path": "system.runtime.interopservices.runtimeinformation/4.3.0", + "hashPath": "system.runtime.interopservices.runtimeinformation.4.3.0.nupkg.sha512" + }, + "System.Runtime.Numerics/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "path": "system.runtime.numerics/4.3.0", + "hashPath": "system.runtime.numerics.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Algorithms/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "path": "system.security.cryptography.algorithms/4.3.0", + "hashPath": "system.security.cryptography.algorithms.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Cng/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "path": "system.security.cryptography.cng/4.3.0", + "hashPath": "system.security.cryptography.cng.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Csp/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "path": "system.security.cryptography.csp/4.3.0", + "hashPath": "system.security.cryptography.csp.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Encoding/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "path": "system.security.cryptography.encoding/4.3.0", + "hashPath": "system.security.cryptography.encoding.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "path": "system.security.cryptography.openssl/4.3.0", + "hashPath": "system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "path": "system.security.cryptography.primitives/4.3.0", + "hashPath": "system.security.cryptography.primitives.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.X509Certificates/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "path": "system.security.cryptography.x509certificates/4.3.0", + "hashPath": "system.security.cryptography.x509certificates.4.3.0.nupkg.sha512" + }, + "System.Text.Encoding/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "path": "system.text.encoding/4.3.0", + "hashPath": "system.text.encoding.4.3.0.nupkg.sha512" + }, + "System.Text.Encoding.CodePages/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "path": "system.text.encoding.codepages/6.0.0", + "hashPath": "system.text.encoding.codepages.6.0.0.nupkg.sha512" + }, + "System.Text.Encoding.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "path": "system.text.encoding.extensions/4.3.0", + "hashPath": "system.text.encoding.extensions.4.3.0.nupkg.sha512" + }, + "System.Text.RegularExpressions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "path": "system.text.regularexpressions/4.3.0", + "hashPath": "system.text.regularexpressions.4.3.0.nupkg.sha512" + }, + "System.Threading/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "path": "system.threading/4.3.0", + "hashPath": "system.threading.4.3.0.nupkg.sha512" + }, + "System.Threading.Tasks/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "path": "system.threading.tasks/4.3.0", + "hashPath": "system.threading.tasks.4.3.0.nupkg.sha512" + }, + "System.Threading.Tasks.Extensions/4.5.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", + "path": "system.threading.tasks.extensions/4.5.4", + "hashPath": "system.threading.tasks.extensions.4.5.4.nupkg.sha512" + }, + "System.Threading.Timer/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "path": "system.threading.timer/4.3.0", + "hashPath": "system.threading.timer.4.3.0.nupkg.sha512" + }, + "System.Xml.ReaderWriter/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "path": "system.xml.readerwriter/4.3.0", + "hashPath": "system.xml.readerwriter.4.3.0.nupkg.sha512" + }, + "System.Xml.XDocument/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "path": "system.xml.xdocument/4.3.0", + "hashPath": "system.xml.xdocument.4.3.0.nupkg.sha512" + }, + "ClumsyCore/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "ClumsyDance/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "CycleGUI/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "LessokajiWeaverUtilities/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "RefFundamentalLib/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "RefLessokajiProtect/1.2.9365.10902": { + "type": "reference", + "serviceable": false, + "sha512": "" + } + } +} \ No newline at end of file diff --git a/MedullaAdapter/build/Clumsy/ClumsyLite.exe b/MedullaAdapter/build/Clumsy/ClumsyLite.exe new file mode 100644 index 0000000..950f16e Binary files /dev/null and b/MedullaAdapter/build/Clumsy/ClumsyLite.exe differ diff --git a/MedullaAdapter/build/Clumsy/ClumsyLite.runtimeconfig.json b/MedullaAdapter/build/Clumsy/ClumsyLite.runtimeconfig.json new file mode 100644 index 0000000..d784515 --- /dev/null +++ b/MedullaAdapter/build/Clumsy/ClumsyLite.runtimeconfig.json @@ -0,0 +1,13 @@ +{ + "runtimeOptions": { + "tfm": "net8.0", + "framework": { + "name": "Microsoft.NETCore.App", + "version": "8.0.0" + }, + "configProperties": { + "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false + } + } +} \ No newline at end of file diff --git a/MedullaAdapter/build/Clumsy/CommonUsage.dll b/MedullaAdapter/build/Clumsy/CommonUsage.dll new file mode 100644 index 0000000..effb81e Binary files /dev/null and b/MedullaAdapter/build/Clumsy/CommonUsage.dll differ diff --git a/MedullaAdapter/build/Clumsy/MDCSToolBox.dll b/MedullaAdapter/build/Clumsy/MDCSToolBox.dll new file mode 100644 index 0000000..091a9bb Binary files /dev/null and b/MedullaAdapter/build/Clumsy/MDCSToolBox.dll differ diff --git a/MedullaAdapter/build/Clumsy/RefClumsyCore.dll b/MedullaAdapter/build/Clumsy/RefClumsyCore.dll new file mode 100644 index 0000000..ed36470 Binary files /dev/null and b/MedullaAdapter/build/Clumsy/RefClumsyCore.dll differ diff --git a/MedullaAdapter/build/Clumsy/RefClumsyDance.dll b/MedullaAdapter/build/Clumsy/RefClumsyDance.dll new file mode 100644 index 0000000..7e191a1 Binary files /dev/null and b/MedullaAdapter/build/Clumsy/RefClumsyDance.dll differ diff --git a/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.deps.json b/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.deps.json new file mode 100644 index 0000000..72a39f6 --- /dev/null +++ b/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.deps.json @@ -0,0 +1,1944 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v8.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v8.0": { + "ClumsyLite/1.0.0": { + "dependencies": { + "ClumsyCore": "1.0.0", + "ClumsyDance": "1.0.0", + "Costura.Fody": "5.7.0", + "Fody": "6.6.4", + "CycleGUI": "1.0.0.0", + "LessokajiWeaverUtilities": "1.0.0.0", + "RefFundamentalLib": "0.0.0.0", + "RefLessokajiProtect": "1.2.9365.10902" + }, + "runtime": { + "ClumsyLite.dll": {} + } + }, + "Costura.Fody/5.7.0": { + "dependencies": { + "Fody": "6.6.4", + "NETStandard.Library": "1.6.1" + } + }, + "Fody/6.6.4": {}, + "MethodBoundaryAspect.Fody/2.0.148": { + "dependencies": { + "Fody": "6.6.4" + }, + "runtime": { + "lib/netstandard2.0/MethodBoundaryAspect.dll": { + "assemblyVersion": "2.0.148.0", + "fileVersion": "2.0.148.0" + } + } + }, + "Microsoft.Bcl.AsyncInterfaces/1.1.0": { + "runtime": { + "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "Microsoft.CodeAnalysis.Analyzers/3.3.3": {}, + "Microsoft.CodeAnalysis.Common/4.3.1": { + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "6.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.CodeAnalysis.dll": { + "assemblyVersion": "4.3.0.0", + "fileVersion": "4.300.122.47918" + } + }, + "resources": { + "lib/netcoreapp3.1/cs/Microsoft.CodeAnalysis.resources.dll": { + "locale": "cs" + }, + "lib/netcoreapp3.1/de/Microsoft.CodeAnalysis.resources.dll": { + "locale": "de" + }, + "lib/netcoreapp3.1/es/Microsoft.CodeAnalysis.resources.dll": { + "locale": "es" + }, + "lib/netcoreapp3.1/fr/Microsoft.CodeAnalysis.resources.dll": { + "locale": "fr" + }, + "lib/netcoreapp3.1/it/Microsoft.CodeAnalysis.resources.dll": { + "locale": "it" + }, + "lib/netcoreapp3.1/ja/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ja" + }, + "lib/netcoreapp3.1/ko/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ko" + }, + "lib/netcoreapp3.1/pl/Microsoft.CodeAnalysis.resources.dll": { + "locale": "pl" + }, + "lib/netcoreapp3.1/pt-BR/Microsoft.CodeAnalysis.resources.dll": { + "locale": "pt-BR" + }, + "lib/netcoreapp3.1/ru/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ru" + }, + "lib/netcoreapp3.1/tr/Microsoft.CodeAnalysis.resources.dll": { + "locale": "tr" + }, + "lib/netcoreapp3.1/zh-Hans/Microsoft.CodeAnalysis.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netcoreapp3.1/zh-Hant/Microsoft.CodeAnalysis.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.CSharp/4.3.1": { + "dependencies": { + "Microsoft.CodeAnalysis.Common": "4.3.1" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.CodeAnalysis.CSharp.dll": { + "assemblyVersion": "4.3.0.0", + "fileVersion": "4.300.122.47918" + } + }, + "resources": { + "lib/netcoreapp3.1/cs/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "cs" + }, + "lib/netcoreapp3.1/de/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "de" + }, + "lib/netcoreapp3.1/es/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "es" + }, + "lib/netcoreapp3.1/fr/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "fr" + }, + "lib/netcoreapp3.1/it/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "it" + }, + "lib/netcoreapp3.1/ja/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ja" + }, + "lib/netcoreapp3.1/ko/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ko" + }, + "lib/netcoreapp3.1/pl/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "pl" + }, + "lib/netcoreapp3.1/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "pt-BR" + }, + "lib/netcoreapp3.1/ru/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ru" + }, + "lib/netcoreapp3.1/tr/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "tr" + }, + "lib/netcoreapp3.1/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netcoreapp3.1/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.CSharp.Scripting/4.3.1": { + "dependencies": { + "Microsoft.CSharp": "4.7.0", + "Microsoft.CodeAnalysis.CSharp": "4.3.1", + "Microsoft.CodeAnalysis.Common": "4.3.1", + "Microsoft.CodeAnalysis.Scripting.Common": "4.3.1" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.CodeAnalysis.CSharp.Scripting.dll": { + "assemblyVersion": "4.3.0.0", + "fileVersion": "4.300.122.47918" + } + }, + "resources": { + "lib/netcoreapp3.1/cs/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "cs" + }, + "lib/netcoreapp3.1/de/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "de" + }, + "lib/netcoreapp3.1/es/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "es" + }, + "lib/netcoreapp3.1/fr/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "fr" + }, + "lib/netcoreapp3.1/it/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "it" + }, + "lib/netcoreapp3.1/ja/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "ja" + }, + "lib/netcoreapp3.1/ko/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "ko" + }, + "lib/netcoreapp3.1/pl/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "pl" + }, + "lib/netcoreapp3.1/pt-BR/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "pt-BR" + }, + "lib/netcoreapp3.1/ru/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "ru" + }, + "lib/netcoreapp3.1/tr/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "tr" + }, + "lib/netcoreapp3.1/zh-Hans/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netcoreapp3.1/zh-Hant/Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.Scripting.Common/4.3.1": { + "dependencies": { + "Microsoft.CodeAnalysis.Common": "4.3.1" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.CodeAnalysis.Scripting.dll": { + "assemblyVersion": "4.3.0.0", + "fileVersion": "4.300.122.47918" + } + }, + "resources": { + "lib/netcoreapp3.1/cs/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "cs" + }, + "lib/netcoreapp3.1/de/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "de" + }, + "lib/netcoreapp3.1/es/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "es" + }, + "lib/netcoreapp3.1/fr/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "fr" + }, + "lib/netcoreapp3.1/it/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "it" + }, + "lib/netcoreapp3.1/ja/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "ja" + }, + "lib/netcoreapp3.1/ko/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "ko" + }, + "lib/netcoreapp3.1/pl/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "pl" + }, + "lib/netcoreapp3.1/pt-BR/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "pt-BR" + }, + "lib/netcoreapp3.1/ru/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "ru" + }, + "lib/netcoreapp3.1/tr/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "tr" + }, + "lib/netcoreapp3.1/zh-Hans/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netcoreapp3.1/zh-Hant/Microsoft.CodeAnalysis.Scripting.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CSharp/4.7.0": {}, + "Microsoft.Diagnostics.NETCore.Client/0.2.251802": { + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.0", + "Microsoft.Extensions.Logging": "2.1.1" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.Diagnostics.NETCore.Client.dll": { + "assemblyVersion": "0.2.5.1802", + "fileVersion": "0.2.5.1802" + } + } + }, + "Microsoft.Diagnostics.Runtime/2.2.343001": { + "dependencies": { + "Microsoft.Diagnostics.NETCore.Client": "0.2.251802", + "System.Collections.Immutable": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "runtime": { + "lib/net6.0/Microsoft.Diagnostics.Runtime.dll": { + "assemblyVersion": "2.2.6.43001", + "fileVersion": "2.2.6.43001" + } + } + }, + "Microsoft.Extensions.Configuration/2.1.1": { + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Configuration.Abstractions/2.1.1": { + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Configuration.Binder/2.1.1": { + "dependencies": { + "Microsoft.Extensions.Configuration": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/2.1.1": { + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Logging/2.1.1": { + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "2.1.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Logging.Abstractions/2.1.1": { + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Options/2.1.1": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Primitives": "2.1.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Options.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.Extensions.Primitives/2.1.1": { + "dependencies": { + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll": { + "assemblyVersion": "2.1.1.0", + "fileVersion": "2.1.1.18157" + } + } + }, + "Microsoft.NETCore.Platforms/1.1.0": {}, + "Microsoft.NETCore.Targets/1.1.0": {}, + "Microsoft.Win32.Primitives/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.SystemEvents/6.0.0": { + "runtime": { + "lib/net6.0/Microsoft.Win32.SystemEvents.dll": { + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + }, + "runtimeTargets": { + "runtimes/win/lib/net6.0/Microsoft.Win32.SystemEvents.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + } + }, + "NETStandard.Library/1.6.1": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json/13.0.1": { + "runtime": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "assemblyVersion": "13.0.0.0", + "fileVersion": "13.0.1.25517" + } + } + }, + "OpenCvSharp4/4.5.3.20210817": { + "dependencies": { + "System.Drawing.Common": "6.0.0", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "runtime": { + "lib/netcoreapp2.1/OpenCvSharp.Extensions.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + }, + "lib/netcoreapp2.1/OpenCvSharp.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.native.System/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple/4.3.0": { + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple/4.3.0": {}, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, + "System.AppContext/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers/4.3.0": { + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable/6.0.0": { + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Console/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Diagnostics.Tools/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common/6.0.0": { + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + }, + "runtime": { + "lib/net6.0/System.Drawing.Common.dll": { + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/net6.0/System.Drawing.Common.dll": { + "rid": "unix", + "assetType": "runtime", + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + }, + "runtimes/win/lib/net6.0/System.Drawing.Common.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "6.0.0.0", + "fileVersion": "6.0.21.52210" + } + } + }, + "System.Globalization/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile/4.3.0": { + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Linq/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Memory/4.5.4": {}, + "System.Net.Http/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Numerics.Vectors/4.5.0": {}, + "System.ObjectModel/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reflection/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit/4.3.0": { + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata/5.0.0": {}, + "System.Reflection.Primitives/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": {}, + "System.Runtime.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics/4.3.0": { + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives/4.3.0": { + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages/6.0.0": { + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Encoding.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Tasks/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions/4.5.4": {}, + "System.Threading.Timer/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "System.Xml.XDocument/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "ClumsyCore/1.0.0": { + "dependencies": { + "MethodBoundaryAspect.Fody": "2.0.148", + "Microsoft.CodeAnalysis.CSharp": "4.3.1", + "Microsoft.CodeAnalysis.CSharp.Scripting": "4.3.1", + "Microsoft.Diagnostics.Runtime": "2.2.343001", + "Newtonsoft.Json": "13.0.1", + "OpenCvSharp4": "4.5.3.20210817", + "System.Drawing.Common": "6.0.0", + "System.Numerics.Vectors": "4.5.0", + "System.Reflection.Metadata": "5.0.0" + }, + "runtime": { + "ClumsyCore.dll": { + "assemblyVersion": "1.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "ClumsyDance/1.0.0": { + "dependencies": { + "ClumsyCore": "1.0.0", + "MethodBoundaryAspect.Fody": "2.0.148" + }, + "runtime": { + "ClumsyDance.dll": { + "assemblyVersion": "1.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "CycleGUI/1.0.0.0": { + "runtime": { + "CycleGUI.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "LessokajiWeaverUtilities/1.0.0.0": { + "runtime": { + "LessokajiWeaverUtilities.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "RefFundamentalLib/0.0.0.0": { + "runtime": { + "RefFundamentalLib.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "RefLessokajiProtect/1.2.9365.10902": { + "runtime": { + "RefLessokajiProtect.dll": { + "assemblyVersion": "1.2.9365.10902", + "fileVersion": "0.0.0.0" + } + } + } + } + }, + "libraries": { + "ClumsyLite/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Costura.Fody/5.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-MmL28WOOnJEBWORXj6bfSxfWaZW8gWSXEJTdrjB9AQi4COX6RXr2xdGL9HsxpWwn6f5Io0NmNuwFJe94w1YmQA==", + "path": "costura.fody/5.7.0", + "hashPath": "costura.fody.5.7.0.nupkg.sha512" + }, + "Fody/6.6.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vLZS+oa+ndUHYPlx/8n9bBTT3dHkCF0riml4paKq4D663+cZd47x1uagQo32D/gKFZ/sfmV1oqKaLmH0elxq4A==", + "path": "fody/6.6.4", + "hashPath": "fody.6.6.4.nupkg.sha512" + }, + "MethodBoundaryAspect.Fody/2.0.148": { + "type": "package", + "serviceable": true, + "sha512": "sha512-QFZOs5SRehBbRYmuPvdsgr3PhqkoERO9YT0jxW4JzmWIZmk2nlMz4uokz+HiWtK9n+2e0eAZ0pX7om+yMbserw==", + "path": "methodboundaryaspect.fody/2.0.148", + "hashPath": "methodboundaryaspect.fody.2.0.148.nupkg.sha512" + }, + "Microsoft.Bcl.AsyncInterfaces/1.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==", + "path": "microsoft.bcl.asyncinterfaces/1.1.0", + "hashPath": "microsoft.bcl.asyncinterfaces.1.1.0.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.Analyzers/3.3.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==", + "path": "microsoft.codeanalysis.analyzers/3.3.3", + "hashPath": "microsoft.codeanalysis.analyzers.3.3.3.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.Common/4.3.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-wexpJffSEEwptwe6UTMxRDZCCtz+XubI4Qewl4JECnNhcQrtb0anhSUEV9Nz7WkoNfWkx1fptR8xh1egoxYrqw==", + "path": "microsoft.codeanalysis.common/4.3.1", + "hashPath": "microsoft.codeanalysis.common.4.3.1.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.CSharp/4.3.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5C9VHvahL98tumlyaT/loB5rW+K/6q0UU7uLyT1Dv15YjZraRkqML9u2t2e8GaO7XqEOtBVqK/SlxXOPqwzxog==", + "path": "microsoft.codeanalysis.csharp/4.3.1", + "hashPath": "microsoft.codeanalysis.csharp.4.3.1.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.CSharp.Scripting/4.3.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ts1O6eSjqy0B6FfiVUAE24h6Mq5Z9r3hmmXQlu+6Egt/zf5v1p0OkTJCd6PHmb1DcD5GKz/vR/+C8xuvoXUPkg==", + "path": "microsoft.codeanalysis.csharp.scripting/4.3.1", + "hashPath": "microsoft.codeanalysis.csharp.scripting.4.3.1.nupkg.sha512" + }, + "Microsoft.CodeAnalysis.Scripting.Common/4.3.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-WRX2GecORKhED3VoyYsbjFFBvV3D41BF3N4SDpbdM02Hm3rPdPqsxIQaF6xxHZ9iX0+m/YgT9mV6TiHjQL3qOw==", + "path": "microsoft.codeanalysis.scripting.common/4.3.1", + "hashPath": "microsoft.codeanalysis.scripting.common.4.3.1.nupkg.sha512" + }, + "Microsoft.CSharp/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==", + "path": "microsoft.csharp/4.7.0", + "hashPath": "microsoft.csharp.4.7.0.nupkg.sha512" + }, + "Microsoft.Diagnostics.NETCore.Client/0.2.251802": { + "type": "package", + "serviceable": true, + "sha512": "sha512-bqnYl6AdSeboeN4v25hSukK6Odm6/54E3Y2B8rBvgqvAW0mF8fo7XNRVE2DMOG7Rk0fiuA079QIH28+V+W1Zdg==", + "path": "microsoft.diagnostics.netcore.client/0.2.251802", + "hashPath": "microsoft.diagnostics.netcore.client.0.2.251802.nupkg.sha512" + }, + "Microsoft.Diagnostics.Runtime/2.2.343001": { + "type": "package", + "serviceable": true, + "sha512": "sha512-nVwXLEJiXbnnNkQPcWy64DMWNBvMg9XKWpfBBNMVs1gbEJ9HUVTcAA862mOjgyKryAtvGVKkeQ/9cW6pK8YAiA==", + "path": "microsoft.diagnostics.runtime/2.2.343001", + "hashPath": "microsoft.diagnostics.runtime.2.2.343001.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-LjVKO6P2y52c5ZhTLX/w8zc5H4Y3J/LJsgqTBj49TtFq/hAtVNue/WA0F6/7GMY90xhD7K0MDZ4qpOeWXbLvzg==", + "path": "microsoft.extensions.configuration/2.1.1", + "hashPath": "microsoft.extensions.configuration.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.Abstractions/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-VfuZJNa0WUshZ/+8BFZAhwFKiKuu/qOUCFntfdLpHj7vcRnsGHqd3G2Hse78DM+pgozczGM63lGPRLmy+uhUOA==", + "path": "microsoft.extensions.configuration.abstractions/2.1.1", + "hashPath": "microsoft.extensions.configuration.abstractions.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.Binder/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-fcLCTS03poWE4v9tSNBr3pWn0QwGgAn1vzqHXlXgvqZeOc7LvQNzaWcKRQZTdEc3+YhQKwMsOtm3VKSA2aWQ8w==", + "path": "microsoft.extensions.configuration.binder/2.1.1", + "hashPath": "microsoft.extensions.configuration.binder.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA==", + "path": "microsoft.extensions.dependencyinjection.abstractions/2.1.1", + "hashPath": "microsoft.extensions.dependencyinjection.abstractions.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Logging/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==", + "path": "microsoft.extensions.logging/2.1.1", + "hashPath": "microsoft.extensions.logging.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.Abstractions/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA==", + "path": "microsoft.extensions.logging.abstractions/2.1.1", + "hashPath": "microsoft.extensions.logging.abstractions.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Options/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==", + "path": "microsoft.extensions.options/2.1.1", + "hashPath": "microsoft.extensions.options.2.1.1.nupkg.sha512" + }, + "Microsoft.Extensions.Primitives/2.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg==", + "path": "microsoft.extensions.primitives/2.1.1", + "hashPath": "microsoft.extensions.primitives.2.1.1.nupkg.sha512" + }, + "Microsoft.NETCore.Platforms/1.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", + "path": "microsoft.netcore.platforms/1.1.0", + "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512" + }, + "Microsoft.NETCore.Targets/1.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==", + "path": "microsoft.netcore.targets/1.1.0", + "hashPath": "microsoft.netcore.targets.1.1.0.nupkg.sha512" + }, + "Microsoft.Win32.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "path": "microsoft.win32.primitives/4.3.0", + "hashPath": "microsoft.win32.primitives.4.3.0.nupkg.sha512" + }, + "Microsoft.Win32.SystemEvents/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==", + "path": "microsoft.win32.systemevents/6.0.0", + "hashPath": "microsoft.win32.systemevents.6.0.0.nupkg.sha512" + }, + "NETStandard.Library/1.6.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "path": "netstandard.library/1.6.1", + "hashPath": "netstandard.library.1.6.1.nupkg.sha512" + }, + "Newtonsoft.Json/13.0.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==", + "path": "newtonsoft.json/13.0.1", + "hashPath": "newtonsoft.json.13.0.1.nupkg.sha512" + }, + "OpenCvSharp4/4.5.3.20210817": { + "type": "package", + "serviceable": true, + "sha512": "sha512-LeTZ9634aGRTWhJxz75Xciq05aS2HxC25ECEQXNd0T7FROCI8GDDp5xAQ4XPmW5mwLWjRqd9h05XmN8bqju06A==", + "path": "opencvsharp4/4.5.3.20210817", + "hashPath": "opencvsharp4.4.5.3.20210817.nupkg.sha512" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==", + "path": "runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==", + "path": "runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==", + "path": "runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.native.System/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "path": "runtime.native.system/4.3.0", + "hashPath": "runtime.native.system.4.3.0.nupkg.sha512" + }, + "runtime.native.System.IO.Compression/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "path": "runtime.native.system.io.compression/4.3.0", + "hashPath": "runtime.native.system.io.compression.4.3.0.nupkg.sha512" + }, + "runtime.native.System.Net.Http/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "path": "runtime.native.system.net.http/4.3.0", + "hashPath": "runtime.native.system.net.http.4.3.0.nupkg.sha512" + }, + "runtime.native.System.Security.Cryptography.Apple/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "path": "runtime.native.system.security.cryptography.apple/4.3.0", + "hashPath": "runtime.native.system.security.cryptography.apple.4.3.0.nupkg.sha512" + }, + "runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "path": "runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==", + "path": "runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==", + "path": "runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==", + "path": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple/4.3.0", + "hashPath": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.4.3.0.nupkg.sha512" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==", + "path": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==", + "path": "runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==", + "path": "runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==", + "path": "runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==", + "path": "runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl/4.3.0", + "hashPath": "runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "System.AppContext/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "path": "system.appcontext/4.3.0", + "hashPath": "system.appcontext.4.3.0.nupkg.sha512" + }, + "System.Buffers/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", + "path": "system.buffers/4.3.0", + "hashPath": "system.buffers.4.3.0.nupkg.sha512" + }, + "System.Collections/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "path": "system.collections/4.3.0", + "hashPath": "system.collections.4.3.0.nupkg.sha512" + }, + "System.Collections.Concurrent/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "path": "system.collections.concurrent/4.3.0", + "hashPath": "system.collections.concurrent.4.3.0.nupkg.sha512" + }, + "System.Collections.Immutable/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "path": "system.collections.immutable/6.0.0", + "hashPath": "system.collections.immutable.6.0.0.nupkg.sha512" + }, + "System.Console/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "path": "system.console/4.3.0", + "hashPath": "system.console.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.Debug/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "path": "system.diagnostics.debug/4.3.0", + "hashPath": "system.diagnostics.debug.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.DiagnosticSource/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", + "path": "system.diagnostics.diagnosticsource/4.3.0", + "hashPath": "system.diagnostics.diagnosticsource.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.Tools/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "path": "system.diagnostics.tools/4.3.0", + "hashPath": "system.diagnostics.tools.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.Tracing/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "path": "system.diagnostics.tracing/4.3.0", + "hashPath": "system.diagnostics.tracing.4.3.0.nupkg.sha512" + }, + "System.Drawing.Common/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "path": "system.drawing.common/6.0.0", + "hashPath": "system.drawing.common.6.0.0.nupkg.sha512" + }, + "System.Globalization/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "path": "system.globalization/4.3.0", + "hashPath": "system.globalization.4.3.0.nupkg.sha512" + }, + "System.Globalization.Calendars/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "path": "system.globalization.calendars/4.3.0", + "hashPath": "system.globalization.calendars.4.3.0.nupkg.sha512" + }, + "System.Globalization.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "path": "system.globalization.extensions/4.3.0", + "hashPath": "system.globalization.extensions.4.3.0.nupkg.sha512" + }, + "System.IO/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "path": "system.io/4.3.0", + "hashPath": "system.io.4.3.0.nupkg.sha512" + }, + "System.IO.Compression/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "path": "system.io.compression/4.3.0", + "hashPath": "system.io.compression.4.3.0.nupkg.sha512" + }, + "System.IO.Compression.ZipFile/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "path": "system.io.compression.zipfile/4.3.0", + "hashPath": "system.io.compression.zipfile.4.3.0.nupkg.sha512" + }, + "System.IO.FileSystem/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "path": "system.io.filesystem/4.3.0", + "hashPath": "system.io.filesystem.4.3.0.nupkg.sha512" + }, + "System.IO.FileSystem.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "path": "system.io.filesystem.primitives/4.3.0", + "hashPath": "system.io.filesystem.primitives.4.3.0.nupkg.sha512" + }, + "System.Linq/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "path": "system.linq/4.3.0", + "hashPath": "system.linq.4.3.0.nupkg.sha512" + }, + "System.Linq.Expressions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "path": "system.linq.expressions/4.3.0", + "hashPath": "system.linq.expressions.4.3.0.nupkg.sha512" + }, + "System.Memory/4.5.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "path": "system.memory/4.5.4", + "hashPath": "system.memory.4.5.4.nupkg.sha512" + }, + "System.Net.Http/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "path": "system.net.http/4.3.0", + "hashPath": "system.net.http.4.3.0.nupkg.sha512" + }, + "System.Net.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "path": "system.net.primitives/4.3.0", + "hashPath": "system.net.primitives.4.3.0.nupkg.sha512" + }, + "System.Net.Sockets/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "path": "system.net.sockets/4.3.0", + "hashPath": "system.net.sockets.4.3.0.nupkg.sha512" + }, + "System.Numerics.Vectors/4.5.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==", + "path": "system.numerics.vectors/4.5.0", + "hashPath": "system.numerics.vectors.4.5.0.nupkg.sha512" + }, + "System.ObjectModel/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "path": "system.objectmodel/4.3.0", + "hashPath": "system.objectmodel.4.3.0.nupkg.sha512" + }, + "System.Reflection/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "path": "system.reflection/4.3.0", + "hashPath": "system.reflection.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "path": "system.reflection.emit/4.3.0", + "hashPath": "system.reflection.emit.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit.ILGeneration/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "path": "system.reflection.emit.ilgeneration/4.3.0", + "hashPath": "system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit.Lightweight/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "path": "system.reflection.emit.lightweight/4.3.0", + "hashPath": "system.reflection.emit.lightweight.4.3.0.nupkg.sha512" + }, + "System.Reflection.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "path": "system.reflection.extensions/4.3.0", + "hashPath": "system.reflection.extensions.4.3.0.nupkg.sha512" + }, + "System.Reflection.Metadata/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==", + "path": "system.reflection.metadata/5.0.0", + "hashPath": "system.reflection.metadata.5.0.0.nupkg.sha512" + }, + "System.Reflection.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "path": "system.reflection.primitives/4.3.0", + "hashPath": "system.reflection.primitives.4.3.0.nupkg.sha512" + }, + "System.Reflection.TypeExtensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "path": "system.reflection.typeextensions/4.3.0", + "hashPath": "system.reflection.typeextensions.4.3.0.nupkg.sha512" + }, + "System.Resources.ResourceManager/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "path": "system.resources.resourcemanager/4.3.0", + "hashPath": "system.resources.resourcemanager.4.3.0.nupkg.sha512" + }, + "System.Runtime/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "path": "system.runtime/4.3.0", + "hashPath": "system.runtime.4.3.0.nupkg.sha512" + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==", + "path": "system.runtime.compilerservices.unsafe/6.0.0", + "hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512" + }, + "System.Runtime.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "path": "system.runtime.extensions/4.3.0", + "hashPath": "system.runtime.extensions.4.3.0.nupkg.sha512" + }, + "System.Runtime.Handles/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "path": "system.runtime.handles/4.3.0", + "hashPath": "system.runtime.handles.4.3.0.nupkg.sha512" + }, + "System.Runtime.InteropServices/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "path": "system.runtime.interopservices/4.3.0", + "hashPath": "system.runtime.interopservices.4.3.0.nupkg.sha512" + }, + "System.Runtime.InteropServices.RuntimeInformation/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "path": "system.runtime.interopservices.runtimeinformation/4.3.0", + "hashPath": "system.runtime.interopservices.runtimeinformation.4.3.0.nupkg.sha512" + }, + "System.Runtime.Numerics/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "path": "system.runtime.numerics/4.3.0", + "hashPath": "system.runtime.numerics.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Algorithms/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "path": "system.security.cryptography.algorithms/4.3.0", + "hashPath": "system.security.cryptography.algorithms.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Cng/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "path": "system.security.cryptography.cng/4.3.0", + "hashPath": "system.security.cryptography.cng.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Csp/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "path": "system.security.cryptography.csp/4.3.0", + "hashPath": "system.security.cryptography.csp.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Encoding/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "path": "system.security.cryptography.encoding/4.3.0", + "hashPath": "system.security.cryptography.encoding.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "path": "system.security.cryptography.openssl/4.3.0", + "hashPath": "system.security.cryptography.openssl.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "path": "system.security.cryptography.primitives/4.3.0", + "hashPath": "system.security.cryptography.primitives.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.X509Certificates/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "path": "system.security.cryptography.x509certificates/4.3.0", + "hashPath": "system.security.cryptography.x509certificates.4.3.0.nupkg.sha512" + }, + "System.Text.Encoding/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "path": "system.text.encoding/4.3.0", + "hashPath": "system.text.encoding.4.3.0.nupkg.sha512" + }, + "System.Text.Encoding.CodePages/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "path": "system.text.encoding.codepages/6.0.0", + "hashPath": "system.text.encoding.codepages.6.0.0.nupkg.sha512" + }, + "System.Text.Encoding.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "path": "system.text.encoding.extensions/4.3.0", + "hashPath": "system.text.encoding.extensions.4.3.0.nupkg.sha512" + }, + "System.Text.RegularExpressions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "path": "system.text.regularexpressions/4.3.0", + "hashPath": "system.text.regularexpressions.4.3.0.nupkg.sha512" + }, + "System.Threading/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "path": "system.threading/4.3.0", + "hashPath": "system.threading.4.3.0.nupkg.sha512" + }, + "System.Threading.Tasks/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "path": "system.threading.tasks/4.3.0", + "hashPath": "system.threading.tasks.4.3.0.nupkg.sha512" + }, + "System.Threading.Tasks.Extensions/4.5.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", + "path": "system.threading.tasks.extensions/4.5.4", + "hashPath": "system.threading.tasks.extensions.4.5.4.nupkg.sha512" + }, + "System.Threading.Timer/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "path": "system.threading.timer/4.3.0", + "hashPath": "system.threading.timer.4.3.0.nupkg.sha512" + }, + "System.Xml.ReaderWriter/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "path": "system.xml.readerwriter/4.3.0", + "hashPath": "system.xml.readerwriter.4.3.0.nupkg.sha512" + }, + "System.Xml.XDocument/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "path": "system.xml.xdocument/4.3.0", + "hashPath": "system.xml.xdocument.4.3.0.nupkg.sha512" + }, + "ClumsyCore/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "ClumsyDance/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "CycleGUI/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "LessokajiWeaverUtilities/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "RefFundamentalLib/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "RefLessokajiProtect/1.2.9365.10902": { + "type": "reference", + "serviceable": false, + "sha512": "" + } + } +} \ No newline at end of file diff --git a/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.exe b/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.exe new file mode 100644 index 0000000..950f16e Binary files /dev/null and b/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.exe differ diff --git a/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.runtimeconfig.json b/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.runtimeconfig.json new file mode 100644 index 0000000..d784515 --- /dev/null +++ b/MedullaAdapter/build/Clumsy_AGV2/ClumsyLite.runtimeconfig.json @@ -0,0 +1,13 @@ +{ + "runtimeOptions": { + "tfm": "net8.0", + "framework": { + "name": "Microsoft.NETCore.App", + "version": "8.0.0" + }, + "configProperties": { + "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false + } + } +} \ No newline at end of file diff --git a/MedullaAdapter/build/Clumsy_AGV2/ClumsyPilot.dll b/MedullaAdapter/build/Clumsy_AGV2/ClumsyPilot.dll new file mode 100644 index 0000000..51c3bbc Binary files /dev/null and b/MedullaAdapter/build/Clumsy_AGV2/ClumsyPilot.dll differ diff --git a/MedullaAdapter/build/Clumsy_AGV2/ClumsyPilot.pdb b/MedullaAdapter/build/Clumsy_AGV2/ClumsyPilot.pdb new file mode 100644 index 0000000..b4645ec Binary files /dev/null and b/MedullaAdapter/build/Clumsy_AGV2/ClumsyPilot.pdb differ diff --git a/MedullaAdapter/build/Clumsy_AGV2/CommonUsage.dll b/MedullaAdapter/build/Clumsy_AGV2/CommonUsage.dll new file mode 100644 index 0000000..effb81e Binary files /dev/null and b/MedullaAdapter/build/Clumsy_AGV2/CommonUsage.dll differ diff --git a/MedullaAdapter/build/Clumsy_AGV2/MDCSToolBox.dll b/MedullaAdapter/build/Clumsy_AGV2/MDCSToolBox.dll new file mode 100644 index 0000000..091a9bb Binary files /dev/null and b/MedullaAdapter/build/Clumsy_AGV2/MDCSToolBox.dll differ diff --git a/MedullaAdapter/build/Clumsy_AGV2/RefClumsyCore.dll b/MedullaAdapter/build/Clumsy_AGV2/RefClumsyCore.dll new file mode 100644 index 0000000..ed36470 Binary files /dev/null and b/MedullaAdapter/build/Clumsy_AGV2/RefClumsyCore.dll differ diff --git a/MedullaAdapter/build/Clumsy_AGV2/RefClumsyDance.dll b/MedullaAdapter/build/Clumsy_AGV2/RefClumsyDance.dll new file mode 100644 index 0000000..7e191a1 Binary files /dev/null and b/MedullaAdapter/build/Clumsy_AGV2/RefClumsyDance.dll differ diff --git a/MedullaAdapter/deps/DiverCompiler.exe b/MedullaAdapter/deps/DiverCompiler.exe new file mode 100644 index 0000000..42eaeb4 Binary files /dev/null and b/MedullaAdapter/deps/DiverCompiler.exe differ diff --git a/MedullaAdapter/deps/DiverCompiler1.exe b/MedullaAdapter/deps/DiverCompiler1.exe new file mode 100644 index 0000000..86816e2 Binary files /dev/null and b/MedullaAdapter/deps/DiverCompiler1.exe differ diff --git a/MedullaAdapter/native/code.c b/MedullaAdapter/native/code.c new file mode 100644 index 0000000..bdf9c1d --- /dev/null +++ b/MedullaAdapter/native/code.c @@ -0,0 +1,79 @@ +#define i1 char +#define u1 unsigned char +#define i2 short +#define u2 unsigned short +#define i4 int +#define u4 unsigned int +#define r4 float + +// function begins + +r4 cfun0(r4 arg0 ){ +//stack_vars: +r4 stack_0_r4;; +r4 stack_1_r4;; + //local_vars: +r4 var0; + L_0001: stack_0_r4=(arg0); //IL_0001: ldarg.0: s_0, pop0, push1 +L_0002: stack_1_r4=(10.5f); //IL_0002: ldc.r4 10.5: s_1, pop0, push1 +L_0007: stack_0_r4=((stack_0_r4)/(stack_1_r4)); //IL_0007: div: s_2, pop2, push1 +L_0008: stack_1_r4=(60.0f); //IL_0008: ldc.r4 60: s_1, pop0, push1 +L_000d: stack_0_r4=((stack_0_r4)/(stack_1_r4)); //IL_000d: div: s_2, pop2, push1 +L_000e: stack_0_r4=(stack_0_r4); //IL_000e: conv.r8: s_1, pop1, push1 +L_000f: stack_1_r4=(3.1f); //IL_000f: ldc.r8 3.14159265358979: s_1, pop0, push1 +L_0018: stack_0_r4=((stack_0_r4)*(stack_1_r4)); //IL_0018: mul: s_2, pop2, push1 +L_0019: stack_1_r4=(85.0f); //IL_0019: ldc.r8 85: s_1, pop0, push1 +L_0022: stack_0_r4=((stack_0_r4)*(stack_1_r4)); //IL_0022: mul: s_2, pop2, push1 +L_0023: stack_1_r4=(1000.0f); //IL_0023: ldc.r8 1000: s_1, pop0, push1 +L_002c: stack_0_r4=((stack_0_r4)/(stack_1_r4)); //IL_002c: div: s_2, pop2, push1 +L_002d: stack_0_r4=(stack_0_r4); //IL_002d: conv.r4: s_1, pop1, push1 +L_002e: var0=stack_0_r4; //IL_002e: stloc.0: s_1, pop1, push0 +L_002f: goto L_0031; //IL_002f: br.s IL_0031: s_0, pop0, push0 +L_0031: stack_0_r4=(var0); //IL_0031: ldloc.0: s_0, pop0, push1 +L_0032: return stack_0_r4; //IL_0032: ret: s_1, pop1, push0 +} + +r4 cfun1(void* arg0, r4 arg1 ){ +//stack_vars: +r4 stack_0_r4;; +r4 stack_1_r4;; + //local_vars: +r4 var0; + L_0001: stack_0_r4=(arg1); //IL_0001: ldarg.1: s_0, pop0, push1 +L_0002: stack_1_r4=(10.5f); //IL_0002: ldc.r4 10.5: s_1, pop0, push1 +L_0007: stack_0_r4=((stack_0_r4)/(stack_1_r4)); //IL_0007: div: s_2, pop2, push1 +L_0008: stack_0_r4=(stack_0_r4); //IL_0008: conv.r8: s_1, pop1, push1 +L_0009: stack_1_r4=(3.1f); //IL_0009: ldc.r8 3.14159265358979: s_1, pop0, push1 +L_0012: stack_0_r4=((stack_0_r4)*(stack_1_r4)); //IL_0012: mul: s_2, pop2, push1 +L_0013: stack_1_r4=(85.0f); //IL_0013: ldc.r8 85: s_1, pop0, push1 +L_001c: stack_0_r4=((stack_0_r4)*(stack_1_r4)); //IL_001c: mul: s_2, pop2, push1 +L_001d: stack_0_r4=(stack_0_r4); //IL_001d: conv.r4: s_1, pop1, push1 +L_001e: var0=stack_0_r4; //IL_001e: stloc.0: s_1, pop1, push0 +L_001f: goto L_0021; //IL_001f: br.s IL_0021: s_0, pop0, push0 +L_0021: stack_0_r4=(var0); //IL_0021: ldloc.0: s_0, pop0, push1 +L_0022: return stack_0_r4; //IL_0022: ret: s_1, pop1, push0 +} + +r4 cfun2(r4 arg0 ){ +//stack_vars: +r4 stack_0_r4;; +r4 stack_1_r4;; + //local_vars: +r4 var0; + L_0001: stack_0_r4=(arg0); //IL_0001: ldarg.0: s_0, pop0, push1 +L_0002: stack_0_r4=(stack_0_r4); //IL_0002: conv.r8: s_1, pop1, push1 +L_0003: stack_1_r4=(267.0f); //IL_0003: ldc.r8 267.035375555132: s_1, pop0, push1 +L_000c: stack_0_r4=((stack_0_r4)/(stack_1_r4)); //IL_000c: div: s_2, pop2, push1 +L_000d: stack_1_r4=(10.5f); //IL_000d: ldc.r8 10.5: s_1, pop0, push1 +L_0016: stack_0_r4=((stack_0_r4)*(stack_1_r4)); //IL_0016: mul: s_2, pop2, push1 +L_0017: stack_1_r4=(60.0f); //IL_0017: ldc.r8 60: s_1, pop0, push1 +L_0020: stack_0_r4=((stack_0_r4)*(stack_1_r4)); //IL_0020: mul: s_2, pop2, push1 +L_0021: stack_1_r4=(1000.0f); //IL_0021: ldc.r8 1000: s_1, pop0, push1 +L_002a: stack_0_r4=((stack_0_r4)*(stack_1_r4)); //IL_002a: mul: s_2, pop2, push1 +L_002b: stack_0_r4=(stack_0_r4); //IL_002b: conv.r4: s_1, pop1, push1 +L_002c: var0=stack_0_r4; //IL_002c: stloc.0: s_1, pop1, push0 +L_002d: goto L_002f; //IL_002d: br.s IL_002f: s_0, pop0, push0 +L_002f: stack_0_r4=(var0); //IL_002f: ldloc.0: s_0, pop0, push1 +L_0030: return stack_0_r4; //IL_0030: ret: s_1, pop1, push0 +} + diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs b/MedullaAdapter/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs new file mode 100644 index 0000000..8bf3a42 --- /dev/null +++ b/MedullaAdapter/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaA.645DEFF4.Up2Date b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaA.645DEFF4.Up2Date new file mode 100644 index 0000000..e69de29 diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.AssemblyInfo.cs b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.AssemblyInfo.cs new file mode 100644 index 0000000..5033d7b --- /dev/null +++ b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// 姝や唬鐮佺敱宸ュ叿鐢熸垚銆 +// 杩愯鏃剁増鏈:4.0.30319.42000 +// +// 瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋 +// 閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便 +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("MedullaAdapter")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("MedullaAdapter")] +[assembly: System.Reflection.AssemblyTitleAttribute("MedullaAdapter")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// 鐢 MSBuild WriteCodeFragment 绫荤敓鎴愩 + diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.AssemblyInfoInputs.cache b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.AssemblyInfoInputs.cache new file mode 100644 index 0000000..affde94 --- /dev/null +++ b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +2eac81d674c264ce890b4225c419fa343e662bbba0825694002aaadff6e734b7 diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.GeneratedMSBuildEditorConfig.editorconfig b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..d3f4c84 --- /dev/null +++ b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,8 @@ +is_global = true +build_property.RootNamespace = MedullaAdapter +build_property.ProjectDir = D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.CsWinRTUseWindowsUIXamlProjections = false +build_property.EffectiveAnalysisLevelStyle = +build_property.EnableCodeStyleSeverity = diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.assets.cache b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.assets.cache new file mode 100644 index 0000000..ea412ad Binary files /dev/null and b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.assets.cache differ diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.AssemblyReference.cache b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.AssemblyReference.cache new file mode 100644 index 0000000..ad6c7ad Binary files /dev/null and b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.AssemblyReference.cache differ diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.CoreCompileInputs.cache b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..f9b789e --- /dev/null +++ b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +7311d51d953d1fc22835d320a3489ce25305e242222f67ae1dd4ce8b482c0a5a diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.FileListAbsolute.txt b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..3f4c06c --- /dev/null +++ b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.FileListAbsolute.txt @@ -0,0 +1,19 @@ +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.csproj.AssemblyReference.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.GeneratedMSBuildEditorConfig.editorconfig +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.AssemblyInfoInputs.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.AssemblyInfo.cs +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.csproj.CoreCompileInputs.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.pdb +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\MedullaAdapter.deps.json +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\MedullaAdapter.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\MedullaAdapter.pdb +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\CommonUsage.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\CycleGUI.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\MDCSToolBox.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\RefCartActivator.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\RefFundamentalLib.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\bin\Debug\netstandard2.0\RefMedullaCore.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.csproj.Fody.CopyLocal.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaAdapter.csproj.Fody.RuntimeCopyLocal.cache +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\obj\Debug\netstandard2.0\MedullaA.645DEFF4.Up2Date diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.Fody.CopyLocal.cache b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.Fody.CopyLocal.cache new file mode 100644 index 0000000..bd7c46a --- /dev/null +++ b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.Fody.CopyLocal.cache @@ -0,0 +1,6 @@ +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\parkingRobotRef\CommonUsage.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\ref\CycleGUI.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\parkingRobotRef\MDCSToolBox.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\ref\RefCartActivator.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\ref\RefFundamentalLib.dll +D:\@FariyLandTask\@FRLD-GitProject\ParkingRobot\MedullaAdapter\ref\RefMedullaCore.dll diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.Fody.RuntimeCopyLocal.cache b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.Fody.RuntimeCopyLocal.cache new file mode 100644 index 0000000..251acfb --- /dev/null +++ b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.csproj.Fody.RuntimeCopyLocal.cache @@ -0,0 +1,9 @@ +C:\Users\Fairyland\.nuget\packages\microsoft.win32.registry\5.0.0\lib\netstandard2.0\Microsoft.Win32.Registry.dll +C:\Users\Fairyland\.nuget\packages\newtonsoft.json\13.0.4\lib\netstandard2.0\Newtonsoft.Json.dll +C:\Users\Fairyland\.nuget\packages\system.buffers\4.5.1\lib\netstandard2.0\System.Buffers.dll +C:\Users\Fairyland\.nuget\packages\system.io.ports\6.0.0\lib\netstandard2.0\System.IO.Ports.dll +C:\Users\Fairyland\.nuget\packages\system.memory\4.5.4\lib\netstandard2.0\System.Memory.dll +C:\Users\Fairyland\.nuget\packages\system.numerics.vectors\4.4.0\lib\netstandard2.0\System.Numerics.Vectors.dll +C:\Users\Fairyland\.nuget\packages\system.runtime.compilerservices.unsafe\4.5.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll +C:\Users\Fairyland\.nuget\packages\system.security.accesscontrol\5.0.0\lib\netstandard2.0\System.Security.AccessControl.dll +C:\Users\Fairyland\.nuget\packages\system.security.principal.windows\5.0.0\lib\netstandard2.0\System.Security.Principal.Windows.dll diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.dll b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.dll new file mode 100644 index 0000000..2a6d338 Binary files /dev/null and b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.dll differ diff --git a/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.pdb b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.pdb new file mode 100644 index 0000000..c129906 Binary files /dev/null and b/MedullaAdapter/obj/Debug/netstandard2.0/MedullaAdapter.pdb differ diff --git a/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.dgspec.json b/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.dgspec.json new file mode 100644 index 0000000..df2c337 --- /dev/null +++ b/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.dgspec.json @@ -0,0 +1,90 @@ +{ + "format": 1, + "restore": { + "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\MedullaAdapter.csproj": {} + }, + "projects": { + "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\MedullaAdapter.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\MedullaAdapter.csproj", + "projectName": "MedullaAdapter", + "projectPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\MedullaAdapter.csproj", + "packagesPath": "C:\\Users\\Fairyland\\.nuget\\packages\\", + "outputPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "D:\\VS2022\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\Fairyland\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "netstandard2.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netstandard2.0": { + "targetAlias": "netstandard2.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "netstandard2.0": { + "targetAlias": "netstandard2.0", + "dependencies": { + "Fody": { + "include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive", + "suppressParent": "All", + "target": "Package", + "version": "[6.9.3, )" + }, + "NETStandard.Library": { + "suppressParent": "All", + "target": "Package", + "version": "[2.0.3, )", + "autoReferenced": true + }, + "Newtonsoft.Json": { + "target": "Package", + "version": "[13.0.4, )" + }, + "System.IO.Ports": { + "target": "Package", + "version": "[6.0.0, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.308\\RuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.g.props b/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.g.props new file mode 100644 index 0000000..88c0201 --- /dev/null +++ b/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.g.props @@ -0,0 +1,16 @@ +锘 + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + $(UserProfile)\.nuget\packages\ + C:\Users\Fairyland\.nuget\packages\;D:\VS2022\Shared\NuGetPackages + PackageReference + 6.14.2 + + + + + + \ No newline at end of file diff --git a/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.g.targets b/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.g.targets new file mode 100644 index 0000000..de01561 --- /dev/null +++ b/MedullaAdapter/obj/MedullaAdapter.csproj.nuget.g.targets @@ -0,0 +1,7 @@ +锘 + + + + + + \ No newline at end of file diff --git a/MedullaAdapter/obj/project.assets.json b/MedullaAdapter/obj/project.assets.json new file mode 100644 index 0000000..7998aaa --- /dev/null +++ b/MedullaAdapter/obj/project.assets.json @@ -0,0 +1,962 @@ +{ + "version": 3, + "targets": { + ".NETStandard,Version=v2.0": { + "Fody/6.9.3": { + "type": "package", + "build": { + "build/Fody.targets": {} + } + }, + "Microsoft.NETCore.Platforms/1.1.0": { + "type": "package", + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "Microsoft.Win32.Registry/5.0.0": { + "type": "package", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + }, + "compile": { + "ref/netstandard2.0/Microsoft.Win32.Registry.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Win32.Registry.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/win/lib/netstandard2.0/Microsoft.Win32.Registry.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "NETStandard.Library/2.0.3": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + }, + "build": { + "build/netstandard2.0/NETStandard.Library.targets": {} + } + }, + "Newtonsoft.Json/13.0.4": { + "type": "package", + "compile": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + } + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "runtimeTargets": { + "runtimes/linux-arm/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-arm" + } + } + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "runtimeTargets": { + "runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-arm64" + } + } + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "runtimeTargets": { + "runtimes/linux-x64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-x64" + } + } + }, + "runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "dependencies": { + "runtime.linux-arm.runtime.native.System.IO.Ports": "6.0.0", + "runtime.linux-arm64.runtime.native.System.IO.Ports": "6.0.0", + "runtime.linux-x64.runtime.native.System.IO.Ports": "6.0.0", + "runtime.osx-arm64.runtime.native.System.IO.Ports": "6.0.0", + "runtime.osx-x64.runtime.native.System.IO.Ports": "6.0.0" + } + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "runtimeTargets": { + "runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib": { + "assetType": "native", + "rid": "osx-arm64" + } + } + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/6.0.0": { + "type": "package", + "runtimeTargets": { + "runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "System.Buffers/4.5.1": { + "type": "package", + "compile": { + "ref/netstandard2.0/System.Buffers.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Buffers.dll": { + "related": ".xml" + } + } + }, + "System.IO.Ports/6.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Win32.Registry": "5.0.0", + "System.Memory": "4.5.4", + "runtime.native.System.IO.Ports": "6.0.0" + }, + "compile": { + "lib/netstandard2.0/System.IO.Ports.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.IO.Ports.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard2.0/System.IO.Ports.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Memory/4.5.4": { + "type": "package", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Numerics.Vectors": "4.4.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3" + }, + "compile": { + "lib/netstandard2.0/System.Memory.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Memory.dll": { + "related": ".xml" + } + } + }, + "System.Numerics.Vectors/4.4.0": { + "type": "package", + "compile": { + "ref/netstandard2.0/System.Numerics.Vectors.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Numerics.Vectors.dll": { + "related": ".xml" + } + } + }, + "System.Runtime.CompilerServices.Unsafe/4.5.3": { + "type": "package", + "compile": { + "ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + } + }, + "System.Security.AccessControl/5.0.0": { + "type": "package", + "dependencies": { + "System.Security.Principal.Windows": "5.0.0" + }, + "compile": { + "ref/netstandard2.0/System.Security.AccessControl.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Security.AccessControl.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/win/lib/netstandard1.3/System.Security.AccessControl.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Principal.Windows/5.0.0": { + "type": "package", + "compile": { + "ref/netstandard2.0/System.Security.Principal.Windows.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Security.Principal.Windows.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/win/lib/netstandard1.3/System.Security.Principal.Windows.dll": { + "assetType": "runtime", + "rid": "win" + } + } + } + } + }, + "libraries": { + "Fody/6.9.3": { + "sha512": "1CUGgFdyECDKgi5HaUBhdv6k+VG9Iy4OCforGfHyar3xQXAJypZkzymgKtWj/4SPd6nSG0Qi7NH71qHrDSZLaA==", + "type": "package", + "path": "fody/6.9.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/Fody.targets", + "fody.6.9.3.nupkg.sha512", + "fody.nuspec", + "package_icon.png", + "package_readme.md", + "tasks/net472/FodyCommon.dll", + "tasks/net472/FodyHelpers.dll", + "tasks/net472/FodyHelpers.xml", + "tasks/net472/FodyIsolated.dll", + "tasks/net472/FodyTasks.dll", + "tasks/net472/Mono.Cecil.Pdb.dll", + "tasks/net472/Mono.Cecil.Pdb.pdb", + "tasks/net472/Mono.Cecil.Rocks.dll", + "tasks/net472/Mono.Cecil.Rocks.pdb", + "tasks/net472/Mono.Cecil.dll", + "tasks/net472/Mono.Cecil.pdb", + "tasks/netstandard2.0/FodyCommon.dll", + "tasks/netstandard2.0/FodyHelpers.dll", + "tasks/netstandard2.0/FodyHelpers.xml", + "tasks/netstandard2.0/FodyIsolated.dll", + "tasks/netstandard2.0/FodyTasks.dll", + "tasks/netstandard2.0/Mono.Cecil.Pdb.dll", + "tasks/netstandard2.0/Mono.Cecil.Pdb.pdb", + "tasks/netstandard2.0/Mono.Cecil.Rocks.dll", + "tasks/netstandard2.0/Mono.Cecil.Rocks.pdb", + "tasks/netstandard2.0/Mono.Cecil.dll", + "tasks/netstandard2.0/Mono.Cecil.pdb" + ] + }, + "Microsoft.NETCore.Platforms/1.1.0": { + "sha512": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", + "type": "package", + "path": "microsoft.netcore.platforms/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.0/_._", + "microsoft.netcore.platforms.1.1.0.nupkg.sha512", + "microsoft.netcore.platforms.nuspec", + "runtime.json" + ] + }, + "Microsoft.Win32.Registry/5.0.0": { + "sha512": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "type": "package", + "path": "microsoft.win32.registry/5.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net46/Microsoft.Win32.Registry.dll", + "lib/net461/Microsoft.Win32.Registry.dll", + "lib/net461/Microsoft.Win32.Registry.xml", + "lib/netstandard1.3/Microsoft.Win32.Registry.dll", + "lib/netstandard2.0/Microsoft.Win32.Registry.dll", + "lib/netstandard2.0/Microsoft.Win32.Registry.xml", + "microsoft.win32.registry.5.0.0.nupkg.sha512", + "microsoft.win32.registry.nuspec", + "ref/net46/Microsoft.Win32.Registry.dll", + "ref/net461/Microsoft.Win32.Registry.dll", + "ref/net461/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/Microsoft.Win32.Registry.dll", + "ref/netstandard1.3/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/de/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/es/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/fr/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/it/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/ja/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/ko/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/ru/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/zh-hans/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/zh-hant/Microsoft.Win32.Registry.xml", + "ref/netstandard2.0/Microsoft.Win32.Registry.dll", + "ref/netstandard2.0/Microsoft.Win32.Registry.xml", + "runtimes/win/lib/net46/Microsoft.Win32.Registry.dll", + "runtimes/win/lib/net461/Microsoft.Win32.Registry.dll", + "runtimes/win/lib/net461/Microsoft.Win32.Registry.xml", + "runtimes/win/lib/netstandard1.3/Microsoft.Win32.Registry.dll", + "runtimes/win/lib/netstandard2.0/Microsoft.Win32.Registry.dll", + "runtimes/win/lib/netstandard2.0/Microsoft.Win32.Registry.xml", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "NETStandard.Library/2.0.3": { + "sha512": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", + "type": "package", + "path": "netstandard.library/2.0.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "build/netstandard2.0/NETStandard.Library.targets", + "build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll", + "build/netstandard2.0/ref/System.AppContext.dll", + "build/netstandard2.0/ref/System.Collections.Concurrent.dll", + "build/netstandard2.0/ref/System.Collections.NonGeneric.dll", + "build/netstandard2.0/ref/System.Collections.Specialized.dll", + "build/netstandard2.0/ref/System.Collections.dll", + "build/netstandard2.0/ref/System.ComponentModel.Composition.dll", + "build/netstandard2.0/ref/System.ComponentModel.EventBasedAsync.dll", + "build/netstandard2.0/ref/System.ComponentModel.Primitives.dll", + "build/netstandard2.0/ref/System.ComponentModel.TypeConverter.dll", + "build/netstandard2.0/ref/System.ComponentModel.dll", + "build/netstandard2.0/ref/System.Console.dll", + "build/netstandard2.0/ref/System.Core.dll", + "build/netstandard2.0/ref/System.Data.Common.dll", + "build/netstandard2.0/ref/System.Data.dll", + "build/netstandard2.0/ref/System.Diagnostics.Contracts.dll", + "build/netstandard2.0/ref/System.Diagnostics.Debug.dll", + "build/netstandard2.0/ref/System.Diagnostics.FileVersionInfo.dll", + "build/netstandard2.0/ref/System.Diagnostics.Process.dll", + "build/netstandard2.0/ref/System.Diagnostics.StackTrace.dll", + "build/netstandard2.0/ref/System.Diagnostics.TextWriterTraceListener.dll", + "build/netstandard2.0/ref/System.Diagnostics.Tools.dll", + "build/netstandard2.0/ref/System.Diagnostics.TraceSource.dll", + "build/netstandard2.0/ref/System.Diagnostics.Tracing.dll", + "build/netstandard2.0/ref/System.Drawing.Primitives.dll", + "build/netstandard2.0/ref/System.Drawing.dll", + "build/netstandard2.0/ref/System.Dynamic.Runtime.dll", + "build/netstandard2.0/ref/System.Globalization.Calendars.dll", + "build/netstandard2.0/ref/System.Globalization.Extensions.dll", + "build/netstandard2.0/ref/System.Globalization.dll", + "build/netstandard2.0/ref/System.IO.Compression.FileSystem.dll", + "build/netstandard2.0/ref/System.IO.Compression.ZipFile.dll", + "build/netstandard2.0/ref/System.IO.Compression.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.DriveInfo.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.Primitives.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.Watcher.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.dll", + "build/netstandard2.0/ref/System.IO.IsolatedStorage.dll", + "build/netstandard2.0/ref/System.IO.MemoryMappedFiles.dll", + "build/netstandard2.0/ref/System.IO.Pipes.dll", + "build/netstandard2.0/ref/System.IO.UnmanagedMemoryStream.dll", + "build/netstandard2.0/ref/System.IO.dll", + "build/netstandard2.0/ref/System.Linq.Expressions.dll", + "build/netstandard2.0/ref/System.Linq.Parallel.dll", + "build/netstandard2.0/ref/System.Linq.Queryable.dll", + "build/netstandard2.0/ref/System.Linq.dll", + "build/netstandard2.0/ref/System.Net.Http.dll", + "build/netstandard2.0/ref/System.Net.NameResolution.dll", + "build/netstandard2.0/ref/System.Net.NetworkInformation.dll", + "build/netstandard2.0/ref/System.Net.Ping.dll", + "build/netstandard2.0/ref/System.Net.Primitives.dll", + "build/netstandard2.0/ref/System.Net.Requests.dll", + "build/netstandard2.0/ref/System.Net.Security.dll", + "build/netstandard2.0/ref/System.Net.Sockets.dll", + "build/netstandard2.0/ref/System.Net.WebHeaderCollection.dll", + "build/netstandard2.0/ref/System.Net.WebSockets.Client.dll", + "build/netstandard2.0/ref/System.Net.WebSockets.dll", + "build/netstandard2.0/ref/System.Net.dll", + "build/netstandard2.0/ref/System.Numerics.dll", + "build/netstandard2.0/ref/System.ObjectModel.dll", + "build/netstandard2.0/ref/System.Reflection.Extensions.dll", + "build/netstandard2.0/ref/System.Reflection.Primitives.dll", + "build/netstandard2.0/ref/System.Reflection.dll", + "build/netstandard2.0/ref/System.Resources.Reader.dll", + "build/netstandard2.0/ref/System.Resources.ResourceManager.dll", + "build/netstandard2.0/ref/System.Resources.Writer.dll", + "build/netstandard2.0/ref/System.Runtime.CompilerServices.VisualC.dll", + "build/netstandard2.0/ref/System.Runtime.Extensions.dll", + "build/netstandard2.0/ref/System.Runtime.Handles.dll", + "build/netstandard2.0/ref/System.Runtime.InteropServices.RuntimeInformation.dll", + "build/netstandard2.0/ref/System.Runtime.InteropServices.dll", + "build/netstandard2.0/ref/System.Runtime.Numerics.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Formatters.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Json.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Primitives.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Xml.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.dll", + "build/netstandard2.0/ref/System.Runtime.dll", + "build/netstandard2.0/ref/System.Security.Claims.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Algorithms.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Csp.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Encoding.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Primitives.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.X509Certificates.dll", + "build/netstandard2.0/ref/System.Security.Principal.dll", + "build/netstandard2.0/ref/System.Security.SecureString.dll", + "build/netstandard2.0/ref/System.ServiceModel.Web.dll", + "build/netstandard2.0/ref/System.Text.Encoding.Extensions.dll", + "build/netstandard2.0/ref/System.Text.Encoding.dll", + "build/netstandard2.0/ref/System.Text.RegularExpressions.dll", + "build/netstandard2.0/ref/System.Threading.Overlapped.dll", + "build/netstandard2.0/ref/System.Threading.Tasks.Parallel.dll", + "build/netstandard2.0/ref/System.Threading.Tasks.dll", + "build/netstandard2.0/ref/System.Threading.Thread.dll", + "build/netstandard2.0/ref/System.Threading.ThreadPool.dll", + "build/netstandard2.0/ref/System.Threading.Timer.dll", + "build/netstandard2.0/ref/System.Threading.dll", + "build/netstandard2.0/ref/System.Transactions.dll", + "build/netstandard2.0/ref/System.ValueTuple.dll", + "build/netstandard2.0/ref/System.Web.dll", + "build/netstandard2.0/ref/System.Windows.dll", + "build/netstandard2.0/ref/System.Xml.Linq.dll", + "build/netstandard2.0/ref/System.Xml.ReaderWriter.dll", + "build/netstandard2.0/ref/System.Xml.Serialization.dll", + "build/netstandard2.0/ref/System.Xml.XDocument.dll", + "build/netstandard2.0/ref/System.Xml.XPath.XDocument.dll", + "build/netstandard2.0/ref/System.Xml.XPath.dll", + "build/netstandard2.0/ref/System.Xml.XmlDocument.dll", + "build/netstandard2.0/ref/System.Xml.XmlSerializer.dll", + "build/netstandard2.0/ref/System.Xml.dll", + "build/netstandard2.0/ref/System.dll", + "build/netstandard2.0/ref/mscorlib.dll", + "build/netstandard2.0/ref/netstandard.dll", + "build/netstandard2.0/ref/netstandard.xml", + "lib/netstandard1.0/_._", + "netstandard.library.2.0.3.nupkg.sha512", + "netstandard.library.nuspec" + ] + }, + "Newtonsoft.Json/13.0.4": { + "sha512": "pdgNNMai3zv51W5aq268sujXUyx7SNdE2bj1wZcWjAQrKMFZV260lbqYop1d2GM67JI1huLRwxo9ZqnfF/lC6A==", + "type": "package", + "path": "newtonsoft.json/13.0.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.md", + "README.md", + "lib/net20/Newtonsoft.Json.dll", + "lib/net20/Newtonsoft.Json.xml", + "lib/net35/Newtonsoft.Json.dll", + "lib/net35/Newtonsoft.Json.xml", + "lib/net40/Newtonsoft.Json.dll", + "lib/net40/Newtonsoft.Json.xml", + "lib/net45/Newtonsoft.Json.dll", + "lib/net45/Newtonsoft.Json.xml", + "lib/net6.0/Newtonsoft.Json.dll", + "lib/net6.0/Newtonsoft.Json.xml", + "lib/netstandard1.0/Newtonsoft.Json.dll", + "lib/netstandard1.0/Newtonsoft.Json.xml", + "lib/netstandard1.3/Newtonsoft.Json.dll", + "lib/netstandard1.3/Newtonsoft.Json.xml", + "lib/netstandard2.0/Newtonsoft.Json.dll", + "lib/netstandard2.0/Newtonsoft.Json.xml", + "newtonsoft.json.13.0.4.nupkg.sha512", + "newtonsoft.json.nuspec", + "packageIcon.png" + ] + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/6.0.0": { + "sha512": "75q52H7CSpgIoIDwXb9o833EvBZIXJ0mdPhz1E6jSisEXUBlSCPalC29cj3EXsjpuDwr0dj1LRXZepIQH/oL4Q==", + "type": "package", + "path": "runtime.linux-arm.runtime.native.system.io.ports/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-arm.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "runtime.linux-arm.runtime.native.system.io.ports.nuspec", + "runtimes/linux-arm/native/libSystem.IO.Ports.Native.so", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/6.0.0": { + "sha512": "xn2bMThmXr3CsvOYmS8ex2Yz1xo+kcnhVg2iVhS9PlmqjZPAkrEo/I40wjrBZH/tU4kvH0s1AE8opAvQ3KIS8g==", + "type": "package", + "path": "runtime.linux-arm64.runtime.native.system.io.ports/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-arm64.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "runtime.linux-arm64.runtime.native.system.io.ports.nuspec", + "runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/6.0.0": { + "sha512": "16nbNXwv0sC+gLGIuecri0skjuh6R1maIJggsaNP7MQBcbVcEfWFUOkEnsnvoLEjy0XerfibuRptfQ8AmdIcWA==", + "type": "package", + "path": "runtime.linux-x64.runtime.native.system.io.ports/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-x64.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "runtime.linux-x64.runtime.native.system.io.ports.nuspec", + "runtimes/linux-x64/native/libSystem.IO.Ports.Native.so", + "useSharedDesignerContext.txt" + ] + }, + "runtime.native.System.IO.Ports/6.0.0": { + "sha512": "KaaXlpOcuZjMdmyF5wzzx3b+PRKIzt6A5Ax9dKenPDQbVJAFpev+casD0BIig1pBcbs3zx7CqWemzUJKAeHdSQ==", + "type": "package", + "path": "runtime.native.system.io.ports/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "runtime.native.system.io.ports.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/6.0.0": { + "sha512": "fXG12NodG1QrCdoaeSQ1gVnk/koi4WYY4jZtarMkZeQMyReBm1nZlSRoPnUjLr2ZR36TiMjpcGnQfxymieUe7w==", + "type": "package", + "path": "runtime.osx-arm64.runtime.native.system.io.ports/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "runtime.osx-arm64.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "runtime.osx-arm64.runtime.native.system.io.ports.nuspec", + "runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib", + "useSharedDesignerContext.txt" + ] + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/6.0.0": { + "sha512": "/As+zPY49+dSUXkh+fTUbyPhqrdGN//evLxo4Vue88pfh1BHZgF7q4kMblTkxYvwR6Vi03zSYxysSFktO8/SDQ==", + "type": "package", + "path": "runtime.osx-x64.runtime.native.system.io.ports/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "runtime.osx-x64.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "runtime.osx-x64.runtime.native.system.io.ports.nuspec", + "runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib", + "useSharedDesignerContext.txt" + ] + }, + "System.Buffers/4.5.1": { + "sha512": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==", + "type": "package", + "path": "system.buffers/4.5.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net461/System.Buffers.dll", + "lib/net461/System.Buffers.xml", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.1/System.Buffers.dll", + "lib/netstandard1.1/System.Buffers.xml", + "lib/netstandard2.0/System.Buffers.dll", + "lib/netstandard2.0/System.Buffers.xml", + "lib/uap10.0.16299/_._", + "ref/net45/System.Buffers.dll", + "ref/net45/System.Buffers.xml", + "ref/netcoreapp2.0/_._", + "ref/netstandard1.1/System.Buffers.dll", + "ref/netstandard1.1/System.Buffers.xml", + "ref/netstandard2.0/System.Buffers.dll", + "ref/netstandard2.0/System.Buffers.xml", + "ref/uap10.0.16299/_._", + "system.buffers.4.5.1.nupkg.sha512", + "system.buffers.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.IO.Ports/6.0.0": { + "sha512": "dRyGI7fUESar5ZLIpiBOaaNLW7YyOBGftjj5Of+xcduC/Rjl7RjhEnWDvvNBmHuF3d0tdXoqdVI/yrVA8f00XA==", + "type": "package", + "path": "system.io.ports/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.IO.Ports.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.IO.Ports.dll", + "lib/net461/System.IO.Ports.xml", + "lib/net6.0/System.IO.Ports.dll", + "lib/net6.0/System.IO.Ports.xml", + "lib/netstandard2.0/System.IO.Ports.dll", + "lib/netstandard2.0/System.IO.Ports.xml", + "runtimes/unix/lib/net6.0/System.IO.Ports.dll", + "runtimes/unix/lib/net6.0/System.IO.Ports.xml", + "runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll", + "runtimes/unix/lib/netstandard2.0/System.IO.Ports.xml", + "runtimes/win/lib/net461/System.IO.Ports.dll", + "runtimes/win/lib/net461/System.IO.Ports.xml", + "runtimes/win/lib/net6.0/System.IO.Ports.dll", + "runtimes/win/lib/net6.0/System.IO.Ports.xml", + "runtimes/win/lib/netstandard2.0/System.IO.Ports.dll", + "runtimes/win/lib/netstandard2.0/System.IO.Ports.xml", + "system.io.ports.6.0.0.nupkg.sha512", + "system.io.ports.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Memory/4.5.4": { + "sha512": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "type": "package", + "path": "system.memory/4.5.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net461/System.Memory.dll", + "lib/net461/System.Memory.xml", + "lib/netcoreapp2.1/_._", + "lib/netstandard1.1/System.Memory.dll", + "lib/netstandard1.1/System.Memory.xml", + "lib/netstandard2.0/System.Memory.dll", + "lib/netstandard2.0/System.Memory.xml", + "ref/netcoreapp2.1/_._", + "system.memory.4.5.4.nupkg.sha512", + "system.memory.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Numerics.Vectors/4.4.0": { + "sha512": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==", + "type": "package", + "path": "system.numerics.vectors/4.4.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Numerics.Vectors.dll", + "lib/net46/System.Numerics.Vectors.xml", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.0/System.Numerics.Vectors.dll", + "lib/netstandard1.0/System.Numerics.Vectors.xml", + "lib/netstandard2.0/System.Numerics.Vectors.dll", + "lib/netstandard2.0/System.Numerics.Vectors.xml", + "lib/portable-net45+win8+wp8+wpa81/System.Numerics.Vectors.dll", + "lib/portable-net45+win8+wp8+wpa81/System.Numerics.Vectors.xml", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Numerics.Vectors.dll", + "ref/net46/System.Numerics.Vectors.xml", + "ref/netcoreapp2.0/_._", + "ref/netstandard1.0/System.Numerics.Vectors.dll", + "ref/netstandard1.0/System.Numerics.Vectors.xml", + "ref/netstandard2.0/System.Numerics.Vectors.dll", + "ref/netstandard2.0/System.Numerics.Vectors.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.numerics.vectors.4.4.0.nupkg.sha512", + "system.numerics.vectors.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Runtime.CompilerServices.Unsafe/4.5.3": { + "sha512": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw==", + "type": "package", + "path": "system.runtime.compilerservices.unsafe/4.5.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net461/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net461/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml", + "ref/net461/System.Runtime.CompilerServices.Unsafe.dll", + "ref/net461/System.Runtime.CompilerServices.Unsafe.xml", + "ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll", + "ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml", + "ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll", + "ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml", + "system.runtime.compilerservices.unsafe.4.5.3.nupkg.sha512", + "system.runtime.compilerservices.unsafe.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Security.AccessControl/5.0.0": { + "sha512": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", + "type": "package", + "path": "system.security.accesscontrol/5.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net46/System.Security.AccessControl.dll", + "lib/net461/System.Security.AccessControl.dll", + "lib/net461/System.Security.AccessControl.xml", + "lib/netstandard1.3/System.Security.AccessControl.dll", + "lib/netstandard2.0/System.Security.AccessControl.dll", + "lib/netstandard2.0/System.Security.AccessControl.xml", + "lib/uap10.0.16299/_._", + "ref/net46/System.Security.AccessControl.dll", + "ref/net461/System.Security.AccessControl.dll", + "ref/net461/System.Security.AccessControl.xml", + "ref/netstandard1.3/System.Security.AccessControl.dll", + "ref/netstandard1.3/System.Security.AccessControl.xml", + "ref/netstandard1.3/de/System.Security.AccessControl.xml", + "ref/netstandard1.3/es/System.Security.AccessControl.xml", + "ref/netstandard1.3/fr/System.Security.AccessControl.xml", + "ref/netstandard1.3/it/System.Security.AccessControl.xml", + "ref/netstandard1.3/ja/System.Security.AccessControl.xml", + "ref/netstandard1.3/ko/System.Security.AccessControl.xml", + "ref/netstandard1.3/ru/System.Security.AccessControl.xml", + "ref/netstandard1.3/zh-hans/System.Security.AccessControl.xml", + "ref/netstandard1.3/zh-hant/System.Security.AccessControl.xml", + "ref/netstandard2.0/System.Security.AccessControl.dll", + "ref/netstandard2.0/System.Security.AccessControl.xml", + "ref/uap10.0.16299/_._", + "runtimes/win/lib/net46/System.Security.AccessControl.dll", + "runtimes/win/lib/net461/System.Security.AccessControl.dll", + "runtimes/win/lib/net461/System.Security.AccessControl.xml", + "runtimes/win/lib/netcoreapp2.0/System.Security.AccessControl.dll", + "runtimes/win/lib/netcoreapp2.0/System.Security.AccessControl.xml", + "runtimes/win/lib/netstandard1.3/System.Security.AccessControl.dll", + "runtimes/win/lib/uap10.0.16299/_._", + "system.security.accesscontrol.5.0.0.nupkg.sha512", + "system.security.accesscontrol.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Security.Principal.Windows/5.0.0": { + "sha512": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==", + "type": "package", + "path": "system.security.principal.windows/5.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net46/System.Security.Principal.Windows.dll", + "lib/net461/System.Security.Principal.Windows.dll", + "lib/net461/System.Security.Principal.Windows.xml", + "lib/netstandard1.3/System.Security.Principal.Windows.dll", + "lib/netstandard2.0/System.Security.Principal.Windows.dll", + "lib/netstandard2.0/System.Security.Principal.Windows.xml", + "lib/uap10.0.16299/_._", + "ref/net46/System.Security.Principal.Windows.dll", + "ref/net461/System.Security.Principal.Windows.dll", + "ref/net461/System.Security.Principal.Windows.xml", + "ref/netcoreapp3.0/System.Security.Principal.Windows.dll", + "ref/netcoreapp3.0/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/System.Security.Principal.Windows.dll", + "ref/netstandard1.3/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/de/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/es/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/fr/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/it/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/ja/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/ko/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/ru/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/zh-hans/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/zh-hant/System.Security.Principal.Windows.xml", + "ref/netstandard2.0/System.Security.Principal.Windows.dll", + "ref/netstandard2.0/System.Security.Principal.Windows.xml", + "ref/uap10.0.16299/_._", + "runtimes/unix/lib/netcoreapp2.0/System.Security.Principal.Windows.dll", + "runtimes/unix/lib/netcoreapp2.0/System.Security.Principal.Windows.xml", + "runtimes/unix/lib/netcoreapp2.1/System.Security.Principal.Windows.dll", + "runtimes/unix/lib/netcoreapp2.1/System.Security.Principal.Windows.xml", + "runtimes/win/lib/net46/System.Security.Principal.Windows.dll", + "runtimes/win/lib/net461/System.Security.Principal.Windows.dll", + "runtimes/win/lib/net461/System.Security.Principal.Windows.xml", + "runtimes/win/lib/netcoreapp2.0/System.Security.Principal.Windows.dll", + "runtimes/win/lib/netcoreapp2.0/System.Security.Principal.Windows.xml", + "runtimes/win/lib/netcoreapp2.1/System.Security.Principal.Windows.dll", + "runtimes/win/lib/netcoreapp2.1/System.Security.Principal.Windows.xml", + "runtimes/win/lib/netstandard1.3/System.Security.Principal.Windows.dll", + "runtimes/win/lib/uap10.0.16299/_._", + "system.security.principal.windows.5.0.0.nupkg.sha512", + "system.security.principal.windows.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + } + }, + "projectFileDependencyGroups": { + ".NETStandard,Version=v2.0": [ + "Fody >= 6.9.3", + "NETStandard.Library >= 2.0.3", + "Newtonsoft.Json >= 13.0.4", + "System.IO.Ports >= 6.0.0" + ] + }, + "packageFolders": { + "C:\\Users\\Fairyland\\.nuget\\packages\\": {}, + "D:\\VS2022\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\MedullaAdapter.csproj", + "projectName": "MedullaAdapter", + "projectPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\MedullaAdapter.csproj", + "packagesPath": "C:\\Users\\Fairyland\\.nuget\\packages\\", + "outputPath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "D:\\VS2022\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\Fairyland\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "netstandard2.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netstandard2.0": { + "targetAlias": "netstandard2.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "netstandard2.0": { + "targetAlias": "netstandard2.0", + "dependencies": { + "Fody": { + "include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive", + "suppressParent": "All", + "target": "Package", + "version": "[6.9.3, )" + }, + "NETStandard.Library": { + "suppressParent": "All", + "target": "Package", + "version": "[2.0.3, )", + "autoReferenced": true + }, + "Newtonsoft.Json": { + "target": "Package", + "version": "[13.0.4, )" + }, + "System.IO.Ports": { + "target": "Package", + "version": "[6.0.0, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.308\\RuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/MedullaAdapter/obj/project.nuget.cache b/MedullaAdapter/obj/project.nuget.cache new file mode 100644 index 0000000..9a2f97f --- /dev/null +++ b/MedullaAdapter/obj/project.nuget.cache @@ -0,0 +1,27 @@ +{ + "version": 2, + "dgSpecHash": "M6NonK0uNRA=", + "success": true, + "projectFilePath": "D:\\@FariyLandTask\\@FRLD-GitProject\\ParkingRobot\\MedullaAdapter\\MedullaAdapter.csproj", + "expectedPackageFiles": [ + "C:\\Users\\Fairyland\\.nuget\\packages\\fody\\6.9.3\\fody.6.9.3.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\microsoft.netcore.platforms\\1.1.0\\microsoft.netcore.platforms.1.1.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\microsoft.win32.registry\\5.0.0\\microsoft.win32.registry.5.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\netstandard.library\\2.0.3\\netstandard.library.2.0.3.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\newtonsoft.json\\13.0.4\\newtonsoft.json.13.0.4.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\runtime.linux-arm.runtime.native.system.io.ports\\6.0.0\\runtime.linux-arm.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\runtime.linux-arm64.runtime.native.system.io.ports\\6.0.0\\runtime.linux-arm64.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\runtime.linux-x64.runtime.native.system.io.ports\\6.0.0\\runtime.linux-x64.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\runtime.native.system.io.ports\\6.0.0\\runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\runtime.osx-arm64.runtime.native.system.io.ports\\6.0.0\\runtime.osx-arm64.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\runtime.osx-x64.runtime.native.system.io.ports\\6.0.0\\runtime.osx-x64.runtime.native.system.io.ports.6.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\system.buffers\\4.5.1\\system.buffers.4.5.1.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\system.io.ports\\6.0.0\\system.io.ports.6.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\system.memory\\4.5.4\\system.memory.4.5.4.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\system.numerics.vectors\\4.4.0\\system.numerics.vectors.4.4.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\4.5.3\\system.runtime.compilerservices.unsafe.4.5.3.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\system.security.accesscontrol\\5.0.0\\system.security.accesscontrol.5.0.0.nupkg.sha512", + "C:\\Users\\Fairyland\\.nuget\\packages\\system.security.principal.windows\\5.0.0\\system.security.principal.windows.5.0.0.nupkg.sha512" + ], + "logs": [] +} \ No newline at end of file diff --git a/MedullaAdapter/parkingRobotRef/CommonUsage.dll b/MedullaAdapter/parkingRobotRef/CommonUsage.dll new file mode 100644 index 0000000..65e32b6 Binary files /dev/null and b/MedullaAdapter/parkingRobotRef/CommonUsage.dll differ diff --git a/MedullaAdapter/parkingRobotRef/MDCSToolBox.dll b/MedullaAdapter/parkingRobotRef/MDCSToolBox.dll new file mode 100644 index 0000000..d9cc740 Binary files /dev/null and b/MedullaAdapter/parkingRobotRef/MDCSToolBox.dll differ diff --git a/MedullaAdapter/parkingRobotRef/RefCartActivator.dll b/MedullaAdapter/parkingRobotRef/RefCartActivator.dll new file mode 100644 index 0000000..2755d6e Binary files /dev/null and b/MedullaAdapter/parkingRobotRef/RefCartActivator.dll differ diff --git a/MedullaAdapter/parkingRobotRef/RefFundamentalLib.dll b/MedullaAdapter/parkingRobotRef/RefFundamentalLib.dll new file mode 100644 index 0000000..cdebe2e Binary files /dev/null and b/MedullaAdapter/parkingRobotRef/RefFundamentalLib.dll differ diff --git a/MedullaAdapter/parkingRobotRef/RefMedullaCore.dll b/MedullaAdapter/parkingRobotRef/RefMedullaCore.dll new file mode 100644 index 0000000..99a9027 Binary files /dev/null and b/MedullaAdapter/parkingRobotRef/RefMedullaCore.dll differ diff --git a/MedullaAdapter/ref/CommonUsage.dll b/MedullaAdapter/ref/CommonUsage.dll new file mode 100644 index 0000000..9a9a9d6 Binary files /dev/null and b/MedullaAdapter/ref/CommonUsage.dll differ diff --git a/MedullaAdapter/ref/CycleGUI.dll b/MedullaAdapter/ref/CycleGUI.dll new file mode 100644 index 0000000..92e6ca7 Binary files /dev/null and b/MedullaAdapter/ref/CycleGUI.dll differ diff --git a/MedullaAdapter/ref/MDCSToolBox.dll b/MedullaAdapter/ref/MDCSToolBox.dll new file mode 100644 index 0000000..145980e Binary files /dev/null and b/MedullaAdapter/ref/MDCSToolBox.dll differ diff --git a/MedullaAdapter/ref/RefCartActivator.dll b/MedullaAdapter/ref/RefCartActivator.dll new file mode 100644 index 0000000..a43584d Binary files /dev/null and b/MedullaAdapter/ref/RefCartActivator.dll differ diff --git a/MedullaAdapter/ref/RefFundamentalLib.dll b/MedullaAdapter/ref/RefFundamentalLib.dll new file mode 100644 index 0000000..cdebe2e Binary files /dev/null and b/MedullaAdapter/ref/RefFundamentalLib.dll differ diff --git a/MedullaAdapter/ref/RefMedullaCore.dll b/MedullaAdapter/ref/RefMedullaCore.dll new file mode 100644 index 0000000..7ede8c7 Binary files /dev/null and b/MedullaAdapter/ref/RefMedullaCore.dll differ diff --git a/ParkingRobot.sln b/ParkingRobot.sln new file mode 100644 index 0000000..c85f18a --- /dev/null +++ b/ParkingRobot.sln @@ -0,0 +1,31 @@ +锘 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36811.4 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClumsyPilot", "ClumsyPilot\ClumsyPilot.csproj", "{324539E9-2DB3-EA2C-C43F-A9EC06D2861D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MedullaAdapter", "MedullaAdapter\MedullaAdapter.csproj", "{F805DBA5-87F5-3EDA-7FB3-DEAA36C0771F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {324539E9-2DB3-EA2C-C43F-A9EC06D2861D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {324539E9-2DB3-EA2C-C43F-A9EC06D2861D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {324539E9-2DB3-EA2C-C43F-A9EC06D2861D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {324539E9-2DB3-EA2C-C43F-A9EC06D2861D}.Release|Any CPU.Build.0 = Release|Any CPU + {F805DBA5-87F5-3EDA-7FB3-DEAA36C0771F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F805DBA5-87F5-3EDA-7FB3-DEAA36C0771F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F805DBA5-87F5-3EDA-7FB3-DEAA36C0771F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F805DBA5-87F5-3EDA-7FB3-DEAA36C0771F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F320445C-8B46-4DB3-B8C3-020CEF838343} + EndGlobalSection +EndGlobal