Exemplo n.º 1
0
def polar_axis_angle_to_quaternion(polar_axis_angle):
    """
    Convert polar axis-angle representation, which constitutes the elevation and azimuth angles of the axis as well
    as the rotation angle :math:`\mathbf{θ}_{paa} = [ϕ_e, ϕ_a, θ]`, to quaternion form
    :math:`\mathbf{q} = [q_i, q_j, q_k, q_r]`.\n
    `[reference] <https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation>`_

    :param polar_axis_angle: Polar axis angle representation *[batch_shape,3]*
    :type polar_axis_angle: array
    :return: Quaternion *[batch_shape,4]*
    """

    # BS x 1
    theta = polar_axis_angle[..., 0:1]
    phi = polar_axis_angle[..., 1:2]
    angle = polar_axis_angle[..., 2:3]
    x = _ivy.sin(theta) * _ivy.cos(phi)
    y = _ivy.sin(theta) * _ivy.sin(phi)
    z = _ivy.cos(theta)

    # BS x 3
    vector = _ivy.concatenate((x, y, z), -1)

    # BS x 4
    return axis_angle_to_quaternion(_ivy.concatenate([vector, angle], -1))
Exemplo n.º 2
0
    def get_reward(self):
        """
        Get reward based on current state

        :return: Reward array
        """
        # Pole verticality.
        rew = (ivy.cos(self.angle) + 1) / 2
        return ivy.reshape(rew, (1, ))
Exemplo n.º 3
0
    def get_observation(self):
        """
        Get observation from environment.

        :return: observation array
        """
        return ivy.concatenate(
            (ivy.cos(self.angle), ivy.sin(self.angle), self.angle_vel),
            axis=-1)
Exemplo n.º 4
0
    def get_reward(self):
        """
        Get reward based on current state

        :return: Reward array
        """
        # Center proximity.
        rew = ivy.exp(-1 * (self.x**2))
        # Pole verticality.
        rew = rew * (ivy.cos(self.angle) + 1) / 2
        return ivy.reshape(rew[0], (1, ))
Exemplo n.º 5
0
def test_cos(x, dtype_str, tensor_fn, dev_str, call):
    # smoke test
    x = tensor_fn(x, dtype_str, dev_str)
    ret = ivy.cos(x)
    # type test
    assert ivy.is_array(ret)
    # cardinality test
    assert ret.shape == x.shape
    # value test
    assert np.allclose(call(ivy.cos, x), ivy.numpy.cos(ivy.to_numpy(x)))
    # compilation test
    helpers.assert_compilable(ivy.cos)
Exemplo n.º 6
0
    def get_observation(self):
        """
        Get observation from environment.

        :return: observation array
        """
        ob = (ivy.reshape(ivy.cos(self.angles),
                          (1, 2)), ivy.reshape(ivy.sin(self.angles), (1, 2)),
              ivy.reshape(self.angle_vels,
                          (1, 2)), ivy.reshape(self.goal_xy, (1, 2)))
        ob = ivy.concatenate(ob, axis=0)
        return ivy.reshape(ob, (-1, ))
Exemplo n.º 7
0
def polar_to_cartesian_coords(polar_coords):
    """
    Convert spherical polar co-ordinates :math:`\mathbf{x}_p = [r, α, β]` to cartesian co-ordinates
    :math:`\mathbf{x}_c = [x, y, z]`.\n
    `[reference] <https://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates>`_

    :param polar_coords: Spherical polar co-ordinates *[batch_shape,3]*
    :type polar_coords: array
    :return: Cartesian co-ordinates *[batch_shape,3]*
    """

    # BS x 1
    phi = polar_coords[..., 0:1]
    theta = polar_coords[..., 1:2]
    r = polar_coords[..., 2:3]

    x = r * _ivy.sin(theta) * _ivy.cos(phi)
    y = r * _ivy.sin(theta) * _ivy.sin(phi)
    z = r * _ivy.cos(theta)

    # BS x 3
    return _ivy.concatenate((x, y, z), -1)
Exemplo n.º 8
0
    def get_reward(self):
        """
        Get reward based on current state

        :return: Reward array
        """
        # Goal proximity.
        x = ivy.reduce_sum(ivy.cos(self.angles), -1)
        y = ivy.reduce_sum(ivy.sin(self.angles), -1)
        xy = ivy.concatenate([ivy.expand_dims(x, 0),
                              ivy.expand_dims(y, 0)],
                             axis=0)
        rew = ivy.reshape(
            ivy.exp(-1 * ivy.reduce_sum((xy - self.goal_xy)**2, -1)), (-1, ))
        return ivy.reduce_mean(rew, axis=0, keepdims=True)
Exemplo n.º 9
0
 def step(self, action):
     force = self.torque_scale * action
     angle_cos = ivy.cos(self.angle)
     angle_sin = ivy.sin(self.angle)
     temp = (
         (force + self.pole_mass_length * self.angle_vel**2 * angle_sin) /
         self.total_mass)
     angle_acc = (
         (self.g * angle_sin - angle_cos * temp) /
         (self.pole_length *
          (4.0 / 3.0 - self.pole_mass * angle_cos**2 / self.total_mass)))
     x_acc = (
         temp -
         self.pole_mass_length * angle_acc * angle_cos / self.total_mass)
     self.x_vel = self.x_vel + self.dt * x_acc
     self.x = self.x + self.dt * self.x_vel
     self.angle_vel = self.angle_vel + self.dt * angle_acc
     self.angle = self.angle + self.dt * self.angle_vel
     return self.get_observation(), self.get_reward(), False, {}
Exemplo n.º 10
0
def axis_angle_to_quaternion(axis_angle):
    """
    Convert rotation axis unit vector :math:`\mathbf{e} = [e_x, e_y, e_z]` and rotation angle :math:`θ` to quaternion
    :math:`\mathbf{q} = [q_i, q_j, q_k, q_r]`.\n
    `[reference] <https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Quaternions>`_

    :param axis_angle: Axis to rotate about and angle to rotate *[batch_shape,4]*
    :type axis_angle: array
    :return: Quaternion *[batch_shape,4]*
    """

    # BS x 1
    angle = axis_angle[..., -1:]
    n = _ivy.cos(angle / 2)
    e1 = _ivy.sin(angle / 2) * axis_angle[..., 0:1]
    e2 = _ivy.sin(angle / 2) * axis_angle[..., 1:2]
    e3 = _ivy.sin(angle / 2) * axis_angle[..., 2:3]

    # BS x 4
    quaternion = _ivy.concatenate((e1, e2, e3, n), -1)
    return quaternion
Exemplo n.º 11
0
    def render(self, mode='human'):
        """
        Renders the environment.
        The set of supported modes varies per environment. (And some
        environments do not support rendering at all.) By convention,
        if mode is:

        - human: render to the current display or terminal and
          return nothing. Usually for human consumption.
        - rgb_array: Return an numpy.ndarray with shape (x, y, 3),
          representing RGB values for an x-by-y pixel image, suitable
          for turning into a video.
        - ansi: Return a string (str) or StringIO.StringIO containing a
          terminal-style text representation. The text can include newlines
          and ANSI escape sequences (e.g. for colors).

        :param mode: Render mode, one of [human|rgb_array], default human
        :type mode: str, optional
        :return: Rendered image.
        """
        if self.viewer is None:
            # noinspection PyBroadException
            try:
                from gym.envs.classic_control import rendering
            except:
                if not self._logged_headless_message:
                    print(
                        'Unable to connect to display. Running the Ivy environment in headless mode...'
                    )
                    self._logged_headless_message = True
                return
            self.viewer = rendering.Viewer(500, 500)
            bound = self.num_joints + 0.2
            self.viewer.set_bounds(-bound, bound, -bound, bound)

            # Goal.
            goal_geom = rendering.make_circle(0.2)
            goal_geom.set_color(0.4, 0.6, 1.)
            self.goal_tr = rendering.Transform()
            goal_geom.add_attr(self.goal_tr)
            self.viewer.add_geom(goal_geom)

            # Arm segments and joints.
            l, r, t, b = 0, 1., 0.1, -0.1
            self.segment_trs = []
            for _ in range(self.num_joints):
                # Segment.
                segment_geom = rendering.FilledPolygon([(l, b), (l, t), (r, t),
                                                        (r, b)])
                segment_tr = rendering.Transform()
                self.segment_trs.append(segment_tr)
                segment_geom.add_attr(segment_tr)
                segment_geom.set_color(0., 0., 0.)
                self.viewer.add_geom(segment_geom)

                # Joint.
                joint_geom = rendering.make_circle(0.1)
                joint_geom.set_color(0.5, 0.5, 0.5)
                joint_geom.add_attr(segment_tr)
                self.viewer.add_geom(joint_geom)

            # End effector.
            self.end_geom = rendering.make_circle(0.1)
            self.end_tr = rendering.Transform()
            self.end_geom.add_attr(self.end_tr)
            self.viewer.add_geom(self.end_geom)

        self.goal_tr.set_translation(*ivy.to_numpy(self.goal_xy).tolist())

        x, y = 0., 0.
        for segment_tr, angle in zip(self.segment_trs,
                                     ivy.reshape(self.angles, (-1, 1))):
            segment_tr.set_rotation(ivy.to_numpy(angle)[0])
            segment_tr.set_translation(x, y)
            x = ivy.to_numpy(x + ivy.cos(ivy.expand_dims(angle, 0))[0])[0]
            y = ivy.to_numpy(y + ivy.sin(ivy.expand_dims(angle, 0))[0])[0]
        self.end_tr.set_translation(x, y)
        rew = ivy.to_numpy(self.get_reward())[0]
        self.end_geom.set_color(1 - rew, rew, 0.)

        return self.viewer.render(return_rgb_array=mode == 'rgb_array')
Exemplo n.º 12
0
    def render(self, mode='human'):
        """
        Renders the environment.
        The set of supported modes varies per environment. (And some
        environments do not support rendering at all.) By convention,
        if mode is:

        - human: render to the current display or terminal and
          return nothing. Usually for human consumption.
        - rgb_array: Return an numpy.ndarray with shape (x, y, 3),
          representing RGB values for an x-by-y pixel image, suitable
          for turning into a video.
        - ansi: Return a string (str) or StringIO.StringIO containing a
          terminal-style text representation. The text can include newlines
          and ANSI escape sequences (e.g. for colors).

        :param mode: Render mode, one of [human|rgb_array], default human
        :type mode: str, optional
        :return: Rendered image.
        """
        screen_width = 500
        screen_height = 500
        x_min = -1.2
        x_max = 0.6
        world_width = x_max - x_min
        scale = screen_width / world_width
        car_width = 40
        car_height = 20

        if self.viewer is None:
            # noinspection PyBroadException
            try:
                from gym.envs.classic_control import rendering
            except:
                if not self._logged_headless_message:
                    print('Unable to connect to display. Running the Ivy environment in headless mode...')
                    self._logged_headless_message = True
                return

            self.viewer = rendering.Viewer(screen_width, screen_height)

            # Track.
            xs = ivy.linspace(x_min, x_max, 100)
            ys = self._height(xs)
            xys = list((ivy.to_numpy(xt).item(), ivy.to_numpy(yt).item())
                       for xt, yt in zip((xs - x_min) * scale, ys * scale))
            self.track = rendering.make_polyline(xys)
            self.track.set_linewidth(2)
            self.viewer.add_geom(self.track)

            # Car.
            clearance = 10
            l, r, t, b = -car_width / 2, car_width / 2, car_height, 0
            self.car_geom = rendering.FilledPolygon(
                [(l, b), (l, t), (r, t), (r, b)])
            self.car_geom.add_attr(
                rendering.Transform(translation=(0, clearance)))
            self.car_tr = rendering.Transform()
            self.car_geom.add_attr(self.car_tr)
            self.viewer.add_geom(self.car_geom)

            # Wheels.
            front_wheel = rendering.make_circle(car_height / 2.5)
            front_wheel.set_color(0.5, 0.5, 0.5)
            front_wheel.add_attr(
                rendering.Transform(translation=(car_width / 4, clearance)))
            front_wheel.add_attr(self.car_tr)
            self.viewer.add_geom(front_wheel)
            back_wheel = rendering.make_circle(car_height / 2.5)
            back_wheel.add_attr(
                rendering.Transform(translation=(-car_width / 4, clearance)))
            back_wheel.add_attr(self.car_tr)
            back_wheel.set_color(0.5, 0.5, 0.5)
            self.viewer.add_geom(back_wheel)

            # Flag.
            flag_x = (ivy.to_numpy(self.goal_x)[0] - x_min) * scale
            flagy_y1 = ivy.to_numpy(self._height(self.goal_x))[0] * scale
            flagy_y2 = flagy_y1 + 50
            flagpole = rendering.Line((flag_x, flagy_y1), (flag_x, flagy_y2))
            self.viewer.add_geom(flagpole)
            flag = rendering.FilledPolygon(
                [(flag_x, flagy_y2), (flag_x, flagy_y2 - 10),
                 (flag_x + 25, flagy_y2 - 5)])
            flag.set_color(0.4, 0.6, 1.)
            self.viewer.add_geom(flag)

        self.car_tr.set_translation(
            (ivy.to_numpy(self.x)[0] - x_min) * scale, ivy.to_numpy(self._height(self.x))[0] * scale)
        self.car_tr.set_rotation(ivy.to_numpy(ivy.cos(3 * self.x))[0])
        rew = ivy.to_numpy(self.get_reward()).item()
        self.car_geom.set_color(1 - rew, rew, 0.)

        return self.viewer.render(return_rgb_array=mode == 'rgb_array')
Exemplo n.º 13
0
 def step(self, action):
     x_acc = action * self.torque_scale - self.g * ivy.cos(3 * self.x)
     self.x_vel = self.x_vel + self.dt * x_acc
     self.x = self.x + self.dt * self.x_vel
     return self.get_observation(), self.get_reward(), False, {}
Exemplo n.º 14
0
    def __init__(self, a_s, d_s, alpha_s, dh_joint_scales, dh_joint_offsets, base_inv_ext_mat=None):
        """
        Initialize robot manipulator instance

        :param a_s: Denavit–Hartenberg "a" parameters *[num_joints]*
        :type a_s: array
        :param d_s: Denavit–Hartenberg "d" parameters *[num_joints]*
        :type d_s: array
        :param alpha_s: Denavit–Hartenberg "alpha" parameters *[num_joints]*
        :type alpha_s: array
        :param dh_joint_scales: Scalars to apply to input joints *[num_joints]*
        :type dh_joint_scales: array
        :param dh_joint_offsets: Scalar offsets to apply to input joints *[num_joints]*
        :type dh_joint_offsets: array
        :param base_inv_ext_mat: Inverse extrinsic matrix of the robot base *[4,4]*
        :type base_inv_ext_mat: array, optional
        """

        self._num_joints = a_s.shape[-1]
        # ToDo: incorporate the base_inv_ext_mat more elegantly, instead of the hack as in the sample_links method
        if base_inv_ext_mat is None:
            self._base_inv_ext_mat = _ivy.identity(4)
        else:
            self._base_inv_ext_mat = base_inv_ext_mat

        # NJ
        self._dis = d_s
        self._dh_joint_scales = dh_joint_scales
        self._dh_joint_offsets = dh_joint_offsets

        # Forward Kinematics Constant Matrices

        # Based on Denavit-Hartenberg Convention
        # Using same nomenclature as in:
        # Modelling, Planning and Control. Bruno Siciliano, Lorenzo Sciavicco, Luigi Villani, Giuseppe Oriolo
        # page 61 - 65

        AidashtoAis_list = [_ivy.identity(4, batch_shape=[1])]

        # repeated blocks

        # 1 x 1 x 3
        start_of_top_row = _ivy.array([[[1., 0., 0.]]])

        # 1 x 1 x 1
        zeros = _ivy.zeros((1, 1, 1))

        # 1 x 1 x 4
        bottom_row = _ivy.array([[[0., 0., 0., 1.]]])

        for i in range(self._num_joints):
            # 1 x 1 x 1
            a_i = _ivy.reshape(a_s[i], [1] * 3)
            cos_alpha = _ivy.reshape(_ivy.cos(alpha_s[i]), [1] * 3)
            sin_alpha = _ivy.reshape(_ivy.sin(alpha_s[i]), [1] * 3)

            # 1 x 1 x 4
            top_row = _ivy.concatenate((start_of_top_row, a_i), -1)
            top_middle_row = _ivy.concatenate((zeros, cos_alpha, -sin_alpha, zeros), -1)
            bottom_middle_row = _ivy.concatenate((zeros, sin_alpha, cos_alpha, zeros), -1)

            # 1 x 4 x 4
            AidashtoAi = _ivy.concatenate((top_row, top_middle_row, bottom_middle_row, bottom_row), 1)

            # list
            AidashtoAis_list.append(AidashtoAi)

        # NJ x 4 x 4
        self._AidashtoAis = _ivy.concatenate(AidashtoAis_list, 0)

        # Constant Jacobian Params

        # Using same nomenclature as in:
        # Modelling, Planning and Control. Bruno Siciliano, Lorenzo Sciavicco, Luigi Villani, Giuseppe Oriolo
        # page 111 - 113

        # 1 x 3
        self._z0 = _ivy.array([[0],
                                  [0],
                                  [1]])

        # 1 x 4
        self._p0hat = _ivy.array([[0],
                                     [0],
                                     [0],
                                     [1]])

        # link lengths

        # NJ
        self._link_lengths = (a_s ** 2 + d_s ** 2) ** 0.5
