Files
PX4-Autopilot/src/lib/mixer/test_mixer_multirotor.cpp
T
2019-04-07 16:12:17 -04:00

168 lines
4.6 KiB
C++

/****************************************************************************
*
* Copyright (c) 2018 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.
*
****************************************************************************/
/**
* testing binary that runs the multirotor mixer through test cases given
* via file or stdin and compares the mixer output against expected values.
*/
#include "mixer.h"
#include <cstdio>
#include <cmath>
static const unsigned output_max = 16;
static float actuator_controls[output_max] {};
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)
{
control = actuator_controls[control_index];
return 0;
}
int main(int argc, char *argv[])
{
FILE *file_in = stdin;
if (argc > 1) {
file_in = fopen(argv[1], "r");
}
unsigned rotor_count = 0;
MultirotorMixer::Rotor rotors[output_max];
float actuator_outputs[output_max];
// read airmode
int airmode;
fscanf(file_in, "%i", &airmode);
// read the motor count & control allocation matrix
fscanf(file_in, "%i", &rotor_count);
if (rotor_count > output_max) {
return -1;
}
for (unsigned i = 0; i < rotor_count; ++i) {
fscanf(file_in, "%f %f %f %f", &rotors[i].roll_scale, &rotors[i].pitch_scale,
&rotors[i].yaw_scale, &rotors[i].thrust_scale);
}
MultirotorMixer mixer(mixer_callback, 0, rotors, rotor_count);
mixer.set_airmode((Mixer::Airmode)airmode);
int test_counter = 0;
int num_failed = 0;
while (!feof(file_in)) {
// read actuator controls
unsigned count = 0;
while (count < 4 && fscanf(file_in, "%f", &actuator_controls[count]) == 1) {
++count;
}
if (count < 4) {
break;
}
// do the mixing
if (mixer.mix(actuator_outputs, output_max) != rotor_count) {
return -1;
}
// read expected outputs
count = 0;
float expected_output[output_max];
bool failed = false;
while (count < rotor_count && fscanf(file_in, "%f", &expected_output[count]) == 1) {
if (fabsf(expected_output[count] - actuator_outputs[count]) > 0.00001f) {
failed = true;
}
++count;
}
if (count < rotor_count) {
break;
}
if (failed) {
printf("test %i failed:\n", test_counter + 1);
printf("control input : %.3f %.3f %.3f %.3f\n", (double)actuator_controls[0], (double)actuator_controls[1],
(double)actuator_controls[2], (double)actuator_controls[3]);
printf("mixer output : ");
for (unsigned i = 0; i < rotor_count; ++i) {
printf("%.3f ", (double)actuator_outputs[i]);
}
printf("\n");
printf("expected output: ");
for (unsigned i = 0; i < rotor_count; ++i) {
printf("%.3f ", (double)expected_output[i]);
}
printf("\n");
printf("diff : ");
for (unsigned i = 0; i < rotor_count; ++i) {
printf("%.3f ", (double)(expected_output[i] - actuator_outputs[i]));
}
printf("\n");
++num_failed;
}
++test_counter;
}
printf("tested %i cases: %i success, %i failed\n", test_counter,
test_counter - num_failed, num_failed);
if (file_in != stdin) {
fclose(file_in);
}
return num_failed > 0 ? -1 : 0;
}