diff --git a/source/Navigation/libraries/core/CMakeLists.txt b/source/Navigation/libraries/core/CMakeLists.txt index 44373e94c8c8d2c050bb9caa90bce821daf8ed71..c94aa639a276ffaca920f1e60254f1e3488b4422 100644 --- a/source/Navigation/libraries/core/CMakeLists.txt +++ b/source/Navigation/libraries/core/CMakeLists.txt @@ -17,6 +17,7 @@ armarx_add_library( SOURCES StaticScene.cpp Trajectory.cpp + types.cpp HEADERS types.h MemoryReferencedElement.h diff --git a/source/Navigation/libraries/core/types.cpp b/source/Navigation/libraries/core/types.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8e5e149b4caed0957cd6129ec0f14747c3f0cfe --- /dev/null +++ b/source/Navigation/libraries/core/types.cpp @@ -0,0 +1,10 @@ +#include "types.h" + +namespace armarx::nav::core +{ + core::Pose Twist::poseDiff(const float dt) const + { + return core::Pose(Eigen::Translation3f(linear * dt)) * + core::Pose(Eigen::AngleAxisf(angular.norm() * dt, angular.normalized())); + } +} // namespace armarx::nav::core diff --git a/source/Navigation/libraries/core/types.h b/source/Navigation/libraries/core/types.h index b00682034dd561e7edce9141fb8303c04aedf523..6b820ea7af87deb15f4e47e6e2decacc5ab715dd 100644 --- a/source/Navigation/libraries/core/types.h +++ b/source/Navigation/libraries/core/types.h @@ -53,6 +53,8 @@ namespace armarx::nav::core { Eigen::Vector3f linear; Eigen::Vector3f angular; + + core::Pose poseDiff(float dt) const; }; struct Waypoint @@ -60,8 +62,6 @@ namespace armarx::nav::core Pose pose; }; - - struct Scene { std::optional<core::StaticScene> staticScene = std::nullopt; diff --git a/source/Navigation/libraries/global_planning/Point2Point.cpp b/source/Navigation/libraries/global_planning/Point2Point.cpp index 0fcfdc513e87ab2afc8b76f93c5b3ca639d2013f..13407ff3e4af30f52d548bd024b2dd34fd68bdef 100644 --- a/source/Navigation/libraries/global_planning/Point2Point.cpp +++ b/source/Navigation/libraries/global_planning/Point2Point.cpp @@ -48,7 +48,7 @@ namespace armarx::nav::glob_plan { trajectory.push_back(core::TrajectoryPoint { - .waypoint = core::Waypoint{.pose = Eigen::Affine3f(context.robot->getGlobalPose())}, + .waypoint = core::Waypoint{.pose = core::Pose(context.robot->getGlobalPose())}, .twist = {.linear = Eigen::Vector3f::Zero(), .angular = Eigen::Vector3f::Zero()}}); } diff --git a/source/Navigation/libraries/server/Navigator.cpp b/source/Navigation/libraries/server/Navigator.cpp index 7b77b759c05264ac6f060d0aebaade02ae666070..927792ff38fa8c568bb7c3a6805a77c26b197efc 100644 --- a/source/Navigation/libraries/server/Navigator.cpp +++ b/source/Navigation/libraries/server/Navigator.cpp @@ -71,7 +71,7 @@ namespace armarx::nav::server ARMARX_CHECK_NOT_NULL(stack.globalPlanner); StackResult res; - res.globalTrajectory = stack.globalPlanner->plan(Eigen::Affine3f(waypoints.at(0))); + res.globalTrajectory = stack.globalPlanner->plan(core::Pose(waypoints.at(0))); if (stack.localPlanner) { diff --git a/source/Navigation/libraries/server/execution/DummyExecutor.h b/source/Navigation/libraries/server/execution/DummyExecutor.h index d5d075e58910c4c1dd358bbf9af8fa77765cd269..c5bf0cb99fa1e70f46f9323eef3d8df1fbaf1842 100644 --- a/source/Navigation/libraries/server/execution/DummyExecutor.h +++ b/source/Navigation/libraries/server/execution/DummyExecutor.h @@ -42,7 +42,7 @@ namespace armarx::nav::server //lastUpdated = now; - const Eigen::Affine3f diff; // = Eigen::Affine3f(Eigen::Translation3f(twist.linear * dt)) * Eigen::Affine3f(Eigen::AngleAxisf(dt, twist.angular))); + const core::Pose diff; // TODO robot->setGlobalPose(robot->getGlobalPose() * diff.matrix()); } diff --git a/source/Navigation/libraries/trajectory_control/test/trajectory_controlTest.cpp b/source/Navigation/libraries/trajectory_control/test/trajectory_controlTest.cpp index a9cda01677ac16992f8250a3646216eaba8ef519..a6e8743c660791ef8159ba47189321cb5264cb31 100644 --- a/source/Navigation/libraries/trajectory_control/test/trajectory_controlTest.cpp +++ b/source/Navigation/libraries/trajectory_control/test/trajectory_controlTest.cpp @@ -23,9 +23,11 @@ #include <limits> #include <Eigen/Geometry> +#include <Eigen/src/Geometry/AngleAxis.h> #include <Eigen/src/Geometry/Transform.h> #include <Eigen/src/Geometry/Translation.h> +#include <SimoxUtility/math/convert/deg_to_rad.h> #include <VirtualRobot/Robot.h> #include "Navigation/libraries/core/Trajectory.h" @@ -59,7 +61,7 @@ BOOST_AUTO_TEST_CASE(testTrajectoryFollowingControllerOnTrajectory) traj_ctrl::TrajectoryFollowingController controller(params, scene); core::TrajectoryPoint wpBefore; - wpBefore.waypoint.pose = Eigen::Affine3f::Identity(); + wpBefore.waypoint.pose = core::Pose::Identity(); wpBefore.waypoint.pose.translation().x() -= 100.F; wpBefore.twist.linear = Eigen::Vector3f::UnitX(); wpBefore.twist.angular = Eigen::Vector3f::Zero(); @@ -79,16 +81,17 @@ BOOST_AUTO_TEST_CASE(testTrajectoryFollowingControllerOnTrajectory) BOOST_CHECK_EQUAL(true, true); } - /** - * @brief Tests the control - * + * @brief Tests the control + * */ BOOST_AUTO_TEST_CASE(testTrajectoryFollowingControllerNextToTrajectory) { core::Scene scene; scene.robot = std::make_shared<VirtualRobot::LocalRobot>("foo", "bar"); - scene.robot->setGlobalPose(Eigen::Matrix4f::Identity() * Eigen::Affine3f(Eigen::Translation3f(0, 100, 0)).matrix(), false); + scene.robot->setGlobalPose(Eigen::Matrix4f::Identity() * + core::Pose(Eigen::Translation3f(0, 100, 0)).matrix(), + false); traj_ctrl::TrajectoryFollowingControllerParams params; params.pidPos = {1, 0, 0}; @@ -99,7 +102,7 @@ BOOST_AUTO_TEST_CASE(testTrajectoryFollowingControllerNextToTrajectory) traj_ctrl::TrajectoryFollowingController controller(params, scene); core::TrajectoryPoint wpBefore; - wpBefore.waypoint.pose = Eigen::Affine3f::Identity(); + wpBefore.waypoint.pose = core::Pose::Identity(); wpBefore.waypoint.pose.translation().x() -= 100.F; wpBefore.twist.linear = Eigen::Vector3f::UnitX(); wpBefore.twist.angular = Eigen::Vector3f::Zero(); @@ -118,3 +121,96 @@ BOOST_AUTO_TEST_CASE(testTrajectoryFollowingControllerNextToTrajectory) BOOST_CHECK_EQUAL(true, true); } + +class TargetReachedCondition +{ +public: + struct Params + { + struct + { + float linear; + float angular; + } distance; + }; + + TargetReachedCondition(const core::TrajectoryPoint& point, const Params& params) : + point(point), params(params) + { + } + + bool check(const core::Pose& pose) const + { + const float dp = (pose.translation() - point.waypoint.pose.translation()).norm(); + const float dr = + Eigen::AngleAxisf(pose.linear().inverse() * point.waypoint.pose.linear()).angle(); + + return (dp <= params.distance.linear) and (dr <= params.distance.angular); + } + +private: + core::TrajectoryPoint point; + const Params params; +}; + +/** + * @brief Tests the control + * + */ +BOOST_AUTO_TEST_CASE(testTrajectoryFollowingControllerReachGoal) +{ + core::Scene scene; + scene.robot = std::make_shared<VirtualRobot::LocalRobot>("foo", "bar"); + scene.robot->setGlobalPose(Eigen::Matrix4f::Identity() * + core::Pose(Eigen::Translation3f(0, 100, 0)).matrix(), + false); + + traj_ctrl::TrajectoryFollowingControllerParams params; + params.pidPos = {1, 0, 0}; + params.pidOri = {1, 0, 0}; + params.limits.linearVelocity = std::numeric_limits<float>::max(); + params.limits.angularVelocity = std::numeric_limits<float>::max(); + + traj_ctrl::TrajectoryFollowingController controller(params, scene); + + core::TrajectoryPoint wpBefore; + wpBefore.waypoint.pose = core::Pose::Identity(); + wpBefore.waypoint.pose.translation().x() -= 100.F; + wpBefore.twist.linear = Eigen::Vector3f::UnitX(); + wpBefore.twist.angular = Eigen::Vector3f::Zero(); + + core::TrajectoryPoint wpAfter = wpBefore; + wpAfter.waypoint.pose.translation().x() += 2000.F; + + core::TrajectoryPtr traj(new core::Trajectory({wpBefore, wpAfter})); + + auto timestamp = std::chrono::steady_clock::now(); + + TargetReachedCondition condition(wpAfter, + TargetReachedCondition::Params{.distance{ + .linear = 50.F, .angular = simox::math::deg_to_rad(10.F)}}); + + for (int i = 0; i < 50; i++) + { + core::Twist controlVal = controller.control(traj); + ARMARX_DEBUG << "Control val " << controlVal.linear; + + auto now = std::chrono::steady_clock::now(); + + const float dt = std::chrono::duration<float>(now - timestamp).count(); + + core::Pose dp = controlVal.poseDiff(dt); + + const core::Pose newPose = core::Pose(scene.robot->getGlobalPose()) * dp; + scene.robot->setGlobalPose(newPose.matrix()); + + if (condition.check(newPose)) + { + break; + } + + + } + + BOOST_CHECK(condition.check(core::Pose(scene.robot->getGlobalPose()))); +}