libvisiontransfer  10.6.0
protocol-sh2-imu-bno080.h
1 /*******************************************************************************
2  * Copyright (c) 2023 Allied Vision Technologies GmbH
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *******************************************************************************/
14 
15 #ifndef VISIONTRANSFER_PROTOCOL_SH2_IMU_BNO080
16 #define VISIONTRANSFER_PROTOCOL_SH2_IMU_BNO080
17 
18 #include <cstdint>
19 
20 namespace visiontransfer {
21 namespace internal {
22 
23 struct SH2Constants {
24  static constexpr uint8_t CHANNEL_COMMAND = 0;
25  static constexpr uint8_t CHANNEL_EXECUTABLE = 1;
26  static constexpr uint8_t CHANNEL_CONTROL = 2;
27  static constexpr uint8_t CHANNEL_REPORTS = 3;
28  static constexpr uint8_t CHANNEL_WAKE_REPORTS= 4;
29  static constexpr uint8_t CHANNEL_GYRO = 5;
30 
31  static constexpr uint8_t REPORT_COMMAND_RESPONSE = 0xf1;
32  static constexpr uint8_t REPORT_COMMAND_REQUEST = 0xf2;
33  static constexpr uint8_t REPORT_FRS_READ_RESPONSE = 0xf3;
34  static constexpr uint8_t REPORT_FRS_READ_REQUEST = 0xf4;
35  static constexpr uint8_t REPORT_FRS_WRITE_RESPONSE = 0xf5;
36  static constexpr uint8_t REPORT_FRS_WRITE_DATA = 0xf6;
37  static constexpr uint8_t REPORT_FRS_WRITE_REQUEST = 0xf7;
38  static constexpr uint8_t REPORT_PRODUCT_ID_RESPONSE = 0xf8;
39  static constexpr uint8_t REPORT_PRODUCT_ID_REQUEST = 0xf9;
40  static constexpr uint8_t REPORT_TIMESTAMP_REBASE = 0xfa;
41  static constexpr uint8_t REPORT_BASE_TIMESTAMP_REFERENCE = 0xfb;
42  static constexpr uint8_t REPORT_GET_FEATURE_RESPONSE = 0xfc;
43  static constexpr uint8_t REPORT_SET_FEATURE_COMMAND = 0xfd;
44  static constexpr uint8_t REPORT_GET_FEATURE_REQUEST = 0xfe;
45 
46  // Commands supported by report 0xf2 / 0xf1
47  static constexpr uint8_t COMMAND_REPORT_ERRORS = 0x01;
48  static constexpr uint8_t COMMAND_COUNTS = 0x02;
49  static constexpr uint8_t COMMAND_TARE = 0x03;
50  static constexpr uint8_t COMMAND_INITIALIZE = 0x04;
51  static constexpr uint8_t COMMAND_RESERVED_05 = 0x05;
52  static constexpr uint8_t COMMAND_SAVE_DCD = 0x06;
53  static constexpr uint8_t COMMAND_ME_CALIBRATION = 0x07;
54  static constexpr uint8_t COMMAND_RESERVED_08 = 0x08;
55  static constexpr uint8_t COMMAND_PERIODIC_DCD_SAVE = 0x09;
56  static constexpr uint8_t COMMAND_GET_OSCILLATOR_TYPE = 0x0a;
57  static constexpr uint8_t COMMAND_CLEAR_DCD_AND_RESET = 0x0b;
58  static constexpr uint8_t COMMAND_CALIBRATION = 0x0c;
59  static constexpr uint8_t COMMAND_BOOTLOADER = 0x0d;
60  static constexpr uint8_t COMMAND_INTERACTIVE_CALIBRATION = 0x0e;
61 
62  // Subcommands, for certain commands only
63  // DCD / ME / Bootloader not considered yet, here
64  static constexpr uint8_t SUBCOMMAND_COUNTS__GET_COUNTS = 0x00;
65  static constexpr uint8_t SUBCOMMAND_COUNTS__CLEAR_COUNTS = 0x01;
66  static constexpr uint8_t SUBCOMMAND_TARE__TARE_NOW = 0x00;
67  static constexpr uint8_t SUBCOMMAND_TARE__PERSIST_TARE = 0x01;
68  static constexpr uint8_t SUBCOMMAND_TARE__SET_REORIENTATION = 0x02;
69  static constexpr uint8_t SUBCOMMAND_CALIBRATION__START_CALIBRATION = 0x00;
70  static constexpr uint8_t SUBCOMMAND_CALIBRATION__FINISH_CALIBRATION = 0x01;
71 
72  // What to tare (can be ORed)
73  static constexpr uint8_t TARE_AXIS_X = 1;
74  static constexpr uint8_t TARE_AXIS_Y = 2;
75  static constexpr uint8_t TARE_AXIS_Z = 4;
76 
77  // Reference for tare operation
78  static constexpr uint8_t TARE_BASE_ROTATION_VECTOR = 0;
79  static constexpr uint8_t TARE_BASE_GAMING_ROTATION_VECTOR = 1;
80  static constexpr uint8_t TARE_BASE_GEOMAGNETIC_ROTATION_VECTOR = 2;
81  static constexpr uint8_t TARE_BASE_GYRO_INTEGRATED_ROTATION_VECTOR = 3;
82  static constexpr uint8_t TARE_BASE_ARVR_STABILIZED_ROTATION_VECTOR = 4;
83  static constexpr uint8_t TARE_BASE_ARVR_STABILIZED_GAME_ROTATION_VECTOR= 5;
84 
85  // Sensor types (= sensor input report ID)
86  static constexpr uint8_t SENSOR_ACCELEROMETER = 0x01;
87  static constexpr uint8_t SENSOR_GYROSCOPE = 0x02;
88  static constexpr uint8_t SENSOR_MAGNETOMETER = 0x03;
89  static constexpr uint8_t SENSOR_LINEAR_ACCELERATION = 0x04;
90  static constexpr uint8_t SENSOR_ROTATION_VECTOR = 0x05;
91  static constexpr uint8_t SENSOR_GRAVITY = 0x06;
92  static constexpr uint8_t SENSOR_GYROSCOPE_UNCALIBRATED = 0x07;
93  static constexpr uint8_t SENSOR_GAME_ROTATION_VECTOR = 0x08;
94  static constexpr uint8_t SENSOR_GEOMAGNETIC_ROTATION = 0x09;
95  static constexpr uint8_t SENSOR_PRESSURE = 0x0a;
96  static constexpr uint8_t SENSOR_AMBIENT_LIGHT = 0x0b;
97  static constexpr uint8_t SENSOR_HUMIDITY = 0x0c;
98  static constexpr uint8_t SENSOR_PROXIMITY = 0x0d;
99  static constexpr uint8_t SENSOR_TEMPERATURE = 0x0e;
100  static constexpr uint8_t SENSOR_MAGNETOMETER_UNCALIBRATED = 0x0f;
101  static constexpr uint8_t SENSOR_TAP_DETECTOR = 0x10;
102  static constexpr uint8_t SENSOR_STEP_COUNTER = 0x11;
103  static constexpr uint8_t SENSOR_SIGNIFICANT_MOTION = 0x12;
104  static constexpr uint8_t SENSOR_STABILITY_CLASSIFIER = 0x13;
105  static constexpr uint8_t SENSOR_ACCELEROMETER_RAW = 0x14;
106  static constexpr uint8_t SENSOR_GYROSCOPE_RAW = 0x15;
107  static constexpr uint8_t SENSOR_MAGNETOMETER_RAW = 0x16;
108  static constexpr uint8_t SENSOR_STEP_DETECTOR = 0x18;
109  static constexpr uint8_t SENSOR_SHAKE_DETECTOR = 0x19;
110  static constexpr uint8_t SENSOR_FLIP_DETECTOR = 0x1a;
111  static constexpr uint8_t SENSOR_PICKUP_DETECTOR = 0x1b;
112  static constexpr uint8_t SENSOR_STABILITY_DETECTOR = 0x1c;
113  static constexpr uint8_t SENSOR_PERSONAL_ACTIVITY_CLASSIFIER = 0x1e;
114  static constexpr uint8_t SENSOR_SLEEP_DETECTOR = 0x1f;
115  static constexpr uint8_t SENSOR_TILT_DETECTOR = 0x20;
116  static constexpr uint8_t SENSOR_POCKET_DETECTOR = 0x21;
117  static constexpr uint8_t SENSOR_CIRCLE_DETECTOR = 0x22;
118  static constexpr uint8_t SENSOR_HEART_RATE_MONITOR = 0x23;
119  static constexpr uint8_t SENSOR_ARVR_STABILIZED_ROTATION_VECTOR = 0x28;
120  static constexpr uint8_t SENSOR_ARVR_STABILIZED_GAME_ROTATION_VECTOR= 0x29;
121  static constexpr uint8_t SENSOR_GYRO_INTEGRATED_ROTATION_VECTOR = 0x2a;
122  static constexpr uint8_t SENSOR_MOTION_REQUEST = 0x2b;
123 
124  // FRS Configuration Response: Status/Error field
125  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_WORDS_RECEIVED = 0x00;
126  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_UNRECOGNIZED_FRS_TYPE = 0x01;
127  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_BUSY = 0x02;
128  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_WRITE_COMPLETED = 0x03;
129  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_WRITE_MODE_READY = 0x04;
130  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_WRITE_FAILED = 0x05;
131  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_UNEXPECTED_DATA = 0x06;
132  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_INVALID_LENGTH = 0x07;
133  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_RECORD_VALID = 0x08;
134  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_RECORD_INVALID = 0x09;
135  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_DEVICE_ERROR__DEPRECATED = 0x0A;
136  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_READ_ONLY_RECORD = 0x0B;
137  static constexpr uint8_t FRS_WRITE_RESPONSE_STATUS_CANNOT_WRITE_MEMORY_FULL = 0x0C;
138 };
139 
140 inline uint64_t sh2GetU64(const unsigned char* d) {
141  return static_cast<uint64_t>(d[0]) | (static_cast<uint64_t>(d[1]) << 8)
142  | (static_cast<uint64_t>(d[2]) << 16) | (static_cast<uint64_t>(d[3]) << 24)
143  | (static_cast<uint64_t>(d[4]) << 32) | (static_cast<uint64_t>(d[5]) << 40)
144  | (static_cast<uint64_t>(d[6]) << 48) | (static_cast<uint64_t>(d[7]) << 56);
145 }
146 inline uint32_t sh2GetU32(const unsigned char* d) {
147  return static_cast<uint64_t>(d[0]) | (static_cast<uint64_t>(d[1]) << 8) |
148  (static_cast<uint64_t>(d[2]) << 16) | (static_cast<uint64_t>(d[3]) << 24);
149 }
150 inline uint16_t sh2GetU16(const unsigned char* d) {
151  return static_cast<uint16_t>(d[0]) | (static_cast<uint16_t>(d[1]) << 8);
152 }
153 inline uint8_t sh2GetU8(const unsigned char* d) {
154  return d[0];
155 }
156 inline double sh2ConvertFixedQ16(uint16_t v, unsigned char q) {
157  return (double) ((int16_t) v) / (double)(1 << q);
158 }
159 
160 inline int sh2GetSensorReportLength(unsigned int sensorReportID) {
161  switch(sensorReportID) {
162  case SH2Constants::SENSOR_ACCELEROMETER: return 10; //ID 0x01
163  case SH2Constants::SENSOR_GYROSCOPE: return 10; //ID 0x02
164  case SH2Constants::SENSOR_MAGNETOMETER: return 10; //ID 0x03
165  case SH2Constants::SENSOR_LINEAR_ACCELERATION: return 10; //ID 0x04
166  case SH2Constants::SENSOR_ROTATION_VECTOR: return 14; //ID 0x05
167  case SH2Constants::SENSOR_GRAVITY: return 10; //ID 0x06
168  case SH2Constants::SENSOR_GYROSCOPE_UNCALIBRATED: return 16; //ID 0x07
169  case SH2Constants::SENSOR_GAME_ROTATION_VECTOR: return 12; //ID 0x08
170  case SH2Constants::SENSOR_GEOMAGNETIC_ROTATION: return 14; //ID 0x09
171  case SH2Constants::SENSOR_PRESSURE: return 8; //ID 0x0a
172  case SH2Constants::SENSOR_AMBIENT_LIGHT: return 8; //ID 0x0b
173  case SH2Constants::SENSOR_HUMIDITY: return 6; //ID 0x0c
174  case SH2Constants::SENSOR_PROXIMITY: return 6; //ID 0x0d
175  case SH2Constants::SENSOR_TEMPERATURE: return 6; //ID 0x0e
176  case SH2Constants::SENSOR_MAGNETOMETER_UNCALIBRATED: return 16; //ID 0x0f
177  case SH2Constants::SENSOR_TAP_DETECTOR: return 5; //ID 0x10
178  case SH2Constants::SENSOR_STEP_COUNTER: return 12; //ID 0x11
179  case SH2Constants::SENSOR_SIGNIFICANT_MOTION: return 6; //ID 0x12
180  case SH2Constants::SENSOR_STABILITY_CLASSIFIER: return 6; //ID 0x13
181  case SH2Constants::SENSOR_ACCELEROMETER_RAW: return 16; //ID 0x14
182  case SH2Constants::SENSOR_GYROSCOPE_RAW: return 16; //ID 0x15
183  case SH2Constants::SENSOR_MAGNETOMETER_RAW: return 16; //ID 0x16
184  case SH2Constants::SENSOR_STEP_DETECTOR: return 8; //ID 0x18
185  case SH2Constants::SENSOR_SHAKE_DETECTOR: return 6; //ID 0x19
186  case SH2Constants::SENSOR_FLIP_DETECTOR: return 6; //ID 0x1a
187  case SH2Constants::SENSOR_PICKUP_DETECTOR: return 6; //ID 0x1b
188  case SH2Constants::SENSOR_STABILITY_DETECTOR: return 6; //ID 0x1c
189  case SH2Constants::SENSOR_PERSONAL_ACTIVITY_CLASSIFIER: return 16; //ID 0x1e
190  case SH2Constants::SENSOR_SLEEP_DETECTOR: return 6; //ID 0x1f
191  case SH2Constants::SENSOR_TILT_DETECTOR: return 6; //ID 0x20
192  case SH2Constants::SENSOR_POCKET_DETECTOR: return 6; //ID 0x21
193  case SH2Constants::SENSOR_CIRCLE_DETECTOR: return 6; //ID 0x22
194  case SH2Constants::SENSOR_HEART_RATE_MONITOR: return 6; //ID 0x23
195  case SH2Constants::SENSOR_ARVR_STABILIZED_ROTATION_VECTOR: return 14; //ID 0x28
196  case SH2Constants::SENSOR_ARVR_STABILIZED_GAME_ROTATION_VECTOR: return 12; //ID 0x29
197  case SH2Constants::SENSOR_GYRO_INTEGRATED_ROTATION_VECTOR: return 14; //ID 0x2a
198  case SH2Constants::SENSOR_MOTION_REQUEST: return 6; //ID 0x2b
199  default: return -1;
200  }
201 }
202 
203 // The Q point for fixed-point values, i.e. the base 2 exponent for division
204 // for consistency reasons also 0 for N/A / undefined
205 inline int sh2GetSensorQPoint(unsigned int sensorReportID) {
206  switch(sensorReportID) {
207  case SH2Constants::SENSOR_ACCELEROMETER: return 8; //ID 0x01
208  case SH2Constants::SENSOR_GYROSCOPE: return 9; //ID 0x02
209  case SH2Constants::SENSOR_MAGNETOMETER: return 4; //ID 0x03
210  case SH2Constants::SENSOR_LINEAR_ACCELERATION: return 8; //ID 0x04
211  case SH2Constants::SENSOR_ROTATION_VECTOR: return 14; //ID 0x05 // but 12 for accuracy fields
212  case SH2Constants::SENSOR_GRAVITY: return 8; //ID 0x06
213  case SH2Constants::SENSOR_GYROSCOPE_UNCALIBRATED: return 9; //ID 0x07
214  case SH2Constants::SENSOR_GAME_ROTATION_VECTOR: return 14; //ID 0x08
215  case SH2Constants::SENSOR_GEOMAGNETIC_ROTATION: return 14; //ID 0x09
216  case SH2Constants::SENSOR_PRESSURE: return 20; //ID 0x0a
217  case SH2Constants::SENSOR_AMBIENT_LIGHT: return 8; //ID 0x0b
218  case SH2Constants::SENSOR_HUMIDITY: return 8; //ID 0x0c
219  case SH2Constants::SENSOR_PROXIMITY: return 4; //ID 0x0d
220  case SH2Constants::SENSOR_TEMPERATURE: return 7; //ID 0x0e
221  case SH2Constants::SENSOR_MAGNETOMETER_UNCALIBRATED: return 4; //ID 0x0f
222  case SH2Constants::SENSOR_TAP_DETECTOR: return 0; //ID 0x10
223  case SH2Constants::SENSOR_STEP_COUNTER: return 0; //ID 0x11
224  case SH2Constants::SENSOR_SIGNIFICANT_MOTION: return 0; //ID 0x12
225  case SH2Constants::SENSOR_STABILITY_CLASSIFIER: return 0; //ID 0x13
226  case SH2Constants::SENSOR_ACCELEROMETER_RAW: return 0; //ID 0x14
227  case SH2Constants::SENSOR_GYROSCOPE_RAW: return 0; //ID 0x15
228  case SH2Constants::SENSOR_MAGNETOMETER_RAW: return 0; //ID 0x16
229  case SH2Constants::SENSOR_STEP_DETECTOR: return 0; //ID 0x18
230  case SH2Constants::SENSOR_SHAKE_DETECTOR: return 0; //ID 0x19
231  case SH2Constants::SENSOR_FLIP_DETECTOR: return 0; //ID 0x1a
232  case SH2Constants::SENSOR_PICKUP_DETECTOR: return 0; //ID 0x1b
233  case SH2Constants::SENSOR_STABILITY_DETECTOR: return 0; //ID 0x1c
234  case SH2Constants::SENSOR_PERSONAL_ACTIVITY_CLASSIFIER: return 0; //ID 0x1e
235  case SH2Constants::SENSOR_SLEEP_DETECTOR: return 0; //ID 0x1f
236  case SH2Constants::SENSOR_TILT_DETECTOR: return 0; //ID 0x20
237  case SH2Constants::SENSOR_POCKET_DETECTOR: return 0; //ID 0x21
238  case SH2Constants::SENSOR_CIRCLE_DETECTOR: return 0; //ID 0x22
239  case SH2Constants::SENSOR_HEART_RATE_MONITOR: return 0; //ID 0x23
240  case SH2Constants::SENSOR_ARVR_STABILIZED_ROTATION_VECTOR: return 14; //ID 0x28
241  case SH2Constants::SENSOR_ARVR_STABILIZED_GAME_ROTATION_VECTOR: return 14; //ID 0x29
242  case SH2Constants::SENSOR_GYRO_INTEGRATED_ROTATION_VECTOR: return 14; //ID 0x2a // but 10 for angular velocity
243  case SH2Constants::SENSOR_MOTION_REQUEST: return 0; //ID 0x2b
244  default: return 0;
245  }
246 }
247 
248 inline const char* sh2GetSensorName(unsigned int sensorReportID) {
249  switch(sensorReportID) {
250  case SH2Constants::SENSOR_ACCELEROMETER: return "Accelerometer";
251  case SH2Constants::SENSOR_GYROSCOPE: return "Gyroscope";
252  case SH2Constants::SENSOR_MAGNETOMETER: return "Magnetometer";
253  case SH2Constants::SENSOR_LINEAR_ACCELERATION: return "Linear Acceleration";
254  case SH2Constants::SENSOR_ROTATION_VECTOR: return "Rotation Vector";
255  case SH2Constants::SENSOR_GRAVITY: return "Gravity";
256  case SH2Constants::SENSOR_GYROSCOPE_UNCALIBRATED: return "Gyroscope Uncalibrated";
257  case SH2Constants::SENSOR_GAME_ROTATION_VECTOR: return "Game Rotation Vector";
258  case SH2Constants::SENSOR_GEOMAGNETIC_ROTATION: return "Geomagnetic Rotation";
259  case SH2Constants::SENSOR_PRESSURE: return "Pressure";
260  case SH2Constants::SENSOR_AMBIENT_LIGHT: return "Ambient Light";
261  case SH2Constants::SENSOR_HUMIDITY: return "Humidity";
262  case SH2Constants::SENSOR_PROXIMITY: return "Proximity";
263  case SH2Constants::SENSOR_TEMPERATURE: return "Temperature";
264  case SH2Constants::SENSOR_MAGNETOMETER_UNCALIBRATED: return "Magnetometer Uncalibrated";
265  case SH2Constants::SENSOR_TAP_DETECTOR: return "Tap Detector";
266  case SH2Constants::SENSOR_STEP_COUNTER: return "Step Counter";
267  case SH2Constants::SENSOR_SIGNIFICANT_MOTION: return "Significant Motion";
268  case SH2Constants::SENSOR_STABILITY_CLASSIFIER: return "Stability Classifier";
269  case SH2Constants::SENSOR_ACCELEROMETER_RAW: return "Accelerometer Raw";
270  case SH2Constants::SENSOR_GYROSCOPE_RAW: return "Gyroscope Raw";
271  case SH2Constants::SENSOR_MAGNETOMETER_RAW: return "Magnetometer Raw";
272  case SH2Constants::SENSOR_STEP_DETECTOR: return "Step Detector";
273  case SH2Constants::SENSOR_SHAKE_DETECTOR: return "Shake Detector";
274  case SH2Constants::SENSOR_FLIP_DETECTOR: return "Flip Detector";
275  case SH2Constants::SENSOR_PICKUP_DETECTOR: return "Pickup Detector";
276  case SH2Constants::SENSOR_STABILITY_DETECTOR: return "Stability Detector";
277  case SH2Constants::SENSOR_PERSONAL_ACTIVITY_CLASSIFIER: return "Personal Activity Classifier";
278  case SH2Constants::SENSOR_SLEEP_DETECTOR: return "Sleep Detector";
279  case SH2Constants::SENSOR_TILT_DETECTOR: return "Tilt Detector";
280  case SH2Constants::SENSOR_POCKET_DETECTOR: return "Pocket Detector";
281  case SH2Constants::SENSOR_CIRCLE_DETECTOR: return "Circle Detector";
282  case SH2Constants::SENSOR_HEART_RATE_MONITOR: return "Heart Rate Monitor";
283  case SH2Constants::SENSOR_ARVR_STABILIZED_ROTATION_VECTOR: return "ARVR-Stabilized Rotation Vector";
284  case SH2Constants::SENSOR_ARVR_STABILIZED_GAME_ROTATION_VECTOR: return "ARVR-Stabilized Game Rotation Vector";
285  case SH2Constants::SENSOR_GYRO_INTEGRATED_ROTATION_VECTOR: return "Gyro-Integrated Rotation Vector";
286  case SH2Constants::SENSOR_MOTION_REQUEST: return "Motion Request";
287  default: return "UNKNOWN";
288  }
289 }
290 
291 // Convenience function to return the appropriate unit string, if applicable
292 inline const char* sh2GetSensorUnit(unsigned int sensorReportID) {
293  switch(sensorReportID) {
294  case SH2Constants::SENSOR_ACCELEROMETER: //ID 0x01
295  case SH2Constants::SENSOR_LINEAR_ACCELERATION: //ID 0x04
296  case SH2Constants::SENSOR_GRAVITY: return "m/s²"; //ID 0x06
297  case SH2Constants::SENSOR_GYROSCOPE: //ID 0x02
298  case SH2Constants::SENSOR_GYROSCOPE_UNCALIBRATED: return "rad/s"; //ID 0x07
299  case SH2Constants::SENSOR_MAGNETOMETER: //ID 0x03
300  case SH2Constants::SENSOR_MAGNETOMETER_UNCALIBRATED: return "μT"; //ID 0x0f
301  case SH2Constants::SENSOR_PRESSURE: return "hPa"; //ID 0x0a
302  case SH2Constants::SENSOR_AMBIENT_LIGHT: return "lx"; //ID 0x0b "cd/m²"
303  case SH2Constants::SENSOR_HUMIDITY: return "%"; //ID 0x0c
304  case SH2Constants::SENSOR_PROXIMITY: return "cm"; //ID 0x0d
305  case SH2Constants::SENSOR_TEMPERATURE: return "°C"; //ID 0x0e
306  default: return "";
307  }
308 }
309 
310 inline const char* sh2GetCommandName(unsigned int cmdID) {
311  static const char* cmdNames[] = {"Reserved", "Errors", "Counter", "Tare", "Initialize",
312  "Reserved", "Save DCD", "ME Calibration", "Reserved", "Periodic DCD Save", "Get Oscillator Type",
313  "Clear DCD and Reset", "Calibration", "Bootloader", "Interactive Calibration"};
314  if (cmdID < sizeof(cmdNames)) return cmdNames[cmdID];
315  else return "Unknown";
316 }
317 
318 #pragma pack(push,1) // Packed struct definitions from SH-2, co-opted for transfer
319 
320 // Common prefix for all SH-2 cargos. SHTP headers irrelevant and not represented.
321 class SH2CargoBase {
322 private:
323  uint8_t cargoLength[2];
324  uint8_t channel;
325  uint8_t sequenceNumber;
326  uint8_t reportType;
327 public:
328  inline uint16_t getCargoLength() const { return sh2GetU16(cargoLength) & 0x7fff; } // mask out subtransfer bit
329  inline uint8_t getChannel() const { return channel; }
330  inline uint8_t getSequenceNumber() const { return sequenceNumber; }
331  inline uint8_t getReportType() const { return reportType; }
332 };
333 
334 // Our own custom extension for sending the raw interrupt timestamp (report 0xFF, never reported by SH2)
335 class SH2CargoBodyScenescanTimestamp {
336 private:
337  SH2CargoBase base;
338  uint8_t usecSinceEpoch[8]; // 64-bit microsecond count
339 public:
340  inline uint64_t getUSecSinceEpoch() const { return (uint64_t) sh2GetU64(usecSinceEpoch); }
341 };
342 
343 // A Timestamp Rebase (0xFA), reporting additional sensor delay offset since last Timebase
344 class SH2CargoBodyTimestampRebase {
345 private:
346  SH2CargoBase base;
347  uint8_t rebaseTime[4];
348 public:
349  inline long getRebaseTime() const { return (int32_t) sh2GetU32(rebaseTime); }
350 };
351 
352 // A Time Base report with a batch transfer (0xFB)
353 // It may be followed by any amount of sensor reports, below.
354 // Refer to the base.getCargoLength() value and the known
355 // record sizes for parsing them.
356 class SH2CargoBodyTimeBase {
357 private:
358  SH2CargoBase base;
359  uint8_t timeBase_100uSec[4];
360 public:
361  inline long getTimeBase() const { return 100l * sh2GetU32(timeBase_100uSec); }
362 };
363 
364 // Common base prefix for all sensor reports
365 class SH2SensorReportBase {
366 private:
367  uint8_t sensorID;
368  uint8_t sequenceNumber;
369  uint8_t statusAndDelayMSB;
370  uint8_t delayLSB;
371 public:
372  inline unsigned int getStatus() const { return statusAndDelayMSB & 0x03; }
373  inline unsigned int getDelay() const { return ((statusAndDelayMSB & 0xfc) << 6) | delayLSB; }
374 };
375 
376 // 10-byte reports with individual Q scaling for non-raw 3D sensors
377 class SH2SensorReportAccelerometer {
378 private:
379  SH2SensorReportBase base;
380  uint8_t xAxis[2];
381  uint8_t yAxis[2];
382  uint8_t zAxis[2];
383 public:
384  inline double getX() const { return sh2ConvertFixedQ16(sh2GetU16(xAxis), 8); } // Accel Q: shift 8 bits
385  inline double getY() const { return sh2ConvertFixedQ16(sh2GetU16(yAxis), 8); }
386  inline double getZ() const { return sh2ConvertFixedQ16(sh2GetU16(zAxis), 8); }
387 };
388 class SH2SensorReportMagnetometer {
389 private:
390  SH2SensorReportBase base;
391  uint8_t xAxis[2];
392  uint8_t yAxis[2];
393  uint8_t zAxis[2];
394 public:
395  inline double getX() const { return sh2ConvertFixedQ16(sh2GetU16(xAxis), 4); } // Magn Q: shift 4 bits
396  inline double getY() const { return sh2ConvertFixedQ16(sh2GetU16(yAxis), 4); }
397  inline double getZ() const { return sh2ConvertFixedQ16(sh2GetU16(zAxis), 4); }
398 };
399 class SH2SensorReportGyroscope {
400 private:
402  uint8_t xAxis[2];
403  uint8_t yAxis[2];
404  uint8_t zAxis[2];
405 public:
406  inline double getX() const { return sh2ConvertFixedQ16(sh2GetU16(xAxis), 9); } // Gyro Q: shift 9 bits
407  inline double getY() const { return sh2ConvertFixedQ16(sh2GetU16(yAxis), 9); }
408  inline double getZ() const { return sh2ConvertFixedQ16(sh2GetU16(zAxis), 9); }
409 };
410 
411 // 14-byte orientation (quaternion) data. i,j,k,real are also known as x,y,z,w
413 private:
414  SH2SensorReportBase base;
415  uint8_t quatI[2];
416  uint8_t quatJ[2];
417  uint8_t quatK[2];
418  uint8_t quatReal[2];
419  uint8_t accuracy[2];
420 public:
421  inline double getI() const { return sh2ConvertFixedQ16(sh2GetU16(quatI), 14); } // Quaternion data: shift 14 bits
422  inline double getJ() const { return sh2ConvertFixedQ16(sh2GetU16(quatJ), 14); }
423  inline double getK() const { return sh2ConvertFixedQ16(sh2GetU16(quatK), 14); }
424  inline double getReal() const { return sh2ConvertFixedQ16(sh2GetU16(quatReal), 14); }
425  inline double getAccuracy() const { return sh2ConvertFixedQ16(sh2GetU16(accuracy), 12); } // Accuracy: shift 12
426 };
427 
428 // 6-byte 1D sensor (pressure, ambient light, humidity, proximity, temperature,
429 // 16-byte data for *raw* accelerometer, gyro, magnetometer
430 class SH2SensorReportRawAGM {
431 private:
432  SH2SensorReportBase base;
433  uint8_t xAxisRaw[2];
434  uint8_t yAxisRaw[2];
435  uint8_t zAxisRaw[2];
436  uint8_t temperature_forGyro[2];
437  uint8_t timestamp[4];
438 };
439 
440 #pragma pack(pop) // End of common sensor data / transport packed struct definitions
441 
442 }} // namespaces
443 
444 #endif
445 
visiontransfer::internal::SH2CargoBase
Definition: protocol-sh2-imu-bno080.h:345
visiontransfer::internal::SH2SensorReportOrientation
Definition: protocol-sh2-imu-bno080.h:436
visiontransfer::internal::SH2SensorReportBase
Definition: protocol-sh2-imu-bno080.h:389
Allied Vision