Supported sensors

The BlackBerry 10 Native SDK supports numerous sensors that can be accessed from the BPS library by using a sensor_type_t value. The following table shows the supported sensors with their corresponding sensor_type_t types.

It is important to note that not all sensor types are available on all devices. You must call sensor_is_supported() to verify that the sensor you want to use is supported on the device your app is running on before attempting to use the sensor.
Sensor Sensor Type (BPS)
Accelerometer SENSOR_TYPE_ACCELEROMETER
Azimuth, Pitch and Roll SENSOR_TYPE_AZIMUTH_PITCH_ROLL
Gravity SENSOR_TYPE_GRAVITY
Gyroscope SENSOR_TYPE_GYROSCOPE
Holster The holster sensor may be accessed in BPS using the functions defined by holster.h
Light SENSOR_TYPE_LIGHT
Linear Acceleration SENSOR_TYPE_LINEAR_ACCEL
Magnetometer SENSOR_TYPE_MAGNETOMETER
Orientation SENSOR_TYPE_ORIENTATION
Proximity SENSOR_TYPE_PROXIMITY
Rotation Matrix SENSOR_TYPE_ROTATION_MATRIX
Temperature SENSOR_TYPE_TEMPERATURE

Sensor types available to BlackBerry PlayBook

The list of available sensor types in the above section applies to BlackBerry 10 devices. The BPS API for BlackBerry PlayBook supports the same sensor types with the following exception:
  • Holster
  • SENSOR_TYPE_ORIENTATION

Using sensors in an app

The BPS sensor APIs include the following files:

  • bps/sensor.h: General BPS sensor definitions and functions
  • bps/orientation.h: Device orientation definitions and functions
  • bps/geolocation.h: Geolocation definitions and functions
  • bps/holster.h: Holster definition and functions

The World Magnetic Model library's header file, wmm/wmm.h, contains magnetic field definitions and a function that you can use to retrieve the geomagnetic field of the device. You can then use the retrieved value to adjust sensor values that are affected by the Earth's magnetic field. For more information, see World Magnetic Model Library.

You must add libbps to your project in order to use BPS functions in your application. For instructions on how to add a library, see Using libraries.

Your application must perform these steps to use BPS calls to access any of the sensor types defined by sensor_type_t:
  1. Initialize BPS by calling bps_initialize().
  2. Check for sensor existence by calling sensor_is_supported() with the appropriate sensor_type_t.
  3. Optionally configure the sensor by calling sensor_set_rate() and/or sensor_set_skip_duplicates(), depending on your application's needs.
  4. Start receiving sensor events by calling sensor_request_events().
  5. Get the next BPS event by calling bps_get_event().
  6. Determine whether the BPS event is a sensor reading event. If so, get which type of sensor reading has occurred.
  7. Get the sensor data from the event by calling the appropriate sensor_event_get_*() function.
  8. Apply the sensor data to your application.
  9. Continue getting and processing BPS events until application exit occurs.
  10. Free the resources used by BPS by calling bps_shutdown().
Steps 5 to 9 occur in your app's main loop. You can also poll for event data.
The following code snippet demonstrates the above steps to fetch values from the accelerometer:
if (bps_initialize() != BPS_SUCCESS) { 
    printf("Failed to initialize BPS.\n"; 
    return 1; 
}

if (!sensor_is_supported(SENSOR_TYPE_ACCELEROMETER)) {
    printf("Sensor is not supported by device; exiting.\n");
    bps_shutdown();
    return 1; 
}

// Configure the sensor to be updated every 250,000 microseconds.
if (sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 250000) != BPS_SUCCESS) {
    printf("Failed to set sensor rate.\n");
}

