Skip to content

Commit 987fe90

Browse files
authored
Controller exceptions (#3227)
* added result codes for global planner * code review * code review * cleanup * cleanup * update smac lattice planner * update planner instances * cleanup * added controller exception * renaming * follow path updates * rename exceptions * updated regulated pure pursuit * completed pure pursuit * completed dwb * linting fixes * cleanup * revert planner server * revert planner server * revert planner server * revert planner server * code review * code review * cleanup * cleanup * bug fix * final cleanup * set follow path error on bt * update groot * code review Co-authored-by: Joshua Wallace <josho.wallace.com>
1 parent d6b7304 commit 987fe90

File tree

23 files changed

+237
-83
lines changed

23 files changed

+237
-83
lines changed

nav2_behavior_tree/include/nav2_behavior_tree/plugins/action/follow_path_action.hpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ namespace nav2_behavior_tree
2929
*/
3030
class FollowPathAction : public BtActionNode<nav2_msgs::action::FollowPath>
3131
{
32+
using Action = nav2_msgs::action::FollowPath;
33+
using ActionResult = Action::Result;
34+
using ActionGoal = Action::Goal;
35+
3236
public:
3337
/**
3438
* @brief A constructor for nav2_behavior_tree::FollowPathAction
@@ -46,13 +50,28 @@ class FollowPathAction : public BtActionNode<nav2_msgs::action::FollowPath>
4650
*/
4751
void on_tick() override;
4852

53+
/**
54+
* @brief Function to perform some user-defined operation upon successful completion of the action
55+
*/
56+
BT::NodeStatus on_success() override;
57+
58+
/**
59+
* @brief Function to perform some user-defined operation upon abortion of the action
60+
*/
61+
BT::NodeStatus on_aborted() override;
62+
63+
/**
64+
* @brief Function to perform some user-defined operation upon cancellation of the action
65+
*/
66+
BT::NodeStatus on_cancelled() override;
67+
4968
/**
5069
* @brief Function to perform some user-defined operation after a timeout
5170
* waiting for a result that hasn't been received yet
5271
* @param feedback shared_ptr to latest feedback message
5372
*/
5473
void on_wait_for_result(
55-
std::shared_ptr<const nav2_msgs::action::FollowPath::Feedback> feedback) override;
74+
std::shared_ptr<const Action::Feedback> feedback) override;
5675

5776
/**
5877
* @brief Creates list of BT ports
@@ -65,6 +84,8 @@ class FollowPathAction : public BtActionNode<nav2_msgs::action::FollowPath>
6584
BT::InputPort<nav_msgs::msg::Path>("path", "Path to follow"),
6685
BT::InputPort<std::string>("controller_id", ""),
6786
BT::InputPort<std::string>("goal_checker_id", ""),
87+
BT::OutputPort<ActionResult::_error_code_type>(
88+
"follow_path_error_code", "The follow path error code"),
6889
});
6990
}
7091
};

nav2_behavior_tree/nav2_tree_nodes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
<input_port name="goal_checker_id" default="GoalChecker">Goal checker</input_port>
114114
<input_port name="service_name">Service name</input_port>
115115
<input_port name="server_timeout">Server timeout</input_port>
116+
<output_port name="follow_path_error_code">Follow Path error code</output_port>
116117
</Action>
117118

118119
<Action ID="NavigateToPose">

nav2_behavior_tree/plugins/action/follow_path_action.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ FollowPathAction::FollowPathAction(
2424
const std::string & xml_tag_name,
2525
const std::string & action_name,
2626
const BT::NodeConfiguration & conf)
27-
: BtActionNode<nav2_msgs::action::FollowPath>(xml_tag_name, action_name, conf)
27+
: BtActionNode<Action>(xml_tag_name, action_name, conf)
2828
{
2929
}
3030

@@ -35,8 +35,27 @@ void FollowPathAction::on_tick()
3535
getInput("goal_checker_id", goal_.goal_checker_id);
3636
}
3737

38+
BT::NodeStatus FollowPathAction::on_success()
39+
{
40+
setOutput("follow_path_error_code", ActionGoal::NONE);
41+
return BT::NodeStatus::SUCCESS;
42+
}
43+
44+
BT::NodeStatus FollowPathAction::on_aborted()
45+
{
46+
setOutput("follow_path_error_code", result_.result->error_code);
47+
return BT::NodeStatus::FAILURE;
48+
}
49+
50+
BT::NodeStatus FollowPathAction::on_cancelled()
51+
{
52+
// Set empty error code, action was cancelled
53+
setOutput("compute_path_to_pose_error_code", ActionGoal::NONE);
54+
return BT::NodeStatus::SUCCESS;
55+
}
56+
3857
void FollowPathAction::on_wait_for_result(
39-
std::shared_ptr<const nav2_msgs::action::FollowPath::Feedback>/*feedback*/)
58+
std::shared_ptr<const Action::Feedback>/*feedback*/)
4059
{
4160
// Grab the new path
4261
nav_msgs::msg::Path new_path;

nav2_constrained_smoother/src/constrained_smoother.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include <vector>
2222

2323
#include "nav2_constrained_smoother/constrained_smoother.hpp"
24-
#include "nav2_core/exceptions.hpp"
2524
#include "nav2_util/node_utils.hpp"
2625
#include "nav2_util/geometry_utils.hpp"
2726
#include "nav2_costmap_2d/costmap_filters/filter_values.hpp"
@@ -138,7 +137,7 @@ bool ConstrainedSmoother::smooth(nav_msgs::msg::Path & path, const rclcpp::Durat
138137
logger_,
139138
"%s: failed to smooth plan, Ceres could not find a usable solution to optimize.",
140139
plugin_name_.c_str());
141-
throw new nav2_core::PlannerException(
140+
throw std::runtime_error(
142141
"Failed to smooth plan, Ceres could not find a usable solution.");
143142
}
144143

nav2_controller/plugins/simple_progress_checker.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <string>
1818
#include <memory>
1919
#include <vector>
20-
#include "nav2_core/exceptions.hpp"
2120
#include "nav_2d_utils/conversions.hpp"
2221
#include "geometry_msgs/msg/pose_stamped.hpp"
2322
#include "geometry_msgs/msg/pose2_d.hpp"

nav2_controller/src/controller_server.cpp

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include <utility>
2020
#include <limits>
2121

22-
#include "nav2_core/exceptions.hpp"
22+
#include "nav2_core/controller_exceptions.hpp"
2323
#include "nav_2d_utils/conversions.hpp"
2424
#include "nav_2d_utils/tf_help.hpp"
2525
#include "nav2_util/node_utils.hpp"
@@ -353,17 +353,15 @@ void ControllerServer::computeControl()
353353
if (findControllerId(c_name, current_controller)) {
354354
current_controller_ = current_controller;
355355
} else {
356-
action_server_->terminate_current();
357-
return;
356+
throw nav2_core::ControllerException("Failed to find controller name: " + c_name);
358357
}
359358

360359
std::string gc_name = action_server_->get_current_goal()->goal_checker_id;
361360
std::string current_goal_checker;
362361
if (findGoalCheckerId(gc_name, current_goal_checker)) {
363362
current_goal_checker_ = current_goal_checker;
364363
} else {
365-
action_server_->terminate_current();
366-
return;
364+
throw nav2_core::ControllerException("Failed to find goal checker name: " + gc_name);
367365
}
368366

369367
setPlannerPath(action_server_->get_current_goal()->path);
@@ -405,10 +403,47 @@ void ControllerServer::computeControl()
405403
controller_frequency_);
406404
}
407405
}
408-
} catch (nav2_core::PlannerException & e) {
409-
RCLCPP_ERROR(this->get_logger(), e.what());
406+
} catch (nav2_core::ControllerTFError & e) {
407+
RCLCPP_ERROR(this->get_logger(), "%s", e.what());
408+
publishZeroVelocity();
409+
std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
410+
result->error_code = Action::Goal::TF_ERROR;
411+
action_server_->terminate_current(result);
412+
return;
413+
} catch (nav2_core::NoValidControl & e) {
414+
RCLCPP_ERROR(this->get_logger(), "%s", e.what());
415+
publishZeroVelocity();
416+
std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
417+
result->error_code = Action::Goal::NO_VALID_CONTROL;
418+
action_server_->terminate_current(result);
419+
return;
420+
} catch (nav2_core::FailedToMakeProgress & e) {
421+
RCLCPP_ERROR(this->get_logger(), "%s", e.what());
422+
publishZeroVelocity();
423+
std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
424+
result->error_code = Action::Goal::FAILED_TO_MAKE_PROGRESS;
425+
action_server_->terminate_current(result);
426+
return;
427+
} catch (nav2_core::PatienceExceeded & e) {
428+
RCLCPP_ERROR(this->get_logger(), "%s", e.what());
429+
publishZeroVelocity();
430+
std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
431+
result->error_code = Action::Goal::PATIENCE_EXCEEDED;
432+
action_server_->terminate_current(result);
433+
return;
434+
} catch (nav2_core::InvalidPath & e) {
435+
RCLCPP_ERROR(this->get_logger(), "%s", e.what());
436+
publishZeroVelocity();
437+
std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
438+
result->error_code = Action::Goal::INVALID_PATH;
439+
action_server_->terminate_current(result);
440+
return;
441+
} catch (nav2_core::ControllerException & e) {
442+
RCLCPP_ERROR(this->get_logger(), "%s", e.what());
410443
publishZeroVelocity();
411-
action_server_->terminate_current();
444+
std::shared_ptr<Action::Result> result = std::make_shared<Action::Result>();
445+
result->error_code = Action::Goal::UNKNOWN;
446+
action_server_->terminate_current(result);
412447
return;
413448
}
414449

@@ -426,7 +461,7 @@ void ControllerServer::setPlannerPath(const nav_msgs::msg::Path & path)
426461
get_logger(),
427462
"Providing path to the controller %s", current_controller_.c_str());
428463
if (path.poses.empty()) {
429-
throw nav2_core::PlannerException("Invalid path, Path is empty.");
464+
throw nav2_core::InvalidPath("Path is empty.");
430465
}
431466
controllers_[current_controller_]->setPlan(path);
432467

@@ -446,11 +481,11 @@ void ControllerServer::computeAndPublishVelocity()
446481
geometry_msgs::msg::PoseStamped pose;
447482

448483
if (!getRobotPose(pose)) {
449-
throw nav2_core::PlannerException("Failed to obtain robot pose");
484+
throw nav2_core::ControllerTFError("Failed to obtain robot pose");
450485
}
451486

452487
if (!progress_checker_->check(pose)) {
453-
throw nav2_core::PlannerException("Failed to make progress");
488+
throw nav2_core::FailedToMakeProgress("Failed to make progress");
454489
}
455490

456491
nav_2d_msgs::msg::Twist2D twist = getThresholdedTwist(odom_sub_->getTwist());
@@ -464,7 +499,9 @@ void ControllerServer::computeAndPublishVelocity()
464499
nav_2d_utils::twist2Dto3D(twist),
465500
goal_checkers_[current_goal_checker_].get());
466501
last_valid_cmd_time_ = now();
467-
} catch (nav2_core::PlannerException & e) {
502+
// Only no valid control exception types are valid to attempt to have control patience, as
503+
// other types will not be resolved with more attempts
504+
} catch (nav2_core::NoValidControl & e) {
468505
if (failure_tolerance_ > 0 || failure_tolerance_ == -1.0) {
469506
RCLCPP_WARN(this->get_logger(), e.what());
470507
cmd_vel_2d.twist.angular.x = 0;
@@ -478,10 +515,10 @@ void ControllerServer::computeAndPublishVelocity()
478515
if ((now() - last_valid_cmd_time_).seconds() > failure_tolerance_ &&
479516
failure_tolerance_ != -1.0)
480517
{
481-
throw nav2_core::PlannerException("Controller patience exceeded");
518+
throw nav2_core::PatienceExceeded("Controller patience exceeded");
482519
}
483520
} else {
484-
throw nav2_core::PlannerException(e.what());
521+
throw nav2_core::NoValidControl(e.what());
485522
}
486523
}
487524

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) 2022. Joshua Wallace
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
#ifndef NAV2_CORE__CONTROLLER_EXCEPTIONS_HPP_
15+
#define NAV2_CORE__CONTROLLER_EXCEPTIONS_HPP_
16+
17+
#include <stdexcept>
18+
#include <string>
19+
20+
namespace nav2_core
21+
{
22+
23+
class ControllerException : public std::runtime_error
24+
{
25+
public:
26+
explicit ControllerException(const std::string & description)
27+
: std::runtime_error(description) {}
28+
};
29+
30+
class ControllerTFError : public ControllerException
31+
{
32+
public:
33+
explicit ControllerTFError(const std::string & description)
34+
: ControllerException(description) {}
35+
};
36+
37+
class FailedToMakeProgress : public ControllerException
38+
{
39+
public:
40+
explicit FailedToMakeProgress(const std::string & description)
41+
: ControllerException(description) {}
42+
};
43+
44+
class PatienceExceeded : public ControllerException
45+
{
46+
public:
47+
explicit PatienceExceeded(const std::string & description)
48+
: ControllerException(description) {}
49+
};
50+
51+
class InvalidPath : public ControllerException
52+
{
53+
public:
54+
explicit InvalidPath(const std::string & description)
55+
: ControllerException(description) {}
56+
};
57+
58+
class NoValidControl : public ControllerException
59+
{
60+
public:
61+
explicit NoValidControl(const std::string & description)
62+
: ControllerException(description) {}
63+
};
64+
65+
} // namespace nav2_core
66+
67+
#endif // NAV2_CORE__CONTROLLER_EXCEPTIONS_HPP_

