API Reference / Adding New Sensors

From RidgeRun Developer Wiki







Introduction

The sensors are responsible for capturing the data needed to adjust the videos. Depending on the application, different types of IMU sensors may be required to measure the angular rate and orientation of objects. To add a new sensor, follow these steps:

  • Define the New Sensor class, inheriting from the ISensor class.
  • Add the new sensor to Sensor Interface.

Define the New Sensor

The RidgeRun Sensor Interface, known as ISensor, is an extensible class designed to support various types of IMU sensors. To add a new sensor, the user must implement a new sensor class that derives from the ISensor class. This class must implement the following methods:

  • Start: Initializes and enables the sensor to begin data collection.
  • Stop: Stops the sensor.
  • Get: Retrieves data from the IMU sensor.


Defining the Start method

This method receives a constant Sensor Parameter configuration. This configuration includes the sensor's operating frequency (in Hz), the sample rate of the measurements (in Hz), and the sensor ID, which helps distinguish the connected sensors.

RuntimeError NewSensorExample::Start(
    const std::shared_ptr<SensorParams> config) {
  RuntimeError ret{};

  /* Sensor initialization logic */

  return ret;
}

Defining the Stop method

This method disables data reception from the sensor when called. It does not receive any parameters, so the logic to stop the sensor is managed internally.

RuntimeError NewSensorExample::Stop() {
  RuntimeError ret{};

  /* Sensor stop logic */

  return ret;
}


Defining the Get method

This method gets data from the IMU sensor. It receives a sensor payload parameter that consists of data from the accelerometer (m/s²), gyroscope (rad/s), and magnetometer (if needed). The data for each axis (x, y, z) includes the corresponding timestamp (in microseconds). The measured values must be saved in the payload to be accessible to the user-space.

RuntimeError NewSensorExample::Get(std::shared_ptr<SensorPayload> payload) {
  RuntimeError ret{};

  /* Get data logic */

  /* Assign the accelerator data obtained */
  payload->accel.x = accel_data_obtained.x;
  payload->accel.y = accel_data_obtained.y;
  payload->accel.z = accel_data_obtained.z;
  payload->accel.timestamp = accel_data_obtained.sensortime;

  /* Assign the gyroscope data obtained */
  payload->gyro.x = gyro_data_obtained.x;
  payload->gyro.y = gyro_data_obtained.y;
  payload->gyro.z = gyro_data_obtained.z;
  payload->gyro.timestamp = gyro_data_obtained.sensortime;

  /* Assign the gyroscope data obtained (if measured) */
  payload->mag.x = mag_data_obtained.x;
  payload->mag.y = mag_data_obtained.y;
  payload->mag.z = mag_data_obtained.z;
  payload->mag.timestamp = mag_data_obtained.sensortime;

  return ret;
}

It is crucial to take into account that the orientations may change depending on the sensor. For that, please refer to SensorParams::orientation.

Add the New Sensor to ISensor

In order to add the new sensor class to the sensor interface follow these steps:

  • Add the constructor method to the new sensor header file.
  • Extend the Sensors enumeration with the new IMU sensor.
  • Add the new sensor to the ISensor Build method.

Add the constructor method

The constructor method receives the sensor settings parameter. These settings include the device_filename, which refers to the bus where the sensor is mounted.

class NewSensorExample : public ISensor {
 public:
  explicit NewSensorExample(std::shared_ptr<SensorSettings> settings);

  /* Rest of class */

}


Extend the Sensors enumeration

To enable the ISensor interface to create an instance of the new sensor, it must be added to the Sensors enumeration.

enum class Sensors {
  kRb5Imu = 0,
  kBmi160 = 0,

  /* Add new sensor */
  kNewSensorExample = 0
};

Add New Sensor to ISensor Build method

Finally, the new sensor case must be added to the ISensor build method to allow the interface to instantiate the sensor.

std::shared_ptr<ISensor> ISensor::Build(
    const Sensors sensor, const std::shared_ptr<SensorSettings> settings) {
  switch (sensor) {
    case Sensors::kRb5Imu:
      return std::make_shared<Rb5Imu>(settings);

    case Sensors::kBmi160:
      return std::make_shared<Bmi160>(settings);
    
    /* Add new sensor */
    case Sensors::kNewSensorExample:
      return std::make_shared<NewSensorExample>(settings);

    default:
      return nullptr;
  }
}