6#include "dawn/prog/ahrs.hxx"
11#include "dawn/debug.hxx"
12#include "dawn/io/common.hxx"
18constexpr float GRAVITY = 9.80665f;
19constexpr float RAD2DEG = 57.29577951308232f;
20constexpr float DT_MIN = 0.001f;
21constexpr float DT_MAX = 0.1f;
27 clock_gettime(CLOCK_MONOTONIC, &ts);
28 return static_cast<uint64_t
>(ts.tv_sec) * 1000000000ull + ts.tv_nsec;
55CProgAhrs::~CProgAhrs()
60int CProgAhrs::configureDesc(
const CDescObject &desc)
66 for (
size_t i = 0; i < desc.
getSize(); i++)
70 if (item->
cfgid.
s.
cls != CProgCommon::PROG_CLASS_AHRS)
72 DAWNERR(
"ahrs: unsupported cfg class 0x%" PRIx32
"\n", item->
cfgid.
v);
78 case PROG_AHRS_CFG_ACCEL:
86 case PROG_AHRS_CFG_GYRO:
94 case PROG_AHRS_CFG_MAG:
102 case PROG_AHRS_CFG_OUTPUT:
110 case PROG_AHRS_CFG_PARAMS:
112 if (item->
cfgid.
s.
size !=
sizeof(SProgAhrsParams) / 4)
114 DAWNERR(
"ahrs: invalid PARAMS size %d, expected %zu\n",
116 sizeof(SProgAhrsParams) / 4);
120 const SProgAhrsParams *params =
reinterpret_cast<const SProgAhrsParams *
>(item->
data);
130 DAWNERR(
"ahrs: unsupported cfg id %u\n", item->
cfgid.
s.
id);
135 if (accelId == 0 || gyroId == 0 || outputId == 0)
137 DAWNERR(
"ahrs: accel, gyro and output are required\n");
141 if (!paramsValid(pGain, pRejection, pPeriod, pRate))
143 DAWNERR(
"ahrs: params out of range\n");
152 return configureDesc(
getDesc());
155bool CProgAhrs::paramsValid(
float gain,
float rejection,
float period,
float rate)
157 return gain >= 0.0f && gain <= 10.0f && rejection >= 0.0f && rejection <= 90.0f &&
158 period >= 0.0f && period <= 60.0f && rate >= 1.0f && rate <= 1000.0f;
161int CProgAhrs::validateInput(
CIOCommon *io)
const
177void CProgAhrs::applySettings()
179 FusionAhrsSettings settings;
181 settings.convention = FusionConventionNwu;
182 settings.gain = pGain;
183 settings.gyroscopeRange = 2000.0f;
184 settings.accelerationRejection = pRejection;
186 settings.magneticRejection = (magId != 0) ? pRejection : 0.0f;
187 settings.recoveryTriggerPeriod =
static_cast<unsigned int>(pPeriod * pRate);
189 FusionAhrsSetSettings(&ahrs, &settings);
196 accel =
getIO(accelId);
197 gyro =
getIO(gyroId);
198 output =
getIO(outputId);
200 if (accel ==
nullptr || gyro ==
nullptr || output ==
nullptr)
202 DAWNERR(
"ahrs: IO not found\n");
206 ret = validateInput(accel);
209 DAWNERR(
"ahrs: accel IO 0x%" PRIx32
" incompatible\n", accelId);
213 ret = validateInput(gyro);
216 DAWNERR(
"ahrs: gyro IO 0x%" PRIx32
" incompatible\n", gyroId);
223 ret = validateInput(mag);
226 DAWNERR(
"ahrs: mag IO 0x%" PRIx32
" incompatible\n", magId);
231 ret = prepareWritableTarget(output, 3,
true);
234 DAWNERR(
"ahrs: output prepare failed %d\n", ret);
239 if (outData ==
nullptr)
241 DAWNERR(
"ahrs: data allocation failed\n");
245 FusionOffsetInitialise(&offset,
static_cast<unsigned int>(pRate));
246 FusionAhrsInitialise(&ahrs);
271int CProgAhrs::accelNotifierCb(
void *priv,
io_ddata_t *data)
275 if (obj ==
nullptr || !obj->active || data ==
nullptr)
280 const float *v =
reinterpret_cast<const float *
>(data->
getDataPtr());
282 obj->accelG.axis.x = v[0] / GRAVITY;
283 obj->accelG.axis.y = v[1] / GRAVITY;
284 obj->accelG.axis.z = v[2] / GRAVITY;
285 obj->haveAccel =
true;
289int CProgAhrs::magNotifierCb(
void *priv,
io_ddata_t *data)
293 if (obj ==
nullptr || !obj->active || data ==
nullptr)
298 const float *v =
reinterpret_cast<const float *
>(data->
getDataPtr());
300 obj->magRaw.axis.x = v[0];
301 obj->magRaw.axis.y = v[1];
302 obj->magRaw.axis.z = v[2];
307int CProgAhrs::gyroNotifierCb(
void *priv,
io_ddata_t *data)
311 if (obj ==
nullptr || !obj->active || data ==
nullptr)
316 obj->handleGyro(data);
322 if (!haveAccel || outData ==
nullptr || output ==
nullptr)
329 const float *v =
reinterpret_cast<const float *
>(data->
getDataPtr());
332 g.axis.x = v[0] * RAD2DEG;
333 g.axis.y = v[1] * RAD2DEG;
334 g.axis.z = v[2] * RAD2DEG;
339 uint64_t now = monotonicNs();
340 float dt = 1.0f / pRate;
344 float measured =
static_cast<float>(now - lastNs) * 1e-9f;
345 if (measured >= DT_MIN && measured <= DT_MAX)
353 g = FusionOffsetUpdate(&offset, g);
356 FusionAhrsUpdate(&ahrs, g, accelG, magRaw, dt);
360 FusionAhrsUpdateNoMagnetometer(&ahrs, g, accelG, dt);
363 const FusionVector earth = FusionAhrsGetEarthAcceleration(&ahrs);
364 float *out =
reinterpret_cast<float *
>(outData->
getDataPtr());
366 out[0] = earth.axis.x * GRAVITY;
367 out[1] = earth.axis.y * GRAVITY;
368 out[2] = earth.axis.z * GRAVITY;
370 int ret = output->
setData(*outData);
373 DAWNERR(
"ahrs: output setData failed %d\n", ret);
384 if (data ==
nullptr || len !=
sizeof(SProgAhrsParams) /
sizeof(uint32_t))
389 const SProgAhrsParams *params =
reinterpret_cast<const SProgAhrsParams *
>(data);
395 if (!paramsValid(gain, rejection, period, rate))
400 bool rateChanged = rate != pRate;
403 pRejection = rejection;
410 FusionOffsetInitialise(&offset,
static_cast<unsigned int>(pRate));
422 ret = accel->setNotifier(accelNotifierCb, 0,
this);
425 DAWNERR(
"ahrs: accel setNotifier failed %d\n", ret);
429 ret = gyro->setNotifier(gyroNotifierCb, 0,
this);
432 DAWNERR(
"ahrs: gyro setNotifier failed %d\n", ret);
433 accel->setNotifier(
nullptr, 0,
nullptr);
439 ret = mag->setNotifier(magNotifierCb, 0,
this);
442 DAWNERR(
"ahrs: mag setNotifier failed %d\n", ret);
443 accel->setNotifier(
nullptr, 0,
nullptr);
444 gyro->setNotifier(
nullptr, 0,
nullptr);
460 if (accel !=
nullptr)
462 accel->setNotifier(
nullptr, 0,
nullptr);
467 gyro->setNotifier(
nullptr, 0,
nullptr);
472 mag->setNotifier(
nullptr, 0,
nullptr);
CIOCommon * getIO(SObjectId::ObjectId id)
Get an I/O object by ID.
void setObjectMapItem(SObjectId::ObjectId id, CObject *obj)
Set an item in the object map.
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemNext(size_t &offset) const
Get config item at current offset and advance past it.
Base class for all I/O objects.
int setData(IODataCmn &data, size_t offset=0)
Set data for I/O (public interface with stats tracking).
virtual bool isNotify() const =0
Check if IO supports notifications.
virtual size_t getDataDim() const =0
Get data vector dimension.
io_ddata_t * ddata_alloc(size_t batch, size_t chunk_size=0)
Allocate data buffer for this I/O.
virtual bool isRead() const =0
Check if IO supports read operations.
CDescObject & getDesc()
Get descriptor object for this object.
uint8_t getDtype() const
Get data type field.
AHRS sensor fusion (x-io Fusion): accel + gyro IOs in, world-frame linear acceleration (gravity remov...
int init()
One-time initialize object after bindings are resolved.
int doStart()
Start implementation hook.
bool hasThread() const
Check if a background thread is active.
int deinit()
De-initialize object.
int onSetObjConfig(SObjectCfg::ObjectCfgId objcfg, uint32_t *data, size_t len)
Pre-update hook for runtime configuration writes.
int configure()
Configure object from descriptor data.
int doStop()
Stop implementation hook.
Base class for all PROG (processing) objects.
uint32_t ObjectCfgId
ConfigID type - single 32-bit value.
static float cfgToF(ObjectCfgData_t x)
Convert ObjectCfgData_t to float.
static uint8_t objectCfgGetId(const ObjectCfgId objcfg)
Extract configuration identifier from ConfigID.
Out-of-tree user-extension hooks for Dawn.
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
@ DTYPE_FLOAT
IEEE 754 single-precision floating point (32-bit).
Heap-allocated dynamic I/O data buffer.
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.
32-bit encoded object identifier (union with bit field).
ObjectId v
Raw 32-bit ObjectID value (for comparison, hashing, storage).