@@ -33,19 +33,24 @@ def plan(grid: Grid, start_and_goals: list[StartAndGoal], single_agent_planner_c
3333
3434 initial_solution : dict [AgentId , NodePath ] = {}
3535
36- # Reserve initial positions
36+ # Generate initial solution (no reservations for robots)
3737 for agent_idx , start_and_goal in enumerate (start_and_goals ):
38- # grid.reserve_position(start_and_goal.start, start_and_goal.index, Interval(0, 10))
3938 path = single_agent_planner_class .plan (grid , start_and_goal .start , start_and_goal .goal , agent_idx , verbose )
4039 initial_solution [AgentId (agent_idx )] = path
4140
41+ # for (agent_idx, path) in initial_solution.items():
42+ # print(f"\nAgent {agent_idx} path:\n {path}")
43+
4244 constraint_tree = ConstraintTree (initial_solution )
4345
46+ attempted_constraint_combos = set ()
47+
4448 while constraint_tree .nodes_to_expand :
4549 constraint_tree_node = constraint_tree .get_next_node_to_expand ()
4650 ancestor_constraints = constraint_tree .get_ancestor_constraints (constraint_tree_node .parent_idx )
47- print (f"Expanded node: { constraint_tree_node .constraint } with parent: { constraint_tree_node .parent_idx } " )
48- print (f"\t Ancestor constraints: { ancestor_constraints } " )
51+
52+ # print(f"Expanded node: {constraint_tree_node.constraint} with parent: {constraint_tree_node.parent_idx}")
53+ # print(f"\tAncestor constraints: {ancestor_constraints}")
4954
5055 if verbose :
5156 print (f"Expanding node with constraint { constraint_tree_node .constraint } and parent { constraint_tree_node .parent_idx } " )
@@ -66,48 +71,96 @@ def plan(grid: Grid, start_and_goals: list[StartAndGoal], single_agent_planner_c
6671 if verbose :
6772 print (f"\n Outer loop step for agent { constrained_agent } " )
6873
69- applied_constraint = AppliedConstraint (constraint_tree_node .constraint .constraint , constrained_agent )
70- all_constraints = deepcopy (ancestor_constraints )
74+ applied_constraint = AppliedConstraint (constrained_agent .constraint , constrained_agent .agent )
75+
76+ # TODO: check type of other constraints somewhere
77+ all_constraints = deepcopy (ancestor_constraints ) # TODO - no deepcopy pls
7178 all_constraints .append (applied_constraint )
7279
80+ # Skip if we have already tried this set of constraints
81+ constraint_hash = hash (frozenset (all_constraints ))
82+ if constraint_hash in attempted_constraint_combos :
83+ break
84+ else :
85+ attempted_constraint_combos .add (constraint_hash )
86+
7387 if verbose :
7488 print (f"\t all constraints: { all_constraints } " )
7589
7690 grid .clear_constraint_points ()
7791 grid .apply_constraint_points (all_constraints )
7892
93+ failed_to_plan = False
7994 for agent_idx , start_and_goal in enumerate (start_and_goals ):
80- path = single_agent_planner_class .plan (grid , start_and_goal .start , start_and_goal .goal , agent_idx , verbose )
95+ # print("planning for:", agent_idx)
96+ try :
97+ path = single_agent_planner_class .plan (grid , start_and_goal .start , start_and_goal .goal , agent_idx , verbose )
98+ except Exception as e :
99+ print (f"Failed to plan with constraints: { all_constraints } " )
100+ failed_to_plan = True
101+
81102 if path is None :
82103 raise RuntimeError (f"Failed to find path for { start_and_goal } " )
83104 paths [AgentId (start_and_goal .index )] = path
84105
106+ if failed_to_plan :
107+ print (f"Failed to plan with constraints: { all_constraints } " )
108+ continue
109+
110+ # for (agent_idx, path) in paths.items():
111+ # print(f"\nAgent {agent_idx} path:\n {path}")
112+
85113 applied_constraint_parent = deepcopy (constraint_tree_node ) #TODO: not sure if deepcopy is actually needed
86114 applied_constraint_parent .constraint = applied_constraint
87115 parent_idx = constraint_tree .add_expanded_node (applied_constraint_parent )
88116
89117 new_constraint_tree_node = ConstraintTreeNode (paths , parent_idx )
90118 if new_constraint_tree_node .constraint is None :
91119 # This means we found a solution!
120+ print ("Found a path with constraints:" )
121+ for constraint in all_constraints :
122+ print (f"\t { constraint } " )
92123 return (start_and_goals , [paths [AgentId (i )] for i in range (len (start_and_goals ))])
93124
94- if verbose :
95- print (f"Adding new constraint tree node with constraint: { new_constraint_tree_node .constraint } " )
125+ # if verbose:
126+ print (f"Adding new constraint tree node with constraint: { new_constraint_tree_node .constraint } " )
96127 constraint_tree .add_node_to_tree (new_constraint_tree_node )
97128
129+ raise RuntimeError ("No solution found" )
130+ # TODO
131+ # * get SIPP working w CBS
132+ # * add checks for duplicate expansions
133+ # * fan out across multiple threads
134+ # * sipp intervals seem much larger than needed?
135+
98136verbose = False
99137show_animation = True
100138def main ():
101139 grid_side_length = 21
102140
103- # start_and_goals = [StartAndGoal(i, Position(1, i), Position(19, 19-i)) for i in range(1, 16)]
104- start_and_goals = [StartAndGoal (i , Position (1 , 8 + i ), Position (19 , 19 - i )) for i in range (4 )]
141+ # TODO: bug somewhere where it expects agent ids to match indices
142+ # start_and_goals = [StartAndGoal(i, Position(1, i), Position(19, 19-i)) for i in range(1, 12)]
143+ start_and_goals = [StartAndGoal (i , Position (1 , 8 + i ), Position (19 , 19 - i )) for i in range (6 )]
144+ # start_and_goals = [StartAndGoal(i, Position(1, 2*i), Position(19, 19-i)) for i in range(4)]
145+
146+ # hallway cross
147+ # start_and_goals = [StartAndGoal(0, Position(6, 10), Position(13, 10)),
148+ # StartAndGoal(1, Position(13, 10), Position(7, 10)),
149+ # StartAndGoal(2, Position(11, 10), Position(6, 10))]
150+
151+ # temporary obstacle
152+ # start_and_goals = [StartAndGoal(0, Position(15, 14), Position(15, 16))]
153+
154+ # start_and_goals = [StartAndGoal(1, Position(6, 10), Position(8, 10)),
155+ # StartAndGoal(2, Position(13, 10), Position(11, 10))]
105156 obstacle_avoid_points = [pos for item in start_and_goals for pos in (item .start , item .goal )]
106157
107158 grid = Grid (
108159 np .array ([grid_side_length , grid_side_length ]),
109160 num_obstacles = 250 ,
110161 obstacle_avoid_points = obstacle_avoid_points ,
162+ # obstacle_arrangement=ObstacleArrangement.TEMPORARY_OBSTACLE,
163+ # obstacle_arrangement=ObstacleArrangement.HALLWAY,
111164 obstacle_arrangement = ObstacleArrangement .NARROW_CORRIDOR ,
112165 # obstacle_arrangement=ObstacleArrangement.ARRANGEMENT1,
113166 # obstacle_arrangement=ObstacleArrangement.RANDOM,
0 commit comments