3dmgx2.cc
Go to the documentation of this file.
1 /*
2  * Player - One Hell of a Robot Server
3  * Copyright (C) 2008-20010 Willow Garage
4  *
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 #include <assert.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <math.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <termios.h>
29 #include <unistd.h>
30 #include <netinet/in.h>
31 #include <stdlib.h>
32 
33 #include <sys/time.h>
34 
35 //#include <ros/console.h>
36 
38 
39 #include "poll.h"
40 
41 
43 #define IMU_EXCEPT(except, msg, ...) \
44  { \
45  char buf[1000]; \
46  snprintf(buf, 1000, msg" (in microstrain_3dmgx2_imu::IMU:%s)", ##__VA_ARGS__, __FUNCTION__); \
47  throw except(buf); \
48  }
49 
50 // Some systems (e.g., OS X) require explicit externing of static class
51 // members.
52 extern const double microstrain_3dmgx2_imu::IMU::G;
53 extern const double microstrain_3dmgx2_imu::IMU::KF_K_1;
54 extern const double microstrain_3dmgx2_imu::IMU::KF_K_2;
55 
57 static inline unsigned short bswap_16(unsigned short x) {
58  return (x>>8) | (x<<8);
59 }
60 
62 static inline unsigned int bswap_32(unsigned int x) {
63  return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16));
64 }
65 
66 
68 static float extract_float(uint8_t* addr) {
69 
70  float tmp;
71 
72  *((unsigned char*)(&tmp) + 3) = *(addr);
73  *((unsigned char*)(&tmp) + 2) = *(addr+1);
74  *((unsigned char*)(&tmp) + 1) = *(addr+2);
75  *((unsigned char*)(&tmp)) = *(addr+3);
76 
77  return tmp;
78 }
79 
80 
82 static unsigned long long time_helper()
83 {
84 #if POSIX_TIMERS > 0
85  struct timespec curtime;
86  clock_gettime(CLOCK_REALTIME, &curtime);
87  return (unsigned long long)(curtime.tv_sec) * 1000000000 + (unsigned long long)(curtime.tv_nsec);
88 #else
89  struct timeval timeofday;
90  gettimeofday(&timeofday,NULL);
91  return (unsigned long long)(timeofday.tv_sec) * 1000000000 + (unsigned long long)(timeofday.tv_usec) * 1000;
92 #endif
93 }
94 
95 
97 // Constructor
98 microstrain_3dmgx2_imu::IMU::IMU() : fd(-1), continuous(false), is_gx3(false)
99 { }
100 
101 
103 // Destructor
105 {
106  closePort();
107 }
108 
109 
111 // Open the IMU port
112 void
114 {
115  closePort(); // In case it was previously open, try to close it first.
116 
117  // Open the port
118  fd = open(port_name, O_RDWR | O_SYNC | O_NONBLOCK | O_NOCTTY, S_IRUSR | S_IWUSR );
119  if (fd < 0)
120  {
121  const char *extra_msg = "";
122  switch (errno)
123  {
124  case EACCES:
125  extra_msg = "You probably don't have premission to open the port for reading and writing.";
126  break;
127  case ENOENT:
128  extra_msg = "The requested port does not exist. Is the IMU connected? Was the port name misspelled?";
129  break;
130  }
131 
132  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "Unable to open serial port [%s]. %s. %s", port_name, strerror(errno), extra_msg);
133  }
134 
135  // Lock the port
136  struct flock fl;
137  fl.l_type = F_WRLCK;
138  fl.l_whence = SEEK_SET;
139  fl.l_start = 0;
140  fl.l_len = 0;
141  fl.l_pid = getpid();
142 
143  if (fcntl(fd, F_SETLK, &fl) != 0)
144  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "Device %s is already locked. Try 'lsof | grep %s' to find other processes that currently have the port open.", port_name, port_name);
145 
146  // Change port settings
147  struct termios term;
148  if (tcgetattr(fd, &term) < 0)
149  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "Unable to get serial port attributes. The port you specified (%s) may not be a serial port.", port_name);
150 
151  cfmakeraw( &term );
152  cfsetispeed(&term, B115200);
153  cfsetospeed(&term, B115200);
154 
155  if (tcsetattr(fd, TCSAFLUSH, &term) < 0 )
156  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "Unable to set serial port attributes. The port you specified (%s) may not be a serial port.", port_name);
157 
158  // Stop continuous mode
159  stopContinuous();
160 
161  // Make sure queues are empty before we begin
162  if (tcflush(fd, TCIOFLUSH) != 0)
163  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "Tcflush failed. Please report this error if you see it.");
164 }
165 
166 
168 // Close the IMU port
169 void
171 {
172  if (fd != -1)
173  {
174  if (continuous)
175  {
176  try {
177  //ROS_DEBUG("stopping continuous");
178  stopContinuous();
179 
180  } catch (microstrain_3dmgx2_imu::Exception &e) {
181  // Exceptions here are fine since we are closing anyways
182  }
183  }
184 
185  if (close(fd) != 0)
186  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "Unable to close serial port; [%s]", strerror(errno));
187  fd = -1;
188  }
189 }
190 
191 
192 
194 // Initialize time information
195 void
197 {
198  wraps = 0;
199 
200  uint8_t cmd[1];
201  uint8_t rep[31];
202  cmd[0] = CMD_RAW;
203 
204  transact(cmd, sizeof(cmd), rep, sizeof(rep), 1000);
206 
207  int k = 25;
208  offset_ticks = bswap_32(*(uint32_t*)(rep + k));
210 
211  // reset kalman filter state
212  offset = 0;
213  d_offset = 0;
214  sum_meas = 0;
215  counter = 0;
216 
217  // fixed offset
218  fixed_offset = fix_off;
219 }
220 
222 // Initialize IMU gyros
223 void
224 microstrain_3dmgx2_imu::IMU::initGyros(double* bias_x, double* bias_y, double* bias_z)
225 {
226  wraps = 0;
227 
228  uint8_t cmd[5];
229  uint8_t rep[19];
230 
231  cmd[0] = CMD_CAPTURE_GYRO_BIAS;
232  cmd[1] = 0xC1;
233  cmd[2] = 0x29;
234  *(unsigned short*)(&cmd[3]) = bswap_16(10000);
235 
236  transact(cmd, sizeof(cmd), rep, sizeof(rep), 30000);
237 
238  if (bias_x)
239  *bias_x = extract_float(rep + 1);
240 
241  if (bias_y)
242  *bias_y = extract_float(rep + 5);
243 
244  if (bias_z)
245  *bias_z = extract_float(rep + 9);
246 }
247 
248 
250 // Put the IMU into continuous mode
251 bool
253 {
254  uint8_t cmd[4];
255  uint8_t rep[8];
256 
257  cmd[0] = CMD_CONTINUOUS;
258  cmd[1] = 0xC1; //Confirms user intent
259  cmd[2] = 0x29; //Confirms user intent
260  cmd[3] = command;
261 
262  transact(cmd, sizeof(cmd), rep, sizeof(rep), 1000);
263 
264  // Verify that continuous mode is set on correct command:
265  if (rep[1] != command) {
266  return false;
267  }
268 
269  continuous = true;
270  return true;
271 }
272 
273 
275 // Take the IMU out of continuous mode
276 void
278 {
279  uint8_t cmd[3];
280 
281  cmd[0] = CMD_STOP_CONTINUOUS;
282 
283  cmd[1] = 0x75; // gx3 - confirms user intent
284 
285  cmd[2] = 0xb4; // gx3 - confirms user intent
286 
287  send(cmd, sizeof(cmd));
288 
289  send(cmd, is_gx3 ? 3 : 1);
290 
291  usleep(1000000);
292 
293  if (tcflush(fd, TCIOFLUSH) != 0)
294  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "Tcflush failed");
295 
296  continuous = false;
297 }
298 
299 
300 
302 // Receive ACCEL_ANGRATE_MAG message
303 void
304 microstrain_3dmgx2_imu::IMU::receiveAccelAngrateMag(uint64_t *time, double accel[3], double angrate[3], double mag[3])
305 {
306  int i, k;
307  uint8_t rep[43];
308 
309  uint64_t sys_time;
310  uint64_t imu_time;
311 
312  //ROS_DEBUG("About to do receive.");
313  receive(CMD_ACCEL_ANGRATE_MAG, rep, sizeof(rep), 1000, &sys_time);
314  //ROS_DEBUG("Receive finished.");
315 
316  // Read the acceleration:
317  k = 1;
318  for (i = 0; i < 3; i++)
319  {
320  accel[i] = extract_float(rep + k) * G;
321  k += 4;
322  }
323 
324  // Read the angular rates
325  k = 13;
326  for (i = 0; i < 3; i++)
327  {
328  angrate[i] = extract_float(rep + k);
329  k += 4;
330  }
331 
332  // Read the magnetometer reading.
333  k = 25;
334  for (i = 0; i < 3; i++) {
335  mag[i] = extract_float(rep + k);
336  k += 4;
337  }
338 
339  imu_time = extractTime(rep+37);
340  *time = filterTime(imu_time, sys_time);
341 }
342 
344 // Receive ACCEL_ANGRATE_ORIENTATION message
345 void
346 microstrain_3dmgx2_imu::IMU::receiveAccelAngrateOrientation(uint64_t *time, double accel[3], double angrate[3], double orientation[9])
347 {
348  int i, k;
349  uint8_t rep[67];
350 
351  uint64_t sys_time;
352  uint64_t imu_time;
353 
354  //ROS_DEBUG("About to do receive.");
355  receive(CMD_ACCEL_ANGRATE_ORIENT, rep, sizeof(rep), 1000, &sys_time);
356  //ROS_DEBUG("Finished receive.");
357 
358  // Read the acceleration:
359  k = 1;
360  for (i = 0; i < 3; i++)
361  {
362  accel[i] = extract_float(rep + k) * G;
363  k += 4;
364  }
365 
366  // Read the angular rates
367  k = 13;
368  for (i = 0; i < 3; i++)
369  {
370  angrate[i] = extract_float(rep + k);
371  k += 4;
372  }
373 
374  // Read the orientation matrix
375  k = 25;
376  for (i = 0; i < 9; i++) {
377  orientation[i] = extract_float(rep + k);
378  k += 4;
379  }
380 
381  imu_time = extractTime(rep+61);
382  *time = filterTime(imu_time, sys_time);
383 }
384 
385 
387 // Receive ACCEL_ANGRATE message
388 void
389 microstrain_3dmgx2_imu::IMU::receiveAccelAngrate(uint64_t *time, double accel[3], double angrate[3])
390 {
391  int i, k;
392  uint8_t rep[31];
393 
394  uint64_t sys_time;
395  uint64_t imu_time;
396 
397  receive(CMD_ACCEL_ANGRATE, rep, sizeof(rep), 1000, &sys_time);
398 
399  // Read the acceleration:
400  k = 1;
401  for (i = 0; i < 3; i++)
402  {
403  accel[i] = extract_float(rep + k) * G;
404  k += 4;
405  }
406 
407  // Read the angular rates
408  k = 13;
409  for (i = 0; i < 3; i++)
410  {
411  angrate[i] = extract_float(rep + k);
412  k += 4;
413  }
414 
415  imu_time = extractTime(rep+25);
416  *time = filterTime(imu_time, sys_time);
417 }
418 
420 // Receive DELVEL_DELANG message
421 void
422 microstrain_3dmgx2_imu::IMU::receiveDelvelDelang(uint64_t *time, double delvel[3], double delang[3])
423 {
424  int i, k;
425  uint8_t rep[31];
426 
427  uint64_t sys_time;
428  uint64_t imu_time;
429 
430  receive(CMD_DELVEL_DELANG, rep, sizeof(rep), 1000, &sys_time);
431 
432  // Read the delta angles:
433  k = 1;
434  for (i = 0; i < 3; i++)
435  {
436  delang[i] = extract_float(rep + k);
437  k += 4;
438  }
439 
440  // Read the delta velocities
441  k = 13;
442  for (i = 0; i < 3; i++)
443  {
444  delvel[i] = extract_float(rep + k) * G;
445  k += 4;
446  }
447 
448  imu_time = extractTime(rep+25);
449  *time = filterTime(imu_time, sys_time);
450 }
451 
452 
454 // Receive EULER message
455 void
456 microstrain_3dmgx2_imu::IMU::receiveEuler(uint64_t *time, double *roll, double *pitch, double *yaw)
457 {
458  uint8_t rep[19];
459 
460  uint64_t sys_time;
461  uint64_t imu_time;
462 
463  receive(CMD_EULER, rep, sizeof(rep), 1000, &sys_time);
464 
465  *roll = extract_float(rep + 1);
466  *pitch = extract_float(rep + 5);
467  *yaw = extract_float(rep + 9);
468 
469  imu_time = extractTime(rep + 13);
470  *time = filterTime(imu_time, sys_time);
471 }
472 
474 // Receive Device Identifier String
475 
477 {
478  uint8_t cmd[2];
479  uint8_t rep[20];
480 
481  cmd[0] = CMD_DEV_ID_STR;
482  cmd[1] = type;
483 
484  transact(cmd, sizeof(cmd), rep, sizeof(rep), 1000);
485 
486  if (cmd[0] != CMD_DEV_ID_STR || cmd[1] != type)
487  return false;
488 
489  id[16] = 0;
490  memcpy(id, rep+2, 16);
491 
492  if( type==ID_DEVICE_NAME ){
493  is_gx3 = (strstr(id,"GX3") != NULL);
494  }
495 
496  return true;
497 }
498 
499 /* ideally it would be nice to feed these functions back into willowimu */
500 #define CMD_ACCEL_ANGRATE_MAG_ORIENT_REP_LEN 79
501 #define CMD_RAW_ACCEL_ANGRATE_LEN 31
502 // Receive ACCEL_ANGRATE_MAG_ORIENT message
504 void
505 microstrain_3dmgx2_imu::IMU::receiveAccelAngrateMagOrientation (uint64_t *time, double accel[3], double angrate[3], double mag[3], double orientation[9])
506 {
508 
509  int k, i;
510  uint64_t sys_time;
511  uint64_t imu_time;
512 
513  receive( CMD_ACCEL_ANGRATE_MAG_ORIENT, rep, sizeof(rep), 1000, &sys_time);
514 
515  // Read the acceleration:
516  k = 1;
517  for (i = 0; i < 3; i++)
518  {
519  accel[i] = extract_float(rep + k) * G;
520  k += 4;
521  }
522 
523  // Read the angular rates
524  k = 13;
525  for (i = 0; i < 3; i++)
526  {
527  angrate[i] = extract_float(rep + k);
528  k += 4;
529  }
530 
531  // Read the magnetic field matrix
532  k = 25;
533  for (i = 0; i < 3; i++) {
534  mag[i] = extract_float(rep + k);
535  k += 4;
536  }
537 
538  // Read the orientation matrix
539  k = 37;
540  for (i = 0; i < 9; i++) {
541  orientation[i] = extract_float(rep + k);
542  k += 4;
543  }
544  imu_time = extractTime(rep + 73);
545 
546  *time = filterTime(imu_time, sys_time);
547 }
548 
550 // Receive RAW message
551 // (copy of receive accel angrate but with raw cmd)
552 void
553 microstrain_3dmgx2_imu::IMU::receiveRawAccelAngrate(uint64_t *time, double accel[3], double angrate[3])
554 {
555  int i, k;
556  uint8_t rep[CMD_RAW_ACCEL_ANGRATE_LEN];
557 
558  uint64_t sys_time;
559  uint64_t imu_time;
560 
561  receive(microstrain_3dmgx2_imu::IMU::CMD_RAW, rep, sizeof(rep), 1000, &sys_time);
562 
563  // Read the accelerator AD register values 0 - 65535 given as float
564  k = 1;
565  for (i = 0; i < 3; i++)
566  {
567  accel[i] = extract_float(rep + k);
568  k += 4;
569  }
570 
571  // Read the angular rates AD registor values 0 - 65535 (given as float
572  k = 13;
573  for (i = 0; i < 3; i++)
574  {
575  angrate[i] = extract_float(rep + k);
576  k += 4;
577  }
578 
579  imu_time = extractTime(rep+25);
580  *time = filterTime(imu_time, sys_time);
581 }
582 
583 
585 // Extract time and process rollover
586 uint64_t
588 {
589  uint32_t ticks = bswap_32(*(uint32_t*)(addr));
590 
591  if (ticks < last_ticks) {
592  wraps += 1;
593  }
594 
595  last_ticks = ticks;
596 
597  uint64_t all_ticks = ((uint64_t)wraps << 32) - offset_ticks + ticks;
598 
599  return start_time + (is_gx3 ? (uint64_t)(all_ticks * (1000000000.0 / TICKS_PER_SEC_GX3)) : (uint64_t)(all_ticks * (1000000000.0 / TICKS_PER_SEC_GX2))); // syntax a bit funny because C++ compiler doesn't like conditional ?: operator near the static consts (???)
600 
601 }
602 
603 
604 
606 // Send a packet and wait for a reply from the IMU.
607 // Returns the number of bytes read.
608 int microstrain_3dmgx2_imu::IMU::transact(void *cmd, int cmd_len, void *rep, int rep_len, int timeout)
609 {
610  send(cmd, cmd_len);
611 
612  return receive(*(uint8_t*)cmd, rep, rep_len, timeout);
613 }
614 
615 
617 // Send a packet to the IMU.
618 // Returns the number of bytes written.
619 int
621 {
622  int bytes;
623 
624  // Write the data to the port
625  bytes = write(fd, cmd, cmd_len);
626  if (bytes < 0)
627  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "error writing to IMU [%s]", strerror(errno));
628 
629  if (bytes != cmd_len)
630  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "whole message not written to IMU");
631 
632  // Make sure the queue is drained
633  // Synchronous IO doesnt always work
634  if (tcdrain(fd) != 0)
635  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "tcdrain failed");
636 
637  return bytes;
638 }
639 
640 
641 static int read_with_timeout(int fd, void *buff, size_t count, int timeout)
642 {
643  ssize_t nbytes;
644  int retval;
645 
646  struct pollfd ufd[1];
647  ufd[0].fd = fd;
648  ufd[0].events = POLLIN;
649 
650  if (timeout == 0)
651  timeout = -1; // For compatibility with former behavior, 0 means no timeout. For poll, negative means no timeout.
652 
653  if ( (retval = poll(ufd, 1, timeout)) < 0 )
654  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "poll failed [%s]", strerror(errno));
655 
656  if (retval == 0)
657  IMU_EXCEPT(microstrain_3dmgx2_imu::TimeoutException, "timeout reached");
658 
659  nbytes = read(fd, (uint8_t *) buff, count);
660 
661  if (nbytes < 0)
662  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "read failed [%s]", strerror(errno));
663 
664  return nbytes;
665 }
666 
668 // Receive a reply from the IMU.
669 // Returns the number of bytes read.
670 int
671 microstrain_3dmgx2_imu::IMU::receive(uint8_t command, void *rep, int rep_len, int timeout, uint64_t* sys_time)
672 {
673  int nbytes, bytes, skippedbytes;
674 
675  skippedbytes = 0;
676 
677  struct pollfd ufd[1];
678  ufd[0].fd = fd;
679  ufd[0].events = POLLIN;
680 
681  // Skip everything until we find our "header"
682  *(uint8_t*)(rep) = 0;
683 
684  while (*(uint8_t*)(rep) != command && skippedbytes < MAX_BYTES_SKIPPED)
685  {
686  read_with_timeout(fd, rep, 1, timeout);
687 
688  skippedbytes++;
689  }
690 
691  if (sys_time != NULL)
692  *sys_time = time_helper();
693 
694  // We now have 1 byte
695  bytes = 1;
696 
697  // Read the rest of the message:
698  while (bytes < rep_len)
699  {
700  nbytes = read_with_timeout(fd, (uint8_t *)rep + bytes, rep_len - bytes, timeout);
701 
702  if (nbytes < 0)
703  IMU_EXCEPT(microstrain_3dmgx2_imu::Exception, "read failed [%s]", strerror(errno));
704 
705  bytes += nbytes;
706  }
707 
708  // Checksum is always final 2 bytes of transaction
709 
710  uint16_t checksum = 0;
711  for (int i = 0; i < rep_len - 2; i++) {
712  checksum += ((uint8_t*)rep)[i];
713  }
714 
715  // If wrong throw Exception
716  if (checksum != bswap_16(*(uint16_t*)((uint8_t*)rep+rep_len-2)))
717  IMU_EXCEPT(microstrain_3dmgx2_imu::CorruptedDataException, "invalid checksum.\n Make sure the IMU sensor is connected to this computer.");
718 
719  return bytes;
720 }
721 
723 // Kalman filter for time estimation
724 uint64_t microstrain_3dmgx2_imu::IMU::filterTime(uint64_t imu_time, uint64_t sys_time)
725 {
726  // first calculate the sum of KF_NUM_SUM measurements
727  if (counter < KF_NUM_SUM){
728  counter ++;
729  sum_meas += (toDouble(imu_time) - toDouble(sys_time));
730  }
731  // update kalman filter with fixed innovation
732  else{
733  // system update
734  offset += d_offset;
735 
736  // measurement update
737  double meas_diff = (sum_meas/KF_NUM_SUM) - offset;
738  offset += KF_K_1 * meas_diff;
739  d_offset += KF_K_2 * meas_diff;
740 
741  // reset counter and average
742  counter = 0; sum_meas = 0;
743  }
744  return imu_time - toUint64_t( offset ) + toUint64_t( fixed_offset );
745 }
746 
747 
749 // convert uint64_t time to double time
751 {
752  double res = trunc(time/1e9);
753  res += (((double)time)/1e9) - res;
754  return res;
755 }
756 
757 
759 // convert double time to uint64_t time
761 {
762  return (uint64_t)(time * 1e9);
763 }
int fd
The file descriptor.
Definition: 3dmgx2.h:302
static const int TICKS_PER_SEC_GX3
Definition: 3dmgx2.h:99
void initGyros(double *bias_x=0, double *bias_y=0, double *bias_z=0)
Initial gyros.
Definition: 3dmgx2.cc:224
unsigned long long start_time
The time at which the imu was started.
Definition: 3dmgx2.h:317
static const int MAX_BYTES_SKIPPED
Maximum bytes allowed to be skipped when seeking a message.
Definition: 3dmgx2.h:101
IMU()
Constructor.
Definition: 3dmgx2.cc:98
static float extract_float(uint8_t *addr)
Code to extract a floating point number from the IMU.
Definition: 3dmgx2.cc:68
#define CMD_ACCEL_ANGRATE_MAG_ORIENT_REP_LEN
Definition: 3dmgx2.cc:500
static const int TICKS_PER_SEC_GX2
IMU internal ticks/second.
Definition: 3dmgx2.h:98
void openPort(const char *port_name)
Open the port.
Definition: 3dmgx2.cc:113
void closePort()
Close the port.
Definition: 3dmgx2.cc:170
int send(void *cmd, int cmd_len)
Send a single packet frmo the IMU.
Definition: 3dmgx2.cc:620
void receiveDelvelDelang(uint64_t *time, double delvel[3], double delang[3])
Read a message of type "DELVEL_DELANG".
Definition: 3dmgx2.cc:422
double fixed_offset
Variables used by the kalman computation.
Definition: 3dmgx2.h:332
void receiveAccelAngrate(uint64_t *time, double accel[3], double angrate[3])
Read a message of type "ACCEL_ANGRATE".
Definition: 3dmgx2.cc:389
int transact(void *cmd, int cmd_len, void *rep, int rep_len, int timeout=0)
Send a command to the IMU and wait for a reply.
Definition: 3dmgx2.cc:608
void initTime(double fix_off)
Initialize timing variables.
Definition: 3dmgx2.cc:196
bool continuous
Whether continuous mode is enabled.
Definition: 3dmgx2.h:326
static const unsigned int KF_NUM_SUM
Number of KF samples to sum over.
Definition: 3dmgx2.h:103
void receiveRawAccelAngrate(uint64_t *time, double accel[3], double angrate[3])
Read a message of type "CMD_RAW".
Definition: 3dmgx2.cc:553
cmd
Enumeration of possible IMU commands.
Definition: 3dmgx2.h:118
uint32_t wraps
The number of times the imu has wrapped.
Definition: 3dmgx2.h:305
void stopContinuous()
Take the device out of continous mode.
Definition: 3dmgx2.cc:277
void receiveAccelAngrateOrientation(uint64_t *time, double accel[3], double angrate[3], double orientation[9])
Read a message of type "ACCEL_ANGRATE_ORIENTATION".
Definition: 3dmgx2.cc:346
uint32_t last_ticks
The last number of ticks for computing wraparound.
Definition: 3dmgx2.h:311
void receiveEuler(uint64_t *time, double *roll, double *pitch, double *yaw)
Read a message of type "EULER".
Definition: 3dmgx2.cc:456
uint32_t offset_ticks
The number of ticks the initial offset is off by.
Definition: 3dmgx2.h:308
bool setContinuous(cmd command)
Put the device in continuous mode.
Definition: 3dmgx2.cc:252
uint64_t extractTime(uint8_t *addr)
Extract time from a pointer into an imu buffer.
Definition: 3dmgx2.cc:587
int receive(uint8_t command, void *rep, int rep_len, int timeout=0, uint64_t *sys_time=NULL)
Receive a particular message from the IMU.
Definition: 3dmgx2.cc:671
uint64_t filterTime(uint64_t imu_time, uint64_t sys_time)
Run the filter on the imu time and system times.
Definition: 3dmgx2.cc:724
id_string
Enumeration of possible identifier strings for the getDeviceIdentifierString command.
Definition: 3dmgx2.h:143
static unsigned int bswap_32(unsigned int x)
Code to swap bytes since IMU is big endian.
Definition: 3dmgx2.cc:62
static int read_with_timeout(int fd, void *buff, size_t count, int timeout)
Definition: 3dmgx2.cc:641
static const double G
Gravity (m/sec^2)
Definition: 3dmgx2.h:112
#define CMD_RAW_ACCEL_ANGRATE_LEN
Definition: 3dmgx2.cc:501
double toDouble(uint64_t time)
Convert the uint64_t time to a double for numerical computations.
Definition: 3dmgx2.cc:750
bool is_gx3
Is the IMU a GX3?
Definition: 3dmgx2.h:335
uint64_t toUint64_t(double time)
Convert the double time back to a uint64_t.
Definition: 3dmgx2.cc:760
bool getDeviceIdentifierString(id_string type, char id[17])
Read one of the device identifier strings.
Definition: 3dmgx2.cc:476
static const double KF_K_2
Second KF term.
Definition: 3dmgx2.h:107
static unsigned short bswap_16(unsigned short x)
Code to swap bytes since IMU is big endian.
Definition: 3dmgx2.cc:57
static const double KF_K_1
First KF term.
Definition: 3dmgx2.h:105
void receiveAccelAngrateMagOrientation(uint64_t *time, double accel[3], double angrate[3], double mag[3], double orientation[9])
Read a message of type "ACCEL_ANGRATE_MAG_ORIENT".
Definition: 3dmgx2.cc:505
#define IMU_EXCEPT(except, msg,...)
Macro for throwing an exception with a message.
Definition: 3dmgx2.cc:43
unsigned int counter
A counter used by the filter.
Definition: 3dmgx2.h:329
static unsigned long long time_helper()
Helper function to get system time in nanoseconds.
Definition: 3dmgx2.cc:82
void receiveAccelAngrateMag(uint64_t *time, double accel[3], double angrate[3], double mag[3])
Read a message of type "ACCEL_ANGRATE_MAG".
Definition: 3dmgx2.cc:304


microstrain_3dmgx2_imu
Author(s): Jeremy Leibs, Blaise Gassend
autogenerated on Tue Jul 2 2019 19:40:35