Exemplo n.º 15
0
    def compute_link_matrices(self, joint_angles, link_num, batch_shape=None):
        """
        Compute homogeneous transformation matrices relative to base frame, up to link_num of links.

        :param joint_angles: Joint angles of the robot *[batch_shape,num_joints]*
        :type joint_angles: array
        :param link_num: Link number for which to compute matrices up to
        :type link_num: int
        :param batch_shape: Shape of batch. Inferred from inputs if None.
        :type batch_shape: sequence of ints, optional
        :return: The link_num matrices, up the link_num *[batch_shape,link_num,4,4]*
        """

        if batch_shape is None:
            batch_shape = joint_angles.shape[:-1]
        batch_shape = list(batch_shape)
        num_batch_dims = len(batch_shape)

        # BS x 1 x NJ
        try:
            dh_joint_angles = _ivy.expand_dims(joint_angles * self._dh_joint_scales - self._dh_joint_offsets, -2)
        except:
            d = 0

        # BS x 1 x 4 x 4
        A00 = _ivy.identity(4, batch_shape=batch_shape + [1])

        Aitoip1dashs = list()
        Aiip1s = list()
        A0is = [A00]

        # repeated blocks

        # BS x 1 x NJ
        dis = _ivy.tile(_ivy.reshape(self._dis, [1] * num_batch_dims + [1, self._num_joints]),
                           batch_shape + [1, 1])

        # BS x 1 x 4
        bottom_row = _ivy.tile(
            _ivy.reshape(_ivy.array([0., 0., 0., 1.]), [1] * num_batch_dims + [1, 4]),
            batch_shape + [1, 1])

        # BS x 1 x 3
        start_of_bottom_middle = _ivy.tile(
            _ivy.reshape(_ivy.array([0., 0., 1.]), [1] * num_batch_dims + [1, 3]),
            batch_shape + [1, 1])

        # BS x 1 x 2
        zeros = _ivy.zeros(batch_shape + [1, 2])

        for i in range(self._num_joints):

            # BS x 1 x 4
            top_row = _ivy.concatenate((_ivy.cos(dh_joint_angles[..., i:i + 1]),
                                           -_ivy.sin(dh_joint_angles[..., i:i + 1]), zeros), -1)
            top_middle_row = _ivy.concatenate((_ivy.sin(dh_joint_angles[..., i:i + 1]),
                                                  _ivy.cos(dh_joint_angles[..., i:i + 1]), zeros), -1)
            bottom_middle_row = _ivy.concatenate((start_of_bottom_middle, dis[..., i:i + 1]), -1)

            # BS x 4 x 4
            Aitoip1dash = _ivy.concatenate((top_row, top_middle_row, bottom_middle_row, bottom_row), -2)

            # (BSx4) x 4
            Aitoip1dash_flat = _ivy.reshape(Aitoip1dash, (-1, 4))

            # (BSx4) x 4
            Aiip1_flat = _ivy.matmul(Aitoip1dash_flat, self._AidashtoAis[i + 1])

            # BS x 4 x 4
            Aiip1 = _ivy.reshape(Aiip1_flat, batch_shape + [4, 4])

            # BS x 4 x 4
            A0ip1 = _ivy.matmul(A0is[-1][..., 0, :, :], Aiip1)

            # append term to lists
            Aitoip1dashs.append(Aitoip1dash)
            Aiip1s.append(Aiip1)
            A0is.append(_ivy.expand_dims(A0ip1, -3))

            if i + 1 == link_num:
                # BS x LN x 4 x 4
                return _ivy.concatenate(A0is, -3)

        raise Exception('wrong parameter entered for link_num, please enter integer from 1-' + str(self._num_joints))