2024-09-03 11:37:23 +02:00

144 lines
5.8 KiB
C#

using System;
using System.Linq;
namespace FreeD
{
[Serializable]
public class Packet
{
// From https://github.com/stvmyr/freeD
//Offset Function Description
//0 Identifier Message Type.The Encode function always uses 0xD1. (see freeD manual section A.3.1 for further information)
//1 ID Camera ID.This is a relict when using multiple Systems via RS232 or RS422.
//2:5 Pitch Camera Pitch angle described in degree.
//5:8 Yaw Camera Yaw angle described in degree.
//8:11 Roll Camera Roll angle described in degree.
//11:14 Position Z Camera Z Offset from origin.Typically described in millimeter.
//14:17 Position Y Camera Y Offset from origin.Typically described in millimeter.
//17:20 Position X Camera X Offset from origin.Typically described in millimeter.
//20:23 Zoom Lens Zoom Position.Typically measured with an external encoder attached to the Lens.In the most cases this is a value between 0-4095.
//23:26 Focus Lens Focus Position. Typically measured with an external encoder attached to the Lens. In the most cases this is a value between 0-4095.
//26:28 Reserved Currently not used in freeD.
//28 Checksum Checksum of the first 28 bytes.The Decode function uses the checksum to verify if the incoming data is a valid freeD package.
public int Id;
public float Pan;
public float Tilt;
public float Roll;
public float PosZ;
public float PosX;
public float PosY;
public float Zoom;
public float Focus;
public static Packet Decode(byte[] data)
{
//if (Checksum(data) == data[28])
{
var trackingData = new Packet
{
Id = data.Skip(1).First(),
Pan = GetRotation(data.Skip(2).Take(3).ToArray()),
Tilt = GetRotation(data.Skip(5).Take(3).ToArray()),
Roll = GetRotation(data.Skip(8).Take(3).ToArray()),
PosZ = GetPosition(data.Skip(11).Take(3).ToArray()),
PosX = GetPosition(data.Skip(14).Take(3).ToArray()),
PosY = GetPosition(data.Skip(17).Take(3).ToArray()),
Zoom = GetPosition(data.Skip(20).Take(3).ToArray()),
Focus = GetPosition(data.Skip(23).Take(3).ToArray())
};
return trackingData;
}
throw new Exception("Calculated checksum does not match provided data. Probably not FreeD.");
}
public static byte[] Encode(Packet data)
{
byte[] output = { 0xD1 }; // Identifier
//output = output.Concat(new byte[] { 0xFF }).ToArray(); // ID
output = output.Concat(SetCameraId(data.Id)).ToArray(); // ID: LQ
output = output.Concat(SetRotation(data.Pan)).ToArray(); // Pitch
output = output.Concat(SetRotation(data.Tilt)).ToArray(); // Yaw
output = output.Concat(SetRotation(data.Roll)).ToArray(); // Roll
output = output.Concat(SetPosition(data.PosZ)).ToArray(); // X
output = output.Concat(SetPosition(data.PosX)).ToArray(); // Y
output = output.Concat(SetPosition(data.PosY)).ToArray(); // Z
output = output.Concat(SetPosition(data.Zoom)).ToArray(); // Zoom
output = output.Concat(SetPosition(data.Focus)).ToArray(); // Focus
output = output.Concat(new byte[] { 0x00, 0x00 }).ToArray(); // Reserved
output = output.Concat(new byte[] { (byte)Checksum(output) }).ToArray(); // Checksum
return output;
}
public static byte[] SetCameraId(int cameraId)
{
int id = (UInt16)(cameraId);
byte[] data = BitConverter.GetBytes(id);
if (!BitConverter.IsLittleEndian)
Array.Reverse(data);
return data.Skip(0).Take(1).ToArray();
}
public static byte[] SetPosition(float pos)
{
long position = (long)(pos * 64 * 256);
byte[] data = BitConverter.GetBytes(position);
Array.Reverse(data);
return data.Skip(4).Take(3).ToArray();
}
public static byte[] SetRotation(float rot)
{
long rotation = (long)(rot * 32768 * 256);
byte[] data = BitConverter.GetBytes(rotation);
Array.Reverse(data);
return data.Skip(4).Take(3).ToArray();
}
public static byte[] SetEncoder(int enc)
{
byte[] data = BitConverter.GetBytes(enc);
Array.Reverse(data);
return new byte[] { 0x00 }.Concat(data.Skip(5).Take(2)).ToArray();
}
public static float GetPosition(byte[] data)
{
return (float)(BitConverter.ToInt32(new byte[] { 0x00, data[2], data[1], data[0] }, 0) / 64 / 256);
}
public static float GetRotation(byte[] data)
{
return (float)(BitConverter.ToInt32(new byte[] { 0x00, data[2], data[1], data[0] }, 0) / 32768f / 256f);
}
public static int GetEncoder(byte[] data)
{
byte[] value = new byte[] { 0x00 }.Concat(data).ToArray();
Array.Reverse(value);
return BitConverter.ToInt32(value, 0);
}
public static int Checksum(byte[] data)
{
int sum = 64;
for (int i = 0; i < 28; i++)
{
sum -= data[i];
}
return Modulo(sum, 256);
}
public static int Modulo(int d, int m)
{
int res = d % m;
if ((res < 0 && m > 0) || (res > 0 && m < 0))
{
return res + m;
}
return res;
}
}
}