Webots Odor Simulation/Using the Wind and Odor Sensor on Robots

Using the sensors on a robot (or elsewhere in the environment) requires adding a sensor object onto the robot, and then reading the value of this sensor object in the robot controller. An example of this can be found in the files worlds/odor_test.wbt (world file) and controllers/odor_test/odor_test.cpp (robot controller).

Adding an Odor and a Wind Sensor on the Robot edit

A general sensor in Webots can simply be created by adding a receiver object with a special DEF name onto the robot. The magic DEF names for our sensors are SENSOR_ODOR_# and SENSOR_WIND_#, where the # has to be replaced by a unique number between 1-16. (For more sensors, the corresponding definition in the odor_physics plugin can be modified.)

E.g. your Khepera III robot number 1 could have the following odor and wind sensors configured in the world file (see worlds/odor_test.wbt for an example):

DEF KHEPERA_III DifferentialWheels {
  ...
  children [
    DEF SENSOR_ODOR_1 Receiver {
      translation 0 0.07 -0.05
      children [
        Shape {
          appearance Appearance {
            material Material {
              diffuseColor 0 1 0
            }
          }
          geometry DEF CYLINDER_ODOR Cylinder {
            height 0.02
            radius 0.01
          }
        }
      ]
      name "sensor_odor"
      boundingObject USE CYLINDER_ODOR
      channel 1
    }
    DEF SENSOR_WIND_1 Receiver {
      translation 0 0.07 0
      children [
        Shape {
          appearance Appearance {
            material Material {
              diffuseColor 0.3 1 1
            }
          }
          geometry DEF CYLINDER_WIND Cylinder {
            height 0.02
            radius 0.02
          }
        }
      ]
      name "sensor_wind"
      boundingObject USE CYLINDER_WIND
      channel 101
    }
    ...
  ]
  ...
}

Note the name property which is here set to "sensor_odor" and "sensor_wind" respectively. This name is used by the robot controller to find the sensor.

You may have noticed that the above code does not contain any sensor configuration values (e.g. noise level, type of odor, ...). The properties of the sensors (as well as all other properties of the simulation model) are configured directly in the odor simulation plugin.

Reading the Sensors edit

In your robot controller, you can read the odor and the wind sensors as follows (see controllers/odor_test/odor_test.cpp for an example):

// Wind direction
struct sWind {
	double x;
	double y;
	double z;
};

// Odor sensor
DeviceTag sensor_odor;
// Wind sensor
DeviceTag sensor_wind;

// Initializes the simulation
void reset() {
    sensor_odor = robot_get_device("sensor_odor");
    receiver_enable(sensor_odor, CONTROL_STEP);
    sensor_wind = robot_get_device("sensor_wind");
    receiver_enable(sensor_wind, CONTROL_STEP);

    ...
}

void read_odor(double *result) {
    while (receiver_get_queue_length(sensor_odor) > 0) {
        assert(receiver_get_data_size(sensor_odor) == sizeof(double));
        *result = *(const double *)receiver_get_data(sensor_odor);
        receiver_next_packet(sensor_odor);
    }
}

void read_wind(struct sWind *result) {
    while (receiver_get_queue_length(sensor_wind) > 0) {
        assert(receiver_get_data_size(sensor_wind) == sizeof(struct sWind));
        *result = *(const struct sWind *)receiver_get_data(sensor_wind);
        receiver_next_packet(sensor_wind);
    }
}

int run(int dt) {
    double odor;
    struct sWind wind;

    read_odor(&odor);
    read_wind(&wind);

    robot_console_printf("Odor concentration: %f\n", odor);
    robot_console_printf("Wind vector: %f %f %f\n", wind.x, wind.y, wind.z);

    ...
}