From 583a7d00ca9be6332b6b0a9fbd9c5db915076862 Mon Sep 17 00:00:00 2001 From: shenyuxiang Date: Tue, 28 Jul 2026 18:38:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=95=E5=85=A5=E6=9C=80=E7=9F=AD=E8=88=B5?= =?UTF-8?q?=E8=A7=92=E8=A1=8C=E9=A9=B6=E7=9A=84CommonUsage=E5=B9=B6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=A1=B9=E7=9B=AE=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- ClumsyPilot/ClumsyPilot.csproj | 6 +- ClumsyPilot/build/Clumsy/ClumsyPilot.dll | Bin 26624 -> 52736 bytes ClumsyPilot/build/Clumsy/ClumsyPilot.pdb | Bin 14224 -> 21032 bytes ClumsyPilot/build/Clumsy/CommonUsage.dll | Bin 134144 -> 140288 bytes .../obj/Debug/ClumsyPilot.AssemblyInfo.cs | 2 +- .../ClumsyPilot.AssemblyInfoInputs.cache | 2 +- ....GeneratedMSBuildEditorConfig.editorconfig | 2 +- .../obj/Debug/ClumsyPilot.assets.cache | Bin 1890 -> 1890 bytes ...ClumsyPilot.csproj.AssemblyReference.cache | Bin 54987 -> 58857 bytes ...ClumsyPilot.csproj.CoreCompileInputs.cache | 2 +- ClumsyPilot/obj/Debug/ClumsyPilot.dll | Bin 52736 -> 52736 bytes ClumsyPilot/obj/Debug/ClumsyPilot.pdb | Bin 21024 -> 21032 bytes .../commonusage/.gitattributes | 2 + .../commonusage/.gitignore | 362 ++++++ .../commonusage/Chassis/AbstractChassis.cs | 126 ++ .../commonusage/Chassis/DiffSteerWheel.cs | 47 + .../Chassis/DifferentialChassis.cs | 170 +++ .../commonusage/Chassis/MultiWheelChassis.cs | 1083 +++++++++++++++++ .../commonusage/Chassis/SingleSteerChassis.cs | 172 +++ .../commonusage/Chassis/SteerWheel.cs | 100 ++ .../commonusage/Chassis/Wheel.cs | 56 + .../commonusage/CommonUsage.csproj | 48 + .../commonusage/CommonUsageSln.sln | 25 + .../commonusage/Deps/RefFundamentalLib.dll | Bin 0 -> 11776 bytes .../Geometries/AbstractGeometry.cs | 93 ++ .../commonusage/Geometries/BezierCurve.cs | 334 +++++ .../commonusage/Geometries/CircularArc.cs | 256 ++++ .../commonusage/Geometries/NurbsCurve.cs | 349 ++++++ .../commonusage/Geometries/Vectoriel.cs | 71 ++ .../commonusage/Mathematics/CommonMath.cs | 774 ++++++++++++ .../commonusage/Mathematics/LineSegment.cs | 161 +++ .../Properties/launchSettings.json | 12 + .../VDA5050/CommunicationProtocolFactory.cs | 19 + .../Protocols/VDA5050/HTTPCommunication.cs | 94 ++ .../VDA5050/IVDACommunicationProtocol.cs | 19 + .../Protocols/VDA5050/MQTTCommunication.cs | 319 +++++ .../VDA5050/Messages/connectionMessage.cs | 18 + .../VDA5050/Messages/errorMessage.cs | 16 + .../VDA5050/Messages/factsheetMessage.cs | 23 + .../VDA5050/Messages/instanceAction.cs | 19 + .../VDA5050/Messages/orderMessage.cs | 27 + .../VDA5050/Messages/stateMessage.cs | 69 ++ .../VDA5050/Messages/visualizationMessage.cs | 12 + .../Protocols/VDA5050/Objects/action.cs | 18 + .../Protocols/VDA5050/Objects/actionState.cs | 45 + .../Protocols/VDA5050/Objects/agvGeometry.cs | 63 + .../Protocols/VDA5050/Objects/agvPosition.cs | 21 + .../Protocols/VDA5050/Objects/batteryState.cs | 15 + .../VDA5050/Objects/boundingBoxReference.cs | 14 + .../Protocols/VDA5050/Objects/controlPoint.cs | 21 + .../Protocols/VDA5050/Objects/edge.cs | 31 + .../Protocols/VDA5050/Objects/edgeState.cs | 15 + .../VDA5050/Objects/errorReference.cs | 12 + .../Protocols/VDA5050/Objects/errorState.cs | 15 + .../Protocols/VDA5050/Objects/info.cs | 26 + .../Protocols/VDA5050/Objects/load.cs | 16 + .../VDA5050/Objects/loadDimensions.cs | 13 + .../Protocols/VDA5050/Objects/node.cs | 17 + .../Protocols/VDA5050/Objects/nodePosition.cs | 36 + .../Protocols/VDA5050/Objects/nodeState.cs | 26 + .../VDA5050/Objects/physicalParameters.cs | 20 + .../VDA5050/Objects/protocolFeatures.cs | 10 + .../VDA5050/Objects/protocolLimits.cs | 10 + .../Protocols/VDA5050/Objects/safetyState.cs | 20 + .../Protocols/VDA5050/Objects/sequenceItem.cs | 13 + .../Protocols/VDA5050/Objects/trajectory.cs | 15 + .../VDA5050/Objects/typeSpecification.cs | 15 + .../Protocols/VDA5050/Objects/velocity.cs | 15 + .../Protocols/VDA5050/VDA5050Basic.cs | 118 ++ .../Protocols/VDA5050/VDA5050Helper.cs | 11 + .../commonusage/Visualizer.cs | 28 + MedullaAdapter/MedullaAdapter.csproj | 8 +- .../build/Medulla/plugins/CommonUsage.dll | Bin 0 -> 140288 bytes .../Medulla/plugins/MedullaAdapter.deps.json | 16 + .../build/Medulla/plugins/MedullaAdapter.dll | Bin 60416 -> 60416 bytes .../build/Medulla/plugins/MedullaAdapter.pdb | Bin 30144 -> 30152 bytes Shared/MultiWheelChassisAdapter.cs | 4 + ref/CommonUsage.dll | Bin 0 -> 140288 bytes 78 files changed, 5585 insertions(+), 12 deletions(-) create mode 100644 CommonUsage-MultiVehicleSync/commonusage/.gitattributes create mode 100644 CommonUsage-MultiVehicleSync/commonusage/.gitignore create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Chassis/AbstractChassis.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Chassis/DiffSteerWheel.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Chassis/DifferentialChassis.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Chassis/MultiWheelChassis.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Chassis/SingleSteerChassis.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Chassis/SteerWheel.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Chassis/Wheel.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/CommonUsage.csproj create mode 100644 CommonUsage-MultiVehicleSync/commonusage/CommonUsageSln.sln create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Deps/RefFundamentalLib.dll create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Geometries/AbstractGeometry.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Geometries/BezierCurve.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Geometries/CircularArc.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Geometries/NurbsCurve.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Geometries/Vectoriel.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Mathematics/CommonMath.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Mathematics/LineSegment.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Properties/launchSettings.json create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/CommunicationProtocolFactory.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/HTTPCommunication.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/IVDACommunicationProtocol.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/MQTTCommunication.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/connectionMessage.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/errorMessage.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/factsheetMessage.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/instanceAction.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/orderMessage.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/stateMessage.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/visualizationMessage.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/action.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/actionState.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/agvGeometry.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/agvPosition.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/batteryState.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/boundingBoxReference.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/controlPoint.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/edge.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/edgeState.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/errorReference.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/errorState.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/info.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/load.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/loadDimensions.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/node.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/nodePosition.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/nodeState.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/physicalParameters.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/protocolFeatures.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/protocolLimits.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/safetyState.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/sequenceItem.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/trajectory.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/typeSpecification.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/velocity.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/VDA5050Basic.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/VDA5050Helper.cs create mode 100644 CommonUsage-MultiVehicleSync/commonusage/Visualizer.cs create mode 100644 MedullaAdapter/build/Medulla/plugins/CommonUsage.dll create mode 100644 ref/CommonUsage.dll diff --git a/ClumsyPilot/ClumsyPilot.csproj b/ClumsyPilot/ClumsyPilot.csproj index ceb2716..2553db3 100644 --- a/ClumsyPilot/ClumsyPilot.csproj +++ b/ClumsyPilot/ClumsyPilot.csproj @@ -21,9 +21,6 @@ - - ref\CommonUsage.dll - ref\LessokajiWeaverUtilities.dll @@ -39,6 +36,9 @@ ref\RefFundamentalLib.dll + + ..\ref\CommonUsage.dll + diff --git a/ClumsyPilot/build/Clumsy/ClumsyPilot.dll b/ClumsyPilot/build/Clumsy/ClumsyPilot.dll index 3d485444778fa71617469c3bb4f5cfd8596704f7..bf4e1816df53392283a93ce5ae2bee990bf2a4e1 100644 GIT binary patch literal 52736 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 delta 12850 zcma)i3w%>mw*ERhrzejlAxYaLErnuo#71U79uBjd4i}?4~v2Nbfv#z?QKwnaLv$HD7p4_ zNF1+?r;ndx8ICnkqNnV}XG`qaqfET)m> zO^XkMIK;^k`rtS(3Y37XBaQs7PiqOrBcLz*-KRZ#>Ulo~pl93z1s%Vr3D&rbZY{|4 zS&is6^4hfcNH!(tMv(rhW0P`)ep7lRV76r7#Vr}7uTKvtBlNxL*DJ-k>I}`f65b9C zy-v6Ovd@~cfNc3g%tj!?j{HF_S0Huqt60uyDK&0od|N^-&}w;>L^fv)$#rA~TE^lQ z!Jr{ieMIDHz0;YMyaqIH@i<@tW9!HhZJF>$RInWR6|n6(F1x;)k7quin`5Fm5)-@m zB<7R5`4r}r-TX%8Q%#;k1vjx`TDQS;<~MiqUo*d@o8QX(wr*agIEqH+Sx(yX;`{_@(nB+&~XV#-oOS^R9l0eLvBtooce)poj^pi#%+!qp-1hyD8e*>0!e+YSnmVO0VWC<6FHnuc1OIc%dLZxl! z0y61^30L5>4eUqFe?=w!$X&3DEF(%f9L+ynq;aHEL4(p4ABaLB=j71Q_rpB~n z>;>AJTJAv`FgY+hDq)=vs_{~@-9k;x*?`EsD0j4sk!^@92T9~`3l?LF8e@S8ivh$8 zzAzRjNg9KZ+P3b!Lgqdn6$%O{s1ZMI)t%*u2sgjahKC;>ofsg+qrbm?bOL#Ymdz3c z-Qqw~ymm~YP>RxRkfBY|OJfq3nHK+EmKbb`?N=p=Op!_xcr3`kp|S)X1rSl)m5CB5 zIzGxBl^A-#mJ-^d+#VLabnMloX>ZVn|it zPhjJf?r)7rV273BmeNEii;)#bHRa1$$C)bQ{^Q4qc%?i6D$VDVConWB<~jzLLt@{> z?drsh2F2FMg;=l%d7lh6XvSjs?y2?{)xb&Y!dGkUfEN2xKoRa4kZM;`4;-%2G3eA>>gU9j$7xdUc)V9^# z1wpfb7fq@|cB;PHKC%X`k+lFUL9VHdcfLp`6c=i^5Ga*%0D~tNb=71VNX`a+f3`n< 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 ASO5S3 diff --git a/ClumsyPilot/build/Clumsy/ClumsyPilot.pdb b/ClumsyPilot/build/Clumsy/ClumsyPilot.pdb index fc4ea1fdbd2ba68827f26bc6ae414a0ee8f2b2a6..f62506fa02879a069c3af3e2543797492a7bd391 100644 GIT binary patch delta 9619 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 diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs index 1f11488..79a3c54 100644 --- a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs @@ -13,7 +13,7 @@ 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+e6b99c45b352f24ff58092f7855d0eadd8828d42")] +[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")] diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache index 29381a2..8fb9fb2 100644 --- a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache @@ -1 +1 @@ -3e5507bf56e38facdc245d5ff407e181c060d8094f38b94ad743b8c3305523f2 +5d77794fa0720c6591db5b06ac60427413c18989a6f7b64420ccb07d122d85bc diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig b/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig index f169771..a3aa451 100644 --- a/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig @@ -1,6 +1,6 @@ is_global = true build_property.RootNamespace = MultiWheelC -build_property.ProjectDir = d:\MyParking\ClumsyPilot\ +build_property.ProjectDir = D:\Users\Desktop\入职培训\停车机器人\MyParking\ClumsyPilot\ build_property.EnableComHosting = build_property.EnableGeneratedComInterfaceComImportInterop = build_property.CsWinRTUseWindowsUIXamlProjections = false diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.assets.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.assets.cache index 9dedb7e4d2f5865fe1e73aebfa765250805ce842..3d28e6fb1b5b420d1ca767798115b725bd6c3ced 100644 GIT binary patch delta 49 zcmV-10M7s74&n|dP)kQa3;+NC@HzeA-&3!0r8Q+hU=vEt*yPups$yDEymP>{bk|}j Hu_!tR4a*i6 delta 49 zcmV-10M7s74&n|dP)kQa3;+NC{0%vo^c*(66g@ziEe-r0d^yefJBU8brIU=lxI59W Hu_!tR!CDjV diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.AssemblyReference.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.AssemblyReference.cache index 787d0262596f00dec0234cd46ef4759a10173abf..0de62a8391c8679862129e5f33afca6e44e5732a 100644 GIT binary patch delta 2900 zcmcImU2GIp6yCGj-5Ru{Xed>xtbr&YbS$YfwI(9j?E}?mmu@RyR>*btQikr%Y-a8j zH#{IwdE#ZAXo4Z3#t6PF5+D$3jBok?BoOR_1RhK*sX-GB@xcehbMO3goF8qQc#=Jt zy>rfY&;OY#&BRYv5?fPHkHun8$_^C94XPW3EHx&XRxQlE_v!r6<8!CJm_OSr%pE;B z|JCWcCuinPeD>qajCl>#Htv6$1VCN0Kb1CjK-&>~j`0KJ4kzjsLv*&i$doCKUQVneB}8fWi;Uv{WmXNd_fH z)^#q(SjIb&=AoALJWu@|0iLI!N6W`MzQ42HJx0it`2$3+W_L@wcc|4G1L2JM5_G0r zDJ#hrZ~uCK@A%WdxyOy|-O(0&7vKD>D;eU*NR_IYDRDRYEO|t^p$Bi>m~Z`S`h9g;sL_y81kN;k66UE)#ZO zm@;X&R>6c94M=j;Xm3Bdxq-*qkKNN8xqJTf*S(~WmYYL+f=hzFi zW<~q=x2JO*_nIGjRXaRElLp^nR5cV$H86huh786};4G~n_bj;~*P55&(@8NBmerIp zw~|v>_k=a&6Lz9U>Hads9@11vri_#bBUZ}N0*x~(tN{?yPF-4vaApYxQfGF-z%pts z#gpq#PjFrWJSi(hT{E=(Ov)-`Le&h0g(r>HRHjt0NYF6;OX2U2GstWTi`15{`(JDJ z4R7TlVlX)Kz;8!z9tf4CmC5VND3f;+pZv2-(ypym_yZ9#aiDa0g!m&TXNGns&h4GdWBq4#9 zIkUm*T+}FTvm+?eil*1ab`tg?^R8UKhf#2yZp?O3Vs3^_UK=ta^Xq>DsOEHs delta 141 zcmaEPn)&ovW-d0yN(Kf7Mx7L^$!FQ6rJVC~bMx~;ixbmR^-^+j7#V?*Qqz`O+;}$G zOsH-0(g_00mJp>A1CE2aP@R*XF)je}^}y1*!EAjnTV?V-?pa{I5tuKxIh;R{5hO4< M@_g`SE7A2A0EVG6y#N3J diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.CoreCompileInputs.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.CoreCompileInputs.cache index 7c7bf92..d102794 100644 --- a/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.CoreCompileInputs.cache +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -e5afef3021b83202643b31f468b83ac62f224cd367fe52dc0a1cbb98570c91e1 +e972a413d047c4137a8ce86cbff54a8d2e2558806d9d974d3d6312467ee8ba4d diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.dll b/ClumsyPilot/obj/Debug/ClumsyPilot.dll index 883712377cd22bd376299e1de9280699b24d9efe..bf4e1816df53392283a93ce5ae2bee990bf2a4e1 100644 GIT binary patch delta 12862 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 PdPep*UjAI!T5kD2AK5|J delta 12909 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 delta 1347 zcmY+Ce@q)?7{|Zw-Er50@@xDUbtpw>=@sY-l(w`Wb!-l2jKf5N%3^24O*duX57Ft; z!;EB_{b0E$#<|!TqziLNyDDZ@P5;2e84X4^%`~#hoD!Fy(<~$lYJBeKG+y%gKHukg z-sgF9$$N5&#i!WB9{a{Fpl-wN;YR@+9$pd;-}t*Hr5$|Z>QqVJ&x;%0KRV%JOR2N3 zu-G?sR&1=dqMz7F+~TkzK`c5Lek1yv36DI(g{CqFLi1xQrf;`dsYJ z#i3jrck!6a`762Dq40P>LChQ+RaO_AQ3U)zJnk0oBXQkr)CJ@>3OG%iBfcZ{HwlOn zXNWoCbK*SlX|sSU&8suZ;dG0HcZm#f zjac6*;Ys2u;cAn>d=e&!%fxk`F=u={n%a46_G`7mx;)ArHl0lF6F-kT14iA*`U5=L zf;Y3?Adk6!vjxhIgl=xgn9fEs!(kqy;njPLn_`rgcN*u6uBVfSzw^KD9hAGfG$xd% zb>SVZ^l54}BOgUz^oPKX^l|AvOUq_w0VNFQoP}o0G!&aL;4U@egtyF$)7}a*9?)(r z(PCfJW%ER=ueXaL;E0eOazsflIUTWyx~mxin)VWj~U5fv_2B-mUL@{Obtd@hyz zJ){!)U0L!Yq!RYIAR8O(q%$tNEa8GHO8zz_O1@2r8{JrKmckAtOQm5&mo0cnLB5Ei zq!MOGEjXb>sPdpYO8TW+Cq32}DG;%%DNfNE#AhD z`tRPBUQ-q3tLDP9UqR(iV2zy`c&OsuLp_=Mx9;xQpB`GbQq6j`?ZHiDjC;<)#-8Pd zxUsJXis)siW7@~Tr<_wVLp5h91RXG6hI)!BHJrt2RMc1L)iCuvt*;}=E@@ooAj{W| zgt}R^HXj<4mf198)3 + /// 当前行进方向。 + /// + [Obsolete] + public float DirectionAngle + { + get => _originBiasTh; + set + { + _originBiasTh = value; + if (_originBiasTh != _lastDirectionAngle) AfterDirectionChanged(); + _lastDirectionAngle = _originBiasTh; + } + } + + protected float _originBiasX = 0f, _originBiasY = 0f, _originBiasTh; + + public Vector3 GetOriginBias() + { + return new Vector3(_originBiasX, _originBiasY, _originBiasTh); + } + + public class CarSpeed + { + public float Vx,Vy,Vw; + } + + public abstract CarSpeed GetCarSpeed(bool isActual = false); + public List GetGeometricControlPoints() + { + return GeometricControlPoints; + } + + public void ComputeWheelsGeometrically(float speed) + { + // 打印调用位置信息 + var stackTrace = new StackTrace(true); + var callerFrame = stackTrace.GetFrame(1); // 获取调用者的帧 + if (callerFrame != null) + { + var fileName = callerFrame.GetFileName(); + var lineNumber = callerFrame.GetFileLineNumber(); + DLog.Log($"s:{speed:0.000} from {fileName} ln.{lineNumber}", $"WheelComputeCaller"); + } + + DefineGeometricWheelComputation(speed); + } + + protected abstract void DefineGeometricWheelComputation(float speed); + + public void DriveStop() + { + PredefinedDriveStop(); + CustomDriveStop?.Invoke(); + } + + public abstract void PredefinedDriveStop(); + + public Action CustomDriveStop; + + public abstract bool ComputeRotateWheels(float rotSpeed); + + public abstract float CalculateTurningSpeedDecayFac(float turn); + + public enum ChassisState + { + Standby, + Running, + AbnormalFeedback, + ExceedMotionAbility, + } + + protected ChassisState State; + + protected string StateDescription; + + public (ChassisState State, string Description) GetChassisState() + { + return (State, StateDescription); + } + + public bool Debug = false; + public float AccPerSecond = 0.2f; + public float DeAccPerSecond = 0.2f; + public float MaxSpeed = 1; // m/s + public float MinTurnSpeedFac = 0.5f; + public float MaxTurnThreshold = 90f; + + public float GcpThetaPerSecond = 10f; + + public DateTime LastMoveTime = DateTime.MinValue; + + protected bool Valid = false; + protected List GeometricControlPoints = new(); + protected bool RotatingActive = false; + protected bool GoingActive = false; + protected bool GoingWheelAligned = false; + + private float _lastDirectionAngle = 0; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Chassis/DiffSteerWheel.cs b/CommonUsage-MultiVehicleSync/commonusage/Chassis/DiffSteerWheel.cs new file mode 100644 index 0000000..4f179ae --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Chassis/DiffSteerWheel.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Text; + +namespace CommonUsage.Chassis +{ + public class DiffSteerWheel:SteerWheel + { + public DiffSteerWheel(float wheelDistance,Vector2 position, float angleLowerLimit, float angleUpperLimit, Action speedWriter, + Func speedReader, Action angleWriter, Func angleReader, Action leftSpeedWriter, Action rightSpeedWriter, + float angleLimitMarginDeg = 15f) : base(position, + angleLowerLimit, angleUpperLimit, speedWriter, speedReader, angleWriter, angleReader, angleLimitMarginDeg) + { + _leftSpeedWriter = leftSpeedWriter; + _rightSpeedWriter = rightSpeedWriter; + WheelDistance = wheelDistance; + } + + public float GetLeftSendSpeed() + { + return _leftSendSpeed; + } + + public float GetRightSendSpeed() + { + return _rightSendSpeed; + } + + public void WriteLeftSpeed(float speed) + { + _leftSpeedWriter(_leftSendSpeed = speed); + } + + public void WriteRightSpeed(float speed) + { + _rightSpeedWriter(_rightSendSpeed = speed); + } + + public float WheelDistance; + private readonly Action _leftSpeedWriter; + private readonly Action _rightSpeedWriter; + + private float _leftSendSpeed; + private float _rightSendSpeed; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Chassis/DifferentialChassis.cs b/CommonUsage-MultiVehicleSync/commonusage/Chassis/DifferentialChassis.cs new file mode 100644 index 0000000..e6a7279 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Chassis/DifferentialChassis.cs @@ -0,0 +1,170 @@ +using FundamentalLib; +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Text; +using System.Diagnostics; + +namespace CommonUsage.Chassis +{ + public class DifferentialChassis : AbstractChassis + { + public void SetLeftRightWheels(Wheel wheelL, Wheel wheelR) + { + _leftWheel = wheelL; + _rightWheel = wheelR; + _halfWheelTrack = Math.Abs(_leftWheel.Position.Y); + } + + public override void Visualize() + { + + } + + public override CarSpeed GetCarSpeed(bool isActual = false) + { + if (!isActual) + { + return new CarSpeed() + { + Vx = (_speedL + _speedR) / 2f, + Vw = (_speedR - _speedL) / Math.Abs(_leftWheel.Position.Y - _rightWheel.Position.Y) / + (float)Math.PI * 180f * 1000f, + Vy = 0 + }; + } + else + { + return new CarSpeed() + { + Vx = GetLinearSpeed(), + Vw = (_rightWheel.ReadSpeed() - _leftWheel.ReadSpeed()) / + Math.Abs(_leftWheel.Position.Y - _rightWheel.Position.Y) / + (float)Math.PI * 180f * 1000f, + Vy = 0 + }; + } + + } + + public (Wheel,Wheel) GetWheels() + { + return (_leftWheel, _rightWheel); + } + + public float GetLinearSpeed() + { + return (_leftWheel.ReadSpeed() + _rightWheel.ReadSpeed()) / 2f; + } + + public override void Initialize() + { + GeometricControlPoints.Add(new GeometricControlPoint(new Vector2(0, 0))); + Valid = true; + } + + public override void AfterDirectionChanged() + { + + } + + public override void PredefinedDriveStop() + { + if (!Valid) return; + _sendSpeedL = _sendSpeedR = 0; + _speedL = _speedR = 0; + _leftWheel.WriteSpeed(_sendSpeedL); + _rightWheel.WriteSpeed(_sendSpeedR); + GoingActive = false; + RotatingActive = false; + } + + protected override void DefineGeometricWheelComputation(float speed) + { + var now = DateTime.Now; + if (!GoingActive) LastMoveTime = now; + + SendSpeed(speed, GeometricControlPoints[0].Theta, now - LastMoveTime); + + GoingActive = true; + RotatingActive = false; + } + + public override bool ComputeRotateWheels(float rotSpeed) + { + if (!RotatingActive) LastMoveTime = DateTime.Now; + + SendSpeed(0, rotSpeed); + + GoingActive = false; + RotatingActive = true; + return true; + } + + public override float CalculateTurningSpeedDecayFac(float turn) + { + return 1 - Math.Min(turn, MaxTurnThreshold) / MaxTurnThreshold * MinTurnSpeedFac; + } + + public void SendSpeed(float linearSpeed, float angularSpeed, TimeSpan? deltaTime = null) + { + var edgeLinearSpeed = (float)(angularSpeed / 180f * Math.PI * _halfWheelTrack / 1000); + var vl = linearSpeed - edgeLinearSpeed; + var vr = linearSpeed + edgeLinearSpeed; + _speedL = vl; + _speedR = vr; + AccumulateSpeed(vl, vr, deltaTime); + LastMoveTime = DateTime.Now; + } + + private void AccumulateSpeed(float vl, float vr, TimeSpan? deltaTime = null) + { + // var dTime = (float)(deltaTime ?? DateTime.Now - LastMoveTime).TotalSeconds; + // + // var speedSignL = Math.Sign(vl - _sendSpeedL); + // var accL = Math.Abs(vl) > Math.Abs(_sendSpeedL) ? AccPerSecond : DeAccPerSecond; + // _sendSpeedL += speedSignL * Math.Min(Math.Abs(vl - _sendSpeedL), accL * dTime); + // _leftWheel.WriteSpeed(_sendSpeedL); + // + // var speedSignR = Math.Sign(vr - _sendSpeedR); + // var accR = Math.Abs(vr) > Math.Abs(_sendSpeedR) ? AccPerSecond : DeAccPerSecond; + // _sendSpeedR += speedSignR * Math.Min(Math.Abs(vr - _sendSpeedR), accR * dTime); + // _rightWheel.WriteSpeed(_sendSpeedR); + + // if (Debug) + // Console.WriteLine($"DiffChassis, target:{v:0.00},send:{_sendSpeed:0.0}"); + // var dTime = (float)(deltaTime ?? DateTime.Now - LastMoveTime).TotalSeconds; + var dTime = (float)(deltaTime ?? DateTime.Now - LastMoveTime).TotalSeconds; + float diffL = vl - _sendSpeedL; + float diffR = vr - _sendSpeedR; + + float accL = Math.Abs(vl) > Math.Abs(_sendSpeedL) ? AccPerSecond : DeAccPerSecond; + float accR = Math.Abs(vr) > Math.Abs(_sendSpeedR) ? AccPerSecond : DeAccPerSecond; + + float maxDeltaL = accL * dTime; + float maxDeltaR = accR * dTime; + + float factorL = Math.Abs(diffL) > maxDeltaL ? maxDeltaL / Math.Abs(diffL) : 1.0f; + float factorR = Math.Abs(diffR) > maxDeltaR ? maxDeltaR / Math.Abs(diffR) : 1.0f; + + float factor = Math.Min(factorL, factorR); + + _sendSpeedL += diffL * factor; + _sendSpeedR += diffR * factor; + + _leftWheel.WriteSpeed(_sendSpeedL); + _rightWheel.WriteSpeed(_sendSpeedR); + // Console.WriteLine($"DiffChassis, target:{vl:0.00},send:{_sendSpeedL:0.00} dTime:{dTime} diffL:{diffL} factor:{factor}" ); + } + + private Wheel _leftWheel; + private Wheel _rightWheel; + private float _halfWheelTrack; // millimeter + + private float _sendSpeedL; + private float _sendSpeedR; + private int _direction = 1; // 1 forward, -1 backward + private float _speedL; + private float _speedR; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Chassis/MultiWheelChassis.cs b/CommonUsage-MultiVehicleSync/commonusage/Chassis/MultiWheelChassis.cs new file mode 100644 index 0000000..fa96e28 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Chassis/MultiWheelChassis.cs @@ -0,0 +1,1083 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Diagnostics; +using System.Text; +using CommonUsage.Mathematics; +using FundamentalLib; +using System.Drawing; + +namespace CommonUsage.Chassis +{ + public class MultiWheelChassis : AbstractChassis + { + public float ThConsistentThreshold = 1.0f; + + public float ControlPointRadius = 500f; + + // 原地旋转纠偏钳位:SendRotateMotion 中每轮纠偏速度幅值不超过 该比例×本轮旋转切向速度, + // 防止减速末段旋转切向变小时纠偏盖过它、使轮向矢量乱摆(频繁打方向/卡死)。<0 关闭钳位。 + public float RotateCompTangentFrac = 0.5f; + + // 上一次 SendRotateMotion 的舵轮对齐状态:false 表示舵轮未追上目标角(gate=0、车未真正转动)。 + // 供上层做积分抗饱和(卡死时冻结积分)。 + public bool LastRotateAligned { get; private set; } = true; + + public string LastMotionDecomposeFailureReason { get; private set; } = ""; + + // 为true时,在两个等价舵角都可用的情况下优先选择机械转动距离更小的方案。 + // 默认关闭以保持旧项目原有行为,由需要该策略的车型适配器主动开启。 + public bool PreferMinimumSteeringTravel { get; set; } + + public float MinimumTurningAngleForAckermann = 60f; + + + public MultiWheelChassis() : base() + { + + } + + public void AddWheel(SteerWheel wheel) + { + _steerWheels.Add(wheel); + } + + public override void Initialize() + { + _steerWheels = _steerWheels.OrderByDescending(sw => sw.Position.X).ToList(); + _targetSpeeds = new float[_steerWheels.Count].ToList(); + _sendSpeeds = new float[_steerWheels.Count].ToList(); + _tmpSpeeds = new float[_steerWheels.Count].ToList(); + _wheelDirs = Enumerable.Repeat(1, _steerWheels.Count).ToList(); + _sendAngle = new float[_steerWheels.Count].ToList(); + _debugSpeeds = new float[_steerWheels.Count].ToList(); + + if (_steerWheels.Count < 2) + { + Console.WriteLine($"steer wheel num: {_steerWheels.Count}. invalid!"); + Valid = false; + return; + } + + CalculateAxes(); + Valid = true; + } + + public Visualizer MainVisualizer = null; + + public override void Visualize() + { + MainVisualizer?.Clear(); + + if (_rotCenter != Vector2.Zero) + { + MainVisualizer?.DrawText(Color.Chartreuse, $"({_rotCenter.X:f1}, {_rotCenter.Y:f2})", _rotCenter); + } + + for (var i = 0; i < _steerWheels.Count; ++i) + { + var sw = _steerWheels[i]; + if (sw is DiffSteerWheel dsw) + { + var pointing = CommonMath.Transform2D(dsw.Position, dsw.ZeroDirection, new Vector2(200, 0)); + MainVisualizer?.DrawLine(Color.Gray, dsw.Position, pointing); + MainVisualizer?.DrawText(Color.Gray, $"{dsw.GetSendSpeed():f2} {sw.GetSendAngle():f2}", dsw.Position); + + var left = CommonMath.Transform2D(dsw.Position, dsw.GetAngleRelativeToChassis() + 90, new Vector2(dsw.WheelDistance, 0)); + MainVisualizer?.DrawLine(Color.GreenYellow, left, + CommonMath.Transform2D(left, dsw.GetAngleRelativeToChassis(), new Vector2(200, 0)), endArrow: true); + MainVisualizer?.DrawText(Color.GreenYellow, $"{dsw.GetLeftSendSpeed():0.00}", left); + + var right = CommonMath.Transform2D(dsw.Position, dsw.GetAngleRelativeToChassis() - 90, new Vector2(dsw.WheelDistance, 0)); + MainVisualizer?.DrawLine(Color.DeepPink, right, + CommonMath.Transform2D(right, dsw.GetAngleRelativeToChassis(), new Vector2(200, 0)), endArrow: true); + MainVisualizer?.DrawText(Color.DeepPink, $"{dsw.GetRightSendSpeed():0.00}", right); + } + else + { + MainVisualizer?.DrawLine(Color.Green, sw.Position, + CommonMath.Transform2D(sw.Position, sw.GetAngleRelativeToChassis(), new Vector2(200, 0)), endArrow: true); + MainVisualizer?.DrawText(Color.Chartreuse, $"{sw.GetSendSpeed():f2} {sw.GetAngleRelativeToChassis():f2}", sw.Position); + } + + if (_rotCenter != Vector2.Zero) + { + MainVisualizer?.DrawLine(Color.DodgerBlue, sw.Position, _rotCenter); + } + } + } + + public override void AfterDirectionChanged() + { + Hedingben.ToastText($"AfterDirectionChanged", "MultiWheelChassis-AfterDirectionChanged"); + + foreach (var sw in _steerWheels) + { + sw.Position = CommonMath.Transform2D(new Vector2(_originBiasX, _originBiasY), _originBiasTh, + sw.PhysicalPosition); + sw.ZeroDirection = _originBiasTh; + } + + CalculateAxes(); + GoingWheelAligned = false; + } + + protected override void DefineGeometricWheelComputation(float speed) + { + if (!GoingActive) ResetMotionState(); + var targetGcpTheta0 = GeometricControlPoints[0].Theta; + var targetGcpTheta1 = GeometricControlPoints[1].Theta; + var lastGcpTheta0Before = _lastGcpTheta0; + var lastGcpTheta1Before = _lastGcpTheta1; + + void Process(ref float current, float target, int id) + { + current += Math.Sign(target - current) * Math.Min(Math.Abs(target - current), + GcpThetaPerSecond * (float)(DateTime.Now - LastMoveTime).TotalSeconds); + // Hedingben.ToastText($"current:{current:0.00} target:{target:0.00}", $"gcp-accumulation-{id}"); + } + + Process(ref _lastGcpTheta0, GeometricControlPoints[0].Theta, 0); + Process(ref _lastGcpTheta1, GeometricControlPoints[1].Theta, 1); + if ((DateTime.Now - _geometricComputeLastLog).TotalMilliseconds >= 200) + { + _geometricComputeLastLog = DateTime.Now; + DLog.Log( + $"ComputeWheelsGeometrically speed:{speed:F3} " + + $"targetGcp:({targetGcpTheta0:F1},{targetGcpTheta1:F1}) " + + $"smoothBefore:({lastGcpTheta0Before:F1},{lastGcpTheta1Before:F1}) " + + $"smoothAfter:({_lastGcpTheta0:F1},{_lastGcpTheta1:F1}) " + + $"originBias:({_originBiasX:F1},{_originBiasY:F1},{_originBiasTh:F1}) goingActive:{GoingActive}", + "MultiWheelGoDiag"); + } + SendMotion(speed, _lastGcpTheta0, _lastGcpTheta1); + + GoingActive = true; + RotatingActive = false; + XYThActive = false; + } + + private float _lastGcpTheta0; + + private float _lastGcpTheta1; + + /// + /// 转速单位为度/s,逆时针为正。 + /// + /// + public override bool ComputeRotateWheels(float rotSpeed) + { + if (!RotatingActive) ResetMotionState(); + + var feasible = SendRotateMotion(rotSpeed); + + GoingActive = false; + RotatingActive = true; + XYThActive = false; + return feasible; + } + + public override void PredefinedDriveStop() + { + if (!Valid) return; + for (var i = 0; i < _steerWheels.Count; i++) + { + _sendSpeeds[i] = 0; + _debugSpeeds[i] = 0; + if (_steerWheels[i] is DiffSteerWheel dfw) + { + dfw.WriteLeftSpeed(0); + dfw.WriteRightSpeed(0); + } + else + { + _steerWheels[i].WriteSpeed(0); + } + } + GoingActive = false; + RotatingActive = false; + XYThActive = false; + } + + public void RampStop(TimeSpan? deltaTime = null) + { + if (!Valid) return; + + for (var i = 0; i < _steerWheels.Count; i++) + { + _debugSpeeds[i] = 0; + AccumulateSpeed(i, 0, false, Vector2.Zero, deltaTime); + } + + GoingActive = false; + RotatingActive = false; + XYThActive = false; + LastMoveTime = DateTime.Now; + } + + private struct WheelAngleCandidate + { + public bool Valid; + public float RawAngle; + public float NormalizedAngle; + public float Margin; + public int Direction; + public float Lower; + public float Upper; + } + + private WheelAngleCandidate BuildWheelAngleCandidate(SteerWheel sw, float rawAngle, int direction) + { + var lower = (float)CommonMath.RoundTh(sw.AngleLowerLimit); + var upper = (float)CommonMath.RoundTh(sw.AngleUpperLimit); + while (upper < lower) upper += 360; + + var normalized = (float)CommonMath.RoundTh(rawAngle); + while (normalized < lower) normalized += 360; + while (normalized > upper && normalized - 360 >= lower) normalized -= 360; + + var margin = Math.Min(normalized - lower, upper - normalized); + var marginRequired = Math.Max(0, sw.AngleLimitMarginDeg); + return new WheelAngleCandidate + { + Valid = normalized >= lower && normalized <= upper && margin >= marginRequired, + RawAngle = rawAngle, + NormalizedAngle = normalized, + Margin = margin, + Direction = direction, + Lower = lower, + Upper = upper + }; + } + + private bool TryResolveWheelAngle(int wheelIndex, float targetAngle, string entry, + out float angle, out int direction, out string reason) + { + var sw = _steerWheels[wheelIndex]; + var forward = BuildWheelAngleCandidate(sw, targetAngle, 1); + var reverse = BuildWheelAngleCandidate(sw, targetAngle + 180, -1); + + WheelAngleCandidate? selected = null; + + if (PreferMinimumSteeringTravel && + forward.Valid && + reverse.Valid) + { + var actualAngle = sw.ReadAngle(); + + if (!float.IsNaN(actualAngle) && + !float.IsInfinity(actualAngle)) + { + // 将反馈角映射到与候选角相同的机械限位区间。 + // 这里比较的是受限机械舵角,不能使用圆周最短角度差。 + var actual = BuildWheelAngleCandidate( + sw, + actualAngle, + 1); + var forwardError = Math.Abs( + forward.NormalizedAngle - + actual.NormalizedAngle); + var reverseError = Math.Abs( + reverse.NormalizedAngle - + actual.NormalizedAngle); + + // 迟滞避免两个方案转动量接近时频繁翻转轮速方向。 + const float switchHysteresisDegrees = 5f; + + if (reverseError + + switchHysteresisDegrees < + forwardError) + { + selected = reverse; + } + else if (forwardError + + switchHysteresisDegrees < + reverseError) + { + selected = forward; + } + } + } + + // 未启用最小转舵策略、反馈无效或两个候选差异落在迟滞区时, + // 保持旧版轮速方向,避免破坏其他车型的既有行为。 + if (_wheelDirs != null && wheelIndex < _wheelDirs.Count) + { + if (selected == null && + _wheelDirs[wheelIndex] < 0 && + reverse.Valid) + { + selected = reverse; + } + else if (selected == null && + _wheelDirs[wheelIndex] >= 0 && + forward.Valid) + { + selected = forward; + } + } + + if (selected == null) + { + if (forward.Valid) selected = forward; + else if (reverse.Valid) selected = reverse; + } + + if (selected != null) + { + angle = selected.Value.NormalizedAngle; + direction = selected.Value.Direction; + reason = ""; + return true; + } + + angle = 0; + direction = 0; + var marginRequired = Math.Max(0, sw.AngleLimitMarginDeg); + reason = + $"{entry} infeasible wheel={wheelIndex} target={CommonMath.RoundTh(targetAngle):F1} " + + $"reverse={CommonMath.RoundTh(targetAngle + 180):F1} " + + $"limit=[{forward.Lower:F1},{forward.Upper:F1}] requiredMargin={marginRequired:F1} " + + $"forward(norm={forward.NormalizedAngle:F1},margin={forward.Margin:F1},valid={forward.Valid}) " + + $"reverse(norm={reverse.NormalizedAngle:F1},margin={reverse.Margin:F1},valid={reverse.Valid})"; + return false; + } + + private bool FailMotionDecomposition(string entry, string reason, TimeSpan? deltaTime) + { + LastMotionDecomposeFailureReason = $"{entry}: {reason}"; + Console.WriteLine(LastMotionDecomposeFailureReason); + DLog.Log(LastMotionDecomposeFailureReason, "MultiWheelMotionDecompose"); + Hedingben.ToastText($"Motion decompose failed: {reason}", "MultiWheelChassis-decompose"); + RampStop(deltaTime); + return false; + } + + private Vector2 _rotCenter; + + public Vector2 GetRotCenter() + { + return _rotCenter; + } + + public void SetOriginBias(float x, float y, float th) + { + _originBiasX = x; + _originBiasY = y; + _originBiasTh = th; + + foreach (var sw in _steerWheels) + { + sw.Position = CommonMath.Transform2D(new Vector2(_originBiasX, _originBiasY), _originBiasTh, + sw.PhysicalPosition); + sw.ZeroDirection = _originBiasTh; + } + + CalculateAxes(); + } + + public Visualizer SendMotionVisualizer = null; + + /// + /// frontTh和rearTh是基于当前行进方向,前后轴应该打的角度。 + /// + /// 单位m/s。 + /// 角度制。基于当前行进方向。 + /// 角度制。基于当前行进方向。 + /// 上次下发SendMotion到本次的间隔时间。 + /// 用于多车联动,大于0时生效。 + /// 用于多车联动,localControlRadius大于0时生效。 + /// 用于多车联动,localControlRadius大于0时生效。 + /// 用于多车联动,localControlRadius大于0时生效。 + /// + public bool SendMotion(float speed, float frontTh, float rearTh, TimeSpan? deltaTime = null, + float localControlRadius = 0, float localCompensateX = 0f, float localCompensateY = 0, float localCompensateTh = 0) + { + if (!Valid) return FailMotionDecomposition("SendMotion", "invalid chassis", deltaTime); + LastMotionDecomposeFailureReason = ""; + + var compInputSpeed = speed; + var compInputFrontTh = frontTh; + var compInputRearTh = rearTh; + var compMotionTh = 0f; + var compAlong = 0f; + var compSide = 0f; + var compDSpeed = 0f; + var compDTh = 0f; + + if (localControlRadius > 0) + { + var motionTh = AverageAngle(frontTh, rearTh); + var radMotionTh = motionTh / 180f * Math.PI; + var alongComp = (float)(localCompensateX * Math.Cos(radMotionTh) + + localCompensateY * Math.Sin(radMotionTh)); + var sideComp = (float)(-localCompensateX * Math.Sin(radMotionTh) + + localCompensateY * Math.Cos(radMotionTh)); + var dSpeed = alongComp / 1000f; + speed += dSpeed; + + var speedSign = Math.Abs(compInputSpeed) > 1e-4f ? Math.Sign(compInputSpeed) : 1; + var steerBaseSpeed = Math.Max(Math.Abs(speed), 0.05f); + var dTh = (float)(Math.Atan2(sideComp / 1000f, steerBaseSpeed) / Math.PI * 180f) * speedSign; + compMotionTh = motionTh; + compAlong = alongComp; + compSide = sideComp; + compDSpeed = dSpeed; + compDTh = dTh; + Hedingben.ToastText($"s:{compInputSpeed:F2} d:{dSpeed:F3}", "MultiWheelChassis-dSpeed"); + Hedingben.ToastText($"F:{frontTh:F1} R:{rearTh:F1} d:{dTh:F1}", "MultiWheelChassis-dTh"); + frontTh += dTh; + rearTh += dTh; + + if (Math.Abs(localCompensateX) > 1e-3f || Math.Abs(localCompensateY) > 1e-3f || + Math.Abs(localCompensateTh) > 1e-3f) + DLog.Log( + $"SendMotionComp in speed:{compInputSpeed:F3} fTh:{compInputFrontTh:F1} rTh:{compInputRearTh:F1} " + + $"motionTh:{motionTh:F1} biasTh:{_originBiasTh:F1} comp({localCompensateX:F1},{localCompensateY:F1},{localCompensateTh:F2}) " + + $"along:{alongComp:F1} side:{sideComp:F1} dSpeed:{dSpeed:F3} dTh:{dTh:F1} " + + $"out speed:{speed:F3} fTh:{frontTh:F1} rTh:{rearTh:F1}", + "MultiWheelMotionComp"); + } + + float scaleFactor = 1.0f; + float currentFrontTh = frontTh; + float currentRearTh = rearTh; + bool needAdjust = true; + const float minScaleFactor = 0.1f; + var finalAngles = new List(); + + var axisDiffFlag = false; + var myRotCenter = new Vector2(); + var lastInvalidReason = ""; + + float AverageAngle(float left, float right) + { + var leftRad = left / 180f * Math.PI; + var rightRad = right / 180f * Math.PI; + var x = Math.Cos(leftRad) + Math.Cos(rightRad); + var y = Math.Sin(leftRad) + Math.Sin(rightRad); + if (Math.Abs(x) < 1e-6 && Math.Abs(y) < 1e-6) + return (float)CommonMath.RoundTh(left); + return (float)CommonMath.RoundTh(Math.Atan2(y, x) / Math.PI * 180f); + } + + float Interpolate(float left, float current, float right) + { + if (current <= left) return 0; + if (current >= right) return 1; + return (current - left) / (right - left); + } + + while (needAdjust && scaleFactor > minScaleFactor) + { + needAdjust = false; + var tmpAngles = new List(); + + // ... 现有的插值函数和旋转中心计算代码 ... + var thDiff = CommonMath.ThDiff(currentFrontTh, currentRearTh); + axisDiffFlag = Math.Abs(thDiff) > ThConsistentThreshold; + + var sign = -1; + if (axisDiffFlag) + { + // Vector2 pFront = new(_frontBase, 0), pRear = new(_rearBase, 0), + Vector2 pFront = new(ControlPointRadius, 0), pRear = new(-ControlPointRadius, 0), + normFront = CommonMath.Transform2D(pFront, currentFrontTh + 90, Vector2.UnitX), + normRear = CommonMath.Transform2D(pRear, currentRearTh + 90, Vector2.UnitX); + var (intersect, center) = + CommonMath.TwoLinesIntersection(pFront, normFront, pRear, normRear); + if (!intersect) + return FailMotionDecomposition("SendMotion", + $"front/rear axes do not intersect frontTh={currentFrontTh:F1} rearTh={currentRearTh:F1}", + deltaTime); + myRotCenter = center; + sign = myRotCenter.Y > 1 ? 1 : -1; + + if (localControlRadius > 0 && localCompensateTh != 0) + { + void VisPointing(Color color, Vector2 point, float th, int width) + { + var localFrontPointing = CommonMath.Transform2D(point, th, new Vector2(200, 0)); + SendMotionVisualizer?.DrawLine(color, point, localFrontPointing, width: width); + } + + var localPFront = CommonMath.Transform2D(new Vector2(_originBiasX, _originBiasY), _originBiasTh, + new Vector2(localControlRadius, 0)); + var localPRear = CommonMath.Transform2D(new Vector2(_originBiasX, _originBiasY), _originBiasTh, + new Vector2(-localControlRadius, 0)); + // SendMotionVisualizer?.DrawLine(Color.DarkRed, myRotCenter, localPFront); + // SendMotionVisualizer?.DrawLine(Color.DarkRed, myRotCenter, localPRear); + + // 计算_rotCenter在"localPRear指向localPFront的向量"的左侧还是右侧 + // 使用叉积判断:叉积 > 0 表示在左侧,< 0 表示在右侧 + var vecRearToFront = new Vector2(localPFront.X - localPRear.X, localPFront.Y - localPRear.Y); + var vecRearToCenter = new Vector2(myRotCenter.X - localPRear.X, myRotCenter.Y - localPRear.Y); + var crossProduct = vecRearToFront.X * vecRearToCenter.Y - vecRearToFront.Y * vecRearToCenter.X; + var side = crossProduct > 0 ? 1 : -1; + + var localFrontTh = + (float)(Math.Atan2(localPFront.Y - myRotCenter.Y, localPFront.X - myRotCenter.X) / Math.PI * + 180) + 90 * side; + var localRearTh = + (float)(Math.Atan2(localPRear.Y - myRotCenter.Y, localPRear.X - myRotCenter.X) / Math.PI * + 180) + 90 * side; + var sameDirectionError = + Math.Abs(CommonMath.ThDiff(localFrontTh, currentFrontTh)) + + Math.Abs(CommonMath.ThDiff(localRearTh, currentRearTh)); + var reverseDirectionError = + Math.Abs(CommonMath.ThDiff(localFrontTh + 180, currentFrontTh)) + + Math.Abs(CommonMath.ThDiff(localRearTh + 180, currentRearTh)); + if (reverseDirectionError < sameDirectionError) + { + localFrontTh = (float)CommonMath.RoundTh(localFrontTh + 180); + localRearTh = (float)CommonMath.RoundTh(localRearTh + 180); + } + // VisPointing(Color.DarkRed, localPFront, localFrontTh, 1); + // VisPointing(Color.DarkRed, localPRear, localRearTh, 1); + + var newLocalFrontTh = localFrontTh + localCompensateTh * Math.Sign(speed); + var newLocalRearTh = localRearTh - localCompensateTh * Math.Sign(speed); + // VisPointing(Color.Red, localPFront, newLocalFrontTh, 2); + // VisPointing(Color.Red, localPRear, newLocalRearTh, 2); + + var localThDiff = CommonMath.ThDiff(newLocalFrontTh, newLocalRearTh); + axisDiffFlag = Math.Abs(localThDiff) > ThConsistentThreshold; + + if (axisDiffFlag) + { + var localNormFront = CommonMath.Transform2D(localPFront, newLocalFrontTh + 90, Vector2.UnitX); + var localNormRear = CommonMath.Transform2D(localPRear, newLocalRearTh + 90, Vector2.UnitX); + var (localIntersect, localCenter) = + CommonMath.TwoLinesIntersection(localPFront, localNormFront, localPRear, localNormRear); + if (!localIntersect) + return FailMotionDecomposition("SendMotion", + $"compensated axes do not intersect frontTh={newLocalFrontTh:F1} rearTh={newLocalRearTh:F1}", + deltaTime); + myRotCenter = localCenter; + sign = myRotCenter.Y > 1 ? 1 : -1; + + // SendMotionVisualizer?.DrawLine(Color.Red, myRotCenter, localPFront, width: 2); + // SendMotionVisualizer?.DrawLine(Color.Red, myRotCenter, localPRear, width: 2); + } + else + { + currentFrontTh = newLocalFrontTh; + currentRearTh = newLocalRearTh; + thDiff = CommonMath.ThDiff(currentFrontTh, currentRearTh); + } + } + } + + _rotCenter = myRotCenter; + Hedingben.ToastText($"fTh:{frontTh:0.0}, rTh:{rearTh:0.0}, DA:{_originBiasTh:0.00}, " + + $"rc:({_rotCenter.X:0.0},{_rotCenter.Y:0.0}), _rb:{_rearBase}, _fb:{_frontBase}", "rotCenter"); + var r0 = _rotCenter.Length(); + + // 计算所有轮子的角度 + bool anyWheelInvalid = false; + for (var i = 0; i < _steerWheels.Count; i++) + { + var sw = _steerWheels[i]; + float th; + + if (axisDiffFlag) + { + var sTh = (float)(Math.Atan2(sw.Position.Y - _rotCenter.Y, sw.Position.X - _rotCenter.X) / + Math.PI * 180) + sign * 90; + th = CommonMath.ThDiff(sTh, sw.ZeroDirection); + var r1 = Vector2.Distance(sw.Position, _rotCenter); + _tmpSpeeds[i] = r1 / (r0 + 0.00001f); + } + else + { + var axisTh = currentRearTh + thDiff * Interpolate(_rearBase, _wheelBases[i], _frontBase); + _tmpSpeeds[i] = 1; + th = CommonMath.ThDiff(axisTh, sw.ZeroDirection); + } + + if (!TryResolveWheelAngle(i, th, "SendMotion", out var resolvedTh, out var resolvedDir, + out var resolveReason)) + { + anyWheelInvalid = true; + needAdjust = true; + lastInvalidReason = resolveReason; + break; + } + + _wheelDirs[i] = resolvedDir; + tmpAngles.Add(resolvedTh); + } + + if (needAdjust && anyWheelInvalid) + { + return FailMotionDecomposition("SendMotion", lastInvalidReason, deltaTime); + } + + finalAngles = tmpAngles; + break; + } + + if (finalAngles.Count == _steerWheels.Count) + { + for (var i = 0; i < _steerWheels.Count; i++) + { + SendTh(i, finalAngles[i]); + } + } + else + { + return FailMotionDecomposition("SendMotion", + $"unable to find valid wheel angles frontTh={frontTh:F1} rearTh={rearTh:F1}", + deltaTime); + } + + // // todo: find better way to limit max speed + // var totalTurn = Math.Abs(frontTh) + Math.Abs(rearTh); + // var turnThresholdSpeed = CalculateTurningSpeedDecayFac(totalTurn) * MaxSpeed; + for (int i = 0; i < _steerWheels.Count; i++) + { + _debugSpeeds[i] = _tmpSpeeds[i] * speed * _wheelDirs[i]; + } + var speedBeforeAlignGate = speed; + + if (!GoingWheelAligned) + { + Hedingben.ToastText("Wheel Not Aligned", "MultiWheelChassis-SendMotion-notAligned"); + speed = 0; + var aligned = _steerWheels.Select((sw, i) => (sw, i)).All(ww => + Math.Abs(CommonMath.ThDiff(ww.sw.ReadAngle(), _sendAngle[ww.i])) < 1); + GoingWheelAligned = aligned; + } + + for (var i = 0; i < _steerWheels.Count; i++) + { + AccumulateSpeed(i, _tmpSpeeds[i] * speed * _wheelDirs[i], axisDiffFlag, _rotCenter, deltaTime); + } + + if ((DateTime.Now - _sendMotionDetailLastLog).TotalMilliseconds >= 200) + { + _sendMotionDetailLastLog = DateTime.Now; + var sb = new StringBuilder(); + sb.Append($"SendMotionDetail speed:{speed:F3} speedBeforeGate:{speedBeforeAlignGate:F3} fTh:{frontTh:F1} rTh:{rearTh:F1} " + + $"curF:{currentFrontTh:F1} curR:{currentRearTh:F1} " + + $"originBias:({_originBiasX:F1},{_originBiasY:F1},{_originBiasTh:F1}) " + + $"in(speed:{compInputSpeed:F3},f:{compInputFrontTh:F1},r:{compInputRearTh:F1}) " + + $"comp({localCompensateX:F1},{localCompensateY:F1},{localCompensateTh:F2}) " + + $"motionTh:{compMotionTh:F1} along:{compAlong:F1} side:{compSide:F1} dSpeed:{compDSpeed:F3} dTh:{compDTh:F1} " + + $"axisDiff:{axisDiffFlag} rotCenter:({_rotCenter.X:F1},{_rotCenter.Y:F1}) goingAligned:{GoingWheelAligned}"); + for (var i = 0; i < _steerWheels.Count; i++) + { + var sw = _steerWheels[i]; + var readTh = sw.ReadAngle(); + var targetTh = _sendAngle[i]; + var errTh = CommonMath.ThDiff(readTh, targetTh); + sb.Append($" | w{i} tgt:{targetTh:F1} read:{readTh:F1} err:{errTh:F1} " + + $"zero:{sw.ZeroDirection:F1} rel:{sw.GetAngleRelativeToChassis():F1} " + + $"dir:{_wheelDirs[i]} tmp:{_tmpSpeeds[i]:F2} targetV:{_targetSpeeds[i]:F3} sendV:{_sendSpeeds[i]:F3} " + + $"lim:[{sw.AngleLowerLimit:F1},{sw.AngleUpperLimit:F1}]"); + if (sw is DiffSteerWheel dsw) + { + sb.Append($" diffSend(L:{dsw.GetLeftSendSpeed():F3},R:{dsw.GetRightSendSpeed():F3})"); + } + else + { + sb.Append($" wheelSend:{sw.GetSendSpeed():F3}"); + } + } + DLog.Log(sb.ToString(), "MultiWheelMotionDetail"); + } + + LastMoveTime = DateTime.Now; + LastMotionDecomposeFailureReason = ""; + return true; + } + + /// + /// 绕"已被 SetOriginBias 偏置到车队中心的原点"做原地旋转,可叠加一个车体系小幅纠偏旋量。 + /// + /// 绕车队中心角速度(deg/s,逆时针为正)。 + /// 车体系纵向(前+)修正速度(mm/s),多车联动维持队形用。 + /// 车体系横向(左+)修正速度(mm/s)。 + /// 绕本车几何中心附加角速度(deg/s),修正朝向偏差。 + public bool SendRotateMotion(float rotSpeed, TimeSpan? deltaTime = null, + float localCompensateX = 0f, float localCompensateY = 0f, float localCompensateTh = 0f) + { + if (!Valid) return FailMotionDecomposition("SendRotateMotion", "invalid chassis", deltaTime); + LastMotionDecomposeFailureReason = ""; + if (Math.Abs(rotSpeed) < 1e-6f && + Math.Abs(localCompensateX) < 1e-6f && + Math.Abs(localCompensateY) < 1e-6f && + Math.Abs(localCompensateTh) < 1e-6f) + { + LastRotateAligned = true; + RampStop(deltaTime); + return true; + } + + var ths = new float[_steerWheels.Count]; + var dirs = new int[_steerWheels.Count]; + // 每轮合速度大小(m/s),含"绕队心旋转 + 车体平移纠偏 + 绕本车中心微转纠偏"三项矢量和。 + var speedMags = new float[_steerWheels.Count]; + var allWheelAligned = true; + + // 把车体系纠偏旋量换算到 sw.Position 所在的偏置帧 F(原点=车队中心, 朝向随 _originBiasTh)。 + // body->F 旋转为 R(_originBiasTh),与 SetOriginBias 里 Transform2D 的约定一致。 + var radBias = _originBiasTh / 180.0 * Math.PI; + var cosB = Math.Cos(radBias); + var sinB = Math.Sin(radBias); + var compVxF = localCompensateX * cosB - localCompensateY * sinB; // mm/s,F帧 + var compVyF = localCompensateX * sinB + localCompensateY * cosB; + var rotRad = rotSpeed / 180.0 * Math.PI; // 绕队心(F原点)角速度 rad/s + var compRad = localCompensateTh / 180.0 * Math.PI; // 绕本车几何中心附加角速度 rad/s + var biasX = (double)_originBiasX; // 本车几何中心在 F 中的位置 + var biasY = (double)_originBiasY; + + for (var i = 0; i < _steerWheels.Count; i++) + { + var sw = _steerWheels[i]; + var px = (double)sw.Position.X; + var py = (double)sw.Position.Y; + // 合成轮速矢量(mm/s, F帧):v = ω_rot ẑ×p + [R(bias)·v_comp + ω_comp ẑ×(p - 本车中心)] + // 旋转切向项与纠偏项分开算,便于把纠偏钳到旋转切向的一定比例。 + var vxRot = -rotRad * py; + var vyRot = rotRad * px; + var vxComp = compVxF - compRad * (py - biasY); + var vyComp = compVyF + compRad * (px - biasX); + // 纠偏钳位:|纠偏| ≤ RotateCompTangentFrac × |旋转切向|,限制合矢量相对纯切向的最大偏角 + // (frac=0.5 → 偏角≤26.6°),避免减速末段纠偏盖过旋转切向导致舵轮 180° 乱翻。 + if (RotateCompTangentFrac >= 0f) + { + var rotMag = Math.Sqrt(vxRot * vxRot + vyRot * vyRot); + var compMag = Math.Sqrt(vxComp * vxComp + vyComp * vyComp); + var compLimit = RotateCompTangentFrac * rotMag; + if (compMag > compLimit && compMag > 1e-6) + { + var s = compLimit / compMag; + vxComp *= s; + vyComp *= s; + } + } + var vx = vxRot + vxComp; + var vy = vyRot + vyComp; + var vmag = Math.Sqrt(vx * vx + vy * vy); + speedMags[i] = (float)(vmag / 1000.0); + + // 轮子应指向的运动方向(F帧)。纠偏后合速度≈0 时退化为纯旋转切向,避免 atan2 抖动。 + var angleF = vmag < 1e-6 + ? Math.Atan2(px, -py) / Math.PI * 180 + : Math.Atan2(vy, vx) / Math.PI * 180; + var tangent = CommonMath.ThDiff((float)angleF, sw.ZeroDirection); + + if (!TryResolveWheelAngle(i, tangent, "SendRotateMotion", out ths[i], out dirs[i], + out var resolveReason)) + return FailMotionDecomposition("SendRotateMotion", resolveReason, deltaTime); + _wheelDirs[i] = dirs[i]; + } + + for (var i = 0; i < _steerWheels.Count; ++i) + SendTh(i, ths[i]); + var slowFac = 1f; + var maxDth = 0f; + for (var i = 0; i < _steerWheels.Count; ++i) + { + var dth = Math.Abs(CommonMath.ThDiff(ths[i], _steerWheels[i].ReadAngle())); + maxDth = Math.Max(maxDth, dth); + slowFac = Math.Min(slowFac, CommonMath.gaussmf(dth, rotSync, 0)); + // if (dth > 5) + // { + // allWheelAligned = false; + // break; + // } + } + LastRotateAligned = allWheelAligned; // 供上层做积分抗饱和 + + // 对齐门控:未对齐则整体停车;对齐后用 slowFac 平滑提速。旋转与纠偏被同等缩放,保持几何一致。 + var gateFac = allWheelAligned ? slowFac : 0f; + for (var i = 0; i < _steerWheels.Count; ++i) + AccumulateSpeed(i, speedMags[i] * gateFac * dirs[i], true, Vector2.Zero, deltaTime); + + // === 原地旋转诊断(节流 ~300ms)=== + // 关注 allWheelAligned(false 说明舵轮追不上目标角)、dirs/半径,以及叠加的纠偏旋量 comp(vx,vy,om)。 + if ((DateTime.Now - _rotDbgLast).TotalMilliseconds >= 300) + { + _rotDbgLast = DateTime.Now; + var sb = new StringBuilder(); + sb.Append($"SendRotateMotion in:{rotSpeed:F1} aligned:{allWheelAligned} maxDth:{maxDth:F1} slowFac:{slowFac:F2} gate:{gateFac:F2} biasTh:{_originBiasTh:F1} comp(vx:{localCompensateX:F1} vy:{localCompensateY:F1} om:{localCompensateTh:F1})"); + for (var i = 0; i < _steerWheels.Count; ++i) + { + var sw = _steerWheels[i]; + sb.Append($" | w{i} tgt:{ths[i]:F1} read:{sw.ReadAngle():F1} dth:{Math.Abs(CommonMath.ThDiff(ths[i], sw.ReadAngle())):F1} dir:{dirs[i]} R:{sw.Position.Length():F0} v:{speedMags[i] * gateFac * dirs[i]:F3} send:{sw.GetSendSpeed():F2}"); + } + DLog.Log(sb.ToString(), "RotateDbg"); + } + + LastMoveTime = DateTime.Now; + LastMotionDecomposeFailureReason = ""; + return true; + } + + private DateTime _rotDbgLast = DateTime.MinValue; + + public override float CalculateTurningSpeedDecayFac(float turn) + { + return 1 - Math.Min(turn, MaxTurnThreshold) / MaxTurnThreshold * MinTurnSpeedFac; + } + + [Obsolete] + public List GetSteerWheels() + { + return _steerWheels.ToList(); + } + + private void SendTh(int i, float targetTh) + { + _steerWheels[i].WriteAngle(targetTh); + _sendAngle[i] = targetTh; + } + + private (int direction, float rangeFront, float rangeRear) DetermineWheelDirection(SteerWheel wheel) + { + var lower = CommonMath.RoundTh(wheel.AngleLowerLimit + wheel.ZeroDirection); + var upper = CommonMath.RoundTh(wheel.AngleUpperLimit + wheel.ZeroDirection); + while (upper < lower) upper += 360; + + var frontDir = 0; + var rearDir = 180; + + // 计算前向和后向的可用范围 + var rangeFront = Math.Min(upper - frontDir, frontDir - lower); + var rangeRear = Math.Min(upper - rearDir, rearDir - lower); + + // 选择范围更大的方向 + if (rangeFront >= rangeRear && rangeFront > 0) + { + return (1, rangeFront, rangeRear); + } + else if (rangeRear > rangeFront && rangeRear > 0) + { + return (-1, rangeFront, rangeRear); + } + + // 如果两个方向都不可行 + return (0, rangeFront, rangeRear); + } + + private void AccumulateSpeed(int i, float v, bool axisDiff, Vector2 rotCenter, TimeSpan? deltaTime = null) + { + _targetSpeeds[i] = v; + var speedSign = Math.Sign(_targetSpeeds[i] - _sendSpeeds[i]); + var acc = Math.Abs(_targetSpeeds[i]) > Math.Abs(_sendSpeeds[i]) ? AccPerSecond : DeAccPerSecond; + _sendSpeeds[i] += speedSign * Math.Min(Math.Abs(_targetSpeeds[i] - _sendSpeeds[i]), + acc * (float)(deltaTime ?? DateTime.Now - LastMoveTime).TotalSeconds); + if (_steerWheels[i] is DiffSteerWheel dsw) + { + if (axisDiff) + { + var wheelRadius = Vector2.Distance(rotCenter, dsw.Position); + var wheelDir = _sendAngle[i]; + + var left = CommonMath.Transform2D(dsw.Position, wheelDir + 90, new Vector2(dsw.WheelDistance, 0)); + var right = CommonMath.Transform2D(dsw.Position, wheelDir - 90, new Vector2(dsw.WheelDistance, 0)); + dsw.WriteLeftSpeed(_sendSpeeds[i] / wheelRadius * Vector2.Distance(rotCenter, left)); + dsw.WriteRightSpeed(_sendSpeeds[i] / wheelRadius * Vector2.Distance(rotCenter, right)); + } + else + { + dsw.WriteLeftSpeed(_sendSpeeds[i]); + dsw.WriteRightSpeed(_sendSpeeds[i]); + } + } + else + { + _steerWheels[i].WriteSpeed(_sendSpeeds[i]); + } + + if (Debug) + Console.WriteLine($"Ackermann wheel{i}: target:{_targetSpeeds[i]:0.00},send:{_sendSpeeds[i]:0.0}"); + } + + private void CalculateAxes() + { + var axes = _steerWheels + .Select(sw => (sw, Vector2.Dot(sw.Position, new Vector2(1, 0)))) + .OrderByDescending(ax => ax.Item2).ToList(); + _wheelBases = axes.Select(ax => ax.Item2).ToList(); + _steerWheels = axes.Select(ax => ax.sw).ToList(); + GeometricControlPoints = new List() + { + new (new Vector2(ControlPointRadius, 0)), + new (new Vector2(-ControlPointRadius, 0)) + }; + _frontBase = _wheelBases.First(); + _rearBase = _wheelBases.Last(); + } + + private List _steerWheels = new (); + private float _frontBase, _rearBase; + private List _wheelBases; + private List _sendSpeeds; + private List _targetSpeeds; + private List _sendAngle; + private List _debugSpeeds; + private DateTime _sendMotionDetailLastLog = DateTime.MinValue; + private DateTime _geometricComputeLastLog = DateTime.MinValue; + + private List _tmpSpeeds; + // add TimeStamp, prevent the wheel from swaying. + // for example, target angle is 90, current wheel is around 0. if no TimeStamp, + // wheel will swing between 90 and -90. + private List _wheelDirs; + + // call this before a new continuous motion happens + private void ResetMotionState() + { + LastMoveTime = DateTime.Now; + GoingWheelAligned = false; + _wheelDirs = Enumerable.Repeat(1, _steerWheels.Count).ToList(); + } + + public void AddTestFunction() + { + + } + /// + /// 得到相对舵轮在车体坐标系下的分解速度 + /// + /// + /// + /// + /// 单位为°/s + /// + private Vector2 VectorVelocity(Vector2 pos, float vx, float vy, float vth, int i) + { + var vRotX = -vth / 180 * (float)Math.PI * pos.Y / 1000; + var vRotY = vth / 180 * (float)Math.PI * pos.X / 1000; + Hedingben.ToastText($"vRot:({vRotX:F3},{vRotY:F3}) pos:({pos.X:F1},{pos.Y:F1})", + $"SendXYThSpeed-VectorVelocity{i}"); + return new Vector2(vx + vRotX, vy + vRotY); + } + /// + /// 获得车轮应该打的角度和速度 + /// + /// + /// + /// + /// 单位为°/s + /// + private (float angle, float speed) AngleAndSpeed(Vector2 pos, float vx, float vy, float vth, int i) + { + var v = VectorVelocity(pos, vx, vy, vth, i); + return ((float)(Math.Atan2(v.Y, v.X) / Math.PI * 180), v.Length()); + } + + private float w = 0; + private float wAcc = 0.1f; + private float rotSync = 3f; + private bool XYThActive = false; + + public bool SendXYThSpeed(float vx, float vy, float vth, TimeSpan? deltaTime = null) + { + if (!Valid) return FailMotionDecomposition("SendXYThSpeed", "invalid chassis", deltaTime); + if (!XYThActive) + { + ResetMotionState(); + w = 0; + } + XYThActive = true; + GoingActive = false; + RotatingActive = false; + + if (Math.Abs(vx) < 1e-6f && Math.Abs(vy) < 1e-6f && Math.Abs(vth) < 1e-6f) + { + RampStop(deltaTime); + LastMotionDecomposeFailureReason = ""; + return true; + } + + w = w + wAcc; + if (w > 1) w = 1; + float[] sendSpeed = new float[_steerWheels.Count]; + for (var i = 0; i < _steerWheels.Count; i++) + { + var sw = _steerWheels[i]; + var (angle, speed) = AngleAndSpeed(sw.Position, vx, vy, vth, i); + var actualTh = sw.ReadAngle(); + if (!TryResolveWheelAngle(i, CommonMath.ThDiff(angle, sw.ZeroDirection), "SendXYThSpeed", + out var useAngle, out var dir, out var resolveReason)) + return FailMotionDecomposition("SendXYThSpeed", resolveReason, deltaTime); + speed *= dir; + _wheelDirs[i] = dir; + + sendSpeed[i] = speed; + if (speed!=0) + SendTh(i, useAngle); + w = (float)Math.Min(w, CommonMath.gaussmf(CommonMath.ThDiff(actualTh, _sendAngle[i]), rotSync, 0)); + + Hedingben.ToastText($"w:{w:F2} s:{speed:F3} th:{_sendAngle[i]:F1} actualTh:{actualTh:F1}", $"SendXYThSpeed-{i}"); + } + for (var i = 0; i < _steerWheels.Count; i++) + AccumulateSpeed(i, w * sendSpeed[i],false,new Vector2(0f,0f), deltaTime); + //todo 计算rotCenter填入 + LastMoveTime = DateTime.Now; + LastMotionDecomposeFailureReason = ""; + return true; + } + + public override CarSpeed GetCarSpeed(bool isActual = false) + { + List vx = new List(); + List vy = new List(); + List vth = new List(); + for (var i = 0; i < _steerWheels.Count; ++i) + { + var sw1 = _steerWheels[i]; + Vector2 a = sw1.Position / 1000; + //var tha = _sendAngle[i] / 180 * (float)Math.PI; + var tha = isActual ? sw1.ReadAngle() / 180 * (float)Math.PI : _sendAngle[i] / 180 * (float)Math.PI; + //var speeda = _sendSpeeds[i]; + //var speeda = isActual ? sw1.ReadSpeed() : _sendSpeeds[i]; + var speeda = isActual ? sw1.ReadSpeed() : _debugSpeeds[i]; + Vector2 va = new Vector2(speeda * (float)Math.Cos(tha), speeda * (float)Math.Sin(tha)); + // painter.DrawLine(Color.Green, sw1.Position, + // LessMath.Transform2D(sw1.Position, sw1.ReadAngle(), new Vector2(200, 0)), endArrow: true); + for (var j = i + 1; j < _steerWheels.Count; ++j) + { + var sw2 = _steerWheels[j]; + Vector2 b = sw2.Position / 1000; + //var thb = _sendAngle[j] / 180 * (float)Math.PI; + var thb = isActual ? sw2.ReadAngle() / 180 * (float)Math.PI : _sendAngle[j] / 180 * (float)Math.PI; + //var speedb = _sendSpeeds[j]; + //var speedb = isActual ? sw2.ReadSpeed() : _sendSpeeds[j]; + var speedb = isActual ? sw2.ReadSpeed() : _debugSpeeds[j]; + Vector2 vb = new Vector2(speedb * (float)Math.Cos(thb), speedb * (float)Math.Sin(thb)); + var (tempvx, tempvy, tempvth) = CenterVelocityFromPoints(a, va, b, vb); + vx.Add(tempvx); + vy.Add(tempvy); + vth.Add(tempvth); + } + } + return new CarSpeed() + { Vx = vx.Average(), Vy = vy.Average(), Vw = (float)(vth.Average() / Math.PI * 180f) }; + } + + private static (float, float, float) CenterVelocityFromPoints(Vector2 a, Vector2 va, Vector2 b, Vector2 vb) + { + float vth_x = 0, vth_y = 0, vth = 0, vx = 0, vy = 0; + var eps = 0.0000001; + if (Math.Abs(a.Y - b.Y) > eps) + { + vth_x = (va.X - vb.X) / (b.Y - a.Y); + } + + if (Math.Abs(a.X - b.X) > eps) + { + vth_y = (va.Y - vb.Y) / (a.X - b.X); + } + vth = vth_x == 0 ? vth_y : vth_x; + vx = va.X + vth * a.Y; + vy = va.Y - vth * a.X; + return (vx, vy, vth); + } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Chassis/SingleSteerChassis.cs b/CommonUsage-MultiVehicleSync/commonusage/Chassis/SingleSteerChassis.cs new file mode 100644 index 0000000..cb0df3e --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Chassis/SingleSteerChassis.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Diagnostics; +using CommonUsage.Mathematics; +using FundamentalLib; + +namespace CommonUsage.Chassis +{ + public class SingleSteerChassis : AbstractChassis + { + public void SetSteerWheel(SteerWheel wheel) + { + _steerWheel = wheel; + } + + public SteerWheel GetSteerWheel() + { + return _steerWheel; + } + + public override void Visualize() + { + + } + + public override CarSpeed GetCarSpeed(bool isActual = false) + { + if (!isActual) + { + var sendAngle = _steerWheel.GetSendAngle(); + var sendAngleRad = _steerWheel.GetSendAngle() / 180f * Math.PI; + // VSteer* Cos = v; + var vsteer = _sendSpeed / ((Math.Cos(Math.Abs(sendAngleRad)) + 0.000001)); + var vsteerY = vsteer * Math.Sin(sendAngleRad); + // Console.WriteLine($"{vsteer} {vsteerY} {sendAngleRad} {_sendSpeed}"); + return new CarSpeed() + { + Vx = (float)(_sendSpeed * Math.Cos(Math.Abs(sendAngle) / 180f * Math.PI)), + Vy = 0, + Vw = (float)(_sendSpeed * Math.Sin(Math.Abs(sendAngle) / 180f * Math.PI) / + Math.Abs(_steerWheel.Position.X / 1000f) / Math.PI * 180f) + //阿克曼 + // Vx = (float)(_sendSpeed), + // Vy = 0, + // Vw = (float)(vsteerY / Math.Abs(_steerWheel.Position.X / 1000f) / Math.PI * 180f) + }; + } + else + { + return new CarSpeed() + { + Vx = (float)(_steerWheel.ReadSpeed() * + Math.Cos(Math.Abs(_steerWheel.ReadAngle()) / 180f * Math.PI)), + Vy = 0, + Vw = (float)(_steerWheel.ReadSpeed() * + Math.Sin(Math.Abs(_steerWheel.ReadAngle()) / 180f * Math.PI) / + Math.Abs(_steerWheel.Position.X / 1000f) / Math.PI * 180f) + }; + } + + } + + public override void Initialize() + { + GeometricControlPoints = new List() + { + new (_steerWheel.Position), + new (Vector2.Zero) + }; + Valid = true; + } + + public override void AfterDirectionChanged() + { + if (Math.Abs(CommonMath.ThDiff(0, _originBiasTh)) > 90) + { + GeometricControlPoints = new List() + { + new (-_steerWheel.Position), + }; + _direction = -1; + } + else + { + GeometricControlPoints = new List() + { + new (_steerWheel.Position), + }; + _direction = 1; + } + } + + public override void PredefinedDriveStop() + { + if (!Valid) return; + _sendSpeed = 0; + _steerWheel.WriteSpeed(_sendSpeed); + GoingActive = false; + RotatingActive = false; + } + + protected override void DefineGeometricWheelComputation(float speed) + { + var now = DateTime.Now; + + if (!GoingActive) + { + LastMoveTime = now; + GoingWheelAligned = false; + } + + SendSteerMotion(speed * _direction, GeometricControlPoints[0].Theta, now - LastMoveTime); + + GoingActive = true; + RotatingActive = false; + } + + public override bool ComputeRotateWheels(float rotSpeed) + { + if (!RotatingActive) + { + LastMoveTime = DateTime.Now; + GoingWheelAligned = false; + } + + SendSteerMotion(rotSpeed, 90); + + GoingActive = false; + RotatingActive = true; + return true; + } + + public void SendSteerMotion(float speed, float theta, TimeSpan? deltaTime = null) + { + _steerWheel.WriteAngle(theta); + + if (!GoingWheelAligned && Math.Abs(CommonMath.ThDiff(_steerWheel.ReadAngle(), theta)) < 1) + GoingWheelAligned = true; + if (!GoingWheelAligned) speed = 0; + + var turnThresholdSpeed = CalculateTurningSpeedDecayFac(Math.Abs(theta)) * MaxSpeed; + AccumulateSpeed(Math.Min(turnThresholdSpeed, Math.Abs(speed)) * Math.Sign(speed), deltaTime); + + LastMoveTime = DateTime.Now; + } + + public override float CalculateTurningSpeedDecayFac(float turn) + { + return 1 - Math.Min(turn, MaxTurnThreshold) / MaxTurnThreshold * MinTurnSpeedFac; + } + + private void AccumulateSpeed(float v, TimeSpan? deltaTime = null) + { + // _targetSpeed = v; + var speedSign = Math.Sign(v - _sendSpeed); + var acc = Math.Abs(v) > Math.Abs(_sendSpeed) ? AccPerSecond : DeAccPerSecond; + _sendSpeed += speedSign * Math.Min(Math.Abs(v - _sendSpeed), + acc * (float)(deltaTime ?? DateTime.Now - LastMoveTime).TotalSeconds); + _steerWheel.WriteSpeed(_sendSpeed); + + if (Debug) + Console.WriteLine($"SingleSteer, target:{v:0.00},send:{_sendSpeed:0.0}"); + } + + private SteerWheel _steerWheel; + private float _sendSpeed; + private int _direction = 1; // 1 forward, -1 backward + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Chassis/SteerWheel.cs b/CommonUsage-MultiVehicleSync/commonusage/Chassis/SteerWheel.cs new file mode 100644 index 0000000..00bc7c4 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Chassis/SteerWheel.cs @@ -0,0 +1,100 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Text; +using CommonUsage.Mathematics; + +namespace CommonUsage.Chassis +{ + public class SteerWheel : Wheel + { + public SteerWheel(Vector2 position, float angleLowerLimit, float angleUpperLimit, Action speedWriter, + Func speedReader, Action angleWriter, Func angleReader, float angleLimitMarginDeg = 15f) : base(position, speedWriter, + speedReader) + { + _angleLowerLimit = angleLowerLimit; + _angleUpperLimit = angleUpperLimit; + _angleWriter = angleWriter; + _angleReader = angleReader; + _centerDistance = position.Length(); + AngleLimitMarginDeg = angleLimitMarginDeg; + } + + public float AngleLimitMarginDeg = 15f; + + public bool TrySetDirection(bool allowReverse, ref float desireDirection, ref int dir) + { + if (TryNormalizeAngleInLimit(desireDirection, out var normalized)) + { + dir = 1; + desireDirection = normalized; + return true; + } + + if (!allowReverse) return false; + + var oppositeTh = (float)CommonMath.RoundTh(desireDirection + 180); + if (TryNormalizeAngleInLimit(oppositeTh, out normalized)) + { + dir = -1; + desireDirection = normalized; + return true; + } + + dir = 0; + return false; + } + + private bool TryNormalizeAngleInLimit(float angle, out float normalized) + { + var lower = CommonMath.RoundTh(_angleLowerLimit); + var upper = CommonMath.RoundTh(_angleUpperLimit); + while (upper < lower) upper += 360; + + normalized = (float)CommonMath.RoundTh(angle); + while (normalized < lower) normalized += 360; + while (normalized > upper && normalized - 360 >= lower) normalized -= 360; + + var margin = Math.Min(normalized - lower, upper - normalized); + return normalized >= lower && normalized <= upper && margin >= Math.Max(0, AngleLimitMarginDeg); + } + + public float ReadAngle() + { + return _angleReader(); + } + + public void WriteAngle(float angle) + { + _angleWriter.Invoke(_sendAngle = Math.Max(_angleLowerLimit, Math.Min(angle, _angleUpperLimit))); + } + + public float GetSendAngle() + { + return _sendAngle; + } + + public float GetAngleRelativeToChassis() + { + return ZeroDirection + _sendAngle; + } + + public float CenterDistance() + { + return _centerDistance; + } + + public float AngleLowerLimit => _angleLowerLimit; + + public float AngleUpperLimit => _angleUpperLimit; + + [JsonIgnore] private readonly Action _angleWriter; + [JsonIgnore] private readonly Func _angleReader; + + private float _angleLowerLimit = -90, _angleUpperLimit = 90; + private float _centerDistance; + + public float _sendAngle = 0f; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Chassis/Wheel.cs b/CommonUsage-MultiVehicleSync/commonusage/Chassis/Wheel.cs new file mode 100644 index 0000000..dea87e1 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Chassis/Wheel.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Text; +using Newtonsoft.Json; + +namespace CommonUsage.Chassis +{ + public class Wheel + { + public Wheel(Vector2 position, Action speedWriter, Func speedReader) + { + PhysicalPosition = Position = position; + SpeedWriter = speedWriter; + SpeedReader = speedReader; + } + + public void WriteSpeed(float speed) + { + SpeedWriter.Invoke(_sendSpeed = speed); + } + + public float GetSendSpeed() + { + return _sendSpeed; + } + + public float ReadSpeed() + { + return SpeedReader(); + } + + // PhysicalPosition ===(chassis transform)===> Position + // useful in dual agv coordination + public readonly Vector2 PhysicalPosition; + public Vector2 Position; + + public float ZeroDirection = 0; + + [JsonIgnore] public readonly Action SpeedWriter; + [JsonIgnore] public readonly Func SpeedReader; + + public float _sendSpeed; + } + + public class GeometricControlPoint + { + public GeometricControlPoint(Vector2 position) + { + Position = position; + } + + public Vector2 Position; + public float Theta; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/CommonUsage.csproj b/CommonUsage-MultiVehicleSync/commonusage/CommonUsage.csproj new file mode 100644 index 0000000..d5f4d92 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/CommonUsage.csproj @@ -0,0 +1,48 @@ + + + + netstandard2.0 + + + + latest + True + + + + embedded + + + + embedded + + + + + + + + + + + + + + + + + + ..\..\MedullaAdapter\ref\RefFundamentalLib.dll + + + ..\..\ClumsyPilot\ref\RefClumsyCore.dll + + + + + + + + + diff --git a/CommonUsage-MultiVehicleSync/commonusage/CommonUsageSln.sln b/CommonUsage-MultiVehicleSync/commonusage/CommonUsageSln.sln new file mode 100644 index 0000000..227bf56 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/CommonUsageSln.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33424.131 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommonUsage", "CommonUsage.csproj", "{E1C5DEA8-3785-40A9-9965-E51E65BF5947}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E1C5DEA8-3785-40A9-9965-E51E65BF5947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1C5DEA8-3785-40A9-9965-E51E65BF5947}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1C5DEA8-3785-40A9-9965-E51E65BF5947}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E1C5DEA8-3785-40A9-9965-E51E65BF5947}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {709F9C19-45DB-46AD-B70A-0E1E3C6CFB0C} + EndGlobalSection +EndGlobal diff --git a/CommonUsage-MultiVehicleSync/commonusage/Deps/RefFundamentalLib.dll b/CommonUsage-MultiVehicleSync/commonusage/Deps/RefFundamentalLib.dll new file mode 100644 index 0000000000000000000000000000000000000000..8ada7edabcdee130cfc813ff1a8ee63c0a838c01 GIT binary patch literal 11776 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 literal 0 HcmV?d00001 diff --git a/CommonUsage-MultiVehicleSync/commonusage/Geometries/AbstractGeometry.cs b/CommonUsage-MultiVehicleSync/commonusage/Geometries/AbstractGeometry.cs new file mode 100644 index 0000000..28ed7b9 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Geometries/AbstractGeometry.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Numerics; +using System.Text; +using static CommonUsage.Geometries.CircularArc; + +namespace CommonUsage.Geometries +{ + /// + /// 便于直接创建几何形状并求几何形状的切点、切线等。 + /// + public abstract class AbstractGeometry + { + protected AbstractGeometry() + { + PaddingType = Padding.StartExtendEndExtend; + VisualizeOption = new VisualizeOption(Color.Red, Color.Gray); + } + + public Padding PaddingType; + + public abstract (Vector2 Pt, float Angle, float Bias, float Position) QueryTangentPoint(Vector2 point); + + public abstract void Visualize(Action processDot, Action processLine, + bool visExtendedPart = false); + + public VisualizeOption VisualizeOption; + + /// + /// 查询指定位置的曲率。 + /// + /// 从起点到查询位置的距离。 + /// + public abstract float QueryCurvature(float position); + + public abstract float Length(); + } + + public class VisualizeOption + { + public VisualizeOption(Color mainColor, Color auxiliaryColor) + { + MainColor = mainColor; + AuxiliaryColor = auxiliaryColor; + } + + public Color MainColor; + public Color AuxiliaryColor; + public bool DrawAuxiliary = true; + public bool VisualizeDirection = true; + } + + public enum Padding + { + StartLineEndLine = 0b_0001_0001, + StartLineEndExtend = 0b_0001_0010, + StartExtendEndLine = 0b_0010_0001, + StartExtendEndExtend = 0b_0010_0010, + } + + public class VisDot + { + public VisDot(Vector2 point, Color color) + { + Point = point; + Color = color; + } + + public Vector2 Point; + public Color Color; + } + + public class VisLine + { + public VisLine(Vector2 start, Vector2 end, bool startArrow, bool endArrow, Color color, float width = 1) + { + Start = start; + End = end; + StartArrow = startArrow; + EndArrow = endArrow; + Color = color; + Width = width; + } + + public Vector2 Start; + public Vector2 End; + public bool StartArrow = false; + public bool EndArrow = false; + public Color Color; + public float Width; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Geometries/BezierCurve.cs b/CommonUsage-MultiVehicleSync/commonusage/Geometries/BezierCurve.cs new file mode 100644 index 0000000..c4c8bbe --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Geometries/BezierCurve.cs @@ -0,0 +1,334 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Numerics; +using System.Reflection; +using CommonUsage.Mathematics; + +namespace CommonUsage.Geometries +{ + public class BezierCurve : AbstractGeometry + { + + public BezierCurve(List controlPoints, int resolution = 100) + { + // Console.WriteLine($"BezierCurve1"); + // Console.WriteLine(string.Join(" ",controlPoints.Select(p=>$"{p.X:f2},{p.Y:f2}"))); + _controlPoints = controlPoints; + _resolution = resolution; + InitializeBezier(); + } + + public override void Visualize(Action processDot, Action processLine, bool visExtendedPart = false) + { + if (VisualizeOption.DrawAuxiliary) + for (var i = 0; i < _controlPoints.Count - 1; ++i) + { + processLine(new VisLine(_controlPoints[i], _controlPoints[i + 1], + false, false, VisualizeOption.AuxiliaryColor)); + if (i == 0) continue; + processDot(new VisDot(_controlPoints[i], VisualizeOption.AuxiliaryColor)); + } + + for (var i = 0; i < _bezierPoints.Count - 1; ++i) + { + if (Direction == -1) + { + processLine(new VisLine(_bezierPoints[i + 1], _bezierPoints[i], + false, i == (int)(_bezierPoints.Count / 2), VisualizeOption.MainColor, 2)); + } + else + { + processLine(new VisLine(_bezierPoints[i], _bezierPoints[i + 1], + false, i == (int)(_bezierPoints.Count / 2), VisualizeOption.MainColor, 2)); + } + + + } + } + + public (Vector2 Point, int Id) QueryPoint(Vector2 point) + { + var p = new Vector2(); + var id = -1; + var bestDistance = float.MaxValue; + + var hashes = _bias.Select(bb => CalculateHash(point, 100, bb.X, bb.Y)).ToList(); + + void TryQuery(Dictionary> dict, List hashList) + { + foreach (var hash in hashList) + { + if (!dict.TryGetValue(hash, out var ll)) continue; + foreach (var (q, qId) in ll) + { + var d = Vector2.Distance(q, point); + if (d < bestDistance) + { + p = q; + id = qId; + bestDistance = d; + } + } + } + } + //map目前有bug,取消cpu占用也不严重,必要时候在优化 + // TryQuery(_pointsMappingSmall, hashes); + // + // if (id == -1) + // { + // hashes = _bias.Select(bb => CalculateHash(point, 1000, bb.X, bb.Y)).ToList(); + // TryQuery(_pointsMappingBig, hashes); + // } + + if (id == -1) + { + // todo: improve the way to find closest point if mappings fail + (p, id) = _bezierPoints.Select((p, i) => (p, i)) + .OrderBy(pair => CommonMath.dist(pair.p.X, pair.p.Y, point.X, point.Y)).First(); + } + + return (p, id); + } + + public override (Vector2 Pt, float Angle, float Bias, float Position) QueryTangentPoint(Vector2 point) + { + var (p, id) = QueryPoint(point); + var tangent = _tangents[id]; + var (bias, lp, fd) = CommonMath.Project2DLine(point, p, tangent); + var next = fd > 0 ? id + 1 : id - 1; + if (id == 0) next = 1; + // Console.WriteLine($"id:{id} next:{next} tangent:{tangent} _tangents.Count:{_tangents.Count}"); + if (next > 0 && next < _tangents.Count)//线性插值 + { + var (_, _, t) = CommonMath.Project2DLine(point, _bezierPoints[id], _bezierPoints[next]); + var partial = t / Vector2.Distance(_bezierPoints[id], _bezierPoints[next]); + if (partial >= 0 && partial <= 1) + { + tangent = CommonMath.RoundTh(_tangents[id] + + partial * CommonMath.RoundTh(_tangents[next] - _tangents[id])); + if (CommonMath.RoundTh(_tangents[next] - _tangents[id]) > 5) + Console.WriteLine($"bezier tangents bug, tanget: {id}:{_tangents[id]} {next}:{_tangents[next]}"); + } + // else Console.WriteLine("bezier tangents bug"); + } + return (lp, tangent, bias, fd + _sumDistances[id]); + } + + public override float Length() + { + return _length; + } + + public override float QueryCurvature(float position) + { + int id = _sumDistances.Count - 1; + if (position <= 0) id = 0; + else + { + for (int i = 1; i < _sumDistances.Count; i++) + { + if (position > _sumDistances[i - 1] && position <= _sumDistances[i]) + { + id = i; + break; + } + } + } + + var result = _curvatures[id]; + if (id > 0 && id < _sumDistances.Count - 1)//插值 + { + var partial = (position - _sumDistances[id - 1]) / (_sumDistances[id] - _sumDistances[id - 1]); + if (partial >= 0 && partial <= 1) result = (1 - partial) * _curvatures[id - 1] + partial * _curvatures[id]; + else Console.WriteLine("bezier curvature bug"); + } + + return result; + } + + public Vector3 QueryBezierPointsById(int id) + { + if (id < 0 || id > Resolution) + { + Console.WriteLine($"QueryBezierPointsById out of range, Resolution:{Resolution},id:{id}."); + return new Vector3(0, 0, 0); + } + + return new Vector3(_bezierPoints[id].X, _bezierPoints[id].Y, _tangents[id]); + } + + public List ControlPoints => _controlPoints; + + public int Resolution => _resolution; + /// + /// 仅用于simple显示路径方向 + /// + public int Direction = 1; + public int Order => _order; + + // public List Tangents => _tangents; + + public void UpdateControlPoint(int id, Vector2 point) + { + _controlPoints[id] = point; + InitializeBezier(); + } + + public void AddControlPoint(int id, Vector2 point) + { + _controlPoints.Insert(id, point); + InitializeBezier(); + } + + public void RemoveControlPoint(int id) + { + _controlPoints.RemoveAt(id); + InitializeBezier(); + } + + public Vector2 GetMidPoint() + { + return _bezierPoints[(int)Math.Ceiling(_resolution / 2d)]; + } + + private void InitializeBezier() + { + _order = _controlPoints.Count - 1; + // _bezierPoints = new List(); + var delta = 1.0f / _resolution; + // for (int t = 0; t <= _resolution; t += 1)//下面循环算了,没必要先递归算一遍 + // _bezierPoints.Add(new Vector2(DeCasteljauX(_order, 0, t*delta), DeCasteljauY(_order, 0, t*delta))); + var allPoints = new List>>(); + for (var i = 0; i < _order; i++) + { + var size = allPoints.Count; + var morePoints = new List>(); + for (var j = 0; j < _order - i; j++) + { + var points = new List(); + for (int t = 0; t <= _resolution; t += 1) + { + float p0x; + float p1x; + float p0y; + float p1y; + var z = t; + if (size > 0) + { + p0x = allPoints[i - 1][j][z].X; + p1x = allPoints[i - 1][j + 1][z].X; + p0y = allPoints[i - 1][j][z].Y; + p1y = allPoints[i - 1][j + 1][z].Y; + } + else + { + p0x = _controlPoints[j].X; + p1x = _controlPoints[j + 1].X; + p0y = _controlPoints[j].Y; + p1y = _controlPoints[j + 1].Y; + } + + var part = t * delta; + points.Add(new Vector2((1 - part) * p0x + part * p1x, (1 - part) * p0y + part * p1y)); + } + morePoints.Add(points); + } + allPoints.Add(morePoints); + } + + _bezierPoints = allPoints.Last().Last(); + _tangentInfo = allPoints; + _tangents = Enumerable.Repeat(0f, _bezierPoints.Count).ToList(); + _curvatures = Enumerable.Repeat(0f, _bezierPoints.Count).ToList(); + var p2 = allPoints[Order - 2]; + for (var id = 0; id < _bezierPoints.Count; ++id) + { + _tangents[id] = + (float)(Math.Atan2(p2[1][id].Y - p2[0][id].Y, p2[1][id].X - p2[0][id].X) / Math.PI * 180); + if (id != 0) _curvatures[id] = (float)((CommonMath.ThDiff(_tangents[id], _tangents[id - 1]) / 180 * Math.PI) + / (Vector2.Distance(_bezierPoints[id], _bezierPoints[id - 1]) / 1000)); + } + // Console.WriteLine($"{string.Join("\n", _tangents.Select((val, i) => $"{i}: {val}"))}"); + _tangents[0] = _tangents[1]; // todo: here is temporary fix + _curvatures[0] = _curvatures[1]; + for (var id = 1; id < _bezierPoints.Count - 1; ++id)//前移0.5 + _curvatures[id] = (_curvatures[id] + _curvatures[id + 1]) / 2; + + _remainDistances = Enumerable.Repeat(0f, _bezierPoints.Count).ToList(); + _sumDistances = Enumerable.Repeat(0f, _bezierPoints.Count).ToList(); + for (var i = _bezierPoints.Count - 2; i >= 0; --i) + { + _remainDistances[i] = + _remainDistances[i + 1] + Vector2.Distance(_bezierPoints[i], _bezierPoints[i + 1]); + } + for (var i = 1; i < _bezierPoints.Count; ++i) + { + _sumDistances[i] = + _sumDistances[i - 1] + Vector2.Distance(_bezierPoints[i], _bezierPoints[i - 1]); + } + _length = _sumDistances.Last(); + + _minX = _bezierPoints.Min(pp => pp.X); + _minY = _bezierPoints.Min(pp => pp.Y); + + var tmpList = _bezierPoints.Select((point, index) => (point, index)).ToList(); + return; + void GenerateGridMapping(ref Dictionary> dict, float gSize) + { + dict = new Dictionary>(); + foreach (var (point, index) in tmpList) + { + var hash = CalculateHash(point, gSize); + if (dict.TryGetValue(hash, out var ll)) + ll.Add((point, index)); + else dict[hash] = new List<(Vector2 Point, int Id)>() { (point, index) }; + } + } + + GenerateGridMapping(ref _pointsMappingSmall, 100); + GenerateGridMapping(ref _pointsMappingBig, 1000); + } + + private uint CalculateHash(Vector2 point, float gridSize, int xBias = 0, int yBias = 0) + { + return (uint)(((int)((point.X - _minX) / gridSize) + xBias) << 16 + (((int)((point.Y - _minY) / gridSize) + yBias) & 0xffff)); + } + + private readonly List<(int X, int Y)> _bias = new() + { + new(-1, -1), new(-1, 0), new(-1, 1), + new(0, -1), new(0, 0), new(0, 1), + new(1, -1), new(1, 0), new(1, 1), + }; + + private float DeCasteljauX(int i, int j, float t) + { + if (i == 1) + return (1 - t) * _controlPoints[j].X + t * _controlPoints[j + 1].X; + return (1 - t) * DeCasteljauX(i - 1, j, t) + t * DeCasteljauX(i - 1, j + 1, t); + } + + private float DeCasteljauY(int i, int j, float t) + { + if (i == 1) + return (1 - t) * _controlPoints[j].Y + t * _controlPoints[j + 1].Y; + return (1 - t) * DeCasteljauY(i - 1, j, t) + t * DeCasteljauY(i - 1, j + 1, t); + } + + private int _order; + private int _resolution; + private List _controlPoints; + private List _bezierPoints; + private List>> _tangentInfo; + private List _tangents; + private List _remainDistances; + private List _sumDistances; + private List _curvatures; + private Dictionary> _pointsMappingSmall; + private Dictionary> _pointsMappingBig; + private float _minX, _minY; + private float _length; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Geometries/CircularArc.cs b/CommonUsage-MultiVehicleSync/commonusage/Geometries/CircularArc.cs new file mode 100644 index 0000000..2126385 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Geometries/CircularArc.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Numerics; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using CommonUsage.Mathematics; + +namespace CommonUsage.Geometries +{ + public class CircularArc : AbstractGeometry + { + /// + /// 以center为圆心、radius为半径,从angleStart逆时针转到angleEnd所构成的圆弧。direction表示圆弧走向。 + /// + /// + /// + /// + /// + /// 表示圆弧走向,1为angleStart到angleEnd,-1为angleEnd到angleStart + public CircularArc(Vector2 center, float radius, float angleStart, float angleEnd, int direction, Padding paddingType) + { + _center = center; + _radius = radius; + _angleStart = angleStart; + _angleEnd = angleEnd; + _direction = direction; + PaddingType = paddingType; + + ChangeShape(); + CalculateVisPoints(); + } + + public override void Visualize(Action processDot, Action processLine, + bool visExtendedPart = false) + { + lock (_visPoints) + { + if (visExtendedPart) + { + + } + + for (var i = 0; i < _visPoints.Length - 1; ++i) + { + if ((i == 0 || i == _visPoints.Length - 2) && !visExtendedPart) continue; + var color = Color.Red; + if (i == 0 || i == _visPoints.Length - 2) color = Color.Gray; + processLine(new VisLine(_visPoints[i], _visPoints[i + 1], + false, i == (_visPoints.Length - 1) / 2, color)); + } + + if (visExtendedPart) + { + + } + } + } + + public void SwitchSide() + { + (_angleStart, _angleEnd) = (_angleEnd, _angleStart); + ChangeShape(); + CalculateVisPoints(); + } + + public float VisAngleResolution = 1; + + public Vector2 Center + { + get => _center; + set + { + _center = value; + ChangeShape(); + CalculateVisPoints(); + } + } + + public float Radius + { + get => _radius; + set + { + _radius = value; + ChangeShape(); + CalculateVisPoints(); + } + } + + public float AngleStart + { + get => _angleStart; + set + { + _angleStart = value; + ChangeShape(); + CalculateVisPoints(); + } + } + + public float AngleEnd + { + get => _angleEnd; + set + { + _angleEnd = value; + ChangeShape(); + CalculateVisPoints(); + } + } + + public int Direction + { + get => _direction; + set + { + _direction = value; + ChangeShape(); + CalculateVisPoints(); + } + } + + public float AngleRange => _totalTh; + + public Vector2 PointStart => _center + new Vector2(_radius * (float)Math.Cos(_angleStart / 180 * Math.PI), + _radius * (float)Math.Sin(_angleStart / 180 * Math.PI)); + + public Vector2 PointEnd => _center + new Vector2(_radius * (float)Math.Cos(_angleEnd / 180 * Math.PI), + _radius * (float)Math.Sin(_angleEnd / 180 * Math.PI)); + + public Vector2 Src => _src; + + public Vector2 Dst => _dst; + + public float TangentSrc => _tangentSrc; + + public float TangentDst => _tangentDst; + + public override (Vector2 Pt, float Angle, float Bias, float Position) QueryTangentPoint(Vector2 point) + { + var queryTh = (float)(Math.Atan2(point.Y - _center.Y, point.X - _center.X) / Math.PI * 180); + + var p = new Vector2(); + var tangent = 0f; + var pd = 0f; + var bestBias = float.MaxValue; + + if ((((int)PaddingType >> 4) & 0x1) == 1) + { + var (bias1, hPnt1, fd1) = CommonMath.Project2DLine(point, _beforeStartSrc, _src); + if (fd1 <= 1000) + { + p = hPnt1; + tangent = (_direction >= 0 ? _angleStart : _angleEnd) + 90 * _direction; + pd = fd1; + bestBias = bias1; + } + } + + if (((int)PaddingType & 0x1) == 1) + { + var (bias2, hPnt2, fd2) = CommonMath.Project2DLine(point, _dst, _afterEndDst); + if (fd2 >= 0 && Math.Abs(bias2) < Math.Abs(bestBias)) + { + p = hPnt2; + tangent = (_direction >= 0 ? _angleEnd : _angleStart) + 90 * _direction; + pd = _totalLen + fd2; + bestBias = bias2; + } + } + + var th1 = _direction == 1 ? CommonMath.ThDiff(queryTh, _angleStart) : CommonMath.ThDiff(_angleEnd, queryTh); + // todo: urgent bug! should use better strategy to prevent sign problem + if (th1 < -55) th1 += 360; + var arcBias = (_radius - Vector2.Distance(point, _center)) * _direction; + if (Math.Abs(arcBias) < Math.Abs(bestBias)) + { + p = _center + _radius * new Vector2((float)Math.Cos(queryTh / 180 * Math.PI), + (float)Math.Sin(queryTh / 180 * Math.PI)); + tangent = queryTh + 90 * _direction; + pd = _radius * th1 / 180 * (float)Math.PI; + bestBias = arcBias; + } + + return (p, tangent, bestBias, pd); + } + + public override float QueryCurvature(float position) + { + // var theta = (float)(_angleEnd - position / _radius / Math.PI * 180f + Math.PI); + // return Vectoriel.FromAngleLen(theta, 1f / _radius); + return 1000f / _radius * _direction; + } + + public override float Length() + { + return _totalLen; + } + + private void CalculateVisPoints() + { + lock (_visPoints) + { + // todo: overlapping start and end is problematic + var ptCnt = (int)Math.Ceiling((_angleEnd + 360 - _angleStart) % 360 / VisAngleResolution); + _visPoints = new Vector2[ptCnt + 2]; + + var starting = _angleStart; + if (_direction == -1) starting = _angleEnd; + _visPoints[0] = _beforeStartSrc; + + for (var j = 0; j < ptCnt; ++j) + { + var th = starting + j * VisAngleResolution * _direction; + var radAngle = (float)(th / 180f * Math.PI); + _visPoints[j + 1] = Center + new Vector2((float)Math.Cos(radAngle), (float)Math.Sin(radAngle)) * Radius; + } + + _visPoints[ptCnt + 1] = _afterEndDst; + } + } + + private void ChangeShape() + { + _totalTh = CommonMath.ThDiff(_angleEnd, _angleStart); + if (_totalTh < 0) _totalTh += 360; + _totalLen = _radius * _totalTh / 180 * (float)Math.PI; + + var radAngleStart = _angleStart / 180 * Math.PI; + var radAngleEnd = _angleEnd / 180 * Math.PI; + double srcAngle = radAngleStart, dstAngle = radAngleEnd; + if (_direction == -1) (srcAngle, dstAngle) = (dstAngle, srcAngle); + _src = _center + new Vector2((float)Math.Cos(srcAngle), (float)Math.Sin(srcAngle)) * _radius; + _dst = _center + new Vector2((float)Math.Cos(dstAngle), (float)Math.Sin(dstAngle)) * _radius; + _beforeStartSrc = CommonMath.Transform2D(_src, + (_direction >= 0 ? _angleStart : _angleEnd) + 90 * _direction, new Vector2(-1000, 0)); + _afterEndDst = CommonMath.Transform2D(_dst, (_direction >= 0 ? _angleEnd : _angleStart) + 90 * _direction, + new Vector2(1000, 0)); + _tangentSrc = QueryTangentPoint(_src).Angle; + _tangentDst = QueryTangentPoint(_dst).Angle; + } + + private Vector2 _center; + private float _radius, _angleStart, _angleEnd; + private int _direction; + + private float _totalTh, _totalLen; + private Vector2 _src, _dst; + private float _tangentSrc, _tangentDst; + private Vector2 _beforeStartSrc, _afterEndDst; + + private Vector2[] _visPoints = Array.Empty(); + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Geometries/NurbsCurve.cs b/CommonUsage-MultiVehicleSync/commonusage/Geometries/NurbsCurve.cs new file mode 100644 index 0000000..aa45227 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Geometries/NurbsCurve.cs @@ -0,0 +1,349 @@ +using CommonUsage.Mathematics; +using System.Collections.Generic; +using System.Numerics; +using System; +using System.Linq; + +namespace CommonUsage.Geometries +{ + public class NurbsCurve : AbstractGeometry + { + + public NurbsCurve(List controlPoints, List weights, List knotVector, int frame = 100) + { + _controlPoints = controlPoints; + _weights = weights; + _knotVector = knotVector; + _frame = frame; + InitializeNurbs(); + } + + public override void Visualize(Action processDot, Action processLine, bool visExtendedPart = false) + { + if (VisualizeOption.DrawAuxiliary) + for (var i = 0; i < _controlPoints.Count - 1; ++i) + { + processLine(new VisLine(_controlPoints[i], _controlPoints[i + 1], + false, false, VisualizeOption.AuxiliaryColor)); + if (i == 0) continue; + processDot(new VisDot(_controlPoints[i], VisualizeOption.AuxiliaryColor)); + } + + for (var i = 0; i < _nurbsPoints.Count - 1; ++i) + { + if (Direction == -1) + { + processLine(new VisLine(_nurbsPoints[i + 1], _nurbsPoints[i], + false, i == (int)(_nurbsPoints.Count / 2), VisualizeOption.MainColor, 2)); + } + else + { + processLine(new VisLine(_nurbsPoints[i], _nurbsPoints[i + 1], + false, i == (int)(_nurbsPoints.Count / 2), VisualizeOption.MainColor, 2)); + } + } + } + public (Vector2 Point, int Id) QueryPoint(Vector2 point) + { + var p = new Vector2(); + var id = -1; + var bestDistance = float.MaxValue; + + var hashes = _bias.Select(bb => CalculateHash(point, 100, bb.X, bb.Y)).ToList(); + + void TryQuery(Dictionary> dict, List hashList) + { + foreach (var hash in hashList) + { + if (!dict.TryGetValue(hash, out var ll)) continue; + foreach (var (q, qId) in ll) + { + var d = Vector2.Distance(q, point); + if (d < bestDistance) + { + p = q; + id = qId; + bestDistance = d; + } + } + } + } + + if (id == -1) + { + // todo: improve the way to find closest point if mappings fail + (p, id) = _nurbsPoints.Select((p, i) => (p, i)) + .OrderBy(pair => CommonMath.dist(pair.p.X, pair.p.Y, point.X, point.Y)).First(); + } + + return (p, id); + } + + private uint CalculateHash(Vector2 point, float gridSize, int xBias = 0, int yBias = 0) + { + return (uint)(((int)((point.X - _minX) / gridSize) + xBias) << 16 + (((int)((point.Y - _minY) / gridSize) + yBias) & 0xffff)); + } + + private readonly List<(int X, int Y)> _bias = new() + { + new(-1, -1), new(-1, 0), new(-1, 1), + new(0, -1), new(0, 0), new(0, 1), + new(1, -1), new(1, 0), new(1, 1), + }; + + public override (Vector2 Pt, float Angle, float Bias, float Position) QueryTangentPoint(Vector2 point) + { + var (p, id) = QueryPoint(point); + var tangent = _tangents[id]; + var (bias, lp, fd) = CommonMath.Project2DLine(point, p, tangent); + var next = fd > 0 ? id + 1 : id - 1; + if (next > 0 && next < _tangents.Count)//线性插值 + { + var (_, _, t) = CommonMath.Project2DLine(point, _nurbsPoints[id], _nurbsPoints[next]); + var partial = t / Vector2.Distance(_nurbsPoints[id], _nurbsPoints[next]); + if (partial >= 0 && partial <= 1) + { + tangent = CommonMath.RoundTh(_tangents[id] + + partial * CommonMath.RoundTh(_tangents[next] - _tangents[id])); + if (CommonMath.RoundTh(_tangents[next] - _tangents[id]) > 5) + Console.WriteLine($"Nurbs tangents bug, tanget: {id}:{_tangents[id]} {next}:{_tangents[next]}"); + } + else Console.WriteLine("Nurbs tangents bug"); + } + return (lp, tangent, bias, fd + _sumDistances[id]); + } + + public override float QueryCurvature(float position) + { + int id = _sumDistances.Count - 1; + if (position <= 0) id = 0; + else + { + for (int i = 1; i < _sumDistances.Count; i++) + { + if (position > _sumDistances[i - 1] && position <= _sumDistances[i]) + { + id = i; + break; + } + } + } + + var result = _curvatures[id]; + if (id > 0 && id < _sumDistances.Count - 1)//插值 + { + var partial = (position - _sumDistances[id - 1]) / (_sumDistances[id] - _sumDistances[id - 1]); + if (partial >= 0 && partial <= 1) result = (1 - partial) * _curvatures[id - 1] + partial * _curvatures[id]; + else Console.WriteLine("Nurbs curvature bug"); + } + + return result; + } + + public Vector3 QueryNurbsPointsById(int id) + { + if (id < 0 || id > Frame) + { + Console.WriteLine($"QueryBezierPointsById out of range, Resolution:{Frame},id:{id}."); + return new Vector3(0, 0, 0); + } + + return new Vector3(_nurbsPoints[id].X, _nurbsPoints[id].Y, _tangents[id]); + } + public override float Length() + { + return _length; + } + + public int Order => _order; + public List ControlPoints => _controlPoints; + public List Weights => _weights; + public List KnotVector => _knotVector; + public int Frame => _frame; + + public int Direction = 1; + + + public void UpdateControlPoint(int id, Vector2 point) + { + _controlPoints[id] = point; + InitializeNurbs(); + } + public void UpdateNurbsWeihgts(int id, float weight) + { + _weights[id] = weight; + InitializeNurbs(); + + } + public void AddControlPoint(int id, Vector2 point) + { + _controlPoints.Insert(id, point); + InitializeNurbs(); + } + + public void RemoveControlPoint(int id) + { + _controlPoints.RemoveAt(id); + InitializeNurbs(); + } + + public Vector2 GetMidPoint() + { + return _nurbsPoints[(int)Math.Ceiling(_frame / 2d)]; + } + + private void InitializeNurbs() + { + _order = _controlPoints.Count - 1; + List> allpoints = new List>(); + List nurbsCurvePoints = new List(); + float delta = 1.0f / Frame; + + for (float t = 0; t <= 1; t += delta) + { + var (point, tangent) = DeBoorAlgorithm(t); + var points = new List + { + point, + point + tangent // Tangent endpoint + }; + allpoints.Add(points); + nurbsCurvePoints.Add(point); // Store the curve point separately + } + + _nurbsPoints = nurbsCurvePoints; + _tangents = Enumerable.Repeat(0f, _nurbsPoints.Count).ToList(); + _curvatures = Enumerable.Repeat(0f, _nurbsPoints.Count).ToList(); + + for (var id = 0; id < _nurbsPoints.Count - 1; ++id) + { + Vector2 p1 = _nurbsPoints[id]; + Vector2 p2 = _nurbsPoints[id + 1]; + + float tangentAngle = (float)Math.Atan2(p2.Y - p1.Y, p2.X - p1.X) * 180 / (float)Math.PI; + _tangents[id] = tangentAngle; + + // Calculate curvature using finite differences of tangent (second derivative approximation) + if (id > 0) + { + float previousTangent = _tangents[id - 1]; + float curvature = (float)(CommonMath.ThDiff(tangentAngle, previousTangent) * Math.PI / 180) / + (Vector2.Distance(p1, p2) / 1000); + _curvatures[id] = curvature; + } + } + + _curvatures.Insert(0, _curvatures[0]); + for (var id = 1; id < _curvatures.Count - 1; ++id) + { + _curvatures[id] = (_curvatures[id] + _curvatures[id + 1]) / 2; + } + + _remainDistances = Enumerable.Repeat(0f, _nurbsPoints.Count).ToList(); + _sumDistances = Enumerable.Repeat(0f, _nurbsPoints.Count).ToList(); + _remainDistances[_nurbsPoints.Count - 1] = 0; + + for (var i = _nurbsPoints.Count - 2; i >= 0; --i) + { + _remainDistances[i] = _remainDistances[i + 1] + Vector2.Distance(_nurbsPoints[i], _nurbsPoints[i + 1]); + } + + _sumDistances[0] = 0; + for (var i = 1; i < _nurbsPoints.Count; ++i) + { + _sumDistances[i] = _sumDistances[i - 1] + Vector2.Distance(_nurbsPoints[i], _nurbsPoints[i - 1]); + } + + _length = _sumDistances.Last(); + + _minX = _nurbsPoints.Min(pp => pp.X); + _minY = _nurbsPoints.Min(pp => pp.Y); + + var tmpList = _nurbsPoints.Select((point, index) => (point, index)).ToList(); + // GenerateGridMapping(ref _pointsMappingSmall, 100, tmpList); + // GenerateGridMapping(ref _pointsMappingBig, 1000, tmpList); + } + + + + + private float CalculateLength() + { + return _nurbsPoints.Zip(_nurbsPoints.Skip(1), Vector2.Distance).Sum(); + } + + private (Vector2, Vector2) DeBoorAlgorithm(float t) + { + Vector2 numerator = Vector2.Zero; + Vector2 tangentNumerator = Vector2.Zero; + float denominator = 0f; + + // Calculate the point on the curve + for (int i = 0; i < ControlPoints.Count; ++i) + { + float basis = BasisFunction(i, _order, t) * Weights[i]; + numerator += basis * ControlPoints[i]; + denominator += basis; + } + + Vector2 point = numerator / denominator; + + // Calculate the tangent vector using the analytical derivative + for (int i = 0; i < ControlPoints.Count; ++i) + { + float basisDerivative = BasisFunctionDerivative(i, _order, t) * Weights[i]; + tangentNumerator += basisDerivative * ControlPoints[i]; + } + Vector2 tangent = tangentNumerator / denominator; + + return (point, tangent); + } + + private float BasisFunction(int i, int p, float t) + { + if (p == 0) + return (KnotVector[i] <= t && t < KnotVector[i + 1]) ? 1.0f : 0.0f; + + float denom1 = KnotVector[i + p] - KnotVector[i]; + float term1 = denom1 == 0 ? 0 : ((t - KnotVector[i]) / denom1) * BasisFunction(i, p - 1, t); + + float denom2 = KnotVector[i + p + 1] - KnotVector[i + 1]; + float term2 = denom2 == 0 ? 0 : ((KnotVector[i + p + 1] - t) / denom2) * BasisFunction(i + 1, p - 1, t); + + return term1 + term2; + } + + private float BasisFunctionDerivative(int i, int k, float t) + { + if (k == 0) return 0; + + float denom1 = KnotVector[i + k] - KnotVector[i]; + float denom2 = KnotVector[i + k + 1] - KnotVector[i + 1]; + + float term1 = denom1 != 0 ? BasisFunction(i, k - 1, t) / denom1 : 0; + float term2 = denom1 != 0 ? (t - KnotVector[i]) * BasisFunctionDerivative(i, k - 1, t) / denom1 : 0; + + float term3 = denom2 != 0 ? -BasisFunction(i + 1, k - 1, t) / denom2 : 0; + float term4 = denom2 != 0 ? (KnotVector[i + k + 1] - t) * BasisFunctionDerivative(i + 1, k - 1, t) / denom2 : 0; + + return term1 + term2 + term3 + term4; + } + + private int _order; + private List _controlPoints; + private List _weights; + private List _knotVector; + private int _frame; + private List _nurbsPoints; + private List>> _tangentPoints; + private List _curvatures; + private List _sumDistances; + private List _remainDistances; + private float _minX, _minY; + private float _length; + private Dictionary> _pointsMappingSmall; + private Dictionary> _pointsMappingBig; + private List _tangents; + + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Geometries/Vectoriel.cs b/CommonUsage-MultiVehicleSync/commonusage/Geometries/Vectoriel.cs new file mode 100644 index 0000000..86b72a9 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Geometries/Vectoriel.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Text; + +namespace CommonUsage.Geometries +{ + /// + /// MDCS数学类:向量。 + /// + public class Vectoriel + { + public Vectoriel() + { + _vec2 = Vector2.Zero; + _dir2 = Vector2.Normalize(_vec2); + _len = _vec2.Length(); + _angle = (float)(Math.Atan2(_vec2.Y, _vec2.X) / Math.PI * 180f); + } + + public Vectoriel(Vector2 vec) + { + _vec2 = vec; + _dir2 = Vector2.Normalize(_vec2); + _len = _vec2.Length(); + _angle = (float)(Math.Atan2(_vec2.Y, _vec2.X) / Math.PI * 180f); + } + + /// + /// 通过笛卡尔坐标系X和Y值构建向量。 + /// + /// + /// + /// + public static Vectoriel FromXY(float x, float y) + { + return new Vectoriel(new Vector2(x, y)); + } + + /// + /// 通过极坐标系的角度和距离值构建向量。 + /// + /// + /// + /// + public static Vectoriel FromAngleLen(float angle, float len) + { + var rad = angle / 180f * Math.PI; + return new Vectoriel(new Vector2((float)Math.Cos(rad), (float)Math.Sin(rad)) * len); + } + + public static implicit operator Vector2(Vectoriel vec) + { + return vec._vec2; + } + + public static explicit operator Vectoriel(Vector2 vec) + { + return FromXY(vec.X, vec.Y); + } + + public Vector2 Direction => _dir2; + + public float Length => _len; + + public float Angle => _angle; + + private Vector2 _vec2, _dir2; + private float _len, _angle; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Mathematics/CommonMath.cs b/CommonUsage-MultiVehicleSync/commonusage/Mathematics/CommonMath.cs new file mode 100644 index 0000000..df49d5b --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Mathematics/CommonMath.cs @@ -0,0 +1,774 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Numerics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace CommonUsage.Mathematics +{ + + using T3 = Tuple; + using D3 = Tuple; + + public class CommonMath + { + public class PrimeEnumerator + { + public PrimeEnumerator(List items, Func process) + { + _n = items.Count; + _items = items; + _process = process; + + foreach (var pNum in _primes) + { + if (_n % pNum != 0) + { + _a = pNum; + _b = 11; + break; + } + } + } + + public void Enumerate() + { + using (var enumerator = Get().GetEnumerator()) + { + while (enumerator.MoveNext()) { } + } + } + + private readonly int _n, _a, _b; + private readonly int[] _primes = new[] { 29, 23, 19, 17, 13 }; + private List _items; + private readonly Func _process; + + private IEnumerable Get() + { + for (var i = 0; i < _n; ++i) + { + var id = (i * _a + _b) % _n; + yield return _process(_items[id]); + } + } + } + + private static IEnumerable> GetPermutationsInternal(IEnumerable list, int length) + { + if (length == 1) return list.Select(t => new T[] { t }); + + return GetPermutationsInternal(list, length - 1) + .SelectMany(t => list.Where(e => !t.Contains(e)), + (t1, t2) => t1.Concat(new T[] { t2 })); + } + + /// + /// 得到一组数据的所有排列。 + /// + /// 元素数据类型 + /// 所有待选元素 + /// 所选出的元素数量 + /// + public static List> GetPermutations(List list, int selectNum) + { + return GetPermutationsInternal(list, selectNum).Select(ll => ll.ToList()).ToList(); + } + + public static (float bias, Vector2 hPnt, float d) Project2DLine(Vector2 pnt, Vector2 segSt, + Vector2 segEnd) + { + var dir = Vector2.Normalize(segEnd - segSt); + var fd = Vector2.Dot(pnt - segSt, dir); + var hPnt = segSt + fd * dir; + var bias = dir.X * (pnt.Y-segSt.Y) - (pnt.X-segSt.X) * dir.Y; + return (bias, hPnt, fd); + } + + public static (float bias, Vector2 hPnt, float fd) Project2DLine(Vector2 pnt, Vector2 segSt, float tangent) + { + var dir = new Vector2((float)System.Math.Cos(tangent / 180 * System.Math.PI), (float)System.Math.Sin(tangent / 180 * System.Math.PI)); + var fd = Vector2.Dot(pnt - segSt, dir); + var hPnt = segSt + fd * dir; + var bias = dir.X * (pnt.Y - segSt.Y) - (pnt.X - segSt.X) * dir.Y; + return (bias, hPnt, fd); + } + + public class LineEqu + { + public double A, B, C, ln, dAB; + public double px1, px2, py1, py2; + public float midX; + public float midY; + } + // Fit line with PCA. + public LineEqu CalcLine(IEnumerable tls) + { + var lidarPoint2Ds = tls as Vector2[] ?? tls.ToArray(); + float fx = lidarPoint2Ds.Average(f => f.X); + float fy = lidarPoint2Ds.Average(f => f.Y); + float fxx = lidarPoint2Ds.Average(f => f.X * f.X); + float fxy = lidarPoint2Ds.Average(f => f.X * f.Y); + float fyy = lidarPoint2Ds.Average(f => f.Y * f.Y); + float a = fxx - fx * fx, b = fxy - fx * fy, c = fyy - fy * fy; + double sqt = System.Math.Sqrt((a - c) * (a - c) + 4 * b * b); + double l1 = a + c + sqt; + double l2 = a + c - sqt; + double dx, dy; + if (System.Math.Abs(a - l1 / 2) > System.Math.Abs(c - l1 / 2)) + { + dy = l1 / 2 - a; dx = b; + } + else + { + dx = l1 / 2 - c; dy = b; + } + double norm = System.Math.Sqrt(dx * dx + dy * dy); + dx /= norm; dy /= norm; + double A = dy, B = -dx, C = dx * fy - dy * fx; + double dAB = System.Math.Sqrt(A * A + B * B); + + return new CommonMath.LineEqu + { + A = A, + B = B, + C = C, + ln = lidarPoint2Ds.Average(p => System.Math.Abs(p.X * A + p.Y * B + C) / dAB), + midX = fx, + midY = fy + }; + } + + public static double QuadInterp3(double[] confsF) + { + if (confsF[0] > confsF[1] && confsF[0] > confsF[2]) + { + //printf("left overflow...\n"); + return -1; + } + + if (confsF[1] > confsF[0] && confsF[1] > confsF[2]) + { + return (-(confsF[2] - confsF[0]) / 2.0f / (confsF[0] + confsF[2] - 2.0f * confsF[1] + 0.0001f)); + } + if (confsF[2] > confsF[0] && confsF[2] > confsF[1]) + { + //printf("right overflow...\n"); + return 1; + } + return 0; + } + + public static double cross(PointF O, PointF A, PointF B) + { + return (A.X - O.X) * (B.Y - O.Y) - (A.Y - O.Y) * (B.X - O.X); + } + + public static List GetConvexHull(List points) + { + if (points == null) + return null; + + if (points.Count() <= 1) + return points; + + int n = points.Count(), k = 0; + List H = new List(new PointF[2 * n]); + + points.Sort((a, b) => + a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); + + // Build lower hull + for (int i = 0; i < n; ++i) + { + while (k >= 2 && cross(H[k - 2], H[k - 1], points[i]) <= 0) + k--; + H[k++] = points[i]; + } + + // Build upper hull + for (int i = n - 2, t = k + 1; i >= 0; i--) + { + while (k >= t && cross(H[k - 2], H[k - 1], points[i]) <= 0) + k--; + H[k++] = points[i]; + } + + return H.Take(k - 1).ToList(); + } + + public static bool IsPointInPolygon4(PointF[] polygon, PointF testPoint) + { + // ray casting odd even test. + bool result = false; + int j = polygon.Count() - 1; + for (int i = 0; i < polygon.Count(); i++) + { + if (polygon[i].Y < testPoint.Y && polygon[j].Y >= testPoint.Y || + polygon[j].Y < testPoint.Y && polygon[i].Y >= testPoint.Y) + { + if (polygon[i].X + (testPoint.Y - polygon[i].Y) / (polygon[j].Y - polygon[i].Y) * + (polygon[j].X - polygon[i].X) < testPoint.X) + { + result = !result; + } + } + + j = i; + } + + return result; + } + + public static double Exp(double val) + { + if (val < -20) return 0.0000001; + if (val > 20) return 99999999999999; + long tmp = (long)(1512775 * val + 1072632447); + return BitConverter.Int64BitsToDouble(tmp << 32); + } + public static double gaussmf(double x, double sig, double c) + { + return Exp(-(x - c) * (x - c) / (2 * sig * sig)); + } + + public static float Exp(float x) + { + if (x < -10) return 0; + if (x > 10) return 99999999999999; + x = 1.0f + x / 64f; + x *= x; + x *= x; + x *= x; + x *= x; + x *= x; + x *= x; + return x; + } + public static float gaussmf(float x, float sig, float c) + { + return Exp(-(x - c) * (x - c) / (2 * sig * sig)); + } + + public static D3 Transform2D(D3 src, D3 t) + { + var rth = src.Item3 / 180.0 * System.Math.PI; + var p1dtx = (src.Item1 + System.Math.Cos(rth) * t.Item1 - + System.Math.Sin(rth) * t.Item2); + var p1dty = (src.Item2 + System.Math.Sin(rth) * t.Item1 + + System.Math.Cos(rth) * t.Item2); + var p1dtth = src.Item3 + t.Item3; + return Tuple.Create(p1dtx, p1dty, p1dtth); + } + + public struct LngLatToXY + { + public double scale; + public double rad; + public double biasX, biasY; + } + + public static LngLatToXY GetTransformLngLatToXY(Vector2 lnglat1, Vector2 xy1, Vector2 lnglat2, Vector2 xy2) + { + var scale = (xy1 - xy2).Length() / (lnglat1 - lnglat2).Length(); + var dxy = (xy1 - xy2); + var dlnglat = lnglat1 - lnglat2; + var rad = System.Math.Atan2(dxy.X, dxy.Y) - System.Math.Atan2(dlnglat.X, dlnglat.Y); + var intm = lnglat1 * scale; + var biasX = xy1.X - (intm.X * System.Math.Cos(rad) - intm.Y * System.Math.Sin(rad)); + var biasY = xy1.Y - (intm.X * System.Math.Sin(rad) + intm.Y * System.Math.Cos(rad)); + return new LngLatToXY {rad = rad, biasX = biasX, biasY = biasY, scale = scale}; + } + + public Vector2 TransformLngLatToXY(Vector2 lnglat, LngLatToXY t) + { + var intm = lnglat * (float) t.scale; + return new Vector2((float) (intm.X * System.Math.Cos(t.rad) - intm.Y * System.Math.Sin(t.rad) + t.biasX), + (float) (intm.X * System.Math.Sin(t.rad) + intm.Y * System.Math.Cos(t.rad) + t.biasY)); + } + + public static D3 ReverseTransform(D3 dest, D3 t) + { + var rth = (dest.Item3 - t.Item3) / 180.0 * System.Math.PI; + var nxT = (dest.Item1 - System.Math.Cos(rth) * t.Item1 + + System.Math.Sin(rth) * t.Item2); + var nyT = (dest.Item2 - System.Math.Sin(rth) * t.Item1 - + System.Math.Cos(rth) * t.Item2); + var pth = dest.Item3 - t.Item3; + return Tuple.Create(nxT, nyT, pth); + } + + public static D3 SolveTransform2D(D3 src, D3 dest) + { + var th = dest.Item3 - src.Item3; + th = (th - System.Math.Round((th) / 360.0f) * 360); + var rth = src.Item3 / 180.0 * System.Math.PI; + var x = ((dest.Item1 - src.Item1) * System.Math.Cos(rth) + + (dest.Item2 - src.Item2) * System.Math.Sin(rth)); + var y = (-(dest.Item1 - src.Item1) * System.Math.Sin(rth) + + (dest.Item2 - src.Item2) * System.Math.Cos(rth)); + return Tuple.Create(x, y, th); + } + + public static T3 Transform2D(T3 src, T3 t) + { + var rth = src.Item3 / 180.0 * System.Math.PI; + var p1dtx = (float)(src.Item1 + System.Math.Cos(rth) * t.Item1 - + System.Math.Sin(rth) * t.Item2); + var p1dty = (float)(src.Item2 + System.Math.Sin(rth) * t.Item1 + + System.Math.Cos(rth) * t.Item2); + var p1dtth = src.Item3 + t.Item3; + return Tuple.Create(p1dtx, p1dty, p1dtth); + } + + public static Vector2 Transform2D(Vector3 src, Vector3 t) + { + var tup = Transform2D(Tuple.Create(src.X, src.Y, src.Z), Tuple.Create(t.X, t.Y, t.Z)); + return new Vector2(tup.Item1, tup.Item2); + } + + public static Vector2 Transform2D(Vector2 srcPos, float srcTh, Vector2 dt, float dth = 0) + { + var tup = Transform2D(Tuple.Create(srcPos.X, srcPos.Y, srcTh), Tuple.Create(dt.X, dt.Y, dth)); + return new Vector2(tup.Item1, tup.Item2); + } + + public static T3 ReverseTransform(T3 dest, T3 t) + { + var rth = (dest.Item3 - t.Item3) / 180.0 * System.Math.PI; + var nxT = (float)(dest.Item1 - System.Math.Cos(rth) * t.Item1 + + System.Math.Sin(rth) * t.Item2); + var nyT = (float)(dest.Item2 - System.Math.Sin(rth) * t.Item1 - + System.Math.Cos(rth) * t.Item2); + var pth = dest.Item3 - t.Item3; + return Tuple.Create(nxT, nyT, pth); + } + + public static T3 SolveTransform2D(T3 src, T3 dest) + { + var th = dest.Item3 - src.Item3; + th = (float)(th - System.Math.Round((th) / 360.0f) * 360); + var rth = src.Item3 / 180.0 * System.Math.PI; + var x = (float)((dest.Item1 - src.Item1) * System.Math.Cos(rth) + + (dest.Item2 - src.Item2) * System.Math.Sin(rth)); + var y = (float)(-(dest.Item1 - src.Item1) * System.Math.Sin(rth) + + (dest.Item2 - src.Item2) * System.Math.Cos(rth)); + return Tuple.Create(x, y, th); + } + + public static Vector2 SolveTransform2D(Vector2 srcPos, float srcTh, Vector2 dt, float dth = 0) + { + var tup = SolveTransform2D(Tuple.Create(srcPos.X, srcPos.Y, srcTh), Tuple.Create(dt.X, dt.Y, dth)); + return new Vector2(tup.Item1, tup.Item2); + } + + public static double dist(double x1, double y1, double x2, double y2) + { + return System.Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + } + + [StructLayout(LayoutKind.Explicit)] + private struct FloatIntUnion + { + [FieldOffset(0)] public float f; + + [FieldOffset(0)] public int tmp; + } + + public static float Sqrt(float z) + { + FloatIntUnion u; + u.tmp = 0; + u.f = z; + u.tmp -= 1 << 23; /* Subtract 2^m. */ + u.tmp >>= 1; /* Divide by 2. */ + u.tmp += 1 << 29; /* Add ((b + 1) / 2) * 2^m. */ + return u.f; + } + + public static float dist2(float x1, float y1, float x2, float y2) + { + return ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + } + + + public static float d2(float x1, float y1, float x2, float y2) + { + return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); + } + + public static float ThAverage(List angles) + { + var anchor = angles[0]; + var diff = 0f; + foreach (var angle in angles) + diff += ThDiff(angle, anchor); + return RoundTh(anchor + diff / angles.Count); + } + + public static float ThDiff(float th1, float th2) + { + return (float)(th1 - th2 - + System.Math.Round((th1 - th2) / 360.0f) * 360); + } + + public static double ThDiff(double th1, double th2) + { + return th1 - th2 - + System.Math.Round((th1 - th2) / 360.0f) * 360; + } + + public static double refine(double x) + { + if (x < 1 && x > -1) return x; + if (x > 1) + return (2 / (1 + System.Math.Exp(-((x - 1) * 2)))); + return (2 / (1 + System.Math.Exp(-((x + 1) * 2)))) - 2; + } + + /// + /// 求点p到两点式直线p1p2的距离 + /// + /// 点p的x坐标 + /// 点p的y坐标 + /// 直线点p1的x坐标 + /// 直线点p1的y坐标 + /// 直线点p2的x坐标 + /// 直线点p2的y坐标 + /// + public static double Point2LineDist(double x, double y, double x1, double y1, double x2, double y2) + { + double a1 = -(y1 - y2) / 10; + double b1 = (x1 - x2) / 10; + double c1 = (x1 * (y1 - y2) - y1 * (x1 - x2)) / 10; + return System.Math.Abs(a1 * x + b1 * y + c1) / System.Math.Sqrt(a1 * a1 + b1 * b1); + } + + public static double Point2LineDist(Vector2 p, LineSegment ll) + { + double a1 = -(ll.Src.Y - ll.Dst.Y) / 10; + double b1 = (ll.Src.X - ll.Dst.X) / 10; + double c1 = (ll.Src.X * (ll.Src.Y - ll.Dst.Y) - ll.Src.Y * (ll.Src.X - ll.Dst.X)) / 10; + return System.Math.Abs(a1 * p.X + b1 * p.Y + c1) / System.Math.Sqrt(a1 * a1 + b1 * b1); + } + + /// + /// 两条两点式直线间的夹角 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// 角度制 + public static double AngleBetweenLines(double x1, double y1, double x2, double y2, double x3, double y3, + double x4, double y4) + { + var vec1 = new Vector2((float)(x2 - x1), (float)(y2 - y1)); + var vec2 = new Vector2((float)(x4 - x3), (float)(y4 - y3)); + return System.Math.Acos(System.Math.Abs(Vector2.Dot(vec1, vec2) / vec1.Length() / vec2.Length())) / System.Math.PI * 180; + } + + public static double AngleBetweenLines(LineSegment ls1, LineSegment ls2) + { + return AngleBetweenLines(ls1.Src.X, ls1.Src.Y, ls1.Dst.X, ls1.Dst.Y, ls2.Src.X, ls2.Src.Y, ls2.Dst.X, + ls2.Dst.Y); + } + + /// + /// 两向量间夹角 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// 角度制 + public static double AngleBetweenVectors(double x1, double y1, double x2, double y2, double x3, double y3, + double x4, double y4) + { + var vec1 = new Vector2((float)(x2 - x1), (float)(y2 - y1)); + var vec2 = new Vector2((float)(x4 - x3), (float)(y4 - y3)); + return System.Math.Acos(Vector2.Dot(vec1, vec2) / vec1.Length() / vec2.Length()) / System.Math.PI * 180; + } + + /// + /// 两向量间夹角. + /// + /// + /// + /// 角度制 + public static double AngleBetweenVectors(Vector2 vec1, Vector2 vec2) + { + return System.Math.Acos(Vector2.Dot(vec1, vec2) / vec1.Length() / vec2.Length()) / System.Math.PI * 180; + } + + public static double AngleBetweenVectors(Vector3 vector1, Vector3 vector2) + { + float dotProduct = Vector3.Dot(vector1, vector2); + float magnitude1 = vector1.Length(); + float magnitude2 = vector2.Length(); + float cosine = dotProduct / (magnitude1 * magnitude2); + + return System.Math.Acos(cosine) / System.Math.PI * 180; + } + + /// + /// 求点到直线的垂足 + /// + /// + /// + /// + /// + /// + /// + /// + public static (double, double) PerpendicularPoint(double x, double y, double x1, double y1, double x2, double y2) + { + double lx = x2 - x1, ly = y2 - y1, dAB = lx * lx + ly * ly; + var u = ((x - x1) * lx + (y - y1) * ly) / dAB; + return new(x1 + u * lx, y1 + u * ly); + } + + public static Vector2 PerpendicularPoint(Vector2 p, LineSegment ls) + { + double lx = ls.Dst.X - ls.Src.X, ly = ls.Dst.Y - ls.Src.Y, dAB = lx * lx + ly * ly; + var u = ((p.X - ls.Src.X) * lx + (p.Y - ls.Src.Y) * ly) / dAB; + return new Vector2((float)(ls.Src.X + u * lx), (float)(ls.Src.Y + u * ly)); + } + + public static double PerpendicularPosition(double x, double y, double x1, double y1, double x2, double y2) + { + double lx = x2 - x1, ly = y2 - y1; + var dAB = CommonMath.Sqrt((float)(lx * lx + ly * ly)); + lx /= dAB; + ly /= dAB; + return (x - x1) * lx + (y - y1) * ly; + } + + + /// + /// 最小二乘法拟合直线,得到两点式。 + /// + /// 待拟合的点集,应至少有2个点。 + /// 检查是否所有点距直线的距离均小于maxDist2Line,若为-1则不检查。 + /// 返回两点式的两个端点坐标。若坐标为全0,则拟合失败。 + public static (bool, Vector2, Vector2) FitLineSegment(List pts, double maxDist2Line = -1) + { + if (pts.Count < 2) + { + Console.WriteLine($"Points too Few! {pts.Count}! Cannot perform line fitting!", + MethodBase.GetCurrentMethod()?.Name ?? "FitLine"); + return (false, Vector2.Zero, Vector2.Zero); + }; + + // y = kx + b + double A = 0, B = 0, C = 0, D = 0; + foreach (var p in pts) + { + A += p.X * p.X; + B += p.X; + C += p.X * p.Y; + D += p.Y; + } + + var tmp = A * pts.Count - B * B; + var k = (C * pts.Count - B * D) / tmp; + var b = (A * D - C * B) / tmp; + + double x1 = 0, + y1 = k * x1 + b, + x2 = 1000, + y2 = k * x2 + b; + + double CalcDist(ref bool fail, ref Vector2 endP, ref Vector2 endQ) + { + double distSum = 0; + double lx = x2 - x1, ly = y2 - y1, dAB = lx * lx + ly * ly; + double minU = double.MaxValue, maxU = double.MinValue; + + foreach (var p in pts) + { + var u = ((p.X - x1) * lx + (p.Y - y1) * ly) / dAB; + var perp = new Vector2((float)(x1 + u * lx), (float)(y1 + u * ly)); + if (u < minU) + { + endP = perp; + minU = u; + } + if (u > maxU) + { + endQ = perp; + maxU = u; + } + + var curDist = dist(perp.X, perp.Y, p.X, p.Y); + if (maxDist2Line > -1 && curDist > maxDist2Line) fail = true; + distSum += curDist; + } + + return distSum; + } + + var kbFail = false; + Vector2 endP1 = new Vector2(), endQ1 = new Vector2(); + double kbDist = CalcDist(ref kbFail, ref endP1, ref endQ1); + + // x = my + n + A = 0; + B = 0; + C = 0; + D = 0; + foreach (var p in pts) + { + A += p.X * p.Y; + B += p.Y * p.Y; + C += p.Y; + D += p.X; + } + + tmp = C * C - B * pts.Count; + var m = (C * D - A * pts.Count) / tmp; + var n = (A * C - B * D) / tmp; + y1 = 0; + x1 = m * y1 + n; + y2 = 1000; + x2 = m * y2 + n; + + var mnFail = false; + Vector2 endP2 = new Vector2(), endQ2 = new Vector2(); + double mnDist = CalcDist(ref mnFail, ref endP2, ref endQ2); + + Vector2 endP = endP1, endQ = endQ1; + if (mnDist < kbDist) + { + if (mnFail) return (false, new Vector2(), new Vector2()); + endP = endP2; + endQ = endQ2; + } + else if (kbFail) return (false, new Vector2(), new Vector2()); + + return (true, endP, endQ); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int toId(int x, int y, int z) + { + return (x * 1140671485 + 12820163) ^ (y * 134775813 + 1) ^ (z * 1103515245 + 12345); + } + + public class Clustering + { + public int numIteration = 3; + public int itemNumThreshold = 10; + + public Func inRange; + public Func, T> average; + private readonly List _inputData; + private Dictionary> _clusters = new Dictionary>(); + + public Clustering(List data, Func inRange, Func, T> average) + { + _inputData = data; + this.inRange = inRange; + this.average = average; + } + + public Dictionary> GetClusters() + { + var tmp = new List<(T center, List items)>(); + + for (var iter = 0; iter < numIteration; iter++) + { + tmp = tmp.Where(cluster => cluster.items.Count > itemNumThreshold) + .Select(cluster => (average(cluster.items), new List())).ToList(); + + foreach (var data in _inputData) + { + var added = false; + foreach (var cluster in tmp) + { + if (inRange(cluster.center, data)) + { + cluster.items.Add(data); + added = true; + break; + } + } + + if (!added) + tmp.Add((data, new List() { data })); + } + } + + _clusters = tmp.Where(cluster => cluster.items.Count > itemNumThreshold) + .ToDictionary(cluster => cluster.center, cluster => cluster.items); + return _clusters; + } + } + + public static (bool, Vector2) TwoLinesIntersection(Vector2 A, Vector2 B, Vector2 C, Vector2 D) + { + // Line AB represented as a1x + b1y = c1 + double a1 = B.Y - A.Y; + double b1 = A.X - B.X; + double c1 = a1 * (A.X) + b1 * (A.Y); + + // Line CD represented as a2x + b2y = c2 + double a2 = D.Y - C.Y; + double b2 = C.X - D.X; + double c2 = a2 * (C.X) + b2 * (C.Y); + + double determinant = a1 * b2 - a2 * b1; + + if (determinant == 0) + { + // The lines are parallel. This is simplified + // by returning a pair of FLT_MAX + return new(false, new Vector2()); + } + else + { + double x = (b2 * c1 - b1 * c2) / determinant; + double y = (a1 * c2 - a2 * c1) / determinant; + return (true, new Vector2((float)x, (float)y)); + } + } + + public static bool IsAtLeft(Vector2 anchor, Vector2 dest, Vector2 p) + { + var v1 = new Vector3(anchor - p, 0); + var v2 = new Vector3(dest - p, 0); + return Vector3.Cross(v1, v2).Z > 0; + } + + /// + /// 将角度转化至-180到180度的范围内。 + /// + /// + /// + public static double RoundTh(double th) + { + return th - System.Math.Round(th / 360) * 360; + } + + /// + /// 将角度转化至-180到180度的范围内。 + /// + /// + /// + public static float RoundTh(float th) + { + return th - (float)System.Math.Round(th / 360f) * 360f; + } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Mathematics/LineSegment.cs b/CommonUsage-MultiVehicleSync/commonusage/Mathematics/LineSegment.cs new file mode 100644 index 0000000..87e0405 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Mathematics/LineSegment.cs @@ -0,0 +1,161 @@ +using System; +using System.Numerics; + +namespace CommonUsage.Mathematics +{ + /// + /// 表示一条线段。 + /// + public class LineSegment + { + /// + /// 默认构造函数。所有坐标初始化为0。 + /// + public LineSegment() + { + + } + + /// + /// 使用两个端点初始化一段2D线段。 + /// + /// 线段起点。 + /// 线段终点。 + public LineSegment(Vector2 src, Vector2 dst) + { + Src = src; + Dst = dst; + } + + /// + /// 使用两个端点初始化一段3D线段。 + /// + /// 线段起点。 + /// 线段终点。 + public LineSegment(Vector3 src, Vector3 dst) + { + Src3D = src; + Dst3D = dst; + } + + /// + /// 使用两个端点初始化一条线段,2D。 + /// + /// 线段起点x坐标。 + /// 线段起点y坐标。 + /// 线段终点x坐标。 + /// 线段终点y坐标。 + public LineSegment(double x1, double y1, double x2, double y2) + { + Src = new Vector2((float)x1, (float)y1); + Dst = new Vector2((float)x2, (float)y2); + } + + /// + /// 使用两个端点初始化一条线段,2D。 + /// + /// 线段起点x坐标。 + /// 线段起点y坐标。 + /// 线段起点y坐标。 + /// 线段终点x坐标。 + /// 线段终点y坐标。 + /// 线段终点y坐标。 + public LineSegment(double x1, double y1, double z1, double x2, double y2, double z2) + { + Src3D = new Vector3((float)x1, (float)y1, (float)z1); + Dst3D = new Vector3((float)x2, (float)y2, (float)z2); + } + + /// + /// 返回线段长度,2D。 + /// + /// + public double Length() + { + return Vector2.Distance(Src, Dst); + } + + /// + /// 返回线段长度,3D。 + /// + /// + public double Length3D() + { + return Vector3.Distance(Src3D, Dst3D); + } + + /// + /// 返回线段与x轴正方向夹角度数,角度制。 + /// + /// + public double Angle() + { + return Math.Atan2(Dst.Y - Src.Y, Dst.X - Src.X) / Math.PI * 180; + } + + /// + /// 返回一段方向相反的线段。 + /// + /// + public LineSegment Reverse() + { + return new LineSegment(Dst3D, Src3D); + } + + /// + /// 线段2D起点。 + /// + public Vector2 Src + { + get => new(_srcX, _srcY); + set + { + _srcX = value.X; + _srcY = value.Y; + } + } + + /// + /// 线段2D终点。 + /// + public Vector2 Dst + { + get => new(_dstX, _dstY); + set + { + _dstX = value.X; + _dstY = value.Y; + } + } + + /// + /// 线段3D起点。 + /// + public Vector3 Src3D + { + get => new(_srcX, _srcY, _srcZ); + set + { + _srcX = value.X; + _srcY = value.Y; + _srcZ = value.Z; + } + } + + /// + /// 线段3D终点。 + /// + public Vector3 Dst3D + { + get => new(_dstX, _dstY, _dstZ); + set + { + _dstX = value.X; + _dstY = value.Y; + _dstZ = value.Z; + } + } + + private float _srcX, _srcY, _srcZ, _dstX, _dstY, _dstZ; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Properties/launchSettings.json b/CommonUsage-MultiVehicleSync/commonusage/Properties/launchSettings.json new file mode 100644 index 0000000..53c176e --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "CommonUsage": { + "commandName": "Project" + }, + "配置文件 1": { + "commandName": "Executable", + "executablePath": "D:\\Code\\Core\\Medulla\\build\\Medulla.exe", + "workingDirectory": "D:\\Code\\Core\\Medulla\\build\\" + } + } +} \ No newline at end of file diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/CommunicationProtocolFactory.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/CommunicationProtocolFactory.cs new file mode 100644 index 0000000..3376c97 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/CommunicationProtocolFactory.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050 +{ + public class CommunicationProtocolFactory + { + public static IVDACommunicationProtocol CreateProtocol(string protocolType, string host, int port) + { + return protocolType.ToLower() switch + { + "http" => new HTTPCommunication(host, port), + "mqtt" => new MQTTCommunication(host, port), + _ => throw new NotSupportedException($"Protocol {protocolType} is not supported") + }; + } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/HTTPCommunication.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/HTTPCommunication.cs new file mode 100644 index 0000000..5ff34a8 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/HTTPCommunication.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using CommonUsage.Protocols.VDA5050.Messages; +using FundamentalLib; +using Newtonsoft.Json; + +namespace CommonUsage.Protocols.VDA5050 +{ + public class HTTPCommunication : IVDACommunicationProtocol + { + private readonly string _host; + private readonly int _port; + + public HTTPCommunication(string host, int port) + { + _host = host; + _port = port; + } + + public async Task PublishConnectionStatus(string status) + { + var message = new connectionMessage() + { + serialNumber = "test-01", + headerId = 1, + timestamp = DateTime.Now, + connectionState = status + }; + + await SendMessageAsync(message, "vda5050/connection"); + } + + public void SetupOrderListener(Action orderReceived) + { + PicoHttpServer.AddPostTextHandler("/order", new { }, (_, str) => + { + var order = JsonConvert.DeserializeObject(str); + orderReceived(order); + return ""; + }); + } + + public void SetUpInstanActionListener(Action onInstanceActionReceived) + { + PicoHttpServer.AddPostTextHandler("/instanceAction", new { }, (_, str) => + { + var instanceAction = JsonConvert.DeserializeObject(str); + onInstanceActionReceived(instanceAction); + return ""; + }); + } + + public void SetUpImmediateCommandListener(Action onChangeCarFieldsReceived) + { + throw new NotImplementedException(); + } + + public async Task SendMessageAsync(T message, string topic) + { + try + { + var url = $"http://{_host}:{_port}/{topic}"; + using var client = new HttpClient(); + var response = await client.PostAsync(url, new StringContent(JsonConvert.SerializeObject(message), Encoding.UTF8, "application/json")); + + if (!response.IsSuccessStatusCode) + { + Console.WriteLine($" >> Sending Message: Failed to send message. Status Code: {response.StatusCode}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error in sending message: {ex.Message}"); + } + } + + public async Task SendVisualizationMessageAsync(T msg, string topic) + { + throw new NotImplementedException(); + } + + public void SetupTestListener(Action testMsg) + { + throw new NotImplementedException(); + } + public async Task PublishFactSheet(factsheetMessage message) + { + throw new NotImplementedException(); + } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/IVDACommunicationProtocol.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/IVDACommunicationProtocol.cs new file mode 100644 index 0000000..f8e998f --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/IVDACommunicationProtocol.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using CommonUsage.Protocols.VDA5050.Messages; + +namespace CommonUsage.Protocols.VDA5050 +{ + public interface IVDACommunicationProtocol + { + Task PublishConnectionStatus(string status); + Task PublishFactSheet(factsheetMessage msg); + void SetupOrderListener(Action orderReceived); + void SetUpInstanActionListener(Action onInstanceActionReceived); + void SetUpImmediateCommandListener(Action onChangeCarFieldsReceived); + Task SendMessageAsync(T message, string topic); + Task SendVisualizationMessageAsync(T message, string topic); + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/MQTTCommunication.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/MQTTCommunication.cs new file mode 100644 index 0000000..133fd46 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/MQTTCommunication.cs @@ -0,0 +1,319 @@ +using System.IO; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using CommonUsage.Protocols.VDA5050.Messages; +using MQTTnet; +using MQTTnet.Client; +using MQTTnet.Extensions.ManagedClient; +using MQTTnet.Packets; +using MQTTnet.Protocol; +using MQTTnet.Server; +using Newtonsoft.Json; +using FundamentalLib; +using CommonUsage.Protocols.VDA5050.Objects; +using FundamentalLib.MiscHelpers; + +namespace CommonUsage.Protocols.VDA5050 +{ + public class MQTTCommunication : IVDACommunicationProtocol + { + private readonly string _host; + private readonly int _port; + private readonly string _orderTopic = "vda5050/frldAGV/order"; + private readonly string _connectionTopic = "vda5050/frldAGV/connection"; + private readonly string _instanceAction = "vda5050/frldAGV/instantActions"; + private readonly string _factsheet = "vda5050/frldAGV/factsheet"; + private readonly string _changeCarFields = "vda5050/frldAGV/changeCarFields"; + + private IManagedMqttClient _client; + private IManagedMqttClient _visualizationClient; + + public MQTTCommunication(string host, int port) + { + _host = host; + _port = port; + InitializeClient(); + InitializeVisualizationClient(); + } + + private void InitializeClient() + { + var willMessage = new connectionMessage() + { + headerId = 1, + timestamp = DateTime.Now, + version = "00", + manufacturer = "frld", + serialNumber = "test-01", + connectionState = "CONNECTIONBROKEN" + }; + + var mqttClientOptions = new MqttClientOptionsBuilder() + .WithClientId("AGV-Client-frldAGV") + .WithTcpServer(_host, _port) + .WithWillTopic(_connectionTopic) + .WithWillPayload(JsonConvert.SerializeObject(willMessage)) + .WithWillRetain(true) + .Build(); + + var managedMqttClientOptions = new ManagedMqttClientOptionsBuilder() + .WithClientOptions(mqttClientOptions) + .WithMaxPendingMessages(20) + .WithPendingMessagesOverflowStrategy(MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage) + .Build(); + + _client = new MqttFactory().CreateManagedMqttClient(); + _client.StartAsync(managedMqttClientOptions).GetAwaiter().GetResult(); + Console.WriteLine($" >> MQTT client initialized and connected to broker at {_host} - {_port}"); + } + + private void InitializeVisualizationClient() + { + var mqttClientOptions = new MqttClientOptionsBuilder() + .WithClientId("AGV-Visualization") + .WithTcpServer(_host, _port) + .Build(); + + var managedMqttClientOptions = new ManagedMqttClientOptionsBuilder() + .WithClientOptions(mqttClientOptions) + .WithMaxPendingMessages(10) // Prevent overloading + .WithPendingMessagesOverflowStrategy(MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage) + .Build(); + + _visualizationClient = new MqttFactory().CreateManagedMqttClient(); + _visualizationClient.StartAsync(managedMqttClientOptions).GetAwaiter().GetResult(); + Console.WriteLine("MQTT Visualization client initialized."); + } + + public void SetUpImmediateCommandListener(Action onChangeCarFieldsReceived) + { + Console.WriteLine($"Subscribed to the topic: {_changeCarFields}"); + _client.SubscribeAsync(_changeCarFields).GetAwaiter().GetResult(); + + _client.ApplicationMessageReceivedAsync += async e => + { + if (e.ApplicationMessage.Topic == _changeCarFields) + { + var payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); + LogMessage($"RECEIVE-{e.ApplicationMessage.Topic}", e.ApplicationMessage.Topic, payload); + //var script = JsonConvert.DeserializeObject(payload); + Console.WriteLine($"Change car field: {payload}"); + onChangeCarFieldsReceived(payload); + } + }; + } + + + public void SetUpInstanActionListener(Action onInstanceActionReceived) + { + Console.WriteLine($"Subscribed to the topic: {_instanceAction}"); + + // Subscribe to the instanceAction topic + _client.SubscribeAsync(_instanceAction).GetAwaiter().GetResult(); + + _client.ApplicationMessageReceivedAsync += async e => + { + if (e.ApplicationMessage.Topic == _instanceAction) + { + var payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); + LogMessage($"RECEIVE-{e.ApplicationMessage.Topic}", e.ApplicationMessage.Topic, payload); + var actions = JsonConvert.DeserializeObject(payload); + Console.WriteLine($"Received instance action: Header ID = {actions.headerId}, Timestamp = {actions.timestamp}"); + foreach (var action in actions.actions) + { + Console.WriteLine($"Action ID: {action.actionId}, Type: {action.actionType}"); + } + + onInstanceActionReceived(actions); + } + }; + } + + public async Task PublishConnectionStatus(string status) + { + var message = new connectionMessage() + { + headerId = 1, + timestamp = DateTime.Now, + version = "00", + manufacturer = "frld", + serialNumber = "test-01", + connectionState = status + }; + + var payload = JsonConvert.SerializeObject(message); + + var content = new MqttApplicationMessageBuilder() + .WithTopic(_connectionTopic) + .WithPayload(payload) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithRetainFlag(true) + .Build(); + + await _client.EnqueueAsync(content); + LogMessage($"SEND-{_connectionTopic}", _connectionTopic, payload); + + //await SendMessageAsync(message, _connectionTopic); + } + + public async Task PublishFactSheet(factsheetMessage message) + { + + //await SendMessageAsync(message, _factsheet); + var payload = JsonConvert.SerializeObject(message); + + var content = new MqttApplicationMessageBuilder() + .WithTopic(_factsheet) + .WithPayload(payload) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + //.WithRetainFlag(true) + .Build(); + + await _client.EnqueueAsync(content); + LogMessage($"SEND-{_factsheet}", _factsheet, payload); + + } + + public void SetupOrderListener(Action orderReceived) + { + // Subscribe to the orders topic + _client.SubscribeAsync(_orderTopic, MqttQualityOfServiceLevel.AtMostOnce).GetAwaiter().GetResult(); + _client.ApplicationMessageReceivedAsync += async e => + { + if (e.ApplicationMessage.Topic == _orderTopic) + { + var payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); + LogMessage($"RECEIVE-{e.ApplicationMessage.Topic}", e.ApplicationMessage.Topic, payload); + var order = JsonConvert.DeserializeObject(payload); + + // Save the order message to a file for debugging + // SaveOrderToFile(payload); + orderReceived(order); + } + await Task.CompletedTask; + }; + } + + private void SaveOrderToFile(string orderJson) + { + try + { + // Specify the file path (e.g., orders_log.txt in the current directory) + string filePath = "orders_log.txt"; + + // Append the order JSON along with a timestamp + File.AppendAllText(filePath, $"{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} - {orderJson}{Environment.NewLine}"); + } + catch (Exception ex) + { + // Handle any exceptions that occur while writing to the file + Console.WriteLine($"Failed to save order to file: {ex.Message}"); + } + } + + public async Task SendMessageAsync(T message, string topic) + { + + var payload = JsonConvert.SerializeObject(message); + + var content = new MqttApplicationMessageBuilder() + .WithTopic(topic) + .WithPayload(payload) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + .Build(); + + await _client.EnqueueAsync(content); + + if (topic != "vda5050/frldAGV/visualization") + { + + LogMessage($"SEND-{topic}", topic, payload); + } + + } + + public async Task SendVisualizationMessageAsync(T message, string topic) + { + if (_visualizationClient == null) return; // Ensure client is initialized + + var payload = JsonConvert.SerializeObject(message); + + var content = new MqttApplicationMessageBuilder() + .WithTopic(topic) + .WithPayload(payload) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) // QoS 0 for lightweight visualization + .Build(); + + if (_visualizationClient.PendingApplicationMessagesCount < 5) // Prevent flooding + { + await _visualizationClient.EnqueueAsync(content); + } + else + { + Console.WriteLine("Skipping visualization update to avoid MQTT congestion."); + } + } + + + public void LogMessage(string direction, string topic, string payload) + { + string formattedPayload = payload; + string logDirectory = "Logs"; // Directory for log files + var filePreName = direction; + filePreName = filePreName.Replace("/", "_"); + string logFilePath = Path.Combine(logDirectory, filePreName + $"-{DateTime.Now:yyyy-MM-dd}.log"); + + if(!Directory.Exists(logDirectory)) Directory.CreateDirectory(logDirectory); + // Try to parse the payload as JSON and pretty-print it + try + { + var jsonObject = JsonConvert.DeserializeObject(payload); + formattedPayload = JsonConvert.SerializeObject(jsonObject, Formatting.Indented); + } + catch (JsonReaderException) + { + // If the payload is not valid JSON, just leave it as is + formattedPayload = payload; + } + + string logMessage = $"[{DateTime.Now:HH:mm:ss}] [{direction}] Topic: {topic}, Payload:\n{formattedPayload}\n"; + RotateLogFile(logFilePath, logDirectory); + + try + { + File.AppendAllText(logFilePath, logMessage + Environment.NewLine); + } + catch (Exception ex) + { + Console.WriteLine($"Error writing to log file: {ex.Message}"); + } + // Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] [{direction}] Topic: {topic}, Payload: {formattedPayload}"); + // DLog.Log($"[{DateTime.Now:HH:mm:ss}] [{direction}] Topic: {topic}, Payload: {formattedPayload}"); + } + + + private void RotateLogFile(string logFilePath, string logDirectory) + { + const long maxFileSize = 10 * 1024 * 1024; // 10 MB in bytes + + FileInfo fileInfo = new FileInfo(logFilePath); + if (fileInfo.Exists && fileInfo.Length > maxFileSize) + { + string archivePath = Path.Combine(logDirectory, $"log_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log"); + + try + { + File.Move(logFilePath, archivePath); // Rename the current log file + Console.WriteLine($"Log file rotated: {archivePath}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error rotating log file: {ex.Message}"); + } + } + } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/connectionMessage.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/connectionMessage.cs new file mode 100644 index 0000000..a4f5c70 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/connectionMessage.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Messages +{ + public class connectionMessage + { + public int headerId; + public DateTime timestamp; + public string version = ""; + public string manufacturer = ""; + public string serialNumber = ""; + public string connectionState = ""; // Enum: {'ONLINE', 'OFFLINE', 'CONNECTIONBROKEN'} + + } + +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/errorMessage.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/errorMessage.cs new file mode 100644 index 0000000..9888fe2 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/errorMessage.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Messages +{ + public class errorMessage + { + public string serialNumber = ""; + public string errorCode = ""; // Unique error code + public string description = ""; // Error description + public string severity = ""; // Enum {'WARNING', 'FATAL'} + public DateTime timestamp; // Time of the error + } + +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/factsheetMessage.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/factsheetMessage.cs new file mode 100644 index 0000000..bcbd349 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/factsheetMessage.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; +using CommonUsage.Protocols.VDA5050.Objects; + +namespace CommonUsage.Protocols.VDA5050.Messages +{ + public class factsheetMessage + { + public int headerId; + public DateTime timestamp; + public string version = ""; + public string manufacturer = ""; + public string serialNumber = ""; + + public typeSpecification typeSpecification; + public physicalParameters physicalParameters; + public protocolLimits protocolLimits; + public protocolFeatures protocolFeatures; + public agvGeometry agvGeometry; + } + +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/instanceAction.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/instanceAction.cs new file mode 100644 index 0000000..e5c5f8d --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/instanceAction.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; +using CommonUsage.Protocols.VDA5050.Objects; + +namespace CommonUsage.Protocols.VDA5050.Messages +{ + public class instanceAction + { + + public uint headerId { get; set; } // Incremented for each new message. + public string timestamp { get; set; } // ISO 8601 UTC timestamp. + public string version { get; set; } // Protocol version. + public string manufacturer { get; set; } // AGV manufacturer. + public string serialNumber { get; set; } // Unique AGV serial number. + + public List actions { get; set; } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/orderMessage.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/orderMessage.cs new file mode 100644 index 0000000..68516c7 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/orderMessage.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; +using CommonUsage.Protocols.VDA5050.Objects; + +namespace CommonUsage.Protocols.VDA5050.Messages +{ + public class orderMessage + { + public uint headerId; + public string timestamp = ""; + public string version = ""; + public string manufacturer = ""; + public string serialNumber = ""; + + public string orderId { get; set; } + + public uint orderUpdateId { get; set; } + + public node[] nodes { get; set; } + + public edge[] edges { get; set; } + + //public action[] action { get; set; } + } +} + diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/stateMessage.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/stateMessage.cs new file mode 100644 index 0000000..44b0438 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/stateMessage.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using CommonUsage.Protocols.VDA5050.Objects; + +namespace CommonUsage.Protocols.VDA5050.Messages +{ + /// + /// 6.10 Topic: "state" (from AGV to master control) + /// todo: complete all fields required by VDA5050 + /// + public class stateMessage + { + public uint headerId; + public string timestamp = ""; + public string version = ""; + public string manufacturer = ""; + public string serialNumber = ""; + /// + /// Unique order identification of the current order or the previously finished order. + /// The orderId is kept until a new order is received. + /// Empty string (""), if no previous orderId is available. + /// + public string orderId = ""; + + /// + /// Order update identification to identify, that an order update has been accepted by the AGV. + /// "0" if no previous orderUpdateId is available. + /// + public uint orderUpdatedId = 0; + + public string lastNodeId; + + public uint lastNodeSequenceId; + + /// + /// Array of nodeState objects that need to be traversed for fulfilling the order (empty array if idle) + /// + public nodeState[] nodeStates = []; + + /// + /// Array of edgeState objects that need to be traversed for fulfilling the order (empty array if idle) + /// + public edgeState[] edgeStates = []; + + public agvPosition agvPosition; + + public velocity velocity; + public load[] loads = []; + + public bool driving; + + public bool paused; + + public bool newBaseRequest; + + public double distanceSinceLastNode; + + public batteryState batteryState; + + public actionState[] actionStates = Array.Empty(); + public string operatingMode = ""; + public List errors { get; set; } = new List(); // Array of errorState objects + + public info[] information = []; + public safetyState safetyState; + + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/visualizationMessage.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/visualizationMessage.cs new file mode 100644 index 0000000..c895311 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Messages/visualizationMessage.cs @@ -0,0 +1,12 @@ +using CommonUsage.Protocols.VDA5050.Objects; +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Messages +{ + public class visualizationMessage + { + public agvPosition agvPosition; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/action.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/action.cs new file mode 100644 index 0000000..e4212b4 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/action.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class action + { + + public string actionId { get; set; } + + public string actionType { get; set; } + public string actionDescription { get; set; } + + public string blockingType { get; set; } + + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/actionState.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/actionState.cs new file mode 100644 index 0000000..fe454e2 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/actionState.cs @@ -0,0 +1,45 @@ +using Newtonsoft.Json.Converters; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class actionState + { + public actionState(action action,ActionStateEnum state) + { + actionId = action.actionId; + actionDescription = action.actionDescription; + actionType = action.actionType; + actionStatus = state; + } + + public actionState() + { + } + + public string actionId { get; set; } + + public string actionType { get; set; } + public string actionDescription { get; set; } + + [JsonConverter(typeof(StringEnumConverter))] + public ActionStateEnum actionStatus { get; set; } + + public string resultDescription { get; set; } + + public enum ActionStateEnum + { + WAITING, + INITIALIZING, + RUNNING, + PAUSED, + FINISHED, + FAILED + } + + } + +} \ No newline at end of file diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/agvGeometry.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/agvGeometry.cs new file mode 100644 index 0000000..d96e7b7 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/agvGeometry.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Text; +using static CommonUsage.Protocols.VDA5050.Objects.agvGeometry; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class agvGeometry + { + // Wheel Definitions + public List wheelDefinitions { get; set; } = new List(); + + // 2D Envelopes + public List envelopes2D { get; set; } = new List(); + + // 3D Envelopes + public List envelopes3D { get; set; } = new List(); + + public class wheelDefinition + { + public enum WheelType { DRIVE, CASTER, FIXED, MECANUM } + + public WheelType type { get; set; } + public bool isActiveDriven { get; set; } + public bool isActiveSteered { get; set; } + + // Wheel Position + public double positionX { get; set; } + public double positionY { get; set; } + public double positionTheta { get; set; } // Required for fixed wheels + + // Wheel Properties + public double diameter { get; set; } + public double width { get; set; } + public double centerDisplacement { get; set; } = 0; // Default to 0 if not defined + public string constraints { get; set; } + } + + public class envelope2D + { + public string set { get; set; } + public List polygonPoints { get; set; } = new List(); + public string description { get; set; } + + public class polygonPoint + { + public double x { get; set; } + public double y { get; set; } + } + } + + public class envelope3D + { + public string set { get; set; } + public string format { get; set; } + public object data { get; set; } // JSON object for 3D envelope data + public string url { get; set; } + public string description { get; set; } + } + } + +} + diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/agvPosition.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/agvPosition.cs new file mode 100644 index 0000000..8659cd3 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/agvPosition.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class agvPosition + { + public bool positionInitialized; + + public double x; + + public double y; + + public double theta; + public double localizationScore; + public double deviationRange; + public string mapId = ""; + public string mapDescription = ""; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/batteryState.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/batteryState.cs new file mode 100644 index 0000000..1d3392c --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/batteryState.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class batteryState + { + public double batteryCharge; + public double batteryVoltage; + public double batteryHealth; + public bool charging; + public int reach; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/boundingBoxReference.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/boundingBoxReference.cs new file mode 100644 index 0000000..be48032 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/boundingBoxReference.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class boundingBoxReference + { + public double X { get; set; } // Reference point X in AGV coordinate system + public double Y { get; set; } // Reference point Y in AGV coordinate system + public double Z { get; set; } // Reference point Z in AGV coordinate system + public double Theta { get; set; } // Orientation of the load bounding box + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/controlPoint.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/controlPoint.cs new file mode 100644 index 0000000..03300b8 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/controlPoint.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class controlPoint + { + public float x; + + public float y; + + public float weight; + public controlPoint(float x, float y, float weight) + { + this.x = x; + this.y = y; + this.weight = weight; + } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/edge.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/edge.cs new file mode 100644 index 0000000..e207eb5 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/edge.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class edge : sequenceItem + { + public string edgeId; + + public string edgeDescription; + + public string startNodeId; + + public string endNodeId; + + public double maxSpeed; + + public double orientation; + + public trajectory? trajectory; + + public float[] trackTypeInfo; + // public List controlPoints; + // + // public List weights; + + public action[] action = []; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/edgeState.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/edgeState.cs new file mode 100644 index 0000000..e5d8af3 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/edgeState.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class edgeState : sequenceItem + { + public string edgeId; + + public string edgeDescription; + + public trajectory trajectory; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/errorReference.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/errorReference.cs new file mode 100644 index 0000000..f44d5c7 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/errorReference.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class errorReference + { + public string referenceKey { get; set; } // Type of reference (e.g., nodeId, edgeId, actionId) + public string referenceValue { get; set; } // Value corresponding to the referenceKey + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/errorState.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/errorState.cs new file mode 100644 index 0000000..227ed80 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/errorState.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class errorState + { + public List errorReferences { get; set; } = new List(); // Array of references + public string errorType { get; set; } // Required: Type/name of the error + public string errorDescription { get; set; } // Verbose description of the error + public string errorHint { get; set; } // Hint for resolving the error + public string errorLevel { get; set; } // Required: WARNING or FATAL + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/info.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/info.cs new file mode 100644 index 0000000..a638ec8 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/info.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class info + { + public string infoType { get; set; } // Type/name of the information + public List infoReferences { get; set; } = new List(); // List of references + public string infoDescription { get; set; } // Description of the information + public infoLevelEnum infoLevel { get; set; } // Debugging or visualization level + + public class infoReference + { + public string ReferenceKey { get; set; } // Reference type (e.g., headerId, orderId) + public string ReferenceValue { get; set; } // The actual referenced field value + } + + public enum infoLevelEnum + { + DEBUG, // Used for debugging + INFO // Used for visualization + } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/load.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/load.cs new file mode 100644 index 0000000..91530d0 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/load.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class load + { + public string loadId { get; set; } // Unique ID (barcode, RFID, etc.) + public string loadType { get; set; } // Type of load + public string loadPosition { get; set; } // Load handling position (e.g., "front", "back") + public boundingBoxReference boundingBoxReference { get; set; } = new boundingBoxReference(); + public loadDimensions loadDimensions { get; set; } = new loadDimensions(); + public double weight { get; set; } // Weight of load in kg (0.0 to ∞) + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/loadDimensions.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/loadDimensions.cs new file mode 100644 index 0000000..90469c6 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/loadDimensions.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class loadDimensions + { + public double Length { get; set; } // Length of the bounding box + public double Width { get; set; } // Width of the bounding box + public double Height { get; set; } // Height of the bounding box (optional) + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/node.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/node.cs new file mode 100644 index 0000000..c6617cf --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/node.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class node : sequenceItem + { + public string nodeId; + + public string nodeDescription; + + public nodePosition nodePosition; + + public action[] actions = []; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/nodePosition.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/nodePosition.cs new file mode 100644 index 0000000..a1c362a --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/nodePosition.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + /// + /// Defines the position on a map in a global project-specific world coordinate system. + /// Each floor has its own map. + /// All maps shall use the same project-specific global origin. + /// + public class nodePosition + { + /// + /// X-position on the map in reference to the map coordinate system. + /// Precision is up to the specific implementation. + /// + public double x; + + /// + /// Y-position on the map in reference to the map coordinate system. + /// Precision is up to the specific implementation. + /// + public double y; + + /// + /// Range: [-Pi ... Pi] + /// Absolute orientation of the AGV on the node. + /// Optional: vehicle can plan the path by itself. If defined, the AGV has to assume the theta angle on this node. + /// If previous edge disallows rotation, the AGV shall rotate on the node. + /// If following edge has a differing orientation defined but disallows rotation, + /// the AGV is to rotate on the node to the edges desired rotation before entering the edge. + /// + public double theta; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/nodeState.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/nodeState.cs new file mode 100644 index 0000000..2a67bdf --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/nodeState.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class nodeState : sequenceItem + { + /// + /// Unique node identification. + /// + public string nodeId; + + /// + /// Additional information on the node. + /// + public string nodeDescription; + + /// + /// Node position. + /// The object is defined in 6.6 Topic: "order" (from master control to AGV) + /// Optional: Master control has this information. Can be sent additionally, e.g., for debugging purposes. + /// + public nodePosition nodePosition; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/physicalParameters.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/physicalParameters.cs new file mode 100644 index 0000000..3b4e0ec --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/physicalParameters.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class physicalParameters + { + public double speedMin; + public double speedMax; + public double angularSpeedMin; + public double angularSpeedMax; + public double accelerationMax; + public double decelerationMax; + public double heightMin; + public double heightMax; + public double width; + public double length; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/protocolFeatures.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/protocolFeatures.cs new file mode 100644 index 0000000..bcead23 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/protocolFeatures.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class protocolFeatures + { + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/protocolLimits.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/protocolLimits.cs new file mode 100644 index 0000000..64c7df7 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/protocolLimits.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class protocolLimits + { + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/safetyState.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/safetyState.cs new file mode 100644 index 0000000..5f67a98 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/safetyState.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class safetyState + { + public eStopEnum eStop { get; set; } // Emergency stop status + public bool fieldViolation { get; set; } // "true" if a safety field is violated, "false" otherwise + + public enum eStopEnum + { + AUTOACK, // Auto-acknowledged emergency stop (e.g., triggered by a bumper) + MANUAL, // Manually confirmed emergency stop + REMOTE, // Remote-confirmed emergency stop + NONE // No emergency stop activated + } + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/sequenceItem.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/sequenceItem.cs new file mode 100644 index 0000000..b77f535 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/sequenceItem.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class sequenceItem + { + public uint sequenceId; + + public bool released; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/trajectory.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/trajectory.cs new file mode 100644 index 0000000..1b792c4 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/trajectory.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class trajectory + { + public float degree; + + public float[] knotVector; + + public controlPoint[] controlPoints; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/typeSpecification.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/typeSpecification.cs new file mode 100644 index 0000000..1f8d6e9 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/typeSpecification.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class typeSpecification + { + public string agvKinemantic = ""; + public string agvClass = ""; + public double maxLoadMass; + public string[] localizationTypes; // Simplified description of localization type (e.g., NATURAL, REFLECTOR, RFID, DMC, GRID) + public string[] navigationTypes; // Path planning types (e.g., 'AUTONOMOUS', 'VIRTUAL_LINE_GUIDED') + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/velocity.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/velocity.cs new file mode 100644 index 0000000..d774ba1 --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/Objects/velocity.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050.Objects +{ + public class velocity + { + public double vx; + + public double vy; + + public double omega; + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/VDA5050Basic.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/VDA5050Basic.cs new file mode 100644 index 0000000..029348c --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/VDA5050Basic.cs @@ -0,0 +1,118 @@ +//using CommonUsage.Protocols.VDA5050.Messages; +//using System; +//using System.Collections.Generic; +//using System.Net.Http.Headers; +//using System.Runtime.CompilerServices; +//using System.Text; +//using System.Threading; +//using System.Threading.Tasks; +//using CommonUsage.Protocols.VDA5050.Objects; +//using ClumsyCore.Utilities; +//using System.Linq; +//using ClumsyCore.Pilot; +//using System.Numerics; + +//namespace CommonUsage.Protocols.VDA5050 +//{ +// public abstract class VDA5050Basic +// { +// protected static IVDACommunicationProtocol _communicationProtocol; + +// public void Enable(IVDACommunicationProtocol protocol) +// { +// _communicationProtocol = protocol; +// Task.Run(() => ManageConnection()); +// StartVisualizationLoop(); +// } +// private void StartVisualizationLoop() +// { +// Console.WriteLine("Visualization in CommonUsage"); +// new Thread(async () => +// { +// while (true) +// { +// var position = GetAGVPosition(); +// if (position != null) +// { +// var msg = new stateMessage() +// { +// serialNumber = "test-01", +// agvPosition = new() +// { +// x = position.Value.X, +// y = position.Value.Y, +// theta = position.Value.Theta, +// positionInitialized = true +// } + +// }; +// await _communicationProtocol.SendMessageAsync(msg, "vda5050/frldAGV/visualization"); +// } + +// Thread.Sleep(100); +// } +// }) +// { Name = "VDA5050TopicVisualization" }.Start(); +// } + +// private void ManageConnection() +// { +// while (true) +// { +// var status = CheckConnectionStatus() ? "ONLINE" : "OFFLINE"; +// _communicationProtocol.PublishConnectionStatus(status); +// Thread.Sleep(1000); +// } +// } + +// protected List OrganizeReceivedSequence(orderMessage order) +// { +// List receivedSequence = new(); + +// int ii = 0, jj = 0; +// while (true) +// { +// var edge = order.edges[ii]; +// var node = order.nodes[jj]; +// var takeEdge = edge.sequenceId < node.sequenceId; + +// if (takeEdge) +// { +// receivedSequence.Add(edge); +// ii++; +// if (ii == order.edges.Length) break; +// } +// else +// { +// receivedSequence.Add(node); +// jj++; +// if (jj == order.nodes.Length) break; +// } +// } +// for (var i = ii; i < order.edges.Length; ++i) receivedSequence.Add(order.edges[i]); +// for (var j = jj; j < order.nodes.Length; ++j) receivedSequence.Add(order.nodes[j]); + +// for (var i = 1; i < receivedSequence.Count; i++) +// { +// if (receivedSequence[i - 1].sequenceId + 1 != receivedSequence[i].sequenceId) +// throw new Exception("stateMessage not continuous!"); +// } + +// return receivedSequence; +// } + +// public virtual bool CheckConnectionStatus() +// { +// return false; +// } + +// protected abstract Vector3? GetAGVPosition(); +// public struct Vector3 +// { +// public double X; +// public double Y; +// public double Theta; +// } +// } + +//} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/VDA5050Helper.cs b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/VDA5050Helper.cs new file mode 100644 index 0000000..9f5217f --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Protocols/VDA5050/VDA5050Helper.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommonUsage.Protocols.VDA5050 +{ + public class VDA5050Helper + { + + } +} diff --git a/CommonUsage-MultiVehicleSync/commonusage/Visualizer.cs b/CommonUsage-MultiVehicleSync/commonusage/Visualizer.cs new file mode 100644 index 0000000..f17c27d --- /dev/null +++ b/CommonUsage-MultiVehicleSync/commonusage/Visualizer.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Numerics; +using System.Text; + +namespace CommonUsage +{ + public class Visualizer + { + public Action LineAction; + + public Action TextAction; + + public Action Clear; + + public void DrawLine(Color color, Vector2 src, Vector2 dst, bool startArrow = false, bool endArrow = false, + int width = 1) + { + LineAction?.Invoke(color, src, dst, startArrow, endArrow, width); + } + + public void DrawText(Color color, string text, Vector2 pos) + { + TextAction?.Invoke(color, text, pos); + } + } +} diff --git a/MedullaAdapter/MedullaAdapter.csproj b/MedullaAdapter/MedullaAdapter.csproj index fbac02d..421f8ce 100644 --- a/MedullaAdapter/MedullaAdapter.csproj +++ b/MedullaAdapter/MedullaAdapter.csproj @@ -27,11 +27,6 @@ false - - ref\CommonUsage.dll - false - - ref\MDCSToolBox.dll false @@ -41,6 +36,9 @@ ref\CycleGUI.dll false + + ..\ref\CommonUsage.dll + diff --git a/MedullaAdapter/build/Medulla/plugins/CommonUsage.dll b/MedullaAdapter/build/Medulla/plugins/CommonUsage.dll new file mode 100644 index 0000000000000000000000000000000000000000..cdb9124dbedd7e2752f99bbb9b7525a3568cbf88 GIT binary patch literal 140288 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

