Skip to content

Commit

Permalink
cloud calculator for custom vector, update doctest
Browse files Browse the repository at this point in the history
  • Loading branch information
pantor committed Sep 30, 2023
1 parent 3ec51f3 commit 5a78272
Show file tree
Hide file tree
Showing 6 changed files with 7,162 additions and 7,053 deletions.
10 changes: 4 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,13 @@ endif()


if(BUILD_EXAMPLES)
set(EXAMPLES_LIST 01_position 02_position_offline 05_velocity 06_stop 07_minimum_duration 09_dynamic_dofs)
set(EXAMPLES_LIST 01_position 02_position_offline 05_velocity 06_stop 07_minimum_duration 09_dynamic_dofs 12_custom_vector_type 13_custom_vector_type_dynamic_dofs)
if(TARGET Eigen3::Eigen)
list(APPEND EXAMPLES_LIST 11_eigen_vector_type)
endif()

if(BUILD_CLOUD_CLIENT)
list(APPEND EXAMPLES_LIST 03_waypoints 04_waypoints_online 08_per_section_minimum_duration 10_dynamic_dofs_waypoints)
else()
list(APPEND EXAMPLES_LIST 12_custom_vector_type 13_custom_vector_type_dynamic_dofs)
if(TARGET Eigen3::Eigen)
list(APPEND EXAMPLES_LIST 11_eigen_vector_type)
endif()
endif()

foreach(example IN LISTS EXAMPLES_LIST)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ Note that `DynamicDOFs` corresponds to `DOFs = 0`. We've included a range of exa

## Tests and Numerical Stability

