Skip to content

Commit c747df5

Browse files
Add toggle cm to simple commander API (#5559)
* Add toggle cm to simple comander API, fix default toggle cm service in test for consistency Signed-off-by: David G <[email protected]> * Fix pre commit, ament flake, add readme Signed-off-by: David G <[email protected]> * add toggle msg to __init__.py Signed-off-by: David G <[email protected]> * add error handling Signed-off-by: David G <[email protected]> * add error handling for clear costmap functions Signed-off-by: David G <[email protected]> --------- Signed-off-by: David G <[email protected]>
1 parent 645d09a commit c747df5

File tree

4 files changed

+56
-3
lines changed

4 files changed

+56
-3
lines changed

nav2_behavior_tree/test/plugins/action/test_toggle_collision_monitor_service.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ToggleCollisionMonitorService : public TestService<nav2_msgs::srv::Toggle>
2626
{
2727
public:
2828
ToggleCollisionMonitorService()
29-
: TestService("toggle_collision_monitor")
29+
: TestService("/collision_monitor/toggle")
3030
{}
3131
};
3232

@@ -105,7 +105,7 @@ TEST_P(ToggleParamTest, test_tick)
105105
R"(
106106
<root BTCPP_format="4">
107107
<BehaviorTree ID="MainTree">
108-
<ToggleCollisionMonitor service_name="toggle_collision_monitor" enable=")")
108+
<ToggleCollisionMonitor service_name="/collision_monitor/toggle" enable=")")
109109
+
110110
std::string(enable ? "true" : "false") +
111111
R"(" />

nav2_msgs/srv/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from nav2_msgs.srv._reload_dock_database import ReloadDockDatabase
1111
from nav2_msgs.srv._save_map import SaveMap
1212
from nav2_msgs.srv._set_initial_pose import SetInitialPose
13+
from nav2_msgs.srv._toggle import Toggle
1314

1415
__all__ = [
1516
'ClearCostmapAroundRobot',
@@ -24,4 +25,5 @@
2425
'ReloadDockDatabase',
2526
'SaveMap',
2627
'SetInitialPose',
28+
'Toggle',
2729
]

nav2_simple_commander/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ New as of September 2023: the simple navigator constructor will accept a `namesp
4040
| clearGlobalCostmap() | Clears the global costmap. |
4141
| getGlobalCostmap() | Returns the global costmap, `nav2_msgs/Costmap` |
4242
| getLocalCostmap() | Returns the local costmap, `nav2_msgs/Costmap` |
43+
| toggleCollisionMonitor(enable) | Toggles the collision monitor on (`True`) or off (`False`). |
4344
| waitUntilNav2Active(navigator='bt_navigator, localizer='amcl') | Blocks until Nav2 is completely online and lifecycle nodes are in the active state. To be used in conjunction with autostart or external lifecycle bringup. Custom navigator and localizer nodes can be specified |
4445
| lifecycleStartup() | Sends a request to all lifecycle management servers to bring them into the active state, to be used if autostart is `false` and you want this program to control Nav2's lifecycle. |
4546
| lifecycleShutdown() | Sends a request to all lifecycle management servers to shut them down. |

nav2_simple_commander/nav2_simple_commander/robot_navigator.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from nav2_msgs.msg import Route
3232
from nav2_msgs.srv import (ClearCostmapAroundPose, ClearCostmapAroundRobot,
3333
ClearCostmapExceptRegion, ClearEntireCostmap, GetCostmap, LoadMap,
34-
ManageLifecycleNodes)
34+
ManageLifecycleNodes, Toggle)
3535
from nav_msgs.msg import Goals, OccupancyGrid, Path
3636
import rclpy
3737
from rclpy.action import ActionClient
@@ -251,6 +251,11 @@ def __init__(self, node_name: str = 'basic_navigator', namespace: str = '') -> N
251251
self.create_client(
252252
GetCostmap, 'local_costmap/get_costmap'
253253
)
254+
self.toggle_collision_monitor_srv: Client[
255+
Toggle.Request, Toggle.Response] = \
256+
self.create_client(
257+
Toggle, 'collision_monitor/toggle'
258+
)
254259

255260
def destroyNode(self) -> None:
256261
self.destroy_node()
@@ -1056,6 +1061,11 @@ def clearLocalCostmap(self) -> None:
10561061
req = ClearEntireCostmap.Request()
10571062
future = self.clear_costmap_local_srv.call_async(req)
10581063
rclpy.spin_until_future_complete(self, future)
1064+
1065+
result = future.result()
1066+
if result is None:
1067+
self.error('Clear local costmap request failed!')
1068+
10591069
return
10601070

10611071
def clearGlobalCostmap(self) -> None:
@@ -1065,6 +1075,11 @@ def clearGlobalCostmap(self) -> None:
10651075
req = ClearEntireCostmap.Request()
10661076
future = self.clear_costmap_global_srv.call_async(req)
10671077
rclpy.spin_until_future_complete(self, future)
1078+
1079+
result = future.result()
1080+
if result is None:
1081+
self.error('Clear global costmap request failed!')
1082+
10681083
return
10691084

10701085
def clearCostmapExceptRegion(self, reset_distance: float) -> None:
@@ -1075,6 +1090,11 @@ def clearCostmapExceptRegion(self, reset_distance: float) -> None:
10751090
req.reset_distance = reset_distance
10761091
future = self.clear_costmap_except_region_srv.call_async(req)
10771092
rclpy.spin_until_future_complete(self, future)
1093+
1094+
result = future.result()
1095+
if result is None:
1096+
self.error('Clear costmap except region request failed!')
1097+
10781098
return
10791099

10801100
def clearCostmapAroundRobot(self, reset_distance: float) -> None:
@@ -1085,6 +1105,11 @@ def clearCostmapAroundRobot(self, reset_distance: float) -> None:
10851105
req.reset_distance = reset_distance
10861106
future = self.clear_costmap_around_robot_srv.call_async(req)
10871107
rclpy.spin_until_future_complete(self, future)
1108+
1109+
result = future.result()
1110+
if result is None:
1111+
self.error('Clear costmap around robot request failed!')
1112+
10881113
return
10891114

10901115
def clearLocalCostmapAroundPose(self, pose: PoseStamped, reset_distance: float) -> None:
@@ -1096,6 +1121,11 @@ def clearLocalCostmapAroundPose(self, pose: PoseStamped, reset_distance: float)
10961121
req.reset_distance = reset_distance
10971122
future = self.clear_local_costmap_around_pose_srv.call_async(req)
10981123
rclpy.spin_until_future_complete(self, future)
1124+
1125+
result = future.result()
1126+
if result is None:
1127+
self.error('Clear local costmap around pose request failed!')
1128+
10991129
return
11001130

11011131
def clearGlobalCostmapAroundPose(self, pose: PoseStamped, reset_distance: float) -> None:
@@ -1107,6 +1137,11 @@ def clearGlobalCostmapAroundPose(self, pose: PoseStamped, reset_distance: float)
11071137
req.reset_distance = reset_distance
11081138
future = self.clear_global_costmap_around_pose_srv.call_async(req)
11091139
rclpy.spin_until_future_complete(self, future)
1140+
1141+
result = future.result()
1142+
if result is None:
1143+
self.error('Clear global costmap around pose request failed!')
1144+
11101145
return
11111146

11121147
def getGlobalCostmap(self) -> OccupancyGrid:
@@ -1140,6 +1175,21 @@ def getLocalCostmap(self) -> OccupancyGrid:
11401175

11411176
return result.map
11421177

1178+
def toggleCollisionMonitor(self, enable: bool) -> None:
1179+
"""Toggle the collision monitor."""
1180+
while not self.toggle_collision_monitor_srv.wait_for_service(timeout_sec=1.0):
1181+
self.info('Toggle collision monitor service not available, waiting...')
1182+
req = Toggle.Request()
1183+
req.enable = enable
1184+
future = self.toggle_collision_monitor_srv.call_async(req)
1185+
1186+
rclpy.spin_until_future_complete(self, future)
1187+
result = future.result()
1188+
if result is None:
1189+
self.error('Toggle collision monitor request failed!')
1190+
1191+
return
1192+
11431193
def lifecycleStartup(self) -> None:
11441194
"""Startup nav2 lifecycle system."""
11451195
self.info('Starting up lifecycle nodes based on lifecycle_manager.')

0 commit comments

Comments
 (0)