nav2_core/include/nav2_core/exceptions.hpp renamed to nav2_core/include/nav2_core/planner_exceptions.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
* POSSIBILITY OF SUCH DAMAGE.
3434
*/
3535

36-
#ifndef NAV2_CORE__EXCEPTIONS_HPP_
37-
#define NAV2_CORE__EXCEPTIONS_HPP_
36+
#ifndef NAV2_CORE__PLANNER_EXCEPTIONS_HPP_
37+
#define NAV2_CORE__PLANNER_EXCEPTIONS_HPP_
3838

3939
#include <stdexcept>
4040
#include <string>
@@ -101,4 +101,4 @@ class PlannerTFError : public PlannerException
101101

102102
} // namespace nav2_core
103103

104-
#endif // NAV2_CORE__EXCEPTIONS_HPP_
104+
#endif // NAV2_CORE__PLANNER_EXCEPTIONS_HPP_

nav2_dwb_controller/dwb_core/include/dwb_core/exceptions.hpp

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,35 +34,23 @@
3434
#ifndef DWB_CORE__EXCEPTIONS_HPP_
3535
#define DWB_CORE__EXCEPTIONS_HPP_
3636

37-
#include <stdexcept>
3837
#include <string>
3938
#include <memory>
4039

41-
#include "nav2_core/exceptions.hpp"
40+
#include "nav2_core/controller_exceptions.hpp"
4241

