Outerra forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Download Outerra Tech Demo. Unofficial Outerra Discord server, MicroProse Discord server for OWS.

Pages: 1 2 [3] 4 5 ... 7

Author Topic: TrackIR  (Read 91352 times)

zaelu

  • Jr. Member
  • *
  • Posts: 47
  • free-track user
Re: TrackIR
« Reply #30 on: May 07, 2013, 04:38:33 am »

I see. Is good that it will not be let out :) .

I understood that facetracknoir team had taken over freetrack interface development when they (facetracknoir) had released their latest version of facetracknoir. I tested it but I don't like it as it is more complicated in some parts and simplified in other parts... maybe later.

Here is a hint that they got freetrack legacy to further development:

http://sourceforge.net/p/facetracknoir/wiki/FreeTrack20/
Logged

foobie42

  • Member
  • **
  • Posts: 63
  • newbie
Re: TrackIR
« Reply #31 on: May 07, 2013, 04:47:09 am »

Only thing that changed is a few fields at the end of the memory-mapped structure. So that all games that support FreeTrack can read previous fields with head-pose data, while the new ones can serve as a bridge between TIR and FT proper.

As for the rest of the statements, I don't appreciate piggybacking on the name. It hasn't been discussed with FT team, so it's unauthorized.

Shameless plug: https://github.com/opentrack/opentrack is a fork for all platforms and bugs fixed at that.
Logged

zaelu

  • Jr. Member
  • *
  • Posts: 47
  • free-track user
Re: TrackIR
« Reply #32 on: May 07, 2013, 04:56:47 am »

I understand. I didn't knew they didn't talked with FT team. I hope they'll fix this and they cooperate with each other.
Logged

Pyroman31FF

  • Jr. Member
  • *
  • Posts: 41
Re: TrackIR
« Reply #33 on: May 11, 2013, 07:33:30 am »

Disclaimer: I never owned NP software or hardware. Never signed any EULA, NDA or whatnot. This code might work but it's best if you test it on a TIR device. Tell me of bugs! I will self-flagellate in contempt...

Also I know no disassembly! And don't know where to find NPClient{64,}.dll!

Code: [Select]
/* This is free and unencumbered software released into the public domain.

 * Anyone is free to copy, modify, publish, use, compile, sell, or
 * distribute this software, either in source code form or as a compiled
 * binary, for any purpose, commercial or non-commercial, and by any
 * means.
 *
 * In jurisdictions that recognize copyright laws, the author or authors
 * of this software dedicate any and all copyright interest in the
 * software to the public domain. We make this dedication for the benefit
 * of the public at large and to the detriment of our heirs and
 * successors. We intend this dedication to be an overt act of
 * relinquishment in perpetuity of all present and future rights to this
 * software under copyright law.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
*/

#include <stdlib.h>
#include <stdio.h>
/* this is unfortunately necessary as the API is Windows-only */
#include <windows.h>

#ifdef __cplusplus
#  define MY_EXTERN extern "C"
#else
#  define MY_EXTERN
#define MY_EXPORT(ret) MY_EXTERN ret __declspec(dllexport) __cdecl
#endif

#pragma pack(push, 1)
typedef struct {
  __int16 status; /* zero means success, it's easy to forget! */
  __int16 frame; /* if idempotent, device paused */
  __int32 padding;
  float roll, pitch, yaw; /* divide by 8191 when received, in radians */
  float x, y, z; /* between -16383 and 16383 */
  float padding2[9];
} tir_headpose_t;
#pragma pack(pop)

typedef struct {
HMODULE hlibrary;
__int32 (__stdcall* tir_reghwnd)(HWND hwnd);
__int32 (__stdcall* tir_regprogid)(__int16 progid);
__int32 (__stdcall* tir_queryver)(__int16* version);
__int32 (__stdcall* tir_reqdata)(__int16 bitmask);
__int32 (__stdcall* tir_stopcurs)(void);
__int32 (__stdcall* tir_startxmit)(void);
__int32 (__stdcall* tir_getdata)(tir_headpose_t* pose);
/* there are more functions, especially for cleaning up
* but the library is typically called on startup
* and unloaded on exit. if you really must add them,
* you can either extract them from NPClient.dll or
* google for it. for instance I once found symbols
* and some constants in Doxygen format...
* if you REALLY need them I can finish the damn thing
* but it's so much boilerplate :(
*/
} tir_state_t;

