First step to adding differential dirve
This commit is contained in:
parent
574a8c742b
commit
25edc506a0
@ -1,20 +1,21 @@
|
||||
|
||||
namespace RoboidControl {
|
||||
|
||||
public class BB2B : Thing {
|
||||
// The robot is based on a differential drive
|
||||
public class BB2B : DifferentialDrive {
|
||||
readonly DifferentialDrive drive;
|
||||
readonly TouchSensor touchLeft;
|
||||
readonly TouchSensor touchRight;
|
||||
|
||||
public BB2B() : base(128) { // thingType = 128
|
||||
|
||||
// The robot's propulsion is a differential drive
|
||||
drive = new();
|
||||
public BB2B(Participant owner) : base(owner) {
|
||||
this.name = "BB2B";
|
||||
this.wheelRadius = 0.032f;
|
||||
this.wheelSeparation = 0.128f;
|
||||
|
||||
// Is has a touch sensor at the front left of the roboid
|
||||
touchLeft = new(drive);
|
||||
touchLeft = new(this);
|
||||
// and other one on the right
|
||||
touchRight = new(drive);
|
||||
touchRight = new(this);
|
||||
}
|
||||
|
||||
public override void Update(ulong currentTimeMs, bool recurse = true) {
|
||||
@ -30,7 +31,7 @@ public class BB2B : Thing {
|
||||
// When both sides are touching something, both wheels will turn backward
|
||||
// and the roboid will move backwards
|
||||
|
||||
drive.SetWheelVelocity(leftWheelSpeed, rightWheelSpeed);
|
||||
this.SetWheelVelocity(leftWheelSpeed, rightWheelSpeed);
|
||||
|
||||
base.Update(currentTimeMs, recurse);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ using RoboidControl;
|
||||
|
||||
class Program {
|
||||
static void Main() {
|
||||
BB2B bb2b = new();
|
||||
BB2B bb2b = new(ParticipantUDP.Isolated());
|
||||
|
||||
while (true) {
|
||||
bb2b.Update();
|
||||
|
108
Unity/DifferentialDrive.cs
Normal file
108
Unity/DifferentialDrive.cs
Normal file
@ -0,0 +1,108 @@
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RoboidControl.Unity {
|
||||
public class DifferentialDrive : Thing {
|
||||
|
||||
public WheelCollider leftWheel;
|
||||
public WheelCollider rightWheel;
|
||||
|
||||
/// <summary>
|
||||
/// Create the Unity representation
|
||||
/// </summary>
|
||||
/// <param name="core">The core touch sensor</param>
|
||||
/// <returns>The Unity representation of the touch sensor</returns>
|
||||
public static DifferentialDrive Create(RoboidControl.DifferentialDrive core) {
|
||||
GameObject gameObj = new(core.name);
|
||||
DifferentialDrive component = gameObj.AddComponent<DifferentialDrive>();
|
||||
component.Init(core);
|
||||
|
||||
Rigidbody rb = gameObj.AddComponent<Rigidbody>();
|
||||
rb.isKinematic = false;
|
||||
rb.mass = 0.5f;
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
protected override void HandleBinary() {
|
||||
RoboidControl.DifferentialDrive drive = core as RoboidControl.DifferentialDrive;
|
||||
if (leftWheel == null) {
|
||||
GameObject leftWheelObj = new GameObject("Left wheel");
|
||||
leftWheelObj.transform.SetParent(this.transform);
|
||||
leftWheel = leftWheelObj.AddComponent<WheelCollider>();
|
||||
leftWheel.mass = 0.1f;
|
||||
leftWheel.suspensionDistance = 0.01f;
|
||||
leftWheel.suspensionSpring = new JointSpring {
|
||||
spring = 1000f, // Very high spring value to make it rigid
|
||||
damper = 100f, // Low damping (could be adjusted for slight 'bounciness')
|
||||
targetPosition = 0.5f // Neutral position (middle of the suspension travel)
|
||||
};
|
||||
leftWheel.radius = drive.wheelRadius;
|
||||
leftWheel.center = new Vector3(-drive.wheelSeparation / 2, 0, 0);
|
||||
}
|
||||
if (rightWheel == null) {
|
||||
GameObject rightWheelObj = new GameObject("Left wheel");
|
||||
rightWheelObj.transform.SetParent(this.transform);
|
||||
rightWheel = rightWheelObj.AddComponent<WheelCollider>();
|
||||
rightWheel.mass = 0.1f;
|
||||
rightWheel.suspensionDistance = 0.01f;
|
||||
rightWheel.suspensionSpring = new JointSpring {
|
||||
spring = 1000f, // Very high spring value to make it rigid
|
||||
damper = 100f, // Low damping (could be adjusted for slight 'bounciness')
|
||||
targetPosition = 0.5f // Neutral position (middle of the suspension travel)
|
||||
};
|
||||
rightWheel.radius = drive.wheelRadius;
|
||||
rightWheel.center = new Vector3(drive.wheelSeparation / 2, 0, 0);
|
||||
|
||||
}
|
||||
// Thing[] children = this.GetComponentsInChildren<Thing>();
|
||||
// if (leftWheel == null) {
|
||||
// leftWheel = children.FirstOrDefault(child => child.core.id == drive.leftWheel.id);
|
||||
// if (leftWheel == null) {
|
||||
// RoboidControl.Thing coreThing = new(drive.owner, 0, drive.leftWheel.id, false) {
|
||||
// name = "Left Wheel"
|
||||
// };
|
||||
// leftWheel = Thing.Create(coreThing);
|
||||
// leftWheel.transform.SetParent(this.transform);
|
||||
// }
|
||||
// WheelCollider wheel = this.GetComponent<WheelCollider>();
|
||||
// if (wheel == null)
|
||||
// wheel = this.gameObject.AddComponent<WheelCollider>();
|
||||
// wheel.mass = 0.1f;
|
||||
// wheel.suspensionDistance = 0.01f;
|
||||
// wheel.suspensionSpring = new JointSpring {
|
||||
// spring = 1000f, // Very high spring value to make it rigid
|
||||
// damper = 100f, // Low damping (could be adjusted for slight 'bounciness')
|
||||
// targetPosition = 0.5f // Neutral position (middle of the suspension travel)
|
||||
// };
|
||||
// wheel.radius = drive.wheelRadius;
|
||||
// wheel.center = new Vector3(-drive.wheelSeparation / 2, 0, 0);
|
||||
// }
|
||||
// if (rightWheel == null) {
|
||||
// this.rightWheel = children.FirstOrDefault(child => child.core.id == drive.rightWheel.id);
|
||||
// if (this.rightWheel == null) {
|
||||
// RoboidControl.Thing coreThing = new(drive.owner, 0, drive.rightWheel.id, false) {
|
||||
// name = "Right Wheel"
|
||||
// };
|
||||
// this.rightWheel = Thing.Create(coreThing);
|
||||
// this.rightWheel.transform.SetParent(this.transform);
|
||||
// }
|
||||
// WheelCollider wheel = this.GetComponent<WheelCollider>();
|
||||
// if (wheel == null)
|
||||
// wheel = this.gameObject.AddComponent<WheelCollider>();
|
||||
// wheel.mass = 0.1f;
|
||||
// wheel.suspensionDistance = 0.01f;
|
||||
// wheel.suspensionSpring = new JointSpring {
|
||||
// spring = 1000f, // Very high spring value to make it rigid
|
||||
// damper = 100f, // Low damping (could be adjusted for slight 'bounciness')
|
||||
// targetPosition = 0.5f // Neutral position (middle of the suspension travel)
|
||||
// };
|
||||
// wheel.radius = drive.wheelRadius;
|
||||
// wheel.center = new Vector3(drive.wheelSeparation / 2, 0, 0);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
@ -24,15 +24,21 @@ namespace RoboidControl.Unity {
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleThingEvent(RoboidControl.Participant.UpdateEvent e) {
|
||||
protected virtual void HandleThingEvent(RoboidControl.Participant.UpdateEvent e) {
|
||||
switch (e.thing) {
|
||||
case RoboidControl.TouchSensor coreTouchSensor:
|
||||
TouchSensor touchSensor = TouchSensor.Create(coreTouchSensor);
|
||||
coreTouchSensor.component = touchSensor;
|
||||
break;
|
||||
case RoboidControl.DifferentialDrive coreDrive:
|
||||
DifferentialDrive differentialDrive = DifferentialDrive.Create(coreDrive);
|
||||
coreDrive.component = differentialDrive;
|
||||
break;
|
||||
case RoboidControl.Thing coreThing:
|
||||
if (coreThing.component != null) {
|
||||
Thing thing = Thing.Create(coreThing);
|
||||
coreThing.component = thing;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,8 @@ namespace RoboidControl.Unity {
|
||||
participant.coreParticipant = e.participant;
|
||||
break;
|
||||
case ThingMsg.id:
|
||||
e.thing.CreateComponent();
|
||||
HandleThingEvent(e);
|
||||
//e.thing.CreateComponent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ namespace RoboidControl.Unity {
|
||||
protected void Init(RoboidControl.Thing core) {
|
||||
this.core = core;
|
||||
this.participant = FindAnyObjectByType<SiteServer>();
|
||||
core.owner = this.participant.coreParticipant;
|
||||
if (core.parent != null && core.parent.component != null)
|
||||
this.transform.SetParent(core.parent.component.transform, false);
|
||||
|
||||
@ -105,6 +106,9 @@ namespace RoboidControl.Unity {
|
||||
if (core.angularVelocity.distance == 0)
|
||||
this.transform.localRotation = core.orientation.ToQuaternion();
|
||||
break;
|
||||
case BinaryMsg.Id:
|
||||
this.HandleBinary();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,6 +147,7 @@ namespace RoboidControl.Unity {
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleBinary() {}
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,7 @@ namespace RoboidControl.Unity {
|
||||
/// <param name="core">The core touch sensor</param>
|
||||
/// <returns>The Unity representation of the touch sensor</returns>
|
||||
public static TouchSensor Create(RoboidControl.TouchSensor core) {
|
||||
GameObject gameObj = core.name != null ?
|
||||
new(core.name) :
|
||||
new("Touch Sensor");
|
||||
GameObject gameObj = new(core.name);
|
||||
TouchSensor component = gameObj.AddComponent<TouchSensor>();
|
||||
component.Init(core);
|
||||
|
||||
|
@ -117,16 +117,7 @@ namespace RoboidControl {
|
||||
Console.WriteLine($"{this.name}: Process thing [{msg.networkId}/{msg.thingId}] {msg.thingType} {msg.parentId} ");
|
||||
|
||||
Thing thing = sender.Get(msg.thingId);
|
||||
if (thing == null) {
|
||||
switch (msg.thingType) {
|
||||
case (byte)Thing.Type.TouchSensor:
|
||||
new TouchSensor(sender, msg.thingId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (thing == null)
|
||||
thing = new Thing(sender, msg.thingType, msg.thingId);
|
||||
thing ??= ProcessNewThing(sender, msg);
|
||||
|
||||
if (msg.parentId != 0) {
|
||||
thing.parent = sender.Get(msg.parentId);
|
||||
@ -139,6 +130,14 @@ 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),
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endregion Receive
|
||||
|
||||
|
@ -17,7 +17,19 @@ namespace RoboidControl {
|
||||
/// <param name="owner">The owning participant</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(Participant participant, byte thingId = 0, bool invokeEvent = true) : base(participant, Type.DifferentialDrive, thingId, invokeEvent) { }
|
||||
public DifferentialDrive(Participant owner, byte thingId = 0, bool invokeEvent = true) : base(owner, Type.DifferentialDrive, thingId, invokeEvent) {
|
||||
Thing leftWheel = new(this) {
|
||||
name = "Left Wheel"
|
||||
};
|
||||
Thing rightWheel = new(this) {
|
||||
name = "Right Wheel"
|
||||
};
|
||||
SetMotors(leftWheel, rightWheel);
|
||||
sendBinary = true;
|
||||
owner.Send(new BinaryMsg(owner.networkId, this));
|
||||
this.updateQueue.Enqueue(new UpdateEvent(BinaryMsg.Id));
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Create a new child differential drive
|
||||
/// </summary>
|
||||
@ -92,17 +104,43 @@ namespace RoboidControl {
|
||||
}
|
||||
|
||||
/// @brief The radius of a wheel in meters
|
||||
protected float wheelRadius = 1.0f;
|
||||
public float wheelRadius = 1.0f;
|
||||
/// @brief The distance between the wheels in meters
|
||||
protected float wheelSeparation = 1.0f;
|
||||
public 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;
|
||||
public Thing leftWheel = null;
|
||||
/// @brief The right wheel
|
||||
protected Thing rightWheel = null;
|
||||
public Thing rightWheel = null;
|
||||
|
||||
bool sendBinary = false;
|
||||
public override byte[] GenerateBinary() {
|
||||
if (!sendBinary)
|
||||
return System.Array.Empty<byte>();
|
||||
|
||||
byte[] data = new byte[6];
|
||||
byte ix = 0;
|
||||
data[ix++] = leftWheel.id;
|
||||
data[ix++] = rightWheel.id;
|
||||
LowLevelMessages.SendFloat16(data, ref ix, wheelRadius);
|
||||
LowLevelMessages.SendFloat16(data, ref ix, wheelSeparation);
|
||||
sendBinary = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
public override void ProcessBinary(byte[] data) {
|
||||
byte ix = 0;
|
||||
byte leftWheelId = data[ix++];
|
||||
this.leftWheel = this.owner.Get(leftWheelId);
|
||||
byte rightWheelId = data[ix++];
|
||||
this.rightWheel = this.owner.Get(rightWheelId);
|
||||
this.wheelRadius = LowLevelMessages.ReceiveFloat16(data, ref ix);
|
||||
this.wheelSeparation = LowLevelMessages.ReceiveFloat16(data, ref ix);
|
||||
this.updateQueue.Enqueue(new UpdateEvent(BinaryMsg.Id));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace RoboidControl
|
@ -24,7 +24,9 @@ namespace RoboidControl {
|
||||
/// <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, byte thingId = 0, bool invokeEvent = true) : base(parent, Type.TouchSensor, thingId, invokeEvent) {
|
||||
this.name = "TouchSensor";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value which is true when the sensor is touching something, false otherwise
|
||||
|
Loading…
x
Reference in New Issue
Block a user