diff --git a/.gitignore b/.gitignore index 6188945..2602af4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ test/bin test/obj /bin /obj -*.meta \ No newline at end of file +**.meta \ No newline at end of file diff --git a/ControlCore.csproj.meta b/ControlCore.csproj.meta deleted file mode 100644 index 1b43085..0000000 --- a/ControlCore.csproj.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 7f964f406734cf74097d61697e5cafc9 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Messages/BinaryMsg.cs b/Messages/BinaryMsg.cs index f9ef94e..e72c6fd 100644 --- a/Messages/BinaryMsg.cs +++ b/Messages/BinaryMsg.cs @@ -47,10 +47,7 @@ namespace Passer.RoboidControl { this.thingId = thing.id; this.bytes = System.Array.Empty(); } - /// - /// Create the message for receiving - /// - /// The byte array to parse + /// @copydoc Passer::RoboidControl::IMessage::IMessage(byte[] buffer) public BinaryMsg(byte[] buffer) { byte ix = 1; this.networkId = buffer[ix++]; @@ -61,13 +58,9 @@ namespace Passer.RoboidControl { this.bytes[bytesIx] = buffer[ix++]; } - /// - /// Serialize the message into a byte array for sending - /// - /// The buffer to serilize into - /// The length of the message in the buffer + /// @copydoc Passer::RoboidControl::IMessage::Serialize public override byte Serialize(ref byte[] buffer) { - if (buffer.Length < BinaryMsg.length + buffer.Length || bytes.Length == 0) + if (buffer.Length < BinaryMsg.length + this.bytes.Length || this.bytes.Length == 0) return 0; byte ix = 0; diff --git a/Messages/DestroyMsg.cs b/Messages/DestroyMsg.cs index 1564a25..e5d0a8e 100644 --- a/Messages/DestroyMsg.cs +++ b/Messages/DestroyMsg.cs @@ -3,29 +3,52 @@ using System.Threading.Tasks; namespace Passer.RoboidControl { + /// + /// Message notifiying that a Thing no longer exists + /// public class DestroyMsg : IMessage { + /// + /// The message ID + /// public const byte Id = 0x20; + /// + /// The length of the message + /// public const byte length = 3; + /// + /// The network ID of the thing + /// public byte networkId; + /// + /// The ID of the thing + /// public byte thingId; + /// + /// Create a message for sending + /// + /// The network ID of the thing + /// The ID of the thing + public DestroyMsg(byte networkId, byte thingId) { + this.networkId = networkId; + this.thingId = thingId; + } + /// @copydoc Passer::RoboidControl::IMessage::IMessage(byte[] buffer) public DestroyMsg(byte[] buffer) : base(buffer) { } - public override void Deserialize(byte[] buffer) { - this.networkId = buffer[0]; - this.thingId = buffer[1]; + /// @copydoc Passer::RoboidControl::IMessage::Serialize + public override byte Serialize(ref byte[] buffer) { + if (buffer.Length < DestroyMsg.length) + return 0; + + byte ix = 0; + buffer[ix++] = DestroyMsg.Id; + buffer[ix++] = this.networkId; + buffer[ix++] = this.thingId; + + return ix; } - public static async Task Receive(Stream dataStream, Participant client, byte packetSize) { - if (packetSize != length) - return false; - - byte[] buffer = await Receive(dataStream, packetSize); - DestroyMsg msg = new DestroyMsg(buffer); - - client.messageQueue.Enqueue(msg); - return true; - } } } \ No newline at end of file diff --git a/Messages/InvestigateMsg.cs b/Messages/InvestigateMsg.cs index 3f55640..43a6d60 100644 --- a/Messages/InvestigateMsg.cs +++ b/Messages/InvestigateMsg.cs @@ -3,18 +3,40 @@ using System.Threading.Tasks; namespace Passer.RoboidControl { + /// + /// Message to request details for a Thing + /// public class InvestigateMsg : IMessage { + /// + /// The message Id + /// public const byte Id = 0x81; + /// + /// The length of the message + /// public const byte length = 3; + /// + /// The network ID of the thing + /// public byte networkId; + /// + /// The ID of the thing + /// public byte thingId; + /// + /// Create a new message for sending + /// + /// The network ID for the thing + /// The ID of the thing public InvestigateMsg(byte networkId, byte thingId) { this.networkId = networkId; this.thingId = thingId; } + /// @copydoc Passer::RoboidControl::IMessage::IMessage(byte[] buffer) public InvestigateMsg(byte[] buffer) : base(buffer) { } + /// @copydoc Passer::RoboidControl::IMessage::Serialize public override byte Serialize(ref byte[] buffer) { byte ix = 0; buffer[ix++] = InvestigateMsg.Id; @@ -22,28 +44,28 @@ namespace Passer.RoboidControl { buffer[ix++] = this.thingId; return ix; } - public override void Deserialize(byte[] buffer) { - uint ix = 0; - this.networkId = buffer[ix++]; - this.thingId = buffer[ix++]; - } + // public override void Deserialize(byte[] buffer) { + // uint ix = 0; + // this.networkId = buffer[ix++]; + // this.thingId = buffer[ix++]; + // } //public static bool Send(Participant client, CoreThing thing) { // InvestigateMsg msg = new(thing.networkId, thing.id); // return SendMsg(client, msg); //} - public static async Task Receive(Stream dataStream, Participant client, byte packetSize) { - if (packetSize != length) - return false; + // public static async Task Receive(Stream dataStream, Participant client, byte packetSize) { + // if (packetSize != length) + // return false; - byte[] buffer = await Receive(dataStream, packetSize); - InvestigateMsg msg = new InvestigateMsg(buffer); - //UnityEngine.Debug.Log($"Receive investigate [{msg.networkId}/{msg.thingId}]"); + // byte[] buffer = await Receive(dataStream, packetSize); + // InvestigateMsg msg = new InvestigateMsg(buffer); + // //UnityEngine.Debug.Log($"Receive investigate [{msg.networkId}/{msg.thingId}]"); - client.messageQueue.Enqueue(msg); - return true; + // client.messageQueue.Enqueue(msg); + // return true; - } + // } } } \ No newline at end of file diff --git a/Messages/Messages.cs b/Messages/Messages.cs index 1e6e6ca..078c8b2 100644 --- a/Messages/Messages.cs +++ b/Messages/Messages.cs @@ -3,40 +3,54 @@ using System.IO; namespace Passer.RoboidControl { + /// + /// Root structure for all communcation messages + /// public class IMessage { public IMessage() { } + + /// + /// Create a message for receiving + /// + /// The byte array to parse public IMessage(byte[] buffer) { - Deserialize(buffer); + //Deserialize(buffer); } + /// + /// Serialize the message into a byte array for sending + /// + /// The buffer to serilize into + /// The length of the message in the buffer public virtual byte Serialize(ref byte[] buffer) { return 0; } - public virtual void Deserialize(byte[] buffer) { } - public bool SendTo(Participant client) { - Serialize(ref client.buffer); - return client.SendBuffer(client.buffer.Length); - } + //public virtual void Deserialize(byte[] buffer) { } - public static bool SendMsg(Participant client, IMessage msg) { - msg.Serialize(ref client.buffer); - return client.SendBuffer(client.buffer.Length); - } + // public bool SendTo(Participant client) { + // Serialize(ref client.buffer); + // return client.SendBuffer(client.buffer.Length); + // } - public static bool PublishMsg(Participant client, IMessage msg) { - msg.Serialize(ref client.buffer); - return client.PublishBuffer(client.buffer.Length); - } + // public static bool SendMsg(Participant client, IMessage msg) { + // msg.Serialize(ref client.buffer); + // return client.SendBuffer(client.buffer.Length); + // } - public static async Task Receive(Stream dataStream, byte packetSize) { - byte[] buffer = new byte[packetSize - 1]; // without msgId - int byteCount = dataStream.Read(buffer, 0, packetSize - 1); - while (byteCount < packetSize - 1) { - // not all bytes have been read, wait and try again - await Task.Delay(1); - byteCount += dataStream.Read(buffer, byteCount, packetSize - 1 - byteCount); - } - return buffer; - } + // public static bool PublishMsg(Participant client, IMessage msg) { + // msg.Serialize(ref client.buffer); + // return client.PublishBuffer(client.buffer.Length); + // } + + // public static async Task Receive(Stream dataStream, byte packetSize) { + // byte[] buffer = new byte[packetSize - 1]; // without msgId + // int byteCount = dataStream.Read(buffer, 0, packetSize - 1); + // while (byteCount < packetSize - 1) { + // // not all bytes have been read, wait and try again + // await Task.Delay(1); + // byteCount += dataStream.Read(buffer, byteCount, packetSize - 1 - byteCount); + // } + // return buffer; + // } } } diff --git a/Messages/NameMsg.cs b/Messages/NameMsg.cs index 8bddcbe..6193c37 100644 --- a/Messages/NameMsg.cs +++ b/Messages/NameMsg.cs @@ -1,23 +1,56 @@ namespace Passer.RoboidControl { + /// + /// Message for communicating the name of a thing + /// public class NameMsg : IMessage { + /// + /// The message ID + /// public const byte Id = 0x91; // 145 + /// + /// The length of the message + /// public const byte length = 4; + /// + /// The network ID of the thing + /// public byte networkId; + /// + /// The ID of the thing + /// public byte thingId; + /// + /// The length of the name, excluding null terminator + /// public byte len; + /// + /// The name of the thing, not terminated with a null character + /// public string name = ""; + /// + /// Create a new message for sending + /// + /// The network ID of the thing + /// The thing public NameMsg(byte networkId, Thing thing) { this.networkId = networkId; this.thingId = thing.id; this.name = thing.name; } + /// + /// Create a new message for sending + /// + /// The network ID of the thing + /// The ID of the thing + /// The name of the thing public NameMsg(byte networkId, byte thingId, string name) { this.networkId = networkId; this.thingId = thingId; this.name = name; } + /// @copydoc Passer::RoboidControl::IMessage::IMessage(byte[] buffer) public NameMsg(byte[] buffer) { byte ix = 1; this.networkId = buffer[ix++]; @@ -26,8 +59,9 @@ namespace Passer.RoboidControl { this.name = System.Text.Encoding.UTF8.GetString(buffer, (int)ix, strlen); } + /// @copydoc Passer::RoboidControl::IMessage::Serialize public override byte Serialize(ref byte[] buffer) { - if (this.name.Length == 0) + if (buffer.Length < NameMsg.length + this.name.Length || this.name.Length == 0) return 0; byte ix = 0; @@ -40,6 +74,7 @@ namespace Passer.RoboidControl { buffer[ix++] = (byte)nameLength; for (int nameIx = 0; nameIx < nameLength; nameIx++) buffer[ix++] = (byte)this.name[nameIx]; + return ix; } } diff --git a/Messages/NetworkIdMsg.cs b/Messages/NetworkIdMsg.cs index c1cf080..fc095d0 100644 --- a/Messages/NetworkIdMsg.cs +++ b/Messages/NetworkIdMsg.cs @@ -1,18 +1,39 @@ namespace Passer.RoboidControl { + /// + /// A message communicating the network ID for that participant + /// public class NetworkIdMsg : IMessage { + /// + /// The message ID + /// public const byte Id = 0xA1; + /// + /// The length of the message + /// public const byte length = 2; + /// + /// The network ID for the participant + /// public byte networkId; + /// + /// Create a new message for sending + /// + /// The network ID for the participant public NetworkIdMsg(byte networkId) { this.networkId = networkId; } + /// @copydoc Passer::RoboidControl::IMessage::IMessage(byte[] buffer) public NetworkIdMsg(byte[] buffer) { this.networkId = buffer[1]; } + /// @copydoc Passer::RoboidControl::IMessage::Serialize public override byte Serialize(ref byte[] buffer) { + if (buffer.Length < NetworkIdMsg.length) + return 0; + buffer[0] = NetworkIdMsg.Id; buffer[1] = this.networkId; return NetworkIdMsg.length; diff --git a/Messages/PoseMsg.cs b/Messages/PoseMsg.cs index 3a9ee8f..e31953e 100644 --- a/Messages/PoseMsg.cs +++ b/Messages/PoseMsg.cs @@ -4,23 +4,73 @@ using Passer.LinearAlgebra; namespace Passer.RoboidControl { + /// + /// Message to communicate the pose of the thing + /// + /// The pose is in local space relative to the parent. If there is not parent (the thing is a root thing), the pose will be in world space. public class PoseMsg : IMessage { + /// + /// The message ID + /// public const byte Id = 0x10; + /// + /// The length of the message + /// public const byte length = 4 + 4 + 4; + /// + /// The network ID of the thing + /// public byte networkId; + /// + /// The ID of the thing + /// public byte thingId; + /// + /// bitpattern stating which pose components are available + /// public byte poseType; + /// + /// Bit pattern for a pose with position + /// public const byte Pose_Position = 0x01; + /// + /// Bit pattern for a pose with orientation + /// public const byte Pose_Orientation = 0x02; + /// + /// Bit pattern for a pose with linear velocity + /// public const byte Pose_LinearVelocity = 0x04; + /// + /// Bit pattern for a pose with angular velocity + /// public const byte Pose_AngularVelocity = 0x08; + /// + /// The position of the thing in local space in meters + /// public Spherical position = Spherical.zero; + /// + /// The orientation of the thing in local space + /// public SwingTwist orientation = SwingTwist.zero; + /// + /// The linear velocity of the thing in local space in meters per second + /// public Spherical linearVelocity = Spherical.zero; + /// + /// The angular veloicty of the thing in local space + /// public Spherical angularVelocity = Spherical.zero; + /// + /// Create a new message for sending + /// + /// The network ID of the thing + /// The ID of the thing + /// The position of the thing in local space in meters + /// The orientation of the thing in local space public PoseMsg(byte networkId, byte thingId, Spherical position, SwingTwist orientation) { this.networkId = networkId; this.thingId = thingId; @@ -34,8 +84,10 @@ namespace Passer.RoboidControl { if (this.orientation != null) this.poseType |= Pose_Orientation; } + /// @copydoc Passer::RoboidControl::IMessage::IMessage(byte[] buffer) public PoseMsg(byte[] buffer) : base(buffer) { } + /// @copydoc Passer::RoboidControl::IMessage::Serialize public override byte Serialize(ref byte[] buffer) { byte ix = 0; buffer[ix++] = PoseMsg.Id; @@ -53,59 +105,59 @@ namespace Passer.RoboidControl { LowLevelMessages.SendSpherical(buffer, ref ix, this.angularVelocity); return ix; } - public override void Deserialize(byte[] buffer) { - byte ix = 0; - this.networkId = buffer[ix++]; - this.thingId = buffer[ix++]; - this.poseType = buffer[ix++]; + // public override void Deserialize(byte[] buffer) { + // byte ix = 0; + // this.networkId = buffer[ix++]; + // this.thingId = buffer[ix++]; + // this.poseType = buffer[ix++]; - if ((poseType & Pose_Position) != 0) - this.position = LowLevelMessages.ReceiveSpherical(buffer, ref ix); - if ((poseType & Pose_Orientation) != 0) - this.orientation = LowLevelMessages.ReceiveSwingTwist(buffer, ref ix); - if ((poseType & Pose_LinearVelocity) != 0) - this.linearVelocity = LowLevelMessages.ReceiveSpherical(buffer, ref ix); - if ((poseType & Pose_AngularVelocity) != 0) - this.angularVelocity = LowLevelMessages.ReceiveSpherical(buffer, ref ix); - } + // if ((poseType & Pose_Position) != 0) + // this.position = LowLevelMessages.ReceiveSpherical(buffer, ref ix); + // if ((poseType & Pose_Orientation) != 0) + // this.orientation = LowLevelMessages.ReceiveSwingTwist(buffer, ref ix); + // if ((poseType & Pose_LinearVelocity) != 0) + // this.linearVelocity = LowLevelMessages.ReceiveSpherical(buffer, ref ix); + // if ((poseType & Pose_AngularVelocity) != 0) + // this.angularVelocity = LowLevelMessages.ReceiveSpherical(buffer, ref ix); + // } - public static bool Send(Participant client, byte thingId, Spherical position, SwingTwist orientation) { - PoseMsg msg = new PoseMsg(client.networkId, thingId, position, orientation); - return SendMsg(client, msg); - } - public static async Task Receive(Stream dataStream, Participant client, byte packetSize) { - byte[] buffer = await Receive(dataStream, packetSize); - PoseMsg msg = new PoseMsg(buffer); + // public static bool Send(Participant client, byte thingId, Spherical position, SwingTwist orientation) { + // PoseMsg msg = new PoseMsg(client.networkId, thingId, position, orientation); + // return SendMsg(client, msg); + // } + // public static async Task Receive(Stream dataStream, Participant client, byte packetSize) { + // byte[] buffer = await Receive(dataStream, packetSize); + // PoseMsg msg = new PoseMsg(buffer); - // Do no process poses with nwid == 0 (== local) - if (msg.networkId == 0) - return true; + // // Do no process poses with nwid == 0 (== local) + // if (msg.networkId == 0) + // return true; - client.messageQueue.Enqueue(msg); - return true; - } + // client.messageQueue.Enqueue(msg); + // return true; + // } - public static bool SendTo(Participant participant, Thing thing) { - if (participant == null || thing == null) - return false; + // public static bool SendTo(Participant participant, Thing thing) { + // if (participant == null || thing == null) + // return false; - byte ix = 0; - participant.buffer[ix++] = PoseMsg.Id; - participant.buffer[ix++] = participant.networkId; - participant.buffer[ix++] = thing.id; - participant.buffer[ix++] = thing.poseUpdated; + // byte ix = 0; + // participant.buffer[ix++] = PoseMsg.Id; + // participant.buffer[ix++] = participant.networkId; + // participant.buffer[ix++] = thing.id; + // participant.buffer[ix++] = thing.poseUpdated; - if ((thing.poseUpdated & Pose_Position) != 0 && thing.position != null) - LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.position); - if ((thing.poseUpdated & Pose_Orientation) != 0 && thing.orientation != null) - LowLevelMessages.SendQuat32(participant.buffer, ref ix, thing.orientation); - if ((thing.poseUpdated & Pose_LinearVelocity) != 0 && thing.linearVelocity != null) - LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.linearVelocity); - if ((thing.poseUpdated & Pose_AngularVelocity) != 0 && thing.angularVelocity != null) - LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.angularVelocity); + // if ((thing.poseUpdated & Pose_Position) != 0 && thing.position != null) + // LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.position); + // if ((thing.poseUpdated & Pose_Orientation) != 0 && thing.orientation != null) + // LowLevelMessages.SendQuat32(participant.buffer, ref ix, thing.orientation); + // if ((thing.poseUpdated & Pose_LinearVelocity) != 0 && thing.linearVelocity != null) + // LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.linearVelocity); + // if ((thing.poseUpdated & Pose_AngularVelocity) != 0 && thing.angularVelocity != null) + // LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.angularVelocity); - return participant.SendBuffer(ix); - } + // return participant.SendBuffer(ix); + // } } } \ No newline at end of file diff --git a/Messages/TextMsg.cs b/Messages/TextMsg.cs index abad8f3..7d353e6 100644 --- a/Messages/TextMsg.cs +++ b/Messages/TextMsg.cs @@ -3,24 +3,59 @@ using System.Threading.Tasks; namespace Passer.RoboidControl { + /// + /// Message for sending generic text. + /// public class TextMsg : IMessage { - public TextMsg(byte[] buffer) : base(buffer) {} + /// + /// The message ID + /// public const byte Id = 0xB0; + /// + /// The length of the message without the text itself + /// + public const byte length = 2; + /// + /// The text + /// public string text = ""; - public override void Deserialize(byte[] buffer) { - uint ix = 0; - uint strlen = buffer[ix++]; - this.text = System.Text.Encoding.UTF8.GetString(buffer, (int)ix, (int)strlen); + /// + /// Create a new message for sending + /// + /// The text to send + public TextMsg(string text) { + this.text = text; } - public static async Task Receive(Stream dataStream, Participant client, byte packetSize) { - byte[] buffer = await Receive(dataStream, packetSize); - TextMsg msg = new TextMsg(buffer); + /// @copydoc Passer::RoboidControl::IMessage::IMessage(byte[] buffer) + public TextMsg(byte[] buffer) : base(buffer) { } - client.messageQueue.Enqueue(msg); - return true; + /// @copydoc Passer::RoboidControl::IMessage::Serialize + public override byte Serialize(ref byte[] buffer) { + if (buffer.Length < TextMsg.length + this.text.Length || this.text.Length == 0) + return 0; + + byte ix = 0; + buffer[ix++] = TextMsg.Id; + buffer[ix++] = (byte)this.text.Length; + for (int textIx = 0; textIx < this.text.Length; textIx++) + buffer[ix++] = (byte)this.text[textIx]; + return ix; } + // public override void Deserialize(byte[] buffer) { + // uint ix = 0; + // uint strlen = buffer[ix++]; + // this.text = System.Text.Encoding.UTF8.GetString(buffer, (int)ix, (int)strlen); + // } + + // public static async Task Receive(Stream dataStream, Participant client, byte packetSize) { + // byte[] buffer = await Receive(dataStream, packetSize); + // TextMsg msg = new TextMsg(buffer); + + // client.messageQueue.Enqueue(msg); + // return true; + // } } } \ No newline at end of file diff --git a/ModelUrlMsg.cs.meta b/ModelUrlMsg.cs.meta deleted file mode 100644 index 7f9b6b8..0000000 --- a/ModelUrlMsg.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 711bdb0248c9f6848a6b4da15cc05db5 \ No newline at end of file diff --git a/Participant.cs b/Participant.cs index a9bce80..bebc1f3 100644 --- a/Participant.cs +++ b/Participant.cs @@ -318,7 +318,9 @@ namespace Passer.RoboidControl { if (client == this) continue; //UnityEngine.Debug.Log($"---> {client.ipAddress}"); - IMessage.SendMsg(client, msg); + //IMessage.SendMsg(client, msg); + msg.Serialize(ref client.buffer); + client.SendBuffer(client.buffer.Length); } } diff --git a/README.md b/README.md index 338a37c..a094cee 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ -\mainpage Control Core for C# +\mainpage Roboid Control for C# -Control Core contains generic functionality for Controlling Things. \ No newline at end of file +Roboid Control support for C# applications. +Includes support for the Unity game engine. + +# Basic components + +- Passer::RoboidControl::Thing +- Passer::RoboidControl::Participant +- Passer::RoboidControl::SiteServer \ No newline at end of file diff --git a/RemoteParticipant.cs b/RemoteParticipant.cs index 44c15f4..3f2bc02 100644 --- a/RemoteParticipant.cs +++ b/RemoteParticipant.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; diff --git a/Sensors.meta b/Sensors.meta deleted file mode 100644 index 6c54616..0000000 --- a/Sensors.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a5a7a42365df0d0459195576ad3bb50b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Sensors/DistanceSensor.cs b/Sensors/DistanceSensor.cs index ed2b369..2c1db64 100644 --- a/Sensors/DistanceSensor.cs +++ b/Sensors/DistanceSensor.cs @@ -1,22 +1,39 @@ -using System; - -namespace Passer.RoboidControl.Core { +namespace Passer.RoboidControl { + /// + /// A sensor measuring the distance in the forward direction + /// public class DistanceSensor : Thing { + /// + /// The current measured distance + /// public float distance = 0; + /// + /// Constructor for a new distance sensor + /// + /// The participant for which the sensor is needed public DistanceSensor(RemoteParticipant 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) { } #if UNITY_5_3_OR_NEWER + /// @copydoc Passer::RoboidControl::Thing::CreateComponent public override void CreateComponent() { this.component = Unity.DistanceSensor.Create(this.parent); this.component.core = this; } #endif - + /// + /// Function to extract the distance received in the binary message + /// + /// The byte array public override void ProcessBinary(byte[] bytes) { byte ix = 0; this.distance = LowLevelMessages.ReceiveFloat16(bytes, ref ix); diff --git a/Sensors/TemperatureSensor.cs b/Sensors/TemperatureSensor.cs index 09a311d..edb9750 100644 --- a/Sensors/TemperatureSensor.cs +++ b/Sensors/TemperatureSensor.cs @@ -1,16 +1,32 @@ -using System; +//using System; -namespace Passer.RoboidControl.Core { +namespace Passer.RoboidControl { + /// + /// A temperature sensor + /// public class TemperatureSensor : Thing { - public float temp = 0; + /// + /// The measured temperature + /// + public float temperature = 0; + /// + /// Create a temperature 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 TemperatureSensor(Participant participant, byte networkId, byte thingId) : base(participant, networkId, thingId, (byte)Type.TemperatureSensor) {} + /// + /// Function to extract the temperature received in the binary message + /// + /// The byte array public override void ProcessBinary(byte[] bytes) { byte ix = 0; - this.temp = LowLevelMessages.ReceiveFloat16(bytes, ref ix); - Console.WriteLine($"temperature {this.name} = {this.temp} C"); + this.temperature = LowLevelMessages.ReceiveFloat16(bytes, ref ix); + //Console.WriteLine($"temperature {this.name} = {this.temperature} C"); } } diff --git a/Sensors/TemperatureSensor.cs.meta b/Sensors/TemperatureSensor.cs.meta deleted file mode 100644 index 69b6d6a..0000000 --- a/Sensors/TemperatureSensor.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 5cd9e2534695ec844bd23b7a48ad498a \ No newline at end of file diff --git a/Sensors/TouchSensor.cs b/Sensors/TouchSensor.cs index c05b59b..72d0350 100644 --- a/Sensors/TouchSensor.cs +++ b/Sensors/TouchSensor.cs @@ -1,12 +1,25 @@ namespace Passer.RoboidControl { + + /// + /// A sensor which can detect touches + /// public class TouchSensor : Thing { + /// + /// Value which is true when the sensor is touching something, false otherwise + /// public bool touchedSomething = false; + /// + /// Create a touch sensor + /// + /// The participant for with the sensor is needed + /// True when the creation should trigger an event public TouchSensor(RemoteParticipant participant, bool invokeEvent = true) : base(participant, invokeEvent) { touchedSomething = false; } #if UNITY_5_3_OR_NEWER + /// @copydoc Passer::RoboidControl::Thing::CreateComponent public override void CreateComponent() { this.component = Unity.TouchSensor.Create(this); this.component.core = this; diff --git a/Thing.cs b/Thing.cs index e1712da..6e40df1 100644 --- a/Thing.cs +++ b/Thing.cs @@ -31,21 +31,41 @@ namespace Passer.RoboidControl { Humanoid, ExternalSensor }; + /// + /// The type of this thing. This can be either a Thing::Type (needs casting) + /// or a byte value for custom types. + /// + public byte type; #endregion Types #region Properties + /// + /// The participant to which this thing belongs + /// public RemoteParticipant participant; public delegate void ChangeHandler(); public delegate void SphericalHandler(Spherical v); + /// + /// The network ID of this thing. + /// public byte networkId; + /// + /// The ID of this thing + /// public byte id; - public event ChangeHandler OnParentChanged = delegate {}; + /// + /// Event which is triggered when the parent changes + /// + public event ChangeHandler OnParentChanged = delegate { }; private Thing _parent; + /// + /// The parent of this thing + /// public Thing parent { get => _parent; set { @@ -63,22 +83,38 @@ namespace Passer.RoboidControl { } } + /// + /// Attach a thing as a child of this thing + /// + /// The thing to attach as a child public void AddChild(Thing child) { if (children.Find(thing => thing == child) != null) return; child._parent = this; children.Add(child); } + /// + /// Remove the given thing as a child of this thing + /// + /// public void RemoveChild(Thing child) { children.Remove(child); } - [System.NonSerialized] + /// + /// The list of children of this thing + /// + [NonSerialized] public List children = new List(); - public byte type; - public event ChangeHandler OnNameChanged = delegate {}; + /// + /// Event which is triggered when the name changes + /// + public event ChangeHandler OnNameChanged = delegate { }; private string _name = ""; + /// + /// The name of the thing + /// public virtual string name { get => _name; set { @@ -89,11 +125,19 @@ namespace Passer.RoboidControl { } } + /// + /// An URL pointing to the location where a model of the thing can be found + /// public string modelUrl = ""; - public byte poseUpdated = 0x00; - public event ChangeHandler OnPositionChanged = delegate {}; + /// + /// Event triggered when the position has changed + /// + public event ChangeHandler OnPositionChanged = delegate { }; private Spherical _position = Spherical.zero; + /// + /// The position of the thing in local space, in meters. + /// public Spherical position { get { return _position; } set { @@ -104,8 +148,14 @@ namespace Passer.RoboidControl { } } - public event ChangeHandler OnOrientationChanged = delegate {}; + /// + /// Event triggered when the orientation has changed + /// + public event ChangeHandler OnOrientationChanged = delegate { }; private SwingTwist _orientation = SwingTwist.zero; + /// + /// The orientation of the thing in local space + /// public SwingTwist orientation { get { return _orientation; } set { @@ -116,8 +166,14 @@ namespace Passer.RoboidControl { } } - public event SphericalHandler OnLinearVelocityChanged = delegate {}; + /// + /// Event triggered when the linear velocity has changed + /// + public event SphericalHandler OnLinearVelocityChanged = delegate { }; private Spherical _linearVelocity = Spherical.zero; + /// + /// The linear velocity of the thing in local space in meters per second + /// public Spherical linearVelocity { get => _linearVelocity; set { @@ -127,9 +183,15 @@ namespace Passer.RoboidControl { } } } + /// + /// The angular velocity of the thing in local space + /// public Spherical angularVelocity = Spherical.zero; #if UNITY_5_3_OR_NEWER + /// + /// A reference to the representation of the thing in Unity + /// [NonSerialized] public Unity.Thing component = null; #endif @@ -138,67 +200,92 @@ namespace Passer.RoboidControl { #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 participant, bool invokeEvent = false) { this.participant = participant; if (invokeEvent) InvokeNewThing(this); } - public Thing(RemoteParticipant sender, byte networkId, byte thingId, byte thingType = 0) { - this.participant = sender; + /// + /// 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.participant = participant; this.id = thingId; this.type = thingType; this.networkId = networkId; } - public virtual void CreateComponent() {} + /// + /// Function which can be used to create components in external engines. + /// + /// Currently this is used to create GameObjects in Unity + public virtual void CreateComponent() { } #endregion Init #region Update #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); } #endif + /// + /// Update this thing + /// + /// The current time in milliseconds public virtual void Update(ulong currentTime) { // should recurse over children... } + /// + /// Function used to generate binary data for this thing + /// + /// a byte array with the binary data + /// @sa Passer::RoboidControl::BinaryMsg public virtual byte[] GenerateBinary() { return new byte[0]; } + /// + /// Function used to process binary data received for this thing + /// + /// The binary data public virtual void ProcessBinary(byte[] bytes) { - //if (sensor != null) - // sensor.ProcessBytes(bytes); } #endregion Update - // Experimental - - // public float stressLevel = 0; - - // protected delegate void ReceptorFunc(Sensor sensor); - // protected void SetupReceptor(Sensor sensor, ReceptorFunc receptor) { - // sensor.Signaller += (sensor => Receptor(receptor, sensor)); - // } - // protected void Receptor(ReceptorFunc receptor, Sensor sensor) { - // if (sensor.signalStrength <= stressLevel) - // return; - - // receptor(sensor); - // } - - //---------- All Things - - // private static readonly List allThings = new(); - public delegate void ThingHandler(Thing t); - public static event ThingHandler OnNewThing = delegate {}; + /// + /// Event triggered when a new thing has been created + /// + public static event ThingHandler OnNewThing = delegate { }; + /// + /// Trigger the creation for the given thing + /// + /// The created thing public static void InvokeNewThing(Thing thing) { - OnNewThing?.Invoke(thing); + OnNewThing?.Invoke(thing); } + /// + /// Check if the thing has the given properaties + /// + /// The thing to check + /// The network ID to compare to + /// The thing ID to compare to + /// True when the thing has the given properties public static bool IsThing(Thing thing, byte networkId, byte thingId) { if (thing == null) return false; diff --git a/test.sln.meta b/test.sln.meta deleted file mode 100644 index 606fb16..0000000 --- a/test.sln.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: d5d87461365fd8a4da528aa84a49e62c -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/test/UnitTest1.cs.meta b/test/UnitTest1.cs.meta deleted file mode 100644 index 8ee19d8..0000000 --- a/test/UnitTest1.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 743b128a79ef8414fa29d7bb3b9e2ac8 \ No newline at end of file diff --git a/test/test.csproj.meta b/test/test.csproj.meta deleted file mode 100644 index 1040180..0000000 --- a/test/test.csproj.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 92729868a8379c04197dcb80d0276a63 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: