Skip to content

Commit 98bc88a

Browse files
authored
Merge pull request #283 from JdeRobot/update-robot-api
Add robot reset
2 parents 77d2995 + f72326b commit 98bc88a

16 files changed

Lines changed: 136 additions & 121 deletions

.github/workflows/python_lint.yaml

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,31 @@ name: Python Linting
44
on: [push]
55

66
jobs:
7-
black-lint:
8-
runs-on: ubuntu-latest
9-
name: Python black Lint
10-
steps:
11-
- uses: actions/checkout@v4
12-
- uses: psf/black@stable
13-
with:
14-
version: "22.3.0"
15-
# flake8-lint:
16-
# runs-on: ubuntu-latest
17-
# name: Python flake8 Lint
18-
# steps:
19-
# - name: Check out source repository
20-
# uses: actions/checkout@v3
21-
22-
# - name: Set up Python environment
23-
# uses: actions/setup-python@v4
24-
# with:
25-
# python-version: "3.11"
26-
27-
# - name: flake8 Lint
28-
# uses: py-actions/flake8@v2
29-
# with:
30-
# ignore: "E701,W503,E203"
31-
# exclude: "docs,.idea"
32-
# max-line-length: "88"
33-
# path: "."
34-
# plugins: "flake8-docstrings flake8-black"
7+
black-lint:
8+
runs-on: ubuntu-latest
9+
name: Python black Lint
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: psf/black@stable
13+
with:
14+
version: "26.5.1"
15+
# flake8-lint:
16+
# runs-on: ubuntu-latest
17+
# name: Python flake8 Lint
18+
# steps:
19+
# - name: Check out source repository
20+
# uses: actions/checkout@v3
21+
22+
# - name: Set up Python environment
23+
# uses: actions/setup-python@v4
24+
# with:
25+
# python-version: "3.11"
26+
27+
# - name: flake8 Lint
28+
# uses: py-actions/flake8@v2
29+
# with:
30+
# ignore: "E701,W503,E203"
31+
# exclude: "docs,.idea"
32+
# max-line-length: "88"
33+
# path: "."
34+
# plugins: "flake8-docstrings flake8-black"

robotics_application_manager/manager/launcher/launcher_console.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def pause(self):
4545
def unpause(self):
4646
pass
4747

48-
def reset(self):
48+
def reset(self, robot_entity=None):
4949
pass
5050

5151
def is_running(self):

