def __init__(
        self,
        reward_config_file=None,
        hysr_one_ball_config_file=None,
        log_episodes=False,
        log_tensorboard=False,
    ):

        super().__init__()

        self._log_episodes = log_episodes
        self._log_tensorboard = log_tensorboard

        hysr_one_ball_config = HysrOneBallConfig.from_json(
            hysr_one_ball_config_file)

        reward_function = JsonReward.get(reward_config_file)

        self._config = pam_interface.JsonConfiguration(
            hysr_one_ball_config.pam_config_file)
        self._nb_dofs = len(self._config.max_pressures_ago)
        self._algo_time_step = hysr_one_ball_config.algo_time_step
        self._pressure_change_range = hysr_one_ball_config.pressure_change_range
        self._accelerated_time = hysr_one_ball_config.accelerated_time

        self._hysr = HysrOneBall(hysr_one_ball_config, reward_function)

        self.action_space = gym.spaces.Box(low=-1.0,
                                           high=+1.0,
                                           shape=(self._nb_dofs * 2, ),
                                           dtype=np.float)

        self._obs_boxes = _ObservationSpace()

        self._obs_boxes.add_box("robot_position", -math.pi, +math.pi,
                                self._nb_dofs)
        self._obs_boxes.add_box("robot_velocity", 0.0, 10.0, self._nb_dofs)
        self._obs_boxes.add_box(
            "robot_pressure",
            self._config.min_pressure(),
            self._config.max_pressure(),
            self._nb_dofs * 2,
        )

        self._obs_boxes.add_box(
            "ball_position",
            min(hysr_one_ball_config.world_boundaries["min"]),
            max(hysr_one_ball_config.world_boundaries["max"]),
            3,
        )
        self._obs_boxes.add_box("ball_velocity", -10.0, +10.0, 3)

        self.observation_space = self._obs_boxes.get_gym_box()

        if not self._accelerated_time:
            self._frequency_manager = o80.FrequencyManager(
                1.0 / hysr_one_ball_config.algo_time_step)

        self.n_eps = 0
        self.init_episode()
Exemplo n.º 2
0
def run(config):
    log_handler = logging.StreamHandler(sys.stdout)
    logging.basicConfig(
        format="[o80 PAM segment_id: {} | %(levelname)s %(asctime)s] %(message)s".format(
            config.segment_id
        ),
        level=logging.DEBUG,
        handlers=[log_handler],
    )

    logging.info("read configuration")
    segment_id = config.segment_id
    frequency = config.frequency
    bursting_mode = config.bursting_mode
    robot = config.robot
    pam_config = pam_interface.JsonConfiguration(config.pam_config_file)

    if robot=="pamy2":
        ip = config.ip 
        port = config.port

    logging.info("starting robot: {}".format(robot))
    
    logging.info("cleaning shared memory")
    o80.clear_shared_memory(segment_id)

    logging.info("starting standalone")
    if robot == "pamy1":
        o80_pam.pamy1_start_standalone(segment_id, frequency, bursting_mode, pam_config)
    elif robot == "pamy2":
        o80_pam.pamy2_start_standalone(segment_id, frequency, bursting_mode, pam_config, ip, port)
    else:
        o80_pam.dummy_start_standalone(segment_id, frequency, bursting_mode, pam_config)

    logging.info("setting pressures to minimal values")
    _set_min_pressures(config, pam_config)
    logging.info("init exit signal handler")
    signal_handler.init()
    try:
        time_c = time.time() - 6
        while not signal_handler.has_received_sigint():
            time.sleep(0.01)
            if time.time() - time_c > 5:
                logging.info("running ...")
                time_c = time.time()
    except (KeyboardInterrupt, SystemExit):
        logging.info("exiting ...")
    except Exception as e:
        logging.error(str(e))
    finally:
        logging.info("setting pressures to minimal values")
        _set_min_pressures(config, pam_config)
        logging.info("stopping standalone")
        o80_pam.stop_standalone(config.segment_id)
        logging.info("cleaning shared memory")
        o80.clear_shared_memory(segment_id)
        logging.info("exit")
def read_config(config_path):
    if not os.path.isfile(config_path):
        raise Exception("failed to find", config_path)
    try:
        config = pam_interface.JsonConfiguration(config_path)
        return config
    except Exception as e:
        error = "failed to parse json configuration file " + config_path
        raise Exception(error, ":", str(e))
Exemplo n.º 4
0
    def __init__(self, hysr_config, reward_function):

        self._hysr_config = hysr_config

        # we will track the episode number
        self._episode_number = -1

        # we will track the step number (reset at the start
        # of each episode)
        self._step_number = -1

        # we end an episode after a fixed number of steps
        self._nb_steps_per_episode = hysr_config.nb_steps_per_episode
        # note: if self._nb_steps_per_episode is 0 or less,
        #       an episode will end based on a threshold
        #       in the z component of the ball position
        #       (see method _episode_over)

        # this instance of HysrOneBall interacts with several
        # instances of mujoco (pseudo real robot, simulated robot,
        # possibly instances of mujoco for extra balls).
        # Listing all the corresponding mujoco_ids
        self._mujoco_ids = []

        # pam muscles configuration
        self._pam_config = pam_interface.JsonConfiguration(
            hysr_config.pam_config_file)

        # to control pseudo-real robot (pressure control)
        if not hysr_config.real_robot:
            self._real_robot_handle, self._real_robot_frontend = configure_mujoco.configure_pseudo_real(
                hysr_config.pam_config_file,
                graphics=hysr_config.graphics_pseudo_real,
                accelerated_time=hysr_config.accelerated_time,
            )
            self._mujoco_ids.append(self._real_robot_handle.get_mujoco_id())
        else:
            # real robot: making some sanity check that the
            # rest of the configuration is ok
            if hysr_config.instant_reset:
                raise ValueError(
                    str("HysrOneBall configured for "
                        "real robot and instant reset."
                        "Real robot does not support "
                        "instant reset."))
            if hysr_config.accelerated_time:
                raise ValueError(
                    str("HysrOneBall configured for "
                        "real robot and accelerated time."
                        "Real robot does not support "
                        "accelerated time."))

        # to control the simulated robot (joint control)
        self._simulated_robot_handle = configure_mujoco.configure_simulation(
            hysr_config)
        self._mujoco_ids.append(self._simulated_robot_handle.get_mujoco_id())

        # where we want to shoot the ball
        self._target_position = hysr_config.target_position
        self._goal = self._simulated_robot_handle.interfaces[SEGMENT_ID_GOAL]

        # to read all recorded trajectory files
        self._trajectory_reader = context.BallTrajectories()

        # if requested, logging info about the frequencies of the steps and/or the
        # episodes
        if hysr_config.frequency_monitoring_step:
            size = 1000
            self._frequency_monitoring_step = frequency_monitoring.FrequencyMonitoring(
                SEGMENT_ID_STEP_FREQUENCY, size)
        else:
            self._frequency_monitoring_step = None
        if hysr_config.frequency_monitoring_episode:
            size = 1000
            self._frequency_monitoring_episode = (
                frequency_monitoring.FrequencyMonitoring(
                    SEGMENT_ID_EPISODE_FREQUENCY, size))
        else:
            self._frequency_monitoring_episode = None

        # if o80_pam (i.e. the pseudo real robot)
        # has been started in accelerated time,
        # the corresponding o80 backend will burst through
        # an algorithm time step
        self._accelerated_time = hysr_config.accelerated_time
        if self._accelerated_time:
            self._o80_time_step = hysr_config.o80_pam_time_step
            self._nb_robot_bursts = int(hysr_config.algo_time_step /
                                        hysr_config.o80_pam_time_step)

        # pam_mujoco (i.e. simulated ball and robot) should have been
        # started in accelerated time. It burst through algorithm
        # time steps
        self._mujoco_time_step = hysr_config.mujoco_time_step
        self._nb_sim_bursts = int(hysr_config.algo_time_step /
                                  hysr_config.mujoco_time_step)

        # the config sets either a zero or positive int (playing the
        # corresponding indexed pre-recorded trajectory) or a negative int
        # (playing randomly selected indexed trajectories)
        if hysr_config.trajectory >= 0:
            self._ball_behavior = _BallBehavior(index=hysr_config.trajectory)
        else:
            self._ball_behavior = _BallBehavior(random=True)

        # the robot will interpolate between current and
        # target posture over this duration
        self._period_ms = hysr_config.algo_time_step

        # reward configuration
        self._reward_function = reward_function

        # to get information regarding the ball
        # (instance of o80_pam.o80_ball.o80Ball)
        self._ball_communication = self._simulated_robot_handle.interfaces[
            SEGMENT_ID_BALL]

        # to send pressure commands to the real or pseudo-real robot
        # (instance of o80_pam.o80_pressures.o80Pressures)
        # hysr_config.real robot is either false (i.e. pseudo real
        # mujoco robot) or the segment_id of the real robot backend
        if not hysr_config.real_robot:
            self._pressure_commands = self._real_robot_handle.interfaces[
                SEGMENT_ID_PSEUDO_REAL_ROBOT]
        else:
            self._real_robot_frontend = o80_pam.FrontEnd(
                hysr_config.real_robot)
            self._pressure_commands = o80_pam.o80Pressures(
                hysr_config.real_robot, frontend=self._real_robot_frontend)

        # will encapsulate all information
        # about the ball (e.g. min distance with racket, etc)
        self._ball_status = context.BallStatus(hysr_config.target_position)

        # to send mirroring commands to simulated robots
        self._mirrorings = [
            self._simulated_robot_handle.interfaces[SEGMENT_ID_ROBOT_MIRROR]
        ]

        # to move the hit point marker
        # (instance of o80_pam.o80_hit_point.o80HitPoint)
        self._hit_point = self._simulated_robot_handle.interfaces[
            SEGMENT_ID_HIT_POINT]

        # tracking if this is the first step of the episode
        # (a call to the step function sets it to false, call to reset function sets it
        # back to true)
        self._first_episode_step = True

        # normally an episode ends when the ball z position goes
        # below a certain threshold (see method _episode_over)
        # this is to allow user to force ending an episode
        # (see force_episode_over method)
        self._force_episode_over = False

        # if false, the system will reset via execution of commands
        # if true, the system will reset by resetting the simulations
        # Only "false" is supported by the real robot
        self._instant_reset = hysr_config.instant_reset

        # adding extra balls (if any)
        if (hysr_config.extra_balls_sets is not None
                and hysr_config.extra_balls_sets > 0):

            self._extra_balls = []

            for setid in range(hysr_config.extra_balls_sets):

                # balls: list of instances of _ExtraBalls (defined in this file)
                # mirroring : for sending mirroring command to the robot
                #             of the set (joint controlled)
                #             (instance of
                #             o80_pam.o80_robot_mirroring.o80RobotMirroring)
                balls, mirroring, mujoco_id, frontend = _get_extra_balls(
                    setid, hysr_config)

                self._extra_balls.extend(balls)
                self._mirrorings.append(mirroring)
                self._mujoco_ids.append(mujoco_id)
                self._extra_balls_frontend = frontend
        else:
            self._extra_balls = []
            self._extra_balls_frontend = None

        # for running all simulations (main + for extra balls)
        # in parallel (i.e. when bursting is called, all mujoco
        # instance perform step(s) in parallel)
        self._parallel_burst = pam_mujoco.mirroring.ParallelBurst(
            self._mirrorings)

        # if set, logging the position of the robot at the end of reset, and possibly
        # get a warning when this position drifts as the number of episodes increase
        if hysr_config.robot_integrity_check is not None:
            self._robot_integrity = robot_integrity.RobotIntegrity(
                hysr_config.robot_integrity_threshold,
                file_path=hysr_config.robot_integrity_check,
            )
        else:
            self._robot_integrity = None

        # when starting, the real robot and the virtual robot(s)
        # may not be aligned, which may result in graphical issues,
        # so aligning them
        # (get values of real robot via self._pressure_commands,
        # and set values to all simulated robot via self._mirrorings)
        # source of mirroring in pam_mujoco.mirroring.py
        pam_mujoco.mirroring.align_robots(self._pressure_commands,
                                          self._mirrorings)
Exemplo n.º 5
0
 def __enter__(self):
     pam_config = pam_interface.JsonConfiguration(self._pam_config_path)
     o80_pam.dummy_start_standalone(
         self._segment_id, self._frequency, self._bursting_mode, pam_config
     )
     return