diff --git a/tests/unit/modules/motion/CMakeLists.txt b/tests/unit/modules/motion/CMakeLists.txt index 626a338..c9f8096 100644 --- a/tests/unit/modules/motion/CMakeLists.txt +++ b/tests/unit/modules/motion/CMakeLists.txt @@ -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) diff --git a/tests/unit/modules/motion/rampgen.cpp b/tests/unit/modules/motion/rampgen.cpp new file mode 100644 index 0000000..7048abf --- /dev/null +++ b/tests/unit/modules/motion/rampgen.cpp @@ -0,0 +1,61 @@ +#include +#include + +#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 \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; +} diff --git a/tests/unit/modules/motion/test_motion.cpp b/tests/unit/modules/motion/test_motion.cpp index 1aa4df2..ece685f 100644 --- a/tests/unit/modules/motion/test_motion.cpp +++ b/tests/unit/modules/motion/test_motion.cpp @@ -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); - } -} diff --git a/tests/unit/modules/motion/test_motion_ramp.py b/tests/unit/modules/motion/test_motion_ramp.py new file mode 100755 index 0000000..3a3f56f --- /dev/null +++ b/tests/unit/modules/motion/test_motion_ramp.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 +import numpy as np +import pandas as pd + +exit(0)