mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-11-06 07:41:35 +08:00
mixer: move MixerGroup out of Mixer hierarchy and delete mixer.h header
This commit is contained in:
@@ -56,7 +56,7 @@
|
|||||||
#include <uORB/topics/battery_status.h>
|
#include <uORB/topics/battery_status.h>
|
||||||
#include <uORB/topics/esc_status.h>
|
#include <uORB/topics/esc_status.h>
|
||||||
|
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <lib/mixer/mixer_load.h>
|
#include <lib/mixer/mixer_load.h>
|
||||||
#include <battery/battery.h>
|
#include <battery/battery.h>
|
||||||
|
|
||||||
@@ -307,7 +307,7 @@ int initialize_mixers(const char *mixers_filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_mixers == nullptr) {
|
if (_mixers == nullptr) {
|
||||||
_mixers = new MixerGroup(mixers_control_callback, (uintptr_t)_controls);
|
_mixers = new MixerGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mixers == nullptr) {
|
if (_mixers == nullptr) {
|
||||||
@@ -315,7 +315,7 @@ int initialize_mixers(const char *mixers_filename)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
int ret = _mixers->load_from_buf(buf, buflen);
|
int ret = _mixers->load_from_buf(mixers_control_callback, (uintptr_t)_controls, buf, buflen);
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
PX4_ERR("Unable to parse mixers file");
|
PX4_ERR("Unable to parse mixers file");
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
#include <drivers/drv_mixer.h>
|
#include <drivers/drv_mixer.h>
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <lib/mixer/mixer_load.h>
|
#include <lib/mixer/mixer_load.h>
|
||||||
#include <parameters/param.h>
|
#include <parameters/param.h>
|
||||||
#include <output_limit/output_limit.h>
|
#include <output_limit/output_limit.h>
|
||||||
@@ -155,12 +155,12 @@ int initialize_mixer(const char *mixer_filename)
|
|||||||
unsigned buflen = sizeof(buf);
|
unsigned buflen = sizeof(buf);
|
||||||
memset(buf, '\0', buflen);
|
memset(buf, '\0', buflen);
|
||||||
|
|
||||||
_mixer_group = new MixerGroup(mixer_control_callback, (uintptr_t) &_controls);
|
_mixer_group = new MixerGroup();
|
||||||
|
|
||||||
// PX4_INFO("Trying to initialize mixer from config file %s", mixer_filename);
|
// PX4_INFO("Trying to initialize mixer from config file %s", mixer_filename);
|
||||||
|
|
||||||
if (load_mixer_file(mixer_filename, buf, buflen) == 0) {
|
if (load_mixer_file(mixer_filename, buf, buflen) == 0) {
|
||||||
if (_mixer_group->load_from_buf(buf, buflen) == 0) {
|
if (_mixer_group->load_from_buf(mixer_control_callback, (uintptr_t) &_controls, buf, buflen) == 0) {
|
||||||
PX4_INFO("Loaded mixer from file %s", mixer_filename);
|
PX4_INFO("Loaded mixer from file %s", mixer_filename);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
#include <drivers/drv_tone_alarm.h>
|
#include <drivers/drv_tone_alarm.h>
|
||||||
|
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
|
|
||||||
#include <uORB/topics/actuator_controls.h>
|
#include <uORB/topics/actuator_controls.h>
|
||||||
#include <uORB/topics/actuator_outputs.h>
|
#include <uORB/topics/actuator_outputs.h>
|
||||||
@@ -1045,7 +1045,7 @@ MK::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
|||||||
unsigned buflen = strlen(buf);
|
unsigned buflen = strlen(buf);
|
||||||
|
|
||||||
if (_mixers == nullptr) {
|
if (_mixers == nullptr) {
|
||||||
_mixers = new MixerGroup(control_callback, (uintptr_t)&_controls);
|
_mixers = new MixerGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mixers == nullptr) {
|
if (_mixers == nullptr) {
|
||||||
@@ -1053,7 +1053,7 @@ MK::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ret = _mixers->load_from_buf(buf, buflen);
|
ret = _mixers->load_from_buf(control_callback, (uintptr_t)&_controls, buf, buflen);
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
DEVICE_DEBUG("mixer load failed with %d", ret);
|
DEVICE_DEBUG("mixer load failed with %d", ret);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2018 PX4 Development Team. All rights reserved.
|
* Copyright (c) 2012-2019 PX4 Development Team. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@@ -37,7 +37,6 @@
|
|||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
#include <drivers/drv_mixer.h>
|
#include <drivers/drv_mixer.h>
|
||||||
#include <drivers/drv_pwm_output.h>
|
#include <drivers/drv_pwm_output.h>
|
||||||
#include <lib/mixer/mixer.h>
|
|
||||||
#include <lib/mixer_module/mixer_module.hpp>
|
#include <lib/mixer_module/mixer_module.hpp>
|
||||||
#include <px4_platform_common/px4_config.h>
|
#include <px4_platform_common/px4_config.h>
|
||||||
#include <px4_platform_common/module.h>
|
#include <px4_platform_common/module.h>
|
||||||
|
|||||||
@@ -70,7 +70,8 @@
|
|||||||
#include <rc/dsm.h>
|
#include <rc/dsm.h>
|
||||||
|
|
||||||
#include <lib/mathlib/mathlib.h>
|
#include <lib/mathlib/mathlib.h>
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
|
#include <lib/mixer/MultirotorMixer.hpp>
|
||||||
#include <perf/perf_counter.h>
|
#include <perf/perf_counter.h>
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <parameters/param.h>
|
#include <parameters/param.h>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
#include <drivers/drv_mixer.h>
|
#include <drivers/drv_mixer.h>
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <lib/mixer/mixer_multirotor_normalized.generated.h>
|
#include <lib/mixer/mixer_multirotor_normalized.generated.h>
|
||||||
#include <parameters/param.h>
|
#include <parameters/param.h>
|
||||||
|
|
||||||
|
|||||||
@@ -48,12 +48,13 @@
|
|||||||
|
|
||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
#include <drivers/drv_mixer.h>
|
#include <drivers/drv_mixer.h>
|
||||||
#include <mixer/mixer.h>
|
#include <lib/mixer/MultirotorMixer.hpp>
|
||||||
#include <mixer/mixer_load.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <mixer/mixer_multirotor_normalized.generated.h>
|
#include <lib/mixer/mixer_load.h>
|
||||||
#include <parameters/param.h>
|
#include <lib/parameters/param.h>
|
||||||
#include <perf/perf_counter.h>
|
#include <lib/perf/perf_counter.h>
|
||||||
#include <output_limit/output_limit.h>
|
#include <lib/output_limit/output_limit.h>
|
||||||
|
|
||||||
#include <dev_fs_lib_pwm.h>
|
#include <dev_fs_lib_pwm.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -174,55 +175,30 @@ void update_params(Mixer::Airmode &airmode)
|
|||||||
|
|
||||||
int initialize_mixer(const char *mixer_filename)
|
int initialize_mixer(const char *mixer_filename)
|
||||||
{
|
{
|
||||||
|
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
size_t buflen = sizeof(buf);
|
size_t buflen = sizeof(buf);
|
||||||
PX4_INFO("Trying to initialize mixer from config file %s", mixer_filename);
|
PX4_INFO("Trying to initialize mixer from config file %s", mixer_filename);
|
||||||
int fd_load = ::open(mixer_filename, O_RDONLY);
|
int fd_load = ::open(mixer_filename, O_RDONLY);
|
||||||
|
|
||||||
if (fd_load != -1) {
|
int nRead = ::read(fd_load, buf, buflen);
|
||||||
int nRead = ::read(fd_load, buf, buflen);
|
close(fd_load);
|
||||||
close(fd_load);
|
|
||||||
|
|
||||||
if (nRead > 0) {
|
if (nRead > 0) {
|
||||||
_mixer = MultirotorMixer::from_text(mixer_control_callback, (uintptr_t)&_controls, buf, buflen);
|
_mixer = MultirotorMixer::from_text(mixer_control_callback, (uintptr_t)&_controls, buf, buflen);
|
||||||
|
|
||||||
if (_mixer != nullptr) {
|
if (_mixer != nullptr) {
|
||||||
PX4_INFO("Successfully initialized mixer from config file");
|
PX4_INFO("Successfully initialized mixer from config file");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
} else {
|
|
||||||
PX4_ERR("Unable to parse from mixer config file");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PX4_WARN("Unable to read from mixer config file");
|
PX4_ERR("Unable to parse from mixer config file");
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
PX4_WARN("No mixer config file found, using default mixer.");
|
|
||||||
|
|
||||||
/* Mixer file loading failed, fall back to default mixer configuration for
|
|
||||||
* QUAD_X airframe. */
|
|
||||||
float roll_scale = 1;
|
|
||||||
float pitch_scale = 1;
|
|
||||||
float yaw_scale = 1;
|
|
||||||
float deadband = 0;
|
|
||||||
|
|
||||||
_mixer = new MultirotorMixer(mixer_control_callback, (uintptr_t)&_controls,
|
|
||||||
MultirotorGeometry::QUAD_X,
|
|
||||||
roll_scale, pitch_scale, yaw_scale, deadband);
|
|
||||||
|
|
||||||
if (_mixer == nullptr) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
} else {
|
||||||
|
PX4_WARN("Unable to read from mixer config file");
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void subscribe()
|
void subscribe()
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
#include <drivers/drv_mixer.h>
|
#include <drivers/drv_mixer.h>
|
||||||
#include <mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
|
|
||||||
#include "tap_esc_common.h"
|
#include "tap_esc_common.h"
|
||||||
|
|
||||||
@@ -677,7 +677,7 @@ int TAP_ESC::ioctl(cdev::file_t *filp, int cmd, unsigned long arg)
|
|||||||
unsigned buflen = strlen(buf);
|
unsigned buflen = strlen(buf);
|
||||||
|
|
||||||
if (_mixers == nullptr) {
|
if (_mixers == nullptr) {
|
||||||
_mixers = new MixerGroup(control_callback_trampoline, (uintptr_t)this);
|
_mixers = new MixerGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mixers == nullptr) {
|
if (_mixers == nullptr) {
|
||||||
@@ -685,8 +685,7 @@ int TAP_ESC::ioctl(cdev::file_t *filp, int cmd, unsigned long arg)
|
|||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
ret = _mixers->load_from_buf(control_callback_trampoline, (uintptr_t)this, buf, buflen);
|
||||||
ret = _mixers->load_from_buf(buf, buflen);
|
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
PX4_DEBUG("mixer load failed with %d", ret);
|
PX4_DEBUG("mixer load failed with %d", ret);
|
||||||
|
|||||||
@@ -50,7 +50,6 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <parameters/param.h>
|
#include <parameters/param.h>
|
||||||
#include <lib/mixer/mixer.h>
|
|
||||||
#include <version/version.h>
|
#include <version/version.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
#include <arch/chip/chip.h>
|
#include <arch/chip/chip.h>
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
#include <mathlib/mathlib.h>
|
#include <mathlib/mathlib.h>
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <parameters/param.h>
|
#include <parameters/param.h>
|
||||||
#include <lib/mixer/mixer.h>
|
|
||||||
#include <version/version.h>
|
#include <version/version.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
#include <arch/chip/chip.h>
|
#include <arch/chip/chip.h>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <parameters/param.h>
|
#include <parameters/param.h>
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <version/version.h>
|
#include <version/version.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
#include <arch/chip/chip.h>
|
#include <arch/chip/chip.h>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <parameters/param.h>
|
#include <parameters/param.h>
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <version/version.h>
|
#include <version/version.h>
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
#include <nuttx/board.h>
|
#include <nuttx/board.h>
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
* Helicopter mixers.
|
* Helicopter mixers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mixer.h"
|
|
||||||
|
|
||||||
#include "HelicopterMixer.hpp"
|
#include "HelicopterMixer.hpp"
|
||||||
|
|
||||||
#include <mathlib/mathlib.h>
|
#include <mathlib/mathlib.h>
|
||||||
@@ -52,9 +50,9 @@
|
|||||||
|
|
||||||
using math::constrain;
|
using math::constrain;
|
||||||
|
|
||||||
HelicopterMixer::HelicopterMixer(ControlCallback control_cb, uintptr_t cb_handle, mixer_heli_s *mixer_info) :
|
HelicopterMixer::HelicopterMixer(ControlCallback control_cb, uintptr_t cb_handle, mixer_heli_s mixer_info) :
|
||||||
Mixer(control_cb, cb_handle),
|
Mixer(control_cb, cb_handle),
|
||||||
_mixer_info(*mixer_info)
|
_mixer_info(mixer_info)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,10 +180,7 @@ HelicopterMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handl
|
|||||||
|
|
||||||
debug("remaining in buf: %d, first char: %c", buflen, buf[0]);
|
debug("remaining in buf: %d, first char: %c", buflen, buf[0]);
|
||||||
|
|
||||||
HelicopterMixer *hm = new HelicopterMixer(
|
HelicopterMixer *hm = new HelicopterMixer(control_cb, cb_handle, mixer_info);
|
||||||
control_cb,
|
|
||||||
cb_handle,
|
|
||||||
&mixer_info);
|
|
||||||
|
|
||||||
if (hm != nullptr) {
|
if (hm != nullptr) {
|
||||||
debug("loaded heli mixer with %d swash plate input(s)", mixer_info.control_count);
|
debug("loaded heli mixer with %d swash plate input(s)", mixer_info.control_count);
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Mixer.hpp"
|
||||||
|
|
||||||
/** helicopter swash servo mixer */
|
/** helicopter swash servo mixer */
|
||||||
struct mixer_heli_servo_s {
|
struct mixer_heli_servo_s {
|
||||||
float angle;
|
float angle;
|
||||||
@@ -50,7 +52,7 @@ struct mixer_heli_s {
|
|||||||
uint8_t control_count; /**< number of inputs */
|
uint8_t control_count; /**< number of inputs */
|
||||||
float throttle_curve[HELI_CURVES_NR_POINTS];
|
float throttle_curve[HELI_CURVES_NR_POINTS];
|
||||||
float pitch_curve[HELI_CURVES_NR_POINTS];
|
float pitch_curve[HELI_CURVES_NR_POINTS];
|
||||||
struct mixer_heli_servo_s servos[4]; /**< up to four inputs */
|
mixer_heli_servo_s servos[4]; /**< up to four inputs */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,7 +71,7 @@ public:
|
|||||||
* @param cb_handle Passed to control_cb.
|
* @param cb_handle Passed to control_cb.
|
||||||
* @param mixer_info Pointer to heli mixer configuration
|
* @param mixer_info Pointer to heli mixer configuration
|
||||||
*/
|
*/
|
||||||
HelicopterMixer(ControlCallback control_cb, uintptr_t cb_handle, mixer_heli_s *mixer_info);
|
HelicopterMixer(ControlCallback control_cb, uintptr_t cb_handle, mixer_heli_s mixer_info);
|
||||||
virtual ~HelicopterMixer() = default;
|
virtual ~HelicopterMixer() = default;
|
||||||
|
|
||||||
// no copy, assignment, move, move assignment
|
// no copy, assignment, move, move assignment
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
* Programmable multi-channel mixer library.
|
* Programmable multi-channel mixer library.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mixer.h"
|
|
||||||
|
|
||||||
#include "Mixer.hpp"
|
#include "Mixer.hpp"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -48,12 +46,6 @@
|
|||||||
#define debug(fmt, args...) do { } while(0)
|
#define debug(fmt, args...) do { } while(0)
|
||||||
//#define debug(fmt, args...) do { printf("[mixer] " fmt "\n", ##args); } while(0)
|
//#define debug(fmt, args...) do { printf("[mixer] " fmt "\n", ##args); } while(0)
|
||||||
|
|
||||||
Mixer::Mixer(ControlCallback control_cb, uintptr_t cb_handle) :
|
|
||||||
_control_cb(control_cb),
|
|
||||||
_cb_handle(cb_handle)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
float
|
||||||
Mixer::get_control(uint8_t group, uint8_t index)
|
Mixer::get_control(uint8_t group, uint8_t index)
|
||||||
{
|
{
|
||||||
|
|||||||
+96
-9
@@ -31,16 +31,102 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file Mixer.hpp
|
||||||
|
*
|
||||||
|
* Generic, programmable, procedural control signal mixers.
|
||||||
|
*
|
||||||
|
* This library implements a generic mixer interface that can be used
|
||||||
|
* by any driver or subsytem that wants to combine several control signals
|
||||||
|
* into a single output.
|
||||||
|
*
|
||||||
|
* Terminology
|
||||||
|
* ===========
|
||||||
|
*
|
||||||
|
* control value
|
||||||
|
* A mixer input value, typically provided by some controlling
|
||||||
|
* component of the system.
|
||||||
|
*
|
||||||
|
* control group
|
||||||
|
* A collection of controls provided by a single controlling component.
|
||||||
|
*
|
||||||
|
* actuator
|
||||||
|
* The mixer output value.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Mixing basics
|
||||||
|
* =============
|
||||||
|
*
|
||||||
|
* An actuator derives its value from the combination of one or more
|
||||||
|
* control values. Each of the control values is scaled according to
|
||||||
|
* the actuator's configuration and then combined to produce the
|
||||||
|
* actuator value, which may then be further scaled to suit the specific
|
||||||
|
* output type.
|
||||||
|
*
|
||||||
|
* Internally, all scaling is performed using floating point values.
|
||||||
|
* Inputs and outputs are clamped to the range -1.0 to 1.0.
|
||||||
|
*
|
||||||
|
* control control control
|
||||||
|
* | | |
|
||||||
|
* v v v
|
||||||
|
* scale scale scale
|
||||||
|
* | | |
|
||||||
|
* | v |
|
||||||
|
* +-------> mix <------+
|
||||||
|
* |
|
||||||
|
* scale
|
||||||
|
* |
|
||||||
|
* v
|
||||||
|
* out
|
||||||
|
*
|
||||||
|
* Scaling
|
||||||
|
* -------
|
||||||
|
*
|
||||||
|
* Each scaler allows the input value to be scaled independently for
|
||||||
|
* inputs greater/less than zero. An offset can be applied to the output,
|
||||||
|
* as well as lower and upper boundary constraints.
|
||||||
|
* Negative scaling factors cause the output to be inverted (negative input
|
||||||
|
* produces positive output).
|
||||||
|
*
|
||||||
|
* Scaler pseudocode:
|
||||||
|
*
|
||||||
|
* if (input < 0)
|
||||||
|
* output = (input * NEGATIVE_SCALE) + OFFSET
|
||||||
|
* else
|
||||||
|
* output = (input * POSITIVE_SCALE) + OFFSET
|
||||||
|
*
|
||||||
|
* if (output < LOWER_LIMIT)
|
||||||
|
* output = LOWER_LIMIT
|
||||||
|
* if (output > UPPER_LIMIT)
|
||||||
|
* output = UPPER_LIMIT
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Mixing
|
||||||
|
* ------
|
||||||
|
*
|
||||||
|
* Mixing behaviour varies based on the specific mixer class; each
|
||||||
|
* mixer class describes its behaviour in more detail.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Controls
|
||||||
|
* --------
|
||||||
|
*
|
||||||
|
* The precise assignment of controls may vary depending on the
|
||||||
|
* application, but the following assignments should be used
|
||||||
|
* when appropriate. Some mixer classes have specific assumptions
|
||||||
|
* about the assignment of controls.
|
||||||
|
*
|
||||||
|
* control | standard meaning
|
||||||
|
* --------+-----------------------
|
||||||
|
* 0 | roll
|
||||||
|
* 1 | pitch
|
||||||
|
* 2 | yaw
|
||||||
|
* 3 | primary thrust
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/** simple channel scaler */
|
#include <mathlib/mathlib.h>
|
||||||
struct mixer_scaler_s {
|
|
||||||
float negative_scale;
|
|
||||||
float positive_scale;
|
|
||||||
float offset;
|
|
||||||
float min_output;
|
|
||||||
float max_output;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class defining a mixer mixing zero or more inputs to
|
* Abstract class defining a mixer mixing zero or more inputs to
|
||||||
@@ -74,7 +160,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @param control_cb Callback invoked when reading controls.
|
* @param control_cb Callback invoked when reading controls.
|
||||||
*/
|
*/
|
||||||
Mixer(ControlCallback control_cb, uintptr_t cb_handle);
|
Mixer(ControlCallback control_cb, uintptr_t cb_handle) : _control_cb(control_cb), _cb_handle(cb_handle) {}
|
||||||
virtual ~Mixer() = default;
|
virtual ~Mixer() = default;
|
||||||
|
|
||||||
// no copy, assignment, move, move assignment
|
// no copy, assignment, move, move assignment
|
||||||
@@ -146,6 +232,7 @@ public:
|
|||||||
virtual unsigned get_multirotor_count() { return 0; }
|
virtual unsigned get_multirotor_count() { return 0; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** client-supplied callback used when fetching control values */
|
/** client-supplied callback used when fetching control values */
|
||||||
ControlCallback _control_cb;
|
ControlCallback _control_cb;
|
||||||
uintptr_t _cb_handle;
|
uintptr_t _cb_handle;
|
||||||
|
|||||||
@@ -37,39 +37,19 @@
|
|||||||
* Mixer collection.
|
* Mixer collection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <px4_platform_common/px4_config.h>
|
#include "MixerGroup.hpp"
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "mixer.h"
|
|
||||||
|
|
||||||
#include "MixerGroup.hpp"
|
#include "MixerGroup.hpp"
|
||||||
|
#include "NullMixer.hpp"
|
||||||
|
#include "SimpleMixer.hpp"
|
||||||
|
#include "MultirotorMixer.hpp"
|
||||||
|
#include "HelicopterMixer.hpp"
|
||||||
|
|
||||||
#define debug(fmt, args...) do { } while(0)
|
#define debug(fmt, args...) do { } while(0)
|
||||||
//#define debug(fmt, args...) do { printf("[mixer] " fmt "\n", ##args); } while(0)
|
//#define debug(fmt, args...) do { printf("[mixer] " fmt "\n", ##args); } while(0)
|
||||||
//#include <debug.h>
|
//#include <debug.h>
|
||||||
//#define debug(fmt, args...) syslog(fmt "\n", ##args)
|
//#define debug(fmt, args...) syslog(fmt "\n", ##args)
|
||||||
|
|
||||||
MixerGroup::MixerGroup(ControlCallback control_cb, uintptr_t cb_handle) :
|
|
||||||
Mixer(control_cb, cb_handle)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MixerGroup::~MixerGroup()
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerGroup::add_mixer(Mixer *mixer)
|
MixerGroup::add_mixer(Mixer *mixer)
|
||||||
{
|
{
|
||||||
@@ -187,7 +167,7 @@ MixerGroup::set_thrust_factor(float val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerGroup::set_airmode(Airmode airmode)
|
MixerGroup::set_airmode(Mixer::Airmode airmode)
|
||||||
{
|
{
|
||||||
Mixer *mixer = _first;
|
Mixer *mixer = _first;
|
||||||
|
|
||||||
@@ -255,7 +235,7 @@ MixerGroup::groups_required(uint32_t &groups)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
MixerGroup::load_from_buf(const char *buf, unsigned &buflen)
|
MixerGroup::load_from_buf(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf, unsigned &buflen)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
const char *end = buf + buflen;
|
const char *end = buf + buflen;
|
||||||
@@ -278,15 +258,15 @@ MixerGroup::load_from_buf(const char *buf, unsigned &buflen)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
m = SimpleMixer::from_text(_control_cb, _cb_handle, p, resid);
|
m = SimpleMixer::from_text(control_cb, cb_handle, p, resid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
m = MultirotorMixer::from_text(_control_cb, _cb_handle, p, resid);
|
m = MultirotorMixer::from_text(control_cb, cb_handle, p, resid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'H':
|
case 'H':
|
||||||
m = HelicopterMixer::from_text(_control_cb, _cb_handle, p, resid);
|
m = HelicopterMixer::from_text(control_cb, cb_handle, p, resid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -33,15 +33,21 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Mixer.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Group of mixers, built up from single mixers and processed
|
* Group of mixers, built up from single mixers and processed
|
||||||
* in order when mixing.
|
* in order when mixing.
|
||||||
*/
|
*/
|
||||||
class MixerGroup : public Mixer
|
class MixerGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MixerGroup(ControlCallback control_cb, uintptr_t cb_handle);
|
MixerGroup() = default;
|
||||||
virtual ~MixerGroup();
|
|
||||||
|
~MixerGroup()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
// no copy, assignment, move, move assignment
|
// no copy, assignment, move, move assignment
|
||||||
MixerGroup(const MixerGroup &) = delete;
|
MixerGroup(const MixerGroup &) = delete;
|
||||||
@@ -49,9 +55,11 @@ public:
|
|||||||
MixerGroup(MixerGroup &&) = delete;
|
MixerGroup(MixerGroup &&) = delete;
|
||||||
MixerGroup &operator=(MixerGroup &&) = delete;
|
MixerGroup &operator=(MixerGroup &&) = delete;
|
||||||
|
|
||||||
unsigned mix(float *outputs, unsigned space) override;
|
unsigned mix(float *outputs, unsigned space);
|
||||||
uint16_t get_saturation_status() override;
|
|
||||||
void groups_required(uint32_t &groups) override;
|
uint16_t get_saturation_status();
|
||||||
|
|
||||||
|
void groups_required(uint32_t &groups);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a mixer to the group.
|
* Add a mixer to the group.
|
||||||
@@ -125,7 +133,7 @@ public:
|
|||||||
* bytes as they are consumed.
|
* bytes as they are consumed.
|
||||||
* @return Zero on successful load, nonzero otherwise.
|
* @return Zero on successful load, nonzero otherwise.
|
||||||
*/
|
*/
|
||||||
int load_from_buf(const char *buf, unsigned &buflen);
|
int load_from_buf(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf, unsigned &buflen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update slew rate parameter. This tells instances of the class MultirotorMixer
|
* @brief Update slew rate parameter. This tells instances of the class MultirotorMixer
|
||||||
@@ -137,25 +145,25 @@ public:
|
|||||||
* @param[in] delta_out_max Maximum delta output.
|
* @param[in] delta_out_max Maximum delta output.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void set_max_delta_out_once(float delta_out_max) override;
|
void set_max_delta_out_once(float delta_out_max);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoke the set_offset method of each mixer in the group
|
* Invoke the set_offset method of each mixer in the group
|
||||||
* for each value in page r_page_servo_control_trim
|
* for each value in page r_page_servo_control_trim
|
||||||
*/
|
*/
|
||||||
unsigned set_trims(int16_t *v, unsigned n);
|
unsigned set_trims(int16_t *v, unsigned n);
|
||||||
unsigned get_trims(int16_t *values);
|
unsigned get_trims(int16_t *values);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the thrust factor used to calculate mapping from desired thrust to motor control signal output.
|
* @brief Sets the thrust factor used to calculate mapping from desired thrust to motor control signal output.
|
||||||
*
|
*
|
||||||
* @param[in] val The value
|
* @param[in] val The value
|
||||||
*/
|
*/
|
||||||
void set_thrust_factor(float val) override;
|
void set_thrust_factor(float val);
|
||||||
|
|
||||||
void set_airmode(Airmode airmode) override;
|
void set_airmode(Mixer::Airmode airmode);
|
||||||
|
|
||||||
unsigned get_multirotor_count() override;
|
unsigned get_multirotor_count();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mixer *_first{nullptr}; /**< linked list of mixers */
|
Mixer *_first{nullptr}; /**< linked list of mixers */
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
* Multi-rotor mixers.
|
* Multi-rotor mixers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mixer.h"
|
#include "MultirotorMixer.hpp"
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -45,8 +45,6 @@
|
|||||||
|
|
||||||
#include <mathlib/mathlib.h>
|
#include <mathlib/mathlib.h>
|
||||||
|
|
||||||
#include "MultirotorMixer.hpp"
|
|
||||||
|
|
||||||
#ifdef MIXER_MULTIROTOR_USE_MOCK_GEOMETRY
|
#ifdef MIXER_MULTIROTOR_USE_MOCK_GEOMETRY
|
||||||
enum class MultirotorGeometry : MultirotorGeometryUnderlyingType {
|
enum class MultirotorGeometry : MultirotorGeometryUnderlyingType {
|
||||||
QUAD_X,
|
QUAD_X,
|
||||||
@@ -81,28 +79,18 @@ const char *_config_key[] = {"4x"};
|
|||||||
//#include <debug.h>
|
//#include <debug.h>
|
||||||
//#define debug(fmt, args...) syslog(fmt "\n", ##args)
|
//#define debug(fmt, args...) syslog(fmt "\n", ##args)
|
||||||
|
|
||||||
MultirotorMixer::MultirotorMixer(ControlCallback control_cb,
|
MultirotorMixer::MultirotorMixer(ControlCallback control_cb, uintptr_t cb_handle, MultirotorGeometry geometry,
|
||||||
uintptr_t cb_handle,
|
float roll_scale, float pitch_scale, float yaw_scale, float idle_speed) :
|
||||||
MultirotorGeometry geometry,
|
MultirotorMixer(control_cb, cb_handle, _config_index[(int)geometry], _config_rotor_count[(int)geometry])
|
||||||
float roll_scale,
|
|
||||||
float pitch_scale,
|
|
||||||
float yaw_scale,
|
|
||||||
float idle_speed) :
|
|
||||||
Mixer(control_cb, cb_handle),
|
|
||||||
_roll_scale(roll_scale),
|
|
||||||
_pitch_scale(pitch_scale),
|
|
||||||
_yaw_scale(yaw_scale),
|
|
||||||
_idle_speed(-1.0f + idle_speed * 2.0f), /* shift to output range here to avoid runtime calculation */
|
|
||||||
_rotor_count(_config_rotor_count[(MultirotorGeometryUnderlyingType)geometry]),
|
|
||||||
_rotors(_config_index[(MultirotorGeometryUnderlyingType)geometry]),
|
|
||||||
_outputs_prev(new float[_rotor_count]),
|
|
||||||
_tmp_array(new float[_rotor_count])
|
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < _rotor_count; ++i) {
|
_roll_scale = roll_scale;
|
||||||
_outputs_prev[i] = _idle_speed;
|
_pitch_scale = pitch_scale;
|
||||||
}
|
_yaw_scale = yaw_scale;
|
||||||
|
_idle_speed = -1.0f + idle_speed * 2.0f; /* shift to output range here to avoid runtime calculation */
|
||||||
}
|
}
|
||||||
MultirotorMixer::MultirotorMixer(ControlCallback control_cb, uintptr_t cb_handle, Rotor *rotors, unsigned rotor_count) :
|
|
||||||
|
MultirotorMixer::MultirotorMixer(ControlCallback control_cb, uintptr_t cb_handle, const Rotor *rotors,
|
||||||
|
unsigned rotor_count) :
|
||||||
Mixer(control_cb, cb_handle),
|
Mixer(control_cb, cb_handle),
|
||||||
_rotor_count(rotor_count),
|
_rotor_count(rotor_count),
|
||||||
_rotors(rotors),
|
_rotors(rotors),
|
||||||
@@ -423,7 +411,6 @@ MultirotorMixer::mix(float *outputs, unsigned space)
|
|||||||
outputs[i] = _outputs_prev[i] - _delta_out_max;
|
outputs[i] = _outputs_prev[i] - _delta_out_max;
|
||||||
clipping_low_roll_pitch = true;
|
clipping_low_roll_pitch = true;
|
||||||
clipping_low_yaw = true;
|
clipping_low_yaw = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Mixer.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported multirotor geometries.
|
* Supported multirotor geometries.
|
||||||
*
|
*
|
||||||
@@ -77,13 +79,8 @@ public:
|
|||||||
* tuned to ensure that rotors never stall at the
|
* tuned to ensure that rotors never stall at the
|
||||||
* low end of their control range.
|
* low end of their control range.
|
||||||
*/
|
*/
|
||||||
MultirotorMixer(ControlCallback control_cb,
|
MultirotorMixer(ControlCallback control_cb, uintptr_t cb_handle, MultirotorGeometry geometry,
|
||||||
uintptr_t cb_handle,
|
float roll_scale, float pitch_scale, float yaw_scale, float idle_speed);
|
||||||
MultirotorGeometry geometry,
|
|
||||||
float roll_scale,
|
|
||||||
float pitch_scale,
|
|
||||||
float yaw_scale,
|
|
||||||
float idle_speed);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor (for testing).
|
* Constructor (for testing).
|
||||||
@@ -93,7 +90,7 @@ public:
|
|||||||
* @param rotors control allocation matrix
|
* @param rotors control allocation matrix
|
||||||
* @param rotor_count length of rotors array (= number of motors)
|
* @param rotor_count length of rotors array (= number of motors)
|
||||||
*/
|
*/
|
||||||
MultirotorMixer(ControlCallback control_cb, uintptr_t cb_handle, Rotor *rotors, unsigned rotor_count);
|
MultirotorMixer(ControlCallback control_cb, uintptr_t cb_handle, const Rotor *rotors, unsigned rotor_count);
|
||||||
virtual ~MultirotorMixer();
|
virtual ~MultirotorMixer();
|
||||||
|
|
||||||
// no copy, assignment, move, move assignment
|
// no copy, assignment, move, move assignment
|
||||||
|
|||||||
@@ -31,17 +31,12 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "mixer.h"
|
#include "NullMixer.hpp"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
NullMixer::NullMixer() :
|
|
||||||
Mixer(nullptr, 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
NullMixer::mix(float *outputs, unsigned space)
|
NullMixer::mix(float *outputs, unsigned space)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Mixer.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Null mixer; returns zero.
|
* Null mixer; returns zero.
|
||||||
*
|
*
|
||||||
@@ -41,7 +43,7 @@
|
|||||||
class NullMixer : public Mixer
|
class NullMixer : public Mixer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NullMixer();
|
NullMixer() : Mixer(nullptr, 0) {}
|
||||||
virtual ~NullMixer() = default;
|
virtual ~NullMixer() = default;
|
||||||
|
|
||||||
// no copy, assignment, move, move assignment
|
// no copy, assignment, move, move assignment
|
||||||
@@ -65,9 +67,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
static NullMixer *from_text(const char *buf, unsigned &buflen);
|
static NullMixer *from_text(const char *buf, unsigned &buflen);
|
||||||
|
|
||||||
unsigned mix(float *outputs, unsigned space) override;
|
unsigned mix(float *outputs, unsigned space) override;
|
||||||
|
|
||||||
unsigned set_trim(float trim) override { return 1; }
|
unsigned set_trim(float trim) override { return 1; }
|
||||||
unsigned get_trim(float *trim) override { return 1; }
|
unsigned get_trim(float *trim) override { return 1; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,7 +37,8 @@
|
|||||||
* Simple summing mixer.
|
* Simple summing mixer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mixer.h"
|
#include "SimpleMixer.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -190,7 +191,6 @@ SimpleMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, c
|
|||||||
next_tag = findnexttag(end - buflen, buflen);
|
next_tag = findnexttag(end - buflen, buflen);
|
||||||
|
|
||||||
if (next_tag == 'S') {
|
if (next_tag == 'S') {
|
||||||
|
|
||||||
/* No output scalers specified. Use default values.
|
/* No output scalers specified. Use default values.
|
||||||
* Corresponds to:
|
* Corresponds to:
|
||||||
* O: 10000 10000 0 -10000 10000
|
* O: 10000 10000 0 -10000 10000
|
||||||
@@ -202,7 +202,6 @@ SimpleMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, c
|
|||||||
mixinfo->output_scaler.max_output = 1.0f;
|
mixinfo->output_scaler.max_output = 1.0f;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (parse_output_scaler(end - buflen, buflen, mixinfo->output_scaler)) {
|
if (parse_output_scaler(end - buflen, buflen, mixinfo->output_scaler)) {
|
||||||
debug("simple mixer parser failed parsing out scaler tag, ret: '%s'", buf);
|
debug("simple mixer parser failed parsing out scaler tag, ret: '%s'", buf);
|
||||||
goto out;
|
goto out;
|
||||||
@@ -217,7 +216,6 @@ SimpleMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, c
|
|||||||
debug("simple mixer parser failed parsing ctrl scaler tag, ret: '%s'", buf);
|
debug("simple mixer parser failed parsing ctrl scaler tag, ret: '%s'", buf);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sm = new SimpleMixer(control_cb, cb_handle, mixinfo);
|
sm = new SimpleMixer(control_cb, cb_handle, mixinfo);
|
||||||
|
|||||||
@@ -33,11 +33,22 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Mixer.hpp"
|
||||||
|
|
||||||
|
/** simple channel scaler */
|
||||||
|
struct mixer_scaler_s {
|
||||||
|
float negative_scale{1.0f};
|
||||||
|
float positive_scale{1.0f};
|
||||||
|
float offset{0.0f};
|
||||||
|
float min_output{-1.0f};
|
||||||
|
float max_output{1.0f};
|
||||||
|
};
|
||||||
|
|
||||||
/** mixer input */
|
/** mixer input */
|
||||||
struct mixer_control_s {
|
struct mixer_control_s {
|
||||||
uint8_t control_group; /**< group from which the input reads */
|
uint8_t control_group; /**< group from which the input reads */
|
||||||
uint8_t control_index; /**< index within the control group */
|
uint8_t control_index; /**< index within the control group */
|
||||||
struct mixer_scaler_s scaler; /**< scaling applied to the input before use */
|
mixer_scaler_s scaler; /**< scaling applied to the input before use */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MIXER_SIMPLE_SIZE(_icount) (sizeof(struct mixer_simple_s) + (_icount) * sizeof(struct mixer_control_s))
|
#define MIXER_SIMPLE_SIZE(_icount) (sizeof(struct mixer_simple_s) + (_icount) * sizeof(struct mixer_control_s))
|
||||||
@@ -45,8 +56,8 @@ struct mixer_control_s {
|
|||||||
/** simple mixer */
|
/** simple mixer */
|
||||||
struct mixer_simple_s {
|
struct mixer_simple_s {
|
||||||
uint8_t control_count; /**< number of inputs */
|
uint8_t control_count; /**< number of inputs */
|
||||||
struct mixer_scaler_s output_scaler; /**< scaling for the output */
|
mixer_scaler_s output_scaler; /**< scaling for the output */
|
||||||
struct mixer_control_s controls[0]; /**< actual size of the array is set by control_count */
|
mixer_control_s controls[]; /**< actual size of the array is set by control_count */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,6 +143,6 @@ private:
|
|||||||
static int parse_control_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler, uint8_t &control_group,
|
static int parse_control_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler, uint8_t &control_group,
|
||||||
uint8_t &control_index);
|
uint8_t &control_index);
|
||||||
|
|
||||||
mixer_simple_s *_pinfo{nullptr};
|
mixer_simple_s *_pinfo;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,8 +45,8 @@
|
|||||||
|
|
||||||
int load_mixer_file(const char *fname, char *buf, unsigned maxlen)
|
int load_mixer_file(const char *fname, char *buf, unsigned maxlen)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char line[120];
|
char line[120];
|
||||||
|
|
||||||
/* open the mixer definition file */
|
/* open the mixer definition file */
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012 PX4 Development Team. 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, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in
|
|
||||||
* the documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
|
||||||
* used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
||||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file mixer.h
|
|
||||||
*
|
|
||||||
* Generic, programmable, procedural control signal mixers.
|
|
||||||
*
|
|
||||||
* This library implements a generic mixer interface that can be used
|
|
||||||
* by any driver or subsytem that wants to combine several control signals
|
|
||||||
* into a single output.
|
|
||||||
*
|
|
||||||
* Terminology
|
|
||||||
* ===========
|
|
||||||
*
|
|
||||||
* control value
|
|
||||||
* A mixer input value, typically provided by some controlling
|
|
||||||
* component of the system.
|
|
||||||
*
|
|
||||||
* control group
|
|
||||||
* A collection of controls provided by a single controlling component.
|
|
||||||
*
|
|
||||||
* actuator
|
|
||||||
* The mixer output value.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Mixing basics
|
|
||||||
* =============
|
|
||||||
*
|
|
||||||
* An actuator derives its value from the combination of one or more
|
|
||||||
* control values. Each of the control values is scaled according to
|
|
||||||
* the actuator's configuration and then combined to produce the
|
|
||||||
* actuator value, which may then be further scaled to suit the specific
|
|
||||||
* output type.
|
|
||||||
*
|
|
||||||
* Internally, all scaling is performed using floating point values.
|
|
||||||
* Inputs and outputs are clamped to the range -1.0 to 1.0.
|
|
||||||
*
|
|
||||||
* control control control
|
|
||||||
* | | |
|
|
||||||
* v v v
|
|
||||||
* scale scale scale
|
|
||||||
* | | |
|
|
||||||
* | v |
|
|
||||||
* +-------> mix <------+
|
|
||||||
* |
|
|
||||||
* scale
|
|
||||||
* |
|
|
||||||
* v
|
|
||||||
* out
|
|
||||||
*
|
|
||||||
* Scaling
|
|
||||||
* -------
|
|
||||||
*
|
|
||||||
* Each scaler allows the input value to be scaled independently for
|
|
||||||
* inputs greater/less than zero. An offset can be applied to the output,
|
|
||||||
* as well as lower and upper boundary constraints.
|
|
||||||
* Negative scaling factors cause the output to be inverted (negative input
|
|
||||||
* produces positive output).
|
|
||||||
*
|
|
||||||
* Scaler pseudocode:
|
|
||||||
*
|
|
||||||
* if (input < 0)
|
|
||||||
* output = (input * NEGATIVE_SCALE) + OFFSET
|
|
||||||
* else
|
|
||||||
* output = (input * POSITIVE_SCALE) + OFFSET
|
|
||||||
*
|
|
||||||
* if (output < LOWER_LIMIT)
|
|
||||||
* output = LOWER_LIMIT
|
|
||||||
* if (output > UPPER_LIMIT)
|
|
||||||
* output = UPPER_LIMIT
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Mixing
|
|
||||||
* ------
|
|
||||||
*
|
|
||||||
* Mixing behaviour varies based on the specific mixer class; each
|
|
||||||
* mixer class describes its behaviour in more detail.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Controls
|
|
||||||
* --------
|
|
||||||
*
|
|
||||||
* The precise assignment of controls may vary depending on the
|
|
||||||
* application, but the following assignments should be used
|
|
||||||
* when appropriate. Some mixer classes have specific assumptions
|
|
||||||
* about the assignment of controls.
|
|
||||||
*
|
|
||||||
* control | standard meaning
|
|
||||||
* --------+-----------------------
|
|
||||||
* 0 | roll
|
|
||||||
* 1 | pitch
|
|
||||||
* 2 | yaw
|
|
||||||
* 3 | primary thrust
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <lib/mathlib/mathlib.h>
|
|
||||||
|
|
||||||
#include "Mixer.hpp"
|
|
||||||
#include "MixerGroup.hpp"
|
|
||||||
#include "NullMixer.hpp"
|
|
||||||
#include "SimpleMixer.hpp"
|
|
||||||
#include "MultirotorMixer.hpp"
|
|
||||||
#include "HelicopterMixer.hpp"
|
|
||||||
@@ -36,7 +36,8 @@
|
|||||||
* via file or stdin and compares the mixer output against expected values.
|
* via file or stdin and compares the mixer output against expected values.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mixer.h"
|
#include "MultirotorMixer.hpp"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#include "mixer_module.hpp"
|
#include "mixer_module.hpp"
|
||||||
|
|
||||||
|
#include <lib/mixer/MultirotorMixer.hpp>
|
||||||
|
|
||||||
#include <uORB/PublicationQueued.hpp>
|
#include <uORB/PublicationQueued.hpp>
|
||||||
#include <px4_platform_common/log.h>
|
#include <px4_platform_common/log.h>
|
||||||
|
|
||||||
@@ -543,7 +545,7 @@ void MixingOutput::resetMixer()
|
|||||||
int MixingOutput::loadMixer(const char *buf, unsigned len)
|
int MixingOutput::loadMixer(const char *buf, unsigned len)
|
||||||
{
|
{
|
||||||
if (_mixers == nullptr) {
|
if (_mixers == nullptr) {
|
||||||
_mixers = new MixerGroup(controlCallback, (uintptr_t)this);
|
_mixers = new MixerGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mixers == nullptr) {
|
if (_mixers == nullptr) {
|
||||||
@@ -551,7 +553,7 @@ int MixingOutput::loadMixer(const char *buf, unsigned len)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = _mixers->load_from_buf(buf, len);
|
int ret = _mixers->load_from_buf(controlCallback, (uintptr_t)this, buf, len);
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
PX4_ERR("mixer load failed with %d", ret);
|
PX4_ERR("mixer load failed with %d", ret);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
#include <board_config.h>
|
#include <board_config.h>
|
||||||
#include <drivers/drv_pwm_output.h>
|
#include <drivers/drv_pwm_output.h>
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <lib/perf/perf_counter.h>
|
#include <lib/perf/perf_counter.h>
|
||||||
#include <lib/output_limit/output_limit.h>
|
#include <lib/output_limit/output_limit.h>
|
||||||
#include <px4_platform_common/atomic.h>
|
#include <px4_platform_common/atomic.h>
|
||||||
@@ -52,7 +52,6 @@
|
|||||||
#include <uORB/topics/parameter_update.h>
|
#include <uORB/topics/parameter_update.h>
|
||||||
#include <uORB/topics/test_motor.h>
|
#include <uORB/topics/test_motor.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class OutputModuleInterface
|
* @class OutputModuleInterface
|
||||||
* Base class for an output module.
|
* Base class for an output module.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/Mixer.hpp>
|
||||||
#include <matrix/matrix/math.hpp>
|
#include <matrix/matrix/math.hpp>
|
||||||
#include <perf/perf_counter.h>
|
#include <perf/perf_counter.h>
|
||||||
#include <px4_platform_common/px4_config.h>
|
#include <px4_platform_common/px4_config.h>
|
||||||
|
|||||||
@@ -37,7 +37,6 @@
|
|||||||
|
|
||||||
#include <lib/mathlib/math/filter/LowPassFilter2pVector3f.hpp>
|
#include <lib/mathlib/math/filter/LowPassFilter2pVector3f.hpp>
|
||||||
#include <lib/matrix/matrix/math.hpp>
|
#include <lib/matrix/matrix/math.hpp>
|
||||||
#include <lib/mixer/mixer.h>
|
|
||||||
#include <lib/perf/perf_counter.h>
|
#include <lib/perf/perf_counter.h>
|
||||||
#include <px4_platform_common/defines.h>
|
#include <px4_platform_common/defines.h>
|
||||||
#include <px4_platform_common/module.h>
|
#include <px4_platform_common/module.h>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
#include <matrix/matrix/math.hpp>
|
#include <matrix/matrix/math.hpp>
|
||||||
#include <mathlib/math/filter/LowPassFilter2pVector3f.hpp>
|
#include <mathlib/math/filter/LowPassFilter2pVector3f.hpp>
|
||||||
|
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/MultirotorMixer.hpp>
|
||||||
#include <uORB/topics/rate_ctrl_status.h>
|
#include <uORB/topics/rate_ctrl_status.h>
|
||||||
|
|
||||||
class RateControl
|
class RateControl
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
#include <drivers/drv_pwm_output.h>
|
#include <drivers/drv_pwm_output.h>
|
||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
|
|
||||||
#include <mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <output_limit/output_limit.h>
|
#include <output_limit/output_limit.h>
|
||||||
#include <rc/sbus.h>
|
#include <rc/sbus.h>
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ static volatile mixer_source source;
|
|||||||
static int mixer_callback(uintptr_t handle, uint8_t control_group, uint8_t control_index, float &control);
|
static int mixer_callback(uintptr_t handle, uint8_t control_group, uint8_t control_index, float &control);
|
||||||
static int mixer_mix_threadsafe(float *outputs, volatile uint16_t *limits);
|
static int mixer_mix_threadsafe(float *outputs, volatile uint16_t *limits);
|
||||||
|
|
||||||
static MixerGroup mixer_group(mixer_callback, 0);
|
static MixerGroup mixer_group;
|
||||||
|
|
||||||
int mixer_mix_threadsafe(float *outputs, volatile uint16_t *limits)
|
int mixer_mix_threadsafe(float *outputs, volatile uint16_t *limits)
|
||||||
{
|
{
|
||||||
@@ -114,7 +114,7 @@ int mixer_mix_threadsafe(float *outputs, volatile uint16_t *limits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mixer_tick(void)
|
mixer_tick()
|
||||||
{
|
{
|
||||||
/* check if the mixer got modified */
|
/* check if the mixer got modified */
|
||||||
mixer_handle_text_create_mixer();
|
mixer_handle_text_create_mixer();
|
||||||
@@ -540,7 +540,7 @@ mixer_handle_text_create_mixer()
|
|||||||
|
|
||||||
/* process the text buffer, adding new mixers as their descriptions can be parsed */
|
/* process the text buffer, adding new mixers as their descriptions can be parsed */
|
||||||
unsigned resid = mixer_text_length;
|
unsigned resid = mixer_text_length;
|
||||||
mixer_group.load_from_buf(&mixer_text[0], resid);
|
mixer_group.load_from_buf(mixer_callback, 0, &mixer_text[0], resid);
|
||||||
|
|
||||||
/* if anything was parsed */
|
/* if anything was parsed */
|
||||||
if (resid != mixer_text_length) {
|
if (resid != mixer_text_length) {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include <drivers/drv_mixer.h>
|
#include <drivers/drv_mixer.h>
|
||||||
#include <lib/mixer/mixer.h>
|
#include <lib/mixer/Mixer.hpp>
|
||||||
#include <lib/mixer/mixer_load.h>
|
#include <lib/mixer/mixer_load.h>
|
||||||
#include <uORB/topics/actuator_controls.h>
|
#include <uORB/topics/actuator_controls.h>
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,6 @@
|
|||||||
#include <ecl/geo_lookup/geo_mag_declination.h>
|
#include <ecl/geo_lookup/geo_mag_declination.h>
|
||||||
#include <px4iofirmware/px4io.h>
|
#include <px4iofirmware/px4io.h>
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <lib/mixer/mixer.h>
|
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -43,8 +43,8 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <px4_platform_common/px4_config.h>
|
#include <px4_platform_common/px4_config.h>
|
||||||
#include <mixer/mixer.h>
|
#include <lib/mixer/MixerGroup.hpp>
|
||||||
#include <mixer/mixer_load.h>
|
#include <lib/mixer/mixer_load.h>
|
||||||
#include <output_limit/output_limit.h>
|
#include <output_limit/output_limit.h>
|
||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
#include <drivers/drv_pwm_output.h>
|
#include <drivers/drv_pwm_output.h>
|
||||||
@@ -95,7 +95,7 @@ class MixerTest : public UnitTest
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool run_tests();
|
virtual bool run_tests();
|
||||||
MixerTest();
|
MixerTest() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mixerTest();
|
bool mixerTest();
|
||||||
@@ -112,11 +112,6 @@ private:
|
|||||||
MixerGroup mixer_group;
|
MixerGroup mixer_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
MixerTest::MixerTest() :
|
|
||||||
mixer_group(mixer_callback, 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MixerTest::run_tests()
|
bool MixerTest::run_tests()
|
||||||
{
|
{
|
||||||
ut_run_test(loadIOPass);
|
ut_run_test(loadIOPass);
|
||||||
@@ -251,11 +246,8 @@ bool MixerTest::load_mixer(const char *filename, unsigned expected_count, bool v
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MixerTest::load_mixer(const char *filename, const char *buf, unsigned loaded, unsigned expected_count,
|
bool MixerTest::load_mixer(const char *filename, const char *buf, unsigned loaded, unsigned expected_count,
|
||||||
const unsigned chunk_size,
|
const unsigned chunk_size, bool verbose)
|
||||||
bool verbose)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/* load the mixer in chunks, like
|
/* load the mixer in chunks, like
|
||||||
* in the case of a remote load,
|
* in the case of a remote load,
|
||||||
* e.g. on PX4IO.
|
* e.g. on PX4IO.
|
||||||
@@ -264,7 +256,7 @@ bool MixerTest::load_mixer(const char *filename, const char *buf, unsigned loade
|
|||||||
/* load at once test */
|
/* load at once test */
|
||||||
unsigned xx = loaded;
|
unsigned xx = loaded;
|
||||||
mixer_group.reset();
|
mixer_group.reset();
|
||||||
mixer_group.load_from_buf(&buf[0], xx);
|
mixer_group.load_from_buf(mixer_callback, 0, &buf[0], xx);
|
||||||
|
|
||||||
if (expected_count > 0) {
|
if (expected_count > 0) {
|
||||||
ut_compare("check number of mixers loaded", mixer_group.count(), expected_count);
|
ut_compare("check number of mixers loaded", mixer_group.count(), expected_count);
|
||||||
@@ -275,7 +267,7 @@ bool MixerTest::load_mixer(const char *filename, const char *buf, unsigned loade
|
|||||||
empty_buf[0] = ' ';
|
empty_buf[0] = ' ';
|
||||||
empty_buf[1] = '\0';
|
empty_buf[1] = '\0';
|
||||||
mixer_group.reset();
|
mixer_group.reset();
|
||||||
mixer_group.load_from_buf(&empty_buf[0], empty_load);
|
mixer_group.load_from_buf(mixer_callback, 0, &empty_buf[0], empty_load);
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PX4_INFO("empty buffer load: loaded %u mixers, used: %u", mixer_group.count(), empty_load);
|
PX4_INFO("empty buffer load: loaded %u mixers, used: %u", mixer_group.count(), empty_load);
|
||||||
@@ -310,7 +302,7 @@ bool MixerTest::load_mixer(const char *filename, const char *buf, unsigned loade
|
|||||||
|
|
||||||
/* process the text buffer, adding new mixers as their descriptions can be parsed */
|
/* process the text buffer, adding new mixers as their descriptions can be parsed */
|
||||||
resid = mixer_text_length;
|
resid = mixer_text_length;
|
||||||
mixer_group.load_from_buf(&mixer_text[0], resid);
|
mixer_group.load_from_buf(mixer_callback, 0, &mixer_text[0], resid);
|
||||||
|
|
||||||
/* if anything was parsed */
|
/* if anything was parsed */
|
||||||
if (resid != mixer_text_length) {
|
if (resid != mixer_text_length) {
|
||||||
|
|||||||
Reference in New Issue
Block a user