C API Area Learning Tutorial

Configuration

There are two TangoConfig configuration options that are relevant to area learning.

Loading area descriptions

The first option is config_load_area_description_UUID. If a UUID is set, the ADF specified by the UUID is loaded and localizations will occur against it.

if (TangoConfig_setString(config_, "config_load_area_description_UUID",
                          "ADF UUID to load") != TANGO_SUCCESS) {
  // Handle the error.
}

Learning mode

The second option is config_enable_learning_mode. If set to true, the device will build an area description of the current session.

if (TangoConfig_setBool(config_, "config_enable_learning_mode", true)
    != TANGO_SUCCESS) {
  // Handle the error.
}

This area description can be saved for later use by using TangoService_saveAreaDescription(). This call can be long-running, so don't call it on the UI thread.

Learning mode with a loaded area description

If both options are used, an area description of the current session will be built. If localization occurs against the loaded ADF and TangoService_saveAreaDescription() is called, the a new ADF will be saved containing the combination of both.

Motion tracking with area learning

In general, using motion tracking with area learning is very similar to basic motion tracking. You need to define the coordinate pairs you are interested in, then use either callbacks or polling to get data.

There are two coordinate frame pairs for area learning. The TangoCoordinateFramePair with base == TANGO_COORDINATE_FRAME_AREA_DESCRIPTION and target == TANGO_COORDINATE_FRAME_DEVICE gets you the pose of the device from the area description's origin, including drift corrections. If an ADF was loaded, pose data is only available after you have localized to the ADF and the origin will be the same as the ADF. If learning mode enabled without loading an ADF, pose data will be available immediately after initialization and the origin will be the same as the start of service.

The frame pair with base == TANGO_COORDINATE_FRAME_AREA_DESCRIPTION and target == TANGO_COORDINATE_FRAME_START_OF_SERVICE provides the offset between the area description and start of service at the requested time. This pair updates only when a localization occurs.

Applications should use TANGO_COORDINATE_FRAME_DEVICE with respect to TANGO_COORDINATE_FRAME_AREA_DESCRIPTION for tracking a device's motion, and use TANGO_COORDINATE_FRAME_START_OF_SERVICE with respect to TANGO_COORDINATE_FRAME_AREA_DESCRIPTION only as a localization signal.

static void onPoseAvailable(void* context, const TangoPoseData* pose) {
  // Get the pose of the device with respect to the ADF.
  else if (pose->frame.base == TANGO_COORDINATE_FRAME_AREA_DESCRIPTION
      && pose->frame.target == TANGO_COORDINATE_FRAME_DEVICE) {
    // Process new ADF to device pose data.
  }
  // Get the pose of the start of service with respect to the ADF.
  else if (pose->frame.base == TANGO_COORDINATE_FRAME_AREA_DESCRIPTION
      && pose->frame.target == TANGO_COORDINATE_FRAME_START_OF_SERVICE) {
    // Process new localization.
  }
}

Working with ADFs

Using metadata

ADFs have metadata you can use, so you don't have to work with UUID alone. The metadata consists of key-value pairs; for a list of supported keys see the C API docs for TangoAreaDescriptionMetadata_get().

Set the value of a metadata field of value_size bytes, given its key for the ADF uuid:

void TangoData::SetUUIDMetadataValue(const char* uuid, const char* key,
                                     int value_size, const char* value) {
  TangoAreaDescriptionMetadata metadata;
  if (TangoService_getAreaDescriptionMetadata(uuid, &metadata) !=
      TANGO_SUCCESS) {
    LOGE("TangoService_getAreaDescriptionMetadata(): Failed");
  }
  if (TangoAreaDescriptionMetadata_set(metadata, key, value_size, value) !=
      TANGO_SUCCESS) {
    LOGE("TangoAreaDescriptionMetadata_set(): Failed");
  }
  if (TangoService_saveAreaDescriptionMetadata(uuid, metadata) !=
      TANGO_SUCCESS) {
    LOGE("TangoService_saveAreaDescriptionMetadata(): Failed");
  }
}

Get the value of a metadata field, given its key, for the ADF uuid:

char* TangoData::GetUUIDMetadataValue(const char* uuid, const char* key) {
  size_t size = 0;
  char* value;
  TangoAreaDescriptionMetadata metadata;
  if (TangoService_getAreaDescriptionMetadata(uuid, &metadata) !=
      TANGO_SUCCESS) {
    LOGE("TangoService_getAreaDescriptionMetadata(): Failed");
  }
  if (TangoAreaDescriptionMetadata_get(metadata, key, &size, &value) !=
      TANGO_SUCCESS) {
    LOGE("TangoAreaDescriptionMetadata_get(): Failed");
  }
  return value;
}

List all UUIDs of the ADFs on the device:

char* uuid_list;

// uuid_list will contain a comma separated list of UUIDs.
if (TangoService_getAreaDescriptionUUIDList(&uuid_list) != TANGO_SUCCESS) {
  LOGI("TangoService_getAreaDescriptionUUIDList");
}

// Parse the uuid_list to get the individual uuids.
if (uuid_list != NULL && uuid_list[0] != '\0') {
  LOGI("uuid list: %s", uuid_list);
  vector<string> adf_list;

  char* parsing_char;
  parsing_char = strtok(uuid_list, ",");
  while (parsing_char != NULL) {
    string s = string(parsing_char);
    LOGI("parsed: %s", parsing_char);
    adf_list.push_back(s);
    parsing_char = strtok(NULL, ",");
  }

  int list_size = adf_list.size();
  LOGI("Loaded ADF: %s", adf_list[list_size - 1].c_str());
  if (TangoConfig_setString(config_, "config_load_area_description_UUID",
                            adf_list[list_size - 1].c_str()) !=
      TANGO_SUCCESS) {
    LOGE("config_load_area_description_uuid Failed");
    return false;
  }
} else {
  LOGE("No area description file available, no file loaded.");
}

Send feedback about...

Tango C API
Tango C API