Skip to content

Commit

Permalink
bidirectional connections now possible
Browse files Browse the repository at this point in the history
  • Loading branch information
IASpaceAdmin committed Apr 27, 2021
1 parent ee410dc commit eeaea52
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 76 deletions.
Binary file modified lib/x64/SharpOSC.dll
Binary file not shown.
Binary file modified lib/x86/SharpOSC.dll
Binary file not shown.
17 changes: 11 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
NatNetThree2OSC 8.3.0
NatNetThree2OSC 8.4.0
===================================


Expand All @@ -23,15 +23,16 @@ Using The Application
-----------------

Usage: NatNetThree2OSC
* **--localIP** Required. IP address of this machine.
* **--localIP** Required. IP address of this machine.
* **--motiveIP** Required. IP address of the machine Motive is running on.
* **--oscSendIP** Required. IP address of the machine OSC data is sent to.
* **--oscSendIP** Required. IP-address or URL of the machine OSC data is sent to.
* **--oscSendPort** Required. receiving port of the machine OSC data is sent to.
* **--oscCtrlPort** (Default: 65111) local listening port to refetch descriptions.
* **--oscMode** (Default: max) OSC format (max, isadora, touch, sparck, ambi)
* **--mulitCastIP** (Default: 239.255.42.99) Multicast IP Motive is sending on.
* **--motiveDataPort** (Default: 1511) Motives data port
* **--motiveCmdPort** (Default: 1510) Motives command port
* **--oscSendPort** Required. listening port of the machine OSC data is sent to.
* **--oscCtrlPort** (Default: 65111) listening port of this service to trigger Motive.
* **--oscMode** (Default: max) OSC format (max, isadora, touch, sparck)
* **--dataStreamInfo** (Default: 0=off) sends each specified [ms] streaminfo message to the console.
* **--sendSkeletons** (Default: false) send skeleton data
* **--sendMarkerInfo** (Default: false) send marker info (position data)
* **--yup2zup** (Default: false) transform y-up to z-up
Expand Down Expand Up @@ -102,6 +103,8 @@ upon streaming, the following messages are sent depending on the OSC Mode

+ /icst/ambi/sourceindex/xyz \<rigidbodyID> \<x> \<y> \<z>

in this mode **no** frame messages are sent.

#### SPARCK: OSC MODE = sparck

the addresses for sparck mode are structured in a way to process them quickly in sparck and are therefore not very human readable.
Expand Down Expand Up @@ -173,6 +176,8 @@ Open the NatNetSamples inside the /Samples - folder and build NatNetThree2OSC Pr

[CommandLine Parser Library](https://github.com/commandlineparser/commandline). How install the package got [here](https://github.com/commandlineparser/commandline/wiki/Getting-Started).

[SharpOSC](https://github.com/tecartlab/SharpOSC/releases/tag/v0.1.2.0). This is a fork from the official repo with a new class that allows "bidirectional" udp connectîons.

Contribute
----------

Expand Down
175 changes: 105 additions & 70 deletions source/NatNetThree2OSC/NatNetThree2OSC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using System.Threading;

using NatNetML;

Expand Down Expand Up @@ -62,7 +63,7 @@ class Options
[Option("motiveIP", Required = true, HelpText = "IP address of the machine Motive is running on.")]
public string mStrServerIP { get; set; }

[Option("oscSendIP", Required = true, HelpText = "IP address of the machine OSC data is sent to.")]
[Option("oscSendIP", Required = true, HelpText = "IP address or URL of the machine OSC data is sent to.")]
public string mStrOscSendIP { get; set; }

[Option("multiCastIP", Required = false, Default = "239.255.42.99", HelpText = "Multicast IP Motive is sending on.")]
Expand Down Expand Up @@ -92,6 +93,9 @@ class Options
[Option("yup2zup", Required = false, Default = false, HelpText = "transform y-up to z-up")]
public bool myUp2zUp { get; set; }

[Option("dataStreamInfo", Required = false, Default = 0, HelpText = "sends streaminfo message to the console as feedback")]
public int mDataStreamInfo { get; set; }

[Option("leftHanded", Required = false, Default = false, HelpText = "transform right handed to left handed coordinate system")]
public bool myleftHanded { get; set; }

Expand Down Expand Up @@ -135,6 +139,10 @@ public class NatNetThree2OSC
private static bool mSendMarkerInfo = false;
private static bool mVerbose = false;
private static bool mBundled = false;
private static int mDataStreamInfo = 0;

private static Int16 mProxyHS_data = 0;
private static Int16 mProxyHS_ctrl = 0;

private static bool mMatrix = false;
private static bool mInvMatrix = false;
Expand All @@ -155,8 +163,11 @@ public class NatNetThree2OSC
private static bool mAssetChanged = false;

// create an OSC Udp sender

private static UDPSender OSCsender;
private static IPAddress ipAddress;

private static UDProxy OSCProxy;

private static byte[] heartbeat_sequence = new byte[] { 47, 104, 98, 0, 44, 0, 0, 0};

static void Main(string[] args)
{
Expand All @@ -181,6 +192,17 @@ private static void HandleParseError(IEnumerable<Error> errs)
Console.WriteLine("Parser Fail");
}

public static void StreamInfoThread()
{
while (true)
{
Console.WriteLine("streaminfo {0} {1}", mProxyHS_data, mProxyHS_ctrl);
mProxyHS_data = 0;
mProxyHS_ctrl = 0;
Thread.Sleep(mDataStreamInfo);
}
}

static void Run(Options opts)
{
mOscModeMax = (opts.mOscMode.Contains("max")) ? true : false;
Expand All @@ -195,12 +217,13 @@ static void Run(Options opts)
mSendMarkerInfo = opts.mySendMarkerInfo;
mVerbose = opts.mVerbose;
mBundled = opts.mBundled;
mDataStreamInfo = opts.mDataStreamInfo;

mMatrix = opts.mMatrix;
mInvMatrix = opts.mInvMatrix;

Console.WriteLine("\n---- NatNetThree2OSC v. 8.2.0 ----");
Console.WriteLine("\n---- 20210212 by maybites ----");
Console.WriteLine("\n---- NatNetThree2OSC v. 8.4.0 ----");
Console.WriteLine("\n---- 20210426 by maybites ----");

Console.WriteLine("\nNatNetThree2OSC");
Console.WriteLine("\t oscSendIP = \t\t({0:N3})", opts.mStrOscSendIP);
Expand All @@ -219,55 +242,17 @@ static void Run(Options opts)
Console.WriteLine("\t multiCastIP = \t\t({0:N3})", opts.mStrMultiCastIP);
Console.WriteLine("\t motiveDataPort = \t({0})", opts.mIntMotiveDataPort);
Console.WriteLine("\t motiveCmdPort = \t({0})", opts.mIntMotiveCmdPort);
Console.WriteLine("\t dataStreamInfo = \t\t[{0}]", opts.mDataStreamInfo);
Console.WriteLine("\t verbose = \t\t[{0}]", opts.mVerbose);

IPAddress ipAddress;

// parse the ip address
if (IPAddress.TryParse(opts.mStrOscSendIP, out ipAddress) == false)
{
Console.WriteLine("\nInvalid IP address, {0}", opts.mStrOscSendIP);

return;
}

// intantiate an OSC udp sender
OSCsender = new UDPSender(ipAddress.ToString(), opts.mIntOscSendPort);

//OSCsender.Connect();

Console.WriteLine("\nNatNetThree2OSC managed client application starting...\n");
/* [NatNet] Initialize client object and connect to the server */
connectToServer(opts); // Initialize a NatNetClient object and connect to a server.

Console.WriteLine("============================ SERVER DESCRIPTOR ================================\n");
/* [NatNet] Confirming Server Connection. Instantiate the server descriptor object and obtain the server description. */
bool connectionConfirmed = fetchServerDescriptor(); // To confirm connection, request server description data

if (connectionConfirmed) // Once the connection is confirmed.
{
Console.WriteLine("============================= DATA DESCRIPTOR =================================\n");
Console.WriteLine("Now Fetching the Data Descriptor.\n");
fetchDataDescriptor(); //Fetch and parse data descriptor

Console.WriteLine("============================= FRAME OF DATA ===================================\n");
Console.WriteLine("Now Fetching the Frame Data\n");

/* [NatNet] Assigning a event handler function for fetching frame data each time a frame is received */
mNatNet.OnFrameReady += new NatNetML.FrameReadyEventHandler(fetchFrameData);

Console.WriteLine("Success: Data Port Connected \n");

Console.WriteLine("======================== STREAMING IN (PRESS ESC TO EXIT) =====================\n");
}

// The cabllback function for receiveing OSC messages
SharpOSC.HandleOscPacket callback = delegate (SharpOSC.OscPacket packet)
SharpOSC.ProxyOscPacket callback = delegate (SharpOSC.OscPacket packet)
{
mProxyHS_ctrl = 1;
var messageReceived = (SharpOSC.OscMessage)packet;
if (messageReceived != null && messageReceived.Address.Equals(value: "/motive/command"))
{
if(messageReceived.Arguments.Count > 0 && messageReceived.Arguments.IndexOf("refetch") != -1)
if (messageReceived.Arguments.Count > 0 && messageReceived.Arguments.IndexOf("refetch") != -1)
{
Console.WriteLine("Received Refetching Command.");
mAssetChanged = true;
Expand Down Expand Up @@ -373,7 +358,56 @@ static void Run(Options opts)
};


var listener = new SharpOSC.UDPListener(opts.mIntOscCtrlPort, callback);
try
{
Uri myUri = new Uri("http://" + opts.mStrOscSendIP);
ipAddress = Dns.GetHostAddresses(myUri.Host)[0];
}
catch (Exception)
{
if (IPAddress.TryParse(opts.mStrOscSendIP, out ipAddress) == false)
{
Console.WriteLine("\nInvalid IP or URL, {0}", opts.mStrOscSendIP);
return;
}
}

// intantiate an OSC udp sender
Console.WriteLine("\nStarting OSC sender to {0} on port {1}", ipAddress.ToString(), opts.mIntOscSendPort);
OSCProxy = new UDProxy(opts.mStrOscSendIP, opts.mIntOscSendPort, opts.mIntOscCtrlPort, callback);

if (mDataStreamInfo > 0)
{
var th = new Thread(StreamInfoThread);
th.Start();
Console.WriteLine("StreamInfoThread started");
Console.WriteLine("streaminfo 0 0");
}

Console.WriteLine("\nNatNetThree2OSC managed client application starting...\n");
/* [NatNet] Initialize client object and connect to the server */
connectToServer(opts); // Initialize a NatNetClient object and connect to a server.

Console.WriteLine("============================ SERVER DESCRIPTOR ================================\n");
/* [NatNet] Confirming Server Connection. Instantiate the server descriptor object and obtain the server description. */
bool connectionConfirmed = fetchServerDescriptor(); // To confirm connection, request server description data

if (connectionConfirmed) // Once the connection is confirmed.
{
Console.WriteLine("============================= DATA DESCRIPTOR =================================\n");
Console.WriteLine("Now Fetching the Data Descriptor.\n");
fetchDataDescriptor(); //Fetch and parse data descriptor

Console.WriteLine("============================= FRAME OF DATA ===================================\n");
Console.WriteLine("Now Fetching the Frame Data\n");

/* [NatNet] Assigning a event handler function for fetching frame data each time a frame is received */
mNatNet.OnFrameReady += new NatNetML.FrameReadyEventHandler(fetchFrameData);

Console.WriteLine("Success: Data Port Connected \n");

Console.WriteLine("======================== STREAMING IN (PRESS ESC TO EXIT) =====================\n");
}


while (true)
Expand Down Expand Up @@ -412,7 +446,7 @@ static void Run(Options opts)
mNatNet.Disconnect();
//listener.Close();

OSCsender.Close();
OSCProxy.Close();
}

/// <summary>
Expand Down Expand Up @@ -502,15 +536,16 @@ This conditional statement is included in order to simplify the program output *
if (mBundled)
{
var bundled = new OscBundle((ulong)(data.fTimestamp * 1000), bundle.ToArray());
OSCsender.Send(bundled);
OSCProxy.Send(bundled);
}
else
{
for (int i = 0; i < bundle.Count; i++)
{
OSCsender.Send(bundle[i]);
OSCProxy.Send(bundle[i]);
}
}
mProxyHS_data = 1;
}

static void processFrameData(NatNetML.FrameOfMocapData data, List<OscMessage> bundle)
Expand Down Expand Up @@ -952,27 +987,27 @@ static void fetchDataDescriptor()
static void fetchOptions()
{
var message = new OscMessage("/script/oscModeSparck", mOscModeSparck);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/oscModeMax", mOscModeMax);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/oscModeIsaodra", mOscModeIsa);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/oscModeTouch", mOscModeTouch);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/leftHanded", mleftHanded);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/zUpAxis", mUpAxis);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/sendSkeletons", mSendSkeletons);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/sendMarkerInfo", mSendMarkerInfo);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/bundled", mBundled);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/calcMatrix", mMatrix);
OSCsender.Send(message);
OSCProxy.Send(message);
message = new OscMessage("/script/calcInvMatrix", mInvMatrix);
OSCsender.Send(message);
OSCProxy.Send(message);
}

static void parseDataDescriptor(List<NatNetML.DataDescriptor> description)
Expand All @@ -983,7 +1018,7 @@ static void parseDataDescriptor(List<NatNetML.DataDescriptor> description)
Console.WriteLine("Total {0} data sets in the capture:", numDataSet);

var message = new OscMessage("/motive/update/start", 1);
OSCsender.Send(message);
OSCProxy.Send(message);

for (int i = 0; i < numDataSet; ++i)
{
Expand All @@ -995,7 +1030,7 @@ static void parseDataDescriptor(List<NatNetML.DataDescriptor> description)
NatNetML.MarkerSet mkset = (NatNetML.MarkerSet)description[i];
Console.WriteLine("\tMarkerSet ({0})", mkset.Name);
message = new OscMessage("/motive/markerset/id", mkset.Name);
OSCsender.Send(message);
OSCProxy.Send(message);

break;

Expand All @@ -1004,7 +1039,7 @@ static void parseDataDescriptor(List<NatNetML.DataDescriptor> description)
Console.WriteLine("\tRigidBody ({0})", rb.Name);

message = new OscMessage("/motive/rigidbody/id", rb.Name, rb.ID);
OSCsender.Send(message);
OSCProxy.Send(message);

// Saving Rigid Body Descriptions
mRigidBodies.Add(rb);
Expand All @@ -1016,7 +1051,7 @@ static void parseDataDescriptor(List<NatNetML.DataDescriptor> description)
Console.WriteLine("\tSkeleton ({0}), Bones:", skl.Name);

message = new OscMessage("/motive/skeleton/id", skl.Name, skl.ID);
OSCsender.Send(message);
OSCProxy.Send(message);

//Saving Skeleton Descriptions
mSkeletons.Add(skl);
Expand All @@ -1025,7 +1060,7 @@ static void parseDataDescriptor(List<NatNetML.DataDescriptor> description)
for (int j = 0; j < skl.nRigidBodies; j++)
{
message = new OscMessage("/motive/skeleton/id/bone", skl.Name, skl.RigidBodies[j].ID, skl.RigidBodies[j].Name);
OSCsender.Send(message);
OSCProxy.Send(message);

Console.WriteLine("\t\t{0}. {1}", skl.RigidBodies[j].ID, skl.RigidBodies[j].Name);
int uniqueID = skl.ID * 1000 + skl.RigidBodies[j].ID;
Expand All @@ -1040,15 +1075,15 @@ static void parseDataDescriptor(List<NatNetML.DataDescriptor> description)
Console.WriteLine("\tForcePlate ({0})", fp.Serial);

message = new OscMessage("/motive/forceplate/id", fp.Serial);
OSCsender.Send(message);
OSCProxy.Send(message);

// Saving Force Plate Channel Names
mForcePlates.Add(fp);

for (int j = 0; j < fp.ChannelCount; j++)
{
message = new OscMessage("/motive/forceplate/id/channel", fp.Serial, j + 1, fp.ChannelNames[j]);
OSCsender.Send(message);
OSCProxy.Send(message);

Console.WriteLine("\t\tChannel {0}: {1}", j + 1, fp.ChannelNames[j]);
}
Expand All @@ -1064,7 +1099,7 @@ static void parseDataDescriptor(List<NatNetML.DataDescriptor> description)
}
}
message = new OscMessage("/motive/update/end", 1);
OSCsender.Send(message);
OSCProxy.Send(message);

}

Expand Down

0 comments on commit eeaea52

Please sign in to comment.