Skip to content

Commit eab31d3

Browse files
committed
rviz launch file and new exrcise wrapper for physical robots
1 parent 6a968eb commit eab31d3

2 files changed

Lines changed: 199 additions & 0 deletions

File tree

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import json
2+
import logging
3+
import os.path
4+
import subprocess
5+
import sys
6+
import threading
7+
import time
8+
from threading import Thread
9+
10+
from src.manager.libs.applications.compatibility.client import Client
11+
from src.manager.libs.process_utils import stop_process_and_children
12+
from src.manager.ram_logging.log_manager import LogManager
13+
from src.manager.manager.application.robotics_python_application_interface import IRoboticsPythonApplication
14+
from src.manager.manager.lint.linter import Lint
15+
16+
17+
class CompatibilityExerciseWrapperRos2(IRoboticsPythonApplication):
18+
def __init__(self, exercise_command, gui_command, update_callback):
19+
super().__init__(update_callback)
20+
21+
home_dir = os.path.expanduser('~')
22+
self.running = False
23+
self.linter = Lint()
24+
self.brain_ready_event = threading.Event()
25+
# TODO: review hardcoded values
26+
process_ready, self.exercise_server = self._run_exercise_server(f"python3 {exercise_command}",
27+
f'{home_dir}/ws_code.log',
28+
'websocket_code=ready')
29+
if process_ready:
30+
LogManager.logger.info(
31+
f"Exercise code {exercise_command} launched")
32+
time.sleep(1)
33+
self.exercise_connection = Client(
34+
'ws://127.0.0.1:1905', 'exercise', self.server_message)
35+
self.exercise_connection.start()
36+
else:
37+
self.exercise_server.kill()
38+
raise RuntimeError(f"Exercise {exercise_command} could not be run")
39+
40+
process_ready, self.gui_server = self._run_exercise_server(f"python3 {gui_command}", f'{home_dir}/ws_gui.log',
41+
'websocket_gui=ready')
42+
if process_ready:
43+
LogManager.logger.info(f"Exercise gui {gui_command} launched")
44+
time.sleep(1)
45+
self.gui_connection = Client(
46+
'ws://127.0.0.1:2303', 'gui', self.server_message)
47+
self.gui_connection.start()
48+
else:
49+
self.gui_server.kill()
50+
raise RuntimeError(f"Exercise GUI {gui_command} could not be run")
51+
52+
self.running = True
53+
54+
self.start_send_freq_thread()
55+
56+
57+
def send_freq(self, exercise_connection, is_alive):
58+
"""Send the frequency of the brain and gui to the exercise server"""
59+
while is_alive():
60+
exercise_connection.send(
61+
"""#freq{"brain": 20, "gui": 10, "rtf": 100}""")
62+
time.sleep(1)
63+
64+
def start_send_freq_thread(self):
65+
"""Start a thread to send the frequency of the brain and gui to the exercise server"""
66+
daemon = Thread(target=lambda: self.send_freq(self.exercise_connection,
67+
lambda: self.is_alive), daemon=False, name='Monitor frequencies')
68+
daemon.start()
69+
70+
def _run_exercise_server(self, cmd, log_file, load_string, timeout: int = 5):
71+
process = subprocess.Popen(f"{cmd}", shell=True, stdout=sys.stdout, stderr=subprocess.STDOUT,
72+
bufsize=1024, universal_newlines=True)
73+
74+
process_ready = False
75+
while not process_ready:
76+
try:
77+
f = open(log_file, "r")
78+
if f.readline() == load_string:
79+
process_ready = True
80+
f.close()
81+
time.sleep(0.2)
82+
except Exception as e:
83+
LogManager.logger.debug(
84+
f"waiting for server string '{load_string}'...")
85+
time.sleep(0.2)
86+
87+
return process_ready, process
88+
89+
def server_message(self, name, message):
90+
if name == "gui": # message received from GUI server
91+
LogManager.logger.debug(
92+
f"Message received from gui: {message[:30]}")
93+
self._process_gui_message(message)
94+
elif name == "exercise": # message received from EXERCISE server
95+
if message.startswith("#exec"):
96+
self.brain_ready_event.set()
97+
LogManager.logger.info(
98+
f"Message received from exercise: {message[:40]}")
99+
self._process_exercise_message(message)
100+
101+
def _process_gui_message(self, message):
102+
payload = json.loads(message[4:])
103+
self.update_callback(payload)
104+
self.gui_connection.send("#ack")
105+
106+
def _process_exercise_message(self, message):
107+
comand = message[:5]
108+
if (message==comand):
109+
payload = comand
110+
else:
111+
payload = json.loads(message[5:])
112+
self.update_callback(payload)
113+
self.exercise_connection.send("#ack")
114+
115+
def run(self):
116+
self.exercise_connection.send("#play")
117+
118+
def stop(self):
119+
self.exercise_connection.send("#rest")
120+
121+
def resume(self):
122+
self.exercise_connection.send("#play")
123+
124+
def pause(self):
125+
self.exercise_connection.send("#stop")
126+
127+
def restart(self):
128+
# pause_cmd = "ros2 service call /restart_simulation std_srvs/srv/Empty"
129+
# subprocess.call(f"{pause_cmd}", shell=True, stdout=sys.stdout, stderr=subprocess.STDOUT, bufsize=1024,
130+
# universal_newlines=True)
131+
pass
132+
133+
@property
134+
def is_alive(self):
135+
return self.running
136+
137+
def load_code(self, code: str):
138+
errors = self.linter.evaluate_code(code)
139+
if errors == "":
140+
self.brain_ready_event.clear()
141+
self.exercise_connection.send(f"#code {code}")
142+
self.brain_ready_event.wait()
143+
else:
144+
raise Exception(errors)
145+
146+
def terminate(self):
147+
self.running = False
148+
self.exercise_connection.stop()
149+
self.gui_connection.stop()
150+
151+
stop_process_and_children(self.exercise_server)
152+
stop_process_and_children(self.gui_server)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from src.manager.manager.launcher.launcher_interface import ILauncher
2+
from src.manager.manager.docker_thread.docker_thread import DockerThread
3+
from src.manager.manager.vnc.vnc_server import Vnc_server
4+
import os
5+
import stat
6+
7+
class LauncherRvizRos2(ILauncher):
8+
display: str
9+
internal_port: str
10+
external_port: str
11+
running = False
12+
threads = []
13+
14+
def run(self, callback):
15+
DRI_PATH = os.path.join("/dev/dri", os.environ.get("DRI_NAME", "card0"))
16+
ACCELERATION_ENABLED = self.check_device(DRI_PATH)
17+
rviz_vnc = Vnc_server()
18+
19+
if ACCELERATION_ENABLED:
20+
rviz_vnc.start_vnc_gpu(self.display, self.internal_port, self.external_port, DRI_PATH)
21+
rviz_cmd = f"export DISPLAY=:0; export VGL_DISPLAY={DRI_PATH}; vglrun rviz2"
22+
else:
23+
rviz_vnc.start_vnc(self.display, self.internal_port, self.external_port)
24+
rviz_cmd = f"export DISPLAY=:0; rviz2"
25+
26+
rviz_thread = DockerThread(rviz_cmd)
27+
rviz_thread.start()
28+
self.threads.append(rviz_thread)
29+
self.running = True
30+
31+
def check_device(self, device_path):
32+
try:
33+
return stat.S_ISCHR(os.lstat(device_path)[stat.ST_MODE])
34+
except:
35+
return False
36+
37+
def is_running(self):
38+
return self.running
39+
40+
def terminate(self):
41+
for thread in self.threads:
42+
thread.terminate()
43+
thread.join()
44+
self.running = False
45+
46+
def died(self):
47+
pass

0 commit comments

Comments
 (0)