Tuio client with reactivision

Swiftlikeninja's picture

Hello everybody, I have been messing with the TuioClient plugin with quartz running on leopard using the reactivision program for fiducial tracking and ran into a snag. If I have one tracker set up to use the xpos, it works without a hitch if I'm only using one tracker. How can I have certain symbols do different things, the reactivision comes with 200+ built in symbols but depending on the order presented then currently that dictates the function. I know the tuioclient has a structure for the c_id but how can I have it do a function based on that and not the initial structure order without having 200+ macro patches set to enable if c_id string matches. I am not a javascripter so if this is the route needed I will need some more assistant but any help world be greatly appreciated.

Forgive me if I'm not making any since just ask and I will clarify

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

dust's picture
Re: Tuio client with reactivision

a couple things you can do. i think the c_id is very important. honestly i have not used tuio much fiducially but i am building a table for the discovery museum as well as at home so i can do more experiments with augmentation later.

im not sure i understand the question entirely ? you want to take care of all 200 patterns in one shot ? (without making structures for all)

there are limitations to using an iterator to take of everything in one shot. there will be times when you are going to want to work on an index individually but lets take care of them all in one shot.

snow leopard lets you make an output on an iterator now so im thinking your really going to want snow leopard.

so make structure out all your data then make a macro or clip. so you have one object that represents all your structure data make sure to include the index in your clip you can use the same index for cursor and objects but make one for each so you can use objects and fingers. actually its best to have 2 clips one objects and one cursors. throw that clip into an iterator connect up the iterator variables to current index to the index or indexs. its best to have two iterators one for objects one for cursors so i will be talking about cursor data but just apply to object data. so now on the root level connect a structure count to the cursor and connect that to the iterations variable. make sure to publish the structure input from your clip inside the iterator. so connect the cursor structure to the what ever you named the publish port of your structure input.

then do what ever augmentation you want to do to all the cursors and objects as whole. meaning this is how you make a cross hair or pointer for all events.

ok the good part using the c_id. so lets say you have 3 touches touch one with c_id 0 touch 2 c_id 1 touch 3 c_id 2 etc... let go of one touch and c_id 2 turns to one etc...

so i would use this if you want to do something special with an individual object. so yesterday i made a fluid finger painting patch. the velocity takes an x y input but not x1,x2,x3 etc.. so i put the tuio macro inside an iterator and outputted just my c_id from the iteration (only snow leopard) then used the c_id as the index input to my cursor macro so if im using 3 fingers the velocity x,y will use finger 3 data until i let go of the third finger.

i suppose if your on leopard do everything inside the iterator which might get messy, or you can use a interpolator. connect the structure count to the end val of the interpolator and connect the interpolation value to the index value of your macro so it will not iterate more than the amount of objects you are using at any time then connect the c_id to another tuio clip that you can work on independently based on the c_id.

here i will up load tuio finger flow painting. it needs snow leopard so you won't be able to use it till you got snow leopard. i will upload the iterator example i just explained. not sure if you can open it or not im all snow leopard now but you might be able to.

PreviewAttachmentSize
tuioFingerPaintFlow.qtz87.5 KB
tui_c_id.qtz7.55 KB

Swiftlikeninja's picture
Re: Tuio client with reactivision

I will check out the examples and you have explained in great detail quite a bit about tuio tracking which will help me through quite a few of my issues but let me trow another issue you way.

I have a ever changing structure based on what order the different fiducial tracker are shown in front of the camera. If I hold up tracker 10 and then (while tracker 10 is in front of the camera) I hold up tracker 11 the structure is as follows:

0:(0)= 0:----------- 1:"c_id"= 10 1:(1)= 0:------------ 1:"c_id"= 11

But if I hold up tracker 11 first and then 10 the structure is as follows

0:(0)= 0:----------- 1:"c_id"= 11 1:(1)= 0:------------ 1:"c_id"= 10

Whereas the c_id changed. Now within the structure each tracker has a xpos and a ypos amongst others but what I want is to have for example; the xpos of c_id 1 to affect the position of a cube, independent of where in the structure the c_id is.

fsk's picture
Re: Tuio client with reactivision

i think i know what you are talking about but im not sure. i made a plugin once that i think does what you need. i never really used it in anything so i cant be responsible for any crashes and stuff (only ever made two plugins and this one is second) ;). im not even sure how it works anymore and i cant test it now as i dont have any fucidals. but ill attach it and let you figure it out.

