Samurai Robot Series:
I wanted a simple way to track the movement and orientation of an object (In this case, my Samurai robot). TrackIR’s SDK is not public, and has no python support as far as I know.
I looked at the symbols in dll that is distributed with the trackir app, and with some googling around on the function names, I could piece together how to use this API.
Here’s the result – my console program running in a window in the middle. I have pressed ctrl+c after 70ms, to cancel, to give a better screenshot:
Implementation Details
Python lets you call functions in any .dll library pretty easily (although the documentation for doing so is pretty awful). The entire code is approximately 500 lines, with half of that being comments, and I’ve put on github here:
https://github.com/johnflux/python_trackir
But here’s a high overview of the implementation:
- Query the Windows registry for where the TrackIR software is installed.
- Load the NPClient64.dll in that TrackIR software folder, using python ctypes.WinDLL (Note, I’m using 64 bit python, so I want the 64 bit library)
- Expose each function in the dll that we want to use. This can get a bit cryptic, and took a bit of messing about to get right. For example, there is a function in the dll ‘NP_StopCursor’, that in C would look like:
int NP_StopCursor(void)
This translates in python to:
NP_StopCursor = ctypes.WINFUNCTYPE(ctypes.c_int)( ("NP_StopCursor", trackIrDll), ())
where ‘NP_StopCursor’ is now a function that can then be called with: NP_StopCursor(). See the trackir.py file for more, including on how to pass parameters which are data structures etc.
Note: Python ctypes supports a way to mark a parameter as an ‘output’, but I didn’t fully understand what it was doing. It seemed to just work, and appeared to automatically allocate the memory for you, but the documentation didn’t explain it, and I didn’t entirely trust that I wasn’t just corrupting random memory, so I stuck to making all the parameters input parameters and ‘new’ing the data structure myself.
- Create a graphical window and get its handle (hWnd), and call the functions in the TrackIR .dll to setup the polling, and pass the handle along. The TrackIR software will poll every 10 seconds ish to check that the given graphic window is still alive, and shutdown the connection if not.
- Poll the DLL at 120hz to get the 6DOF position and orientation information.
ROS Integration
I wanted to get this to stream 6DOF data to ROS as well, to open up possibilities such as being able to determine the position of a robot, or to control the robot with your head etc.
The easiest way is to run a websocket server on the linux ROS server, and send the data via ROS message via the websocket.
A good place to start: https://github.com/Sanic/ROSBridgeTestclient/blob/master/BSONTestClient.py
Pingback: Samurai Robot: Part 1 | John Tapsell