MY_EXPORT(tir_state_t*) mytir_init(void)
{
HKEY hkey = NULL;
tir_state_t* ret;
int i;
DWORD sz = 1900;
/* Windows paths are limited to 260 characters */
char buf[2048];

ret = malloc(sizeof(tir_state_t));
if (ret == NULL)
return NULL;
memset(ret, 0, sizeof(tir_state_t));
RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\NaturalPoint\\NATURALPOINT\\NPClient Location", 0, KEY_QUERY_VALUE, &hkey);
if (!hkey)
goto error;
buf[0] = '\0';
if (RegQueryValueExA(hkey, "Path", NULL, NULL, buf, &sz) != ERROR_SUCCESS)
goto error;
(void) RegCloseKey(hkey);
hkey = NULL;
buf[2047] = '\0';
for (i = 0; buf[i]; i++)
if (buf[i] == '/')
buf[i] = '\\';
/* in the registry path there's normally a trailing slash already */
#ifdef MY_BUILD_AMD64
strcat(buf, "NPClient64.dll");
#else
strcat(buf, "NPClient.dll");
#endif
ret->hlibrary = LoadLibraryA(buf);
if (ret->hlibrary == NULL)
goto error;
if ((ret->tir_reghwnd = GetProcAddress(ret->hlibrary, "NP_RegisterWindowHandle")) == NULL)
goto error;
if ((ret->tir_regprogid = GetProcAddress(ret->hlibrary, "NP_RegisterProgramProfileID")) == NULL)
goto error;
if ((ret->tir_queryver = GetProcAddress(ret->hlibrary, "NP_QueryVersion")) == NULL)
goto error;
if ((ret->tir_reqdata = GetProcAddress(ret->hlibrary, "NP_RequestData")) == NULL)
goto error;
if ((ret->tir_stopcurs = GetProcAddress(ret->hlibrary, "NP_StopCursor")) == NULL)
goto error;
if ((ret->tir_startxmit = GetProcAddress(ret->hlibrary, "NP_StartDataTransmission")) == NULL)
goto error;
if ((ret->tir_getdata = GetProcAddress(ret->hlibrary, "NP_GetData")) == NULL)
goto error;
return ret;
error:
if (hkey)
  (void) RegCloseKey(hkey);
free(ret);
/* sorry but I don't know anything about unloading DLLs. unless you do, there's a handle leak */
/* if you unload it, no need to touch function pointers, they just become invalid */
return NULL;
}

MY_EXPORT(void) mytir_start(tir_state_t* state, HWND window_handle)
{
__int16 tmp;
/* while you have to call it, can pass anything valid, like desktop handle I suppose? */
(void) state->tir_reghwnd(window_handle);
(void) state->tir_regprogid(1901); /* Falcon 4, an old flight simulation. Need to pass valid Id */
(void) state->tir_queryver(&tmp); /* better to call it, even if we don't care about it! */
(void) state->tir_reqdata(119); /* specifies which elements of the pose structure to return */
(void) state->tir_stopcurs(); /* better to call it */
(void) state->tir_startxmit(); /* idem */
}

MY_EXPORT(void) mytir_get_pose(tir_state_t* state, tir_headpose_t* ret)
{
memset(ret, 0, sizeof(tir_headpose_t));
ret->status = 1; /* if the call fails for some reason, at least we shouldn't think we have a valid pose when we don't */
(void) state->tir_getdata(ret);
}

#ifdef MY_DEMO
int main(void)
{
tir_state_t* state;
int i;
tir_headpose_t ret;

state = mytir_init();
if (!state)
return 1;
mytir_start(state, GetDesktopWindow());
for (i = 0; i < 3600; i++)
{
mytir_get_pose(state, &ret);
if (ret.status)
return 1;
printf("%f %f %f ~ %f %f %f\n", ret.yaw * 180 / 3.14 / 8191, ret.pitch * 180 / 3.14 / 8191, ret.roll * 180 / 3.14 / 8191, ret.x, ret.y, ret.z);
Sleep(35);
}
return 0;
}
#endif


