30 #include <netinet/in.h> 43 #define IMU_EXCEPT(except, msg, ...) \ 46 snprintf(buf, 1000, msg" (in microstrain_3dmgx2_imu::IMU:%s)", ##__VA_ARGS__, __FUNCTION__); \ 57 static inline unsigned short bswap_16(
unsigned short x) {
58 return (x>>8) | (x<<8);
62 static inline unsigned int bswap_32(
unsigned int x) {
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);
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);
89 struct timeval timeofday;
90 gettimeofday(&timeofday,NULL);
91 return (
unsigned long long)(timeofday.tv_sec) * 1000000000 + (
unsigned long long)(timeofday.tv_usec) * 1000;
118 fd = open(port_name, O_RDWR | O_SYNC | O_NONBLOCK | O_NOCTTY, S_IRUSR | S_IWUSR );
121 const char *extra_msg =
"";
125 extra_msg =
"You probably don't have premission to open the port for reading and writing.";
128 extra_msg =
"The requested port does not exist. Is the IMU connected? Was the port name misspelled?";
132 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"Unable to open serial port [%s]. %s. %s", port_name, strerror(errno), extra_msg);
138 fl.l_whence = SEEK_SET;
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);
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);
152 cfsetispeed(&term, B115200);
153 cfsetospeed(&term, B115200);
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);
162 if (tcflush(
fd, TCIOFLUSH) != 0)
163 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"Tcflush failed. Please report this error if you see it.");
180 }
catch (microstrain_3dmgx2_imu::Exception &e) {
186 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"Unable to close serial port; [%s]", strerror(errno));
204 transact(cmd,
sizeof(cmd), rep,
sizeof(rep), 1000);
234 *(
unsigned short*)(&cmd[3]) =
bswap_16(10000);
236 transact(cmd,
sizeof(cmd), rep,
sizeof(rep), 30000);
262 transact(cmd,
sizeof(cmd), rep,
sizeof(rep), 1000);
265 if (rep[1] != command) {
287 send(cmd,
sizeof(cmd));
293 if (tcflush(
fd, TCIOFLUSH) != 0)
294 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"Tcflush failed");
318 for (i = 0; i < 3; i++)
326 for (i = 0; i < 3; i++)
334 for (i = 0; i < 3; i++) {
360 for (i = 0; i < 3; i++)
368 for (i = 0; i < 3; i++)
376 for (i = 0; i < 9; i++) {
401 for (i = 0; i < 3; i++)
409 for (i = 0; i < 3; i++)
434 for (i = 0; i < 3; i++)
442 for (i = 0; i < 3; i++)
484 transact(cmd,
sizeof(cmd), rep,
sizeof(rep), 1000);
490 memcpy(
id, rep+2, 16);
493 is_gx3 = (strstr(
id,
"GX3") != NULL);
500 #define CMD_ACCEL_ANGRATE_MAG_ORIENT_REP_LEN 79 501 #define CMD_RAW_ACCEL_ANGRATE_LEN 31 517 for (i = 0; i < 3; i++)
525 for (i = 0; i < 3; i++)
533 for (i = 0; i < 3; i++) {
540 for (i = 0; i < 9; i++) {
565 for (i = 0; i < 3; i++)
573 for (i = 0; i < 3; i++)
589 uint32_t ticks =
bswap_32(*(uint32_t*)(addr));
612 return receive(*(uint8_t*)cmd, rep, rep_len, timeout);
625 bytes = write(
fd, cmd, cmd_len);
627 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"error writing to IMU [%s]", strerror(errno));
629 if (bytes != cmd_len)
630 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"whole message not written to IMU");
634 if (tcdrain(
fd) != 0)
635 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"tcdrain failed");
646 struct pollfd ufd[1];
648 ufd[0].events = POLLIN;
653 if ( (retval = poll(ufd, 1, timeout)) < 0 )
654 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"poll failed [%s]", strerror(errno));
657 IMU_EXCEPT(microstrain_3dmgx2_imu::TimeoutException,
"timeout reached");
659 nbytes = read(fd, (uint8_t *) buff, count);
662 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"read failed [%s]", strerror(errno));
673 int nbytes, bytes, skippedbytes;
677 struct pollfd ufd[1];
679 ufd[0].events = POLLIN;
682 *(uint8_t*)(rep) = 0;
691 if (sys_time != NULL)
698 while (bytes < rep_len)
703 IMU_EXCEPT(microstrain_3dmgx2_imu::Exception,
"read failed [%s]", strerror(errno));
710 uint16_t checksum = 0;
711 for (
int i = 0; i < rep_len - 2; i++) {
712 checksum += ((uint8_t*)rep)[i];
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.");
752 double res = trunc(time/1e9);
753 res += (((double)time)/1e9) - res;
762 return (uint64_t)(time * 1e9);
int fd
The file descriptor.
static const int TICKS_PER_SEC_GX3
void initGyros(double *bias_x=0, double *bias_y=0, double *bias_z=0)
Initial gyros.
unsigned long long start_time
The time at which the imu was started.
static const int MAX_BYTES_SKIPPED
Maximum bytes allowed to be skipped when seeking a message.
static float extract_float(uint8_t *addr)
Code to extract a floating point number from the IMU.
#define CMD_ACCEL_ANGRATE_MAG_ORIENT_REP_LEN
static const int TICKS_PER_SEC_GX2
IMU internal ticks/second.
void openPort(const char *port_name)
Open the port.
void closePort()
Close the port.
int send(void *cmd, int cmd_len)
Send a single packet frmo the IMU.
void receiveDelvelDelang(uint64_t *time, double delvel[3], double delang[3])
Read a message of type "DELVEL_DELANG".
double fixed_offset
Variables used by the kalman computation.
void receiveAccelAngrate(uint64_t *time, double accel[3], double angrate[3])
Read a message of type "ACCEL_ANGRATE".
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.
void initTime(double fix_off)
Initialize timing variables.
bool continuous
Whether continuous mode is enabled.
static const unsigned int KF_NUM_SUM
Number of KF samples to sum over.
void receiveRawAccelAngrate(uint64_t *time, double accel[3], double angrate[3])
Read a message of type "CMD_RAW".
cmd
Enumeration of possible IMU commands.
uint32_t wraps
The number of times the imu has wrapped.
void stopContinuous()
Take the device out of continous mode.
void receiveAccelAngrateOrientation(uint64_t *time, double accel[3], double angrate[3], double orientation[9])
Read a message of type "ACCEL_ANGRATE_ORIENTATION".
uint32_t last_ticks
The last number of ticks for computing wraparound.
void receiveEuler(uint64_t *time, double *roll, double *pitch, double *yaw)
Read a message of type "EULER".
uint32_t offset_ticks
The number of ticks the initial offset is off by.
bool setContinuous(cmd command)
Put the device in continuous mode.
uint64_t extractTime(uint8_t *addr)
Extract time from a pointer into an imu buffer.
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.
uint64_t filterTime(uint64_t imu_time, uint64_t sys_time)
Run the filter on the imu time and system times.
id_string
Enumeration of possible identifier strings for the getDeviceIdentifierString command.
static unsigned int bswap_32(unsigned int x)
Code to swap bytes since IMU is big endian.
static int read_with_timeout(int fd, void *buff, size_t count, int timeout)
static const double G
Gravity (m/sec^2)
#define CMD_RAW_ACCEL_ANGRATE_LEN
double toDouble(uint64_t time)
Convert the uint64_t time to a double for numerical computations.
bool is_gx3
Is the IMU a GX3?
uint64_t toUint64_t(double time)
Convert the double time back to a uint64_t.
bool getDeviceIdentifierString(id_string type, char id[17])
Read one of the device identifier strings.
static const double KF_K_2
Second KF term.
static unsigned short bswap_16(unsigned short x)
Code to swap bytes since IMU is big endian.
static const double KF_K_1
First KF term.
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".
#define IMU_EXCEPT(except, msg,...)
Macro for throwing an exception with a message.
unsigned int counter
A counter used by the filter.
static unsigned long long time_helper()
Helper function to get system time in nanoseconds.
void receiveAccelAngrateMag(uint64_t *time, double accel[3], double angrate[3], double mag[3])
Read a message of type "ACCEL_ANGRATE_MAG".