Compare commits

..

No commits in common. "960519fee63b10dc5fae549ceefc5300409d508d" and "fcc584d37b68b14bd2af8ad67812dbcfb3dff3b7" have entirely different histories.

8 changed files with 155 additions and 1095 deletions

View File

@ -1,718 +0,0 @@
flf2a$ 7 7 26 32 3
Alligator by Simon Bradley <syb3@aber.ac.uk>
17th June, 1994
$ $@
$ $@
$ $@
$ $@
$ $@
$ $@
$ $@@
:::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
$ $ @
###$ @@
::: :::$@
:+: :+:$ @
$ $ @
$ $ @
$ $ @
$ $ @
$ $ @@
::: :::$ @
:+: :+:$ @
+:+:+:+:+:+:+:+$@
+#+ +:+$ @
+#+#+#+#+#+#+#+$ @
#+# #+#$ @
### ###$ @@
:::$ @
:+:+:+:+:$@
+:+ +:+$ @
+#++:++#+$ @
+#+ +#+$ @
#+#+#+#+#$ @
###$ @@
::: :::$ @
:+: :+:$ @
+:+$ @
+#+$ @
+#+$ @
#+# #+#$@
### ###$ @@
:::::::$ @
:+: :+:$ @
+:+ +:+$ @
+#++: ++#$@
+#+ +#+#+#$ @
#+# #+#+$ @
##########$ @@
:::$@
:+$ @
$$ @
$$ @
$$ @
$$ @
$$ @@
:::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
###$ @@
:::$@
:+:$@
+:+$@
+#+$ @
+#+$ @
#+#$ @
###$ @@
$ $ $ $@
:+: :+:$@
+:+ +:+$ @
+#++:++#++:++$ @
+#+ +#+$ @
#+# #+#$ @
$ $ $ $ @@
$ $ @
:+:$ @
+:+$ @
+#++:++#++:++$@
+#+$ @
#+#$ @
$ $ @@
$ $@
$ $ @
$ $ @
$ $ @
$ $ @
#+#$ @
##$ @@
$ $@
$ $ @
$ $ @
+#++:++#++:++$ @
$ $ @
$ $ @
$ $ @@
$ $@
$ $ @
$ $ @
$ $ @
$ $ @
#+#$ @
###$ @@
:::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
###$ @@
:::::::$@
:+: :+:$@
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
#######$ @@
:::$@
:+:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
#######$ @@
::::::::$@
:+: :+:$@
$ +:+$ @
$ +#+$ @
$ +#+$ @
#+#$ @
##########$ @@
::::::::$@
:+: :+:$@
$ +:+$ @
$ +#++:$ @
$ +#+$ @
#+# #+#$ @
########$ @@
:::$@
:+:$ @
+:+ +:+$@
+#+ +:+$ @
+#+#+#+#+#+$@
#+#$ @
###$ @@
::::::::::$@
:+: :+:$ @
+:+ $ @
+#++:++#+$ @
$ +#+$ @
#+# #+#$ @
########$ @@
::::::::$@
:+: :+:$@
+:+ $ @
+#++:++#+$ @
+#+ +#+$ @
#+# #+#$ @
########$ @@
:::::::::::$@
:+: :+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
###$ @@
::::::::$@
:+: :+:$@
+:+ +:+$ @
+#++:++#$ @
+#+ +#+$ @
#+# #+#$ @
########$ @@
::::::::$@
:+: :+:$@
+:+ +:+$ @
+#++:++#+$ @
$ +#+$ @
#+# #+#$ @
########$ @@
$ $@
:+:$@
$ $ @
$ $ @
$ $ @
#+#$ @
$ $ @@
$ $@
:+:$@
$ $ @
$ $ @
$ $ @
#+#$ @
##$ @@
:::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
###$ @@
$ $@
$ $ @
+:+:+:+:+:+:+$ @
$ $ @
+#+#+#+#+#+#+$ @
$ $ @
$ $ @@
:::$@
:+:$@
+:+$@
+#+$@
+#+$ @
#+#$ @
###$ @@
:::::::::$@
:+: :+:$@
+:+$ @
+#+$ @
+#+$ @
$ $ @
###$ @@
:::::::::::$ @
:+: :+:+:+:+:+:$@
+:+ +:+ +:+ +:+$@
+#+ +:+ +#+ +:+$ @
+#+ +#+ +#+ +#+$ @
#+# #+#+#+#+#+$ @
#####$ @@
:::$ @
:+: :+:$@
+:+ +:+$@
+#++:++#++:$@
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
:::::::::$@
:+: :+:$@
+:+ +:+$ @
+#++:++#+$ @
+#+ +#+$ @
#+# #+#$ @
#########$ @@
::::::::$@
:+: :+:$@
+:+ $ @
+#+ $ @
+#+ $ @
#+# #+#$ @
########$ @@
:::::::::$@
:+: :+:$@
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
#########$ @@
::::::::::$@
:+:$ @
+:+$ @
+#++:++#$ @
+#+$ @
#+#$ @
##########$ @@
::::::::::$@
:+:$ @
+:+$ @
:#::+::#$ @
+#+$ @
#+#$ @
###$ @@
::::::::$@
:+: :+:$@
+:+ $ @
:#: $ @
+#+ +#+#$ @
#+# #+#$ @
########$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#++:++#++$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
:::::::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
###########$ @@
:::::::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+# #+#$ @
#####$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#++:++$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
:::$ @
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
##########$@@
::: :::$@
:+:+: :+:+:$@
+:+ +:+:+ +:+$@
+#+ +:+ +#+$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
:::: :::$@
:+:+: :+:$ @
:+:+:+ +:+$ @
+#+ +:+ +#+$ @
+#+ +#+#+#$ @
#+# #+#+#$ @
### ####$ @@
::::::::$@
:+: :+:$@
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
########$ @@
:::::::::$@
:+: :+:$@
+:+ +:+$ @
+#++:++#+$ @
+#+$ @
#+#$ @
###$ @@
::::::::$@
:+: :+:$@
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
###########$ @@
:::::::::$@
:+: :+:$@
+:+ +:+$ @
+#++:++#:$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
::::::::$@
:+: :+:$@
+:+ $ @
+#++:++#++$ @
$ +#+$ @
#+# #+#$ @
########$ @@
:::::::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
###$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
########$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+#+#+#$ @
###$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#+ +:+ +#+$ @
+#+ +#+#+ +#+$ @
#+#+# #+#+#$ @
### ###$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#++:+$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#++:$ @
+#+$ @
#+#$ @
###$ @@
:::::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
#########$ @@
::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
######$ @@
:::$@
:+:$@
+:+$@
+#+$@
+#+$@
#+#$@
###$@@
::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
######$ @@
:::$ @
:+: :+:$ @
+:+ +:+$@
$ $ @
$ $ @
$ $ @
$ $ @@
$ $@
$ $ @
$ $ @
$ $ @
$ $ @
$ $ @
##########$ @@
:::$@
:+$ @
$$ @
$$ @
$$ @
$$ @
$$ @@
:::$ @
:+: :+:$@
+:+ +:+$@
+#++:++#++:$@
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
:::::::::$@
:+: :+:$@
+:+ +:+$ @
+#++:++#+$ @
+#+ +#+$ @
#+# #+#$ @
#########$ @@
::::::::$@
:+: :+:$@
+:+ $ @
+#+ $ @
+#+ $ @
#+# #+#$ @
########$ @@
:::::::::$@
:+: :+:$@
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
#########$ @@
::::::::::$@
:+:$ @
+:+$ @
+#++:++#$ @
+#+$ @
#+#$ @
##########$ @@
::::::::::$@
:+:$ @
+:+$ @
:#::+::#$ @
+#+$ @
#+#$ @
###$ @@
::::::::$@
:+: :+:$@
+:+ $ @
:#: $ @
+#+ +#+#$ @
#+# #+#$ @
########$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#++:++#++$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
:::::::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
###########$ @@
:::::::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+# #+#$ @
#####$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#++:++$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
:::$ @
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
##########$@@
::: :::$@
:+:+: :+:+:$@
+:+ +:+:+ +:+$@
+#+ +:+ +#+$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
:::: :::$@
:+:+: :+:$ @
:+:+:+ +:+$ @
+#+ +:+ +#+$ @
+#+ +#+#+#$ @
#+# #+#+#$ @
### ####$ @@
::::::::$@
:+: :+:$@
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
########$ @@
:::::::::$@
:+: :+:$@
+:+ +:+$ @
+#++:++#+$ @
+#+$ @
#+#$ @
###$ @@
::::::::$@
:+: :+:$@
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
###########$ @@
:::::::::$@
:+: :+:$@
+:+ +:+$ @
+#++:++#:$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
::::::::$@
:+: :+:$@
+:+ $ @
+#++:++#++$ @
$ +#+$ @
#+# #+#$ @
########$ @@
:::::::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
###$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+# #+#$ @
########$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#+ +:+$ @
+#+ +#+$ @
#+#+#+#$ @
###$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#+ +:+ +#+$ @
+#+ +#+#+ +#+$ @
#+#+# #+#+#$ @
### ###$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#++:+$ @
+#+ +#+$ @
#+# #+#$ @
### ###$ @@
::: :::$@
:+: :+:$ @
+:+ +:+$ @
+#++:$ @
+#+$ @
#+#$ @
###$ @@
:::::::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
#########$ @@
::::$@
:+:$ @
+:+$ @
+#+$ @
+#+$ @
#+#$ @
####$ @@
:::$@
:+:$ @
+:+$ @
$ $ @
+#+$ @
#+#$ @
###$ @@
::::$@
:+:$@
+:+$ @
+#+$@
+#+$ @
#+#$ @
####$ @@
::::: :::$@
:+: :+:+:$ @
$ $ @
$ $ @
$ $ @
$ $ @
$ $ @@
@
@
@
@
@
@
@@
@
@
@
@
@
@
@@
@
@
@
@
@
@
@@
@
@
@
@
@
@
@@
@
@
@
@
@
@
@@
@
@
@
@
@
@
@@
@
@
@
@
@
@
@@

