Navigation

core.quat.euler_correction

Inputs

Name

Type

Title

Mandatory

Description

roll_err

core.type.f64

Roll

True

None

pitch_err

core.type.f64

Pitch

True

None

yaw_err

core.type.f64

Yaw

True

None

q

<fspeclib.Structure object at 0x7f2b33a7c250>

Quaternion to correct

True

None

roll

core.type.f64

Current roll

True

None

Outputs

Name

Type

Title

Description

q

<fspeclib.Structure object at 0x7f2b33a7c250>

Correction quaternion

None

Parameters

Function has no parameters

State variables

Function has no state variables

Usage XML code snippet

core_quat_euler_correction snippet for FLOW configuration file
<f name="euler_correction" by_spec="core.quat.euler_correction">
    <in alias="roll_err">some_block_1/output</in>
    <in alias="pitch_err">some_block_2/output</in>
    <in alias="yaw_err">some_block_3/output</in>
    <in alias="q">some_block_4/output</in>
    <in alias="roll">some_block_5/output</in>
</f>

Function’s artifacts

declaration.py
from fspeclib import *





Function(
    name='core.quat.euler_correction',
    title=LocalizedString(
        en='Calculate correction quaternion from Euler angles errors'
    ),
    inputs=[
        Input(
            name='roll_err',
            title='Roll',
            value_type='core.type.f64'
        ),
        Input(
            name='pitch_err',
            title='Pitch',
            value_type='core.type.f64'
        ),
        Input(
            name='yaw_err',
            title='Yaw',
            value_type='core.type.f64'
        ),

        Input(
            name='q',
            title='Quaternion to correct',
            value_type='core.type.quat'
        ),

        Input(
            name='roll',
            title='Current roll',
            value_type='core.type.f64'
        ),

    ],
    outputs=[
        Output(
            name='q',
            title='Correction quaternion',
            value_type='core.type.quat'
        ),
    ],
)
core_quat_euler_correction_exec.c
#include <math.h>

#include "core_quat_euler_correction.h"


void quat_product ( const core_type_quat_t * ql, const core_type_quat_t* qr, core_type_quat_t* out ) {
    core_type_quat_t tmp;
    tmp.w = qr->w * ql->w - qr->x * ql->x - qr->y * ql->y - qr->z * ql->z;
    tmp.x = qr->w * ql->x + qr->x * ql->w - qr->y * ql->z + qr->z * ql->y;
    tmp.y = qr->w * ql->y + qr->x * ql->z + qr->y * ql->w - qr->z * ql->x;
    tmp.z = qr->w * ql->z - qr->x * ql->y + qr->y * ql->x + qr->z * ql->w;
    *out = tmp;
}

void core_quat_euler_correction_exec(
    const core_quat_euler_correction_inputs_t *i,
    core_quat_euler_correction_outputs_t *o
)
{
    core_type_quat_t q_err;
    core_type_quat_t q_out;

    if (fabs(i->yaw_err) > 0.0) {
        q_err.w = cos(-i->yaw_err * 0.5);
        q_err.x = 0;
        q_err.y = 0;
        q_err.z = sin(-i->yaw_err * 0.5);

        quat_product(&q_err, &i->q, &q_out);
    } else {
        q_out = i->q;
    }

    if ((fabs(i->roll_err) > 0.0) || (fabs(i->pitch_err) > 0.0)) {
        q_err.w = cos(-i->roll_err * 0.5);
        q_err.x = sin(-i->roll_err * 0.5);;
        q_err.y = 0;
        q_err.z = 0;

        core_type_quat_t q_err2;
        core_type_f64_t sin_err_pitch = sin(-i->pitch_err * 0.5);
        q_err2.w = cos(-i->pitch_err * 0.5);;
        q_err2.x = 0;
        q_err2.y =  sin_err_pitch * cos(-i->roll);
        q_err2.z = -sin_err_pitch * sin(-i->roll);

        quat_product(&q_err2, &q_err, &q_err);
        quat_product(&q_out, &q_err, &q_out);
    }

    o->q = q_out;
}
core_quat_euler_correction.h
/**
 *  Automatically-generated file. Do not edit!
 */

