Copyright 2023 Travis J. West, https://traviswest.ca, Input Devices and Music Interaction Laboratory (IDMIL), Centre for Interdisciplinary Research in Music Media and Technology (CIRMMT), McGill University, Montréal, Canada, and Univ. Lille, Inria, CNRS, Centrale Lille, UMR 9189 CRIStAL, F-59000 Lille, France
SPDX-License-Identifier: MIT
This document describes concepts useful for implementing MIMU components.
Endpoints Existence
A MIMU is a component that exposes output endpoints for the accelerometer, gyroscope, and magnetometer. Each of these are detected with their own concepts so that different spellings are possible. We define the concept in terms of the generic accessor function; if none of the expected spellings are found, the accessor returns void. The concept returns true for any type where the accessor does not return void. We use a macro to facilitate the implementation of the accessors.
As well as existing, the MIMU data needs to be accessible somehow. A number of different APIs are supported and abstracted over, including array subscript operator, x-y-z methods, and x-y-z members.
// @='endpoints'
#define try_spelling(SPELLING)\
if constexpr (requires {mimu_data.SPELLING;}) return mimu_data.SPELLING; /* member acces */ \
else if constexpr (requires {mimu_data.SPELLING();}) return mimu_data.SPELLING(); /* member function */ \
else if constexpr (requires {mimu_data->SPELLING;}) return mimu_data->SPELLING; /* member through pointer */ \
else if constexpr (requires {mimu_data->SPELLING();}) return mimu_data->SPELLING() /* member function through pointer */
auto& accl_of(auto& mimu_data)
{
try_spelling(accelerometer);
else try_spelling(acceleration);
else try_spelling(accel);
else try_spelling(accl);
else try_spelling(acc);
else try_spelling(a);
elsereturn 0; // mimu_data is not MIMU data!
}
auto& gyro_of(auto& mimu_data)
{
try_spelling(gyroscope);
else try_spelling(angular_rate);
else try_spelling(gyro);
else try_spelling(g);
elsereturn 0; // mimu_data is not MIMU data!
}
auto& magn_of(auto& mimu_data)
{
try_spelling(magnetometer);
else try_spelling(magnetic_field);
else try_spelling(magn);
else try_spelling(mag);
else try_spelling(m);
elsereturn 0; // mimu_data is not MIMU data!
}
auto& vecx_of(auto& mimu_data) // this arg has to be called `mimu_data` to work with the macro
Access the first vector component of a presumed MIMU data vector.
Definition sygac-mimu.hpp:63
With these generic functions for accessing the elements of a MIMU data vector, and for accessing a MIMU data vector from a MIMU data structure, we go on to define type traits and concepts. The type traits are a bit of a mouthful, but it essentially boils down to decltype(accl_of(T)) modulo detail, declval and removed and added references. It's an implementation detail. Don't worry too much about it unless you're trying to fix it...
The above concepts are the most general possible. Sygaldry imposes a few additional expectations on MIMU data for its sensor fusion and mapping facilities to be able to injest this data.
First, a MIMU component is one whose output endpoints structure meets the above MimuDataStruct concept. Second, MIMU data within Sygaldry must signal that it has been updated, meeting the requirements of ClearableFlag. This gives the following concept:
// @+'MimuDataStruct'
template<typename T>
concept MimuComponent
= MimuDataStruct<outputs_t<T>>
&& ClearableFlag<accl_t<outputs_t<T>>>
&& ClearableFlag<gyro_t<outputs_t<T>>>
&& ClearableFlag<magn_t<outputs_t<T>>>
;
// @/
Accessors
We define the following additional accessors for convenience.