Skip to content

Commit bfd1f22

Browse files
authored
Use Exception Pointers in Locomotor (#47)
1 parent 15a7d21 commit bfd1f22

File tree

12 files changed

+270
-94
lines changed

12 files changed

+270
-94
lines changed

locomotor/doc/ErrorHandling.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ Let's take a precise look at what the error handling functions look like.
55
using PlannerExceptionCallback = std::function<void (nav_core2::PlannerException, const ros::Duration&)>;
66
```
77

8-
There are several standard extensions for the base `PlannerException` class in `nav_core2/exceptions.h`. When the function is called, you should be able to check the class of the exception against your known types and react accordingly. For instance,
8+
There are several standard extensions for the base `PlannerException` class in `nav_core2/exceptions.h` that will be passed as an exception pointer. When the function is called, you should be able to check the class of the exception against your known types and react accordingly. For instance,
99

1010
```
11-
void SomeStateMachine::onGlobalPlanningException(nav_core2::PlannerException e,
11+
void SomeStateMachine::onGlobalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr,
1212
const ros::Duration& planning_time)
1313
{
1414
try
1515
{
16-
throw e;
16+
std::rethrow_exception(e_ptr);
1717
}
1818
catch (nav_core2::OccupiedGoalException& e)
1919
{
@@ -33,12 +33,12 @@ void SomeStateMachine::onGlobalPlanningException(nav_core2::PlannerException e,
3333
Importantly, the individual planners can implement their own extensions of `PlannerException` and have their version of `StateMachine` handle it however they like.
3434

3535
```
36-
void LocomotorBrown::onGlobalPlanningException(nav_core2::PlannerException e,
36+
void LocomotorBrown::onGlobalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr,
3737
const ros::Duration& planning_time)
3838
{
3939
try
4040
{
41-
throw e;
41+
std::rethrow_exception(e_ptr);
4242
}
4343
catch (LocomotorBrown::TimeTravelException& e)
4444
{

locomotor/include/locomotor/locomotor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ namespace locomotor
5555
{
5656
// Callback Type Definitions
5757
using CostmapUpdateCallback = std::function<void (const ros::Duration&)>;
58-
using CostmapUpdateExceptionCallback = std::function<void (nav_core2::CostmapException, const ros::Duration&)>;
58+
using CostmapUpdateExceptionCallback = std::function<void (nav_core2::NavCore2ExceptionPtr, const ros::Duration&)>;
5959
using GlobalPlanCallback = std::function<void (const nav_2d_msgs::Path2D&, const ros::Duration&)>;
6060
using LocalPlanCallback = std::function<void (const nav_2d_msgs::Twist2DStamped&, const ros::Duration&)>;
61-
using PlannerExceptionCallback = std::function<void (nav_core2::PlannerException, const ros::Duration&)>;
61+
using PlannerExceptionCallback = std::function<void (nav_core2::NavCore2ExceptionPtr, const ros::Duration&)>;
6262
using NavigationCompleteCallback = std::function<void ()>;
6363
using NavigationFailureCallback = std::function<void (const locomotor_msgs::ResultCode)>;
6464

locomotor/src/double_thread_locomotor.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838

3939
namespace locomotor
4040
{
41+
using nav_core2::getResultCode;
42+
4143
/**
4244
* @class DoubleThreadLocomotor
4345
* @brief Connect the callbacks in Locomotor to do global and local planning on two separate timers
@@ -107,9 +109,9 @@ class DoubleThreadLocomotor
107109
std::bind(&DoubleThreadLocomotor::onGlobalPlanningException, this, std::placeholders::_1, std::placeholders::_2));
108110
}
109111

110-
void onGlobalCostmapException(nav_core2::CostmapException e, const ros::Duration& planning_time)
112+
void onGlobalCostmapException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
111113
{
112-
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::GLOBAL_COSTMAP, e.getResultCode(),
114+
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::GLOBAL_COSTMAP, getResultCode(e_ptr),
113115
"Global Costmap failure."));
114116
}
115117

@@ -128,10 +130,10 @@ class DoubleThreadLocomotor
128130
as_.publishFeedback(locomotor_.getNavigationState());
129131
}
130132

131-
void onGlobalPlanningException(nav_core2::PlannerException e, const ros::Duration& planning_time)
133+
void onGlobalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
132134
{
133135
ROS_ERROR_NAMED("Locomotor", "Global planning error. Giving up.");
134-
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::GLOBAL_PLANNER, e.getResultCode(),
136+
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::GLOBAL_PLANNER, getResultCode(e_ptr),
135137
"Global Planning Failure."));
136138
}
137139

@@ -150,9 +152,9 @@ class DoubleThreadLocomotor
150152
std::bind(&DoubleThreadLocomotor::onNavigationCompleted, this));
151153
}
152154

153-
void onLocalCostmapException(nav_core2::CostmapException e, const ros::Duration& planning_time)
155+
void onLocalCostmapException(nav_core2::CostmapException e_ptr, const ros::Duration& planning_time)
154156
{
155-
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::LOCAL_COSTMAP, e.getResultCode(),
157+
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::LOCAL_COSTMAP, getResultCode(e_ptr),
156158
"Local Costmap failure."));
157159
}
158160

@@ -168,7 +170,7 @@ class DoubleThreadLocomotor
168170
as_.publishFeedback(locomotor_.getNavigationState());
169171
}
170172

171-
void onLocalPlanningException(nav_core2::PlannerException e, const ros::Duration& planning_time)
173+
void onLocalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
172174
{
173175
ROS_WARN_NAMED("Locomotor", "Local planning error. Creating new global plan.");
174176
control_loop_timer_.stop();

locomotor/src/locomotor.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ void Locomotor::doCostmapUpdate(nav_core2::Costmap& costmap, Executor& result_ex
168168
}
169169
catch (const nav_core2::CostmapException& e)
170170
{
171-
if (fail_cb) result_ex.addCallback(std::bind(fail_cb, e, getTimeDiffFromNow(start_t)));
171+
if (fail_cb)
172+
result_ex.addCallback(std::bind(fail_cb, std::current_exception(), getTimeDiffFromNow(start_t)));
172173
}
173174
}
174175

@@ -188,7 +189,8 @@ void Locomotor::makeGlobalPlan(Executor& result_ex, GlobalPlanCallback cb, Plann
188189
// if we didn't get a plan and we are in the planning state (the robot isn't moving)
189190
catch (const nav_core2::PlannerException& e)
190191
{
191-
if (fail_cb) result_ex.addCallback(std::bind(fail_cb, e, getTimeDiffFromNow(start_t)));
192+
if (fail_cb)
193+
result_ex.addCallback(std::bind(fail_cb, std::current_exception(), getTimeDiffFromNow(start_t)));
192194
}
193195
}
194196

@@ -221,7 +223,8 @@ void Locomotor::makeLocalPlan(Executor& result_ex, LocalPlanCallback cb, Planner
221223
catch (const nav_core2::PlannerException& e)
222224
{
223225
lock.unlock();
224-
if (fail_cb) result_ex.addCallback(std::bind(fail_cb, e, getTimeDiffFromNow(start_t)));
226+
if (fail_cb)
227+
result_ex.addCallback(std::bind(fail_cb, std::current_exception(), getTimeDiffFromNow(start_t)));
225228
}
226229
}
227230
}

locomotor/src/single_thread_locomotor.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838

3939
namespace locomotor
4040
{
41+
using nav_core2::getResultCode;
42+
4143
/**
4244
* @class SingleThreadLocomotor
4345
* @brief Connect the callbacks in Locomotor to do global planning once and then local planning on a timer
@@ -96,9 +98,9 @@ class SingleThreadLocomotor
9698
std::bind(&SingleThreadLocomotor::onGlobalPlanningException, this, std::placeholders::_1, std::placeholders::_2));
9799
}
98100

99-
void onGlobalCostmapException(nav_core2::CostmapException e, const ros::Duration& planning_time)
101+
void onGlobalCostmapException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
100102
{
101-
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::GLOBAL_COSTMAP, e.getResultCode(),
103+
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::GLOBAL_COSTMAP, getResultCode(e_ptr),
102104
"Global Costmap failure."));
103105
}
104106

@@ -110,10 +112,10 @@ class SingleThreadLocomotor
110112
as_.publishFeedback(locomotor_.getNavigationState());
111113
}
112114

113-
void onGlobalPlanningException(nav_core2::PlannerException e, const ros::Duration& planning_time)
115+
void onGlobalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
114116
{
115117
ROS_ERROR_NAMED("Locomotor", "Global planning error. Giving up.");
116-
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::GLOBAL_PLANNER, e.getResultCode(),
118+
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::GLOBAL_PLANNER, getResultCode(e_ptr),
117119
"Global Planning Failure."));
118120
}
119121

@@ -132,9 +134,9 @@ class SingleThreadLocomotor
132134
std::bind(&SingleThreadLocomotor::onNavigationCompleted, this));
133135
}
134136

135-
void onLocalCostmapException(nav_core2::CostmapException e, const ros::Duration& planning_time)
137+
void onLocalCostmapException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
136138
{
137-
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::LOCAL_COSTMAP, e.getResultCode(),
139+
requestNavigationFailure(makeResultCode(locomotor_msgs::ResultCode::LOCAL_COSTMAP, getResultCode(e_ptr),
138140
"Local Costmap failure."));
139141
}
140142

@@ -150,7 +152,7 @@ class SingleThreadLocomotor
150152
as_.publishFeedback(locomotor_.getNavigationState());
151153
}
152154

153-
void onLocalPlanningException(nav_core2::PlannerException e, const ros::Duration& planning_time)
155+
void onLocalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
154156
{
155157
ROS_WARN_NAMED("Locomotor", "Local planning error. Creating new global plan.");
156158
control_loop_timer_.stop();

locomove_base/include/locomove_base/locomove_base.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,18 @@ class LocoMoveBase
6262
void requestGlobalCostmapUpdate();
6363

6464
void onGlobalCostmapUpdate(const ros::Duration& planning_time);
65-
void onGlobalCostmapException(nav_core2::CostmapException e, const ros::Duration& planning_time);
65+
void onGlobalCostmapException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time);
6666

6767
void onNewGlobalPlan(nav_2d_msgs::Path2D new_global_plan, const ros::Duration& planning_time);
68-
void onGlobalPlanningException(nav_core2::PlannerException e, const ros::Duration& planning_time);
68+
void onGlobalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time);
6969

7070
void controlLoopCallback(const ros::TimerEvent& event);
7171

7272
void onLocalCostmapUpdate(const ros::Duration& planning_time);
73-
void onLocalCostmapException(nav_core2::CostmapException e, const ros::Duration& planning_time);
73+
void onLocalCostmapException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time);
7474

7575
void onNewLocalPlan(nav_2d_msgs::Twist2DStamped new_command, const ros::Duration& planning_time);
76-
void onLocalPlanningException(nav_core2::PlannerException e, const ros::Duration& planning_time);
76+
void onLocalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time);
7777

7878
void onNavigationCompleted();
7979
void onNavigationFailure(const locomotor_msgs::ResultCode result);

locomove_base/src/locomove_base.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ void LocoMoveBase::onGlobalCostmapUpdate(const ros::Duration& planning_time)
281281
std::bind(&LocoMoveBase::onGlobalPlanningException, this, std::placeholders::_1, std::placeholders::_2));
282282
}
283283

284-
void LocoMoveBase::onGlobalCostmapException(nav_core2::CostmapException e, const ros::Duration& planning_time)
284+
void LocoMoveBase::onGlobalCostmapException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
285285
{
286286
// If the planner_frequency is non-zero, the costmap will attempt to update again on its own (via the Timer).
287287
// If it is zero, then we manually request a new update
@@ -311,7 +311,7 @@ void LocoMoveBase::onNewGlobalPlan(nav_2d_msgs::Path2D new_global_plan, const ro
311311
control_loop_timer_.start();
312312
}
313313

314-
void LocoMoveBase::onGlobalPlanningException(nav_core2::PlannerException e, const ros::Duration& planning_time)
314+
void LocoMoveBase::onGlobalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
315315
{
316316
if (has_global_plan_)
317317
{
@@ -352,7 +352,7 @@ void LocoMoveBase::onLocalCostmapUpdate(const ros::Duration& planning_time)
352352
std::bind(&LocoMoveBase::onNavigationCompleted, this));
353353
}
354354

355-
void LocoMoveBase::onLocalCostmapException(nav_core2::CostmapException e, const ros::Duration& planning_time)
355+
void LocoMoveBase::onLocalCostmapException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
356356
{
357357
ROS_WARN_NAMED("LocoMoveBase",
358358
"Sensor data is out of date, we're not going to allow commanding of the base for safety");
@@ -394,7 +394,7 @@ void LocoMoveBase::onNewLocalPlan(nav_2d_msgs::Twist2DStamped new_command, const
394394
server_.publishFeedback(feedback);
395395
}
396396

397-
void LocoMoveBase::onLocalPlanningException(nav_core2::PlannerException e, const ros::Duration& planning_time)
397+
void LocoMoveBase::onLocalPlanningException(nav_core2::NavCore2ExceptionPtr e_ptr, const ros::Duration& planning_time)
398398
{
399399
// check if we've tried to find a valid control for longer than our time limit
400400
if (ros::Time::now() > last_valid_control_ + ros::Duration(controller_patience_))

nav_core2/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ if(CATKIN_ENABLE_TESTING)
2727
roslint_add_test()
2828

2929
catkin_add_gtest(bounds_test test/bounds_test.cpp)
30+
catkin_add_gtest(exception_test test/exception_test.cpp)
3031
endif()
3132

3233
install(DIRECTORY include/${PROJECT_NAME}/

nav_core2/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Now let's compare the old [nav_core::BaseLocalPlanner](https://github.com/ros-pl
4646
## Exceptions
4747
A hierarchical collection of [exceptions](include/nav_core2/exceptions.h) is provided to allow for reacting to navigation failures in a more robust and contextual way.
4848
![exception hierarchy tree](doc/exceptions.png)
49-
Each exception has a corresponding integer "result code" that can be used in ROS interfaces where passing the C++ object is infeasible.
49+
Each exception has a corresponding integer "result code" that can be used in ROS interfaces where passing the C++ object is infeasible. Note that due to the hierarchy, the result_code will be for the child-most exception. For example, if you throw a `StartBoundsException` which has a corresponding result code of `6`, it could also be seen as a `InvalidStartPoseException`, `GlobalPlannerException`, `PlannerException` or `NavCore2Exception`, all of which would also have the result code of `6`.
5050

5151
## Bounds
5252
For use in tracking `Costmap` changes and more, this package also provides an implementation of [bounding boxes](include/nav_core2/bounds.h). These are represented with the ranges `[min_x, max_x]` and `[min_y, max_y]` (inclusive).

nav_core2/doc/exceptions.png

697 Bytes
Loading

0 commit comments

Comments
 (0)