#ifndef FSPEC_CORE_QUAT_EULER_CORRECTION_H
#define FSPEC_CORE_QUAT_EULER_CORRECTION_H

#include <stdint.h>
#include <eswb/types.h>

#include "function.h"

/* Include declaration of dependency types */
#include "core_type_f64.h"
#include "core_type_quat.h"

/**
 * @brief Inputs of `core.quat.euler_correction` function
 */
typedef struct core_quat_euler_correction_inputs_ {
    core_type_f64_t roll_err;  /// Roll
    core_type_f64_t pitch_err;  /// Pitch
    core_type_f64_t yaw_err;  /// Yaw
    core_type_quat_t q;  /// Quaternion to correct
    core_type_f64_t roll;  /// Current roll

} core_quat_euler_correction_inputs_t;

/**
 * @brief Outputs of `core.quat.euler_correction` function
 */
typedef struct core_quat_euler_correction_outputs_ {
    core_type_quat_t q; /// Correction quaternion

} core_quat_euler_correction_outputs_t;

typedef struct core_quat_euler_correction_eswb_descriptors_ {
    eswb_topic_descr_t in_roll_err;
    eswb_topic_descr_t in_pitch_err;
    eswb_topic_descr_t in_yaw_err;
    eswb_topic_descr_t in_q;
    eswb_topic_descr_t in_roll;
    eswb_topic_descr_t out_all;
} core_quat_euler_correction_eswb_descriptors_t;

typedef struct core_quat_euler_correction_interface_ {
    core_quat_euler_correction_inputs_t i;
    core_quat_euler_correction_outputs_t o;
    core_quat_euler_correction_eswb_descriptors_t eswb_descriptors;
} core_quat_euler_correction_interface_t;

void core_quat_euler_correction_exec(
    const core_quat_euler_correction_inputs_t *i,
    core_quat_euler_correction_outputs_t *o
);

#endif // FSPEC_CORE_QUAT_EULER_CORRECTION_H
core_quat_euler_correction_spec.c
/**
 *  Automatically-generated file. Do not edit!
 */

#include "core_quat_euler_correction.h"
#include <eswb/types.h>

static const param_spec_t *params[1] = {
    NULL
};

static const input_spec_t i_roll_err = {
    .name = "roll_err",
    .annotation = "Roll",
    .flags = 0
};

static const input_spec_t i_pitch_err = {
    .name = "pitch_err",
    .annotation = "Pitch",
    .flags = 0
};

static const input_spec_t i_yaw_err = {
    .name = "yaw_err",
    .annotation = "Yaw",
    .flags = 0
};

static const input_spec_t i_q = {
    .name = "q",
    .annotation = "Quaternion to correct",
    .flags = 0
};

static const input_spec_t i_roll = {
    .name = "roll",
    .annotation = "Current roll",
    .flags = 0
};

static const input_spec_t *inputs[6] = {
    &i_roll_err,
    &i_pitch_err,
    &i_yaw_err,
    &i_q,
    &i_roll,
    NULL
};

static const output_spec_t o_q = {
    .name = "q",
    .annotation = "Correction quaternion",
    .flags = 0
};

static const output_spec_t *outputs[2] = {
    &o_q,
    NULL
};

fspec_rv_t core_quat_euler_correction_call_init_inputs(
    void *dh,
    const func_conn_spec_t *conn_spec,
    eswb_topic_descr_t mounting_td
);

fspec_rv_t core_quat_euler_correction_call_init_outputs(
    void *dh,
    const func_conn_spec_t *conn_spec,
    eswb_topic_descr_t mounting_td,
    const char *func_name
);

void core_quat_euler_correction_call_exec(void *dh);

const function_spec_t atomic_core_quat_euler_correction_spec = {
    .name = "core.quat.euler_correction",
    .annotation = "Calculate correction quaternion from Euler angles errors",
    .inputs = inputs,
    .outputs = outputs,
    .params = params
};

const function_calls_t atomic_core_quat_euler_correction_calls = {
    .interface_handle_size = sizeof(core_quat_euler_correction_interface_t),
    .init = NULL,
    .init_inputs = core_quat_euler_correction_call_init_inputs,
    .init_outputs = core_quat_euler_correction_call_init_outputs,
    .pre_exec_init = NULL,
    .exec = core_quat_euler_correction_call_exec,
    .set_params = NULL
};

