diff --git a/Examples/BB2B/BB2B.cs b/Examples/BB2B/BB2B.cs
index 2a398ca..3036333 100644
--- a/Examples/BB2B/BB2B.cs
+++ b/Examples/BB2B/BB2B.cs
@@ -25,7 +25,7 @@ namespace RoboidControl {
};
}
- public override void Update(ulong currentTimeMs, bool recurse = true) {
+ public override void Update(bool recurse = true) {
// The left wheel turns forward when nothing is touched on the right side
// and turn backward when the roboid hits something on the right
@@ -40,7 +40,7 @@ namespace RoboidControl {
this.SetWheelVelocity(leftWheelSpeed, rightWheelSpeed);
- base.Update(currentTimeMs, recurse);
+ base.Update(recurse);
}
}
diff --git a/Examples/BB2B/BB2B_Encoder.cs b/Examples/BB2B/BB2B_Encoder.cs
index 21787c6..7870126 100644
--- a/Examples/BB2B/BB2B_Encoder.cs
+++ b/Examples/BB2B/BB2B_Encoder.cs
@@ -33,7 +33,7 @@ namespace RoboidControl {
};
}
- public override void Update(ulong currentTimeMs, bool recurse = true) {
+ public override void Update(bool recurse = true) {
// The left wheel turns forward when nothing is touched on the right side
// and turn backward when the roboid hits something on the right
@@ -48,7 +48,7 @@ namespace RoboidControl {
this.SetWheelAngularVelocity(leftWheelVelocity, rightWheelVelocity);
- base.Update(currentTimeMs, recurse);
+ base.Update(recurse);
}
}
diff --git a/src/Participant.cs b/src/Participant.cs
index 066cb44..43b42d9 100644
--- a/src/Participant.cs
+++ b/src/Participant.cs
@@ -15,10 +15,13 @@ namespace RoboidControl {
/// It is used as a basis for the local participant, but also as a reference to remote participants.
public class Participant {
+ #region Init
+
+ ///
+ /// Create a generic participant
+ ///
private Participant() {
- this.root = Thing.CreateRoot(this);
- this.root.name = "Root";
- this.Add(this.root);
+ Thing.CreateRoot(this);
}
///
@@ -26,47 +29,60 @@ namespace RoboidControl {
///
/// The IP address of the participant
/// The UDP port of the participant
+ /// This does not belong here, it should move to ParticipantUDP or something like that in the future
public Participant(string ipAddress, int port, Participant localParticipant = null) {
this.ipAddress = ipAddress;
this.port = port;
- this.root = Thing.CreateRoot(this);
- this.root.name = "Root";
+ Thing.CreateRoot(this);
if (localParticipant != null)
this.udpClient = localParticipant.udpClient;
}
+ ///
+ /// The local participant for this application
+ ///
public static Participant localParticipant = new();
- public static void ReplaceLocalParticipant(Participant participant) {
- Participant.localParticipant = participant;
+ ///
+ /// Replace the local participant
+ ///
+ /// The new local participant
+ public static void ReplaceLocalParticipant(Participant newParticipant) {
+ Participant.localParticipant = newParticipant;
}
- public Thing root = null;
+ #endregion Init
+
+ #region Properties
+
///
/// The Ip Address of a participant. When the participant is local, this contains 0.0.0.0
///
+ /// This does not belong here, it should move to ParticipantUDP or something like that in the future
public string ipAddress = "0.0.0.0";
///
/// The port number for UDP communication with the participant. This is 0 for isolated participants.
///
+ /// This does not belong here, it should move to ParticipantUDP or something like that in the future
public int port = 0;
-#if UNITY_5_3_OR_NEWER
///
- /// A reference to the representation of the thing in Unity
+ /// The udpClient for this participant
///
- [NonSerialized]
- public Unity.Participant component = null;
-#endif
-
+ /// This does not belong here, it should move to ParticipantUDP or something like that in the future
public UdpClient udpClient = null;
///
- /// he network Id to identify the participant
+ /// The network Id to identify the participant
///
public byte networkId = 0;
+ ///
+ /// The root thing for this participant
+ ///
+ public Thing root = null;
+
///
/// The things managed by this participant
///
@@ -110,26 +126,47 @@ namespace RoboidControl {
this.things.Remove(thing);
}
+#if UNITY_5_3_OR_NEWER
+ ///
+ /// A reference to the representation of the thing in Unity
+ ///
+ [NonSerialized]
+ public Unity.Participant component = null;
+#endif
+
+ #endregion properties
+
#region Update
///
/// Update all things for this participant
///
- /// The current time in milliseconds (optional)
- public virtual void Update(ulong currentTimeMS = 0) {
+ public virtual void Update() {
int n = this.things.Count;
for (int ix = 0; ix < n; ix++) {
Thing thing = this.things[ix];
if (thing != null)
- thing.Update(currentTimeMS, true);
+ thing.Update(true);
}
}
+ ///
+ /// Event for a participant
+ ///
public class UpdateEvent {
+ ///
+ /// The type of event happened.
+ ///
+ /// This value is filled with the Ids of the communication messages.
public int messageId; // see the communication messages
+ ///
+ /// The thing relevant fo the event
+ ///
public Thing thing;
- public Participant participant;
}
+ ///
+ /// Queue containing events happened to this participant
+ ///
public ConcurrentQueue updateQueue = new();
#endregion Update
@@ -155,6 +192,8 @@ namespace RoboidControl {
#endregion Send
+ #region Participant Registry
+
///
/// The collection of known participants.
///
@@ -213,6 +252,7 @@ namespace RoboidControl {
Participant.participants.Add(participant);
}
+ #endregion Participant Registery
}
}
\ No newline at end of file
diff --git a/src/Participants/ParticipantUDP.cs b/src/Participants/ParticipantUDP.cs
index d54a607..4e3de23 100644
--- a/src/Participants/ParticipantUDP.cs
+++ b/src/Participants/ParticipantUDP.cs
@@ -150,9 +150,8 @@ namespace RoboidControl {
protected ulong nextPublishMe = 0;
protected ulong nextSendUpdate = 0;
- public override void Update(ulong currentTimeMS = 0) {
- if (currentTimeMS == 0)
- currentTimeMS = Thing.GetTimeMs();
+ public override void Update() {
+ ulong currentTimeMS = Thing.GetTimeMs();
if (this.isIsolated == false) {
if (this.publishIntervalMS > 0 && currentTimeMS > this.nextPublishMe) {
@@ -185,7 +184,7 @@ namespace RoboidControl {
// Because when a thing creates a thing in the update,
// that new thing is not sent out (because of hierarchyChanged)
// before it is updated itself: it is immediatedly updated!
- thing.Update(currentTimeMS, false);
+ thing.Update(false);
if (!(this.isIsolated || this.networkId == 0)) {
if (thing.terminate) {
DestroyMsg destroyMsg = new(this.networkId, thing);
@@ -213,7 +212,7 @@ namespace RoboidControl {
if (participant == null || participant == this)
continue;
- participant.Update(currentTimeMS);
+ participant.Update();
if (this.isIsolated)
continue;
diff --git a/src/Participants/SiteServer.cs b/src/Participants/SiteServer.cs
index 682d3eb..3cbea8c 100644
--- a/src/Participants/SiteServer.cs
+++ b/src/Participants/SiteServer.cs
@@ -72,7 +72,7 @@ namespace RoboidControl {
if (thing == null)
continue;
- thing.Update(currentTimeMS, false);
+ thing.Update(false);
if (this.isIsolated == false) {
// Send to all other participants
@@ -104,8 +104,7 @@ namespace RoboidControl {
// this.Send(sender, new NetworkIdMsg(sender.networkId));
sender.Send(new NetworkIdMsg(sender.networkId));
UpdateEvent e = new() {
- messageId = ParticipantMsg.Id,
- participant = sender
+ messageId = ParticipantMsg.Id
};
this.updateQueue.Enqueue(e);
}
diff --git a/src/Thing.cs b/src/Thing.cs
index 0aea683..a9a3ef0 100644
--- a/src/Thing.cs
+++ b/src/Thing.cs
@@ -38,73 +38,14 @@ namespace RoboidControl {
#region Init
- private Thing(Participant owner) {
- this.type = Type.Root;
-
- this.positionUpdated = true;
- this.orientationUpdated = true;
- this.hierarchyChanged = true;
-
- this.owner = owner;
- this.parent = null;
- }
-
- public static Thing CreateRoot(Participant owner) {
- return new Thing(owner);
- }
-
- static Thing localRoot {
- get {
- Participant participant = Participant.localParticipant;
- return participant.root;
- }
- }
-
- /*
///
- /// Create a new thing without communication abilities
+ /// Create a new Thing
///
- /// The type of thing (can use \ref RoboidControl::Thing::Type "Thing.Type")
- /// Invoke a OnNewThing event when the thing has been created
- public Thing(byte thingType = Type.Undetermined, bool invokeEvent = true) : this(ParticipantUDP.Isolated(), thingType, 0, invokeEvent) {
- }
-
- ///
- /// Create a new thing for a participant
- ///
- /// The owning participant
- /// The type of thing (can use \ref RoboidControl::Thing::Type "Thing.Type")
- /// The ID of the thing, leave out or set to zero to generate an ID
- /// Invoke a OnNewThing event when the thing has been created
- public Thing(Participant owner, byte thingType = Type.Undetermined, byte thingId = 0, bool invokeEvent = true) {
- this.owner = owner;
- this.id = thingId;
- this.type = thingType;
- if (this.owner != null)
- this.owner.Add(this);
- if (invokeEvent) {
- Participant.UpdateEvent e = new() {
- messageId = ThingMsg.id,
- thing = this
- };
- this.owner.updateQueue.Enqueue(e);
- }
- }
- */
-
- ///
- /// Create a new child thing
- ///
- /// The parent thing
- /// The type of thing (can use \ref RoboidControl::Thing::Type "Thing.Type")
- /// The ID of the thing, leave out or set to zero to generate an ID
- /// Invoke a OnNewThing event when the thing has been created
- /// The owner will be the same as the owner of the parent thing
- /*
- public Thing(Thing parent, byte thingType = Type.Undetermined, byte thingId = 0, bool invokeEvent = true) : this(parent.owner, thingType, thingId, invokeEvent) {
- this.parent = parent;
- }
- */
+ /// (optional) The parent thing
+ /// The owner will be the same as the owner of the parent thing, it will
+ /// be Participant.LocalParticipant if the parent is not specified. A thing
+ /// without a parent will be connected to the root thing.
+ ///
public Thing(Thing parent = default) {
this.type = Type.Undetermined;
@@ -127,12 +68,41 @@ namespace RoboidControl {
this.owner.updateQueue.Enqueue(e);
}
- // public static Thing CreateRemote(Participant owner, byte thingId) {
- // Thing remoteThing = new(owner.root) {
- // id = thingId
- // };
- // return remoteThing;
- // }
+ ///
+ /// Constructor to create a root thing
+ ///
+ /// The participant who will own this root thing
+ /// This function is private because CreateRoot() should be used instead
+ private Thing(Participant owner) {
+ this.type = Type.Root;
+ this.name = "Root";
+
+ this.positionUpdated = true;
+ this.orientationUpdated = true;
+ this.hierarchyChanged = true;
+
+ this.owner = owner;
+ this.parent = null;
+ this.owner.Add(this);
+ }
+
+ ///
+ /// Create a root Thing for a participant
+ ///
+ /// The participant who will own this root thing
+ public static void CreateRoot(Participant owner) {
+ owner.root = new Thing(owner);
+ }
+
+ ///
+ /// The root thing for the local participant
+ ///
+ public static Thing localRoot {
+ get {
+ Participant participant = Participant.localParticipant;
+ return participant.root;
+ }
+ }
///
/// Function which can be used to create components in external engines.
@@ -147,14 +117,13 @@ namespace RoboidControl {
#endregion Init
+ ///
+ /// Terminated things are no longer updated
+ ///
public bool terminate = false;
#region Properties
- ///
- /// The participant owning this thing
- ///
- public Participant owner = null;
///
/// The ID of this thing
///
@@ -166,6 +135,11 @@ namespace RoboidControl {
/// This can be either a \ref RoboidControl::Thing::Type "Thing.Type" or a byte value for custom types.
public byte type = Type.Undetermined;
+ ///
+ /// The participant owning this thing
+ ///
+ public Participant owner = null;
+
private string _name = "";
///
/// The name of the thing
@@ -186,6 +160,9 @@ namespace RoboidControl {
///
/// An URL pointing to the location where a model of the thing can be found
///
+ /// Although the roboid implementation is not dependent on the model,
+ /// the only official supported model formats are .png (sprite), .gltf and .glb
+ ///
public string modelUrl {
get => _modelUrl;
set {
@@ -230,6 +207,12 @@ namespace RoboidControl {
}
}
+ ///
+ /// Indication whether this is a root thing
+ ///
+ public bool isRoot {
+ get => this == localRoot || this.parent == null;
+ }
///
/// The children of this thing
@@ -392,32 +375,11 @@ namespace RoboidControl {
#region Update
- ///
- /// Get the current time in milliseconds
- ///
- /// The current time in milliseconds
- public static ulong GetTimeMs() {
-#if UNITY_5_3_OR_NEWER
- return (ulong)(UnityEngine.Time.time * 1000);
-#else
- return TimeManager.GetCurrentTimeMilliseconds();
-#endif
- }
-
///
/// Update de state of the thing
///
/// When true, this will Update the descendants recursively
- public void Update(bool recurse = false) {
- Update(GetTimeMs(), recurse);
- }
- // #endif
- ///
- /// Update this thing
- ///
- /// he current clock time in milliseconds; if this is zero, the current time is retrieved automatically
- /// When true, this will Update the descendants recursively
- public virtual void Update(ulong currentTimeMs, bool recurse = false) {
+ public virtual void Update(bool recurse = false) {
this.positionUpdated = false;
this.orientationUpdated = false;
this.linearVelocityUpdated = false;
@@ -430,19 +392,42 @@ namespace RoboidControl {
Thing child = this.children[childIx];
if (child == null)
continue;
- child.Update(currentTimeMs, recurse);
+ child.Update(recurse);
}
}
}
+ ///
+ /// An event happened to this event
+ ///
+ /// The messageId indicates which kind of event happened
public class CoreEvent {
public CoreEvent(int messageId) {
this.messageId = messageId;
}
- public int messageId; // see the communication messages
+ ///
+ /// The type of event happened.
+ ///
+ /// This value is filled with the Ids of the communication messages.
+ public int messageId;
};
+ ///
+ /// Queue containing events happened to this thing
+ ///
public ConcurrentQueue updateQueue = new();
+ ///
+ /// Get the current time in milliseconds
+ ///
+ /// The current time in milliseconds
+ public static ulong GetTimeMs() {
+#if UNITY_5_3_OR_NEWER
+ return (ulong)(UnityEngine.Time.time * 1000);
+#else
+ return TimeManager.GetCurrentTimeMilliseconds();
+#endif
+ }
+
#endregion Update
///
diff --git a/src/Things/ControlledMotor.cs b/src/Things/ControlledMotor.cs
index fb5ad79..f08df2b 100644
--- a/src/Things/ControlledMotor.cs
+++ b/src/Things/ControlledMotor.cs
@@ -52,13 +52,14 @@ namespace RoboidControl {
float pidD = 0.0F;
//float pidI = 0.0F;
- public override void Update(ulong currentTimeMs, bool recurse = false) {
+ public override void Update(bool recurse = false) {
float actualSpeed = this.encoder.angularSpeed;
// Simplified rotation direction, shouldbe improved
// This goes wrong when the target speed is inverted and the motor axcle is still turning in the old direction
if (this.targetAngularSpeed < 0)
actualSpeed = -actualSpeed;
+ ulong currentTimeMs = Thing.GetTimeMs();
float deltaTime = (currentTimeMs - this.lastUpdateTime) / 1000.0f;
float error = this.targetAngularSpeed - actualSpeed;
diff --git a/src/Things/DifferentialDrive.cs b/src/Things/DifferentialDrive.cs
index c266d4f..78459ae 100644
--- a/src/Things/DifferentialDrive.cs
+++ b/src/Things/DifferentialDrive.cs
@@ -86,7 +86,7 @@ namespace RoboidControl {
}
/// @copydoc RoboidControl::Thing::Update(unsigned long)
- public override void Update(ulong currentMs, bool recursive = true) {
+ public override void Update(bool recursive = true) {
if (this.linearVelocityUpdated) {
// this assumes forward velocity only....
float linearVelocity = this.linearVelocity.distance;
diff --git a/src/Things/EncoderMotor.cs b/src/Things/EncoderMotor.cs
index 7a1302e..e20f6b5 100644
--- a/src/Things/EncoderMotor.cs
+++ b/src/Things/EncoderMotor.cs
@@ -52,13 +52,14 @@ namespace RoboidControl {
float pidD = 0.0F;
//float pidI = 0.0F;
- public override void Update(ulong currentTimeMs, bool recurse = false) {
+ public override void Update(bool recurse = false) {
float actualSpeed = this.encoder.angularSpeed;
// Simplified rotation direction, shouldbe improved
// This goes wrong when the target speed is inverted and the motor axcle is still turning in the old direction
if (this.targetAngularSpeed < 0)
actualSpeed = -actualSpeed;
+ ulong currentTimeMs = Thing.GetTimeMs();
float deltaTime = (currentTimeMs - this.lastUpdateTime) / 1000.0f;
float error = this.targetAngularSpeed - actualSpeed;
diff --git a/test/UnitTest1.cs b/test/UnitTest1.cs
index 9fc8f79..0cf87a5 100644
--- a/test/UnitTest1.cs
+++ b/test/UnitTest1.cs
@@ -18,7 +18,7 @@ namespace RoboidControl.test {
ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
ulong startTime = milliseconds;
while (milliseconds < startTime + 7000) {
- participant.Update(milliseconds);
+ participant.Update();
Thread.Sleep(100);
milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
@@ -34,7 +34,7 @@ namespace RoboidControl.test {
ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
ulong startTime = milliseconds;
while (milliseconds < startTime + 7000) {
- siteServer.Update(milliseconds);
+ siteServer.Update();
Thread.Sleep(100);
milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
@@ -51,8 +51,8 @@ namespace RoboidControl.test {
ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
ulong startTime = milliseconds;
while (milliseconds < startTime + 1000) {
- siteServer.Update(milliseconds);
- participant.Update(milliseconds);
+ siteServer.Update();
+ participant.Update();
Thread.Sleep(100);
milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
@@ -73,8 +73,8 @@ namespace RoboidControl.test {
ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
ulong startTime = milliseconds;
while (milliseconds < startTime + 7000) {
- siteServer.Update(milliseconds);
- participant.Update(milliseconds);
+ siteServer.Update();
+ participant.Update();
Thread.Sleep(100);
milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();