IMU and GPS

This section describes the functions for using the built-in Inertial Motion Unit (IMU) and the external GPS sensor.

Inertial Motion Unit (IMU)

RoverWing contains a built-in Inertial Motion Unit (IMU), which is based on ICM42605 chip from Invensense. This chip combines a 3-axis accelerometer and a 3-axis gyro sensor, which provide information about acceleration and rotational speed. RoverWing firmware combines the sensor data to provide information about rover orientation in space, in the form of Yaw, Pitch, and Roll angles. (RoverWing’s firmware is based on the work of Kris Winer and uses data fusion algorithm invented by Sebastian Madgwick.)

Note

Current version of RoverWing firmware requires that the RoverWing be mounted horizontally.

Below is the description of functions related to IMU. You can also check sample code in IMU example sketch included with RoverWing library.

Initialization

By default, the IMU is inactive. To start/stop it, use the functions below.

void IMUbegin()

Activate IMU

void IMUend()

Stop the IMU

bool IMUisActive()

Returns true if IMU is active. This function can be used to verify that IMU activation was successful.

Calibration

Before use, the IMU needs to be calibrated. The calibration process determines and then applies corrections (offsets) to the raw data; without these corrections, the data returned by the sensor is very inaccurate.

If you haven’t calibrated the sensor before (or want to recalibrate it), use the following function:

void IMUcalibrate()

This function will determine and apply the corrections; it will also save these corrections in the flash storage of the RoverWing microcontroller, where they will be stored for future use. This data is preserved even after you disconnect power from your RoverWing board (much like the usual USB flash drive).

This function will take about 10 seconds to execute; during this time, the robot must be completely stationary on a flat horizontal surface.

If you had previously calibrated the sensor, you do not need to repeat the calibration process - by default, upon initialization the IMU loads previously saved calibration values.

Note that the IMU is somewhat sensitive to temperature changes, so if the temperature changes (e.g., you moved your robot from indoors to the street for testing), it is advised that you recalibrate the IMU.

Reading Values

RoverWing allows you to read both the raw data (accelerometer and gyro readings) and computed orientation, using the following functions:

void getAccel()

Fetches from the RoverWing raw acceleration data and saves it using member variables ax, ay, az, which give the acceleration in x-, y-, and z- directions respectively in in units of 1g (9.81 m/sec^2) as floats.

void getGyro()

Fetches from the RoverWing raw gyro data and saves it using member variables gx, gy, gz, which give the angular rotation velocity around x-, y-, and z- axes respectively, in degree/s (as floats).

float getYaw()
float getPitch()
float getRoll()

These functions return yaw, pitch, and roll angles for the robot. These three angles describe the robot orientation as described below (this assumes that RoverWing is mounted horizontally on the robot, with power supply connector facing the back of the robot and the USB port on the right).

  • yaw is the rotation around the vertical axis (positive angle corresponds to clockwise rotation, i.e. right turns), relative to the starting position of the robot
  • pitch is the rotation around the horizontal line, running from left to right. Positive pitch angle corresponds to raising the front of the robot and lowering the back
  • roll is the rotation around the horizontal line running from front to back. Positive roll angle corresponds to raising the left side of the robot and lowering the right.

For more information about yaw, pitch, and roll angles, please visit https://en.wikipedia.org/wiki/Aircraft_principal_axes

void getOrientationQuat()
Gets robot orientation as a unit quaternion (see https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation). The result can be accessed using member variable float quat[4], which contains the four components of the quaternion:

q=quat[0]+i*quat[1]+j*quat[2]+k*quat[3]

GPS

If you have connected a GPS sensor to RoverWing as described in RoverWing User Guide, you can use the functions below to access it.

Initialization

void GPSbegin()

Start the GPS. Note that after starting, it can take the sensor a while to get GPS location fix: the time ranges from several seconds if the sensor had recently been used in a nearby location to several minutes if the sensor has been moved to a completely new location.

void GPSend()

Stops the GPS sensor.

uint8_t GPSstatus()

Gets current GPS status. Possible values are

  • GPS_OFF: GPS is inactive
  • GPS_OK: GPS is active and has a valid location fix
  • GPS_WAITING: GPS is active, but is waiting to receive a location fix. The sensor switches to this status if it hasn’t received a valid GPS signal for more than 3 seconds.

Usage

After the GPS has been initialized and received location fix, you can use the following functions to access the GPS coordinates.

void getGPSlocation()

Gets from RoverWing and saves the latest GPS location data, which can later be accessed using the functions below.

double latitude()
double longitude()

Return the robot latitude and longitude in degrees, following the usual conventions: latitude ranges from -90 (South Pole) to 90 (North Pole); longitude ranges from -180 (west of Greenwich) to 180 (east of Greenwich). Note that these coordinates refer to the location fetched at last call of getGPSlocation().

int32_t latitudeL()
int32_t longitudeL()

Return longitude and latitude of the robot, in units of 10^{-7} degree (about 10 cm).

uint32_t GPStimestamp()

Returns time when the last GPS location fix was received, in milliseconds since reboot of the RoverWing board.

Location Data

RoverWing library provides a type for storing GPS location and timestamp. It is defined in RoverWing.h as follows:

struct location_t {
  int32_t latitude; //latitude, in units of 10^{-7} degree
  int32_t longitude;
  uint32_t timestamp; //in ms, as reported by millis()
};

The functions below provide some tools for working with location data:

void saveGPSlocation(location_t & loc)

Saves current robot location to variable loc ot type location_t.

float distanceTo(const location_t & loc)

Returns distance from current robot location to location loc, in meters.

float bearingTo(const location_t & loc)

Returns bearing from current robot location to loc. The bearing is measured in degrees and ranges from -180 to 180, with North being 0.

Note

Functions distanceTo(), bearingTo() use flat map model. The results are accurate enough for distances up to 10 km, but if you want to find the distance between your robot and Mount Everest, you need to write your own code or google for existing solutions (unless you are within 10 km of Mount Everest).