Skip to content

Commit 6deb31b

Browse files
committed
ros for multiplanner jaeyoun local
2 parents 73bb385 + ffff6b1 commit 6deb31b

File tree

9 files changed

+312
-136
lines changed

9 files changed

+312
-136
lines changed

omniplanner/examples/pddl_example.py

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import logging
2-
from importlib.resources import as_file, files
32

4-
import dsg_pddl.domains
53
import numpy as np
64
import spark_dsg
75
from dsg_pddl.pddl_grounding import PddlDomain, PddlGoal
86
from ruamel.yaml import YAML
9-
from utils import DummyRobotPlanningAdaptor
7+
from utils import DummyRobotPlanningAdaptor, load_omniplanner_pddl_domain
108

119
from omniplanner.compile_plan import collect_plans
1210
from omniplanner.omniplanner import PlanRequest, full_planning_pipeline
@@ -22,7 +20,7 @@
2220
# goal = PddlGoal(robot_id="euclid", pddl_goal="(and (visited-object o0) (visited-object o1))")
2321
# goal = PddlGoal(robot_id="euclid", pddl_goal="(object-in-place o1 p0)")
2422
G = spark_dsg.DynamicSceneGraph.load(
25-
"/home/ubuntu/lxc_datashare/west_point_fused_map_wregions_labelspace.json"
23+
"/home/jaeyoun-choi/colcon_ws/assets/west_point_fused_map_wregions_labelspace.json"
2624
)
2725

2826

@@ -43,10 +41,7 @@
4341
)
4442

4543
# Load the PDDL domain you want to use
46-
with as_file(files(dsg_pddl.domains).joinpath("GotoObjectDomain.pddl")) as path:
47-
print(f"Loading domain {path}")
48-
with open(str(path), "r") as fo:
49-
domain = PddlDomain(fo.read())
44+
domain = PddlDomain(load_omniplanner_pddl_domain("GotoObjectDomain.pddl"))
5045

5146

5247
# Build the plan request
@@ -62,7 +57,7 @@
6257
print("Plan from planning domain:")
6358
print(plan)
6459

65-
compiled_plan = compile_plan(adaptors, plan)
60+
compiled_plan = compile_plan(adaptors, "map", plan)
6661
print(compiled_plan)
6762

6863
collected_plans = collect_plans(compiled_plan)
@@ -77,12 +72,7 @@
7772
goal = PddlGoal(robot_id="euclid", pddl_goal="(and (object-in-place o94 p2157))")
7873

7974
# Load the PDDL domain you want to use
80-
with as_file(
81-
files(dsg_pddl.domains).joinpath("ObjectRearrangementDomain.pddl")
82-
) as path:
83-
print(f"Loading domain {path}")
84-
with open(str(path), "r") as fo:
85-
domain = PddlDomain(fo.read())
75+
domain = PddlDomain(load_omniplanner_pddl_domain("ObjectRearrangementDomain.pddl"))
8676

8777

8878
# Build the plan request
@@ -98,7 +88,7 @@
9888
print("Plan from planning domain:")
9989
print(plan)
10090

101-
collected_plan = collect_plans(compile_plan(adaptors, plan))
91+
collected_plan = collect_plans(compile_plan(adaptors, "map", plan))
10292
print("collected plan: ", collected_plan)
10393

10494

@@ -117,12 +107,9 @@
117107
)
118108

119109
# Load the PDDL domain you want to use
120-
with as_file(
121-
files(dsg_pddl.domains).joinpath("RegionObjectRearrangementDomain.pddl")
122-
) as path:
123-
print(f"Loading domain {path}")
124-
with open(str(path), "r") as fo:
125-
domain = PddlDomain(fo.read())
110+
domain = PddlDomain(
111+
load_omniplanner_pddl_domain("RegionObjectRearrangementDomain.pddl")
112+
)
126113

127114