edit: i looked at the code and i think it works something like this. the inputLength (dunno why i chose such a name) input tells it the max id you want to use. inputStructure should be the output of the tuio patch. the output structure will be a structure the length of inputLength but with stuff ordered by id (it will have an empty element if the id is not present).

one thing is important though. you can only use one representative of each id. if you use more, the output will still give you only one (the last one it deals with). should have made it return structures :/.

looking back, this could have probably been done with javascript.

PreviewAttachmentSize
TUIO distributor.plugin.zip12.97 KB

Swiftlikeninja's picture
Re: Tuio client with reactivision

Downloaded and installed your plugin fsk but cannot seem to figure out how it works to see if its what I need. Im pluging in the tuio client tuioobjects into the tuioobjects of your plugin and am not getting any structure output.

fsk's picture
Re: Tuio client with reactivision

you have to set the other input port to whatever is the highest id you are using. otherwise the plugin doesnt know how big a structure it should make to fill in all the stuff. lets say you need 15 fucidals for whatever you need them. set the "objectCount" to 15 and use only fucidals with ids from 0 to 14 (only one of each).

Swiftlikeninja's picture
Re: Tuio client with reactivision

Thank you Fsk (my problem was having the consumer disabled when I first tried your plugin... heh) This plugin is exactly what I needed it handles the fiducial tracking without any issues and as long as I bump the structure count to what my max is the it will seperate the trackers and sort them via their C_id. This is beautiful and again many thanks

dust's picture
Re: Tuio client with reactivision

i think i messed up my explanation a bit. i'm using the c_id for indexing a object because the paint velocity only has input for x,y not 10 sets of xy so i used the c_id in this context to be my indexed value of the tuio cursor object. meaning if i had three fingers down then c_id = 2 the 2 is connected to structures index so it pulled out values for that index which subsequently is the third touch when i lift a finger seeing that the c_id is being iterated it changes to the next c_id which is number 1 because i only have 2 finger down now.

c_id is the ordering count of your objects. so that means it is the order in which you place objects and their respective counts. it is a very useful feature built into the tuio plugin.

so this sounds like c_id is just your objects structure count and nothing more. well martin is smart guy so he included this into tuio for a reason.

it sounds more like you need to be using your f_id not c_id. c_id 's change is only respective to the order of objects and increments when you add objects. and remembers the order while your structure is not = to null. meaning the c_ids will change when you take all objects off the table and put them down again in a different order.

like i said i use c_id for indexing sounds like you might want s_id.

look at it like like touches 0,1,2 put 0 down first then 1 then two lift up 0 and 2 then put down 2 before zero and now his c_id changed to 0 from 2 because you changed the order in which you placed them.

i see this useful for z ordering.

im not entirely sure what the c stands for i know s is for session and m stands for motion or martin ?

so yeah your going to go crazy fid_11 will not always = c_id 11 its dependent on the order placed which changes as you move objects around etc..

dust's picture
Re: Tuio client with reactivision

sweet i like tuio i will investigate what the distributer does.

fsk's picture
Re: Tuio client with reactivision

glad its what you need.

there is one problem though. as i said its the second plugin i ever made and as such my second (and last for now) attempt at cocoa. and from looking at the code im afraid this plugin is one big memory leak:).

ill shamelessly post the code here so the experts can fix it (and maybe teach me what im doing wrong or if im doing anything right at all :D ). please excuse the bad variable names.

NSArray* input=[NSArray arrayWithArray: self.inputArray]; NSUInteger count=self.inputLength; NSMutableArray* poo = [NSMutableArray arrayWithCapacity:count];

