Sensor Description

Introduction

The Broadcom GLL or GLCT API can accept direct sensor input from a wide variety of raw and processed sources. The GL_EXT_SENS_TYPE lists each type supported.

Multiple sensor data streams are collected into one GlExtSensInfo structure and sent to the GLL or GLCT. Each sensor reading is of type ::SampleValues, a union of several possible data formats.

Each sensor can have different data rates, reporting rates, uncertainties, and data type. Most sensor data arrives at a 1Hz interval. Higher-rate sensor data should be collected at the higher data rate and sent to the GLL as an array of samples at the one Hertz rate. Avoiding measurement lag is very important for good performance.

Uncertainties can be either an RMSE (sigma plus offset), ellipsoid (major axis, minor axis, degrees relative to North), or unused (for state sensors). In the case of an RMSE, the offset is never explicitly passed to the GLL. The driver should remove the offset from the sensor value or should increase the uncertainty (unc.fValue) reported. The uncertainty is of type ::SampleUncertainty.

Measurement Inputs

There are five broad classes of inputs into the GLL:

  • Low-level sensors not requiring filtering. These are sensors such as pressure, temperature. These are used directly by the GLL.
  • High-level sensors not requiring filters. These are sensors such as steering wheel turn detectors or speed detectors. These are very effective and are directly used by the GLL.
  • High-level measurements. These are position measurements from alternate sources such as FM stations, WiFi, cellular baseband (NMR/MRL). These are very effective and are directly used by the GLL. GPS itself generates high-level measurements from GPS, GLONASS, and SBAS satellites.
  • High-level state sensors not requiring filtering. These are other types high-level sensors that are reported as a state. These are the turn, move and mounted state sensors.
  • Low-level filtered sensors. These are the classical gyroscope, accelerometer, and magnetic compass sensors that require calibration, filtering, masking and other processing. The GLL has parameters hard-coded for a limited number of low-level sensors. This capability is limited.

Software Overview

Device drivers (typically in kernel space) take readings from the sensor hardware to deliver sensor data to the GLL periodically.

sensor_sw.gif

Sensor Data Notes

  • Latitude and longitude are always in decimal degrees with north and east positive, south and west negative.
  • Elevation is meters above the WGS84 ellipsoid.
  • Time and uncertainty must be provided with each measurement (except some uncertainty measurements noted elsewhere).
  • Heading and turn rate are measured clockwise from true North.
  • Each measurement generally has an identical uncertainty value of the same units unless otherwise noted.
  • When uncertainty is not used, it must be filled in with -1.

Software output of the GLL are via the GL_FIX_STATUS structure. This includes time, position, heading, speed, and various quality, uncertainty, or uncertainty values.

Hardware output of the GLL is via the 1pps sync pulse. Customer's sensor-related hardware can use this signal as a timing reference. Field GlExtSensData::eSensorTime should be GL_EXT_SENS_TIME_PPS for these cases.

There are three types of state sensors: turn, move, mount. These are GL_TURN_SENSOR_STATE, GL_MOVE_SENSOR_STATE, and GL_MOUNT_SENSOR_STATE. The last received state is assume valid until another state is received. There is an unknown state to indicate either we don't know or the input stream is no longer available. Since these are highly filtered and processed inputs, no uncertainty is required for these sensors so the unc value should be set to UNKNOWN (GLTS_UNKNOWN,GLMS_UNKNOWN,GLMTS_UNKNOWN).

Sensor Input Example

The basic operation is to call GlEngine::SetExtSensData() with a pointer to a GlExtSensInfo.

The GlExtSensInfo points to an array of GlExtSensData. Each entry in the array contains one type of timestamped sensor input.

For example, if you have one pressure reading, two temperature readings, and 10 X-axis gyro samples for the past second, create a GlExtSensData structure for all of them and a convenience pointer to each.

    GlExtSensData myThreeSensors[3];

    GlExtSensData *baro = myThreeSensors;
    baro->eSensorType = GL_EXT_SENS_BARO;

    GlExtSensData *temp = myThreeSensors + 1;
    temp->eSensorType = GL_EXT_SENS_TEMP;

    GlExtSensData *gyro = myThreeSensors + 2;
    gyro->eSensorType = GL_EXT_SENS_GYRO_X;

You'll also need to specify the type of timestamps used for each one:

Since we chose UTC-relative timestamps, we must fill in the utcBase:

    UTC_TIME utc = {0};
    customer_utc_fill(&utc);
    memcpy(&baro->utcBase, utc, sizeof(utc));
    memcpy(&temp->utcBase, utc, sizeof(utc));
    memcpy(&gyro->utcBase, utc, sizeof(utc));

Fill in the pressure sample from the current reading:

    baro.nNumSamples = 1;
    GlExtSensSample* pSamp = baro->aSamples;
    pSamp->sDeltaTime   = 0;     // we're collecting the sample now!
    pSamp->v.fValue     = read_barometer();
    pSamp->unc.fValue   = -1.0   // none

Fill in the temperature sample from the past and current readings:

    temp->nNumSamples = 2;
    pSamp = temp.aSamples;

    pSamp->sDeltaTime = -500;   // we collected the temp 1/2 sec ago.
    pSamp->v.fValue   = gf_prior_temp;
    pSamp->unc.fValue = -1.0    // none

    ++pSamp;

    pSamp->sDeltaTime = 0;      // we're collecting the sample now!
    pSamp->v.fValue   = read_temperature();
    pSamp->unc.fValue = -1.0    // none

This is an artificial example because you'd generally expect to have at least one accelerometer with a gyro, or multiple gyros. For this example, the customer_device_gyro_read() is assumed to maintain a running history of gyro samples and the variance of each sample. It can also generate an array of delta timestamps from when the gyros are read. In this example, the age[] array would most likely be filled in with these values: {-900, -800, -700, -600, .... -200, -100, 0} reflecting the relative age of the gyro samples (and variances). Example code to fill in the gyro samples from a device driver input:

    gyro->nNumSamples = 10;
    pSamp = gyro->aSamples;

    float raw_gyro[10] = {0};
    float variance[10] = {0};
    int   age[10] = {0};
    customer_device_driver_gyro_read(10, &raw_gyro, &age, &variance);

    for (int i = 0; i < 10; ++pSamp, ++i)
    {
        pSamp->sDeltaTime   = age[i];
        pSamp->v.fValue     = raw_gyro[i];  // degrees per second per second.
        pSamp->unc.fValue   = variance[i];  // the gyro driver computes the RMSE.
    }

Now combine all three sensor streams into one GlExtSensInfo structure.

    GlExtSensInfo sensor_info = {0};
    sensor_info.sSensNum  = 3;
    sensor_info.pSensData = myThreeSensors;

Send the sensor information to the GlEngine:

    GlEngine* pEngine = NULL;
    // ...
    pEngine->SetExtSensInfo(&sensor_info);

Or you can send the data to the GLCT:

int GpsHalWaitForEvent(GpsHal* pHal, GPSCTRL_EVENT* potEvent, int iTimeoutMs)
{
    //...

    if (have_sensor_data)
    {
        potEvent->eCode = GLCTEV_PAL_EXT_SENS;
        potEvent->pData = &sensor_info;
        return 1;
    }

    //...
}
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines