diff --git a/data/RobotAPI/VariantInfo-RobotAPI.xml b/data/RobotAPI/VariantInfo-RobotAPI.xml index fac11b677edbf7fc26cd2538e453981601e94f13..9d9342ab21b51d11fd188a70c5e4cf6066afff24 100644 --- a/data/RobotAPI/VariantInfo-RobotAPI.xml +++ b/data/RobotAPI/VariantInfo-RobotAPI.xml @@ -43,10 +43,18 @@ <Proxy include="RobotAPI/interface/units/PlatformUnitInterface.h" humanName="Platform Unit (obstacle avoiding)" typeName="PlatformUnitInterfacePrx" - memberName="obstacleAvoidingPlatformUnit" - getterName="getObstacleAvoidingPlatformUnit" - propertyName="ObstacleAvoidingPlatformUnitName" + memberName="platformUnit1" + getterName="getPlatformUnit1" + propertyName="PlatformUnitName1" propertyDefaultValue="ObstacleAvoidingPlatformUnit" + propertyIsOptional="true" /> + <Proxy include="RobotAPI/interface/units/PlatformUnitInterface.h" + humanName="Platform Unit (obstacle aware)" + typeName="PlatformUnitInterfacePrx" + memberName="platformUnit2" + getterName="getPlatformUnit2" + propertyName="PlatformUnitName2" + propertyDefaultValue="ObstacleAwarePlatformUnit" propertyIsOptional="true" /> <Proxy include="RobotAPI/interface/observers/PlatformUnitObserverInterface.h" humanName="Platform Unit Observer" diff --git a/source/RobotAPI/components/ArViz/Client/elements/Path.cpp b/source/RobotAPI/components/ArViz/Client/elements/Path.cpp index 0a88d089382eebb915104c24ee41339a18dd2f29..cf5e9899e943dd4076c2dd21ca9fe982b3c1a9bc 100644 --- a/source/RobotAPI/components/ArViz/Client/elements/Path.cpp +++ b/source/RobotAPI/components/ArViz/Client/elements/Path.cpp @@ -1,27 +1,21 @@ #include "Path.h" +#include <iterator> + +#include <ArmarXCore/interface/core/BasicVectorTypes.h> +#include <ArmarXCore/interface/core/BasicVectorTypesHelpers.h> + namespace armarx::viz { Path& Path::clear() { data_->points.clear(); - return *this; - } - - Path& Path::lineColor(Color color) - { - data_->lineColor = color; return *this; } - Path& Path::lineColorGlasbeyLUT(std::size_t id, int alpha) - { - return lineColor(Color::fromRGBA(simox::color::GlasbeyLUT::at(id, alpha))); - } - - Path& Path::lineWidth(float w) + Path& Path::width(float w) { data_->lineWidth = w; @@ -33,17 +27,21 @@ namespace armarx::viz auto& points = data_->points; points.clear(); points.reserve(ps.size()); - for (auto& p : ps) + + std::transform(ps.begin(), + ps.end(), + std::back_inserter(points), + [](const auto & e) { - points.push_back(armarx::Vector3f{p.x(), p.y(), p.z()}); - } + return ToBasicVectorType(e); + }); return *this; } Path& Path::addPoint(Eigen::Vector3f p) { - data_->points.push_back(armarx::Vector3f{p.x(), p.y(), p.z()}); + data_->points.emplace_back(ToBasicVectorType(p)); return *this; } diff --git a/source/RobotAPI/components/ArViz/Client/elements/Path.h b/source/RobotAPI/components/ArViz/Client/elements/Path.h index 50eec6abe454bbf56bc45053c4d35f5e41ca5bc6..7cfbecbd973a194cef0e0e350a5c7c3c1aedbc13 100644 --- a/source/RobotAPI/components/ArViz/Client/elements/Path.h +++ b/source/RobotAPI/components/ArViz/Client/elements/Path.h @@ -35,17 +35,7 @@ namespace armarx::viz Path& clear(); - Path& lineColor(Color color); - - template<class...Ts> - Path& lineColor(Ts&& ...ts) - { - return lineColor({std::forward<Ts>(ts)...}); - } - - Path& lineColorGlasbeyLUT(std::size_t id, int alpha = 255); - - Path& lineWidth(float w); + Path& width(float w); Path& points(std::vector<Eigen::Vector3f> const& ps); diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizationPath.cpp b/source/RobotAPI/components/ArViz/Coin/VisualizationPath.cpp index 3018a3af51e25222b97c0c60ed06fea65a8c5822..a0190abd75a8438a2371c728a580837d68c3eecc 100644 --- a/source/RobotAPI/components/ArViz/Coin/VisualizationPath.cpp +++ b/source/RobotAPI/components/ArViz/Coin/VisualizationPath.cpp @@ -1,9 +1,12 @@ #include "VisualizationPath.h" +#include <algorithm> + #include <Inventor/SbVec3f.h> #include <Inventor/nodes/SoCoordinate3.h> #include <Inventor/nodes/SoDrawStyle.h> #include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoPointSet.h> namespace armarx::viz::coin { @@ -27,19 +30,36 @@ namespace armarx::viz::coin node->addChild(coordinate3); node->addChild(lineSep); + + // points (use the following, if the points should be drawn in a different color) + + // pclMat = new SoMaterial; + + // SoMaterialBinding* pclMatBind = new SoMaterialBinding; + // pclMatBind->value = SoMaterialBinding::PER_PART; + + pclCoords = new SoCoordinate3; + pclStyle = new SoDrawStyle; + + // node->addChild(pclMat); + // node->addChild(pclMatBind); + node->addChild(pclCoords); + node->addChild(pclStyle); + node->addChild(new SoPointSet); } bool VisualizationPath::update(ElementType const& element) { // set position - coordinate3->point.setValuesPointer(element.points.size(), reinterpret_cast<const float*>(element.points.data())); + coordinate3->point.setValuesPointer(element.points.size(), + reinterpret_cast<const float*>(element.points.data())); // set color - const auto lineColor = element.lineColor; + const auto lineColor = element.color; constexpr float toUnit = 1.0F / 255.0F; - const auto color = SbVec3f(lineColor.r, lineColor.g, lineColor.b) * toUnit; + const auto color = SbVec3f(lineColor.r, lineColor.g, lineColor.b) * toUnit; const float transparency = 1.0F - static_cast<float>(lineColor.a) * toUnit; lineMaterial->diffuseColor.setValue(color); @@ -58,6 +78,20 @@ namespace armarx::viz::coin const int pointSize = static_cast<int>(element.points.size()); lineSet->numVertices.set1Value(0, pointSize); + // points at each node + // const std::vector<SbVec3f> colorData(element.points.size(), color); + + // pclMat->diffuseColor.setValuesPointer(colorData.size(), + // reinterpret_cast<const float*>(colorData.data())); + // pclMat->ambientColor.setValuesPointer(colorData.size(), + // reinterpret_cast<const float*>(colorData.data())); + // pclMat->transparency = transparency; + + pclCoords->point.setValuesPointer(element.points.size(), + reinterpret_cast<const float*>(element.points.data())); + + pclStyle->pointSize = element.lineWidth + 5; + return true; } } // namespace armarx::viz::coin \ No newline at end of file diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizationPath.h b/source/RobotAPI/components/ArViz/Coin/VisualizationPath.h index e1e446bbe66bc49a6d0c4bdf1999c7f0615f06ec..487ee9df58baeb6b91e91de6fdb3be873511a0af 100644 --- a/source/RobotAPI/components/ArViz/Coin/VisualizationPath.h +++ b/source/RobotAPI/components/ArViz/Coin/VisualizationPath.h @@ -39,9 +39,17 @@ namespace armarx::viz::coin bool update(ElementType const& element); + /// lines SoCoordinate3* coordinate3; SoDrawStyle* lineStyle; SoLineSet* lineSet; SoMaterial* lineMaterial; + + + /// points + // SoMaterial* pclMat; + SoCoordinate3* pclCoords; + SoDrawStyle* pclStyle; + }; } // namespace armarx::viz::coin diff --git a/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp index e712e30ccb2978fdc7caa0210b919773b7dce46b..41fc3e85f7a6a7250c47fe58c0730973a16480be 100644 --- a/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp +++ b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp @@ -22,6 +22,8 @@ #include "DynamicObstacleManager.h" +#include <VirtualRobot/MathTools.h> + // STD/STL #include <string> #include <vector> @@ -118,6 +120,7 @@ namespace armarx void DynamicObstacleManager::add_decayable_line_segment(const Eigen::Vector2f& line_start, const Eigen::Vector2f& line_end, const Ice::Current&) { + TIMING_START(add_decayable_line_segment); const Eigen::Vector2f difference_vec = line_end - line_start; const float length = difference_vec.norm(); const Eigen::Vector2f center_vec = line_start + 0.5 * difference_vec; @@ -136,10 +139,10 @@ namespace armarx return; } - { std::shared_lock<std::shared_mutex> l(m_managed_obstacles_mutex); + TIMING_START(add_decayable_line_segment_mutex); // First check own obstacles for (ManagedObstaclePtr& managed_obstacle : m_managed_obstacles) { @@ -155,13 +158,15 @@ namespace armarx managed_obstacle->line_matches.push_back(line_start); managed_obstacle->line_matches.push_back(line_end); managed_obstacle->m_last_matched = IceUtil::Time::now(); + TIMING_END(add_decayable_line_segment_mutex); return; } } + TIMING_END(add_decayable_line_segment_mutex); } // Second check the obstacles from the obstacle avoidance - for (const auto& published_obstacle : m_obstacle_detection->getObstacles()) + /*for (const auto& published_obstacle : m_obstacle_detection->getObstacles()) { float coverage = ManagedObstacle::line_segment_ellipsis_coverage( {published_obstacle.posX, published_obstacle.posY}, published_obstacle.axisLengthX, published_obstacle.axisLengthY, published_obstacle.yaw, @@ -172,7 +177,7 @@ namespace armarx ARMARX_DEBUG << "Found the obstacle in the static obstacle list! Matching name: " << published_obstacle.name; return; } - } + }*/ ARMARX_DEBUG << " No matching obstacle found. Create new obstacle and add to list"; ManagedObstaclePtr new_managed_obstacle(new ManagedObstacle()); @@ -198,6 +203,15 @@ namespace armarx std::lock_guard<std::shared_mutex> l(m_managed_obstacles_mutex); m_managed_obstacles.push_back(new_managed_obstacle); } + TIMING_END(add_decayable_line_segment); + } + + void DynamicObstacleManager::add_decayable_line_segments(const dynamicobstaclemanager::LineSegments& lines, const Ice::Current& c) + { + for (const auto& line : lines) + { + add_decayable_line_segment(line.lineStart, line.lineEnd, c); + } } @@ -218,7 +232,7 @@ namespace armarx std::lock_guard l(m_managed_obstacles_mutex); ARMARX_DEBUG << "Remove Obstacle " << name << " from obstacle map and from obstacledetection"; - for (ManagedObstaclePtr& managed_obstacle : m_managed_obstacles) + for (ManagedObstaclePtr managed_obstacle : m_managed_obstacles) { if (managed_obstacle->m_obstacle.name == name) { @@ -240,6 +254,36 @@ namespace armarx } + float + DynamicObstacleManager::distanceToObstacle(const Eigen::Vector2f& agentPosition, float safetyRadius, const Eigen::Vector2f& goal, const Ice::Current&) + { + std::shared_lock<std::shared_mutex> l{m_managed_obstacles_mutex}; + + const float sample_step = 5; // in [mm], sample step size towards goal. + const float distance_to_goal = (goal - agentPosition).norm() + safetyRadius; + float current_distance = safetyRadius; + + while (current_distance < distance_to_goal) + { + for (const auto man_obstacle : m_managed_obstacles) + { + Eigen::Vector2f sample = agentPosition + ((goal - agentPosition).normalized() * current_distance); + obstacledetection::Obstacle obstacle = man_obstacle->m_obstacle; + Eigen::Vector2f obstacle_origin{obstacle.posX, obstacle.posY}; + + if (ManagedObstacle::point_ellipsis_coverage(obstacle_origin, obstacle.axisLengthX, obstacle.axisLengthY, obstacle.yaw, sample)) + { + return current_distance - safetyRadius; + } + } + + current_distance += sample_step; + } + + return std::numeric_limits<float>::infinity(); + } + + void DynamicObstacleManager::directly_update_obstacle(const std::string& name, const Eigen::Vector2f& obs_pos, float e_rx, float e_ry, float e_yaw, const Ice::Current&) { obstacledetection::Obstacle new_unmanaged_obstacle; @@ -283,7 +327,6 @@ namespace armarx } } - // Update obstacle avoidance int checked_obstacles = 0; bool updated = false; diff --git a/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.h b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.h index 1629b7efe3102dccf85521ac0fac6379e09225cc..5f2d8065a307706ea16789930c12f5165d6044eb 100644 --- a/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.h +++ b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.h @@ -69,10 +69,12 @@ namespace armarx void add_decayable_obstacle(const Eigen::Vector2f&, float, float, float, const Ice::Current& = Ice::Current()) override; void add_decayable_line_segment(const Eigen::Vector2f&, const Eigen::Vector2f&, const Ice::Current& = Ice::Current()) override; + void add_decayable_line_segments(const dynamicobstaclemanager::LineSegments& lines, const Ice::Current& = Ice::Current()) override; void remove_all_decayable_obstacles(const Ice::Current& = Ice::Current()) override; void directly_update_obstacle(const std::string& name, const Eigen::Vector2f&, float, float, float, const Ice::Current& = Ice::Current()) override; void remove_obstacle(const std::string& name, const Ice::Current& = Ice::Current()) override; void wait_unitl_obstacles_are_ready(const Ice::Current& = Ice::Current()) override; + float distanceToObstacle(const Eigen::Vector2f& agentPosition, float safetyRadius, const Eigen::Vector2f& goal, const Ice::Current& = Ice::Current()) override; protected: void onInitComponent() override; diff --git a/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.cpp b/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.cpp index fe21cc4e46558b3a70102592ee77ef56715421f8..f718a45434ec538fbd5d2541fb9413568f3e79f0 100644 --- a/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.cpp +++ b/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.cpp @@ -94,10 +94,25 @@ namespace armarx float ManagedObstacle::line_segment_ellipsis_coverage(const Eigen::Vector2f e_origin, const float e_rx, const float e_ry, const float e_yaw, const Eigen::Vector2f line_seg_start, const Eigen::Vector2f line_seg_end) { // Again we discretize the line into n points and we check the coverage of those points - const unsigned int SAMPLES = 40; const Eigen::Vector2f difference_vec = line_seg_end - line_seg_start; const Eigen::Vector2f difference_vec_normed = difference_vec.normalized(); const float distance = difference_vec.norm(); + const unsigned int SAMPLES = std::max(distance / 10.0, 40.0); + + const Vector2f difference_start_origin = e_origin - line_seg_start; + const Vector2f difference_end_origin = e_origin - line_seg_end; + + if (difference_start_origin.norm() > std::max(e_rx, e_ry) && distance < std::max(e_rx, e_ry)) + { + return 0.0; + } + + if (difference_end_origin.norm() > std::max(e_rx, e_ry) && distance < std::max(e_rx, e_ry)) + { + return 0.0; + } + + const float step_size = distance / SAMPLES; const Eigen::Vector2f dir = difference_vec_normed * step_size; diff --git a/source/RobotAPI/components/units/CMakeLists.txt b/source/RobotAPI/components/units/CMakeLists.txt index 51d1930b83753c195ff7558154092ea025466e4c..3fa53590170e0ff9d288f7f130adae9814ee7446 100644 --- a/source/RobotAPI/components/units/CMakeLists.txt +++ b/source/RobotAPI/components/units/CMakeLists.txt @@ -75,6 +75,7 @@ set(LIB_FILES armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}") add_subdirectory(ObstacleAvoidingPlatformUnit) +add_subdirectory(ObstacleAwarePlatformUnit) add_subdirectory(relays) add_subdirectory(RobotUnit) diff --git a/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/CMakeLists.txt b/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..524b650bf5a3767a92a457ab97b26ffcdd903a40 --- /dev/null +++ b/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/CMakeLists.txt @@ -0,0 +1,10 @@ +armarx_add_component( + COMPONENT_NAME ObstacleAwarePlatformUnit + HEADERS ObstacleAwarePlatformUnit.h + SOURCES ObstacleAwarePlatformUnit.cpp + COMPONENT_LIBS ArmarXCoreComponentPlugins + RobotAPICore + RobotAPIComponentPlugins + RobotUnit +) +armarx_add_component_executable("main.cpp") diff --git a/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/ObstacleAwarePlatformUnit.cpp b/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/ObstacleAwarePlatformUnit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2acb4a23b423df17ca7f80ffc76251634bcb933f --- /dev/null +++ b/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/ObstacleAwarePlatformUnit.cpp @@ -0,0 +1,728 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::ObstacleAwarePlatformUnit + * @author Christian R. G. Dreher <c.dreher@kit.edu> + * @date 2021 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + + +#include <RobotAPI/components/units/ObstacleAwarePlatformUnit/ObstacleAwarePlatformUnit.h> + + +// STD/STL +#include <algorithm> +#include <cmath> +#include <limits> +#include <numeric> + +// Eigen +#include <Eigen/Core> +#include <Eigen/Geometry> + +// Simox +#include <SimoxUtility/math.h> + +// ArmarX +#include <ArmarXCore/observers/variant/Variant.h> + + +namespace +{ + + void + invalidate(float& v) + { + v = std::numeric_limits<float>::infinity(); + } + + + void + invalidate(Eigen::Vector2f& v) + { + v.x() = std::numeric_limits<float>::infinity(); + v.y() = std::numeric_limits<float>::infinity(); + } + + + void + invalidate(Eigen::Vector3f& v) + { + v.x() = std::numeric_limits<float>::infinity(); + v.y() = std::numeric_limits<float>::infinity(); + v.z() = std::numeric_limits<float>::infinity(); + } + + template<typename T> + void invalidate(std::deque<T>& d) + { + d.clear(); + } + + + std::string + to_string(armarx::ObstacleAwarePlatformUnit::control_mode mode) + { + switch (mode) + { + case armarx::ObstacleAwarePlatformUnit::control_mode::position: + return "position"; + case armarx::ObstacleAwarePlatformUnit::control_mode::velocity: + return "velocity"; + case armarx::ObstacleAwarePlatformUnit::control_mode::none: + default: + return "unset"; + } + } + +} + + +const std::string +armarx::ObstacleAwarePlatformUnit::default_name = "ObstacleAwarePlatformUnit"; + + +armarx::ObstacleAwarePlatformUnit::ObstacleAwarePlatformUnit() = default; + + +armarx::ObstacleAwarePlatformUnit::~ObstacleAwarePlatformUnit() = default; + + +void +armarx::ObstacleAwarePlatformUnit::onInitPlatformUnit() +{ + ARMARX_DEBUG << "Initializing " << getName() << "."; + + ARMARX_DEBUG << "Initialized " << getName() << "."; +} + + +void +armarx::ObstacleAwarePlatformUnit::onStartPlatformUnit() +{ + ARMARX_DEBUG << "Starting " << getName() << "."; + + if (!hasRobot("robot")) + { + m_robot = addRobot("robot", VirtualRobot::RobotIO::eStructure); + } + + invalidate(m_control_data.target_vel); + invalidate(m_control_data.target_rot_vel); + invalidate(m_control_data.target_pos); + invalidate(m_control_data.target_ori); + invalidate(m_viz.start); + + ARMARX_DEBUG << "Started " << getName() << "."; +} + + +void +armarx::ObstacleAwarePlatformUnit::onExitPlatformUnit() +{ + ARMARX_DEBUG << "Exiting " << getName() << "."; + + schedule_high_level_control_loop(control_mode::none); + + ARMARX_DEBUG << "Exited " << getName() << "."; +} + + +std::string +armarx::ObstacleAwarePlatformUnit::getDefaultName() +const +{ + return default_name; +} + + +void +armarx::ObstacleAwarePlatformUnit::moveTo( + const float target_pos_x, + const float target_pos_y, + const float target_ori, + const float pos_reached_threshold, + const float ori_reached_threshold, + const Ice::Current&) +{ + using namespace simox::math; + + std::scoped_lock l{m_control_data.mutex}; + + m_control_data.target_pos = Eigen::Vector2f{target_pos_x, target_pos_y}; + m_control_data.target_ori = periodic_clamp<float>(target_ori, -M_PI, M_PI); + m_control_data.pos_reached_threshold = pos_reached_threshold; + m_control_data.ori_reached_threshold = ori_reached_threshold; + + invalidate(m_control_data.target_vel); + invalidate(m_control_data.target_rot_vel); + + schedule_high_level_control_loop(control_mode::position); +} + + +void +armarx::ObstacleAwarePlatformUnit::move( + const float target_vel_x, + const float target_vel_y, + const float target_rot_vel, + const Ice::Current&) +{ + using namespace simox::math; + + std::scoped_lock l{m_control_data.mutex}; + + m_control_data.target_vel = Eigen::Vector2f{target_vel_x, target_vel_y}; + m_control_data.target_rot_vel = periodic_clamp<float>(target_rot_vel, -M_PI, M_PI); + + invalidate(m_control_data.target_pos); + invalidate(m_control_data.target_ori); + + ARMARX_CHECK(m_control_data.target_vel.allFinite()); + ARMARX_CHECK(std::isfinite(m_control_data.target_rot_vel)); + + schedule_high_level_control_loop(control_mode::velocity); +} + + +void +armarx::ObstacleAwarePlatformUnit::moveRelative( + const float target_pos_delta_x, + const float target_pos_delta_y, + const float target_delta_ori, + const float pos_reached_threshold, + const float ori_reached_threshold, + const Ice::Current& current) +{ + using namespace simox::math; + + // Transform relative to global. + std::unique_lock lock{m_control_data.mutex}; + synchronizeLocalClone(m_robot); + const Eigen::Vector2f agent_pos = m_robot->getGlobalPosition().head<2>(); + const float agent_ori = mat4f_to_rpy(m_robot->getGlobalPose()).z(); + lock.unlock(); + + // Use moveTo. + moveTo( + agent_pos.x() + target_pos_delta_x, + agent_pos.y() + target_pos_delta_y, + agent_ori + target_delta_ori, + pos_reached_threshold, + ori_reached_threshold, + current); +} + + +void +armarx::ObstacleAwarePlatformUnit::setMaxVelocities( + const float max_pos_vel, + const float max_rot_vel, + const Ice::Current&) +{ + std::scoped_lock l{m_control_data.mutex}; + m_control_data.max_vel = max_pos_vel; + m_control_data.max_rot_vel = max_rot_vel; + m_platform->setMaxVelocities(max_pos_vel, max_rot_vel); +} + + +void +armarx::ObstacleAwarePlatformUnit::stopPlatform(const Ice::Current&) +{ + schedule_high_level_control_loop(control_mode::none); + m_platform->stopPlatform(); +} + + +void +armarx::ObstacleAwarePlatformUnit::schedule_high_level_control_loop(control_mode mode) +{ + std::scoped_lock l{m_control_loop.mutex}; + + // If the control mode didn't change, there's nothing to do. + if (m_control_loop.mode == mode) + { + return; + } + + // If a control loop is runnung, stop it and wait for termination. + if (m_control_loop.mode != mode and m_control_loop.task) + { + ARMARX_VERBOSE << "Stopping " << ::to_string(m_control_loop.mode) << " control."; + const bool join = true; + m_control_loop.task->stop(join); + } + + // If the new control mode is none, no new control loop needs to be created. + if (mode == control_mode::none) + { + ARMARX_VERBOSE << "Going into stand-by."; + return; + } + + // Start next control loop. + ARMARX_VERBOSE << "Starting " << ::to_string(mode) << " control."; + m_control_loop.mode = mode; + m_control_loop.task = new RunningTask<ObstacleAwarePlatformUnit>( + this, + &ObstacleAwarePlatformUnit::high_level_control_loop); + m_control_loop.task->start(); +} + + +void +armarx::ObstacleAwarePlatformUnit::high_level_control_loop() +{ + const control_mode mode = m_control_loop.mode; + ARMARX_VERBOSE << "Started " << ::to_string(mode) << " control."; + + try + { + CycleUtil cu{m_control_loop.cycle_time}; + while (not m_control_loop.task->isStopped()) + { + const velocities vels = get_velocities(); + + // Debug. + StringVariantBaseMap m; + m["err_dist"] = new Variant{vels.err_dist}; + m["err_angular_dist"] = new Variant{vels.err_angular_dist}; + + m["target_global_x"] = new Variant{vels.target_global.x()}; + m["target_global_y"] = new Variant{vels.target_global.y()}; + m["target_global_abs"] = new Variant{vels.target_global.norm()}; + + m["target_local_x"] = new Variant{vels.target_local.x()}; + m["target_local_y"] = new Variant{vels.target_local.y()}; + m["target_local_abs"] = new Variant(vels.target_local.norm()); + m["target_rot"] = new Variant{vels.target_rot}; + + m["modulated_global_x"] = new Variant{vels.modulated_global.x()}; + m["modulated_global_y"] = new Variant{vels.modulated_global.y()}; + m["modulated_global_abs"] = new Variant{vels.modulated_global.norm()}; + + m["modulated_local_x"] = new Variant{vels.modulated_local.x()}; + m["modulated_local_y"] = new Variant{vels.modulated_local.y()}; + m["modulated_local_abs"] = new Variant{vels.modulated_local.norm()}; + + setDebugObserverChannel("ObstacleAvoidingPlatformCtrl", m); + + m_platform->move(vels.modulated_local.x(), vels.modulated_local.y(), vels.target_rot); + visualize(vels); + cu.waitForCycleDuration(); + } + } + catch (const std::exception& e) + { + ARMARX_ERROR << "Error occured while running control loop.\n" + << e.what(); + } + catch (...) + { + ARMARX_ERROR << "Unknown error occured while running control loop."; + } + + m_platform->move(0, 0, 0); + m_platform->stopPlatform(); + m_control_loop.mode = control_mode::none; + + visualize(); + + ARMARX_VERBOSE << "Stopped " << ::to_string(mode) << " control."; +} + + +armarx::ObstacleAwarePlatformUnit::velocities +armarx::ObstacleAwarePlatformUnit::get_velocities() +{ + using namespace simox::math; + + // Acquire control_data mutex to ensure data remains consistent. + std::scoped_lock l{m_control_data.mutex}; + // Update agent and get target velocities. + update_agent_dependent_values(); + const Eigen::Vector2f target_vel = get_target_velocity(); + const float target_rot_vel = get_target_rotational_velocity(); + + const Eigen::Vector2f extents = Eigen::Affine3f(m_robot->getRobotNode("PlatformCornerFrontLeft")->getPoseInRootFrame()).translation().head<2>(); + + // Apply obstacle avoidance and apply post processing to get the modulated velocity. + const Eigen::Vector2f modulated_vel = [this, &target_vel, &extents] + { + const VirtualRobot::Circle circle = VirtualRobot::projectedBoundingCircle(*m_robot); + ARMARX_DEBUG << "Circle approximation: " << circle.radius; + m_viz.boundingCircle = circle; + const float distance = m_obsman->distanceToObstacle(m_control_data.agent_pos /*circle.center*/, circle.radius, m_control_data.target_pos); + + ARMARX_DEBUG << "Distance to obstacle: " << distance; + + // https://www.wolframalpha.com/input/?i=line+through+%281000%2C+0%29+and+%282000%2C+1%29 + float modifier = std::clamp((distance / 1000) - 1., 0.0, 1.0); + + const Eigen::Vector2f vel = modifier * target_vel; + return vel.norm() > 20 ? vel : Eigen::Vector2f{0, 0}; + }(); + + ARMARX_CHECK(modulated_vel.allFinite()) << "Velocity contains non-finite values."; + ARMARX_CHECK(std::isfinite(target_rot_vel)) << "Rotation velocity is non-finite."; + + ARMARX_DEBUG << "Target velocity: " << target_vel.transpose() + << "; norm: " << target_vel.norm() << "; " << target_rot_vel; + ARMARX_DEBUG << "Modulated velocity: " << modulated_vel.transpose() << modulated_vel.norm(); + + const auto r = Eigen::Rotation2D(m_control_data.agent_ori).toRotationMatrix().inverse(); + + velocities vels; + vels.target_local = r * target_vel; + vels.target_global = target_vel; + vels.modulated_local = r * modulated_vel; + vels.modulated_global = modulated_vel; + vels.target_rot = target_rot_vel; + vels.err_dist = m_control_data.target_dist; + vels.err_angular_dist = m_control_data.target_angular_dist; + + return vels; +} + + +Eigen::Vector2f +armarx::ObstacleAwarePlatformUnit::get_target_velocity() +const +{ + using namespace simox::math; + + Eigen::Vector2f uncapped_target_vel = Eigen::Vector2f::Zero(); + + if (m_control_loop.mode == control_mode::position /*and not target_position_reached()*/) + { + uncapped_target_vel = + (m_control_data.target_pos - m_control_data.agent_pos) * m_control_data.kp; + } + else if (m_control_loop.mode == control_mode::velocity) + { + uncapped_target_vel = m_control_data.target_vel; + } + + ARMARX_CHECK(uncapped_target_vel.allFinite()); + + return norm_max(uncapped_target_vel, m_control_data.max_vel); +} + + +float +armarx::ObstacleAwarePlatformUnit::get_target_rotational_velocity() +const +{ + using namespace simox::math; + + float uncapped_target_rot_vel = 0; + + if (m_control_loop.mode == control_mode::position /*and not target_orientation_reached()*/) + { + m_rot_pid_controller.update(m_control_data.target_angular_dist, 0); + uncapped_target_rot_vel = -m_rot_pid_controller.getControlValue(); + } + else if (m_control_loop.mode == control_mode::velocity) + { + uncapped_target_rot_vel = m_control_data.target_rot_vel; + } + + ARMARX_CHECK(std::isfinite(uncapped_target_rot_vel)); + + return std::copysign(std::min(std::fabs(uncapped_target_rot_vel), m_control_data.max_rot_vel), + uncapped_target_rot_vel); +} + + +void +armarx::ObstacleAwarePlatformUnit::update_agent_dependent_values() +{ + using namespace simox::math; + + synchronizeLocalClone(m_robot); + m_control_data.agent_pos = m_robot->getGlobalPosition().head<2>(); + m_control_data.agent_ori = + periodic_clamp<float>(mat4f_to_rpy(m_robot->getGlobalPose()).z(), -M_PI, M_PI); + + ARMARX_CHECK_GREATER(m_control_data.agent_ori, -M_PI); + ARMARX_CHECK_LESS(m_control_data.agent_ori, M_PI); + + // Update distances in position mode. + if (m_control_loop.mode == control_mode::position) + { + ARMARX_CHECK_GREATER(m_control_data.target_ori, -M_PI); + ARMARX_CHECK_LESS(m_control_data.target_ori, M_PI); + ARMARX_CHECK(m_control_data.target_pos.allFinite()); + ARMARX_CHECK(std::isfinite(m_control_data.target_ori)); + + m_control_data.target_dist = + (m_control_data.target_pos - m_control_data.agent_pos).norm(); + m_control_data.target_angular_dist = + periodic_clamp<float>(m_control_data.target_ori - m_control_data.agent_ori, + -M_PI, M_PI); + + ARMARX_CHECK_GREATER(m_control_data.target_angular_dist, -M_PI); + ARMARX_CHECK_LESS(m_control_data.target_angular_dist, M_PI); + + ARMARX_DEBUG << "Distance to target: " << m_control_data.target_dist << " mm and " + << m_control_data.target_angular_dist << " rad."; + } + // Otherwise invalidate them. + else + { + invalidate(m_control_data.target_dist); + invalidate(m_control_data.target_angular_dist); + } +} + + +bool +armarx::ObstacleAwarePlatformUnit::target_position_reached() +const +{ + if (m_control_loop.mode == control_mode::position) + { + return m_control_data.target_dist < m_control_data.pos_reached_threshold; + } + + // Cannot reach any target in non-position mode. + return false; +} + + +bool +armarx::ObstacleAwarePlatformUnit::target_orientation_reached() +const +{ + if (m_control_loop.mode == control_mode::position) + { + return std::fabs(m_control_data.target_angular_dist) < m_control_data.ori_reached_threshold; + } + + // Cannot reach any target in non-position mode. + return false; +} + + +bool +armarx::ObstacleAwarePlatformUnit::target_reached() +const +{ + if (m_control_loop.mode == control_mode::position) + { + return target_position_reached() and target_orientation_reached(); + } + + return false; +} + + +bool +armarx::ObstacleAwarePlatformUnit::is_near_target(const Eigen::Vector2f& control_velocity) +const noexcept +{ + if (m_control_data.target_dist < m_control_data.pos_near_threshold) + { + const Eigen::Vector2f target_direction = m_control_data.target_pos - m_control_data.agent_pos; + const Eigen::Vector2f control_direction = control_velocity / control_velocity.norm(); + + const float sim = simox::math::cosine_similarity(target_direction, control_direction); + + // if almost pointing into same direction + if (sim > cos(M_PI_4f32)) + { + return true; + } + } + + return false; +} + + +void +armarx::ObstacleAwarePlatformUnit::visualize() +{ + const Eigen::Vector2f zero = Eigen::Vector2f::Zero(); + velocities vels; + vels.target_local = zero; + vels.target_global = zero; + vels.modulated_local = zero; + vels.modulated_global = zero; + vels.target_rot = 0; + + visualize(vels); +} + + +void +armarx::ObstacleAwarePlatformUnit::visualize(const velocities& vels) +{ + using namespace armarx::viz; + + if (not m_viz.enabled) + { + return; + } + + Eigen::Vector3f agent_pos{m_control_data.agent_pos.x(), m_control_data.agent_pos.y(), 0}; + + // Progress. Only draw in position control mode. + Layer l_prog = arviz.layer("progress"); + if (m_control_loop.mode == control_mode::position) + { + const float min_keypoint_dist = 50; + + { + l_prog.add(Cylinder{"boundingCylinder"} + .position(agent_pos) + .color(Color::cyan(255, 64)) + .pose(simox::math::pos_rpy_to_mat4f(agent_pos, -M_PI_2, 0, 0)) + .radius(m_viz.boundingCircle.radius) + .height(2000)); + } + + // If no start is set, use current agent pos. + if (not m_viz.start.allFinite()) + { + m_viz.start = agent_pos; + } + + const Eigen::Vector3f& last_keypoint_pos = + m_viz.path.size() >= 1 ? m_viz.path.back() : m_viz.start; + + // Keep a certain distance between path keypoints. + if ((last_keypoint_pos - agent_pos).norm() > min_keypoint_dist) + { + m_viz.path.push_back(agent_pos); + } + + // Draw path. + if (not target_reached()) + { + // Start. + l_prog.add(Sphere{"start"} + .position(m_viz.start) + .color(Color::cyan(255, 64)) + .radius(40)); + + // Path. + for (unsigned i = 0; i < m_viz.path.size(); ++i) + { + l_prog.add(Sphere{"path_" + std::to_string(i + 1)} + .position(m_viz.path[i]) + .color(Color::magenta(255, 128)) + .radius(20)); + } + + // Goal. + const Eigen::Vector3f target{m_control_data.target_pos.x(), + m_control_data.target_pos.y(), + 0}; + l_prog.add(Arrow{"goal"} + .fromTo(target + Eigen::Vector3f{0, 0, 220}, + target + Eigen::Vector3f{0, 0, 40}) + .color(Color::red(255, 128)) + .width(20)); + } + else + { + m_viz.path.clear(); + invalidate(m_viz.start); + } + } + + // Velocities. + Layer l_vels = arviz.layer("velocities"); + if (m_control_loop.mode != control_mode::none) + { + const float min_velocity = 15; + const Eigen::Vector3f from1{agent_pos + Eigen::Vector3f{0, 0, 2000}}; + const Eigen::Vector3f from2 = from1 + Eigen::Vector3f{0, 0, 200}; + const Eigen::Vector3f original{vels.target_global.x(), vels.target_global.y(), 0}; + const Eigen::Vector3f modulated{vels.modulated_global.x(), vels.modulated_global.y(), 0}; + + if (original.norm() > min_velocity) + { + l_vels.add(Arrow{"original"} + .fromTo(from1, from1 + original * 5) + .color(Color::green(255, 128)) + .width(25)); + } + + if (modulated.norm() > min_velocity) + { + l_vels.add(Arrow{"modulated"} + .fromTo(from2, from2 + modulated * 5) + .color(Color::cyan(255, 128)) + .width(25)); + } + } + + // Agent. + Layer l_agnt = arviz.layer("agent"); + if (m_control_loop.mode != control_mode::none) + { + l_agnt.add(Sphere{"agent"} + .position(agent_pos) + .color(Color::red(255, 128)) + .radius(50)); + + // Agent safety margin. + if (m_control_data.agent_safety_margin > 0) + { + l_agnt.add(Cylinder{"agent_safety_margin"} + .pose(simox::math::pos_rpy_to_mat4f(agent_pos, -M_PI_2, 0, 0)) + .color(Color::red(255, 64)) + .radius(m_control_data.agent_safety_margin) + .height(2)); + } + } + + arviz.commit({l_prog, l_vels, l_agnt}); +} + + +armarx::PropertyDefinitionsPtr +armarx::ObstacleAwarePlatformUnit::createPropertyDefinitions() +{ + PropertyDefinitionsPtr def = PlatformUnit::createPropertyDefinitions(); + + def->component(m_platform, "Platform"); + def->component(m_obsman, "ObstacleAvoidingPlatformUnit"); + + // Settings. + def->optional(m_control_data.min_vel_near_target, "min_vel_near_target", "Velocity in [mm/s] " + "the robot should at least set when near the target"); + def->optional(m_control_data.min_vel_general, "min_vel_general", "Velocity in [mm/s] the robot " + "should at least set on general"); + def->optional(m_control_data.pos_near_threshold, "pos_near_threshold", "Distance in [mm] after " + "which the robot is considered to be near the target for min velocity, " + "smoothing, etc."); + + // Control parameters. + def->optional(m_control_data.kp, "control.pos.kp"); + def->optional(m_rot_pid_controller.Kp, "control.rot.kp"); + def->optional(m_rot_pid_controller.Ki, "control.rot.ki"); + def->optional(m_rot_pid_controller.Kd, "control.rot.kd"); + def->optional(m_control_loop.cycle_time, "control.pose.cycle_time", "Control loop cycle time."); + + // Obstacle avoidance parameter. + def->optional(m_control_data.agent_safety_margin, "doa.agent_safety_margin"); + + return def; +} diff --git a/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/ObstacleAwarePlatformUnit.h b/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/ObstacleAwarePlatformUnit.h new file mode 100644 index 0000000000000000000000000000000000000000..274b67ea153eec20473b67fa4f45b8425c7b174d --- /dev/null +++ b/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/ObstacleAwarePlatformUnit.h @@ -0,0 +1,259 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::ObstacleAwarePlatformUnit + * @author Christian R. G. Dreher <c.dreher@kit.edu> + * @date 2021 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + + +#pragma once + + +// STD/STL +#include <deque> +#include <string> +#include <tuple> +#include <mutex> +#include <vector> + +// Eigen +#include <Eigen/Core> + +// Ice +#include <IceUtil/Time.h> + +// Simox +#include <VirtualRobot/Nodes/RobotNode.h> +#include <VirtualRobot/Safety.h> + +// ArmarX +#include <ArmarXCore/libraries/ArmarXCoreComponentPlugins/DebugObserverComponentPlugin.h> +#include <ArmarXCore/util/tasks.h> +#include <ArmarXCore/util/time.h> + +// RobotAPI +#include <RobotAPI/components/units/PlatformUnit.h> +#include <RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.h> +#include <RobotAPI/libraries/core/PIDController.h> +#include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h> +#include <RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.h> + + +namespace armarx +{ + + class ObstacleAwarePlatformUnit : + virtual public PlatformUnit, + virtual public RobotStateComponentPluginUser, + virtual public ArVizComponentPluginUser, + virtual public DebugObserverComponentPluginUser + { + + public: + + enum class control_mode + { + position, + velocity, + none + }; + + private: + + struct control_loop + { + std::mutex mutex; + control_mode mode = control_mode::none; + RunningTask<ObstacleAwarePlatformUnit>::pointer_type task; + IceUtil::Time cycle_time = IceUtil::Time::milliSeconds(10); + }; + + struct control_data + { + std::mutex mutex; + Eigen::Vector2f target_pos; + float target_ori; + Eigen::Vector2f target_vel; + float target_rot_vel; + float target_dist; + float target_angular_dist; + Eigen::Vector2f agent_pos; + float agent_ori; + double agent_safety_margin = 0; + float min_vel_near_target = 50; + float min_vel_general = 100; + float max_vel = 200; + float max_rot_vel = 0.3; + float pos_near_threshold = 250; + float pos_reached_threshold = 8; + float ori_reached_threshold = 0.1; + float kp = 3.5; + }; + + struct visualization + { + Eigen::Vector3f start; + std::vector<Eigen::Vector3f> path; + bool enabled = true; + VirtualRobot::Circle boundingCircle; + }; + + struct velocities + { + Eigen::Vector2f target_local; + Eigen::Vector2f modulated_local; + Eigen::Vector2f target_global; + Eigen::Vector2f modulated_global; + float target_rot; + float err_dist; + float err_angular_dist; + }; + + public: + + ObstacleAwarePlatformUnit(); + + ~ObstacleAwarePlatformUnit() + override; + + std::string + getDefaultName() + const override; + + void + moveTo( + float target_pos_x, + float target_pos_y, + float target_ori, + float pos_reached_threshold, + float ori_reached_threshold, + const Ice::Current& = Ice::Current{}) + override; + + void + move( + float target_vel_x, + float target_vel_y, + float target_rot_vel, + const Ice::Current& = Ice::Current{}) + override; + + void + moveRelative( + float target_pos_delta_x, + float target_pos_delta_y, + float target_delta_ori, + float pos_reached_threshold, + float ori_reached_threshold, + const Ice::Current& = Ice::Current{}) + override; + + void + setMaxVelocities( + float max_pos_vel, + float max_rot_vel, + const Ice::Current& = Ice::Current{}) + override; + + void + stopPlatform(const Ice::Current& = Ice::Current{}) + override; + + protected: + + void + onInitPlatformUnit() + override; + + void + onStartPlatformUnit() + override; + + void + onExitPlatformUnit() + override; + + PropertyDefinitionsPtr + createPropertyDefinitions() + override; + + private: + + void + schedule_high_level_control_loop(control_mode mode); + + void + high_level_control_loop(); + + velocities + get_velocities(); + + void + update_agent_dependent_values(); + + Eigen::Vector2f + get_target_velocity() + const; + + float + get_target_rotational_velocity() + const; + + bool + target_position_reached() + const; + + bool + target_orientation_reached() + const; + + bool + target_reached() + const; + + void + visualize(); + + void + visualize(const velocities& vels); + + bool + is_near_target(const Eigen::Vector2f& control_velocity) + const + noexcept; + + public: + + static const std::string default_name; + + private: + + PlatformUnitInterfacePrx m_platform; + VirtualRobot::RobotPtr m_robot; + DynamicObstacleManagerInterfacePrx m_obsman; + + ObstacleAwarePlatformUnit::control_loop m_control_loop; + ObstacleAwarePlatformUnit::control_data m_control_data; + + mutable PIDController m_rot_pid_controller{1.0, 0.00009, 0.0}; + + visualization m_viz; + + }; + +} diff --git a/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/main.cpp b/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f168208f6734ea228aa848dcf0c5d0976370bae7 --- /dev/null +++ b/source/RobotAPI/components/units/ObstacleAwarePlatformUnit/main.cpp @@ -0,0 +1,40 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::ObstacleAwarePlatformUnit + * @author Christian R. G. Dreher <c.dreher@kit.edu> + * @date 2021 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + + +// STD/STL +#include <string> + +// ArmarX +#include <ArmarXCore/core/application/Application.h> +#include <ArmarXCore/core/Component.h> + +// RobotAPI +#include <RobotAPI/components/units/ObstacleAwarePlatformUnit/ObstacleAwarePlatformUnit.h> + + +int main(int argc, char* argv[]) +{ + using namespace armarx; + const std::string name = ObstacleAwarePlatformUnit::default_name; + return runSimpleComponentApp<ObstacleAwarePlatformUnit>(argc, argv, name); +} diff --git a/source/RobotAPI/interface/ArViz/Elements.ice b/source/RobotAPI/interface/ArViz/Elements.ice index 1c00dd4e630208a79852ea3d18d96da8a501f7d0..bebbb3f414be2184f51fdb8518cdcd368da33ebc 100644 --- a/source/RobotAPI/interface/ArViz/Elements.ice +++ b/source/RobotAPI/interface/ArViz/Elements.ice @@ -104,7 +104,6 @@ module data { Vector3fSeq points; - Color lineColor; float lineWidth = 10.0f; }; diff --git a/source/RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.ice b/source/RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.ice index d21a3c55b7574a459f0be3e2577870cf7640f5e3..5ff2649fae12cb906f5821f73ba1fb1fd21647fe 100644 --- a/source/RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.ice +++ b/source/RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.ice @@ -30,6 +30,18 @@ module armarx { + module dynamicobstaclemanager + { + struct LineSegment + { + Eigen::Vector2f lineStart; + Eigen::Vector2f lineEnd; + }; + + sequence<LineSegment> LineSegments; + } + + interface DynamicObstacleManagerInterface { void @@ -38,6 +50,9 @@ module armarx void add_decayable_line_segment(Eigen::Vector2f line_start, Eigen::Vector2f line_end); + void + add_decayable_line_segments(dynamicobstaclemanager::LineSegments lines); + void remove_all_decayable_obstacles(); @@ -48,6 +63,8 @@ module armarx remove_obstacle(string name); void wait_unitl_obstacles_are_ready(); + + float distanceToObstacle(Eigen::Vector2f agentPosition, float safetyRadius, Eigen::Vector2f goal); }; };