예제 #1
0
class UnrealCvSearch_base(gym.Env):
    def __init__(self,
                 setting_file,
                 category,
                 reset_type='waypoint',  # testpoint, waypoint,
                 augment_env=None,  # texture, target, light
                 action_type='Discrete',  # 'Discrete', 'Continuous'
                 observation_type='Rgbd',  # 'color', 'depth', 'rgbd'
                 reward_type='bbox',  # distance, bbox, bbox_distance,
                 docker=False,
                 resolution=(160, 120)
                 ):
        #print(setting_file)
        setting = self.load_env_setting(setting_file)
        self.cam_id = setting['cam_id']
        self.target_list = setting['targets'][category]
        self.trigger_th = setting['trigger_th']
        self.height = setting['height']
        self.pitch = setting['pitch']
        self.discrete_actions = setting['discrete_actions']
        self.continous_actions = setting['continous_actions']

        self.docker = docker
        self.reset_type = reset_type
        self.augment_env = augment_env
        
        # start unreal env
        self.unreal = env_unreal.RunUnreal(ENV_BIN=setting['env_bin'])
        env_ip, env_port = self.unreal.start(docker, resolution)

        # connect UnrealCV
        self.unrealcv = Navigation(cam_id=self.cam_id,
                                   port=env_port,
                                   ip=env_ip,
                                   targets=self.target_list,
                                   env=self.unreal.path2env,
                                   resolution=resolution)
        self.unrealcv.pitch = self.pitch

        #  define action
        self.action_type = action_type
        assert self.action_type == 'Discrete' or self.action_type == 'Continuous'
        if self.action_type == 'Discrete':
            self.action_space = spaces.Discrete(len(self.discrete_actions))
        elif self.action_type == 'Continuous':
            self.action_space = spaces.Box(low=np.array(self.continous_actions['low']),
                                           high=np.array(self.continous_actions['high']))

        # define observation space,
        # color, depth, rgbd,...
        self.observation_type = observation_type
        assert self.observation_type == 'Color' or self.observation_type == 'Depth' or self.observation_type == 'Rgbd'
        self.observation_space = self.unrealcv.define_observation(self.cam_id, self.observation_type, 'direct')

        # define reward type
        # distance, bbox, bbox_distance,
        self.reward_type = reward_type
        self.reward_function = reward.Reward(setting)

        # set start position
        self.trigger_count = 0
        current_pose = self.unrealcv.get_pose(self.cam_id)
        current_pose[2] = self.height
        self.unrealcv.set_location(self.cam_id, current_pose[:3])

        self.count_steps = 0

        self.targets_pos = self.unrealcv.build_pose_dic(self.target_list)

        # for reset point generation and selection
        self.reset_module = reset_point.ResetPoint(setting, reset_type, current_pose)

    def _step(self, action ):
        info = dict(
            Collision=False,
            Done=False,
            Trigger=0.0,
            Reward=0.0,
            Action=action,
            Bbox=[],
            Pose=[],
            Trajectory=self.trajectory,
            Steps=self.count_steps,
            Target=[],
            Direction=None,
            Waypoints=self.reset_module.waypoints,
            Color=None,
            Depth=None,
        )

        action = np.squeeze(action)
        if self.action_type == 'Discrete':
            (velocity, angle, info['Trigger']) = self.discrete_actions[action]
        else:
            (velocity, angle, info['Trigger']) = action
        self.count_steps += 1
        info['Done'] = False

        # take action
        info['Collision'] = self.unrealcv.move_2d(self.cam_id, angle, velocity)
        info['Pose'] = self.unrealcv.get_pose(self.cam_id, 'soft')
        # the robot think that it found the target object,the episode is done
        # and get a reward by bounding box size
        # only three times false trigger allowed in every episode
        if info['Trigger'] > self.trigger_th:
            self.trigger_count += 1
            # get reward
            if 'bbox' in self.reward_type:
                object_mask = self.unrealcv.read_image(self.cam_id, 'object_mask')
                boxes = self.unrealcv.get_bboxes(object_mask, self.target_list)
                info['Reward'], info['Bbox'] = self.reward_function.reward_bbox(boxes)
            else:
                info['Reward'] = 0

            if info['Reward'] > 0 or self.trigger_count > 3:
                info['Done'] = True
                if info['Reward'] > 0 and self.reset_type == 'waypoint':
                    self.reset_module.success_waypoint(self.count_steps)
        else:
            # get reward
            distance, self.target_id = self.select_target_by_distance(info['Pose'][:3], self.targets_pos)
            info['Target'] = self.targets_pos[self.target_id]
            info['Direction'] = self.get_direction(info['Pose'], self.targets_pos[self.target_id])

            # calculate reward according to the distance to target object
            if 'distance' in self.reward_type:
                info['Reward'] = self.reward_function.reward_distance(distance)
            else:
                info['Reward'] = 0

            # if collision detected, the episode is done and reward is -1
            if info['Collision']:
                info['Reward'] = -1
                info['Done'] = True
                if self.reset_type == 'waypoint':
                    self.reset_module.update_dis2collision(info['Pose'])

        # update observation
        state = self.unrealcv.get_observation(self.cam_id, self.observation_type)
        info['Color'] = self.unrealcv.img_color
        info['Depth'] = self.unrealcv.img_depth

        # save the trajectory
        self.trajectory.append(info['Pose'][:6])
        info['Trajectory'] = self.trajectory
        if info['Done'] and len(self.trajectory) > 5 and self.reset_type == 'waypoint':
            self.reset_module.update_waypoint(info['Trajectory'])

        return state, info['Reward'], info['Done'], info

    def _reset(self, ):

        # double check the resetpoint, it is necessary for random reset type
        collision = True
        while collision:
            current_pose = self.reset_module.select_resetpoint()
            self.unrealcv.set_pose(self.cam_id, current_pose)
            collision = self.unrealcv.move_2d(self.cam_id, 0, 100)
        self.unrealcv.set_pose(self.cam_id, current_pose)

        state = self.unrealcv.get_observation(self.cam_id, self.observation_type)

        self.trajectory = []
        self.trajectory.append(current_pose)
        self.trigger_count = 0
        self.count_steps = 0
        self.reward_function.dis2target_last, self.targetID_last = \
            self.select_target_by_distance(current_pose, self.targets_pos)
        return state

    def _seed(self, seed=None):
        return seed

    def _render(self, mode='rgb_array', close=False):
        if close==True:
            self.unreal.close()
        return self.unrealcv.img_color

    def _close(self):
        self.unreal.close()

    def _get_action_size(self):
        return len(self.action)

    def select_target_by_distance(self, current_pos, targets_pos):
        # find the nearest target, return distance and targetid
        target_id = list(self.targets_pos.keys())[0]
        distance_min = self.unrealcv.get_distance(targets_pos[target_id], current_pos, 2)
        for key, target_pos in targets_pos.items():
            distance = self.unrealcv.get_distance(target_pos, current_pos, 2)
            if distance < distance_min:
                target_id = key
                distance_min = distance
        return distance_min, target_id

    def get_direction(self, current_pose, target_pose):
        y_delt = target_pose[1] - current_pose[1]
        x_delt = target_pose[0] - current_pose[0]
        angle_now = np.arctan2(y_delt, x_delt)/np.pi*180-current_pose[4]
        if angle_now > 180:
            angle_now -= 360
        if angle_now < -180:
            angle_now += 360
        return angle_now

    def load_env_setting(self, filename):
        import gym_unrealcv
        gympath = os.path.dirname(gym_unrealcv.__file__)
        gympath = os.path.join(gympath, 'envs/setting', filename)
        #print(gympath)
        f = open(gympath)
        filetype = os.path.splitext(filename)[1]
        if filetype == '.json':
            import json
            setting = json.load(f)
        else:
            print ('unknown type')

        return setting
예제 #2
0
class sfmHouseTarget(gym.Env):
    # init the Unreal Gym Environment
    def __init__(
        self,
        setting_file='sfmHouseTarget.json',
        reset_type='waypoint',  # testpoint, waypoint,
        augment_env=None,  #texture, target, light
        test=True,  # if True will use the test_xy as start point
        action_type='discrete',  # 'discrete', 'continuous'
        observation_type='rgbd',  # 'color', 'depth', 'rgbd'
        reward_type='bbox',  # distance, bbox, bbox_distance,
        docker=False,
        # resolution = (320,240)
        resolution=(640, 480)):
        setting = self.load_env_setting(setting_file)
        self.cam_id = 0

        # run virtual enrionment in docker container
        # self.docker = run_docker.RunDocker()
        # env_ip, env_dir = self.docker.start(ENV_NAME=ENV_NAME)

        # start unreal env
        docker = False
        # self.unreal = env_unreal.RunUnreal(ENV_BIN="house_withfloor/MyProject2/Binaries/Linux/MyProject2")
        self.unreal = env_unreal.RunUnreal(ENV_BIN=self.env_bin)
        env_ip, env_port = self.unreal.start(docker, resolution)

        # connect unrealcv client to server
        # self.unrealcv = UnrealCv(self.cam_id, ip=env_ip, env=env_dir)

        # connect UnrealCV
        self.unrealcv = Navigation(cam_id=self.cam_id,
                                   port=env_port,
                                   ip=env_ip,
                                   targets=self.target_list,
                                   env=self.unreal.path2env,
                                   resolution=resolution)
        self.unrealcv.pitch = self.pitch

        # define action
        self.action_type = action_type
        assert self.action_type == 'discrete' or self.action_type == 'continuous'
        if self.action_type == 'discrete':
            self.action_space = spaces.Discrete(len(self.discrete_actions))
        elif self.action_type == 'continuous':
            self.action_space = spaces.Box(
                low=np.array(self.continous_actions['low']),
                high=np.array(self.continous_actions['high']))

        self.startpose = self.unrealcv.get_pose(self.cam_id)
        print('start_pose: ', self.startpose)
        #try hardcode start pose
        # self.startpose = [750.0, 295.0, 212.3,356.5,190.273, 0.0]
        self.startpose = [0.0, 707.1068, 707.1067, 0.0, 270.0,
                          -45.0]  # [0,45,1000]
        # ACTION: (Azimuth, Elevation, Distance)
        print("start")
        object_mask = self.unrealcv.read_image(self.cam_id,
                                               'object_mask',
                                               mode='file')
        cv2.imshow('object_mask', object_mask)
        cv2.waitKey(0)
        boxes = self.unrealcv.get_bboxes(object_mask, self.target_list)

        # ACTION: (linear velocity ,angle velocity)
        # self.ACTION_LIST = [
        #         (20,  0),
        #         (20, 15),
        #         (20,-15),
        #         (20, 30),
        #         (20,-30),
        # ]
        self.count_steps = 0
        # self.max_steps = 35
        self.target_pos = (-60, 0, 50)
        # self.action_space = gym.spaces.Discrete(len(self.ACTION_LIST))
        state = self.unrealcv.read_image(self.cam_id, 'lit')
        self.observation_space = gym.spaces.Box(low=0,
                                                high=255,
                                                shape=state.shape)

        self.reward_type = reward_type
        self.reward_function = reward.Reward(setting)

    # update the environment step by step
    def _step(self, action=0):
        # (velocity, angle) = self.ACTION_LIST[action]
        self.count_steps += 1
        # collision =  self.unrealcv.move(self.cam_id, angle, velocity)
        # collision = self.unrealcv.move_2d(self.cam_id, angle, velocity)
        # collision = self.unrealcv.move_2d(self.cam_id, angle, velocity)
        azimuth, elevation, distance = action
        collision, move_dist = self.unrealcv.move_rel(self.cam_id, azimuth,
                                                      elevation, distance)

        # print('distance:   ', move_dist)
        print('reward type: ', self.reward_type)
        print('target list: ', self.target_list)
        if 'bbox' in self.reward_type:
            object_mask = self.unrealcv.read_image(self.cam_id, 'object_mask')
            cv2.imshow('object_mask', object_mask)
            cv2.waitKey(0)
            boxes = self.unrealcv.get_bboxes(object_mask, self.target_list)
            reward_bbox, bbox = self.reward_function.reward_bbox(boxes)
            print('bbox reward: ', reward_bbox, bbox)
        reward, done = self.reward(collision, move_dist)
        state = self.unrealcv.read_image(self.cam_id, 'lit')

        # limit max step per episode
        if self.count_steps > self.max_steps:
            done = True
            print('Reach Max Steps')

        return state, reward, done, {}

    # reset the environment
    def _reset(self, ):
        x, y, z, _, yaw, _ = self.startpose
        pose = self.startpose

        # self.unrealcv.set_position(self.cam_id, x, y, z)
        # self.unrealcv.set_rotation(self.cam_id, 0, yaw, 0)

        self.unrealcv.set_pose(self.cam_id, self.startpose)

        state = self.unrealcv.read_image(self.cam_id, 'lit')
        self.count_steps = 0
        return state

    # close docker while closing openai gym
    # def _close(self):
    # self.docker.close()

    # calcuate reward according to your task
    def reward(self, collision, move_dist):
        done = False
        reward = -0.01

        if collision:
            done = True
            reward = -1
            print('Collision Detected!!')
        else:
            #hard code to 1
            reward = -1 * move_dist * (1 / 2000)
            # print('dist reward: ', reward)
            # distance = self.cauculate_distance(self.target_pos, self.unrealcv.get_pose())
            # if distance < 50:
            #     reward = 10
            #     done = True
            #     print ('Get Target Place!')
        return reward, done

    # calcuate the 2D distance between the target and camera
    def cauculate_distance(self, target, current):
        error = abs(np.array(target) - np.array(current))[:2]  # only x and y
        distance = math.sqrt(sum(error * error))
        return distance

    def load_env_setting(self, filename):
        f = open(self.get_settingpath(filename))
        type = os.path.splitext(filename)[1]
        if type == '.json':
            import json
            setting = json.load(f)
        elif type == '.yaml':
            import yaml
            setting = yaml.load(f)
        else:
            print('unknown type')

        self.cam_id = setting['cam_id']
        self.target_list = setting['targets']
        self.max_steps = setting['maxsteps']
        self.trigger_th = setting['trigger_th']
        self.height = setting['height']
        self.pitch = setting['pitch']

        self.discrete_actions = setting['discrete_actions']
        self.continous_actions = setting['continous_actions']
        self.env_bin = setting['env_bin']
        self.env_name = setting['env_name']
        print('env name: ', self.env_name)
        print('env id: ', setting['env_bin'])
        return setting

    def get_settingpath(self, filename):
        import gym_unrealcv
        gympath = os.path.dirname(gym_unrealcv.__file__)
        return os.path.join(gympath, 'envs/setting', filename)
class UnrealCvSearch_topview(gym.Env):
   def __init__(self,
                setting_file = 'search_rr_plant78.json',
                reset_type = 'waypoint',       # testpoint, waypoint,
                test = True,               # if True will use the test_xy as start point
                action_type = 'discrete',  # 'discrete', 'continuous'
                observation_type = 'rgbd', # 'color', 'depth', 'rgbd'
                reward_type = 'bbox', # distance, bbox, bbox_distance,
                docker = False,
                ):

     setting = self.load_env_setting(setting_file)
     self.test = test
     self.docker = docker
     self.reset_type = reset_type

     # start unreal env
     self.unreal = env_unreal.RunUnreal(ENV_BIN=setting['env_bin'])
     env_ip,env_port = self.unreal.start(docker)

     # connect UnrealCV
     self.unrealcv = Navigation(cam_id=self.cam_id,
                              port= env_port,
                              ip=env_ip,
                              targets=self.target_list,
                              env=self.unreal.path2env)
     self.unrealcv.pitch = self.pitch
    # define action
     self.action_type = action_type
     assert self.action_type == 'discrete' or self.action_type == 'continuous'
     if self.action_type == 'discrete':
         self.action_space = spaces.Discrete(len(self.discrete_actions))
     elif self.action_type == 'continuous':
         self.action_space = spaces.Box(low = np.array(self.continous_actions['low']),high = np.array(self.continous_actions['high']))

     self.count_steps = 0
     self.targets_pos = self.unrealcv.build_pose_dic(self.target_list)

    # define observation space,
    # color, depth, rgbd,...
     self.observation_type = observation_type
     assert self.observation_type == 'color' or self.observation_type == 'depth' or self.observation_type == 'rgbd'
     if self.observation_type == 'color':
         state = self.unrealcv.read_image(self.cam_id,'lit')
         self.observation_space = spaces.Box(low=0, high=255, shape=state.shape)
     elif self.observation_type == 'depth':
         state = self.unrealcv.read_depth(self.cam_id)
         self.observation_space = spaces.Box(low=0, high=10, shape=state.shape)
     elif self.observation_type == 'rgbd':
         state = self.unrealcv.get_rgbd(self.cam_id)
         s_high = state
         s_high[:,:,-1] = 10.0 #max_depth
         s_high[:,:,:-1] = 255 #max_rgb
         s_low = np.zeros(state.shape)
         self.observation_space = spaces.Box(low=s_low, high=s_high)


     # define reward type
     # distance, bbox, bbox_distance,
     self.reward_type = reward_type


     # set start position
     self.trigger_count  = 0
     current_pose = self.unrealcv.get_pose(self.cam_id)
     current_pose[2] = self.height
     self.unrealcv.set_location(self.cam_id,current_pose[:3])


     self.trajectory = []

     # for reset point generation and selection
     self.reset_module = reset_point.ResetPoint(setting, reset_type, test, current_pose)

     self.reward_function = reward.Reward(setting)
     self.reward_function.dis2target_last, self.targetID_last = self.select_target_by_distance(current_pose, self.targets_pos)

     self.rendering = False

   def _step(self, action ):
        info = dict(
            Collision=False,
            Done = False,
            Trigger=0.0,
            Maxstep=False,
            Reward=0.0,
            Action = action,
            Bbox =[],
            Pose = [],
            Trajectory = self.trajectory,
            Steps = self.count_steps,
            Target = [],
            Direction = None,
            Waypoints = self.reset_module.waypoints,
            Color = None,
            Depth = None,
        )


        if self.action_type == 'discrete':
            (velocity, angle, info['Trigger']) = self.discrete_actions[action]
        else:
            (velocity, angle, info['Trigger']) = action
        self.count_steps += 1
        info['Done'] = False



        info['Pose'] = self.unrealcv.get_pose(self.cam_id,'soft')


        # the robot think that it found the target object,the episode is done
        # and get a reward by bounding box size
        # only three times false trigger allowed in every episode
        if info['Trigger'] > self.trigger_th :
            self.trigger_count += 1
            # get reward
            if self.reward_type == 'bbox_distance' or self.reward_type == 'bbox':
                object_mask = self.unrealcv.read_image(self.cam_id, 'object_mask')
                boxes = self.unrealcv.get_bboxes(object_mask, self.target_list)
                info['Reward'], info['Bbox'] = self.reward_function.reward_bbox(boxes)
            else:
                info['Reward'] = 0

            if info['Reward'] > 0 or self.trigger_count > 3:
                info['Done'] = True
                if info['Reward'] > 0 and self.test == False:
                    self.reset_module.success_waypoint(self.count_steps)

                print('Trigger Terminal!')
        # if collision occurs, the episode is done and reward is -1
        else :
            # take action
            info['Collision'] = self.unrealcv.move_2d(self.cam_id, angle, velocity)
            # get reward
            info['Pose'] = self.unrealcv.get_pose(self.cam_id)
            distance, self.target_id = self.select_target_by_distance(info['Pose'][:3],self.targets_pos)
            info['Target'] = self.targets_pos[self.target_id]

            if self.reward_type=='distance' or self.reward_type == 'bbox_distance':
                info['Reward'] = self.reward_function.reward_distance(distance)
            else:
                info['Reward'] = -0.1

            info['Direction'] = self.get_direction (info['Pose'],self.targets_pos[self.target_id])
            if distance < 50:
                info['Done'] = True
                info['Reward'] = 10
                print ('get location')

            if info['Collision']:
                info['Reward'] = -1
                info['Done'] = True
                self.reset_module.update_dis2collision(info['Pose'])
                print ('Collision!!')

        # update observation
        if self.observation_type == 'color':
            state = info['Color'] = self.unrealcv.read_image(self.cam_id, 'lit')
        elif self.observation_type == 'depth':
            state = info['Depth'] = self.unrealcv.read_depth(self.cam_id)
        elif self.observation_type == 'rgbd':
            info['Color'] = self.unrealcv.read_image(self.cam_id, 'lit')
            info['Depth'] = self.unrealcv.read_depth(self.cam_id)
            state = np.append(info['Color'], info['Depth'], axis=2)

        # limit the max steps of every episode
        if self.count_steps > self.max_steps:
           info['Done'] = True
           info['Maxstep'] = True
           print('Reach Max Steps')

        # save the trajectory
        self.trajectory.append(info['Pose'][:6])
        info['Trajectory'] = self.trajectory

        if info['Done'] and len(self.trajectory) > 5 and not self.test:
            self.reset_module.update_waypoint(info['Trajectory'])

        #print info['Reward']
        if self.rendering:
            show_info(info)
        return state, info['Reward'], info['Done'], info
   def _reset(self, ):
       #self.unrealcv.keyboard('G')
       collision = True
       while collision:
           current_pose = self.reset_module.select_resetpoint()
           self.unrealcv.set_location(self.cam_id, current_pose[:3])
           self.unrealcv.set_rotation(self.cam_id, current_pose[-3:])
           collision = self.unrealcv.move_2d(self.cam_id,0,50)

       self.unrealcv.move_2d(self.cam_id, 0, -50)

       self.random_scene()


       if self.observation_type == 'color':
           state = self.unrealcv.read_image(self.cam_id, 'lit')
       elif self.observation_type == 'depth':
           state = self.unrealcv.read_depth(self.cam_id)
       elif self.observation_type == 'rgbd':
           state = self.unrealcv.get_rgbd(self.cam_id)


       self.trajectory = []
       self.trajectory.append(current_pose)
       self.trigger_count = 0
       self.count_steps = 0

       self.targets_pos = self.unrealcv.build_pose_dic(self.target_list)

       #print current_pose,self.targets_pos
       self.reward_function.dis2target_last, self.targetID_last = self.select_target_by_distance(current_pose,
                                                                                                 self.targets_pos)
       return state

   def _close(self):
       if self.docker:
           self.unreal.docker.close()

       #sys.exit()


   def _get_action_size(self):
       return len(self.action)


   def get_distance(self,target,current):

       error = abs(np.array(target)[:2] - np.array(current)[:2])# only x and y
       distance = math.sqrt(sum(error * error))
       return distance


   def select_target_by_distance(self,current_pos, targets_pos):
       # find the nearest target, return distance and targetid
       target_id = self.targets_pos.keys()[0]
       distance_min = self.get_distance(targets_pos[target_id], current_pos)
       for key, target_pos in targets_pos.items():
           distance = self.get_distance(target_pos, current_pos)
           if distance < distance_min:
               target_id = key
               distance_min = distance

       return distance_min,target_id

   def get_direction(self,current_pose,target_pose):
       y_delt = target_pose[1] - current_pose[1]
       x_delt = target_pose[0] - current_pose[0]
       if x_delt == 0:
           x_delt = 0.00001

       angle_now = np.arctan(y_delt / x_delt) / 3.1415926 * 180 - current_pose[-1]

       if x_delt < 0:
           angle_now += 180
       if angle_now < 0:
           angle_now += 360
       if angle_now > 360:
           angle_now -= 360

       return angle_now

   def random_scene(self):
       # change material
       num = ['One', 'Two', 'Three', 'Four', 'Five','Six']
       for i in num:
           self.unrealcv.keyboard(i)

       # random place the target object
       for i in self.target_list:
           z1 = 60
           while z1 > 50:
               x = random.uniform(self.reset_area[0],self.reset_area[1])
               y = random.uniform(self.reset_area[2],self.reset_area[3])
               self.unrealcv.set_object_location(i,[x,y,50])
               time.sleep(0.5)
               [x1,y1,z1] = self.unrealcv.get_obj_location(i)



   def load_env_setting(self,filename):
       f = open(self.get_settingpath(filename))
       type = os.path.splitext(filename)[1]
       if type == '.json':
           import json
           setting = json.load(f)
       elif type == '.yaml':
           import yaml
           setting = yaml.load(f)
       else:
           print('unknown type')

       #print setting
       self.cam_id = setting['cam_id']
       self.pitch = setting['pitch']
       self.target_list = setting['targets']
       self.max_steps = setting['maxsteps']
       self.trigger_th = setting['trigger_th']
       self.height = setting['height']
       self.reset_area = setting['reset_area']

       self.discrete_actions = setting['discrete_actions']
       self.continous_actions = setting['continous_actions']

       return setting


   def get_settingpath(self, filename):
       import gym_unrealcv
       gympath = os.path.dirname(gym_unrealcv.__file__)
       return os.path.join(gympath, 'envs/setting', filename)


   def open_door(self):
       self.unrealcv.keyboard('RightMouseButton')
       time.sleep(2)
       self.unrealcv.keyboard('RightMouseButton') # close the door