//
// Copyright (c) 2018-2019, 2021-2024, 2026 LAAS/CNRS
// All rights reserved.
//
// Redistribution  and  use  in  source  and binary  forms,  with  or  without
// modification, are permitted provided that the following conditions are met:
//
//   1. Redistributions of  source  code must retain the  above copyright
//      notice and this list of conditions.
//   2. Redistributions in binary form must reproduce the above copyright
//      notice and  this list of  conditions in the  documentation and/or
//      other materials provided with the distribution.
//
// THE SOFTWARE  IS PROVIDED "AS IS"  AND THE AUTHOR  DISCLAIMS ALL WARRANTIES
// WITH  REGARD   TO  THIS  SOFTWARE  INCLUDING  ALL   IMPLIED  WARRANTIES  OF
// MERCHANTABILITY AND  FITNESS.  IN NO EVENT  SHALL THE AUTHOR  BE LIABLE FOR
// ANY  SPECIAL, DIRECT,  INDIRECT, OR  CONSEQUENTIAL DAMAGES  OR  ANY DAMAGES
// WHATSOEVER  RESULTING FROM  LOSS OF  USE, DATA  OR PROFITS,  WHETHER  IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR  OTHER TORTIOUS ACTION, ARISING OUT OF OR
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
//                                           Anthony Mallet on Wed May 30 2018
//


// This file was generated from uavatt.gen by the skeleton
// template. Manual changes should be preserved, although they should
// rather be added to the "doc" attributes of the genom objects defined in
// uavatt.gen.

= uavatt component
openrobots@laas.fr
1.3
:toc: left

// fix default asciidoctor stylesheet issue #2407 and add hr clear rule
ifdef::backend-html5[]
[pass]
++++
<link rel="stylesheet" href="data:text/css,p{font-size: inherit !important}" >
<link rel="stylesheet" href="data:text/css,hr{clear: both}" >
++++
endif::[]



== Ports


[[uav_input]]
=== uav_input (in)


[role="small", width="50%", float="right", cols="1"]
|===
a|.Data structure
[disc]
 * `struct ::or_uav::input` `uav_input`
 ** `struct ::or::time::ts` `ts`
 *** `long` `sec`
 *** `long` `nsec`
 ** `boolean` `intrinsic`
 ** `optional< struct ::or::rb3d::force >` `thrust`
 *** `double` `x`
 *** `double` `y`
 *** `double` `z`
 ** `optional< struct ::or::t3d::att >` `att`
 *** `double` `qw`
 *** `double` `qx`
 *** `double` `qy`
 *** `double` `qz`
 ** `optional< struct ::or::t3d::avel >` `avel`
 *** `double` `wx`
 *** `double` `wy`
 *** `double` `wz`
 ** `optional< struct ::or::t3d::aacc >` `aacc`
 *** `double` `awx`
 *** `double` `awy`
 *** `double` `awz`

|===

Attitude/thrust control input.

'''

[[wrench_measure]]
=== wrench_measure (out)


[role="small", width="50%", float="right", cols="1"]
|===
a|.Data structure
[disc]
 * `struct ::or_wrench_estimator::state` `wrench_measure`
 ** `struct ::or::time::ts` `ts`
 *** `long` `sec`
 *** `long` `nsec`
 ** `boolean` `intrinsic`
 ** `optional< struct ::or::rb3d::force >` `force`
 *** `double` `x`
 *** `double` `y`
 *** `double` `z`
 ** `optional< struct ::or::rb3d::force_cov >` `force_cov`
 *** `double` `cov[6]`
 ** `optional< struct ::or::rb3d::torque >` `torque`
 *** `double` `x`
 *** `double` `y`
 *** `double` `z`
 ** `optional< struct ::or::rb3d::torque_cov >` `torque_cov`
 *** `double` `cov[6]`

|===

Provides current wrench measurements.

This port contains the current wrench exerted by the UAV according
to the propeller measurements and the geometric model.

'''

[[rotor_input]]
=== rotor_input (out)


[role="small", width="50%", float="right", cols="1"]
|===
a|.Data structure
[disc]
 * `struct ::or_rotorcraft::input` `rotor_input`
 ** `struct ::or::time::ts` `ts`
 *** `long` `sec`
 *** `long` `nsec`
 ** `enum ::or_rotorcraft::control_type` `control` ∈ { `velocity`, `throttle` }
 ** `sequence< double, 8 >` `desired`

|===

'''

[[rotor_measure]]
=== rotor_measure (in)


[role="small", width="50%", float="right", cols="1"]
|===
a|.Data structure
[disc]
 * `struct ::or_rotorcraft::output` `rotor_measure`
 ** `sequence< struct ::or_rotorcraft::rotor_state, 8 >` `rotor`
 *** `struct ::or::time::ts` `ts`
 **** `long` `sec`
 **** `long` `nsec`
 *** `boolean` `emerg`
 *** `boolean` `spinning`
 *** `boolean` `starting`
 *** `boolean` `disabled`
 *** `double` `velocity`
 *** `double` `throttle`
 *** `double` `consumption`
 *** `double` `energy_level`

|===

'''

[[state]]
=== state (in)


[role="small", width="50%", float="right", cols="1"]
|===
a|.Data structure
[disc]
 * `struct ::or_pose_estimator::state` `state`
 ** `struct ::or::time::ts` `ts`
 *** `long` `sec`
 *** `long` `nsec`
 ** `boolean` `intrinsic`
 ** `optional< struct ::or::t3d::pos >` `pos`
 *** `double` `x`
 *** `double` `y`
 *** `double` `z`
 ** `optional< struct ::or::t3d::att >` `att`
 *** `double` `qw`
 *** `double` `qx`
 *** `double` `qy`
 *** `double` `qz`
 ** `optional< struct ::or::t3d::vel >` `vel`
 *** `double` `vx`
 *** `double` `vy`
 *** `double` `vz`
 ** `optional< struct ::or::t3d::avel >` `avel`
 *** `double` `wx`
 *** `double` `wy`
 *** `double` `wz`
 ** `optional< struct ::or::t3d::acc >` `acc`
 *** `double` `ax`
 *** `double` `ay`
 *** `double` `az`
 ** `optional< struct ::or::t3d::aacc >` `aacc`
 *** `double` `awx`
 *** `double` `awy`
 *** `double` `awz`
 ** `optional< struct ::or::t3d::pos_cov >` `pos_cov`
 *** `double` `cov[6]`
 ** `optional< struct ::or::t3d::att_cov >` `att_cov`
 *** `double` `cov[10]`
 ** `optional< struct ::or::t3d::att_pos_cov >` `att_pos_cov`
 *** `double` `cov[12]`
 ** `optional< struct ::or::t3d::vel_cov >` `vel_cov`
 *** `double` `cov[6]`
 ** `optional< struct ::or::t3d::avel_cov >` `avel_cov`
 *** `double` `cov[6]`
 ** `optional< struct ::or::t3d::acc_cov >` `acc_cov`
 *** `double` `cov[6]`
 ** `optional< struct ::or::t3d::aacc_cov >` `aacc_cov`
 *** `double` `cov[6]`

|===

'''

== Services

[[set_mass]]
=== set_mass (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `double` `mass`

|===

'''

