Move motion::dual_move_ramp into the separate motion::rampgen test

- Remove motion::dual_move_ramp from the Catch2 tests and reimplement
  it as a minimal c++ program for the ramp validation.
- Add a skeleton python validator to check the ramp output
- Use test "fixtures" to ensure the rampgen is run (both as a test,
  and to generate output) when the test_motion_ramp.py is requested.
pull/87/head
Yuri D'Elia 2021-08-11 11:33:04 +02:00 committed by DRracer
parent f37c9e363c
commit 89ab29dbde
4 changed files with 89 additions and 60 deletions

View File

@ -1,19 +1,25 @@
# define the test executable
add_executable(
motion_tests
${CMAKE_SOURCE_DIR}/src/modules/motion.cpp
${CMAKE_SOURCE_DIR}/src/modules/speed_table.cpp
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
${MODULES_STUBS_DIR}/stub_gpio.cpp
${MODULES_STUBS_DIR}/stub_shr16.cpp
${MODULES_STUBS_DIR}/stub_tmc2130.cpp
test_motion.cpp
)
# common include and source directories
set(include_common ${CMAKE_SOURCE_DIR}/src/modules ${CMAKE_SOURCE_DIR}/src/hal)
set(source_common
${CMAKE_SOURCE_DIR}/src/modules/motion.cpp ${CMAKE_SOURCE_DIR}/src/modules/speed_table.cpp
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp ${MODULES_STUBS_DIR}/stub_gpio.cpp
${MODULES_STUBS_DIR}/stub_shr16.cpp ${MODULES_STUBS_DIR}/stub_tmc2130.cpp
)
# define required search paths
target_include_directories(
motion_tests PUBLIC ${CMAKE_SOURCE_DIR}/src/modules ${CMAKE_SOURCE_DIR}/src/hal
)
# tell build system about the test case
# general motion tests
add_executable(motion_tests ${source_common} test_motion.cpp)
target_include_directories(motion_tests PUBLIC ${include_common})
add_catch_test(motion_tests)
# ramp generation tests
add_executable(rampgen ${source_common} rampgen.cpp)
target_include_directories(rampgen PUBLIC ${include_common})
add_test(NAME motion::rampgen COMMAND rampgen ramp_data.txt)
add_test(NAME motion::test_motion_ramp COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_motion_ramp.py
ramp_data.txt
)
# define the ramp_data fixture to chain tests
set_tests_properties(motion::test_motion_ramp PROPERTIES FIXTURES_REQUIRED motion::ramp_data)
set_tests_properties(motion::rampgen PROPERTIES FIXTURES_SETUP motion::ramp_data)

View File

@ -0,0 +1,61 @@
#include <cstdio>
#include <sysexits.h>
#include "motion.h"
using namespace modules::motion;
int main(int argc, const char *argv[]) {
const char *output = argv[1];
if (!argv[1]) {
fprintf(stderr, "Usage: %s <output>\n", argv[0]);
return EX_USAGE;
}
FILE *fd = fopen(output, "w");
if (!fd) {
fprintf(stderr, "%s: can't open output file %s: ", argv[0], output);
perror(NULL);
return EX_OSERR;
}
// common settings
const int idlerSteps = 100;
const int selectorSteps = 80;
const int maxFeedRate = 1000;
for (int accel = 2000; accel <= 50000; accel *= 2) {
// first axis using nominal values
motion.SetPosition(Idler, 0);
motion.SetAcceleration(Idler, accel);
motion.PlanMoveTo(Idler, idlerSteps, maxFeedRate);
fprintf(fd, "[{\"steps\": %d, \"accel\": %d, \"maxrate\": %d}, ",
idlerSteps, accel, maxFeedRate);
// second axis finishes slightly sooner at triple acceleration to maximize the
// aliasing effects
int accel_3 = accel * 3;
motion.SetPosition(Selector, 0);
motion.SetAcceleration(Selector, accel_3);
motion.PlanMoveTo(Selector, selectorSteps, maxFeedRate);
fprintf(fd, "{\"steps\": %d, \"accel\": %d, \"maxrate\": %d}]\n",
selectorSteps, accel_3, maxFeedRate);
// step and output time, interval and positions
unsigned long ts = 0;
st_timer_t next;
do {
next = motion.Step();
pos_t pos_idler = motion.CurPosition(Idler);
pos_t pos_selector = motion.CurPosition(Selector);
fprintf(fd, "%lu %u %d %d\n", ts, next, pos_idler, pos_selector);
ts += next;
} while (next);
fprintf(fd, "\n\n");
}
return EX_OK;
}

View File

@ -164,46 +164,3 @@ TEST_CASE("motion::triple_move", "[motion]") {
REQUIRE(motion.Position(Selector) == 20);
REQUIRE(motion.Position(Pulley) == 30);
}
TEST_CASE("motion::dual_move_ramp", "[motion]") {
// TODO: output ramps still to be checked
const int idlerSteps = 100;
const int selectorSteps = 80;
const int maxFeedRate = 1000;
for (int accel = 2000; accel <= 50000; accel *= 2) {
REQUIRE(motion.QueueEmpty());
// first axis using nominal values
motion.SetPosition(Idler, 0);
motion.SetAcceleration(Idler, accel);
motion.PlanMoveTo(Idler, idlerSteps, maxFeedRate);
// second axis finishes slightly sooner at triple acceleration to maximize the
// aliasing effects
motion.SetPosition(Selector, 0);
motion.SetAcceleration(Selector, accel * 3);
motion.PlanMoveTo(Selector, selectorSteps, maxFeedRate);
// step and output time, interval and positions
unsigned long ts = 0;
st_timer_t next;
do {
next = motion.Step();
pos_t pos_idler = motion.CurPosition(Idler);
pos_t pos_selector = motion.CurPosition(Selector);
printf("%lu %u %d %d\n", ts, next, pos_idler, pos_selector);
ts += next;
} while (next);
printf("\n\n");
// check queue status
REQUIRE(motion.QueueEmpty());
// check final position
REQUIRE(motion.Position(Idler) == idlerSteps);
REQUIRE(motion.Position(Selector) == selectorSteps);
}
}

View File

@ -0,0 +1,5 @@
#!/usr/bin/env python3
import numpy as np
import pandas as pd
exit(0)