using System.IO; using System.Threading.Tasks; 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; this.position = position; this.orientation = orientation; this.poseType = 0; if (this.position != null) this.poseType |= Pose_Position; 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; buffer[ix++] = this.networkId; buffer[ix++] = this.thingId; buffer[ix++] = this.poseType; if ((poseType & Pose_Position) != 0) LowLevelMessages.SendSpherical(buffer, ref ix, this.position); if ((poseType & Pose_Orientation) != 0) LowLevelMessages.SendQuat32(buffer, ref ix, this.orientation); if ((poseType & Pose_LinearVelocity) != 0) LowLevelMessages.SendSpherical(buffer, ref ix, this.linearVelocity); if ((poseType & Pose_AngularVelocity) != 0) 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++]; // 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); // // Do no process poses with nwid == 0 (== local) // if (msg.networkId == 0) // return true; // client.messageQueue.Enqueue(msg); // return true; // } // 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; // 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); // } } }