8t}sK4@%^+(?kgiGvG&YqaDnMVun@EYe7RBTL+J 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 literal 0 HcmV?d00001 diff --git a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.deps.json b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.deps.json index f850763..c1ccd7d 100644 --- a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.deps.json +++ b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.deps.json @@ -7,9 +7,20 @@ "targets": { ".NETCoreApp,Version=v8.0": { "MedullaAdapter/1.0.0": { + "dependencies": { + "CommonUsage": "1.0.0.0" + }, "runtime": { "MedullaAdapter.dll": {} } + }, + "CommonUsage/1.0.0.0": { + "runtime": { + "CommonUsage.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } } } }, @@ -18,6 +29,11 @@ "type": "project", "serviceable": false, "sha512": "" + }, + "CommonUsage/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" } } } \ No newline at end of file diff --git a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll index 52be01ca1184d5661d4b41128b9a8cfdaee85ab8..cfce787598cb5dd5144278ad7abff176daf3be87 100644 GIT binary patch delta 18523 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 delta 18329 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 T$1ZI?!P~5BdSbg?s%QTKmk)BH diff --git a/Shared/MultiWheelChassisAdapter.cs b/Shared/MultiWheelChassisAdapter.cs index 0af8468..2ad3417 100644 --- a/Shared/MultiWheelChassisAdapter.cs +++ b/Shared/MultiWheelChassisAdapter.cs @@ -119,6 +119,10 @@ namespace MyParking.Shared // 禁用旧版DirectionAngle/ZeroDirection坐标偏置, // 保证SendXYThSpeed直接使用真实车体坐标系。 ResetToBodyFrame(); + + // 停车机器人优先保持当前机械舵角,通过反转轮速表达反向运动, + // 避免蟹行正反切换时四个舵轮无意义地旋转180°。 + _chassis.PreferMinimumSteeringTravel = true; } diff --git a/ref/CommonUsage.dll b/ref/CommonUsage.dll new file mode 100644 index 0000000000000000000000000000000000000000..cdb9124dbedd7e2752f99bbb9b7525a3568cbf88 GIT binary patch literal 140288 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

8t}sK4@%^+(?kgiGvG&YqaDnMVun@EYe7RBTL+J z%1Yqc=n&S$*<*`aKl9XoEE&<)@6G;-y6{}8fA|ow5R#<*Cgp`COQciJkPaDT(jc3< zUB*S)By=r1ab|4wB8TC%W@e2=3ACjNKm`K;cV;dzhribT}n_;8RL#% z*KgKW=Hu2C(Jd022^W9o!?1wnRAGf6V3v%ngJJFEGnfxXOl>#VN3CbK`uOInlmC8e zxGJ$ffSuEkBMPbc8^ha-PI$1wI+&HcaRx6L>dKJzu#a#713=CK4^;9~(a_wyKpeF& z)~%z_pJaEx-B5A$M)>(6DefmFAn7JKoN&u>YOM2kGLB~3hK~C5m}u#kCh;CUW8n|; zgn&()(PK4a!+qhm^U&Hv(bg!n)AhNzm6TR4#*=2_M#xYIQy$@sU$*gKjR6x$b(G)O zf-;<>PstUO+e4{Ew$#5C;<&;Ddj*%{dgmf07{=JQ&qgK1O~+eBqe)!ElLhDTE(5i^8ho=zX1z7_Xc z(|PNnH((*Rln6&PGz?Pbr?+u=uL5l=9AIVYjp~$pY8yBh>aX`CY!$NQ0Oo~ z!uP=40rf})fw9sk-)9_wH=0}!bFN?fjDPZs{>%}@(`KRXA6nm@$Qe%Kt5yHNw;z6o zs=kM+&i-=K+X~M8k<(^}yCYouFeaXpX6p&%teMv(6C*! zBJA^6eVA(-88FJ~4@9#`YkFNn!-5C9acz%rd`mN`wCCj;IN;p9^47;iY3_Dm1&}89 zU9;ZRw+b*NX+Fpyp_*opB25cA8MC!@@=MT0bDhjJu#;4VCZOl-U#CYt+grB$30z~bNcbh|7ND$d+k#vhStP6i=!XoeAFg&1pN zxiYz=`|&?B1`5m~& zsk10&GyhEI_7#o9OX|r}TF;XR+k#(7NIJbz&IFHr%eh-#zNrO{DM$Cglx#S2$dI9O z4J=DNi2?4MaFTLJ@g!Wu(8=hda{UozXroN4PCryXD6wS%#F<$8c3RuwnsIZ*VeTMP zVo-`-O2Sm&FY;P>u+J>;RMh1I`FYz^Ne?SS`hD_FqplmbOG?q+y_{LZZ@C}tW2tE? zS9g4?ejOiM=-9a*&hxg4mh@Nwf>RA?N}*PtS6S?0^u4PS{mPBHFD20)`gu1UAa1BP z?hWW@oR2}6vKz#$5V+C3qMlzoJMH62tPwG>2-%hn>82W-q~vDn@Y`xZva)|yv&^q#3%OAYp}dvow@cM^feVvfD3gNPkvRA+TKj)`3O3*8e% zT7zNg!8tz(0A;xID`=+Ou^A(0#tBTKpTeL@D+iM=;Tyz7@a2SO-STJzqgBM+n3=M> z^l+E(L13*sx8OR*uK)AgIsZ|GHoLYC6vb1BqfiNDuW8>mb!zVJFJrYh-?xJ>z-Nzt z;ziHjYP2EQ;m%Qnm)yuTC{8Gt-n7dsb)4bpQWsQAm?cAeo7lqbcAJEo-1=a!UooK| z)E)4I-KyjLVo*DuQ_ahUTie_}P9fa_sw?ee<^a}e`kXAE5tnz?F*(SsL=y2*6{yOY z#8c>C=y_T{H!9NOEcg3u(&zKTyTdDHf z$rM%`E`s13`$O}pX4~YD6WQAr;5f@5%d46nTK5t&E*2^3PtiE9a?mZ>wc!(9W6WHB z;OQDP=+`~SiI<$&##`d1ubZG-oi-u*+ zW)nK#jO=yLu!F^rOk?Ifp}r;L6QJfurakw`zqnTGs=*Tk2Wv!qkHd#_459AH;A)>= zVkJM$$fW)z*px`rkxtZ+P4xUp&~`#Jpc~f^(|{miAuRx9_=LaqQy5G}sGdv^SCYu0 zYCcw{1g3(<8iU~4tHUr1yCQlqjS)xIcWrIhsq_P}P4u}HVKCV!!knUA@FQGkLxXU5 z3iKZJ(H&oYmLrC>bM<<$rB9MW%GyL;eqicFQ&}L#G1{m(#Vsq@fsQr>sW)9WD7~>D zq0IG$@E#=71wZsc*{<=rf~$#o67^-3BwQ6IOblkxuCQ!=>LFyfXzabY(08At8 znb~g}o9{6s4)a;vZ`=AY?^cXo?;{ucpe59$Ili-r62%)Q-!dr4d5EdgFHR3M4QkI_ z_SxjEJaGd0Rz7Ib_Tw;0q}gL=OLI@8VcU|v>L@==%KYwCH>D^pGLZjC7ls)k@w@g9 z6iaL#6QSJccUCu%hT#1coRA~Yp3tRa#1)Z%&ZY(DBZ8pi2KLM zOl}<<5G)-9aFyd(8d2pXYi7IL2`)ICW*6%M69`!wl3Q;e=y^}|2E8wE+)+V0P1S-p z5%FCIx%-ZT)XxR!L4wjdsoWe|w~ql#SlLe;bk>)Lq715{fy^`LE-Q^IN!s7d zkeNgd%wKO2VDn=iA_N90a`BmFazFMRvl4$nLRcdU0HBJ#f0;5iqxnfq{13KhbVhop zvY{JsC{%REfi;;QJxp0t|Ieend6+}AR+G8;FDT)v7TSIK?O)n|jT9{6ce>;Z(3`DZ z-1!tfrkU}6D9bh(5Bp&@|Iv32p|j84x2#c|exe0Rgf$*|x5zkcLyJk2B;<*Q+1L+yO z^F;yTTNEz7C`Np3-yQp$oW3Ov_!b6=eAt79^Z(lKTF6c=DxS3fJtE z(;QU#*gRzzRa8X`iD!&LP8*UXZ2G84b5aP}zD zjKxXq@70mujhQn}etovWDt&+B5YZxB$h7-?&Z+L?_dGNPYqV^X8=s6#d`U_P!?1SS z?XJ~ArJsB8!3VekaAo{!i%ca7)G5c6P16niSLYaOvAxRmg>1ZtHdeTnc2`zE?YQ$#RdGmdnPP3gP0U!4&@f zq$4g?z}7}D1nH)wY?b%Tmnos6(6zbQ1EMBe1=7>p4D{Qb1YiLt&dRwUlyzFA&;3YM zpoOUnfjKgOE97}dy= z#=StD8|CLCQaQZ!Mp2=Znsz-4WlH@pZik?Fd+4K$k7+HKM&E>lyJ6$_uxwMs`;F?7 z9gcR-_?9MAH#{r)R0a1FE1&k21)dNDo_Ze_2F>ZhX?YZ`opsomFz8mLpG_m+(1n+aoQxw%4k%iXw@*nc z?T7`EIg|(@f_nDYek*0s9mP^buv01&Mrg(jmj|$mTPf^pVHEG|ZhbhvGvFmGy)q?H z*fT;{%M@My3@0o;2D+}D5%yT7(GNM>_~Po83_sqY0&WYnMiEOp74Q2-+3N7g6CjcB zBw;_9Du+HbXgI-)bF(jn9z$F$eaBxFMH+89Z;v70+*WihJu56B$w2~Av{+=KHwGT) zi}^N3Ve`19owI`)0VTLhQxM$dt3@WL9Om%vdqMM#b6+mXvsb4TuP5rm0^wN6WuRFJ%w0wPuM*z=fmo)va8^8G1RAIG zeX&klbCod!GZXWeb+2inP0^vm8n~7+l>$U>xqA`*!srCZaUo69G9;F&m}L@kQv4!+ zr``Mb_y?q2Q-i^L2^vq~G12c|*Wahuh+kTYiagUsYrb7?E0S`Fj=jjiW|rj#QXy$| zuG6jtFDHKV6i>pYZB6Tf6lbL7od`YubVY{_x$LosSvpAv?bcNz22(+{1RIE9_F`d! zx{o?N*?)CCX_`q{;$h7~OigGGbQtoHfA#=;fx{f$c|-K7v>~9SCDdj!pB&Ppl43!x zUCfr3tL)+a^pt|Zm^^p(P;lSN4!1}1)!~jpbL^{LFE7UKWEf0Px56)c>msC#vRvyFiWGDO{+;Lx28cgYR1raPBHCjZwisWgso*v8eP4?fB{iCv_Lq8}f zX>yYo5ed3R=?G6G$VM>FPExd1c$ZY8?8D9&gDhmuy8FLxseq|3xv$DKor;*3k2A%KQ@ln1DKZghDeNeX{lyV~|nkW1sy=aX6 z3{+RXK}rAp0rP8SKdCQ_XbGh5JbA@)fD!gMb?o(AdHq}2?GH$laas-~Kj^#hZiG5Z zX1FY@=G{DJzkHg+Nb;u7^0>`Jb+K!f7kNtbawv;s%rf%7lbEYqF(>ar5ieksYQxwW z!vrj3v9klWjOKh$H8o;P!U=b6=rd$7vg>D^yK2!XV_De0r#I#Q#L_!;Jdx0W{z1jY zCBHY%6apRELNY5@_^9KZg=KP?I9egmUx(gEM=7fB>W5^P(k_45&rbaNeR0ReM^|+# zOpAEyi>{FI2Cd?JVzI~dBG%N}AdWUpY5pd~vXOHn$o4UlGJz;N9dclExqKIOrum#+ zCkccRPJwZXk@)FQwMQAQnu@&5*W=XuF{{dg=9fD59XPwaRASS{WIJ2B=7j8zIjezv z2^_axPJM|qE9ODs$UcG?*O9+e=1m3x>L+2=eb3Sx2j-V;T)dXZN%zWKHSoWZt$aOE z$V}l5i+1W<_-dfBhm4nvomtWb6q@8NIH%kNU{A1k3N?~3E~(rMLS_=+3tJ$mDhRum zoJnh6zvc>;2nRqIen)a{|H0S-pVi46uGT46YcV2LQ6T?i2+~v`outgX1X$5Kcu?-%dzZa}gktX(0O&vVnr_y0Boa*9brZL1XZ8`V|VqQCta(X@K zl`)sVnzE2##Cci-cjYQY1$}?b6Xu;uwNholfXNOmaB>(vj=fcYDO`w#1t6Lyf1rbB zMGLt6g*WlaaW8;$1$;w%@jG`g0wc%x`Nz(H2y!bAU1Xm&t9}2F3p}U_7)~5%Ufm3$ zP1Qfvx)9em%~>q^-RtMz?w7-Ropw5RFP{2kMXULgfVZGBRz0^djbVR<%L{ChD9WjC|{X|cMg6{N!_edbiXu;>!R~y5fIR0Tp`~%9K z!Q4k$uh#;;rw@WpE3b?G{--ami*frW@K0+L{`cP36BW(=R>eNVdhdV_Mo+`X3#U6)cPG{cU>fS0n@dwZ|BiCd=ZfDEEXnt;(l?2N|{FSR-c5urKFPd&;eYch9t zi?m_r2{s`qUp|s$tB;JrU@E-b_p>b)u`O$5WEj0QMq<<7G2s1#N+(T7d+f zdDtuCnm?n}R5KU%M3x@YI;|I!GoVomQr$bDwqlLT=^!_95P7}`z3nubhm$tTpB2j~ z=;RwbD>rCT(XXsEea2g!*Lv5;k8;;=`UA;*YAq4*JCce*YLhq z5sF8F-ia$to5ph8)5k)Zg%o@I^WDq| zn_+>=0=uK6CxN9qY{opf&3clj!1?X_hsofFRu>c^Q}9Y1xzg(%L@Y?q$(R(|m*G`L zfsm*TM_v%exZS{%H)fp;#)=!J^2PczTp4$uw7AE z>trkgpOGHF&V$QDIM+W(r2Nzm)TAkNq_y5PbK_#EyD-gPtyE|t1oSx$G(yDgphc)8 zXRoAb-O;TlMJOz_>(d=LQt>TDbRl|#x|Lk&}!7%DY(yBfU?>Ir0@{f+y zX=2oBe4*u5Xx-sj88rpE*38-}Cau(&+%hvfcF@Fy_bPl`aoO=``?9zD1v}O0icN89 zryP^7SvqoNV(dW0GeMD`rj+nfz%4wy6m@6|wow;5MYwhSjP||~BAYDG$maOFIBC-t zg&2KYY3mVlwZjUA16=VMibR`gCC<7=8-|mgwG_@1f1Ewq-Dp)!Mb|X?0mUKcl}7lw z15;hnL8J9{OF&~VKK7rz0lW{4**d>eCB04+pY|V~7HtLYj0Nssa-ZF(LB*cAlUD>` zbA#!>o?t0mD1G_3xwKi@iiF_&oF;WeBcM9mWO*}It@WAPp-rTrLznIi@L)7o9AkMs zQmK!-!Z z#|pm7g)D2AUQ446tnM{5qrDFS$5v@yG_j}Gt>r6`tEa+4(#`!5Z71`e=tI!)8a~I& zIm*Hrf5}=aF!MljvKf1{4KprRfXd2)J*&ZF5eU6Fh}Vnp+FJh8EtSQqLr-lmoHGK@ zJvU7K#x7JFS!Wgzt&+@5WaNxrab6NGA=4U+l@?AuFG+o#teS<#Bu3_;;zpfrrb5OO zj!VJ7sjE3*>}I29US$9!dS^#2%Dy-@ds@gx(Ge^ z8>qgA400^SeEpyzfMtwZNA|wtiAPBp*fGZLQ!)V88(9`aer=imm@ytvKu>QxLv zG#z{Jme?jnzqxnbVxQ94*PkWgr}Z|Mb>cX9AR4OhZY+JXEhVHuX>CYndHbzzQdr#g zresYHavC>F=WikXY>eUC?Qc|{)&5E>P0pjgWg&0^Ob7BR4bsOfY#LWYe#s*3R- z@3^63HP&p?IeY^vUok{J)b28V%KA)8f@@d(RRVpvt)p7yjz?b0(AaY>nEsbR3Jtk! z-0?38eP5=DQunjNi^V(rt*D4~?=3F<)*S$Z)-5r9kMbY-&lT$Yc0;+kg>K8M8JGYF zS@csz2Z<U zoFO>xfv-2G!8_G=)1E4<$6!adBi+(Z^7zn@bWHVG|0@Yt7TF&JbCA)#5QkbEXG8AW zy#}y|P7zBmFF^-VFA4r(5s6`o?N|0>w$)3cnB%2qlW>LqQ3YiP$-EV*uSLB11FPV7 zCE+=VMni7dpw0moy9UQoqS!63<#p=IS-2%By1qXOcxwPAifi~?$qPMNfO@&6u55Q? zT>w=-Xiu+giJ@k9mqu3+lomnC7%6&l$-GDfRk6zZO#xY3u~1uP#AAmJ*5RZRJ|LeTz4Za0aH-Q+Qqk$VsIqmOG%Hd z>?O-4a~p^PZM)R(A$2=!tCj#a;$wN8H(ZR)#E(=)St02U20T?8Z|-uE+nId}w7M!e zpzW_DzAz(TXuGlHJn}Zm3~iO&UVye1Ttoyq)1(!&+u`i@=ilbjUY1N@m~3f-3>j0} z$Ww>MKd^2phhMGPxpn2IkzL}2!=%sIO2u7q4GmMr=FJowjyWWSUC)$JH_fK!(yU@d z)2ysu3aUP4H7}9JJnEGF=~$XAE_&CI*v{={o!4_s zOwd!bBfNadL{uDNGa1Nt?oCu>coR;3$yShpKnwJ4`2Jkh%W9sK7rDUFJGrDtZwfI zE$kfp<7It=O@HXb?z8pz6xaLd$@U$%pinJ}${#b?L_J3-ym88i7M@`jj3%!$8z9ni zK@t#=%ubi>q|+~Bnq}oHa|VTm2k~qF@}56{0Yu!`Wz9!JINFBm}15vk*@kL>qla@n1~1jRfskU$o&q#8pn zb4$&_z?^ZC= z*5-rA0n)Z$QofBkpuzn=mBg$@G3P}IR$%+^-k*vcNl&gGkf zvzZx#sjcmQuz<g>Gz|=d--qb zh5>^96-DxIq{qMMUuVI8RsI!^^FPY}K8gK9r2%0K;ruSg3c?n`>|LfkggJ!6KO|)T zaH+lb8o#%?y!RVJxW3alyx0Df>R{O3ZH0Wd$@QJe>b>3Ke9~!22zyGzdL74o- z0D=qR(>t%|yF5Dx$A5Hqy?bQ*UNieg{J(na{?VuYuHX1w`rjU*fB61wvDkZ?3&gj7 z^gI4H`~JW9nIJyA>-{&s#yh|ByM+Jriy4C9-M)Y4zxq($>Hi|*`VX!ByCt^&#nS(| z9tH^0cdEZni1+x~@BDJ_ycYj({-t+>@cPGM3kb`1sSy7>grxq_qxc`~f6@G_=ihez zt^Es`|CPRf;i~j5$Kl-uw|8t@|BJQnaX|k;{C~ui2?Flj&i~H$|3>FOvH5%b{^BV7 wj-AW9Z+7oj)%M-1ukYjZza#peJby9$-!w5ny^qTG#Ph$YfB)C5|6c_DA1n&^hX4Qo literal 0 HcmV?d00001