robotics_application_manager/manager/launcher/launcher_gazebo.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""
22
Gazebo Classic Launcher and Lifecycle Manager.
33
4-
Handles the initialization, state management, and cleanup of the
5-
Gazebo GUI client (gzclient). Orchestrates display routing via
6-
VNC and provides hardware-accelerated rendering through VirtualGL
4+
Handles the initialization, state management, and cleanup of the
5+
Gazebo GUI client (gzclient). Orchestrates display routing via
6+
VNC and provides hardware-accelerated rendering through VirtualGL
77
when compatible DRI devices are detected.
88
"""
99

@@ -106,7 +106,7 @@ def unpause(self):
106106
"""Resumes the physics engine via the /unpause_physics ROS 2 service."""
107107
call_service("/unpause_physics", "std_srvs/srv/Empty")
108108

109-
def reset(self):
109+
def reset(self, robot_entity=None):
110110
call_service("/reset_world", "std_srvs/srv/Empty")
111111

112112
def is_running(self):

robotics_application_manager/manager/launcher/launcher_gzsim.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
from typing import List, Any
1414
from robotics_application_manager import LogManager
1515

16+
from gz.msgs10.world_control_pb2 import WorldControl
17+
from gz.msgs10.world_reset_pb2 import WorldReset
18+
from gz.msgs10.entity_pb2 import Entity
19+
from gz.msgs10.boolean_pb2 import Boolean
20+
from gz.transport13 import Node
21+
1622

1723
def call_gzservice(service, reqtype, reptype, timeout, req):
1824
command = f"gz service -s {service} --reqtype {reqtype} --reptype {reptype} --timeout {timeout} --req '{req}'"
@@ -150,20 +156,32 @@ def unpause(self):
150156
"pause: false",
151157
)
152158

153-
def reset(self):
159+
def reset(self, robot_entity=None):
154160
if is_ros_service_available("/drone0/platform/state_machine/_reset"):
155161
call_service(
156162
"/drone0/platform/state_machine/_reset",
157163
"std_srvs/srv/Trigger",
158164
"{}",
159165
)
160-
call_gzservice(
161-
"/world/default/control",
162-
"gz.msgs.WorldControl",
163-
"gz.msgs.Boolean",
164-
"3000",
165-
"reset: {all: true}",
166+
node = Node()
167+
168+
if robot_entity is not None:
169+
node.request(
170+
f"/world/default/remove",
171+
Entity(name=robot_entity, type=Entity.MODEL),
172+
Entity,
173+
Boolean,
174+
1000,
175+
)
176+
177+
node.request(
178+
f"/world/default/control",
179+
WorldControl(pause=True, reset=WorldReset(all=True)),
180+
WorldControl,
181+
Boolean,
182+
1000,
166183
)
184+
167185
if is_ros_service_available("/drone0/controller/_reset"):
168186
call_service("/drone0/controller/_reset", "std_srvs/srv/Trigger", "{}")
169187

robotics_application_manager/manager/launcher/launcher_o3de.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def unpause(self):
5050
self.running = True
5151
pass
5252

53-
def reset(self):
53+
def reset(self, robot_entity=None):
5454
# TODO: add reset
5555
pass
5656

robotics_application_manager/manager/launcher/launcher_robot.py

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,55 +13,20 @@
1313

1414
worlds = {
1515
"gazebo": {
16-
"1": [
17-
{
18-
"type": "module",
19-
"module": "ros_api",
20-
"parameters": [],
21-
"launch_file": [],
22-
}
23-
],
2416
"2": [
2517
{
26-
"type": "module",
18+
"type": "gazebo",
2719
"module": "robot_ros2_api",
2820
"parameters": [],
2921
"launch_file": [],
3022
}
3123
],
3224
},
33-
"drones": {
34-
"1": [
35-
{
36-
"type": "module",
37-
"module": "drones",
38-
"resource_folders": [],
39-
"model_folders": [],
40-
"plugin_folders": [],
41-
"parameters": [],
42-
"launch_file": [],
43-
}
44-
],
45-
"2": [
46-
{
47-
"type": "module",
48-
"module": "drones_ros2",
49-
"resource_folders": [],
50-
"model_folders": [],
51-
"plugin_folders": [],
52-
"parameters": [],
53-
"launch_file": [],
54-
}
55-
],
56-
},
57-
"gzsimdrones": {
25+
"gz": {
5826
"2": [
5927
{
60-
"type": "module",
61-
"module": "drones_gzsim",
62-
"resource_folders": [],
63-
"model_folders": [],
64-
"plugin_folders": [],
28+
"type": "gz",
29+
"module": "robot_ros2_api",
6530
"parameters": [],
6631
"launch_file": [],
6732
}
@@ -81,13 +46,17 @@ class LauncherRobot(BaseModel):
8146
launchers: Optional[ILauncher] = []
8247
start_pose: Optional[list] = []
8348

84-
def run(self, start_pose=None):
49+
def run(self, start_pose=None, extra_config=None):
8550
"""Run the robot launcher with an optional start pose."""
8651
if start_pose is not None:
8752
self.start_pose = start_pose
53+
54+
if extra_config is None:
55+
extra_config = ""
56+
8857
for module in worlds[self.type][str(self.ros_version)]:
8958
module["launch_file"] = self.launch_file_path
90-
launcher = self.launch_module(module)
59+
launcher = self.launch_module(module, extra_config)
9160
self.launchers.append(launcher)
9261
LogManager.logger.info(self.launchers)
9362

@@ -99,7 +68,7 @@ def terminate(self):
9968
launcher.terminate()
10069
self.launchers = []
10170

102-
def launch_module(self, configuration):
71+
def launch_module(self, configuration, extra_config=None):
10372
"""Launch a robot module based on the provided configuration."""
10473

10574
def process_terminated(name, exit_code):
@@ -117,7 +86,7 @@ def process_terminated(name, exit_code):
11786
launcher_class = get_class(launcher_module)
11887
launcher = launcher_class.from_config(launcher_class, configuration)
11988

120-
launcher.run(self.start_pose, process_terminated)
89+
launcher.run(self.start_pose, extra_config, process_terminated)
12190
return launcher
12291

12392
def launch_command(self, configuration):

robotics_application_manager/manager/launcher/launcher_robot_ros2_api.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,31 @@
99
)
1010
from robotics_application_manager.manager.docker_thread import DockerThread
1111
import subprocess
12+
import sys
1213

1314
import logging
15+
from robotics_application_manager import LogManager
16+
17+
18+
def call_service(service, service_type, request_data="{}"):
19+
command = f"ros2 service call {service} {service_type} '{request_data}'"
20+
try:
21+
p = subprocess.Popen(
22+
[
23+
f"{command}",
24+
],
25+
shell=True,
26+
stdout=sys.stdout,
27+
stderr=subprocess.STDOUT,
28+
bufsize=1024,
29+
universal_newlines=True,
30+
)
31+
p.wait(10)
32+
except:
33+
p.kill()
34+
35+
LogManager.logger.exception(f"Unable to complete call: {service}")
36+
raise Exception(f"Unable to complete call: {service}")
1437

1538

1639
class LauncherRobotRos2Api(ILauncher):
@@ -19,7 +42,7 @@ class LauncherRobotRos2Api(ILauncher):
1942
launch_file: str
2043
threads: List[Any] = []
2144

22-
def run(self, robot_pose, callback):
45+
def run(self, robot_pose, extra_config, callback):
2346
DRI_PATH = self.get_dri_path()
2447
ACCELERATION_ENABLED = self.check_device(DRI_PATH)
2548

@@ -30,12 +53,15 @@ def run(self, robot_pose, callback):
3053
xserver_thread.start()
3154
self.threads.append(xserver_thread)
3255

33-
ROBOT_POSE = f"ROBOT_X={robot_pose[0]} ROBOT_Y={robot_pose[1]} ROBOT_Z={robot_pose[2]} ROBOT_ROLL={robot_pose[3]} ROBOT_PITCH={robot_pose[4]} ROBOT_YAW={robot_pose[5]}"
56+
x, y, z, R, P, Y = robot_pose
57+
58+
if extra_config == "None":
59+
extra_config = ""
3460

3561
if ACCELERATION_ENABLED:
36-
exercise_launch_cmd = f"export VGL_DISPLAY={DRI_PATH}; vglrun {ROBOT_POSE} ros2 launch {self.launch_file}"
62+
exercise_launch_cmd = f"export VGL_DISPLAY={DRI_PATH}; vglrun ros2 launch {self.launch_file} x:={x} y:={y} z:={z} R:={R} P:={P} Y:={Y} {extra_config}"
3763
else:
38-
exercise_launch_cmd = f"{ROBOT_POSE} ros2 launch {self.launch_file}"
64+
exercise_launch_cmd = f"ros2 launch {self.launch_file} x:={x} y:={y} z:={z} R:={R} P:={P} Y:={Y} {extra_config}"
3965

4066
exercise_launch_thread = DockerThread(exercise_launch_cmd)
4167
exercise_launch_thread.start()
@@ -58,8 +84,7 @@ def terminate(self):
5884
universal_newlines=True,
5985
)
6086

61-
kill_cmd = "pkill -9 "
62-
cmd = kill_cmd + "bridg"
87+
cmd = kill_cmd + "bridge"
6388
subprocess.call(
6489
cmd,
6590
shell=True,

robotics_application_manager/manager/launcher/launcher_rviz.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def pause(self):
6868
def unpause(self):
6969
pass
7070

71-
def reset(self):
71+
def reset(self, robot_entity=None):
7272
pass
7373

7474
def is_running(self):

robotics_application_manager/manager/launcher/launcher_state_monitor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def pause(self):
4040
def unpause(self):
4141
pass
4242

43-
def reset(self):
43+
def reset(self, robot_entity=None):
4444
pass
4545

4646
def died(self):

robotics_application_manager/manager/launcher/launcher_tools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ def unpause(self):
131131
for launcher in self.launchers:
132132
launcher.unpause()
133133

134-
def reset(self):
134+
def reset(self, robot_entity=None):
135135
for launcher in self.launchers:
136-
launcher.reset()
136+
launcher.reset(robot_entity)
137137

138138
def pass_msg(self, data):
139139
for launcher in self.launchers:

0 commit comments

Comments
 (0)