Where's the SDK?

Post questions, comments and feedback to our 3Dconnexion Windows Development Team.

Moderator: Moderators

calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

ngomes wrote:Hi calli,
calli wrote:- What is a "message pump"
- how can I implement on in Python?
- why can`t we have a function just reading out the values?
A "message pump" is what is generally called the Windows feature of transmitting "messages" between the system and applications.
Are you able, on your Python script, to process raw Windows messages? Like WM_ACTIVATE or WM_PAINT?
I guess not. Maybe it is the wrong way I am trying to use the SN. Especially because Blender is a multi-platform app and my test should not run only on Windows.

Of course the better way would be a function inside Blender to provide me with the values. I am in contact with the devs.

Carsten
calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

It would still be nice to have a way to use a Space Navigator from Python (and other scripting languages)!

Carsten
ngomes
Moderator
Moderator
Posts: 3431
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

calli wrote:It would still be nice to have a way to use a Space Navigator from Python (and other scripting languages)!
That's one of the reasons why we developed (and maintain) a COM interface to our API: most scripting languages have support for COM.
For Python, you should perhaps have a look at Mark Hammond's pywin32 project and his web site.
calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

I am very aware about win32com or ctypes (http://starship.python.net/crew/theller/ctypes/ which is more Multiplatform, at least it also works with .so libraries on Linux).

However I could not read anything from my SN with this:

Code: Select all

#!/usr/bin/env python

import sys
import win32com.client

sn = win32com.client.Dispatch("TDxInput.Device")
sn.Connect()

print sn.Type

def updateSensorData():   
   global x, y, z, rot_x, rot_y, rot_z

   Tx = float(sn.Sensor.Translation.X)
   Ty = sn.Sensor.Translation.Y
   Tz = sn.Sensor.Translation.Z
   Rx = float(sn.Sensor.Rotation.X)
   Ry = sn.Sensor.Rotation.Y
   Rz = sn.Sensor.Rotation.Z
   
   print 'Tx', Tx,
   print 'Ty', Ty,
   print 'Tz', Tz,
   print 'Rx', Rx,
   print 'Ry', Ry,
   print 'Rz', Rz


def main():  
   updateSensorData()
   

main()
Thanks for your patience!
Carsten
ngomes
Moderator
Moderator
Posts: 3431
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Hi calli,

What does it print if you're pushing on the cap? Always zeros? And what is the output of sn.Type()?
calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

Always Zero.

And sn.Type() gives (as expected) 6.

"my" sample is the striped version of Martijns code, he also got the Zeros in his first try, however inside a OpenGL context he got it working.

Carsten
ngomes
Moderator
Moderator
Posts: 3431
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Hi calli,
Always Zero.
This is probably -- as previously discussed -- because there's no "message pump" on the thread that is connecting to the driver.

The key is enabling your program to receive window messages. The COM api wraps a protocol that uses registered window messages (Win32's ::RegisterWindowMessage()).
calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

ngomes wrote:Hi calli,
Always Zero.
This is probably -- as previously discussed -- because there's no "message pump" on the thread that is connecting to the driver.

The key is enabling your program to receive window messages. The COM api wraps a protocol that uses registered window messages (Win32's ::RegisterWindowMessage()).
Ok, but then the (one...) advantage of scripting languages is gone. Its not portable anymore.

So I would suggest to have a function to immediate read out the values, of course it will mean that lazy boys like me will write polling applications :-(

But I will try your suggestion! Maybe I can adapt it to ctypes which should be portable to at least linux.

Thanks,
Carsten
ngomes
Moderator
Moderator
Posts: 3431
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Hi calli,

We are actually working to remove that requirement (message pump on Windows). So, it will stop being an issue some time in the future.

Having said that, you should also note that removing the need for a message pump does not make your Python script any more portable. The reason being that to, receive 3D mouse data, you will also need to code something that is platform -specific.

Of course, if 3D mouse support becomes a standard feature of Python, then you have your problems solved. That's not such an unreasonable thing to do since our 3D mice follow a strict (and open) standard: HID multi-axis controller.
calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

ngomes wrote: Having said that, you should also note that removing the need for a message pump does not make your Python script any more portable. The reason being that to, receive 3D mouse data, you will also need to code something that is platform -specific.
Well, I coded a python app for a angular decoder (to USB) and the only line which needet to be platform specific was deciding if to use a .so or .dll. I was using ctypes which is now in python 2.5. If I start using win32 functions I will be lost on linux or other systems. The .so/.dll sould encapsulate this and be usable from all systems.

So I will change my argument to "less platform specific code" ;-)

Carsten
kitsu
Posts: 7
Joined: Thu Aug 09, 2007 1:28 pm

Post by kitsu »

To pump the Windows message queue in Python in a loop call either win32gui.PumpWaitingMessages() if your using the pyWin32 package, or the following function if you are using ctypes.comtypes;

Code: Select all

from ctypes import *

class POINT(Structure):
    _fields_ = [("x", c_long),
                ("y", c_long)]

class MSG(Structure):
    _fields_ = [("hWnd", c_ulong),
                ("message", c_uint),
                ("wParam", c_ulong),
                ("lParam", c_ulong),
                ("time", c_ulong),
                ("pt", POINT)]

def PumpWaitingMessages():
    from ctypes import windll, byref
    user32 = windll.user32
    msg = MSG()
    PM_REMOVE = 0x0001
    while user32.PeekMessageA(byref(msg), 0, 0, 0, PM_REMOVE):
        user32.TranslateMessage(byref(msg))
        user32.DispatchMessageA(byref(msg))
Which is from This file.

I have used these to successfully receive keyboard events from my SpaceExplorer, but have not gotten any values from the sensor events yet? My event loop is crap though, it uses time.sleep to avoid using 100% CPU time. I think what I need is MsgWaitForMultipleObjects, but I don't know what handle to pass as the first arg. I could use RegisterWindowMessage if I knew what name to register...

Anyway it's late and I still have work to finish.
calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

Same here, still no values.

However I still don't understand why I have to deal with all this when I just want to read the values of the device. :oops:

Maybe I want to use the values in a non-graphical way or whatever.


Carsten
kitsu
Posts: 7
Joined: Thu Aug 09, 2007 1:28 pm

Post by kitsu »

One reason you need to deal with the added complexity is if you want to be notified immediately when something happens. Even if the interface worked correctly and you could grab values any time you wanted there is a risk that you will miss the users actions because you are only peeking at the values every once in a while Ex: GetSensorValues() -> wait [user does something here] - GetSensorValues() <- you just missed their action.

The other reason is probably because the code in the driver never gets a chance to run - all the program's cpu time is being spent on your code! If it weren't a COM thingy, with all this event system logic built in, it would probably just have an update method you could call to let the software talk to the hardware. As it is though you need to tell the operating system to tell the COM server to tell the dirver to update its copy of the device state :roll:

I'm still not sure why the attributes of my sensor object are empty when I receive sensor events in my event loop though? I kinda wish they had passed a pointer to the sensor object in the event like they pass the keycode in keyboard events...
Today I'm going to do some research on implementing Window's event loops, and download the 3Dx SDK example code. I'll post if I figure anything out.
calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

Good points kitsu!

Carsten
kitsu
Posts: 7
Joined: Thu Aug 09, 2007 1:28 pm

Post by kitsu »

ngomes wrote:Hi calli,
calli wrote:- What is a "message pump"
- how can I implement on in Python?
- why can`t we have a function just reading out the values?
A "message pump" is what is generally called the Windows feature of transmitting "messages" between the system and applications.
Are you able, on your Python script, to process raw Windows messages? Like WM_ACTIVATE or WM_PAINT?
ngomes: If I am able to catch Window's messages what Windows messages am I looking for? Probably not WM events since I am not using a UI :lol:

Remember - Python is a cross platform high level dynamic scripting language. All this c++/COM/Windows stuff is pretty alien to Python programmers, and most Python developers are coming from outside and top down. We don't know the ins and outs of Windows, and we are mostly starting with some COM IDispatch object and figuring out what to do with it from there. This is evidenced by the fact that there is no Python standard implementation of the Window's event loop, and no one knows how to make one.

I'm trying to do my homework and learn about the systems I'm using, but I'm starting from a very small knowledge base. Starting from what I know I can only get so far before I'm lost in the maze that is COM/the Window's API. I looked at the 3Dx SDK example code, but it doesn't seem to be doing anything related to what I need, and I don't know what parts to look at. What does

Code: Select all

hr = __hook(&_IKeyboardEvents::KeyDown, IKeyboardPtr, &OnKeyDown);

mean?

hr = hook reference?
&_IKeyboardEvents::KeyDown = the KeyDown method of the IkeyEvent interface
IKeyboardPtr = our reference to the keyboard object
&OnKeyDown = the event handler

What is __hook, where did it come from, what does it implement? How does __hook tie into the windows event system, and what messages would it watch for?
Post Reply