View File

@ -1,12 +0,0 @@
namespace VRC_Console;
internal class Config
{
internal string Ip = "127.0.0.1";
internal int PortSend = 9000;
internal double Radius = 100;
internal double CalibrationX = 0;
internal double CalibrationY = 0;
internal double WalkStretchDeadzone = 0.1;
internal double RunStretch = 0.4;
}

View File

@ -1,115 +0,0 @@
using Spectre.Console;
namespace VRC_Console;
public partial class OSCCollar
{
private const byte CoordinateSystemSize = 16;
private void SetupConsoleOutput()
{
Layout layout = new Layout().SplitRows(
new Layout("Top"),
new Layout("Bottom").SplitColumns(
new Layout("Config-Values"),
new Layout("Variable-Values"),
new Layout("Position")
));
Table configTable = new Table();
configTable.AddColumn("ConVar");
configTable.AddColumn("Value");
configTable.AddRow("IP", this._config.Ip);
configTable.AddRow("Send-Osc-Port", this._config.PortSend.ToString());
configTable.AddRow("Receive-Osc-Port", _portReceive.ToString());
configTable.AddRow("HTTP-Port", this.OscQueryService?.TcpPort.ToString() ?? "");
configTable.AddRow("CalibrationX", $"{this._config.CalibrationX}");
configTable.AddRow("CalibrationY", $"{this._config.CalibrationY}");
configTable.AddRow("Stretch Deadzone", $"{this._config.WalkStretchDeadzone}");
configTable.AddRow("Run Stretch", $"{this._config.RunStretch}");
Table variableTable = new Table();
variableTable.AddColumn("OscVar");
variableTable.AddColumn("Value");
layout["Top"].Update(new FigletText(FigletFont.Parse(Resources.alligatorFont), "OSC Collar").LeftJustified());
layout["Config-Values"].Update(configTable);
layout["Variable-Values"].Update(variableTable);
layout["Position"].Update(new Panel(new Text(GetCoordinateSystem())));
variableTable.AddRow("Status", $"{(_allowMoving ? "enabled" : "disabled")}");
variableTable.AddRow("GPS 1", $"{_gps1.Distance:00.00000}");
variableTable.AddRow("GPS 2", $"{_gps2.Distance:00.00000}");
variableTable.AddRow("GPS 3", $"{_gps3.Distance:00.00000}");
variableTable.AddRow("Position Vector", $"{_unitVectorLeash}");
variableTable.AddRow("Leash Stretch", $"{_leashStretch:0.00000}");
variableTable.AddRow("Movement Vector", $"{_movementVector}");
AnsiConsole.Live(layout).StartAsync(async displayContext =>
{
while (true)
{
variableTable.Rows.Update(0, 1, new Text($"{(_allowMoving ? "enabled" : "disabled")}"));
variableTable.Rows.Update(1, 1, new Text($"{_gps1.Distance:00.00000}"));
variableTable.Rows.Update(2, 1, new Text($"{_gps2.Distance:00.00000}"));
variableTable.Rows.Update(3, 1, new Text($"{_gps3.Distance:00.00000}"));
variableTable.Rows.Update(4, 1, new Text($"{_unitVectorLeash}"));
variableTable.Rows.Update(5, 1, new Text($"{_leashStretch:0.00000}"));
variableTable.Rows.Update(6, 1, new Text($"{_movementVector}"));
layout["Position"].Update(new Panel(new Text(GetCoordinateSystem())));
displayContext.Refresh();
await Task.Delay(100);
}
});
}
private String GetCoordinateSystem()
{
string system = "";
byte width = CoordinateSystemSize;
byte height = CoordinateSystemSize / 2;
int positionX = Convert.ToInt32(Math.Floor(_unitVectorLeash.X * (width / 2.0))) + (width / 2);
int positionY = Convert.ToInt32(-Math.Floor(_unitVectorLeash.Y * (height / 2.0))) + (height / 2);
int movementX = Convert.ToInt32(Math.Floor(_movementVector.X * (width / 2.0))) + (width / 2);
int movementY = Convert.ToInt32(-Math.Floor(_movementVector.Y * (height / 2.0))) + (height / 2);
for (int y = 0; y <= height; y++)
{
for (int x = 0; x <= width; x++)
{
if (x == movementX && y == movementY)
{
system += "x";
continue;
}
if (x == positionX && y == positionY)
{
system += "x";
continue;
}
if (y == height / 2)
{
if (x == width / 2)
system += "+";
else
system += "-";
}
else
{
if (x == width / 2)
system += "|";
else
system += " ";
}
}
if (y != height)
system += "\n";
}
return system;
}
}

View File

@ -1,126 +1,177 @@
using System.Net;
using BuildSoft.OscCore;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using VRC.OSCQuery;
using Extensions = VRC.OSCQuery.Extensions;
namespace VRC_Console;
public partial class OSCCollar
public class OSCCollar
{
private static readonly string ConfigFilePath = Path.Combine(Directory.GetCurrentDirectory(), "config.json");
public static void Main(string[] args)
{
OSCCollar _;
if (File.Exists(ConfigFilePath))
string configFilePath = Path.Combine(Directory.GetCurrentDirectory(), "config.json");
if (File.Exists(configFilePath))
{
Config? config = JsonConvert.DeserializeObject<Config>(File.ReadAllText(ConfigFilePath));
if(config is { })
{
_ = new OSCCollar(config);
}
else
{
_ = new OSCCollar();
}
var jObject = JObject.Parse(File.ReadAllText(configFilePath));
string ip = jObject.GetValue("ip")?.ToObject<string>() ?? "127.0.0.1";
int portSend = jObject.GetValue("portSend")?.ToObject<int>() ?? 9000;
double radius = jObject.GetValue("radius")?.ToObject<double>() ?? 100;
double calibrationX = jObject.GetValue("calibrationX")?.ToObject<double>() ?? 0;
double calibrationY = jObject.GetValue("calibrationY")?.ToObject<double>() ?? 0;
double walkStretchDeadzone = jObject.GetValue("walkStretchDeadzone")?.ToObject<double>() ?? 0.1;
double runStretch = jObject.GetValue("runStretch")?.ToObject<double>() ?? 0.4;
bool skipSetup = jObject.GetValue("skipSetup")?.ToObject<bool>() ?? true;
var _ = new OSCCollar(ip, portSend, radius, calibrationX, calibrationY, walkStretchDeadzone, runStretch, skipSetup);
}else
{
_ = new OSCCollar();
var _ = new OSCCollar();
}
}
private Config _config;
private readonly int _portReceive;
private readonly string _ip;
private readonly int _portReceive, _portSend;
private OSCQueryService? OscQueryService { get; set; }
private OscServer _server = null!;
private OscClient _client = null!;
private OscServer Server { get; init; }
private OscClient Client { get; init; }
private float _leashStretch;
private readonly Vector _unitVectorLeash = new(1, 0);
private Vector _movementVector = new(0, 0);
private bool _allowMoving = true;
private uint _nilSentCount;
private DateTime _lastNilMessageSent = DateTime.UnixEpoch;
private DateTime _lastConsoleOutput = DateTime.UnixEpoch;
private static readonly TimeSpan ConsoleUpdateInterval = TimeSpan.FromMilliseconds(500);
private static readonly TimeSpan UpdateInterval = TimeSpan.FromMilliseconds(10);
private static readonly TimeSpan MessageMinInterval = TimeSpan.FromMilliseconds(400);
private GPS _gps1 = null!, _gps2 = null!, _gps3 = null!;
private readonly double _radius, _walkStretch, _runStretch;
private GPS GPS1 { get; init; }
private GPS GPS2 { get; init; }
private GPS GPS3 { get; init; }
private double CalibrationX { get; init; }
private double CalibrationY { get; init; }
private readonly Queue<ValueTuple<double, double>> _calibrationAverage = new();
private double _constantA, _constantB, _constantC, _constantD, _constantE;
private string _debugValue = "";
private double GPSConstantA { get; init; }
private double GPSConstantB { get; init; }
private double GPSConstantC { get; init; }
private double GPSConstantD { get; init; }
private double GPSConstantE { get; init; }
private OSCCollar(Config config, bool skipSetup = true)
private OSCCollar(string ip = "127.0.0.1", int portSend = 9000, double radius = 100, double calibrationX = 0, double calibrationY = 0, double walkStretch = 0.1, double runStretch = 0.4, bool skipSetup = true)
{
this._config = config;
File.WriteAllText(ConfigFilePath, JsonConvert.SerializeObject(this._config));
this.SetupGPSVars();
this._ip = ip;
this._portReceive = Extensions.GetAvailableUdpPort();
this._portSend = portSend;
this._walkStretch = walkStretch;
this._runStretch = runStretch;
this._radius = radius;
this.GPS1 = new(0, -radius);
this.GPS2 = new(-(radius * 0.866), radius / 2);
this.GPS3 = new(radius * 0.866, radius / 2);
this.CalibrationX = calibrationX;
this.CalibrationY = calibrationY;
this.GPSConstantA = 2 * GPS2.X - 2 * GPS1.X;
this.GPSConstantB = 2 * GPS2.Y - 2 * GPS1.Y;
this.GPSConstantC = Math.Pow(GPS1.X, 2) + Math.Pow(GPS2.X, 2) - Math.Pow(GPS1.Y, 2) + Math.Pow(GPS2.Y, 2);
this.GPSConstantD = 2 * GPS3.X - 2 * GPS2.X;
this.GPSConstantE = Math.Pow(GPS2.X, 2) + Math.Pow(GPS3.X, 2) - Math.Pow(GPS2.Y, 2) + Math.Pow(GPS3.Y, 2);
if (!skipSetup)
{
Console.WriteLine($"OSC Port: {this._portReceive} TCP Port: {this.OscQueryService.TcpPort}");
Console.WriteLine("Position your GPS receivers:");
Console.WriteLine($"GPS 1 x: {_gps1.X} y: {_gps1.Y}");
Console.WriteLine($"GPS 2 x: {_gps2.X} y: {_gps2.Y}");
Console.WriteLine($"GPS 3 x: {_gps3.X} y: {_gps3.Y}");
Console.WriteLine($"Radius of each receiver (sphere): {this._config.Radius * 2}");
Console.WriteLine($"GPS 1 x: {GPS1.X} y: {GPS1.Y}");
Console.WriteLine($"GPS 2 x: {GPS2.X} y: {GPS2.Y}");
Console.WriteLine($"GPS 3 x: {GPS3.X} y: {GPS3.Y}");
Console.WriteLine($"Radius of each receiver (sphere): {radius * 2}");
Console.ReadKey();
}
this._portReceive = Extensions.GetAvailableUdpPort();
this.SetupOSCServer();
this.SetupOSCQuery();
this.SetupConsoleOutput();
}
private OSCCollar(string ip = "127.0.0.1", int portSend = 9000, double radius = 100, double calibrationX = 0,
double calibrationY = 0, double walkStretchDeadzone = 0.1, double runStretch = 0.4,
bool skipSetup = true) : this(new Config()
{
Ip = ip,
PortSend = portSend,
WalkStretchDeadzone = walkStretchDeadzone,
RunStretch = runStretch,
Radius = radius,
CalibrationX = calibrationX,
CalibrationY = calibrationY
}, skipSetup)
{
}
#region Setup
private void SetupGPSVars()
{
this._gps1 = new(0, -this._config.Radius);
this._gps2 = new(-(this._config.Radius * 0.866), this._config.Radius / 2);
this._gps3 = new(this._config.Radius * 0.866, this._config.Radius / 2);
this._constantA = 2 * _gps2.X - 2 * _gps1.X;
this._constantB = 2 * _gps2.Y - 2 * _gps1.Y;
this._constantC = Math.Pow(_gps1.X, 2) + Math.Pow(_gps2.X, 2) - Math.Pow(_gps1.Y, 2) + Math.Pow(_gps2.Y, 2);
this._constantD = 2 * _gps3.X - 2 * _gps2.X;
this._constantE = Math.Pow(_gps2.X, 2) + Math.Pow(_gps3.X, 2) - Math.Pow(_gps2.Y, 2) + Math.Pow(_gps3.Y, 2);
}
private void SetupOSCServer()
{
this._server = new OscServer(this._portReceive);
this._client = new OscClient(this._config.Ip, this._config.PortSend);
this._server.TryAddMethod("/avatar/parameters/GPS1", GPS1Handle);
this._server.TryAddMethod("/avatar/parameters/GPS2", GPS2Handle);
this._server.TryAddMethod("/avatar/parameters/GPS3", GPS3Handle);
this._server.TryAddMethod("/avatar/parameters/Leash_Stretch", CollarStretchHandle);
this._server.TryAddMethod("/avatar/parameters/Leash_Toggle", AllowMovingHandle);
this._server.Start();
this.Server = new OscServer(this._portReceive);
this.Client = new OscClient(this._ip, this._portSend);
this.Server.TryAddMethod("/avatar/parameters/GPS1", GPS1Handle);
this.Server.TryAddMethod("/avatar/parameters/GPS2", GPS2Handle);
this.Server.TryAddMethod("/avatar/parameters/GPS3", GPS3Handle);
this.Server.TryAddMethod("/avatar/parameters/Leash_Stretch", CollarStretchHandle);
this.Server.TryAddMethod("/avatar/parameters/Leash_Toggle", AllowMovingHandle);
this.Server.Start();
Thread runningThread = new Thread(RunningThread);
runningThread.Start();
this.SetupOSCQuery();
}
private void PrintOutput()
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"OSC Collar - Status: {(_allowMoving ? "enabled" : "disabled")} IP: {_ip} Send-OSC: {_portSend} Receive-OSC: {_portReceive} OSC-HTTP: {this.OscQueryService?.TcpPort}");
Console.WriteLine("==============================");
Console.WriteLine($"GPS 1:................{GPS1.Distance:00.00000}");
Console.WriteLine($"GPS 2:................{GPS2.Distance:00.00000}");
Console.WriteLine($"GPS 3:................{GPS3.Distance:00.00000}");
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"Position Vector:......{_unitVectorLeash}");
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"Stretch:..............{_leashStretch:0.00000}");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Movement Vector:......{_movementVector}");
Console.ForegroundColor = ConsoleColor.Gray;
ValueTuple<double, double> calibrationValues = GetCalibrationValues();
Console.WriteLine($"Calibration (x y): ...({calibrationValues.Item1:' '00.0000;'-'00.0000} {calibrationValues.Item2:' '00.0000;'-'00.0000})");
Console.ForegroundColor = ConsoleColor.White;
string nilString = $"/input nil {_nilSentCount}";
Console.SetCursorPosition(Console.WindowWidth - nilString.Length - 1, 0);
Console.Write(nilString);
Console.ForegroundColor = ConsoleColor.DarkGray;
if (Console.WindowHeight < 13)
return;
Console.SetCursorPosition(43, 5);
Console.WriteLine("----------+----------");
for (int i = 1; i < 10; i++)
{
if(i == 5)
continue;
Console.SetCursorPosition(53,i);
Console.Write("|");
}
const int centerX = 53;
const int centerY = 5;
int positionX = Convert.ToInt32(Math.Floor(_unitVectorLeash.X * 10));
int positionY = Convert.ToInt32(-Math.Floor(_unitVectorLeash.Y * 4));
double positionPrecision = (_unitVectorLeash.Y * 10) % 10;
char positionPrecisionChar = positionPrecision < 3 ? '.' : positionPrecision > 7 ? '\'' : 'x';
Console.SetCursorPosition(centerX + positionX, centerY + positionY);
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write(positionPrecisionChar);
int movementX = Convert.ToInt32(Math.Floor(_movementVector.X * 10));
int movementY = Convert.ToInt32(-Math.Floor(_movementVector.Y * 4));
double movementPrecision = (_movementVector.Y * 10) % 10;
char movementPrecisionChar = movementPrecision < 3 ? '.' : movementPrecision > 7 ? '\'' : 'x';
Console.SetCursorPosition(centerX + movementX, centerY + movementY);
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(movementPrecisionChar);
Console.SetCursorPosition(Console.WindowWidth - _debugValue.Length - 1, Console.WindowHeight - 2);
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(_debugValue);
}
private void SetupOSCQuery()
{
var tcpPort = Extensions.GetAvailableTcpPort();
this.OscQueryService = new OSCQueryServiceBuilder()
.WithHostIP(IPAddress.Parse(this._config.Ip))
.WithOscIP(IPAddress.Parse(this._config.Ip))
.WithHostIP(IPAddress.Parse(this._ip))
.WithOscIP(IPAddress.Parse(this._ip))
.WithDiscovery(new MeaModDiscovery())
.WithTcpPort(tcpPort)
.WithUdpPort(this._portReceive)
@ -136,7 +187,6 @@ public partial class OSCCollar
this.OscQueryService.AddEndpoint<bool>("/avatar/parameters/Leash_Toggle", Attributes.AccessValues.WriteOnly);
this.OscQueryService.RefreshServices();
}
#endregion
#region Handle OSC-Messages
private void AllowMovingHandle(OscMessageValues messageValues)
@ -146,17 +196,17 @@ public partial class OSCCollar
private void GPS1Handle(OscMessageValues messageValues)
{
this._gps1.Distance = messageValues.ReadFloatElement(0) * this._config.Radius;
this.GPS1.Distance = messageValues.ReadFloatElement(0) * _radius;
}
private void GPS2Handle(OscMessageValues messageValues)
{
this._gps2.Distance = messageValues.ReadFloatElement(0) * this._config.Radius;
this.GPS2.Distance = messageValues.ReadFloatElement(0) * _radius;
}
private void GPS3Handle(OscMessageValues messageValues)
{
this._gps3.Distance = messageValues.ReadFloatElement(0) * this._config.Radius;
this.GPS3.Distance = messageValues.ReadFloatElement(0) * _radius;
}
private void CollarStretchHandle(OscMessageValues messageValues)
@ -167,25 +217,25 @@ public partial class OSCCollar
private void CalculatePositionFromGPS()
{
double gpsFactorA = Math.Pow(_gps1.Distance, 2) - Math.Pow(_gps2.Distance, 2) - _constantC;
double gpsFactorB = Math.Pow(_gps2.Distance, 2) - Math.Pow(_gps3.Distance, 2) - _constantE;
double gpsFactorA = Math.Pow(GPS1.Distance, 2) - Math.Pow(GPS2.Distance, 2) - GPSConstantC;
double gpsFactorB = Math.Pow(GPS2.Distance, 2) - Math.Pow(GPS3.Distance, 2) - GPSConstantE;
double gpsPosX = (gpsFactorB / _constantD);
double gpsPosY = (gpsFactorA * _constantD - _constantA * gpsFactorB) / (_constantB * _constantD);
double gpsPosX = (gpsFactorB / GPSConstantD);
double gpsPosY = (gpsFactorA * GPSConstantD - GPSConstantA * gpsFactorB) / (GPSConstantB * GPSConstantD);
AddCalibrationValues(gpsPosX, gpsPosY);
double posX = gpsPosX + this._config.CalibrationX;
double posY = gpsPosY + this._config.CalibrationY;
double posX = gpsPosX + CalibrationX;
double posY = gpsPosY + CalibrationY;
double inverseLength = 1 / Math.Sqrt(Math.Pow(posX, 2) + Math.Pow(posY, 2));
_unitVectorLeash.X = posX * inverseLength * -1;
_unitVectorLeash.Y = posY * inverseLength;
if (_leashStretch < this._config.WalkStretchDeadzone) //Below Deadzone
if (_leashStretch < _walkStretch) //Below Deadzone
_movementVector = new();
else if (_leashStretch < this._config.RunStretch) //Walk
else if (_leashStretch < _runStretch) //Walk
_movementVector = _unitVectorLeash.MultipliedWith(0.5);
else //Run
_movementVector = _unitVectorLeash.MultipliedWith(1);
@ -195,17 +245,24 @@ public partial class OSCCollar
{
while (true)
{
this._server.Update();
this.Server.Update();
CalculatePositionFromGPS();
if (_lastNilMessageSent.Add(MessageMinInterval) < DateTime.Now)
{
this._client.Send("/input/Vertical", 0f);
this._client.Send("/input/Horizontal", 0f);
this.Client.Send("/input/Vertical", 0f);
this.Client.Send("/input/Horizontal", 0f);
this._lastNilMessageSent = DateTime.Now;
_nilSentCount++;
}else if (_allowMoving)
{
this._client.Send("/input/Vertical", Convert.ToSingle(_movementVector.Y));
this._client.Send("/input/Horizontal", Convert.ToSingle(_movementVector.X));
this.Client.Send("/input/Vertical", Convert.ToSingle(_movementVector.Y));
this.Client.Send("/input/Horizontal", Convert.ToSingle(_movementVector.X));
}
if (_lastConsoleOutput.Add(ConsoleUpdateInterval) < DateTime.Now)
{
PrintOutput();
_lastConsoleOutput = DateTime.Now;
}
Thread.Sleep(UpdateInterval);

View File

@ -13,7 +13,6 @@
<PackageReference Include="MeaMod.DNS" Version="1.0.70" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Spectre.Console" Version="0.48.1-preview.0.7" />
</ItemGroup>
<ItemGroup>
@ -22,25 +21,4 @@
</Reference>
</ItemGroup>
<ItemGroup>
<None Update="Alligator.flf">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
</Project>

View File

@ -1,104 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace VRC_Console {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VRC_Console.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to flf2a$ 7 7 26 32 3
///Alligator by Simon Bradley &lt;syb3@aber.ac.uk&gt;
///17th June, 1994
///
///$ $@
///$ $@
///$ $@
///$ $@
///$ $@
///$ $@
///$ $@@
/// :::$@
/// :+:$ @
/// +:+$ @
/// +#+$ @
/// +#+$ @
/// $ $ @
///###$ @@
/// ::: :::$@
/// :+: :+:$ @
/// $ $ @
/// $ $ @
/// $ $ @
/// $ $ @
///$ $ @@
/// ::: :::$ @
/// :+: :+:$ @
/// +:+:+:+:+:+:+:+$@
/// +#+ +:+$ @
///+#+#+#+#+#+#+#+$ @
/// #+# #+#$ @
/// ### ###$ @@
/// :::$ @
/// [rest of string was truncated]&quot;;.
/// </summary>
internal static string alligatorFont {
get {
return ResourceManager.GetString("alligatorFont", resourceCulture);
}
}
}
}

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="alligatorFont" type="System.Resources.ResXFileRef">
<value>Alligator.flf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral</value>
</data>
</root>

View File

@ -1,4 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005Cvrc_002Doscquery_002Dlib_005Cvrc_002Doscquery_002Dlib_005Cbin_005CDebug_005Cnet6_002E0_005Cvrc_002Doscquery_002Dlib_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=OSCCollar_002FResources/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005Cvrc_002Doscquery_002Dlib_005Cvrc_002Doscquery_002Dlib_005Cbin_005CDebug_005Cnet6_002E0_005Cvrc_002Doscquery_002Dlib_002Edll/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>