From 6a443e111cd58a4f29dcda38bbff38c1c8b787ce Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Fri, 7 Mar 2025 14:32:18 +0100 Subject: [PATCH] Re-organised the repo --- .gitignore | 6 +- .vscode/launch.json | 14 ++ Examples/BB2B/BB2B.csproj | 11 ++ Examples/BB2B/Program.cs | 35 ++++ LinearAlgebra/Angle.cs.meta | 2 - LinearAlgebra/Direction.cs.meta | 11 -- LinearAlgebra/Quat32.cs.meta | 11 -- LinearAlgebra/Spherical.cs.meta | 11 -- LinearAlgebra/SwingTwist.cs.meta | 11 -- RoboidControl.sln | 39 +++++ {LinearAlgebra => src/LinearAlgebra}/Angle.cs | 0 .../LinearAlgebra}/Direction.cs | 0 .../LinearAlgebra}/Matrix.cs | 0 .../LinearAlgebra}/Quat32.cs | 0 .../LinearAlgebra}/Quaternion.cs | 0 .../LinearAlgebra}/Spherical.cs | 0 .../LinearAlgebra}/SwingTwist.cs | 0 .../LinearAlgebra}/Vector2.cs | 0 .../LinearAlgebra}/Vector3.cs | 0 .../LinearAlgebra}/float16.cs | 0 Participant.cs => src/LocalParticipant.cs | 65 ++++---- {Messages => src/Messages}/BinaryMsg.cs | 0 {Messages => src/Messages}/DestroyMsg.cs | 0 {Messages => src/Messages}/InvestigateMsg.cs | 0 .../Messages}/LowLevelMessages.cs | 0 {Messages => src/Messages}/Messages.cs | 0 {Messages => src/Messages}/ModelUrlMsg.cs | 0 {Messages => src/Messages}/NameMsg.cs | 0 {Messages => src/Messages}/NetworkIdMsg.cs | 0 {Messages => src/Messages}/ParticipantMsg.cs | 0 {Messages => src/Messages}/PoseMsg.cs | 0 {Messages => src/Messages}/TextMsg.cs | 0 {Messages => src/Messages}/ThingMsg.cs | 0 RemoteParticipant.cs => src/Participant.cs | 9 +- .../RoboidControl.csproj | 0 SiteServer.cs => src/SiteServer.cs | 12 +- Thing.cs => src/Thing.cs | 156 ++++++++++-------- src/Things/DifferentialDrive.cs | 51 ++++++ {Sensors => src/Things}/DistanceSensor.cs | 4 +- {Sensors => src/Things}/TemperatureSensor.cs | 2 +- {Sensors => src/Things}/TouchSensor.cs | 40 ++--- src/TimeManger.cs | 22 +++ test.meta | 8 - test.sln | 36 ---- test/UnitTest1.cs | 10 +- test/test.csproj | 2 +- 46 files changed, 340 insertions(+), 228 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 Examples/BB2B/BB2B.csproj create mode 100644 Examples/BB2B/Program.cs delete mode 100644 LinearAlgebra/Angle.cs.meta delete mode 100644 LinearAlgebra/Direction.cs.meta delete mode 100644 LinearAlgebra/Quat32.cs.meta delete mode 100644 LinearAlgebra/Spherical.cs.meta delete mode 100644 LinearAlgebra/SwingTwist.cs.meta create mode 100644 RoboidControl.sln rename {LinearAlgebra => src/LinearAlgebra}/Angle.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/Direction.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/Matrix.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/Quat32.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/Quaternion.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/Spherical.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/SwingTwist.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/Vector2.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/Vector3.cs (100%) rename {LinearAlgebra => src/LinearAlgebra}/float16.cs (100%) rename Participant.cs => src/LocalParticipant.cs (83%) rename {Messages => src/Messages}/BinaryMsg.cs (100%) rename {Messages => src/Messages}/DestroyMsg.cs (100%) rename {Messages => src/Messages}/InvestigateMsg.cs (100%) rename {Messages => src/Messages}/LowLevelMessages.cs (100%) rename {Messages => src/Messages}/Messages.cs (100%) rename {Messages => src/Messages}/ModelUrlMsg.cs (100%) rename {Messages => src/Messages}/NameMsg.cs (100%) rename {Messages => src/Messages}/NetworkIdMsg.cs (100%) rename {Messages => src/Messages}/ParticipantMsg.cs (100%) rename {Messages => src/Messages}/PoseMsg.cs (100%) rename {Messages => src/Messages}/TextMsg.cs (100%) rename {Messages => src/Messages}/ThingMsg.cs (100%) rename RemoteParticipant.cs => src/Participant.cs (94%) rename ControlCore.csproj => src/RoboidControl.csproj (100%) rename SiteServer.cs => src/SiteServer.cs (87%) rename Thing.cs => src/Thing.cs (88%) create mode 100644 src/Things/DifferentialDrive.cs rename {Sensors => src/Things}/DistanceSensor.cs (85%) rename {Sensors => src/Things}/TemperatureSensor.cs (86%) rename {Sensors => src/Things}/TouchSensor.cs (80%) create mode 100644 src/TimeManger.cs delete mode 100644 test.meta delete mode 100644 test.sln diff --git a/.gitignore b/.gitignore index 2602af4..3a21083 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ DoxyGen/DoxyWarnLogfile.txt .vscode/settings.json -test/bin -test/obj -/bin -/obj +**bin +**obj **.meta \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ee82cc1 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "C#: BB2B Debug", + "type": "dotnet", + "request": "launch", + "projectPath": "${workspaceFolder}/Examples/BB2B/BB2B.csproj" + } + ] +} \ No newline at end of file diff --git a/Examples/BB2B/BB2B.csproj b/Examples/BB2B/BB2B.csproj new file mode 100644 index 0000000..3499cad --- /dev/null +++ b/Examples/BB2B/BB2B.csproj @@ -0,0 +1,11 @@ + + + + Exe + net5.0 + + + + + + diff --git a/Examples/BB2B/Program.cs b/Examples/BB2B/Program.cs new file mode 100644 index 0000000..d30d335 --- /dev/null +++ b/Examples/BB2B/Program.cs @@ -0,0 +1,35 @@ +using System; +using System.Diagnostics; +using System.Threading; +using RoboidControl; + +class BB2B { + static void Main() { + // The robot's propulsion is a differential drive + DifferentialDrive bb2b = new DifferentialDrive(); + // Is has a touch sensor at the front left of the roboid + TouchSensor touchLeft = new TouchSensor(bb2b); + // and other one on the right + TouchSensor touchRight = new TouchSensor(bb2b); + + // Do forever: + while (true) { + Console.Write("A"); + // The left wheel turns forward when nothing is touched on the right side + // and turn backward when the roboid hits something on the right + float leftWheelSpeed = (touchRight.touchedSomething) ? -600.0f : 600.0f; + // The right wheel does the same, but instead is controlled by + // touches on the left side + float rightWheelSpeed = (touchLeft.touchedSomething) ? -600.0f : 600.0f; + // When both sides are touching something, both wheels will turn backward + // and the roboid will move backwards + bb2b.SetWheelVelocity(leftWheelSpeed, rightWheelSpeed); + + // Update the roboid state + bb2b.Update(true); + + // and sleep for 100ms + Thread.Sleep(100); + } + } +} \ No newline at end of file diff --git a/LinearAlgebra/Angle.cs.meta b/LinearAlgebra/Angle.cs.meta deleted file mode 100644 index 2b65666..0000000 --- a/LinearAlgebra/Angle.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: ee99a6777ed47f743be8068c6ede98c8 \ No newline at end of file diff --git a/LinearAlgebra/Direction.cs.meta b/LinearAlgebra/Direction.cs.meta deleted file mode 100644 index 206e1a6..0000000 --- a/LinearAlgebra/Direction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9975e4702de32624e8d3deaf84669f2f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/LinearAlgebra/Quat32.cs.meta b/LinearAlgebra/Quat32.cs.meta deleted file mode 100644 index c3f81a4..0000000 --- a/LinearAlgebra/Quat32.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 96aa3cf18eaeb574d9265704d68000da -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/LinearAlgebra/Spherical.cs.meta b/LinearAlgebra/Spherical.cs.meta deleted file mode 100644 index 5ba10b9..0000000 --- a/LinearAlgebra/Spherical.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 33f05ee51ff6f7042b3e22723bcfc4f5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/LinearAlgebra/SwingTwist.cs.meta b/LinearAlgebra/SwingTwist.cs.meta deleted file mode 100644 index 0c64209..0000000 --- a/LinearAlgebra/SwingTwist.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 003a6ec763b101642b0589486f087aef -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/RoboidControl.sln b/RoboidControl.sln new file mode 100644 index 0000000..daf2834 --- /dev/null +++ b/RoboidControl.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{B65BB41E-5A93-46FC-BA68-B865F50D57BD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{D6086F71-404B-4D18-BBE9-45947ED33DB2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BB2B", "Examples\BB2B\BB2B.csproj", "{488F28B2-A2CC-4E32-8D3B-7DB4EB1485F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoboidControl", "src\RoboidControl.csproj", "{72BFCD03-FA78-4D0B-8B36-32301D60D6DD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B65BB41E-5A93-46FC-BA68-B865F50D57BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B65BB41E-5A93-46FC-BA68-B865F50D57BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B65BB41E-5A93-46FC-BA68-B865F50D57BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B65BB41E-5A93-46FC-BA68-B865F50D57BD}.Release|Any CPU.Build.0 = Release|Any CPU + {488F28B2-A2CC-4E32-8D3B-7DB4EB1485F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {488F28B2-A2CC-4E32-8D3B-7DB4EB1485F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {488F28B2-A2CC-4E32-8D3B-7DB4EB1485F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {488F28B2-A2CC-4E32-8D3B-7DB4EB1485F9}.Release|Any CPU.Build.0 = Release|Any CPU + {72BFCD03-FA78-4D0B-8B36-32301D60D6DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72BFCD03-FA78-4D0B-8B36-32301D60D6DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72BFCD03-FA78-4D0B-8B36-32301D60D6DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72BFCD03-FA78-4D0B-8B36-32301D60D6DD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {488F28B2-A2CC-4E32-8D3B-7DB4EB1485F9} = {D6086F71-404B-4D18-BBE9-45947ED33DB2} + EndGlobalSection +EndGlobal diff --git a/LinearAlgebra/Angle.cs b/src/LinearAlgebra/Angle.cs similarity index 100% rename from LinearAlgebra/Angle.cs rename to src/LinearAlgebra/Angle.cs diff --git a/LinearAlgebra/Direction.cs b/src/LinearAlgebra/Direction.cs similarity index 100% rename from LinearAlgebra/Direction.cs rename to src/LinearAlgebra/Direction.cs diff --git a/LinearAlgebra/Matrix.cs b/src/LinearAlgebra/Matrix.cs similarity index 100% rename from LinearAlgebra/Matrix.cs rename to src/LinearAlgebra/Matrix.cs diff --git a/LinearAlgebra/Quat32.cs b/src/LinearAlgebra/Quat32.cs similarity index 100% rename from LinearAlgebra/Quat32.cs rename to src/LinearAlgebra/Quat32.cs diff --git a/LinearAlgebra/Quaternion.cs b/src/LinearAlgebra/Quaternion.cs similarity index 100% rename from LinearAlgebra/Quaternion.cs rename to src/LinearAlgebra/Quaternion.cs diff --git a/LinearAlgebra/Spherical.cs b/src/LinearAlgebra/Spherical.cs similarity index 100% rename from LinearAlgebra/Spherical.cs rename to src/LinearAlgebra/Spherical.cs diff --git a/LinearAlgebra/SwingTwist.cs b/src/LinearAlgebra/SwingTwist.cs similarity index 100% rename from LinearAlgebra/SwingTwist.cs rename to src/LinearAlgebra/SwingTwist.cs diff --git a/LinearAlgebra/Vector2.cs b/src/LinearAlgebra/Vector2.cs similarity index 100% rename from LinearAlgebra/Vector2.cs rename to src/LinearAlgebra/Vector2.cs diff --git a/LinearAlgebra/Vector3.cs b/src/LinearAlgebra/Vector3.cs similarity index 100% rename from LinearAlgebra/Vector3.cs rename to src/LinearAlgebra/Vector3.cs diff --git a/LinearAlgebra/float16.cs b/src/LinearAlgebra/float16.cs similarity index 100% rename from LinearAlgebra/float16.cs rename to src/LinearAlgebra/float16.cs diff --git a/Participant.cs b/src/LocalParticipant.cs similarity index 83% rename from Participant.cs rename to src/LocalParticipant.cs index 175dbe5..3350485 100644 --- a/Participant.cs +++ b/src/LocalParticipant.cs @@ -9,7 +9,7 @@ namespace RoboidControl { /// /// A participant is used for communcation between things /// - public class Participant : RemoteParticipant { + public class LocalParticipant : Participant { public byte[] buffer = new byte[1024]; public ulong publishInterval = 3000; // = 3 seconds @@ -26,7 +26,7 @@ namespace RoboidControl { /// /// Create a porticiapnt /// - public Participant() { + public LocalParticipant() { //senders.Add(this); } @@ -34,16 +34,16 @@ namespace RoboidControl { /// Create a participant with the give UDP port /// /// The port number on which to communicate - // public Participant(int port) : this() { - // this.port = port; - // } + public LocalParticipant(int port) : this() { + this.port = port; + } /// /// Create a new participant for a site at the given address and port /// /// The ip address of the site server /// The port number of the site server - public Participant(string ipAddress = "0.0.0.0", int port = 7681) : this() { + public LocalParticipant(string ipAddress = "0.0.0.0", int port = 7681) : this() { this.ipAddress = ipAddress; this.port = port; @@ -61,35 +61,42 @@ namespace RoboidControl { /// /// UDP client to use for communication /// The port number on which to communicate - public Participant(UdpClient udpClient, int port) : this() { + public LocalParticipant(UdpClient udpClient, int port) : this() { this.udpClient = udpClient; this.port = port; } - public List owners = new List(); + private static LocalParticipant isolatedParticipant = null; + public static LocalParticipant Isolated() { + if (isolatedParticipant == null) + isolatedParticipant = new LocalParticipant(0); + return isolatedParticipant; + } - public RemoteParticipant GetParticipant(string ipAddress, int port) { + public List owners = new List(); + + public Participant GetParticipant(string ipAddress, int port) { //Console.WriteLine($"Get Participant {ipAddress}:{port}"); - foreach (RemoteParticipant sender in owners) { + foreach (Participant sender in owners) { if (sender.ipAddress == ipAddress && sender.port == port) return sender; } return null; } - public RemoteParticipant AddParticipant(string ipAddress, int port) { + public Participant AddParticipant(string ipAddress, int port) { Console.WriteLine($"New Participant {ipAddress}:{port}"); - RemoteParticipant participant = new(ipAddress, port) { + Participant participant = new(ipAddress, port) { networkId = (byte)(this.owners.Count + 1) }; owners.Add(participant); return participant; } - protected readonly Dictionary> thingMsgProcessors = new(); + protected readonly Dictionary> thingMsgProcessors = new(); - public delegate Thing ThingConstructor(RemoteParticipant sender, byte networkId, byte thingId); + public delegate Thing ThingConstructor(Participant sender, byte networkId, byte thingId); public void Register(byte thingType, ThingConstructor constr) { - thingMsgProcessors[thingType] = new Func(constr); + thingMsgProcessors[thingType] = new Func(constr); } public void Register(Thing.Type thingType) where ThingClass : Thing { @@ -118,7 +125,7 @@ namespace RoboidControl { // We can receive our own publish (broadcast) packages. How do we recognize them???? // It is hard to determine our source port string ipAddress = this.endPoint.Address.ToString(); - RemoteParticipant remoteParticipant = GetParticipant(ipAddress, this.endPoint.Port); + Participant remoteParticipant = GetParticipant(ipAddress, this.endPoint.Port); remoteParticipant ??= AddParticipant(ipAddress, this.endPoint.Port); ReceiveData(data, remoteParticipant); @@ -161,7 +168,7 @@ namespace RoboidControl { #region Send - public void SendThingInfo(RemoteParticipant remoteParticipant, Thing thing) { + public void SendThingInfo(Participant remoteParticipant, Thing thing) { Console.WriteLine("Send thing info"); this.Send(remoteParticipant, new ThingMsg(this.networkId, thing)); this.Send(remoteParticipant, new NameMsg(this.networkId, thing)); @@ -169,7 +176,7 @@ namespace RoboidControl { this.Send(remoteParticipant, new BinaryMsg(this.networkId, thing)); } - public bool Send(RemoteParticipant remoteParticipant, IMessage msg) { + public bool Send(Participant remoteParticipant, IMessage msg) { int bufferSize = msg.Serialize(ref this.buffer); if (bufferSize <= 0) return true; @@ -220,7 +227,7 @@ namespace RoboidControl { #region Receive - public void ReceiveData(byte[] data, RemoteParticipant remoteParticipant) { + public void ReceiveData(byte[] data, Participant remoteParticipant) { byte msgId = data[0]; if (msgId == 0xFF) { // Timeout @@ -268,9 +275,9 @@ namespace RoboidControl { #region Process - protected virtual void Process(RemoteParticipant sender, ParticipantMsg msg) { } + protected virtual void Process(Participant sender, ParticipantMsg msg) { } - protected virtual void Process(RemoteParticipant sender, NetworkIdMsg msg) { + protected virtual void Process(Participant sender, NetworkIdMsg msg) { Console.WriteLine($"{this.name} receive network id {this.networkId} {msg.networkId}"); if (this.networkId != msg.networkId) { this.networkId = msg.networkId; @@ -279,27 +286,27 @@ namespace RoboidControl { } } - protected virtual void Process(RemoteParticipant sender, InvestigateMsg msg) { } + protected virtual void Process(Participant sender, InvestigateMsg msg) { } - protected virtual void Process(RemoteParticipant sender, ThingMsg msg) { + protected virtual void Process(Participant sender, ThingMsg msg) { //Console.WriteLine($"Participant: Process thing [{msg.networkId}/{msg.thingId}]"); } - protected virtual void Process(RemoteParticipant sender, NameMsg msg) { + protected virtual void Process(Participant sender, NameMsg msg) { //Console.WriteLine($"Participant: Process name [{msg.networkId}/{msg.thingId}] {msg.name}"); Thing thing = sender.Get(msg.networkId, msg.thingId); if (thing != null) thing.name = msg.name; } - protected virtual void Process(RemoteParticipant sender, ModelUrlMsg msg) { + protected virtual void Process(Participant sender, ModelUrlMsg msg) { //Console.WriteLine($"Participant: Process model [{msg.networkId}/{msg.thingId}] {msg.url}"); Thing thing = sender.Get(msg.networkId, msg.thingId); if (thing != null) thing.modelUrl = msg.url; } - protected virtual void Process(RemoteParticipant sender, PoseMsg msg) { + protected virtual void Process(Participant sender, PoseMsg msg) { //Console.WriteLine($"Participant: Process pose [{msg.networkId}/{msg.thingId}] {msg.poseType}"); Thing thing = sender.Get(msg.networkId, msg.thingId); if (thing != null) { @@ -320,15 +327,15 @@ namespace RoboidControl { } } - protected virtual void Process(RemoteParticipant sender, BinaryMsg msg) { + protected virtual void Process(Participant sender, BinaryMsg msg) { // Console.WriteLine($"Participant: Process binary [{msg.networkId}/{msg.thingId}]"); Thing thing = sender.Get(msg.networkId, msg.thingId); thing?.ProcessBinary(msg.bytes); } - protected virtual void Process(RemoteParticipant sender, TextMsg temsgxt) { } + protected virtual void Process(Participant sender, TextMsg temsgxt) { } - protected virtual void Process(RemoteParticipant sender, DestroyMsg msg) { } + protected virtual void Process(Participant sender, DestroyMsg msg) { } private void ForwardMessage(IMessage msg) { // foreach (Participant client in senders) { diff --git a/Messages/BinaryMsg.cs b/src/Messages/BinaryMsg.cs similarity index 100% rename from Messages/BinaryMsg.cs rename to src/Messages/BinaryMsg.cs diff --git a/Messages/DestroyMsg.cs b/src/Messages/DestroyMsg.cs similarity index 100% rename from Messages/DestroyMsg.cs rename to src/Messages/DestroyMsg.cs diff --git a/Messages/InvestigateMsg.cs b/src/Messages/InvestigateMsg.cs similarity index 100% rename from Messages/InvestigateMsg.cs rename to src/Messages/InvestigateMsg.cs diff --git a/Messages/LowLevelMessages.cs b/src/Messages/LowLevelMessages.cs similarity index 100% rename from Messages/LowLevelMessages.cs rename to src/Messages/LowLevelMessages.cs diff --git a/Messages/Messages.cs b/src/Messages/Messages.cs similarity index 100% rename from Messages/Messages.cs rename to src/Messages/Messages.cs diff --git a/Messages/ModelUrlMsg.cs b/src/Messages/ModelUrlMsg.cs similarity index 100% rename from Messages/ModelUrlMsg.cs rename to src/Messages/ModelUrlMsg.cs diff --git a/Messages/NameMsg.cs b/src/Messages/NameMsg.cs similarity index 100% rename from Messages/NameMsg.cs rename to src/Messages/NameMsg.cs diff --git a/Messages/NetworkIdMsg.cs b/src/Messages/NetworkIdMsg.cs similarity index 100% rename from Messages/NetworkIdMsg.cs rename to src/Messages/NetworkIdMsg.cs diff --git a/Messages/ParticipantMsg.cs b/src/Messages/ParticipantMsg.cs similarity index 100% rename from Messages/ParticipantMsg.cs rename to src/Messages/ParticipantMsg.cs diff --git a/Messages/PoseMsg.cs b/src/Messages/PoseMsg.cs similarity index 100% rename from Messages/PoseMsg.cs rename to src/Messages/PoseMsg.cs diff --git a/Messages/TextMsg.cs b/src/Messages/TextMsg.cs similarity index 100% rename from Messages/TextMsg.cs rename to src/Messages/TextMsg.cs diff --git a/Messages/ThingMsg.cs b/src/Messages/ThingMsg.cs similarity index 100% rename from Messages/ThingMsg.cs rename to src/Messages/ThingMsg.cs diff --git a/RemoteParticipant.cs b/src/Participant.cs similarity index 94% rename from RemoteParticipant.cs rename to src/Participant.cs index ee5a0b9..53f637e 100644 --- a/RemoteParticipant.cs +++ b/src/Participant.cs @@ -6,7 +6,7 @@ namespace RoboidControl { /// /// A reference to a participant, possibly on a remote location /// - public class RemoteParticipant { + public class Participant { /// /// The internet address of the participant /// @@ -24,13 +24,13 @@ namespace RoboidControl { /// /// Default constructor /// - public RemoteParticipant() {} + public Participant() { } /// /// Create a new remote participant /// /// The IP address of the participant /// The UDP port of the participant - public RemoteParticipant(string ipAddress, int port) { + public Participant(string ipAddress, int port) { this.ipAddress = ipAddress; this.port = port; } @@ -68,7 +68,8 @@ namespace RoboidControl { if (invokeEvent) Thing.InvokeNewThing(thing); // Console.Write($"Add thing {ipAddress}:{port}[{networkId}/{thing.id}]"); - } else { + } + else { if (thing != foundThing) { // should be: find first non-existing id... thing.id = (byte)this.things.Count; diff --git a/ControlCore.csproj b/src/RoboidControl.csproj similarity index 100% rename from ControlCore.csproj rename to src/RoboidControl.csproj diff --git a/SiteServer.cs b/src/SiteServer.cs similarity index 87% rename from SiteServer.cs rename to src/SiteServer.cs index ab21e80..ce2d178 100644 --- a/SiteServer.cs +++ b/src/SiteServer.cs @@ -7,7 +7,7 @@ namespace RoboidControl { /// /// A site server is a participant which provides a shared simulated environment /// - public class SiteServer : Participant { + public class SiteServer : LocalParticipant { public SiteServer(int port = 7681) : this("0.0.0.0", port) { } @@ -28,7 +28,7 @@ namespace RoboidControl { this.udpClient.BeginReceive( new AsyncCallback(result => ReceiveUDP(result)), new Tuple(this.udpClient, new(IPAddress.Any, port))); - + Register(Thing.Type.TouchSensor); } @@ -42,21 +42,21 @@ namespace RoboidControl { public override void Publish() { } - protected override void Process(RemoteParticipant remoteParticipant, ParticipantMsg msg) { + protected override void Process(Participant remoteParticipant, ParticipantMsg msg) { if (msg.networkId == 0) { Console.WriteLine($"{this.name} received New Client -> {remoteParticipant.networkId}"); this.Send(remoteParticipant, new NetworkIdMsg(remoteParticipant.networkId)); } } - protected override void Process(RemoteParticipant sender, NetworkIdMsg msg) { } + protected override void Process(Participant sender, NetworkIdMsg msg) { } - protected override void Process(RemoteParticipant sender, ThingMsg msg) { + protected override void Process(Participant sender, ThingMsg msg) { //Console.WriteLine($"SiteServer: Process thing [{msg.networkId}/{msg.thingId}]"); Thing thing = sender.Get(msg.networkId, msg.thingId); if (thing == null) { Thing newThing = null; - if (thingMsgProcessors.TryGetValue(msg.thingType, out Func msgProcessor)) { + if (thingMsgProcessors.TryGetValue(msg.thingType, out Func msgProcessor)) { //Console.WriteLine("Found thing message processor"); if (msgProcessor != null) newThing = msgProcessor(sender, msg.networkId, msg.thingId); diff --git a/Thing.cs b/src/Thing.cs similarity index 88% rename from Thing.cs rename to src/Thing.cs index f87f81d..3f12b62 100644 --- a/Thing.cs +++ b/src/Thing.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using Passer.LinearAlgebra; namespace RoboidControl { @@ -12,28 +13,6 @@ namespace RoboidControl { #region Types - #endregion Types - - #region Properties - - public delegate void ChangeHandler(); - public delegate void SphericalHandler(Spherical v); - public delegate void ThingHandler(Thing t); - - /// - /// The participant to which this thing belongs - /// - public RemoteParticipant owner; - - /// - /// The network ID of this thing. - /// - public byte networkId; - /// - /// The ID of this thing - /// - public byte id; - /// /// Predefined thing types /// @@ -54,6 +33,81 @@ namespace RoboidControl { Humanoid, ExternalSensor }; + + #endregion Types + + #region Init + + public Thing(byte thingType = (byte)Type.Undetermined) : this(LocalParticipant.Isolated(), thingType) { + } + + public Thing(Participant owner, byte thingType = (byte)Type.Undetermined) { + this.owner = owner; + this.type = thingType; + } + + public Thing(Thing parent, byte thingType = (byte)Type.Undetermined) : this(parent.owner, thingType) { + this.parent = parent; + } + + /// + /// Create a new thing for the given participant + /// + /// The participant for which this thing is created + /// True when a new thing event should be triggered + public Thing(Participant owner, bool invokeEvent = false) { + this.owner = owner; + //owner.Add(this); + if (invokeEvent) + InvokeNewThing(this); + } + /// + /// Create a new thing for the given participant + /// + /// The participant for which this thing is created + /// The network ID of the thing + /// The ID of the thing + /// The type of thing + public Thing(Participant participant, byte networkId, byte thingId, byte thingType = 0) { + this.owner = participant; + this.id = thingId; + this.type = thingType; + this.networkId = networkId; + } + + /// + /// Function which can be used to create components in external engines. + /// + /// Currently this is used to create GameObjects in Unity + public virtual void CreateComponent() { +#if UNITY_5_3_OR_NEWER + this.component = Unity.Thing.Create(this); + this.component.core = this; +#endif + } + + #endregion Init + + #region Properties + + public delegate void ChangeHandler(); + public delegate void SphericalHandler(Spherical v); + public delegate void ThingHandler(Thing t); + + /// + /// The participant to which this thing belongs + /// + public Participant owner; + + /// + /// The network ID of this thing. + /// + public byte networkId; + /// + /// The ID of this thing + /// + public byte id; + /// /// The type of this thing. This can be either a Thing::Type (needs casting) /// or a byte value for custom types. @@ -201,62 +255,30 @@ namespace RoboidControl { #endregion Properties - #region Init - - /// - /// Create a new thing for the given participant - /// - /// The participant for which this thing is created - /// True when a new thing event should be triggered - public Thing(RemoteParticipant owner, bool invokeEvent = false) { - this.owner = owner; - //owner.Add(this); - if (invokeEvent) - InvokeNewThing(this); - } - /// - /// Create a new thing for the given participant - /// - /// The participant for which this thing is created - /// The network ID of the thing - /// The ID of the thing - /// The type of thing - public Thing(RemoteParticipant participant, byte networkId, byte thingId, byte thingType = 0) { - this.owner = participant; - this.id = thingId; - this.type = thingType; - this.networkId = networkId; - } - - /// - /// Function which can be used to create components in external engines. - /// - /// Currently this is used to create GameObjects in Unity - public virtual void CreateComponent() { -#if UNITY_5_3_OR_NEWER - this.component = Unity.Thing.Create(this); - this.component.core = this; -#endif - } - - #endregion Init - #region Update -#if UNITY_5_3_OR_NEWER + // #if UNITY_5_3_OR_NEWER /// /// Convience function for use in Unity which removes the need for a currentTime argument /// - public void Update() { - Update((ulong)UnityEngine.Time.time * 1000); + public void Update(bool recursive = false) { + Update(TimeManager.GetCurrentTimeMilliseconds(), recursive); } -#endif + // #endif /// /// Update this thing /// /// The current time in milliseconds - public virtual void Update(ulong currentTime) { + public virtual void Update(ulong currentTimeMs, bool recursive = false) { // should recurse over children... + if (recursive) { + for (byte childIx = 0; childIx < this.children.Count; childIx++) { + Thing child = this.children[childIx]; + if (child == null) + continue; + child.Update(currentTimeMs, recursive); + } + } } /// diff --git a/src/Things/DifferentialDrive.cs b/src/Things/DifferentialDrive.cs new file mode 100644 index 0000000..8dcfb2e --- /dev/null +++ b/src/Things/DifferentialDrive.cs @@ -0,0 +1,51 @@ +namespace RoboidControl { + + /// @brief A thing which can move itself using a differential drive system + /// + /// @sa @link https://en.wikipedia.org/wiki/Differential_wheeled_robot @endlink + public class DifferentialDrive : Thing { + /// @brief Create a differential drive without networking support + public DifferentialDrive() { } + /// @brief Create a differential drive with networking support + /// @param participant The local participant + public DifferentialDrive(LocalParticipant participant) : base(participant, false) { } + + /// @brief Configures the dimensions of the drive + /// @param wheelDiameter The diameter of the wheels in meters + /// @param wheelSeparation The distance between the wheels in meters + /// + /// These values are used to compute the desired wheel speed from the set + /// linear and angular velocity. + /// @sa SetLinearVelocity SetAngularVelocity + public void SetDriveDimensions(float wheelDiameter, float wheelSeparation) { } + /// @brief Congures the motors for the wheels + /// @param leftWheel The motor for the left wheel + /// @param rightWheel The motor for the right wheel + public void SetMotors(Thing leftWheel, Thing rightWheel) { } + + /// @brief Directly specify the speeds of the motors + /// @param speedLeft The speed of the left wheel in degrees per second. + /// Positive moves the robot in the forward direction. + /// @param speedRight The speed of the right wheel in degrees per second. + /// Positive moves the robot in the forward direction. + + public void SetWheelVelocity(float speedLeft, float speedRight) { } + + /// @copydoc RoboidControl::Thing::Update(unsigned long) + public override void Update(ulong currentMs, bool recursive = true) { } + + /// @brief The radius of a wheel in meters + protected float wheelRadius = 1.0f; + /// @brief The distance between the wheels in meters + protected float wheelSeparation = 1.0f; + + /// @brief Convert revolutions per second to meters per second + protected float rpsToMs = 1.0f; + + /// @brief The left wheel + protected Thing leftWheel = null; + /// @brief The right wheel + protected Thing rightWheel = null; + }; + +} // namespace RoboidControl \ No newline at end of file diff --git a/Sensors/DistanceSensor.cs b/src/Things/DistanceSensor.cs similarity index 85% rename from Sensors/DistanceSensor.cs rename to src/Things/DistanceSensor.cs index ade3998..c83d940 100644 --- a/Sensors/DistanceSensor.cs +++ b/src/Things/DistanceSensor.cs @@ -13,14 +13,14 @@ namespace RoboidControl { /// Constructor for a new distance sensor /// /// The participant for which the sensor is needed - public DistanceSensor(RemoteParticipant participant) : base(participant, true) { } + public DistanceSensor(Participant participant) : base(participant, true) { } /// /// Create a distance sensor with the given ID /// /// The participant for with the sensor is needed /// The network ID of the sensor /// The ID of the thing - public DistanceSensor(RemoteParticipant participant, byte networkId, byte thingId) : base(participant, networkId, thingId, (byte)Type.TemperatureSensor) { + public DistanceSensor(Participant participant, byte networkId, byte thingId) : base(participant, networkId, thingId, (byte)Type.TemperatureSensor) { } #if UNITY_5_3_OR_NEWER diff --git a/Sensors/TemperatureSensor.cs b/src/Things/TemperatureSensor.cs similarity index 86% rename from Sensors/TemperatureSensor.cs rename to src/Things/TemperatureSensor.cs index b0d6860..6f7e009 100644 --- a/Sensors/TemperatureSensor.cs +++ b/src/Things/TemperatureSensor.cs @@ -17,7 +17,7 @@ namespace RoboidControl { /// The participant for with the sensor is needed /// The network ID of the sensor /// The ID of the thing - public TemperatureSensor(Participant participant, byte networkId, byte thingId) : base(participant, networkId, thingId, (byte)Type.TemperatureSensor) {} + public TemperatureSensor(LocalParticipant participant, byte networkId, byte thingId) : base(participant, networkId, thingId, (byte)Type.TemperatureSensor) { } /// /// Function to extract the temperature received in the binary message diff --git a/Sensors/TouchSensor.cs b/src/Things/TouchSensor.cs similarity index 80% rename from Sensors/TouchSensor.cs rename to src/Things/TouchSensor.cs index 1474e4a..22dc290 100644 --- a/Sensors/TouchSensor.cs +++ b/src/Things/TouchSensor.cs @@ -7,7 +7,25 @@ namespace RoboidControl { /// public class TouchSensor : Thing { - public Participant thisParticipant; + /// + /// Create a touch sensor + /// + /// The participant for with the sensor is needed + /// True when the creation should trigger an event + public TouchSensor(Participant owner, bool invokeEvent = true) : base(owner, invokeEvent) { + //touchedSomething = false; + //thisParticipant = owner; + } + + public TouchSensor(Participant owner, byte networkId, byte thingId) : base(owner, networkId, thingId) { + Console.Write("TouchSensor constructor"); + //touchedSomething = false; + //thisParticipant = participant; + } + + public TouchSensor(Thing parent) : base(parent) { } + + public LocalParticipant thisParticipant; /// /// Value which is true when the sensor is touching something, false otherwise @@ -18,30 +36,14 @@ namespace RoboidControl { get { return _touchedSomething; } set { _touchedSomething = value; - if (thisParticipant != null && this.owner != thisParticipant ) { + if (thisParticipant != null && this.owner != thisParticipant) { BinaryMsg msg = new(networkId, this); - foreach (RemoteParticipant remoteParticipant in thisParticipant.owners) + foreach (Participant remoteParticipant in thisParticipant.owners) thisParticipant.Send(remoteParticipant, msg); } } } - /// - /// Create a touch sensor - /// - /// The participant for with the sensor is needed - /// True when the creation should trigger an event - public TouchSensor(RemoteParticipant owner, bool invokeEvent = true) : base(owner, invokeEvent) { - //touchedSomething = false; - //thisParticipant = owner; - } - - public TouchSensor(RemoteParticipant owner, byte networkId, byte thingId) : base(owner, networkId, thingId) { - Console.Write("TouchSensor constructor"); - //touchedSomething = false; - //thisParticipant = participant; - } - #if UNITY_5_3_OR_NEWER /// @copydoc Passer::RoboidControl::Thing::CreateComponent public override void CreateComponent() { diff --git a/src/TimeManger.cs b/src/TimeManger.cs new file mode 100644 index 0000000..875f459 --- /dev/null +++ b/src/TimeManger.cs @@ -0,0 +1,22 @@ +using System.Diagnostics; + +namespace RoboidControl { + public static class TimeManager { + private static readonly Stopwatch _stopwatch = new Stopwatch(); + + /// + /// Static constructor to start the stopwatch + /// + static TimeManager() { + _stopwatch.Start(); + } + + /// + /// Method to get the current time in milliseconds + /// + /// The current time in milliseconds + public static ulong GetCurrentTimeMilliseconds() { + return (ulong)_stopwatch.ElapsedMilliseconds; + } + } +} \ No newline at end of file diff --git a/test.meta b/test.meta deleted file mode 100644 index 89fd01d..0000000 --- a/test.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 239400f5314a5aa4bac98db5861f77a7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/test.sln b/test.sln deleted file mode 100644 index 5ab05c5..0000000 --- a/test.sln +++ /dev/null @@ -1,36 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCore", "ControlCore.csproj", "{F2DEE6B0-AF41-454E-AAC8-9E1E3ACC769F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{2C350E2B-9DDA-4037-BAE5-E12AB7A52398}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6601071A-9E9C-42E1-95EA-0A36C5D718E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6601071A-9E9C-42E1-95EA-0A36C5D718E4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6601071A-9E9C-42E1-95EA-0A36C5D718E4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6601071A-9E9C-42E1-95EA-0A36C5D718E4}.Release|Any CPU.Build.0 = Release|Any CPU - {DD7238DA-DBEF-4D6A-98DB-6FE28BBDB75D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DD7238DA-DBEF-4D6A-98DB-6FE28BBDB75D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DD7238DA-DBEF-4D6A-98DB-6FE28BBDB75D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DD7238DA-DBEF-4D6A-98DB-6FE28BBDB75D}.Release|Any CPU.Build.0 = Release|Any CPU - {F2DEE6B0-AF41-454E-AAC8-9E1E3ACC769F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F2DEE6B0-AF41-454E-AAC8-9E1E3ACC769F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F2DEE6B0-AF41-454E-AAC8-9E1E3ACC769F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F2DEE6B0-AF41-454E-AAC8-9E1E3ACC769F}.Release|Any CPU.Build.0 = Release|Any CPU - {2C350E2B-9DDA-4037-BAE5-E12AB7A52398}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2C350E2B-9DDA-4037-BAE5-E12AB7A52398}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2C350E2B-9DDA-4037-BAE5-E12AB7A52398}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2C350E2B-9DDA-4037-BAE5-E12AB7A52398}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/test/UnitTest1.cs b/test/UnitTest1.cs index be1bd9c..27012a9 100644 --- a/test/UnitTest1.cs +++ b/test/UnitTest1.cs @@ -5,7 +5,7 @@ using NUnit.Framework; using RoboidControl; -namespace ControlCore.test { +namespace RoboidControl.test { public class Tests { [SetUp] public void Setup() { @@ -13,7 +13,7 @@ namespace ControlCore.test { [Test] public void Test_Participant() { - Participant participant = new Participant("127.0.0.1", 7682); + LocalParticipant participant = new LocalParticipant("127.0.0.1", 7682); ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); ulong startTime = milliseconds; @@ -46,7 +46,7 @@ namespace ControlCore.test { [Test] public void Test_SiteParticipant() { SiteServer siteServer = new SiteServer(7681); - Participant participant = new Participant("127.0.0.1", 7681); + LocalParticipant participant = new LocalParticipant("127.0.0.1", 7681); ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); ulong startTime = milliseconds; @@ -64,8 +64,8 @@ namespace ControlCore.test { [Test] public void Test_ThingMsg() { SiteServer siteServer = new SiteServer(7681); - Participant participant = new Participant("127.0.0.1"); - Thing thing = new Thing(participant) { + LocalParticipant participant = new LocalParticipant("127.0.0.1"); + Thing thing = new Thing(participant, false) { name = "First Thing", modelUrl = "https://passer.life/extras/ant.jpg" }; diff --git a/test/test.csproj b/test/test.csproj index 1c81788..309ab05 100644 --- a/test/test.csproj +++ b/test/test.csproj @@ -13,7 +13,7 @@ - +