NSUInteger i; for(i=0;i<count;i++) { NSArray* kaka=[NSArray array]; [poo addObject:kaka]; } for(i=0;i<[input count];i++) { NSArray* element =[NSArray arrayWithArray: [input objectAtIndex:i]]; if([element count]>5) //checks if the fucidal is ok (cant remember why but it stopped crashing after this) {
NSNumber* kaka=[element objectAtIndex:1]; // the fucidal id NSUInteger index=[kaka unsignedIntegerValue]; if(index<[poo count])[poo replaceObjectAtIndex:index withObject:element]; } } if([poo count]>0)self.outputArray =poo;

return YES;

i read somewhere that i dont have to release the arrays if they arent made with alloc but have no idea when, if ever these get released in this case. im quite sure i should have at least released the NSNumber.

dust's picture
Re: Tuio client with reactivision

haha on the variable names. i suppose those are your foo and bar.. lol

can't really help you with the memory leak stuff haven't really got into the leakage tracking yet.

i think if you set up properties right in your .h file then all the retain counting should be taken care of for you. supposing you synthesize, wait qc plugs use dynamic ? hmmm i think they are almost the same thing. @dynamic will create the accessors for you and @synthesize makes both setter and getter for you not really sure though you would think dynamic implies some sort of mutability that would need a setter ?

if you do property (assign, retain) NSArray *poo; in your .h then do @dynamic poo; in your .m all you will have to do is super de alloc.

the whole retain thing messed with me for a bit.

i think think of them as strings attached to objects that need to pooled and cut all at once or else you will have a head ache trying to figure out who is using what string when and when are they done etc... i think its just best to bunch them together and cut them all at once when your program is done but that might not be proper memory management.

cocoa is still foreign to me so im really just pulling all this out my kaka.

williamcotton's picture
Re: Tuio client with reactivision

Objective-C uses pointers to reference the address space of its objects. It is the same concept as a pointer in C. A pointer is a variable that contains a memory address, not what is stored at that memory address. (There are some good overviews out there. Just google for "c pointers".)

When you instantiate an object in Objective-C, you are dealing with pointers. That way, when you're passing around objects, they location of its constituent values aren't moved or passed along. Think of your variables as signs giving the directions to where the data is stored. At some point you'll no longer need the stored data, however, and you'll want to tell the system to set it free. However, if you set the data free, and still have the sign giving direction to that location, the program will throw an error when it gets there and doesn't find what it's looking for.

Cocoa objects are sub-classes of NSObject, which amongst other things, handles the allocation and deallocation of memory based on a reference counter. When you bring an object to life, it's reference counter is equal to 1. Whenever an object's reference counter falls below 1, it is deallocated from memory. You send an object the message release to lower its reference counter by 1 and the message retain to raise it by 1.

In C, you would handle this by hand, making sure that you malloc()'d and free()'d every reference that you were using.

Objects that are not deallocated will persist in memory. Sometimes you won't notice it at all. In the case of a Quartz Composer patch which executes it's run loop many times, failing to deallocate objects will cause rather large memory leaks.

Even seasoned developers forget to release objects, normally due to the incredible number of things you need to juggle in your head while you're programming, especially larger applications or mathematically complex algorithms.

Learning to use your profiling and analysis tools will help you immensely. If you've got Snow Leopard, Xcode now has the Clang static analyzer built in to it. It does a pretty good job of keeping a track of reference counts and alerting you when you're leaking memory. Using the memory leak profile in Instruments is another good approach to tracking them down.

I'm hoping this made some sense! There are some really good write-ups on pointers, memory allocation, and arrays, in both C and Objective-C out there that go through in much more detail as to what is going on.

williamcotton's picture
Re: Tuio client with reactivision

It looks to me like you could replicate that patch in Javascript pretty easily. Of course, it won't be as fast as compiled code, but I've found Javascript is rarely the bottle neck when it comes to iterating through an array.

And, you don't have to worry about memory leaks. ;)

pablovitamin's picture
Re: Tuio client with reactivision

Hello, I am trying to do an interactive installation using fiducials and I am having the same problem you were having on 2009. do you have the problem solved? do you have any example on how to work with different fiducial s in QC. I am trying to enable and disable color sprites and music. Thanks in advance.

pablovitamin's picture
Re: Tuio client with reactivision

williamcotton wrote:
It looks to me like you could replicate that patch in Javascript pretty easily. Of course, it won't be as fast as compiled code, but I've found Javascript is rarely the bottle neck when it comes to iterating through an array.

And, you don't have to worry about memory leaks. ;)

Hello, could you please post the javascript you are mentioning? I built this one in order to show the fiducial individually but I am missing something because It does´t always work.

function (__structure object, __boolean found) main (__structure TuioObjects, __number count, __number c_id) { var result = new Object();

if(count > 0) { for (index = 0; index <= count -1; index++) {

     if(TuioObjects[index][1] == 9)
     {
        result.object = TuioObjects[index];
        result.found = true;

     } else {
        result.found = false;
        }
     }

  }
else {
  result.found = false;

} return result; }

thanks

Achim Breidenbach's picture
Re: Tuio client with reactivision

I guess your code only works if the last TuioObjects in your array equals "9", because only then the "result.found" is true in the end. I suggest that you set result.found to false at the very beginning and remove all the other places (else-statements).