The current test suite validates over 5.000.000.000 random trajectories as well as many additional edge cases. The numerical exactness is tested for the final position and final velocity to be within `1e-8`, for the final acceleration to be within `1e-10`, and for the velocity, acceleration and jerk limit to be within of a numerical error of `1e-12`. These are absolute values - we suggest to scale your input so that these correspond to your required precision of the system. For example, for most real-world systems we suggest to use input values in `[m]` (instead of e.g. `[mm]`), as `1e-8m` is sufficient precise for practical trajectory generation. Furthermore, all kinematic limits should be below `1e12`. The maximal supported trajectory duration is `7e3`, and you can [scale your input parameter](https://github.com/pantor/ruckig/issues/139#issuecomment-1280730316) to avoid that limitation. Note that Ruckig will also output values outside of this range, there is however no guarantee for correctness.
The current test suite validates over 5.000.000.000 random trajectories as well as many additional edge cases. The numerical exactness is tested for the final position and final velocity to be within `1e-8`, for the final acceleration to be within `1e-10`, and for the velocity, acceleration and jerk limit to be within of a numerical error of `1e-12`. These are absolute values - we suggest to scale your input so that these correspond to your required precision of the system. For example, for most real-world systems we suggest to use input values in `[m]` (instead of e.g. `[mm]`), as `1e-8m` is sufficient precise for practical trajectory generation. Furthermore, all kinematic limits should be below `1e12`. The maximal supported trajectory duration is `7e3`. Note that Ruckig will also output values outside of this range, there is however no guarantee for correctness. The Ruckig Pro version has additional tools to increase the numerical range and improve reliability.


## Benchmark
Expand Down
74 changes: 50 additions & 24 deletions include/ruckig/calculator_cloud.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,32 @@ class CloudClient {
//! Calculation class for a trajectory along waypoints.
template<size_t DOFs, template<class, size_t> class CustomVector = StandardVector>
class WaypointsCalculator {
template<class T> using Vector = CustomVector<T, DOFs>;

// Convert the custom MinimumVector type to json, using only .size() and []
template<class V>
static void vector_to_json(nlohmann::json& j, const V& vector) {
j = nlohmann::json::array();
auto& j_vector = j.get_ref<nlohmann::json::array_t&>();

j_vector.resize(vector.size());
for (size_t i = 0; i < vector.size(); ++i) {
j_vector[i] = vector[i];
}
}

// Convert a double vector to json
template<class V>
static void double_vector_to_json(nlohmann::json& j, const std::vector<V>& vector) {
j = nlohmann::json::array();
auto& j_vector = j.get_ref<nlohmann::json::array_t&>();

j_vector.resize(vector.size());
for (size_t i = 0; i < vector.size(); ++i) {
vector_to_json(j_vector[i], vector[i]);
}
}

CloudClient client;

public:
Expand All @@ -57,60 +83,60 @@ class WaypointsCalculator {

nlohmann::json params;
params["degrees_of_freedom"] = input.degrees_of_freedom;
params["current_position"] = input.current_position;
params["current_velocity"] = input.current_velocity;
params["current_acceleration"] = input.current_acceleration;
params["target_position"] = input.target_position;
params["target_velocity"] = input.target_velocity;
params["target_acceleration"] = input.target_acceleration;
params["max_velocity"] = input.max_velocity;
params["max_acceleration"] = input.max_acceleration;
params["max_jerk"] = input.max_jerk;
vector_to_json<Vector<double>>(params["current_position"], input.current_position);
vector_to_json<Vector<double>>(params["current_velocity"], input.current_velocity);
vector_to_json<Vector<double>>(params["current_acceleration"], input.current_acceleration);
vector_to_json<Vector<double>>(params["target_position"], input.target_position);
vector_to_json<Vector<double>>(params["target_velocity"], input.target_velocity);
vector_to_json<Vector<double>>(params["target_acceleration"], input.target_acceleration);
vector_to_json<Vector<double>>(params["max_velocity"], input.max_velocity);
vector_to_json<Vector<double>>(params["max_acceleration"], input.max_acceleration);
vector_to_json<Vector<double>>(params["max_jerk"], input.max_jerk);
if (input.min_velocity) {
params["min_velocity"] = *input.min_velocity;
vector_to_json<Vector<double>>(params["min_velocity"], input.min_velocity.value());
}
if (input.min_acceleration) {
params["min_acceleration"] = *input.min_acceleration;
vector_to_json<Vector<double>>(params["min_acceleration"], input.min_acceleration.value());
}
if (!input.intermediate_positions.empty()) {
params["intermediate_positions"] = input.intermediate_positions;
double_vector_to_json<Vector<double>>(params["intermediate_positions"], input.intermediate_positions);
}
if (input.per_section_max_velocity) {
params["per_section_max_velocity"] = *input.per_section_max_velocity;
double_vector_to_json<Vector<double>>(params["per_section_max_velocity"], input.per_section_max_velocity.value());
}
if (input.per_section_max_acceleration) {
params["per_section_max_acceleration"] = *input.per_section_max_acceleration;
double_vector_to_json<Vector<double>>(params["per_section_max_acceleration"], input.per_section_max_acceleration.value());
}
if (input.per_section_max_jerk) {
params["per_section_max_jerk"] = *input.per_section_max_jerk;
double_vector_to_json<Vector<double>>(params["per_section_max_jerk"], input.per_section_max_jerk.value());
}
if (input.per_section_min_velocity) {
params["per_section_min_velocity"] = *input.per_section_min_velocity;
double_vector_to_json<Vector<double>>(params["per_section_min_velocity"], input.per_section_min_velocity.value());
}
if (input.per_section_min_acceleration) {
params["per_section_min_acceleration"] = *input.per_section_min_acceleration;
double_vector_to_json<Vector<double>>(params["per_section_min_acceleration"], input.per_section_min_acceleration.value());
}
if (input.max_position) {
params["max_position"] = *input.max_position;
vector_to_json<Vector<double>>(params["max_position"], input.max_position.value());
}
if (input.min_position) {
params["min_position"] = *input.min_position;
vector_to_json<Vector<double>>(params["min_position"], input.min_position.value());
}
params["enabled"] = input.enabled;
vector_to_json<Vector<bool>>(params["enabled"], input.enabled);
params["control_interface"] = input.control_interface;
params["synchronization"] = input.synchronization;
params["duration_discretization"] = input.duration_discretization;
if (input.per_dof_control_interface) {
params["per_dof_control_interface"] = *input.per_dof_control_interface;
vector_to_json<Vector<ControlInterface>>(params["per_dof_control_interface"], input.per_dof_control_interface.value());
}
if (input.per_dof_synchronization) {
params["per_dof_synchronization"] = *input.per_dof_synchronization;
vector_to_json<Vector<Synchronization>>(params["per_dof_synchronization"], input.per_dof_synchronization.value());
}
if (input.minimum_duration) {
params["minimum_duration"] = *input.minimum_duration;
params["minimum_duration"] = input.minimum_duration.value();
}
if (input.per_section_minimum_duration) {
params["per_section_minimum_duration"] = *input.per_section_minimum_duration;
vector_to_json<std::vector<double>>(params["per_section_minimum_duration"], input.per_section_minimum_duration.value());
}

const auto result = client.post(params, throw_error);
Expand Down
2 changes: 0 additions & 2 deletions test/test_target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,6 @@ TEST_CASE("zero-limits") {
CHECK( output.trajectory.get_duration() == doctest::Approx(1.1) );
}

#ifndef WITH_CLOUD_CLIENT
TEST_CASE("custom-vector-type") {
SUBCASE("DOFs compile-time") {
RuckigThrow<3, MinimalVector> otg {0.005};
Expand Down Expand Up @@ -934,7 +933,6 @@ TEST_CASE("custom-vector-type") {
CHECK( new_position[2] == doctest::Approx(input.current_position[2]) );
}
}
#endif

TEST_CASE("random-discrete-3") {
constexpr size_t DOFs {3};
Expand Down
2 changes: 1 addition & 1 deletion third_party/doctest/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2016-2021 Viktor Kirilov
Copyright (c) 2016-2023 Viktor Kirilov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading

0 comments on commit 5a78272

Please sign in to comment.