[[set_geom]]
=== set_geom (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `double` `mass` Mass (kg)

 * `double` `G[48]` Mapping from propellers velocity² to wrench

|===

Set mass and allocation matrix

This is a generic function for setting the geometric parameters of
the controlled robot. See <<set_gtmrp_geom>> for a specialized
function for tilted multi rotors robots.

'''

[[set_gtmrp_geom]]
=== set_gtmrp_geom (function)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `unsigned short` `rotors` (default `"4"`) Number of rotors

 * `double` `cx` (default `"0"`) X position of center of rotors wrt center of mass (m)

 * `double` `cy` (default `"0"`) Y position of center of rotors wrt center of mass (m)

 * `double` `cz` (default `"0"`) Z position of center of rotors wrt center of mass (m)

 * `double` `armlen` (default `"0.23"`) Distance of rotors to the center (m)

 * `double` `mass` (default `"1"`) Total mass (kg)

 * `double` `rx` (default `"0"`) X rotation of the first rotor thrust vector (deg)

 * `double` `ry` (default `"0"`) Y rotation of the first rotor thrust vector (deg)

 * `short` `rz` (default `"-1"`) Z spin direction of the first rotor (1: ccw, -1: cw)

 * `double` `cf` (default `"0.00065"`) Propeller thrust coefficient (N.s²)

 * `double` `ct` (default `"1e-05"`) Propeller torque coefficient (N.m.s²)

a|.Throws
[disc]
 * `exception ::uavatt::e_inval`
 ** `string<128>` `what`

|===

Compute allocation matrix and inertia tensor for tilt rotors robots.

Generically Tilted Multi-Rotor Platforms (GTMRP) are made of a set
of rotors evenly distributed in a horizontal plane. The rotors are
tilted around an axis lying in the plane, all by the same angle but
with alternating signs on the X axis. The spinning direction is also
alternating.

This function is a specialization of the more generic <<set_geom>>.

'''

[[set_saturation_weights]]
=== set_saturation_weights (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `struct ::uavatt::ids::servo_s::satweight_s` `satweight`
 ** `boolean` `enable` (default `"1"`) Enable wrench saturation
 ** `double` `thrust` (default `"10"`) Relative weight for thrust saturation
 ** `double` `lateral` (default `"1"`) Relative weight for lateral forces saturation
 ** `double` `tilt` (default `"100"`) Relative weight for roll and pitch saturation
 ** `double` `head` (default `"1"`) Relative weight for heading saturation

a|.Throws
[disc]
 * `exception ::uavatt::e_inval`
 ** `string<128>` `what`

|===

Select relative priority for thrust, titlting and heading.

When the controller reaches the physical wrench limits of the
platform (see <<set_wlimit>>), an optimisation algorithm finds
the closest feasible wrench that keeps the same thurst direction
as well as the same roll and pitch torque direction.

The weights specified here allow to give higher priority to certain
components of the wrench and let them be less affected by the
optimization algorithm. Higher weight means that the corresponding
component is less likely to change in intensity.

'''

[[set_control_mode]]
=== set_control_mode (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `enum ::uavatt::attitude_control_mode` `att_mode` (default `"::uavatt::tilt_prioritized"`) Attitude tracking control law ∈ { `full_attitude`, `tilt_prioritized` }

|===

Select attitude tracking control law.

With `tilt_prioritized`, attitude error is split into a
reduced attitude error, which describes the misalignment of
the thrust direction, and a yaw error, which describes the
heading orientation error. This is the default.

With `full_attitude`, a conventional controller, based on the full
attitude error, is used.

'''

[[set_wlimit]]
=== set_wlimit (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `double` `wmin` Minimum propeller velocity

 * `double` `wmax` Maximum propeller velocity

|===

'''

[[set_servo_gain]]
=== set_servo_gain (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `struct ::uavatt::ids::servo_s::gain_s` `gain`
 ** `double` `Kqxy`
 ** `double` `Kqz`
 ** `double` `Kwxy`
 ** `double` `Kwz`

|===

'''

[[set_emerg]]
=== set_emerg (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `struct ::uavatt::ids::servo_s::emerg_s` `emerg`
 ** `double` `dq` (default `"5"`) Attitude uncertainty threshold (deg)
 ** `double` `dw` (default `"20"`) Angular velocity uncertainty threshold (deg/s)

|===

Set thresholds for emergency hovering.

`dq` and `dw` represent the maximum uncertainty tolerated in the
input <<state>> for attitude (`dq`) and angular velocity (`dw`),
measured as 3 times the standard deviation.
By default, `dq` is 5⁰ and `dw` 20⁰/s. Beyond that threshold, an
emergency hovering is started.

The emergency hovering uses no feedback, as the state is considered
invalid. Thus, stability is not guaranteed ...

'''

[[get_servo_parameters]]
=== get_servo_parameters (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Outputs
[disc]
 * `struct ::uavatt::ids::servo_s` `servo`
 ** `struct ::uavatt::ids::servo_s::satweight_s` `satweight`
 *** `boolean` `enable`
 *** `double` `thrust`
 *** `double` `lateral`
 *** `double` `tilt`
 *** `double` `head`
 ** `struct ::uavatt::ids::servo_s::gain_s` `gain`
 *** `double` `Kqxy`
 *** `double` `Kqz`
 *** `double` `Kwxy`
 *** `double` `Kwz`
 ** `enum ::uavatt::attitude_control_mode` `att_mode` ∈ { `full_attitude`, `tilt_prioritized` }
 ** `double` `ramp`
 ** `double` `scale`
 ** `struct ::uavatt::ids::servo_s::emerg_s` `emerg`
 *** `double` `dq`
 *** `double` `dw`

|===

'''

[[get_geom_parameters]]
=== get_geom_parameters (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Outputs
[disc]
 * `struct ::uavatt::ids::body_s` `body`
 ** `double` `G[48]`
 ** `double` `iG[48]`
 ** `double` `mass`
 ** `unsigned short` `rotors`
 ** `double` `wmin`
 ** `double` `wmax`
 ** `double` `wrench_min[6]`
 ** `double` `wrench_max[6]`
 ** `boolean` `init`

|===

'''

[[get_reference]]
=== get_reference (attribute)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Outputs
[disc]
 * `struct ::or_uav::input` `reference`
 ** `struct ::or::time::ts` `ts`
 *** `long` `sec`
 *** `long` `nsec`
 ** `boolean` `intrinsic`
 ** `optional< struct ::or::rb3d::force >` `thrust`
 *** `double` `x`
 *** `double` `y`
 *** `double` `z`
 ** `optional< struct ::or::t3d::att >` `att`
 *** `double` `qw`
 *** `double` `qx`
 *** `double` `qy`
 *** `double` `qz`
 ** `optional< struct ::or::t3d::avel >` `avel`
 *** `double` `wx`
 *** `double` `wy`
 *** `double` `wz`
 ** `optional< struct ::or::t3d::aacc >` `aacc`
 *** `double` `awx`
 *** `double` `awy`
 *** `double` `awz`

|===

'''

[[servo]]
=== servo (activity)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Throws
[disc]
 * `exception ::uavatt::e_input`

 * `exception ::uavatt::e_geom`

a|.Context
[disc]
  * In task `<<main>>`
  (frequency 1000.0 _Hz_)
  * Reads port `<<uav_input>>`
|===

Track a desired attitude

'''

[[set_state]]
=== set_state (function)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `struct ::or::rb3d::force` `thrust`: Thrust
 ** `double` `x`
 ** `double` `y`
 ** `double` `z`

 * `struct ::or::t3d::att` `att`: Orientation
 ** `double` `qw`
 ** `double` `qx`
 ** `double` `qy`
 ** `double` `qz`

 * `struct ::or::t3d::avel` `avel`: Angular velocity
 ** `double` `wx`
 ** `double` `wy`
 ** `double` `wz`

 * `struct ::or::t3d::aacc` `aacc`: Angular acceleration
 ** `double` `awx`
 ** `double` `awy`
 ** `double` `awz`

a|.Throws
[disc]
 * `exception ::uavatt::e_geom`

a|.Context
[disc]
  * Interrupts `<<servo>>`
|===

Set the desired state

'''

[[coast]]
=== coast (function)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Context
[disc]
  * Interrupts `<<servo>>`
|===

Stop tracking a desired attitude

This sets the reference thrust to a purely vertical
gravity-compensation vector with 0 angular velocity
and acceleration, resulting in a coasting state.
Any dynamic reference tracking is cancelled (see <<servo>>).

'''

[[log]]
=== log (function)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Inputs
[disc]
 * `string<64>` `path` (default `"/tmp/uavatt.log"`) Log file name

 * `unsigned long` `decimation` (default `"1"`) Reduced logging frequency

a|.Throws
[disc]
 * `exception ::uavatt::e_sys`
 ** `short` `code`
 ** `string<128>` `what`

|===

Log controller data

'''

[[log_stop]]
=== log_stop (function)


Stop logging

'''

[[log_info]]
=== log_info (function)

[role="small", width="50%", float="right", cols="1"]
|===
a|.Outputs
[disc]
 * `unsigned long` `miss` Missed log entries

 * `unsigned long` `total` Total log entries

|===

Show missed log entries

'''

== Tasks

[[main]]
=== main

[role="small", width="50%", float="right", cols="1"]
|===
a|.Context
[disc]
  * Frequency 1000.0 _Hz_
* Updates port `<<wrench_measure>>`
* Updates port `<<rotor_input>>`
* Reads port `<<rotor_measure>>`
* Reads port `<<state>>`
|===

'''
