using System.Drawing; using System.Linq; using System.Threading; using System.Threading.Tasks; using Simple3.RCS; using Simple3.RCS.CarTypes; using SimpleCore; using SimpleCore.Compiler; using SimpleCore.Library; using SimpleCore.PropType; using StandardScene.Coders; namespace StandardScene.CarTypes { //钻车 [TemplateTrackCoderSettings( priority = 18, useVerb = "(dst.name=='FetchSite1'||dst.name=='FetchSite2')&&(plan.action=='fetch')", templateString = "agv.Wait();agv.TireFollowing(${plan.TireNum},${plan.FrontLidarDetect},${src.id},${dst.id},${plan.FirstTire});agv.Wait();", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] [TemplateTrackCoderSettings( priority = 18, useVerb = "(dst.name=='PutSite1'||dst.name=='PutSite2')&&(plan.action=='leave')", templateString = "agv.Wait();agv.TireFollowing(${plan.TireNum},${plan.FrontLidarDetect},${src.id},${dst.id},${plan.FirstTire});agv.Wait();", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] //离开时钻车(后出的那台车) [TemplateTrackCoderSettings( priority = 18, useVerb = "dst.name=='ReadyFetchSite'&&plan.action=='leave'&&plan.Reverse==true", templateString = "agv.Wait();agv.TireFollowing(${plan.TireNum},${plan.FrontLidarDetect},${src.id},${dst.id},${plan.FirstTire});agv.Wait();" + "agv.LineTracking(${src.id},${dst.id},${plan.LineDistance});agv.Wait()", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] //离开时直线行走(先出的那台车) [TemplateTrackCoderSettings( priority = 18, useVerb = "(dst.name=='LeaveSite'||dst.name=='ReadyFetchSite')&&plan.action=='leave'&&plan.Reverse==false", templateString = "agv.Wait();agv.LineTracking(${src.id},${dst.id},${plan.LineDistance});agv.Wait();", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] //下使能+夹抱+上使能 [TemplateSiteCoderSettings( priority = 18, useVerb = "((dst.name=='FetchSite1'||dst.name=='FetchSite2')&&plan.action=='clamp')", templateString = "agv.Wait();agv.DriverDisable();agv.Wait();agv.ClamptoTarget(${dst.ClampClose});agv.Wait();agv.DriverAble();", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] //抱夹打开 [TemplateSiteCoderSettings( priority = 18, useVerb = "(dst.name=='PutSite1'||dst.name=='PutSite2')&&plan.action=='put'", templateString = "agv.Wait();agv.DriverDisable();agv.Wait();agv.ClamptoTarget(${dst.ClampClose});agv.Wait();agv.DriverAble();", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] //临时夹抱动作 [TemplateSiteCoderSettings( priority = 18, useVerb = "plan.action=='templateclamp'||plan.action=='templateput'", templateString = "agv.Wait();agv.DriverDisable();agv.Wait();agv.ClamptoTarget(${plan.ClampClose});agv.Wait();agv.DriverAble();", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] [TemplateTrackCoderSettings( priority = 2, useVerb = "plan.action=='fetch'", templateString = "agv.BasicGo(${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id}," + "${track.id},${track.Speed},${track.Reverse||plan.Reverse}," + "${track.CarDirectionBias},${track.EnableCarAbsoluteDirection},${track.CarAbsoluteDirection},${track.MagnetChoose},${track.MultiVehicleSync},${track.typeInfo});", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] //[TemplateTrackCoderSettings( // priority = 3, // useVerb = "plan.action=='leave'&&(dst.name=='KeepDirectionSite1'||dst.name=='KeepDirectionSite2')", // templateString = "agv.BasicGo(${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id}," + // "${track.id},${track.Speed},${track.Reverse||plan.Reverse}," + // "${track.CarDirectionBias},${track.EnableCarAbsoluteDirection},${track.CarAbsoluteDirection},${track.MagnetChoose},${track.MultiVehicleSync},${track.typeInfo});", // blockVerb = "true", // siteFields = typeof(MultiWheelLifterSiteFields), // trackFields = typeof(MultiWheelLifterTrackFields), // planFields = typeof(MultiWheelLifterPlanFields))] [TemplateTrackCoderSettings( priority = 3, useVerb = "plan.action=='leave'", templateString = "agv.BasicGo(${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id}," + "${track.id},${track.Speed},${track.Reverse||plan.Reverse}," + "${track.CarDirectionBias},${track.EnableCarAbsoluteDirection},${track.CarAbsoluteDirection},${track.MagnetChoose},${track.MultiVehicleSync},${track.typeInfo});", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] [TemplateTrackCoderSettings( priority = 19, useVerb = "dst.tag>0 && src.tag>0", templateString = "agv.QrGo(${src.x},${src.y},${src.id},${src.tag},${dst.x},${dst.y},${dst.id},${dst.tag},${track.id}," + "${track.Speed},${track.Reverse || (track.ReverseDst == dst.id)}," + "${track.CarDirectionBias},${track.EnableCarAbsoluteDirection},${track.CarAbsoluteDirection}," + "${track.typeInfo});", blockVerb = "true", siteFields = typeof(MultiWheelLifterSiteFields), trackFields = typeof(MultiWheelLifterTrackFields), planFields = typeof(MultiWheelLifterPlanFields))] // 通用避障/IO coder 已抽离为 StandardScene.Coders.*(见类前 [ProgramTrackCoderSettings] 引用) // 避障区尺寸(4参,含中心点)切换 coder 已抽离为 StandardScene.Coders.AvoidanceParamCoder(见类前 [ProgramTrackCoderSettings] 引用) // 纠偏阈值 coder 已抽离为 StandardScene.Coders.TrackingErrThreshCoder [ProgramTrackCoderSettings(priority = 27, program = typeof(LidarAreaSwitchCoder))] [ProgramTrackCoderSettings(priority = 20, program = typeof(AvoidanceDistanceCoder))] [ProgramTrackCoderSettings(priority = 20, program = typeof(IoAreaSwitchCoder))] [ProgramTrackCoderSettings(priority = 20, program = typeof(TrackingErrThreshCoder))] [ProgramTrackCoderSettings(priority = 20, program = typeof(AvoidanceParamCoder))] [EnvelopConfig(lengthX = 2000, lengthY = 2000, centerX = 0, centerY = 0)] [CarType(Name = "多车联动AGV")] public class MultiVehicleCar : GhostCar { [FieldMember] public float CarLength = 2000; [FieldMember] public float CarWidth = 1400; public static async Task Create() { var car = new MultiVehicleCar() { lstatus = "连接中", address = "127.0.0.1", name = "联动AGV" }; return car; } protected override void draw(Graphics eGraphics) { var HalfCarLength = CarLength / 2; var HalfCarWidth = CarWidth / 2; eGraphics.FillRectangle(Brushes.Gray, -HalfCarLength, -HalfCarWidth, HalfCarLength * 2, HalfCarWidth * 2); eGraphics.DrawRectangle(Pens.White, -HalfCarLength, -HalfCarWidth, HalfCarLength * 2, HalfCarWidth * 2); eGraphics.DrawLine(Pens.White, HalfCarLength - HalfCarWidth, -HalfCarWidth, HalfCarLength, 0); eGraphics.DrawLine(Pens.White, HalfCarLength - HalfCarWidth, HalfCarWidth, HalfCarLength, 0); } [MethodMember(Name = "模拟车联动初始化")] public void GhostMultiAgvSyncInit() { var car1 = (GhostCar)SimpleLib.GetAllCars().First(cc => cc.name == "sync-1"); while (true) { car1.ManualTeleport(); car1.x = 1770; car1.y = 0; car1.th = 0; Thread.Sleep(100); if (LessMath.dist(car1.x, car1.y, 1770, 0) < 1 && car1.th == 0) break; } car1.NoSchedule(); car1.siteID = -1; car1.tags.Clear(); car1.status.usage.AddUsage("base", new CarUsage.CarUsageInfo() { scheduling = false, refreshing = false }); car1.fields["MultiVehicleSync"] = "True"; var car2 = (GhostCar)SimpleLib.GetAllCars().First(cc => cc.name == "sync-2"); while (true) { //car2.ManualTeleport(-750, 0, 180); car2.ManualTeleport(); car2.x = -750; car2.y = 0; car2.th = 180; Thread.Sleep(100); if (LessMath.dist(car2.x, car2.y, -750, 0) < 1 && car2.th == 180) break; } var car2Site = SimpleLib.GetAllSites().OrderBy(ss => LessMath.dist(ss.x, ss.y, car2.x, car2.y)).First(); var syncInitSite = SimpleLib.GetSite(int.Parse(car2Site.fields["SyncInitId"])); car2.TrafficReset(syncInitSite); car2.siteID = syncInitSite.id; car2.fields["MultiVehicleSync"] = "True"; } [MethodMember(Name = "进入联动状态")] public void StartMultiAgvSync() { var car1 = (Car)SimpleLib.GetAllCars().First(cc => cc.name == "sync-1"); car1.NoSchedule(); car1.siteID = -1; car1.tags.Clear(); car1.status.usage.AddUsage("base", new CarUsage.CarUsageInfo() { scheduling = false, refreshing = false }); car1.fields["MultiVehicleSync"] = "True"; var car2 = (Car)SimpleLib.GetAllCars().First(cc => cc.name == "sync-2"); var car2Site = SimpleLib.GetAllSites().OrderBy(ss => LessMath.dist(ss.x, ss.y, car2.x, car2.y)).First(); var syncInitSite = SimpleLib.GetSite(int.Parse(car2Site.fields["SyncInitId"])); car2.TrafficReset(syncInitSite); car2.siteID = syncInitSite.id; car2.fields["MultiVehicleSync"] = "True"; } [MethodMember(Name = "退出联动状态")] public void ExitMultiAgvSync() { var car1 = (Car)SimpleLib.GetAllCars().First(cc => cc.name == "sync-1"); car1.fields["MultiVehicleSync"] = "False"; car1.Reset(); var car2 = (Car)SimpleLib.GetAllCars().First(cc => cc.name == "sync-2"); car2.fields["MultiVehicleSync"] = "False"; car2.Reset(); } //[MethodMember(Name = "返厂检修new", Description = "不再刷新小车状态,当然也不再被调度")] //[I18N.DocumentTranslation(Name = "Blown new", Description = "Car no longer refresh status and scheduling", locale = "en")] public new void Blown() { AppendDebug("ui-blown"); Diagnosis.Post($"Car {name}({id}) blown"); NoSchedule(); siteID = -1; tags.Clear(); status.usage.AddUsage( "base", new CarUsage.CarUsageInfo { scheduling = false, refreshing = false } ); lstatus = "返厂检修"; } } }