LusidOSC v1.1 -- STILL IN PROGRESS...
|
parameter |
OSC type |
notes |
|
u |
string |
uniqueID; an object's ID written in hex format. e.x., "0x123456". A generated ID can be given to non-ID'd things (such as fingers). |
|
x, y, z |
int32 |
3D position; represented as tenths of millimeters with (0,0,0) at the center. The axis are arranged with positive X to the right, positive Y to the top, and positive Z pointed upwards. |
|
a, b, c |
float32 |
angle around the x, y, and z axis accordingly; range is [0, 2PI]. |
|
e |
string |
short human-readable name of object type |
| t | int32 | type of data (see: Data Types) |
| d | string | data; any string, or null string if no data. Commas are the suggested delimiter if multiple values are being sent as string. |
|
f |
int32 |
frame number |
|
s |
int32 |
seconds since midnight Jan. 1, 1970 (UTC); a.k.a, Unix time. |
|
m |
int32 |
microseconds (decimal part of seconds only) |
| type [t] | example data [d] | default data | description |
| 0 | "anything,you,want" | "" | Ad-hoc data of any kind useful for working with emerging interface technologies. Eventually this data should be formalized as specific data types in subsequent versions of LusidOSC. |
| ? | "tm" | "" | OpenTagDB Family Name (see: http://www.opentagdb.com ). OpenTagDB will allow for unique mappings between an object's ID and data stored online. |
| ? | "0xFFCC99" | "" | Object RGB color (specified in hex) |
| ? | "true" | "false" | Object is a finger |
| ? | "true" | "false" | Object ID was assigned on-the-fly/randomly |
| ? | "20" | "" | Object radius in mm from (x,y,z) center. |
| ? | "-1,-3,17,28,12,-5" | "" | Object 2D shape polygon as (x,y) point pairs relative to (x,y,z) center. |
| ? | "523" | "-1" | Finger Pressure (out of 1000). |
| ? | "12,7,4,13,19,2" | "" | Object 2D skeleton as (x,y) point pairs. |
| ? | "12,-7,2" | "0,0,0" | Position velocity in mm/second for (x, y, z). |
| ? | "0.231,0.0,-0.117" | "0,0,0" | Rotation velocity in radians/second about (x, y, z) axis. |
| ? | "0.57" | "1.0" | Certainty factor (applied to position, id, rotation, etc?) |
| A LOT OF WORK LEFT TO GO HERE TO DEFINE INITIAL DATA TYPES.... | |||
|
do once at startup: 1. initialize OSC Sender to send packets to HOST, PORT. each time new object data is ready to send: 1. create a new OSC bundle. 2. create and add the "fseq" message to the bundle. 3. create the "alive" message, but do not add it yet. 4. for each object being tracked: 4.1. add the object's uniqueID to the "alive" message. 4.2. create and add a "set" message for the object to the bundle. 5. add the "alive" message to the bundle. 6. send the bundle |
|
// // Released under GNU GPLv2; this program is free software. // Copyright (c) 2008, Adam Kumpf // Derived from openframeworks.cc code by Matthias Dorfelt. // Based on classes by Martin Kaltenbrunner for reactivision.sourceforge.net. // Built on top of Open Sound Control (OSC). // OscSender sender = new OscSender(); // create a new OSC sender void setupOnce(){ sender.setup(HOST, PORT); // setup the sender for a host and port. } void objectDataUpdated(){ OscBundle oscBundle = new OscBundle(); // create a new OSC bundle OscMessage fseqMessage = new OscMessage(); // create a new OSC message fseqMessage.setAddress("/lusid/1.0"); fseqMessage.addStringArg("fseq"); fseqMessage.addIntArg(frameNumber); // frameNumber :: Int32 fseqMessage.addIntArg(seconds); // seconds since 1970 :: Int32 fseqMessage.addIntArg(microseconds); // microseconds :: Int32 oscBundle.addMessage(fseqMessage); // add "fseq" message to oscBundle OscMessage aliveMessage = new OscMessage(); // create a new OSC message aliveMessage.setAddress("/lusid/1.0"); aliveMessage.addStringArg("alive"); OscMessage m = new OscMessage(); // create a reusable OSC message for each object sensed by tracking system { m.clear(); // start with a new message m.setAddress("/lusid/1.0"); m.addStringArg("set"); m.addStringArg(uniqueIDString); // unique ID :: String (in hex format) m.addIntArg(objectX); // X Pos :: Int32 m.addIntArg(objectY); // Y Pos :: Int32 m.addIntArg(0); // Z Pos :: Int32 m.addFloatArg(0); // Angle around X axis :: Float32 m.addFloatArg(0); // Angle around Y axis :: Float32 m.addFloatArg(objectAngleRadians); // Angle around Z axis :: Float32 m.addStringArg("tempTracker"); // Name of Data Encoding :: String m.addStringArg("120,cold,roundObj"); // Data :: String oscBundle.addMessage(m); // add "set" message to the oscBundle aliveMessage.addStringArg(uniqueIDString); // add the ID to the "alive" list } oscBundle.addMessage(aliveMessage); // add "alive" message to oscBundle sender.sendBundle(oscBundle); // send the oscBundle on its way! frameNumber++; // increase frame for next time. } |
|
do once at startup: 1. initialize OSC Receiver to listen for packets on PORT. each time a new OSC message is available to read: 1. check to see if it has the correct profile address (/lusid/1.0) 1.1 check to see if it is a "set" message 1.1.1 if frame is out of order, immediately return 1.1.2 update object parameters based on message data 1.1.3 if this is the first time we've seen this object 1.1.3.1 add the object to our local objectList 1.1.3.2 notify event listeners of new object 1.1.4 else (we have seen this object before) 1.1.4.1 notify event listeners that object changed 1.2 check to see if it is an "alive" message 1.2.1 if frame is out of order, immediately return 1.2.2 for each uniqueID in the "alive" message 1.2.2.1 add the uniqueID to a list for later 1.2.3 for each object in objectList (we've seen via "set" messages) 1.2.3.1 if object was not included in the "alive" list 1.2.3.1.1 notify listeners of object removed 1.2.3.1.2 remove the object from the objectList 1.3 check to see if it is a "fseq" message 1.3.1 if frame is older than previous, immediately return 1.2.2 update frame timing information |
|
// // Released under GNU GPLv2; this program is free software. // Copyright (c) 2008, Adam Kumpf // Derived from ofxTuioClient.h for openframeworks.cc by Matthias Dorfelt. // Based on classes by Martin Kaltenbrunner for reactivision.sourceforge.net. // Built on top of Open Sound Control (OSC). // int lastFrame = 0; int lastFrameSeconds = 0; int lastFrameMicroSec = 0; List<LusidObj> listOfLusidObj = new List<LusidObj>(); OscReceiver receiver = new OscReceiver(); // create a new OSC receiver void setupOnce(){ receiver.setup(PORT); // setup the receiver for a host and port. } void oscMessageReceived(OscMessage m){ if(m.getAddress().equals("/lusid/1.0")){ // handle a SET message if(m.getArgAsString(0).equals("set")){ if(currentFrame < lastFrame){ return; // UDP packet was old, don't update anything }else{ // let's update our parameters from the object. String uniqueID = m.getArgAsString(1); int x = m.getArgAsInt32(2); int y = m.getArgAsInt32(3); int z = m.getArgAsInt32(4); float a = m.getArgAsFloat(5); float b = m.getArgAsFloat(6); float c = m.getArgAsFloat(7); String enc = m.getArgAsString(8); // encoding String data = m.getArgAsString(9); // additional data LusidObj lusidObj = listOfLusidObj.getObjectByID(uniqueID); if(lusidObj == null){ // this is the first time we've seen this object. lusidObj = new LusidObj(uniqueID, x, y, z, a, b, c, enc, data); listOfLusidObj.add(lusidObj); // add the new object to the list. LusidOSCEvents.notifyDown(this, uniqueID, x, y, z, a, b, c, enc, data); }else{ // we've seen this object before, it's just being updated/moved. lusidObj.update(x, y, z, a, b, c, enc, data); LusidOSCEvents.notifyMove(this, uniqueID, x, y, z, a, b, c, enc, data); } } } // handle an ALIVE message if(m.getArgAsString(0).equals("alive")){ if(currentFrame < lastFrame){ return; // UDP packet was old, don't update anything }else{ List<String> aliveObjectIDList = new List<String>(); for(int i=0; i<m.getNumArgs(); i++){ String uniqueID = m.getArgAsString(1); aliveObjectIDList.add(uniqueID); } for(int i=listOfLusidObj.length-1; i>=0; i--){ // start at the end of the list and walk backwards... // we do this since we may delete elements and we don't // want to skip anything or try a bad index. LusidObj lusidObj = listOfLusidObj.get(i); if(aliveObjectIDList.doesntContain(lusidObj.uniqueID)){ // we have an object that is no longer alive. // remove it and send an event. String uniqueID = lusidObj.uniqueID; int x = lusidObj.x; int y = lusidObj.y; int z = lusidObj.z; float a = lusidObj.a; float b = lusidObj.b; float c = lusidObj.c; String enc = lusidObj.enc; // encoding String data = lusidObj.data; // additional data LusidOSCEvents.notifyUp(this, uniqueID, x, y, z, a, b, c, enc, data); listOfLusidObj.remove(i); // now remove it from our list. } } } } // handle a FSEQ message if(m.getArgAsString(0).equals("fseq")){ // first, save last frame before we overwrite it. // this is helpful for derived timing calculations. lastFrame = frame; lastFrameSeconds = frameSeconds; lastFrameMicroSec = frameMicroSec; // now update things to the new information. frame = m.getArgAsInt32(1); frameSeconds = m.getArgAsInt32(2); frameMicroSec = m.getArgAsInt32(3); } } } |