// Configure the sensor to skip duplicate readings.
if ((sensor_set_skip_duplicates(SENSOR_TYPE_ACCELEROMETER, true) 
    != BPS_SUCCESS) {
    printf("Failed to enable skip duplicates.\n");
}

// Request accelerometer events be sent to application.
if (sensor_request_events(SENSOR_TYPE_ACCELEROMETER) != BPS_SUCCESS) {
    printf("Failed to request events; exiting.\n");
    bps_shutdown();
    return 1;
}

int sensor_domain = sensor_get_domain();

while (!shutdown) {
    bps_event_t *event = NULL;
    bps_get_event(&event, 0);

    if (event) {
        if (bps_event_get_domain(event) == sensor_domain) {
            if (bps_event_get_code(event) == 
                SENSOR_ACCELEROMETER_READING) {
                float force_x, force_y, force_z;
                sensor_event_get_xyz(event, &force_x, 
                                     &force_y, &force_z);

                // Handle accelerometer readings here.
            }
        }
    }
}

bps_shutdown();
            

Influences on sensors

Some sensor data can be affected by influences from outside of the device. In particular, you may consider the impact of the Earth's magnetic field and the orientation of the device.

Magnetic field

The Earth's magnetic field has an effect on readings from the following sensors:
  • Azimuth, Pitch, and Roll
  • Rotation Matrix

If you intend to point your device to true north, rather than magnetic north, then you must adjust your sensor readings to account for magnetic declination. Magnetic declination is the angle between north (the direction the north end of a compass needle points to) and true north (the direction to the North Pole). The location of the device and the time determine the value of this angle. You can retrieve the geomagnetic field, which includes the magnetic declination value, by calling the function wmm_get_geomagnetic_field(). (This function should be used sparingly, as discussed in Avoiding overuse of expensive sensor functions.)

Device orientation

The orientation of a device has no impact on its sensor data. The sensor coordinate system remains the same, regardless of the orientation of the device, while the device's screen coordinates change when the device is rotated. To successfully incorporate sensor readings into an application whose display is affected by the sensor data, the sensor data must be correctly mapped to the screen coordinates from the sensor coordinates. For more information, see Sensor coordinates and Orientation.

Sensor coordinates

Unless otherwise specified, sensors use the right-hand Cartesian coordinate system. Regardless of the orientation of the device, the coordinate system of the sensors does not change. If your application screen output depends on information from sensors, you may need to remap the sensor data to fit the device's orientation. The following diagram shows the positive axes of the sensor coordinate system.

BlackBerry device showing the positive x, y, and z axes of the sensor coordinates.

To allow for measurement in all six directions, the sensor coordinate system uses positive and negative values. The following diagram shows how the coordinate system incorporates both positive and negative values for each axis.

BlackBerry device showing the positive and negative x, y, and z axes of the sensor coordinates.

Where rotation around an axis is used, the rotation is expressed as a right-hand rotation.

BlackBerry device showing the rotation around each of the positive x, y, and z axes of the sensor coordinates. This rotation is shown to be clockwise around a positive axis.

In general, sensor data is oriented to the top of the device.

BlackBerry device showing the device right-side up with the screen facing the user.

Remapping sensor data based on device orientation angle

If any screen output depends upon sensor data, you might need to remap the data to match the device's orientation.

Your app should check for NAVIGATOR_ORIENTATION events which are generated when the device rotation is detected. When your app gets this event, you can get the device orientation angle by calling navigator_event_get_orientation_angle() . You check for NAVIGATOR_ORIENTATION events instead of SENSOR_ORIENTATION_READING events because the navigator controls whether the screen rotates. You only want to remap the sensor data when the screen coordinates change.

The following code snippet illustrates how to get the device orientation angle after your app gets a NAVIGATOR_ORIENTATION event:
// Upon receiving a BPS event:                  
if ((bps_event_get_domain(event) == navigator_get_domain())) {
    switch (bps_event_get_code(event)) {
    case NAVIGATOR_ORIENTATION:
        int angle;
        // Get the current device orientation angle with
        // respect to gravity.
        angle = navigator_event_get_orientation_angle(event);
        break;
    }
}
                

You can now remap the sensor coordinates to the device orientation angle either manually or by calling sensor_remap_coordinates().

This following code snippet illustrates how you manually remap sensor data returned by sensor_event_get_apr() and sensor_event_get_xyz() to match the device orientation angle:
sensor_event_get_xyz(event, &x, &y, &z);

if (angle == 90) {
    x_remapped = -y;
    y_remapped = x;
} else if (angle == 180) {
    x_remapped = -x;
    y_remapped = -y;
} else if (angle == 270) {
    x_remapped = y;
    y_remapped = -x;
}
                
This following code snippet illustrates how you manually remap sensor data returned by sensor_event_get_rotation_matrix()
// Get rotation matrix sensor data from an event.                    
sensor_event_get_rotation_matrix(event, &rotation_matrix);

if (angle == 0) { 
    // Do not need to rotate as device orientation is the same
    // as the sensor coordinate system.
} else {

    // The following is a standard rotation matrix.
    float R[] = {
        cos(angle*M_PI/180), -sin(angle*M_PI/180),
        sin(angle*M_PI/180), cos(angle*M_PI/180)
    };
    
    // i is the row of the matrix
    // j is the column of the matrix
    // k is an index into the rotation matrix R[].
    int i, j, k;
    sensor_rotation_matrix_t remapped_data;    
    
    for(i = 0; i < 3; i++){
        for(j = 0; j < 2; j++){ // Last column of matrix (column 2) stays unchanged.
            remapped_data.matrix[i*3+j] = 0;
            for(k = 0; k < 2; k++){ // Rotation matrix is zero in bottom row (row 2).
                remapped_data.matrix[i*3+j] += 
                rotation_matrix.matrix[i*3+k] * R[k*2+j];
            }
        }
        // The third column remains untouched after the remapping.
        remapped_data.matrix[i*3+2] = rotation_matrix.matrix[i*3+2];
    }
                
The following code snippet illustrates how you can use sensor_remap_coordinates() in your app:
// Upon receiving a BPS event:                  
if ((bps_event_get_domain(event) == navigator_get_domain())) {
    switch (bps_event_get_code(event)) {
    case NAVIGATOR_ORIENTATION:
        int angle;
        // Get the current device orientation angle with respect to gravity.
        angle = navigator_event_get_orientation_angle(event);
        // Instruct the sensor service to remap sensor data to match 
        // the device orientation. This remaps data that is returned by:
        //     - sensor_event_get_apr()
        //     - sensor_event_get_rotation_matrix()
        //     - sensor_event_get_rotation_xyz()
        sensor_remap_coordinates(angle);        
        break;
    }
}
                

Last modified: 2014-11-17



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus