Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RTIMULib support for low-end IMU devices #189

Open
jolting opened this issue Feb 14, 2016 · 8 comments
Open

Add RTIMULib support for low-end IMU devices #189

jolting opened this issue Feb 14, 2016 · 8 comments

Comments

@jolting
Copy link
Member

jolting commented Feb 14, 2016

RTIMULib supports many cheap IMUs. RTIMULib would be a great addition to mrpt's limited set of supported IMU libraries because it would allow mrpt to support a significant number of IMUs.

It implements the i2c/spi communication, which is necessary to communicate with most cheap IMUs.
There is also a program for creating calibration data for the sensor inputs, which is necessary for accurate readings.
Additionally, it has a couple of methods for sensor fusion which provides similar data to what is outputted by devices like XSens.

Here is an example how to read the IMU data from a precalibrated sensor.
https://github.com/richards-tech/RTIMULib2/blob/master/Linux/RTIMULibDrive/RTIMULibDrive.cpp

RTIMU_DATA is defined like this:

typedef struct
{
    uint64_t timestamp;
    bool fusionPoseValid;
    RTVector3 fusionPose;
    bool fusionQPoseValid;
    RTQuaternion fusionQPose;
    bool gyroValid;
    RTVector3 gyro;
    bool accelValid;
    RTVector3 accel;
    bool compassValid;
    RTVector3 compass;
    bool pressureValid;
    RTFLOAT pressure;
    bool temperatureValid;
    RTFLOAT temperature;
    bool humidityValid;
    RTFLOAT humidity;
} RTIMU_DATA;

XYZ components can be accessed like this.

imuData.fusionPose.x();
imuData.fusionPose.y();
imuData.fusionPose.z();
@jlblancoc
Copy link
Member

Thanks for the recommendation, didn't know that lib.
Will take a look at it for the release after the next one.

Do you know if it works in both Windows and GNU/Linux?

@jlblancoc jlblancoc added this to the Release 1.4.1 milestone Feb 14, 2016
@jolting
Copy link
Member Author

jolting commented Feb 14, 2016

I think the problem you run into with Windows is there isn't a standard i2c interface. On Linux your i2c buses show up as /dev/i2c-%d

In RTIMUHal.cpp they have some stub code for implementing a windows version.

Your best bet for windows is using an Arduino for i2c. You can use RTArduLinkIMU. I don't have an experience with that though, but with a breadboard, an imu, some wires and an arduino you have a cheap system.

@jlblancoc
Copy link
Member

Thanks! I prefer to always offer consistent features and API for Linux & Windows, but if some feature is only easily available in Linux, we can live with it ;-)

@jolting
Copy link
Member Author

jolting commented Apr 29, 2016

I was thinking about the parity with Windows. What about an I2C abstraction layer?

I found this:
https://msdn.microsoft.com/en-us/library/windows.devices.i2c.aspx

It appears to be support on the Raspberry Pi 2 and the MinnowBoard Max on Windows, but I don't know if it supports any Desktop hardware.

In Linux it's really low level. You create an array of commands and call an ioctl on an i2c device.

struct i2c_msg {
        __u16 addr;     /* slave address                        */
        __u16 flags;
#define I2C_M_TEN               0x0010  /* this is a ten bit chip address */
#define I2C_M_RD                0x0001  /* read data, from slave to master */
#define I2C_M_STOP              0x8000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART           0x4000  /* if I2C_FUNC_NOSTART */
#define I2C_M_REV_DIR_ADDR      0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK        0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK         0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN          0x0400  /* length will be first received byte */
        __u16 len;              /* msg length                           */
        __u8 *buf;              /* pointer to msg data                  */
};
struct i2c_rdwr_ioctl_data {
         struct i2c_msg __user *msgs;    /* pointers to i2c_msgs */
         __u32 nmsgs;                    /* number of i2c_msgs */
};

libi2c-dev on Ubuntu installs a header file which contains a bunch of helper functions.
/usr/include/linux/i2c-dev.h

@jlblancoc
Copy link
Member

Is libi2c-dev a dependency of RTIMULib ?

I think such a low-level thing could be left as supported in Linux only without being a big deal...

@jolting
Copy link
Member Author

jolting commented Apr 30, 2016

No, the libi2c-dev isn't necessary. It's just a bunch of helper functions.

The helper functions mimic the internal kernel interface.
http://lxr.free-electrons.com/source/drivers/i2c/i2c-core.c

There are tons of ways to access your I2C from userspace:
http://lxr.free-electrons.com/source/Documentation/i2c/dev-interface

RTIMULib uses write(), read() and uses an ioctl to switch between the slave addresses.

Simply reading a byte using i2c requires 1 write(to set the address of the register) and 1 read(to get the byte). I believe the I2C_RDWR ioctl is probably the best for streaming over i2c, since it allows you to dispatch multiple read/writes with a single ioctl without stopping. RTIMULib doesn't use I2C_RDWR.

@jlblancoc jlblancoc removed this from the Release 1.5.0 milestone Jul 15, 2016
@jlblancoc
Copy link
Member

Due to the overwhelming number of open fronts, I think this feature request can be dropped as a blocker to "milestone 1.5.0"...

@jolting
Copy link
Member Author

jolting commented Jul 15, 2016

@jlblancoc Agreed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants