PDA

View Full Version : PPT UDP data format


MiamiTodd
02-06-2006, 09:31 AM
We are trying to read in the raw data off the socket from the PPT and we were curious what format the data was coming in.

Thanks,
Todd

tobin
02-06-2006, 09:49 AM
Your subject line, UDP, implies you're trying to access our UDP stream. This is a VRPN (www.vrpn.org) data stream and you'll have to go to their website and download their opensource project to determine this. PPT currently implements version 6.06 of VRPN.

If you're interesting in access the serial version of the data, then go to the WorldViz PPT download site:

http://www.worldviz.com/download/index.php?id=16

MiamiTodd
02-08-2006, 07:29 AM
Thanks for the expediant reply.

The reason I titled the message and worded as I did was after reading the other forum posts about using the PPT data in other programs it was mentioned that a socket is an easy way to make this connection. Was that in regard to the serial data?

MiamiTodd
02-08-2006, 09:44 AM
After reading the most recent reply I don't think that cleared up what I was trying to ask.

I know that in Vizard there is already code set up parse the vrpn data into a certain format. What I'm wanting to do is use this type of parsing in another python library other than Vizard. Is it possible to import the vrpn parsing from Vizard into another modeling package, i.e. Panda3d?

Thanks,
Todd

farshizzo
02-08-2006, 12:57 PM
Hi,

Vizards sensor plugins are NOT generic python plugins. Vizard uses its own plugin architecture for accessing data from devices. What you could do is have a Vizard program running as a server and forwarding the data over a socket to your other program. But to be honest, if you are going to go through the trouble of doing this then you might as well just create a python plugin for accessing VRPN data. It would probably take just as much work.

MiamiTodd
02-14-2006, 11:00 AM
Do you have any recommendations on reading to get this done? I'm trying to read through the VRPN documentation but am very unfamiliar with C++.

Am I approaching things correctly if I wanted to get the data sent from the PPT into another program that I would have to code up a plugin for python in C++ and then use that in the desired python modules? There is no way to get this data straight off the socket short of performing these reads through the VRPN 6.0.6 in another program or using the Vizard program?

Thanks,
Todd

farshizzo
02-14-2006, 11:39 AM
Hi,

Have you downloaded the VRPN source code? It contains a few examples of connecting to a device and retrieving data from it. Here is a rough outline of what the code should look like:void handle_pos(void *userdata, const vrpn_TRACKERCB t)
{
printf("Marker %d: %.2lf, %.2lf, %.2lf\n",t.sensor,t.pos[0],t.pos[1],t.pos[2]);
}

//Create tracker object
vrpn_Tracker_Remote *tracker = new vrpn_Tracker_Remote("PPT0@YourMachineName");

//Setup callback for when new position data comes in
tracker->register_change_handler(NULL, handle_pos);

//Need to call this every frame to receive data
tracker->mainloop();

//Cleanup tracker when exiting
delete tracker;The only way to get data from the PPT is either through VRPN or from the serial port using our own API. Our API is on our PPT download page.

MiamiTodd
02-14-2006, 01:35 PM
This looks to be just what I needed. Thanks ever so much!

MiamiTodd
02-24-2006, 02:38 PM
Perhaps I spoke a bit too soon. When I try to create a project and compile it after compiling the VRPN source code I get all sorts of errors regarding the extern "C" lines and other extern lines in the VRPN source if I compile it as a C module.

I did manage to get to a certain point using C++ project though. But when I try to compile the code I get the following error:
...\extender\Tracker.cpp(8): error C2664: 'int vrpn_Tracker_Remote::register_change_handler(void *,vrpn_TRACKERCHANGEHANDLER,vrpn_int32)' : cannot convert parameter 2 from 'void (void *,vrpn_TRACKERCB)' to 'vrpn_TRACKERCHANGEHANDLER'

I'm trying to get a dll compiled from the below code:

(Tracker.h)

#include <vrpn_Tracker.h>

class Tracker{
public:
Tracker(char* address);
int* getPosition();
void handlePos(void *userdata, vrpn_TRACKERCHANGEHANDLER t);

vrpn_Tracker_Remote* tracker;
vrpn_float64* lastPosition;
};

(Tracker.cpp)
#include <string.h>
#include <vrpn_Tracker.h>
#include "Tracker.h"

Tracker::Tracker(char* address){
tracker = new vrpn_Tracker_Remote(address);
//Setup callback for when new position data comes in
tracker->register_change_handler(NULL, handlePos);
lastPosition = new vrpn_float64[3];
}

Tracker::handlePos(void *userdata, vrpn_TRACKERCB t){
lastPosition[0] = t.pos[0];
lastPosition[1] = t.pos[1];
lastPosition[2] = t.pos[2];
}

Tracker::getPosition(){
return lastPosition;
}

I've tried chaning several things such as the vrpn_TRACKERCB to the vrpn_TRACKERCHANGEHANDLER but this doesn't seem to make any headway. I am unfortunately not familiar enough with C/C++ to recognize any simple errors I might be inducing here. Any help you can offer is greatly appreciated.

farshizzo
02-24-2006, 02:56 PM
Hi,

I don't think you can use VRPN with C, you must use C++. Which version of VRPN are you using? The code I supplied you was based on version 6.06. If you have a newer version then that code might now work.

MiamiTodd
02-24-2006, 03:05 PM
The VRPN base is vrpn_06_06.beta9. It was the only 6.6 I could find on their site.

The reason I changed the format to a class was so that the callback would be called again and again and the users that import the dll into python would have access to the most currently recorded position data. It looked like the skeleton provided wouldn't store that data or keep running.

As well the requirements for wrapping that code into an importable module for python required the restructuring from what I could tell. I assume from what I have read that the import in python extensions calls an intializer method once, which makes sense to me to be the spot to make the connection to the tracker. Then have a method that allows the users to fetch the data, hence the getPosition in the above code segments. As well, from what I have read, the callback has to be something that can be called by the VRPN separately so I just had that write the most recent data into the classes data member that would be returned on request.

Does this sound right or completely off base?

Thanks,
Todd

farshizzo
02-24-2006, 03:22 PM
Hi,

Your vrpn callback must be a function. You are trying to pass a class method instead, which won't work. Try the following instead:

(Tracker.h)#include <vrpn_Tracker.h>

class Tracker{
public:
Tracker(char* address);
~Tracker();

vrpn_float64 lastPosition[3];

protected:
vrpn_Tracker_Remote* tracker;
};
(Tracker.cpp)#include <string.h>
#include <vrpn_Tracker.h>
#include "Tracker.h"

void handlePos(void *userdata, vrpn_TRACKERCB t)
{
Tracker *tracker = (Tracker*)userdata;
tracker->lastPosition[0] = t.pos[0];
tracker->lastPosition[1] = t.pos[1];
tracker->lastPosition[2] = t.pos[2];
}

Tracker::Tracker(char* address)
{
tracker = new vrpn_Tracker_Remote(address);
//Setup callback for when new position data comes in
tracker->register_change_handler((void*)this, handlePos);
}

Tracker::~Tracker()
{
delete tracker;
}

MiamiTodd
02-24-2006, 03:33 PM
Wonderful. That seems to compile and link at least! Now to the task of SWIG.

Thanks again for all your help.

Todd

MiamiTodd
04-03-2006, 03:08 PM
We are still having problems using the below code to access the tracker data. We put in a print line call to see if the call back method is ever being called and it never prints out anything.

We saw that there was no tracker->mainloop() or equivalent call any place in your most recent code. Is this something we should be concerned with?

Thanks,
Todd

Tracker.cpp

#include <string.h>
#include <vrpn_Tracker.h>
#include <iostream>

using namespace std;
#include "Tracker.h"

void handlePos(void *userdata, vrpn_TRACKERCB t)
{
Tracker *tracker = (Tracker*)userdata;
tracker->lastPosition[0] = t.pos[0];
tracker->lastPosition[1] = t.pos[1];
tracker->lastPosition[2] = t.pos[2];
cout << t.pos[0] << endl;
}

Tracker::Tracker(char* address)
{
cout << "Printed here" << endl;
tracker = new vrpn_Tracker_Remote(address);
//Setup callback for when new position data comes in
tracker->register_change_handler((void*)this, handlePos);

}

double Tracker::getXPos()
{
return 6.0;//lastPosition[0];
}
double Tracker::getYPos()
{
tracker->mainloop();
return lastPosition[1];
}
double Tracker::getZPos()
{
return lastPosition[2];
}

Tracker::~Tracker()
{
delete tracker;
}


Tracker.h

#include <vrpn_Tracker.h>

class Tracker{
public:
Tracker(char* address);
~Tracker();

vrpn_float64 lastPosition[3];
//double* getPosition();
double getXPos();
double getYPos();
double getZPos();

protected:
vrpn_Tracker_Remote* tracker;
};

farshizzo
04-03-2006, 03:14 PM
Yes, I believe I mentioned in an earlier post that you must call tracker->mainloop() every frame of your simulation. This call will cause the tracker to receive the most recent data from the network and trigger your callbacks.

MiamiTodd
04-03-2006, 03:21 PM
So where abouts should I put this? Even in the individual getXPos() etc... methods I'm not seeing anything displayed when I call them. I even tried adding a tracker->mainloop() before each of the get position methods and I'm still not getting anything displayed that is printed in the handlePos method.

Thanks,
Todd

farshizzo
04-03-2006, 03:56 PM
It really doesn't matter where it is called, as long as it is called on a regular interval. I'm assuming this plugin is being used within some sort of simulation framework. The best thing would be to call tracker->mainloop() at the beginning of every frame of your simulation.

Are there any errors printed out to the console. If VRPN doesn't receive data it should print output messages. Make sure that the mainloop is being called and that you are connecting to the correct address (i.e. "PPT0@ComputerName")

MiamiTodd
04-03-2006, 04:10 PM
You know, had I been putting in "PPT@Machine", that might have worked. :o

I will try that. Thanks.

MiamiTodd
04-03-2006, 04:57 PM
To make sure that I am explaining everything I want to do I will cover the full details in case this influences the reply.

We are trying to write a general Python extension in C++ using the above code to parse and interpret the position data, as well as send it back to Python. Once we get compilable code, we run it through SWIG creating the Python Shadow class and the wrapped C++ code. We then compile it all into a .dll following all the procedures for a normal Python extension.

Then, when we run Python and create a Tracker, as above, while passing in "192.168.1.100" as the argument, which is the local IP of the PPT, we get no errors. Then when we call, tracker.getYPos() in Python after adding in the tracker->mainloop() as the first statement in the C++ code, we get no errors and the print statements in the call back handler do not appear.

I will certainly try passing in the correct address of the PPT tomorrow when I can get back to the systems, but just wanted to make sure there wasn't any other suggestions you could offer.

Thanks,
Todd

farshizzo
04-03-2006, 05:06 PM
If you are passing 192.168.1.100 as the address then it won't work. You need to pass PPT0@192.168.1.100. Also, are you calling tracker.getYPos() multitple times or just once? Keep in mind that the first time you call it there might not be any data received yet.

You should also verify that the PPT computer is actually sending data. Go into the options screen of PPT and make sure the COM port option is set to VRPN. Then make sure PPT is actually sending data by pressing the Talk button.

MiamiTodd
04-10-2006, 12:36 PM
Awesome! This is now working. I really appreciate all your help! :D