Simplified constructors
This commit is contained in:
parent
bd53b71cd3
commit
d9d64ebc8f
@ -9,7 +9,7 @@ namespace RoboidControl {
|
||||
readonly TouchSensor touchRight;
|
||||
const float speed = 0.5f;
|
||||
|
||||
public BB2B(Participant owner) : base(owner) {
|
||||
public BB2B(Thing parent = default) : base(parent) {
|
||||
this.name = "BB2B";
|
||||
this.SetMotors(new Motor(this), new Motor(this));
|
||||
this.SetDriveDimensions(0.064f, 0.128f);
|
||||
|
@ -9,15 +9,15 @@ namespace RoboidControl {
|
||||
readonly TouchSensor touchRight;
|
||||
const float speed = 180.0f; // wheel rotation speed in degrees
|
||||
|
||||
public BB2B_Encoder(Participant owner) : base(owner) {
|
||||
public BB2B_Encoder(Thing parent) : base(parent) {
|
||||
this.name = "BB2B";
|
||||
this.SetDriveDimensions(0.064f, 0.128f);
|
||||
|
||||
// Update the basic motors to motors with encoder
|
||||
EncoderMotor leftMotor = new(this, new RelativeEncoder()) {
|
||||
ControlledMotor leftMotor = new(this, new RelativeEncoder()) {
|
||||
position = new Spherical(0.064f, Direction.left)
|
||||
};
|
||||
EncoderMotor rightMotor = new(this, new RelativeEncoder()) {
|
||||
ControlledMotor rightMotor = new(this, new RelativeEncoder()) {
|
||||
position = new Spherical(0.064f, Direction.right)
|
||||
};
|
||||
this.SetMotors(leftMotor, rightMotor);
|
||||
|
@ -3,7 +3,7 @@ using RoboidControl;
|
||||
|
||||
class Program {
|
||||
static void Main() {
|
||||
BB2B bb2b = new(ParticipantUDP.Isolated());
|
||||
BB2B bb2b = new();
|
||||
|
||||
while (true) {
|
||||
bb2b.Update();
|
||||
|
18
README.md
18
README.md
@ -11,3 +11,21 @@ The documentation for Roboid Control for C# is found at https://docs.roboidcontr
|
||||
|
||||
- RoboidControl::Thing
|
||||
- RoboidControl::Participant
|
||||
|
||||
# Get Started
|
||||
|
||||
## Unity
|
||||
|
||||
The Unity environment can use the same RoboidControl code as every other C# code, but needs a *starter* wrapper around it to make the things visibile. For example, to start the BB2B example in Unity one needs to write a BB2B_Starter.cs component as follows:
|
||||
```
|
||||
using RoboidControl.Unity;
|
||||
|
||||
public class BB2B_Starter : SiteServer {
|
||||
void Start() {
|
||||
new RoboidControl.BB2B();
|
||||
}
|
||||
}
|
||||
```
|
||||
This component then should be attached to a GameObject in the scene.
|
||||
|
||||
It is possible to create a Site Server in Unity by just adding the `SiteServer` Component to a GameObject in the scene. When this is run, other roboids will be able to connect to this site then.
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
namespace RoboidControl {
|
||||
|
||||
@ -14,6 +15,13 @@ namespace RoboidControl {
|
||||
/// It also maintains the communcation information to contact the participant.
|
||||
/// It is used as a basis for the local participant, but also as a reference to remote participants.
|
||||
public class Participant {
|
||||
|
||||
private Participant() {
|
||||
this.root = Thing.CreateRoot(this);
|
||||
this.root.name = "Root";
|
||||
this.Add(this.root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new participant with the given communcation info
|
||||
/// </summary>
|
||||
@ -26,6 +34,10 @@ namespace RoboidControl {
|
||||
this.udpClient = localParticipant.udpClient;
|
||||
}
|
||||
|
||||
public static readonly Participant localParticipant = new();
|
||||
|
||||
public Thing root = null;
|
||||
|
||||
/// <summary>
|
||||
/// The Ip Address of a participant. When the participant is local, this contains 0.0.0.0
|
||||
/// </summary>
|
||||
|
@ -132,9 +132,9 @@ namespace RoboidControl {
|
||||
|
||||
protected virtual Thing ProcessNewThing(Participant sender, ThingMsg msg) {
|
||||
return msg.thingType switch {
|
||||
Thing.Type.TouchSensor => new TouchSensor(sender, msg.thingId),
|
||||
Thing.Type.DifferentialDrive => new DifferentialDrive(sender, msg.thingId),
|
||||
_ => new Thing(sender, msg.thingType, msg.thingId),
|
||||
//Thing.Type.TouchSensor => new TouchSensor(sender, msg.thingId),
|
||||
//Thing.Type.DifferentialDrive => new DifferentialDrive(sender, msg.thingId),
|
||||
_ => Thing.CreateRemote(sender, msg.thingType, msg.thingId)
|
||||
};
|
||||
|
||||
}
|
||||
|
69
src/Thing.cs
69
src/Thing.cs
@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using LinearAlgebra;
|
||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
|
||||
|
||||
namespace RoboidControl {
|
||||
|
||||
@ -26,10 +27,11 @@ namespace RoboidControl {
|
||||
public const byte ControlledMotor = 0x06;
|
||||
public const byte UncontrolledMotor = 0x07;
|
||||
public const byte Servo = 0x08;
|
||||
public const byte IncrementalEncoder = 0x19;
|
||||
public const byte RelativeEncoder = 0x19;
|
||||
// Other
|
||||
public const byte Root = 0x10;
|
||||
public const byte Roboid = 0x09;
|
||||
public const byte HUmanoid = 0x0A;
|
||||
public const byte Humanoid = 0x0A;
|
||||
public const byte ExternalSensor = 0x0B;
|
||||
public const byte Animator = 0x0C;
|
||||
public const byte DifferentialDrive = 0x0D;
|
||||
@ -37,6 +39,29 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Create a new thing without communication abilities
|
||||
/// </summary>
|
||||
@ -66,6 +91,7 @@ namespace RoboidControl {
|
||||
this.owner.updateQueue.Enqueue(e);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Create a new child thing
|
||||
@ -75,26 +101,33 @@ namespace RoboidControl {
|
||||
/// <param name="thingId">The ID of the thing, leave out or set to zero to generate an ID</param>
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
/// <note>The owner will be the same as the owner of the parent thing</note>
|
||||
/*
|
||||
public Thing(Thing parent, byte thingType = Type.Undetermined, byte thingId = 0, bool invokeEvent = true) : this(parent.owner, thingType, thingId, invokeEvent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
*/
|
||||
public Thing(byte thingType = Type.Undetermined, Thing parent = default) {
|
||||
this.type = thingType;
|
||||
|
||||
// /// <summary>
|
||||
// /// Create a new thing for the given participant
|
||||
// /// </summary>
|
||||
// /// <param name="owner">The participant owning the thing</param>
|
||||
// /// <param name="networkId">The network ID of the thing</param>
|
||||
// /// <param name="thingId">The ID of the thing</param>
|
||||
// /// <param name="thingType">The type of thing</param>
|
||||
// public Thing(Participant owner, byte networkId, byte thingId, byte thingType = 0) {
|
||||
// this.owner = owner;
|
||||
// this.id = thingId;
|
||||
// this.type = thingType;
|
||||
// this.networkId = networkId;
|
||||
// // Console.Write($"New thing added to {owner}");
|
||||
// this.owner.Add(this);
|
||||
// InvokeNewThing(this);
|
||||
// }
|
||||
this.positionUpdated = true;
|
||||
this.orientationUpdated = true;
|
||||
this.hierarchyChanged = true;
|
||||
|
||||
if (parent == default)
|
||||
this.parent = Participant.localParticipant.root;
|
||||
else
|
||||
this.parent = parent;
|
||||
|
||||
this.owner = parent.owner;
|
||||
this.owner.Add(this, true);
|
||||
}
|
||||
|
||||
public static Thing CreateRemote(Participant owner, byte thingType, byte thingId) {
|
||||
Thing remoteThing = new(thingType, owner.root) {
|
||||
id = thingId
|
||||
};
|
||||
return remoteThing;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function which can be used to create components in external engines.
|
||||
|
@ -3,12 +3,12 @@ namespace RoboidControl {
|
||||
/// @brief A motor with speed control
|
||||
/// It uses a feedback loop from an encoder to regulate the speed
|
||||
/// The speed is measured in revolutions per second.
|
||||
class EncoderMotor : Motor {
|
||||
public EncoderMotor(Thing parent, RelativeEncoder encoder) : base(parent) {
|
||||
public class ControlledMotor : Motor {
|
||||
public ControlledMotor(Thing parent, RelativeEncoder encoder) : base(parent) {
|
||||
this.encoder = encoder;
|
||||
}
|
||||
// Upgrade an existing motor with an encoder
|
||||
public EncoderMotor(Motor motor, RelativeEncoder encoder) : base(motor.parent) {
|
||||
public ControlledMotor(Motor motor, RelativeEncoder encoder) : base(motor.parent) {
|
||||
this.motor = motor;
|
||||
this.encoder = encoder;
|
||||
}
|
||||
@ -50,7 +50,7 @@ namespace RoboidControl {
|
||||
|
||||
float pidP = 0.1F;
|
||||
float pidD = 0.0F;
|
||||
float pidI = 0.0F;
|
||||
//float pidI = 0.0F;
|
||||
|
||||
public override void Update(ulong currentTimeMs, bool recurse = false) {
|
||||
float actualSpeed = this.encoder.angularSpeed;
|
@ -6,11 +6,13 @@ namespace RoboidControl {
|
||||
///
|
||||
/// @sa @link https://en.wikipedia.org/wiki/Differential_wheeled_robot @endlink
|
||||
public class DifferentialDrive : Thing {
|
||||
/*
|
||||
/// <summary>
|
||||
/// Create a differential drive without communication abilities
|
||||
/// </summary
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
public DifferentialDrive(bool invokeEvent = true) : base(Type.DifferentialDrive, invokeEvent) { }
|
||||
public DifferentialDrive() : base(Type.DifferentialDrive) { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a differential drive for a participant
|
||||
/// </summary>
|
||||
@ -28,15 +30,16 @@ namespace RoboidControl {
|
||||
// sendBinary = true;
|
||||
// owner.Send(new BinaryMsg(owner.networkId, this));
|
||||
// this.updateQueue.Enqueue(new UpdateEvent(BinaryMsg.Id));
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Create a new child differential drive
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent thing</param>
|
||||
/// <param name="thingId">The ID of the thing, leave out or set to zero to generate an ID</param>
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
public DifferentialDrive(Thing parent, byte thingId = 0, bool invokeEvent = true) : base(parent, Type.DifferentialDrive, thingId, invokeEvent) { }
|
||||
public DifferentialDrive(Thing parent) : base(Type.DifferentialDrive, parent) { }
|
||||
|
||||
/// @brief Configures the dimensions of the drive
|
||||
/// @param wheelDiameter The diameter of the wheels in meters
|
||||
@ -101,9 +104,9 @@ namespace RoboidControl {
|
||||
/// Positive moves the robot in the forward direction.
|
||||
public void SetWheelAngularVelocity(float angularSpeedLeft, float angularSpeedRight) {
|
||||
// This only works when the motor is a motor with encoder
|
||||
if (this.leftWheel is EncoderMotor leftMotor)
|
||||
if (this.leftWheel is ControlledMotor leftMotor)
|
||||
leftMotor.targetAngularSpeed = angularSpeedLeft;
|
||||
if (this.rightWheel is EncoderMotor rightMotor)
|
||||
if (this.rightWheel is ControlledMotor rightMotor)
|
||||
rightMotor.targetAngularSpeed = angularSpeedRight;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ namespace RoboidControl {
|
||||
/// A sensor which can detect touches
|
||||
/// </summary>
|
||||
public class DigitalSensor : Thing {
|
||||
/*
|
||||
/// <summary>
|
||||
/// Create a digital sensor without communication abilities
|
||||
/// </summary>
|
||||
@ -18,13 +19,14 @@ namespace RoboidControl {
|
||||
/// <param name="thingId">The ID of the thing, leave out or set to zero to generate an ID</param>
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
public DigitalSensor(Participant owner, byte thingId = 0, bool invokeEvent = true) : base(owner, Type.Switch, thingId, invokeEvent) { }
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create a new child digital sensor
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent thing</param>
|
||||
/// <param name="thingId">The ID of the thing, leave out or set to zero to generate an ID</param>
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
public DigitalSensor(Thing parent, byte thingId = 0, bool invokeEvent = true) : base(parent, Type.Switch, thingId, invokeEvent) { }
|
||||
public DigitalSensor(Thing parent) : base(Type.Switch, parent) { }
|
||||
|
||||
/// <summary>
|
||||
/// Value which is true when the sensor is touching something, false otherwise
|
||||
|
@ -9,19 +9,23 @@ namespace RoboidControl {
|
||||
/// </summary>
|
||||
public float distance = 0;
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Constructor for a new distance sensor
|
||||
/// </summary>
|
||||
/// <param name="participant">The participant for which the sensor is needed</param>
|
||||
public DistanceSensor(Participant participant) : base(participant, Type.Undetermined) { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a distance sensor with the given ID
|
||||
/// </summary>
|
||||
/// <param name="owner">The participant for with the sensor is needed</param>
|
||||
/// <param name="networkId">The network ID of the sensor</param>
|
||||
/// <param name="thingId">The ID of the thing</param>
|
||||
public DistanceSensor(Participant owner, byte thingId) : base(owner, Type.TemperatureSensor, thingId) {
|
||||
}
|
||||
public DistanceSensor(Participant owner, byte thingId) : base(owner, Type.TemperatureSensor, thingId) {}
|
||||
*/
|
||||
public DistanceSensor(Thing parent): base(Type.DistanceSensor, parent) {}
|
||||
|
||||
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
/// @copydoc Passer::RoboidControl::Thing::CreateComponent
|
||||
|
@ -3,8 +3,8 @@ using LinearAlgebra;
|
||||
namespace RoboidControl {
|
||||
|
||||
public class Motor : Thing {
|
||||
public Motor(bool invokeEvent = true) : base(Type.UncontrolledMotor, invokeEvent) { }
|
||||
public Motor(Thing parent, byte thingId = 0, bool invokeEvent = true) : base(parent, Type.UncontrolledMotor, thingId, invokeEvent) { }
|
||||
//public Motor(bool invokeEvent = true) : base(Type.UncontrolledMotor, invokeEvent) { }
|
||||
public Motor(Thing parent) : base(Type.UncontrolledMotor, parent) { }
|
||||
|
||||
/// @brief Motor turning direction
|
||||
public enum Direction {
|
||||
|
@ -1,4 +1,6 @@
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace RoboidControl {
|
||||
|
||||
/// @brief An Incremental Encoder measures the rotations of an axle using a rotary
|
||||
@ -9,7 +11,12 @@ namespace RoboidControl {
|
||||
/// full rotation
|
||||
/// @param distancePerRevolution The distance a wheel travels per full
|
||||
/// rotation
|
||||
/*
|
||||
public RelativeEncoder(bool invokeEvent = true) : base(Type.IncrementalEncoder, invokeEvent) { }
|
||||
*/
|
||||
public RelativeEncoder(Thing parent = default) : base(Type.RelativeEncoder, parent) {
|
||||
|
||||
}
|
||||
|
||||
protected float _rotationSpeed = 0;
|
||||
/// @brief Get the rotation speed since the previous call
|
||||
|
@ -6,6 +6,7 @@ namespace RoboidControl {
|
||||
/// A temperature sensor
|
||||
/// </summary>
|
||||
public class TemperatureSensor : Thing {
|
||||
/*
|
||||
/// <summary>
|
||||
/// Create a temperature sensor without communication abilities
|
||||
/// </summary>
|
||||
@ -18,14 +19,14 @@ namespace RoboidControl {
|
||||
/// <param name="thingId">The ID of the thing</param>
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
public TemperatureSensor(Participant owner, byte thingId = 0, bool invokeEvent = true) : base(owner, Type.TemperatureSensor, thingId, invokeEvent) { }
|
||||
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create a new child temperature sensor
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent thing</param>
|
||||
/// <param name="thingId">The ID of the thing, leave out or set to zero to generate an ID</param>
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
public TemperatureSensor(Thing parent, byte thingId = 0, bool invokeEvent = true) : base(parent, Type.TemperatureSensor, thingId, invokeEvent) { }
|
||||
public TemperatureSensor(Thing parent) : base(Type.TemperatureSensor, parent) { }
|
||||
|
||||
/// <summary>
|
||||
/// The measured temperature
|
||||
|
@ -6,6 +6,7 @@ namespace RoboidControl {
|
||||
/// A sensor which can detect touches
|
||||
/// </summary>
|
||||
public class TouchSensor : Thing {
|
||||
/*
|
||||
/// <summary>
|
||||
/// Create a touch sensor without communication abilities
|
||||
/// </summary>
|
||||
@ -18,13 +19,14 @@ namespace RoboidControl {
|
||||
/// <param name="thingId">The ID of the thing, leave out or set to zero to generate an ID</param>
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
public TouchSensor(Participant owner, byte thingId = 0, bool invokeEvent = true) : base(owner, Type.TouchSensor, thingId, invokeEvent) { }
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create a new child touch sensor
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent thing</param>
|
||||
/// <param name="thingId">The ID of the thing, leave out or set to zero to generate an ID</param>
|
||||
/// <param name="invokeEvent">Invoke a OnNewThing event when the thing has been created</param>
|
||||
public TouchSensor(Thing parent, byte thingId = 0, bool invokeEvent = true) : base(parent, Type.TouchSensor, thingId, invokeEvent) {
|
||||
public TouchSensor(Thing parent) : base(Type.TouchSensor, parent) {
|
||||
this.name = "TouchSensor";
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ namespace RoboidControl.test {
|
||||
public void Test_ThingMsg() {
|
||||
SiteServer siteServer = new(7681);
|
||||
ParticipantUDP participant = new("127.0.0.1", 7681, 7682);
|
||||
Thing thing = new(participant) {
|
||||
Thing thing = new() {
|
||||
name = "First Thing",
|
||||
modelUrl = "https://passer.life/extras/ant.jpg"
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user