128115
# Build the plan request
@@ -139,5 +126,5 @@
139126
print(plan)
140127

141128

142-
collected_plan = collect_plans(compile_plan(adaptors, plan))
129+
collected_plan = collect_plans(compile_plan(adaptors, "map", plan))
143130
print("collected plan: ", collected_plan)

omniplanner/examples/pddl_example_multirobot_FD_ominiplanner.py

Lines changed: 93 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,25 @@
44
Follows the exact format you wanted using existing infrastructure
55
"""
66

7-
import sys
7+
import logging
88

99
import numpy as np
1010
import spark_dsg
1111
from dsg_pddl.pddl_grounding import MultiRobotPddlDomain, PddlGoal
12+
from utils import DummyRobotPlanningAdaptor, load_omniplanner_pddl_domain
1213

14+
from omniplanner.compile_plan import collect_plans
1315
from omniplanner.omniplanner import PlanRequest, full_planning_pipeline
16+
from omniplanner_ros.pddl_planner_ros import compile_plan
1417

15-
multi_robot_path = (
16-
"/home/jaeyoun-choi/colcon_ws/src/awesome_dcist_t4/omniplanner/omniplanner/src"
17-
)
18-
if multi_robot_path not in sys.path:
19-
sys.path.insert(0, multi_robot_path)
18+
logging.basicConfig(level=logging.DEBUG, force=True)
19+
20+
21+
# multi_robot_path = (
22+
# "/home/ubuntu/lxc_datashare/heracles_evaluation_dsg_data/"
23+
# )
24+
# if multi_robot_path not in sys.path:
25+
# sys.path.insert(0, multi_robot_path)
2026

2127

2228
def extract_plan_from_wrapper(plan):
@@ -215,77 +221,87 @@ def print_places_in_region(G, region_symbol: str):
215221
print(f" Error listing places for {region_symbol}: {e}")
216222

217223

218-
def main():
219-
"""Main test function following your exact format"""
220-
print("Multi-Robot Fast Downward Test with Real Scene Graph")
221-
print("=" * 80)
222-
223-
# Configuration
224-
# scene_graph_path = "./src/awesome_dcist_t4/omniplanner/omniplanner/examples/scenegraph/west_point_fused_map_wregions_labelspace.json"
225-
scene_graph_path = "/home/jaeyoun-choi/colcon_ws/assets/b45_clip_final_connected_rooms_and_labelspace.json"
226-
# scene_graph_path = "/home/jaeyoun-choi/colcon_ws/assets/west_point_fused_map_wregions_labelspace.json"
227-
# robot_ids = ["robot1","robot2"]
228-
robot_ids = ["robot1", "robot2", "robot3"]
229-
230-
print(f"Scene graph: {scene_graph_path}")
231-
print(f"Robots: {robot_ids}")
232-
233-
# Load scene graph
234-
print(f"Loading scene graph from: {scene_graph_path}")
235-
G = spark_dsg.DynamicSceneGraph.load(scene_graph_path)
236-
print(f"✓ Scene graph loaded: {G.num_nodes()} total nodes")
237-
238-
# Examine scene graph coordinates
239-
examine_scene_graph_coordinates(G)
240-
# Print existing region kinds
241-
242-
print_region_kinds(G)
243-
# Print region names
244-
print_region_names(G)
245-
# Print places included in specific regions of interest
246-
# print_places_in_region(G, "r68")
247-
print_places_in_region(G, "r3")
248-
print_places_in_region(G, "r4")
249-
250-
# Create robot poses (following your format)
251-
robot_poses = {
252-
"robot1": np.array([-15.0, -15.1]),
253-
"robot2": np.array([-15.0, 0.1]),
254-
"robot3": np.array([0.0, 6.0]),
255-
}
256-
257-
print("=========================================")
258-
print("==== PDDL region Domain (Multi-Robot) ====")
259-
print("=========================================")
260-
print("")
261-
262-
# goal_string ="(and (safe o2)(safe o3))"
263-
goal_string = "(and (explored-region r1)(explored-region r2)(visited-object o2)(visited-object o9)(visited-place p22543)(visited-place p6255))"
264-
goal_string = "(and (in-region robot1 r2) (visited-object o79)(visited-object o285)(visited-object o43)(safe o79)(explored-region r2)(visited-object o2)(visited-object o9)(visited-place p22543)(visited-place p6255))"
265-
# goal_string ="(and (visited-poi o27))"
266-
# goal_string ="(and (object-in-place o5 p91) (object-in-place o85 p118) )"
267-
# goal_string ="(and (object-in-place o5 p91) (object-in-place o94 p2157))"
268-
# goal_string ="(and (safe o2))"
269-
# goal_string ="(and (object-in-place o5 p91) (object-in-place o85 p118) (object-in-place o94 p2157))"
270-
goal = PddlGoal(robot_id="robot1", pddl_goal=goal_string)
271-
272-
# Load the multi-robot domain
273-
domain_path = "./src/awesome_dcist_t4/omniplanner/omniplanner/src/dsg_pddl/domains/RegionObjectRearrangementDomain_MultiRobot_FD_Explore.pddl"
274-
with open(domain_path, "r") as fo:
275-
domain = MultiRobotPddlDomain(fo.read())
276-
277-
# print(f"Loading domain {domain_path}")
278-
# print(f"Domain name: {domain.domain_name}")
279-
req = PlanRequest(
280-
domain=domain,
281-
goal=goal,
282-
robot_states=robot_poses,
224+
"""Main test function following your exact format"""
225+
print("Multi-Robot Fast Downward Test with Real Scene Graph")
226+
print("=" * 80)
227+
228+
# Configuration
229+
# scene_graph_path = "./src/awesome_dcist_t4/omniplanner/omniplanner/examples/scenegraph/west_point_fused_map_wregions_labelspace.json"
230+
scene_graph_path = "/home/jaeyoun-choi/colcon_ws/assets/b45_clip_final_connected_rooms_and_labelspace.json"
231+
# scene_graph_path = "/home/jaeyoun-choi/colcon_ws/assets/west_point_fused_map_wregions_labelspace.json"
232+
# robot_ids = ["robot1","robot2"]
233+
robot_ids = ["robot1", "robot2", "robot3"]
234+
235+
print(f"Scene graph: {scene_graph_path}")
236+
print(f"Robots: {robot_ids}")
237+
238+
# Load scene graph
239+
print(f"Loading scene graph from: {scene_graph_path}")
240+
G = spark_dsg.DynamicSceneGraph.load(scene_graph_path)
241+
print(f"✓ Scene graph loaded: {G.num_nodes()} total nodes")
242+
243+
# Examine scene graph coordinates
244+
examine_scene_graph_coordinates(G)
245+
# Print existing region kinds
246+
247+
print_region_kinds(G)
248+
# Print region names
249+
print_region_names(G)
250+
# Print places included in specific regions of interest
251+
# print_places_in_region(G, "r68")
252+
print_places_in_region(G, "r3")
253+
print_places_in_region(G, "r4")
254+
255+
# Create robot poses (following your format)
256+
robot_poses = {
257+
"ROBOT1": np.array([-15.0, -15.1]),
258+
"ROBOT2": np.array([-15.0, 0.1]),
259+
"ROBOT3": np.array([0.0, 6.0]),
260+
}
261+
262+
print("=========================================")
263+
print("==== PDDL region Domain (Multi-Robot) ====")
264+
print("=========================================")
265+
print("")
266+
267+
# goal_string ="(and (safe o2)(safe o3))"
268+
goal_string = "(and (explored-region r1)(explored-region r2)(visited-object o2)(visited-object o9)(visited-place p22543)(visited-place p6255))"
269+
goal_string = "(and (visited-object o79)(visited-object o285)(visited-object o43)(safe o79)(explored-region r2)(visited-object o2)(visited-object o9)(visited-place p22543)(visited-place p6255))"
270+
# goal_string ="(and (visited-poi o27))"
271+
# goal_string ="(and (object-in-place o5 p91) (object-in-place o85 p118) )"
272+
# goal_string ="(and (object-in-place o5 p91) (object-in-place o94 p2157))"
273+
# goal_string ="(and (safe o2))"
274+
# goal_string ="(and (object-in-place o5 p91) (object-in-place o85 p118) (object-in-place o94 p2157))"
275+
goal = PddlGoal(robot_id="robot1", pddl_goal=goal_string)
276+
277+
# Load the multi-robot domain
278+
domain = MultiRobotPddlDomain(
279+
load_omniplanner_pddl_domain(
280+
"RegionObjectRearrangementDomain_MultiRobot_FD_Explore.pddl"
283281
)
284-
# Automatically generate a multi-robot PDDL problem from DSG (first pass to discover objects)
285-
# pddl_start_time = time.time()
286-
full_planning_pipeline(req, G)
287-
# actual_plan = extract_plan_from_wrapper(plan)
282+
)
288283

289284

290-
if __name__ == "__main__":
291-
main()
285+
# print(f"Loading domain {domain_path}")
286+
# print(f"Domain name: {domain.domain_name}")
287+
req = PlanRequest(
288+
domain=domain,
289+
goal=goal,
290+
robot_states=robot_poses,
291+
)
292+
# Automatically generate a multi-robot PDDL problem from DSG (first pass to discover objects)
293+
# pddl_start_time = time.time()
294+
plan = full_planning_pipeline(req, G)
295+
print("Symbolic Plan:")
296+
for a in plan.value.value.symbolic_actions:
297+
print(a)
298+
299+
adaptor1 = DummyRobotPlanningAdaptor("euclid", "spot", "map", "euclid/body")
300+
adaptor2 = DummyRobotPlanningAdaptor("hamilton", "spot", "map", "hamilton/body")
301+
adaptor3 = DummyRobotPlanningAdaptor("gauss", "husky", "map", "husky/body")
302+
adaptors = {"ROBOT1": adaptor1, "ROBOT2": adaptor2, "ROBOT3": adaptor3}
303+
304+
compiled_plans = compile_plan(adaptors, "map", plan)
305+
306+
collected_plan = collect_plans(compile_plan(adaptors, "map", plan))
307+
print("collected plan: ", collected_plan)

omniplanner/examples/utils.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
from dataclasses import dataclass
2+
from importlib.resources import as_file, files
23

4+
import dsg_pddl.domains
35
import numpy as np
46
import spark_dsg
57

68

9+
def load_omniplanner_pddl_domain(domain_name):
10+
with as_file(files(dsg_pddl.domains).joinpath(domain_name)) as path:
11+
print(f"Loading domain {path}")
12+
with open(str(path), "r") as fo:
13+
domain = fo.read()
14+
return domain
15+
16+
717
@dataclass
818
class DummyRobotPlanningAdaptor:
919
name: str

omniplanner/src/dsg_pddl/dsg_pddl_grounding_Multirobot_Better.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
PddlSymbol,
2828
)
2929
from dsg_pddl.pddl_utils import lisp_string_to_ast
30-
from omniplanner.omniplanner import RobotWrapper
30+
from omniplanner.omniplanner import MultiRobotWrapper
3131
from omniplanner.tsp import LayerPlanner
3232

3333
logger = logging.getLogger(__name__)
@@ -366,9 +366,10 @@ def ground_problem(
366366
robot_states: dict,
367367
goal: PddlGoal,
368368
feedback: Any = None,
369-
) -> RobotWrapper[GroundedPddlProblem]:
369+
) -> MultiRobotWrapper[GroundedPddlProblem]:
370370
logger.info(f"Grounding PDDL Problem {domain.domain_name}")
371371

372+
pddl_compliant_robot_states = {k.lower(): v for k, v in robot_states.items()}
372373
match domain.domain_name:
373374
# case "goto-object-domain-multirobot-fd":
374375
# pddl_problem, symbols = generate_multirobot_inspection_pddl(
@@ -377,14 +378,25 @@ def ground_problem(
377378

378379
case "region-object-rearrangement-domain-multirobot-fd":
379380
pddl_problem, symbols = generate_multirobot_region_pddl(
380-
dsg, goal.pddl_goal, robot_states
381+
dsg, goal.pddl_goal, pddl_compliant_robot_states
381382
)
382383
case _:
383384
raise NotImplementedError(
384385
f"I don't know how to ground a domain of type {domain.domain_name}!"
385386
)
386387

387388
symbol_dict = {s.symbol: s for s in symbols}
388-
return RobotWrapper(
389-
goal.robot_id, GroundedPddlProblem(domain, pddl_problem, symbol_dict)
389+
390+
# TODO: We don't actually want to rely on the robot_states, because
391+
# robot_states may contain information about robots we actually don't care
392+
# about for planning purposes. Instead, we probably want this information
393+
# passed as part of the goal.
394+
395+
names = list(robot_states.keys())
396+
wrapper = MultiRobotWrapper(
397+
names, GroundedPddlProblem(domain, pddl_problem, symbol_dict)
390398
)
399+
for outer_name in robot_states.keys():
400+
inner_name = outer_name.lower()
401+
wrapper.set_name_remap(outer_name, inner_name)
402+
return wrapper

omniplanner/src/dsg_pddl/dsg_pddl_planning.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import spark_dsg
1010
from plum import dispatch
1111

12-
from dsg_pddl.dsg_pddl_grounding import GroundedPddlProblem, PddlSymbol
12+
from dsg_pddl.dsg_pddl_grounding import GroundedPddlProblem, PddlDomain, PddlSymbol
1313
from dsg_pddl.pddl_utils import lisp_string_to_ast
1414
from omniplanner.tsp import LayerPlanner
1515

@@ -18,6 +18,7 @@
1818

1919
@dataclass
2020
class PddlPlan:
21+
domain: PddlDomain
2122
symbolic_actions: List[tuple]
2223
parameterized_actions: List
2324
symbols: Dict[str, PddlSymbol]
@@ -108,4 +109,6 @@ def make_plan(grounded_problem: GroundedPddlProblem, map_context: Any) -> PddlPl
108109
f"Plan contains {p[0]} action, but I don't know how to parameterize!"
109110
)
110111

111-
return PddlPlan(plan, parameterized_plan, grounded_problem.symbols)
112+
return PddlPlan(
113+
grounded_problem.domain, plan, parameterized_plan, grounded_problem.symbols
114+
)

omniplanner/src/dsg_pddl/pddl_grounding.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,8 @@ def to_string(self):
130130
return ast_to_string(self.domain_ast)
131131

132132

133-
class MultiRobotPddlDomain:
134-
def __init__(self, domain_str):
135-
self.domain_ast = lisp_string_to_ast(domain_str)
136-
self.domain_name = get_domain_name(self.domain_ast)
137-
self.requirements = get_domain_requirements(self.domain_ast)
138-
self.get_domain_types = get_domain_types(self.domain_ast)
139-
self.predicates = get_domain_predicates(self.domain_ast)
140-
self.functions = get_functions(self.domain_ast)
141-
self.derived = get_derived(self.domain_ast)
142-
self.actions = get_actions(self.domain_ast)
143-
144-
def to_string(self):
145-
return ast_to_string(self.domain_ast)
133+
class MultiRobotPddlDomain(PddlDomain):
134+
pass
146135

147136

148137
def get_domain_name(ast):

0 commit comments

Comments
 (0)