# Gimbal API

{% hint style="info" %}
Related C++ Header in the Auterion SDK: `<auterion_sdk/gimbal/gimbal.hpp>`
{% endhint %}

Auterion SDK provides an interface for managing and controlling the gimbals mounted on the vehicle.

The regular workflow for operating a gimbal entails the following steps:

* Finding and selecting a suitable gimbal (see [#gimbal-discovery](#gimbal-discovery "mention"));
* Acquiring gimbal ownership (see [#gimbal-ownership](#gimbal-ownership "mention"));
* Setting desired gimbal control mode (see [#gimbal-modes](#gimbal-modes "mention"));
* Actuating selected gimbal (see [#gimbal-control](#gimbal-control "mention")).

## Gimbal Discovery

The discovery process allows the user to select the most suitable gimbal for his needs.

Such process takes place during the `auterion::Gimbal` object construction. The Auterion SDK provides the user two ways select the desired gimbal: by using an `auterion::GimbalDescriptor` or by providing a custom filter function.

### By Descriptor

The user can supply a `auterion::GimbalDescriptor` object that defines the characteristics used to select an appropriate gimbal (e.g., custom name, vendor name, model name, and capabilities).

In this case, the selection of the candidate gimbals behaves as follows:

1. If a custom name is provided, the candidate gimbal name must match it;
2. If vendor or model names are provided, the candidate gimbal must match those.
3. If no custom name, vendor, or model names are provided, it checks the provided capabilities.

For example, when developing for [Virtual Skynode](https://docs.auterion.com/app-development/simulation/virtual-skynode), we can select the simulated gimbal with the following:

```cpp
auterion::SDK sdk(argc, argv, "gimbal_control_app");

// Select simulated gimbal
auterion::GimbalDescriptor gimbal_descriptor{};
gimbal_descriptor.vendor_name = "PX4";
gimbal_descriptor.model_name = "Gazebo Gimbal";

auterion::Gimbal gimbal(sdk, gimbal_descriptor);
```

The `capabilities` field of `auterion::GimbalDescritptor` can be used to specify the gimbal functionalities we are interested in. For example:

```cpp
auterion::SDK sdk(argc, argv, "gimbal_control_app");

// Select gimbal that can yaw and that has a pitch range of at least [-30°; 30°]
auterion::GimbalDescriptor gimbal_descriptor{};
gimbal_descriptor.capabilities.canYaw().PitchRangeDeg(-30.0, 30.0);

auterion::Gimbal gimbal(sdk, gimbal_descriptor);
```

{% hint style="info" %}
Please visit <https://auterion.github.io/auterion-sdk/structauterion_1_1GimbalCapabilities.html> for the full list of available capabilities.
{% endhint %}

### By Selection Function

The user can provide the SDK with custom logic redefining the gimbal selection criteria; for example:

```cpp
auterion::SDK sdk(argc, argv, "gimbal_control_app");

// Select gimbal having vendor name matching the model name
auterion::Gimbal gimbal(sdk, 
    [](const auterion::GimbalDescriptor& candidate) 
        {return candidate.vendor_name == candidate.model_name;}
    );
```

## Gimbal Ownership

Before being able to send control commands the app needs to request control ownership of the gimbal:

```cpp
if (gimbal.takeControl()) {
    // Gimbal control acquired, we can send commands
}
```

For the same reason, using `gimbal.releaseControl()` we can release the control so that other entities can use the same gimbal. At any time, we can check whether we are in control of the gimbal with `gimbal.isInControl()` .

## Gimbal Modes

A gimbal may support multiple operating modes; in particular, each control axis (roll, pitch, and yaw) can be configured to be:

* Relative to the absolute world frame (`auterion::GimbalMode::AxisMode::WorldLock`), meaning that its deflection will compensate any vehicle movement;
* Relative to the vehicle frame (`auterion::GimbalMode::AxisMode::VehicleFollow`), meaning that its deflection is not affected by vehicle movements;

By default roll and pitch axes are in `WorldLock` mode, while yaw axis is in `VehicleFollow` mode.

The user can change the mode with:

```cpp
auterion::GimbalMode gimbal_mode();
gimbal_mode.yaw = auterion::GimbalMode::AxisMode::WorldLock;
gimbal.setGimbalMode(gimbal_mode);
```

## Gimbal Control

We can control either the gimbal axes rates or their absolute orientation.

```cpp
// Rate control
if (gimbal.takeControl()) {
    gimbal.setRateControl(0, 0.1, 0.2); // pitching at 0.1 rad/s and yawing at 0.2 rad/s 
    gimbal.releaseControl();
}
```

```cpp
// Attitude control
if (gimbal.takeControl()) {
    gimbal.setAttitudeControl(5, -10, 0); // roll 5° and pitch -10°
    gimbal.releaseControl();
}
```
