in data/envs/babyai/bot_agent.py [0:0]
def replan_before_action(self):
target_obj = None
if isinstance(self.datum, ObjDesc):
target_obj, target_pos = self.bot._find_obj_pos(self.datum, self.reason == "PutNext")
if not target_pos:
# No path found -> Explore the world
self.bot.stack.append(ExploreSubgoal(self.bot))
return
elif isinstance(self.datum, WorldObj):
target_obj = self.datum
target_pos = target_obj.cur_pos
else:
target_pos = tuple(self.datum)
# Suppore we are walking towards the door that we would like to open,
# it is locked, and we don't have the key. What do we do? If we are carrying
# something, it makes to just continue, as we still need to bring this object
# close to the door. If we are not carrying anything though, then it makes
# sense to change the plan and go straight for the required key.
if self.reason == "Open" and target_obj and target_obj.type == "door" and target_obj.is_locked:
key_desc = ObjDesc("key", target_obj.color)
key_desc.find_matching_objs(self.bot.mission)
if not self.carrying:
# No we need to commit to going to this particular door
self.bot.stack.pop()
self.bot.stack.append(GoNextToSubgoal(self.bot, target_obj, reason="Open"))
self.bot.stack.append(PickupSubgoal(self.bot))
self.bot.stack.append(GoNextToSubgoal(self.bot, key_desc))
return
# The position we are on is the one we should go next to
# -> Move away from it
if manhattan_distance(target_pos, self.pos) == (1 if self.reason == "PutNext" else 0):
def steppable(cell):
return cell is None or (cell.type == "door" and cell.is_open)
if steppable(self.fwd_cell):
return self.actions.forward
if steppable(self.bot.mission.unwrapped.grid.get(*(self.pos + self.right_vec))):
return self.actions.right
if steppable(self.bot.mission.unwrapped.grid.get(*(self.pos - self.right_vec))):
return self.actions.left
# Spin and hope for the best
return self.actions.left
# We are facing the target cell
# -> subgoal completed
if self.reason == "PutNext":
if manhattan_distance(target_pos, self.fwd_pos) == 1:
if self.fwd_cell is None:
self.bot.stack.pop()
return
if self.fwd_cell.type == "door" and self.fwd_cell.is_open:
# We can't drop an object in the cell where the door is.
# Instead, we add a subgoal on the stack that will force
# the bot to move the target object.
self.bot.stack.append(GoNextToSubgoal(self.bot, self.fwd_pos + 2 * self.dir_vec))
return
else:
if np.array_equal(target_pos, self.fwd_pos):
self.bot.stack.pop()
return
# We are still far from the target
# -> try to find a non-blocker path
path, _, _ = self.bot._shortest_path(
lambda pos, cell: pos == target_pos,
)
# No non-blocker path found and
# reexploration within the room is not allowed or there is nothing to explore
# -> Look for blocker paths
if not path:
path, _, _ = self.bot._shortest_path(lambda pos, cell: pos == target_pos, try_with_blockers=True)
# No path found
# -> explore the world
if not path:
self.bot.stack.append(ExploreSubgoal(self.bot))
return
# So there is a path (blocker, or non-blockers)
# -> try following it
next_cell = np.asarray(path[0])
# Choose the action in the case when the forward cell
# is the one we should go next to
if np.array_equal(next_cell, self.fwd_pos):
if self.fwd_cell:
if self.fwd_cell.type == "door":
assert not self.fwd_cell.is_locked
if not self.fwd_cell.is_open:
self.bot.stack.append(OpenSubgoal(self.bot))
return
else:
return self.actions.forward
if self.carrying:
drop_pos_cur = self.bot._find_drop_pos()
drop_pos_block = self.bot._find_drop_pos(drop_pos_cur)
# Take back the object being carried
self.bot.stack.append(PickupSubgoal(self.bot))
self.bot.stack.append(GoNextToSubgoal(self.bot, drop_pos_cur))
# Pick up the blocking object and drop it
self.bot.stack.append(DropSubgoal(self.bot))
self.bot.stack.append(GoNextToSubgoal(self.bot, drop_pos_block))
self.bot.stack.append(PickupSubgoal(self.bot))
self.bot.stack.append(GoNextToSubgoal(self.bot, self.fwd_pos))
# Drop the object being carried
self.bot.stack.append(DropSubgoal(self.bot))
self.bot.stack.append(GoNextToSubgoal(self.bot, drop_pos_cur))
return
else:
drop_pos = self.bot._find_drop_pos()
self.bot.stack.append(DropSubgoal(self.bot))
self.bot.stack.append(GoNextToSubgoal(self.bot, drop_pos))
self.bot.stack.append(PickupSubgoal(self.bot))
return
else:
return self.actions.forward
# The forward cell is not the one we should go to
# -> turn towards the direction we need to go
if np.array_equal(next_cell - self.pos, self.right_vec):
return self.actions.right
elif np.array_equal(next_cell - self.pos, -self.right_vec):
return self.actions.left
# If we reach this point in the code, then the cell is behind us.
# Instead of choosing left or right randomly,
# let's do something that might be useful:
# Because when we're GoingNextTo for the purpose of exploring,
# things might change while on the way to the position we're going to, we should
# pick this right or left wisely.
# The simplest thing we should do is: pick the one
# that doesn't lead you to face a non empty cell.
# One better thing would be to go to the direction
# where the closest wall/door is the furthest
distance_right = self.bot._closest_wall_or_door_given_dir(self.pos, self.right_vec)
distance_left = self.bot._closest_wall_or_door_given_dir(self.pos, -self.right_vec)
if distance_left > distance_right:
return self.actions.left
return self.actions.right