The Game-Trak by In2Games is a funny little PS2 or PC input device.
It determines the 3D-position of two tracked objects via quite the clever method.
if you remember vectors from maths-class, you probably remember that a vector going from (0,0,0) to a point in space
can be defined by the 3D-Coordinates of that point. You might also remember that a vector has a certian length,
and that its angles to any axis of the coordinate system can be calculated.
The Game-Trak does this in reverse. A string can be pulled out of the device and
a ball-joint at the base out of which the string is pulledm tilts in the direction of the string.
The length of the string, aswell as the two angles of the rotational axis of the ball-joint are measured,
becoming the length of the vector, aswell as the ball-joint's angles becoming the vectors angles to the x- and z-Axis.
Those values are transmitted to the PS2 or PC which takes the angles and length to create a vector pointing in 3D-Space
to the position of the tracked object, for example a hand.
The Game-Trak connects via USB and is recognized as an HID-Device. Using libraries like hidapi in C or hid (which uses hidapi) in python, you can read some data from the Game-Trak.
The Game-Trak returns 16 bytes of data every update:
(left_hor, left_ver, left_len, right_hor, right_ver, right_len, buttons) = struct.unpack("<HHHHHHBxxx",b)or C
struct game_trak_data_t { uint16_t left_angle_horizontal; uint16_t left_angle_vertical; uint16_t left_length; uint16_t right_angle_horizontal; uint16_t right_angle_vertical; uint16_t right_length; uint8_t buttons; //usually 00, 10 when foot-pedal pressed /* 3 bytes unknown*/ };
The angle- and length-values roughly go from 0 to nearly 4096. With the string fully retracted, length returns some value near 4096, fully extended 0. Below is an example on how to interpret the data in python.
import struct, math import hid from binascii import hexlify max_adc_angle = 4000 max_angle = 45 max_adc_len=4075 # adc reading with cables fully retracted max_len = 3.2 #cable length when reading 0 min_len = 0.1 # how many meters out from swivel point does length get detected def deg2rad(deg): return (deg/360) * 2*math.pi def calc_3d(hor,ver,dist): #trigonometry time max_angle_rad = deg2rad(max_angle) hor_rad = (2*(hor / max_adc_angle)-1) * max_angle_rad ver_rad = (2*(ver / max_adc_angle)-1) * max_angle_rad dist_m = ((max_adc_len-dist) / max_adc_len) * (max_len - min_len) dist_m += min_len print("Hor=%.3frad Ver=%.3frad Len=%04.2fm"%(hor_rad,ver_rad,dist_m)) x = dist_m * math.sin(hor_rad) z = dist_m * math.sin(ver_rad) y = dist_m #this is wrong i think but works better then the "proper" way??? print("X%06.3f Y%06.3f Z%06.3f" % (x,y,z)) return (x,y,z) def parse_game_trak(b): (left_hor, left_ver, left_len, right_hor, right_ver, right_len, buttons) = struct.unpack("<HHHHHHBxxx",b) print(left_hor, left_ver, left_len, right_hor, right_ver, right_len) l_pos = calc_3d(left_hor, left_ver, left_len) r_pos = calc_3d(right_hor, right_ver, right_len) with hid.Device(0x0982, 0x0982) as dev: print(f'Device manufacturer: {dev.manufacturer}') print(f'Product: {dev.product}') print(f'Serial Number: {dev.serial}') print("starting") while True: d=dev.read(16, 1000) print(hexlify(d, ' ')) parse_game_trak(d)