Skip to content

Commit f959c3d

Browse files
authored
Merge pull request #217 from robotpy/run-romi-xrp
Add `robotpy run-romi` and `robotpy run-xrp` commands
2 parents 3d94355 + 64e053f commit f959c3d

4 files changed

Lines changed: 250 additions & 1 deletion

File tree

subprojects/robotpy-romi/pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@ authors = [
2020
license = "BSD-3-Clause"
2121
dependencies = [
2222
"robotpy-native-romi==2026.1.1b1",
23-
"wpilib==2026.1.1b1"
23+
"wpilib==2026.1.1b1",
24+
"robotpy-halsim-ws==2026.1.1b1",
2425
]
2526

2627
[project.urls]
2728
"Source code" = "https://github.com/robotpy/mostrobotpy"
2829

30+
[project.entry-points."robotpy_cli.2026"]
31+
run-romi = "romi.cli:RunRomi"
32+
2933

3034
[tool.hatch.build.hooks.robotpy]
3135
version_file = "romi/version.py"
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import argparse
2+
import importlib.metadata
3+
import os
4+
import sys
5+
import typing
6+
7+
import wpilib
8+
9+
10+
if sys.version_info < (3, 10):
11+
12+
def entry_points(group):
13+
eps = importlib.metadata.entry_points()
14+
return eps.get(group, [])
15+
16+
else:
17+
entry_points = importlib.metadata.entry_points
18+
19+
20+
def _int_env_default(name: str, fallback: int) -> int:
21+
value = os.environ.get(name)
22+
if value is None:
23+
return fallback
24+
try:
25+
return int(value)
26+
except ValueError:
27+
return fallback
28+
29+
30+
class RunRomi:
31+
"""
32+
Runs the robot using the HAL simulator connected to a ROMI
33+
"""
34+
35+
def __init__(self, parser: argparse.ArgumentParser):
36+
parser.add_argument(
37+
"--nogui",
38+
default=False,
39+
action="store_true",
40+
help="Don't use the WPILib simulation gui",
41+
)
42+
43+
sim_group = parser.add_argument_group("Additional simulation extensions")
44+
self.simexts = {}
45+
46+
for entry_point in entry_points(group="robotpy_sim.2026"):
47+
try:
48+
sim_ext_module = entry_point.load()
49+
except ImportError:
50+
print(f"WARNING: Error detected in {entry_point}")
51+
continue
52+
53+
self.simexts[entry_point.name] = sim_ext_module
54+
55+
try:
56+
if entry_point.name == "ws-client":
57+
cmd_help = argparse.SUPPRESS
58+
else:
59+
cmd_help = importlib.metadata.metadata(entry_point.dist.name)[
60+
"summary"
61+
]
62+
except AttributeError:
63+
cmd_help = "Load specified simulation extension"
64+
sim_group.add_argument(
65+
f"--{entry_point.name}",
66+
default=False,
67+
action="store_true",
68+
help=cmd_help,
69+
)
70+
71+
parser.add_argument(
72+
"--host",
73+
default=os.environ.get("HALSIMWS_HOST", "10.0.0.2"),
74+
help="ROMI websocket host (default: HALSIMWS_HOST or 10.0.0.2)",
75+
)
76+
parser.add_argument(
77+
"--port",
78+
type=int,
79+
default=_int_env_default("HALSIMWS_PORT", 3300),
80+
help="ROMI websocket port (default: HALSIMWS_PORT or 3300)",
81+
)
82+
83+
def run(
84+
self,
85+
options: argparse.Namespace,
86+
project_path: "os.PathLike[str]",
87+
robot_class: typing.Type[wpilib.RobotBase],
88+
):
89+
if "ws-client" not in self.simexts:
90+
print(
91+
"ws-client HALSim extension is missing. Reinstall robotpy-halsim-ws to use run-romi",
92+
file=sys.stderr,
93+
)
94+
return False
95+
96+
os.environ["HALSIMWS_HOST"] = options.host
97+
os.environ["HALSIMWS_PORT"] = str(options.port)
98+
99+
options.ws_client = True
100+
101+
if not options.nogui:
102+
try:
103+
import halsim_gui
104+
except ImportError:
105+
print("robotpy-halsim-gui is not installed!", file=sys.stderr)
106+
return False
107+
else:
108+
halsim_gui.loadExtension()
109+
110+
cwd = os.getcwd()
111+
112+
for name, module in self.simexts.items():
113+
if getattr(options, name.replace("-", "_"), False):
114+
try:
115+
module.loadExtension()
116+
except Exception:
117+
print(f"Error loading {name}!", file=sys.stderr)
118+
raise
119+
120+
os.chdir(cwd)
121+
return robot_class.main(robot_class)

subprojects/robotpy-xrp/pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ dependencies = [
2323
"wpilib==2026.1.1b1"
2424
]
2525

26+
[project.entry-points."robotpy_cli.2026"]
27+
run-xrp = "xrp.cli:RunXrp"
28+
2629
[project.entry-points."robotpy_sim.2026"]
2730
xrp = "xrp.extension"
2831

subprojects/robotpy-xrp/xrp/cli.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import argparse
2+
import importlib.metadata
3+
import os
4+
import sys
5+
import typing
6+
7+
import wpilib
8+
9+
10+
if sys.version_info < (3, 10):
11+
12+
def entry_points(group):
13+
eps = importlib.metadata.entry_points()
14+
return eps.get(group, [])
15+
16+
else:
17+
entry_points = importlib.metadata.entry_points
18+
19+
20+
def _int_env_default(name: str, fallback: int) -> int:
21+
value = os.environ.get(name)
22+
if value is None:
23+
return fallback
24+
try:
25+
return int(value)
26+
except ValueError:
27+
return fallback
28+
29+
30+
class RunXrp:
31+
"""
32+
Runs the robot using the HAL simulator connected to an XRP platform
33+
"""
34+
35+
def __init__(self, parser: argparse.ArgumentParser):
36+
parser.add_argument(
37+
"--nogui",
38+
default=False,
39+
action="store_true",
40+
help="Don't use the WPILib simulation gui",
41+
)
42+
43+
sim_group = parser.add_argument_group("Additional simulation extensions")
44+
self.simexts = {}
45+
46+
for entry_point in entry_points(group="robotpy_sim.2026"):
47+
try:
48+
sim_ext_module = entry_point.load()
49+
except ImportError:
50+
print(f"WARNING: Error detected in {entry_point}")
51+
continue
52+
53+
self.simexts[entry_point.name] = sim_ext_module
54+
55+
try:
56+
if entry_point.name == "xrp":
57+
cmd_help = argparse.SUPPRESS
58+
else:
59+
cmd_help = importlib.metadata.metadata(entry_point.dist.name)[
60+
"summary"
61+
]
62+
except AttributeError:
63+
cmd_help = "Load specified simulation extension"
64+
sim_group.add_argument(
65+
f"--{entry_point.name}",
66+
default=False,
67+
action="store_true",
68+
help=cmd_help,
69+
)
70+
71+
parser.add_argument(
72+
"--host",
73+
default=os.environ.get("HALSIMXRP_HOST", "192.168.42.1"),
74+
help="XRP host (default: HALSIMXRP_HOST or 192.168.42.1)",
75+
)
76+
parser.add_argument(
77+
"--port",
78+
type=int,
79+
default=_int_env_default("HALSIMXRP_PORT", 3540),
80+
help="XRP port (default: HALSIMXRP_PORT or 3540)",
81+
)
82+
83+
def run(
84+
self,
85+
options: argparse.Namespace,
86+
project_path: "os.PathLike[str]",
87+
robot_class: typing.Type[wpilib.RobotBase],
88+
):
89+
if "xrp" not in self.simexts:
90+
print(
91+
"robotpy-xrp HALSim extension is missing. Reinstall robotpy-xrp to use run-xrp.",
92+
file=sys.stderr,
93+
)
94+
return False
95+
96+
os.environ["HALSIMXRP_HOST"] = options.host
97+
os.environ["HALSIMXRP_PORT"] = str(options.port)
98+
99+
options.xrp = True
100+
101+
if not options.nogui:
102+
try:
103+
import halsim_gui
104+
except ImportError:
105+
print("robotpy-halsim-gui is not installed!", file=sys.stderr)
106+
return False
107+
else:
108+
halsim_gui.loadExtension()
109+
110+
cwd = os.getcwd()
111+
112+
for name, module in self.simexts.items():
113+
if getattr(options, name.replace("-", "_"), False):
114+
try:
115+
module.loadExtension()
116+
except Exception:
117+
print(f"Error loading {name}!", file=sys.stderr)
118+
raise
119+
120+
os.chdir(cwd)
121+
return robot_class.main(robot_class)

0 commit comments

Comments
 (0)