How/ where do i have to implement this?
Logged

foobie42

  • Member
  • **
  • Posts: 63
  • newbie
Re: TrackIR
« Reply #34 on: May 11, 2013, 07:37:01 am »

Implement what, sorry?

Edit: The code's pretty self-explanatory and commented. Try running it when compiled as an executable. It even comes with a 'main' function. Given my interest of helping the NaturalFail ship sink, I can help you implementing support for their product in your own software. Down with NDAs and anticompetetive behavior!
« Last Edit: May 11, 2013, 07:44:01 am by foobie42 »
Logged

Pyroman31FF

  • Jr. Member
  • *
  • Posts: 41
Re: TrackIR
« Reply #35 on: May 11, 2013, 07:44:34 am »

The lines of code you posted. I thught i would have to put them in somewhere thus enabeling TIR.
Logged

foobie42

  • Member
  • **
  • Posts: 63
  • newbie
Re: TrackIR
« Reply #36 on: May 11, 2013, 07:55:54 am »

Is this for Outerra? There needs to be an API for controlling the pose for plugins.
Logged

exadeci

  • Jr. Member
  • *
  • Posts: 22
  • newbie
Re: TrackIR
« Reply #37 on: May 13, 2013, 05:12:47 am »

The major flaw of this system is that is not as natural as claimed because the screen doesn't move with your head so you end up seeing less of the screen when you have your head turned.
A good immersive system would be the Oculous Rift http://www.oculusvr.com/ we can hope they lower the price when it start being used in more games and this system is tested and approved by several renowned developers !
« Last Edit: May 13, 2013, 05:14:52 am by exadeci »
Logged

foobie42

  • Member
  • **
  • Posts: 63
  • newbie
Re: TrackIR
« Reply #38 on: May 13, 2013, 05:16:35 am »

Head tracking, either pure image processing, or with some kind of 'aid' like FreeTrack, while not perfectly natural, after some getting used to is better than you claim.

Bigger problem is accuracy, given how one degree of rotation input gets mapped to several degrees output.

I see no problem with supporting both VR devices and 'traditional' head/face tracker. opentrack does both! The developer of the Rift plugin uses the software with the GRID racing game.
Logged

Pyroman31FF

  • Jr. Member
  • *
  • Posts: 41
Re: TrackIR
« Reply #39 on: May 13, 2013, 11:13:40 am »

The major flaw of this system is that is not as natural as claimed because the screen doesn't move with your head so you end up seeing less of the screen when you have your head turned.

Have you ever used it? I takes less than a month to get used to it and i use it absolutely flawless for years now. It is second nature for me, going that far my brother noticed me moving my head lightly flying the outerran MiG29. Next thing is my axis are so tuned (like everyone else does btw) that minor headmovements already turn the FoV ingame multiple times 360°. So you never lose focus of the screen, it still is centered completely. Don't just quote what some clueless good for nothings wrote somewhere in the internet. They got it all wrong.
Logged

cameni

  • Brano Kemen
  • Outerra Administrator
  • Hero Member
  • *****
  • Posts: 6721
  • No sense of urgency.
    • outerra.com
Re: TrackIR
« Reply #40 on: July 20, 2013, 02:47:13 pm »

So I've tested connection to the FaceTrackNoIR, used the file mapping + mutex to get the data from the tracker using a 3-point cap. It generally works, but I'm having some issues there too.

Here's what I'm doing: initially the named file mapping is opened and named mutex created. Acquiring the mutex doesn't seem to prevent FT from changing the values for some reason.

When the tracker doesn't have good info (one IR LED goes out of the screen), I get values reset to zero, is there a way to discern this case of bad input from the centered view, so I can freeze the camera at the last position?

Logged

foobie42

  • Member
  • **
  • Posts: 63
  • newbie
Re: TrackIR
« Reply #41 on: July 20, 2013, 03:00:58 pm »

Most unusual, please see:

https://sourceforge.net/p/facetracknoir/codegit/ci/master/tree/FTNoIR_Protocol_FT/FTNoIR_Protocol_FT.cpp

Code: [Select]
// Check if the pointer is OK and wait for the Mutex.
//
if ( (pMemData != NULL) && (WaitForSingleObject(hFTMutex, 100) == WAIT_OBJECT_0) ) {
//
// Copy the Raw measurements directly to the client.
//
[...]

Code: [Select]
static const char* FREETRACK_MUTEX = "FT_Mutext";
In particular, the return value of WaitForSingleObject is checked for, if mutex wasn't initialized properly, values wouldn't be updated properly. Are you sure that the typo in mutex name is there (it was like this in FT written in Delphi), and that both programs are running as the same user?

It sounds rather lame, but if you check for all values being 0, it would solve your latter issue. All trackers use imprecise numerical methods for the purpose of retrieving the rotation and translation, and chances of it ever being computed to all zeros are amazingly slim.

Unfortunately the beginning part of the FT memory mapping is set in stone and if a new data element was added, you'd lose compatibility with FreeTrack, the Pascal/Delphi software.

Edit: In case you find this helpful, here's the canonical way of accessing memory mappings: https://sourceforge.net/p/facetracknoir/codegit/ci/develop/tree/compat/compat.cpp
« Last Edit: July 20, 2013, 03:09:44 pm by foobie42 »
Logged

cameni

  • Brano Kemen
  • Outerra Administrator
  • Hero Member
  • *****
  • Posts: 6721
  • No sense of urgency.
    • outerra.com
Re: TrackIR
« Reply #42 on: July 20, 2013, 03:16:27 pm »

Yes, both programs are running under the same user, and the mutex name is correct as in that file (I copied them from there).
Double checked if I didn't make a mistake, but I'm getting this:

Code: [Select]
if(prevDataID != pMemData->data.DataID) {
    ...
}
else {
    //here sometimes prevDataID != pMemData->data.DataID
}

Can I detect that the tracker provides some extra info after the FT part? Or the tracker type/version.
I saw some version/provider info methods as dll exports in freetrackclient.cpp, but since this here works through the shared memory mapping we aren't loading/exporting anything.
Logged

foobie42

  • Member
  • **
  • Posts: 63
  • newbie
Re: TrackIR
« Reply #43 on: July 20, 2013, 03:24:27 pm »

Yes, both on develop and master branches, DataID isn't protected by a mutex, even though rest of the data members are.

Paging Wim Vriend, hoping he'll step in and get this fixed in time for 1.8.

Only added data after the 'portable' part of the mapping is what's necessary to pass the NPClient 'api key' through the mappings. So it turns out tracker/filter data isn't passed in any way, no :(

I've fixed the DataID race in my fork ages ago: https://github.com/opentrack/opentrack/blob/master/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp but chances of it finding its way back to the original project are pretty slim :(

I'd disregard the DataID, treat data as always fresh, except for the all-zeros case. Does that sound even remotely sensible?

Will try to get DataID fix into the develop branch, fix mismatched locking, and some logic errors introduced into the shared memory segment class, in worst case I'll lose commit privileges but if hadn't given up on the parent project, wouldn't have forked it in the first place.
« Last Edit: July 20, 2013, 03:26:08 pm by foobie42 »
Logged

cameni

  • Brano Kemen
  • Outerra Administrator
  • Hero Member
  • *****
  • Posts: 6721
  • No sense of urgency.
    • outerra.com
Re: TrackIR
« Reply #44 on: July 20, 2013, 03:35:07 pm »

I'd disregard the DataID, treat data as always fresh, except for the all-zeros case. Does that sound even remotely sensible?
Okay, that sounds reasonable.

I have yet to test it with FreeTrack and OpenTrack, but with FTNoIR and with the 3-point cap the tracker often freezes and stops updating, or when one point vanishes (turning to the side too much) and then returns back, the angles are all wrong, yaw = 180° and such, and I have to stop/start it. Not sure if I'm doing something wrong there.
Logged
Pages: 1 2 [3] 4 5 ... 7