vrpn 07.35
Virtual Reality Peripheral Network
 
Loading...
Searching...
No Matches
vrpn_Laputa.C
Go to the documentation of this file.
1
9
10// Based on the vrpn_Oculus driver
11
12#include "vrpn_Laputa.h"
13
14#include "vrpn_BaseClass.h" // for ::vrpn_TEXT_NORMAL, etc
15
17
18#if defined(VRPN_USE_HID)
19
20// USB vendor and product IDs for the models we support
21static const vrpn_uint16 LAPUTA_VENDOR = 0x2633;
22static const vrpn_uint16 LAPUTA_PRODUCT = 0x0006;
23static const vrpn_int32 NUM_CHANNELS = 11;
24
26 : vrpn_Analog(name, c)
28 new vrpn_HidProductAcceptor(LAPUTA_VENDOR, LAPUTA_PRODUCT))
29{
30
31 vrpn_Analog::num_channel = NUM_CHANNELS;
32
33 memset(channel, 0, sizeof(channel));
34 memset(last, 0, sizeof(last));
35}
36
38{
39 try {
40 delete m_acceptor;
41 } catch (...) {
42 fprintf(stderr, "vrpn_Laputa::~vrpn_Laputa(): delete failed\n");
43 return;
44 }
45}
46
47inline void unpackVector(const vrpn_uint8 raw[8], int vector[3])
48{
49 // @todo Make this also work on big-endian architectures.
50 union // Helper union to assemble 3 or 4 bytes into a signed 32-bit integer
51 {
52 vrpn_uint8 b[4];
53 vrpn_int32 i;
54 } p;
55 struct // Helper structure to sign-extend a 21-bit signed integer value
56 {
57 signed int si : 21;
58 } s;
59
60 /* Assemble the vector's x component: */
61 p.b[0] = raw[2];
62 p.b[1] = raw[1];
63 p.b[2] = raw[0];
64 // p.b[3]=0U; // Not needed because it's masked out below anyway
65 vector[0] = s.si = (p.i >> 3) & 0x001fffff;
66
67 /* Assemble the vector's y component: */
68 p.b[0] = raw[5];
69 p.b[1] = raw[4];
70 p.b[2] = raw[3];
71 p.b[3] = raw[2];
72 vector[1] = s.si = (p.i >> 6) & 0x001fffff;
73
74 /* Assemble the vector's z component: */
75 p.b[0] = raw[7];
76 p.b[1] = raw[6];
77 p.b[2] = raw[5];
78 // p.b[3]=0U; // Not needed because it's masked out below anyway
79 vector[2] = s.si = (p.i >> 1) & 0x001fffff;
80}
81
82void vrpn_Laputa::parse_message_type_1(std::size_t bytes, vrpn_uint8 *buffer)
83{
84 size_t num_reports = buffer[1];
85 if (num_reports > 3) {
86 num_reports = 3;
87 }
88
89 // Skip past the report type and num_reports bytes and
90 // start parsing there.
91 vrpn_uint8 *bufptr = &buffer[2];
92
93 // The next two bytes are an increasing counter that changes by 1 for
94 // every report.
95 vrpn_uint16 report_index =
96 vrpn_unbuffer_from_little_endian<vrpn_uint16, vrpn_uint8>(bufptr);
97 channel[1] = report_index;
98
99 // The next two bytes are zero, so we skip them
100 vrpn_uint16 skip =
101 vrpn_unbuffer_from_little_endian<vrpn_uint16, vrpn_uint8>(bufptr);
102
103 // The next entry is temperature, and it may be in hundredths of a degree C
104 const double temperature_scale = 0.01;
105 vrpn_uint16 temperature =
106 vrpn_unbuffer_from_little_endian<vrpn_uint16, vrpn_uint8>(bufptr);
107 channel[0] = temperature * temperature_scale;
108
109 // The magnetometer data comes after the space to store three
110 // reports.
111 vrpn_uint8 *magnetometer_ptr = &buffer[56];
112 vrpn_int16 magnetometer_raw[3];
113 for (size_t i = 0; i < 3; i++) {
114 magnetometer_raw[i] =
115 vrpn_unbuffer_from_little_endian<vrpn_int16, vrpn_uint8>(
116 magnetometer_ptr);
117 }
118 // Invert all axes to make the magnetometer direction match
119 // the sign of the gravity vector.
120 const double magnetometer_scale = 0.0001;
121 channel[8] = -magnetometer_raw[0] * magnetometer_scale;
122 channel[9] = -magnetometer_raw[1] * magnetometer_scale;
123 channel[10] = -magnetometer_raw[2] * magnetometer_scale;
124
125 // Unpack a 16-byte accelerometer/gyro report using the routines from
126 // Oliver's code.
127 for (size_t i = 0; i < num_reports; i++) {
128 vrpn_int32 accelerometer_raw[3];
129 vrpn_int32 gyroscope_raw[3];
130 unpackVector(bufptr, accelerometer_raw);
131 bufptr += 8;
132 unpackVector(bufptr, gyroscope_raw);
133 bufptr += 8;
134
135 // Compute the double values using default calibration.
136 // The accelerometer data goes into analogs 0,1,2.
137 // The gyro data goes into analogs 3,4,5.
138 // The magnetomoter data goes into analogs 6,7,8.
139 const double accelerometer_scale = 0.0001;
140 const double gyroscope_scale = 0.0001;
141 channel[2] =
142 static_cast<double>(accelerometer_raw[0]) * accelerometer_scale;
143 channel[3] =
144 static_cast<double>(accelerometer_raw[1]) * accelerometer_scale;
145 channel[4] =
146 static_cast<double>(accelerometer_raw[2]) * accelerometer_scale;
147
148 channel[5] = static_cast<double>(gyroscope_raw[0]) * gyroscope_scale;
149 channel[6] = static_cast<double>(gyroscope_raw[1]) * gyroscope_scale;
150 channel[7] = static_cast<double>(gyroscope_raw[2]) * gyroscope_scale;
151
153 }
154}
155
157{
158 update();
160}
161
162bool vrpn_Laputa::parse_message(std::size_t bytes, vrpn_uint8 *buffer)
163{
164 return false;
165}
166
167void vrpn_Laputa::on_data_received(std::size_t bytes, vrpn_uint8 *buffer)
168{
169 /* // For debugging
170 printf("Got %d bytes:\n", static_cast<int>(bytes));
171 for (size_t i = 0; i < bytes; i++) {
172 printf("%02X ", buffer[i]);
173 }
174 printf("\n");
175 */
176 // Set the timestamp for all reports
178
179 // Make sure the message length and type is what we expect.
180 // We get 64-byte responses on Windows and 62-byte responses on the mac.
181 if ((bytes != 62) && (bytes != 64)) {
182 fprintf(stderr, "vrpn_Laputa::on_data_received(): Unexpected message "
183 "length %d, ignoring\n",
184 static_cast<int>(bytes));
185 return;
186 }
187
188 switch (buffer[0]) {
189 case 1:
190 parse_message_type_1(bytes, buffer);
191 break;
192 default:
193 // Delegate message type to child
194 if (!parse_message(bytes, buffer)) {
195 fprintf(stderr, "vrpn_Laputa::on_data_received(): Unexpected "
196 "message type %d, ignoring\n",
197 buffer[0]);
198 }
199 break;
200 }
201}
202
203#endif
vrpn_float64 last[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:39
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:38
vrpn_Analog(const char *name, vrpn_Connection *c=NULL)
Definition vrpn_Analog.C:14
vrpn_int32 num_channel
Definition vrpn_Analog.h:40
virtual void report_changes(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report only if something has changed (for servers) Optionally, tell what time to stamp the val...
Definition vrpn_Analog.C:71
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
Generic connection class not specific to the transport mechanism.
vrpn_HidInterface(vrpn_HidAcceptor *acceptor, vrpn_uint16 vendor=0, vrpn_uint16 product=0, hid_device *device=NULL)
Constructor If we already have a HID device from some other source, it can be passed and we'll take o...
vrpn_HidAcceptor * m_acceptor
This is the HidAcceptor we use when reconnecting.
virtual void update()
Polls the device buffers and causes on_data_received callbacks if appropriate You NEED to call this f...
Accepts any device with the given vendor and product IDs.
vrpn_Laputa(const char *name, vrpn_Connection *c=NULL)
Definition vrpn_Laputa.C:25
virtual bool parse_message(std::size_t bytes, vrpn_uint8 *buffer)
struct timeval d_timestamp
Timestamp updated during mainloop()
Definition vrpn_Laputa.h:53
virtual ~vrpn_Laputa()
Destructor.
Definition vrpn_Laputa.C:37
void on_data_received(std::size_t bytes, vrpn_uint8 *buffer)
Extracts the sensor values from each report and calls the appropriate parser.
void parse_message_type_1(std::size_t bytes, vrpn_uint8 *buffer)
Parse and send reports for type-1 message.
Definition vrpn_Laputa.C:82
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
All types of client/server/peer objects in VRPN should be derived from the vrpn_BaseClass type descri...
#define VRPN_SUPPRESS_EMPTY_OBJECT_WARNING()
void unpackVector(const vrpn_uint8 raw[8], int vector[3])
Definition vrpn_Laputa.C:47
Header for Laputa VR devices.
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99