4342
namespace dwb_core
4443
{
4544

46-
/**
47-
* @class PlannerTFException
48-
* @brief Thrown when the planner cannot complete its operation due to TF errors
49-
*/
50-
class PlannerTFException : public nav2_core::PlannerException
51-
{
52-
public:
53-
explicit PlannerTFException(const std::string description)
54-
: nav2_core::PlannerException(description) {}
55-
};
56-
5745
/**
5846
* @class IllegalTrajectoryException
5947
* @brief Thrown when one of the critics encountered a fatal error
6048
*/
61-
class IllegalTrajectoryException : public nav2_core::PlannerException
49+
class IllegalTrajectoryException : public nav2_core::ControllerException
6250
{
6351
public:
64-
IllegalTrajectoryException(const std::string critic_name, const std::string description)
65-
: nav2_core::PlannerException(description), critic_name_(critic_name) {}
52+
IllegalTrajectoryException(const std::string & critic_name, const std::string & description)
53+
: nav2_core::ControllerException(description), critic_name_(critic_name) {}
6654
std::string getCriticName() const {return critic_name_;}
6755

6856
protected:

nav2_dwb_controller/dwb_core/include/dwb_core/illegal_trajectory_tracker.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#include <utility>
4040
#include <string>
4141
#include "dwb_core/exceptions.hpp"
42-
#include "nav2_core/exceptions.hpp"
42+
#include "nav2_core/controller_exceptions.hpp"
4343

4444
namespace dwb_core
4545
{
@@ -66,11 +66,11 @@ class IllegalTrajectoryTracker
6666
* @brief Thrown when all the trajectories explored are illegal
6767
*/
6868
class NoLegalTrajectoriesException
69-
: public nav2_core::PlannerException
69+
: public nav2_core::ControllerException
7070
{
7171
public:
7272
explicit NoLegalTrajectoriesException(const IllegalTrajectoryTracker & tracker)
73-
: PlannerException(tracker.getMessage()),
73+
: ControllerException(tracker.getMessage()),
7474
tracker_(tracker) {}
7575
IllegalTrajectoryTracker tracker_;
7676
};

0 commit comments

Comments
 (0)