10#include <boost/smart_ptr/make_shared_object.hpp>
12#include <SimoxUtility/algorithm/apply.hpp>
13#include <SimoxUtility/color/Color.h>
14#include <VirtualRobot/CollisionDetection/CollisionModel.h>
15#include <VirtualRobot/Robot.h>
16#include <VirtualRobot/SceneObjectSet.h>
34#include <armarx/navigation/local_planning/aron/TimedElasticBands.aron.generated.h>
39#include <geometry_msgs/Twist.h>
40#include <nlohmann/json_fwd.hpp>
42#include <teb_local_planner/homotopy_class_planner.h>
43#include <teb_local_planner/pose_se2.h>
44#include <teb_local_planner/robot_footprint_model.h>
45#include <teb_local_planner/timed_elastic_band.h>
46#include <teb_local_planner/visualization.h>
59 const auto robotName =
scene.robot->getName();
64 readConfig(
params.cfg, robotName);
73 cfg_.robot.cmd_angle_instead_rotvel =
false;
75 cfg_.optim.weight_kinematics_nh = 0;
76 cfg_.optim.weight_kinematics_forward_drive = 0;
77 cfg_.optim.weight_kinematics_turning_radius = 0;
81 cfg_.goal_tolerance.free_goal_vel =
false;
89 cfg_.robot.max_vel_x_backwards =
generalConfig.maxVel.linear / 1000;
91 cfg_.robot.max_vel_trans =
generalConfig.maxVel.linear / 1000;
95 auto robot_model = boost::make_shared<teb_local_planner::CircularRobotFootprint>(
96 params.cfg.robot_footprint_radius);
100 hcp_ = std::make_unique<teb_local_planner::HomotopyClassPlanner>();
102 cfg_, &teb_obstacles, robot_model, teb_local_planner::TebVisualizationPtr(),
nullptr);
110 .minDistance = 0.5, .epsilon = 0, .exponent = 1.2};
112 teb_costmap->setPenaltyModel(
conv::toRos(penalty));
113 hcp_->setCostmap(&teb_costmap.value());
119 TimedElasticBands::readConfig(arondto::TimedElasticBandsParams& target,
120 const std::string& robotName)
127 "local_planner_config/TimedElasticBands/" + robotName +
".json");
129 if (std::filesystem::exists(robotSpecificConfigPath.toSystemPath()))
133 return robotSpecificConfigPath;
137 "armarx_navigation",
"local_planner_config/TimedElasticBands/default.json");
140 return defaultConfigPath;
143 const std::filesystem::path file = configPath.
toSystemPath();
145 ARMARX_CHECK(std::filesystem::is_regular_file(file)) << file;
148 std::ifstream ifs{file};
150 nlohmann::json jsonConfig;
156 target.read(reader, jsonConfig);
159 std::optional<LocalPlannerResult>
167 currentPose.translation(),
params.cfg.planning_distance * 1000);
169 ARMARX_DEBUG << prunedGoal.points().size() <<
" waypoints in pruned goal";
171 for (
const auto& pt : prunedGoal.points())
173 ARMARX_DEBUG << pt.waypoint.pose.translation().head<2>();
176 const teb_local_planner::TimedElasticBand globalPath =
conv::toRos(prunedGoal);
177 teb_globalPath = globalPath.poses();
178 hcp_->setGlobalPath(&teb_globalPath);
180 const teb_local_planner::PoseSE2 start =
conv::toRos(currentPose);
181 const teb_local_planner::PoseSE2 end =
182 conv::toRos(prunedGoal.points().back().waypoint.pose);
191 const auto runTebOptimization =
192 [&hpc = this->hcp_, &start, &end, &velocity_start, &planToDest]() ->
bool
197 success = hpc->plan(start, end, &velocity_start, !planToDest);
207 if (not runTebOptimization())
211 <<
"Failed to plan trajectory. Trying to recover by replanning from scratch.";
212 hcp_->clearPlanner();
214 if (not runTebOptimization())
232 if (
false && hcp_->hasDiverged())
235 hcp_->clearPlanner();
240 if (hcp_->getTrajectoryContainer().empty())
242 hcp_->clearPlanner();
247 ARMARX_INFO <<
"Planned successfully (found " << hcp_->getTrajectoryContainer().size()
252 const ::teb_local_planner::TebOptimalPlannerPtr tebResult = hcp_->findBestTeb();
306 currentPose.translation().head<2>())
312 auto layer =
arviz.value().layer(
"local_planner_path_alternatives");
315 int bestTebIdx = hcp_->bestTebIdx();
316 for (
const auto& teb : hcp_->getTrajectoryContainer())
323 const std::vector<Eigen::Vector3f> points =
326 { return pt.pose.translation(); });
327 layer.add(
viz::Path(
"path_alternative_" + std::to_string(i))
329 .color(simox::Color::gray()));
333 arviz.value().commit(layer);
336 return {{.trajectory = best}};
340 TimedElasticBands::fillObstacles()
348 visLayer =
arviz.value().layer(
"local_planner_obstacles");
356 for (
const auto& obst :
scene.
staticScene.value().objects->getCollisionModels())
369 for (
const auto& obst :
scene.dynamicScene->laserScannerFeatures)
371 obstManager.addLaserScannerFeaturesObstacle(obst, visPtr);
377 arviz.value().commit(visLayer);
385 TimedElasticBands::setTebCostmap()
387 if (not
scene.staticScene.has_value())
392 if (not
scene.staticScene->distanceToObstaclesCostmap.has_value())
399 const algorithms::Costmap& navigationCostmap =
400 scene.staticScene->distanceToObstaclesCostmap.value();
401 teb_costmap.emplace(
conv::toRos(navigationCostmap));
static DateTime Now()
Current time on the virtual clock.
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
std::pair< GlobalTrajectory, bool > getSubTrajectory(const Position &point, const float distance) const
Project point onto the trajectory and return a new trajectory along the old one from that point for t...
const std::vector< LocalTrajectoryPoint > & points() const
core::GeneralConfig generalConfig
std::optional< viz::ScopedClient > arviz
const core::Scene & scene
LocalPlanner(const core::Scene &context, const core::GeneralConfig &generalConfig)
void addBoxObstacle(const VirtualRobot::BoundingBox &bbox, viz::Layer *visLayer=nullptr)
void addHumanObstacle(const human::Human &human, viz::Layer *visLayer=nullptr)
TimedElasticBands(const Params ¶ms, const core::GeneralConfig &generalConfig, const core::Scene &scene)
std::optional< LocalPlannerResult > plan(const core::GlobalTrajectory &goal) override
TimedElasticBandsParams Params
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
Eigen::Vector2d toRos(const Eigen::Vector3f &vec)
Eigen::Vector3f fromRos(const Eigen::Vector2d &vec)
This file is part of ArmarX.
void toTebCfg(const arondto::TimedElasticBandsParams &dto, ::teb_local_planner::TebConfig &bo)
std::string GetHandledExceptionString()
std::optional< core::StaticScene > staticScene
std::optional< core::DynamicScene > dynamicScene
std::size_t size() const noexcept