const function_handler_t atomic_core_quat_euler_correction_handler = {
    .spec = &atomic_core_quat_euler_correction_spec,
    .calls = &atomic_core_quat_euler_correction_calls,
    .extension_handler = NULL
};
core_quat_euler_correction_interface.c
/**
 *  Automatically-generated file. Do not edit!
 */

#include "core_quat_euler_correction.h"

#include "error.h"
#include <eswb/api.h>
#include <eswb/topic_proclaiming_tree.h>
#include <eswb/errors.h>

int core_quat_euler_correction_interface_inputs_init(
    core_quat_euler_correction_interface_t *interface,
    const func_conn_spec_t *conn_spec,
    eswb_topic_descr_t mounting_td
)
{
    eswb_rv_t rv;
    int errcnt_no_topic = 0;
    int errcnt_no_input = 0;
    const char *topic_path_in_roll_err = fspec_find_path2connect(conn_spec,"roll_err");
    const char *topic_path_in_pitch_err = fspec_find_path2connect(conn_spec,"pitch_err");
    const char *topic_path_in_yaw_err = fspec_find_path2connect(conn_spec,"yaw_err");
    const char *topic_path_in_q = fspec_find_path2connect(conn_spec,"q");
    const char *topic_path_in_roll = fspec_find_path2connect(conn_spec,"roll");

    // Connecting mandatory input "roll_err"
    if (topic_path_in_roll_err != NULL) {
        rv = eswb_connect_nested(mounting_td, topic_path_in_roll_err, &interface->eswb_descriptors.in_roll_err);
        if(rv != eswb_e_ok) {
            error("failed connect input \"roll_err\" to topic \"%s\": %s", topic_path_in_roll_err, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    } else {
        error("mandatory input \"roll_err\" is not speicifed");
        errcnt_no_input++;
    }

    // Connecting mandatory input "pitch_err"
    if (topic_path_in_pitch_err != NULL) {
        rv = eswb_connect_nested(mounting_td, topic_path_in_pitch_err, &interface->eswb_descriptors.in_pitch_err);
        if(rv != eswb_e_ok) {
            error("failed connect input \"pitch_err\" to topic \"%s\": %s", topic_path_in_pitch_err, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    } else {
        error("mandatory input \"pitch_err\" is not speicifed");
        errcnt_no_input++;
    }

    // Connecting mandatory input "yaw_err"
    if (topic_path_in_yaw_err != NULL) {
        rv = eswb_connect_nested(mounting_td, topic_path_in_yaw_err, &interface->eswb_descriptors.in_yaw_err);
        if(rv != eswb_e_ok) {
            error("failed connect input \"yaw_err\" to topic \"%s\": %s", topic_path_in_yaw_err, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    } else {
        error("mandatory input \"yaw_err\" is not speicifed");
        errcnt_no_input++;
    }

    // Connecting mandatory input "q"
    if (topic_path_in_q != NULL) {
        rv = eswb_connect_nested(mounting_td, topic_path_in_q, &interface->eswb_descriptors.in_q);
        if(rv != eswb_e_ok) {
            error("failed connect input \"q\" to topic \"%s\": %s", topic_path_in_q, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    } else {
        error("mandatory input \"q\" is not speicifed");
        errcnt_no_input++;
    }

    // Connecting mandatory input "roll"
    if (topic_path_in_roll != NULL) {
        rv = eswb_connect_nested(mounting_td, topic_path_in_roll, &interface->eswb_descriptors.in_roll);
        if(rv != eswb_e_ok) {
            error("failed connect input \"roll\" to topic \"%s\": %s", topic_path_in_roll, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    } else {
        error("mandatory input \"roll\" is not speicifed");
        errcnt_no_input++;
    }

    if ((errcnt_no_input > 0) || (errcnt_no_topic > 0)) {
        if (errcnt_no_input > errcnt_no_topic) {
            return fspec_rv_no_input;
        } else {
            return fspec_rv_no_topic;
        }
    }
    return fspec_rv_ok;
}

fspec_rv_t core_quat_euler_correction_interface_inputs_update(core_quat_euler_correction_interface_t *interface)
{
    eswb_rv_t rv;

    rv = eswb_read(interface->eswb_descriptors.in_roll_err, &interface->i.roll_err);
    if(rv != eswb_e_ok) {
        /*FIXME nothing to do yet*/
    }

    rv = eswb_read(interface->eswb_descriptors.in_pitch_err, &interface->i.pitch_err);
    if(rv != eswb_e_ok) {
        /*FIXME nothing to do yet*/
    }

    rv = eswb_read(interface->eswb_descriptors.in_yaw_err, &interface->i.yaw_err);
    if(rv != eswb_e_ok) {
        /*FIXME nothing to do yet*/
    }

    rv = eswb_read(interface->eswb_descriptors.in_q, &interface->i.q);
    if(rv != eswb_e_ok) {
        /*FIXME nothing to do yet*/
    }

    rv = eswb_read(interface->eswb_descriptors.in_roll, &interface->i.roll);
    if(rv != eswb_e_ok) {
        /*FIXME nothing to do yet*/
    }

    return 0;
}

fspec_rv_t core_quat_euler_correction_interface_outputs_init(
    core_quat_euler_correction_interface_t *interface,
    const func_conn_spec_t *conn_spec,
    eswb_topic_descr_t mounting_td,
    const char *func_name
)
{
    TOPIC_TREE_CONTEXT_LOCAL_DEFINE(cntx, 6);
    core_quat_euler_correction_outputs_t out;
    eswb_rv_t rv;

    topic_proclaiming_tree_t *rt = usr_topic_set_struct(cntx, out, func_name);

    topic_proclaiming_tree_t* q_s_root = usr_topic_add_struct_child(cntx, rt, core_quat_euler_correction_outputs_t, q, "q", tt_struct);
    usr_topic_add_struct_child(cntx, q_s_root, core_type_quat_t, w, "w", tt_double);
    usr_topic_add_struct_child(cntx, q_s_root, core_type_quat_t, x, "x", tt_double);
    usr_topic_add_struct_child(cntx, q_s_root, core_type_quat_t, y, "y", tt_double);
    usr_topic_add_struct_child(cntx, q_s_root, core_type_quat_t, z, "z", tt_double);

    rv = eswb_proclaim_tree(mounting_td, rt, cntx->t_num, &interface->eswb_descriptors.out_all);
    if (rv != eswb_e_ok) {
        return fspec_rv_publish_err;
    }

    return fspec_rv_ok;
}

fspec_rv_t core_quat_euler_correction_interface_outputs_update(core_quat_euler_correction_interface_t *interface)
{
    eswb_rv_t rv;

    rv = eswb_update_topic(interface->eswb_descriptors.out_all, &interface->o);
    if (rv != eswb_e_ok) {
        return 1;
    }

    return 0;
}

void core_quat_euler_correction_interface_update(core_quat_euler_correction_interface_t *interface)
{
    core_quat_euler_correction_interface_inputs_update(interface);
    core_quat_euler_correction_exec(&interface->i, &interface->o);
    core_quat_euler_correction_interface_outputs_update(interface);
}

fspec_rv_t core_quat_euler_correction_call_init_inputs(
    void *dh,
    const func_conn_spec_t *conn_spec,
    eswb_topic_descr_t mounting_td
)
{
    core_quat_euler_correction_interface_t *interface = (core_quat_euler_correction_interface_t*) dh;
    return core_quat_euler_correction_interface_inputs_init(interface, conn_spec, mounting_td);
}

fspec_rv_t core_quat_euler_correction_call_init_outputs(
    void *dh,
    const func_conn_spec_t *conn_spec,
    eswb_topic_descr_t mounting_td,
    const char *func_name
)
{
    core_quat_euler_correction_interface_t *interface = (core_quat_euler_correction_interface_t*) dh;
    return core_quat_euler_correction_interface_outputs_init(interface, conn_spec, mounting_td, func_name);
}

void core_quat_euler_correction_call_exec(void *dh)
{
    core_quat_euler_correction_interface_t *interface = (core_quat_euler_correction_interface_t*) dh;
    core_quat_euler_correction_interface_update(interface);
}