def worker(): env = BasicEnvironment("0004d52d1aeeb8ae6de39d6bd993e992", suncgDatasetRoot=TEST_SUNCG_DATA_DIR, depth=False, debug=True) env.agent.setPos(LVector3f(45, -42, 1)) env.agent.setHpr(LVector3f(45.0, 0.0, 0.0)) # Simulation loop for _ in range(nbSteps): env.step() _ = env.getObservation() env.destroy()
class HomeEnv(gym.Env): """HoME basic starter environment TODO: explain env basics, reward, other important details Actions: (can do both move & look at the same time) 1) Moving: Discrete 5 - NOOP[0], UP[1], # forward RIGHT[2], # strafe right DOWN[3], # backward LEFT[4] # strafe left - params: min: 0, max: 4 2) Looking: Discrete 5 -NOOP[0], UP[1], RIGHT[2], DOWN[3], LEFT[4] - params: min: 0, max: 4 """ def __init__(self, turning_speed=0.1, moving_speed=100): self.turning_speed = turning_speed # how fast is the camera turning self.moving_speed = moving_speed # how fast is the agent moving # empty init for tests self.observation = Observation(None, None, np.zeros((100, 100, 3), dtype=np.uint8), None).as_dict() self.metadata = {'render.modes': ['human', 'rgb_array']} # Gym environments have no parameters, so we have to # make sure the user first creates a symlink # to their SUNCG dataset in ~/.suncg # so that there are folders ~/.suncg/[room|house|...] self.data_path = data_dir() print("DEBUG: SUNCG DATA DIRECTORY:", self.data_path) self.action_space = spaces.MultiDiscrete(5, 5) self.observation_space = spaces.Dict({ # TODO what are the actual bounds of all possible houses? # position is x, y, z "position": spaces.Box(low=-100, high=100, shape=(3, ), dtype='float32'), # TODO get actual box for HPR # orientation is HPR / heading, pitch, roll "orientation": spaces.Box(low=-100, high=100, shape=(3, ), dtype='float32'), "image": spaces.Box(low=0, high=255, shape=(500, 500, 3)), # collision [0] - no collision, [1] - you bumped into sthg "collision": spaces.Discrete(2) }) print("DEBUG: LOADING HOUSES... ") self.list_of_houses = get_available_houses() print("DEBUG: FOUND HOUSES: ", len(self.list_of_houses)) # for determinism we have to load # the houses in specific order self.next_house = 0 self.render_window = None # if human rendering is on self._reset() def _seed(self, seed=0): """ Force loading a specific house :param seed: integer ID for house (not house ID) :return: """ assert seed < len(self.list_of_houses) self.next_house = seed return [self.next_house] def executeLooking(self, action): new_orientation = self.observation["orientation"] if action == 0: pass # NOOP elif action == 1: new_orientation[0] -= self.turning_speed elif action == 2: new_orientation[2] += self.turning_speed elif action == 3: new_orientation[0] += self.turning_speed elif action == 4: new_orientation[2] -= self.turning_speed else: raise Exception( "Received unknown 'looking' action: {}. " "Try an integer in the range between and including 0-4.". format(action)) self.env.setAgentOrientation(new_orientation) def executeMoving(self, action): new_impulse = [0.0, 0.0, 0.0] # impulse = force * time if action == 0: pass # NOOP elif action == 1: new_impulse[1] += self.moving_speed elif action == 2: new_impulse[0] += self.moving_speed elif action == 3: new_impulse[1] -= self.moving_speed elif action == 4: new_impulse[0] -= self.moving_speed else: raise Exception( "Received unknown 'moving' action: {}. " "Try an integer in the range between and including 0-4.". format(action)) print("new impulse:", new_impulse) self.env.applyImpulseToAgent(new_impulse) def _step(self, action): assert self.action_space.contains(action) self.executeMoving(action[0]) self.executeLooking(action[1]) self.env.step() self.observation = self.env.getObservation().as_dict() reward = 0 done = False misc = None return self.observation, reward, done, misc def _reset(self): # TODO maybe in the future we can unload the old house/rooms/objects # so we don't have to recreate the Panda3dBulletPhysicWorld # and Panda3dRenderWorld on every reset # load a new house into the world houseId = self.list_of_houses[self.next_house] self.env = BasicEnvironment(houseId, suncgDatasetRoot=self.data_path) # TODO move agent to random pos and orientation self.env.setAgentPosition((42, -39, 1)) self.env.setAgentOrientation((0.0, 0.0, 0.0)) self.env.step() # need a single step to create rendering in RAM self.observation = self.env.getObservation().as_dict() self.next_house += 1 # if we went to the end of the house list, loop around if (self.next_house == len(self.list_of_houses)): self.next_house = 0 return self.observation def _create_window(self): self.render_window = tk.Tk() image = np.zeros(self.env.size) img = ImageTk.Image.fromarray(image) imgTk = ImageTk.PhotoImage(img) self.render_panel = tk.Label(self.render_window, image=imgTk) self.render_panel.pack(side="bottom", fill="both", expand="yes") def _update_human_render(self): img = ImageTk.Image.fromarray(self.observation["image"]) imgTk = ImageTk.PhotoImage(img) self.render_panel.configure(image=imgTk) self.render_panel.image = imgTk self.render_window.update() def _render(self, mode='human', close=False): """ "human" render creates a Tk window, returns None "rgb_array" creates NO window, returns ndarray containing the img """ if mode == "rgb_array": return self.observation["image"] else: if self.render_window is None: self._create_window() self._update_human_render() def _close(self): if self.render_window is not None: self.render_window.destroy()