Пример #1
0
    def get_feedback_response(self, state, pos_des, vel_des, acc_des, jerk_des,
                              snap_des):
        X = slice(0, 3)
        V = slice(3, 6)
        RPY = slice(6, 9)
        OM = slice(9, 12)
        U = slice(0, 1)
        AA = slice(1, 4)

        pos = state[X]
        vel = state[V]

        rpy = state[RPY]
        angvel = state[OM]
        rot = Rotation.from_euler('ZYX', rpy[::-1])
        z = rot.apply(np.array((0, 0, 1)))

        roll, pitch, yaw = rpy

        dzdrpy = np.array(((np.sin(yaw) * np.cos(roll) -
                            np.sin(roll) * np.cos(yaw) * np.sin(pitch),
                            np.cos(roll) * np.cos(yaw) * np.cos(pitch),
                            np.sin(roll) * np.cos(yaw) -
                            np.cos(roll) * np.sin(yaw) * np.sin(pitch)),
                           (-np.sin(roll) * np.sin(yaw) * np.sin(pitch) -
                            np.cos(yaw) * np.cos(roll),
                            np.cos(roll) * np.sin(yaw) * np.cos(pitch),
                            np.cos(roll) * np.cos(yaw) * np.sin(pitch) +
                            np.sin(yaw) * np.sin(roll)),
                           (-np.cos(pitch) * np.sin(roll),
                            -np.sin(pitch) * np.cos(roll), 0)))

        skew_z = math_utils.skew_matrix(z)

        pos_vel = state[:6]
        accel_des = -self.K_pos.dot(pos_vel - np.hstack(
            (pos_des, vel_des))) + acc_des + g3
        adota = accel_des.T.dot(accel_des)
        u = np.sqrt(adota)

        K_x = np.zeros((self.n_control, self.n_state))

        adir = accel_des / u

        dadx = -self.K_pos[:, X]
        dadv = -self.K_pos[:, V]

        dudx = adir.dot(dadx)
        dudv = adir.dot(dadv)

        K_x[U, X] = dudx
        K_x[U, V] = dudv

        dzdx = (u * dadx - np.outer(accel_des, dudx)) / adota
        dzdv = (u * dadv - np.outer(accel_des, dudv)) / adota

        z = adir
        deulerdz = np.zeros((3, 3))
        a1 = 1 / np.sqrt(1 - z[1]**2)
        deulerdz[0, 1] = -a1
        deulerdz[1, 0] = 1 / np.sqrt(1 - (z[0] * a1)**2)
        deulerdz[1, 1] = z[0] * z[1] / (np.sqrt(1 - (z[0] * a1)**2) *
                                        ((1 - z[1]**2)**(3 / 2)))

        K_x[AA, X] = self.K_att[:, :3].dot(deulerdz.dot(dzdx))
        K_x[AA, V] = self.K_att[:, :3].dot(deulerdz.dot(dzdv))

        K_x[AA, RPY] = -self.K_att[:, :3]
        K_x[AA, OM] = -self.K_att[:, 3:6]

        return K_x
Пример #2
0
    def get_feedback_response(self, state, pos_des, vel_des, acc_des, jerk_des,
                              snap_des):
        X = slice(0, 3)
        V = slice(3, 6)
        RPY = slice(6, 9)
        OM = slice(9, 12)
        U = slice(0, 1)
        AA = slice(1, 4)

        pos = state[X]
        vel = state[V]

        rpy = state[RPY]
        angvel = state[OM]
        rot = Rotation.from_euler('ZYX', rpy[::-1])
        z = rot.apply(np.array((0, 0, 1)))

        skew_z = math_utils.skew_matrix(z)

        skew_angvel_w = math_utils.skew_matrix(rot.apply(angvel))
        z_dot = skew_angvel_w.dot(z)

        roll, pitch, yaw = rpy

        dzdrpy = np.array(((np.sin(yaw) * np.cos(roll) -
                            np.sin(roll) * np.cos(yaw) * np.sin(pitch),
                            np.cos(roll) * np.cos(yaw) * np.cos(pitch),
                            np.sin(roll) * np.cos(yaw) -
                            np.cos(roll) * np.sin(yaw) * np.sin(pitch)),
                           (-np.sin(roll) * np.sin(yaw) * np.sin(pitch) -
                            np.cos(yaw) * np.cos(roll),
                            np.cos(roll) * np.sin(yaw) * np.cos(pitch),
                            np.cos(roll) * np.cos(yaw) * np.sin(pitch) +
                            np.sin(yaw) * np.sin(roll)),
                           (-np.cos(pitch) * np.sin(roll),
                            -np.sin(pitch) * np.cos(roll), 0)))

        dzdotdrpy = skew_angvel_w.dot(dzdrpy)

        dzdotdang = -skew_z.dot(rot.as_dcm())

        u, udot = self.int_u, self.int_udot

        k1 = 840 * np.eye(3) / self.duration**4
        k2 = 480 * np.eye(3) / self.duration**3
        k3 = 120 * np.eye(3) / self.duration**2
        k4 = 16 * np.eye(3) / self.duration**1

        start_acc = u * z - g3
        start_jerk = u * z_dot + udot * z

        pos_err = pos - pos_des
        vel_err = vel - vel_des
        acc_err = start_acc - acc_des
        jerk_err = start_jerk - jerk_des

        djerkdrpy = u * dzdotdrpy + udot * dzdrpy
        daccdrpy = u * dzdrpy

        dsnapdrpy = -k3.dot(daccdrpy) - k4.dot(djerkdrpy)

        snap = -k1.dot(pos_err) - k2.dot(vel_err) - k3.dot(acc_err) - k4.dot(
            jerk_err) + snap_des
        dv1drpy = dsnapdrpy.T.dot(z) + snap.dot(
            dzdrpy) + 2 * u * z_dot.T.dot(dzdotdrpy)

        v1 = snap.dot(z) + u * z_dot.dot(z_dot)

        u_factor = 1.0 / u
        z_ddot = u_factor * (snap - v1 * z - 2 * udot * z_dot)

        dzddotdrpy = u_factor * (dsnapdrpy - np.outer(dv1drpy, z) -
                                 v1 * dzdrpy - 2 * udot * dzdotdrpy)

        dalphadrpy = skew_z.dot(dzddotdrpy - skew_angvel_w.dot(
            dzdotdrpy)) - math_utils.skew_matrix(
                z_ddot - skew_angvel_w.dot(z_dot)).dot(dzdrpy)

        djerkdang = u * dzdotdang
        dsnapdang = -k4.dot(djerkdang)
        dv1dang = dsnapdang.T.dot(z) + 2 * u * z_dot.T.dot(dzdotdang)
        dzddotdang = u_factor * (dsnapdang - np.outer(dv1dang, z) -
                                 2 * udot * dzdotdang)
        # TODO XXX This is missing the omega cross zdot term.
        dalphawdang = skew_z.dot(dzddotdang)
        dalphabdang = rot.inv().apply(dalphawdang)

        dsnapdpos = -k1
        dsnapdvel = -k2

        dv1dpos = dsnapdpos.dot(z)
        dv1dvel = dsnapdvel.dot(z)

        dzddotdpos = u_factor * (dsnapdpos - np.outer(dv1dpos, z))
        dzddotdvel = u_factor * (dsnapdvel - np.outer(dv1dvel, z))

        dalphadpos = skew_z.dot(dzddotdpos)
        dalphadvel = skew_z.dot(dzddotdvel)

        fb_resp = np.zeros((self.n_control, self.n_state))
        fb_resp[AA, RPY] = dalphadrpy
        fb_resp[AA, OM] = dalphabdang
        fb_resp[AA, X] = dalphadpos
        fb_resp[AA, V] = dalphadvel
        return fb_resp
Пример #3
0
  def get_feedback_response(self, state, pos_des, vel_des, acc_des, jerk_des, snap_des):
    X = slice(0, 3)
    V = slice(3, 6)
    RPY = slice(6, 9)
    OM = slice(9, 12)
    Z1 = slice(12, 13)
    Z2 = slice(13, 14)
    V1 = slice(0, 1)
    AA = slice(1, 4)

    pos = state[X]
    vel = state[V]

    rpy = state[RPY]
    angvel = state[OM]
    rot = Rotation.from_euler('ZYX', rpy[::-1])
    z = rot.apply(np.array((0, 0, 1)))

    roll, pitch, yaw = rpy

    dzdrpy = np.array((
      (np.sin(yaw) * np.cos(roll) - np.sin(roll) * np.cos(yaw) * np.sin(pitch), np.cos(roll) * np.cos(yaw) * np.cos(pitch), np.sin(roll) * np.cos(yaw) - np.cos(roll) * np.sin(yaw) * np.sin(pitch)),
      (-np.sin(roll) * np.sin(yaw) * np.sin(pitch) - np.cos(yaw) * np.cos(roll), np.cos(roll) * np.sin(yaw) * np.cos(pitch), np.cos(roll) * np.cos(yaw) * np.sin(pitch) + np.sin(yaw) * np.sin(roll)),
      (-np.cos(pitch) * np.sin(roll), -np.sin(pitch) * np.cos(roll), 0)
    ))

    skew_z = math_utils.skew_matrix(z)

    skew_angvel_w = math_utils.skew_matrix(rot.apply(angvel))
    z_dot = skew_angvel_w.dot(z)

    u, udot = self.int_u, self.int_udot

    k1 = 840 * np.eye(3) / self.duration ** 4
    k2 = 480 * np.eye(3) / self.duration ** 3
    k3 = 120 * np.eye(3) / self.duration ** 2
    k4 = 16 * np.eye(3) / self.duration ** 1

    dsdu = -k3.dot(z) - k4.dot(z_dot)
    dv1du = dsdu.T.dot(z) + z_dot.T.dot(z_dot)

    dsdudot = -k4.dot(z)
    dv1dudot = dsdudot.T.dot(z)

    K_x = np.zeros((self.n_control, self.n_state))

    K_x[V1, X] = -k1.T.dot(z)
    K_x[V1, V] = -k2.T.dot(z)
    K_x[V1, Z1] = dv1du
    K_x[V1, Z2] = dv1dudot

    fb_resp = Quad3DFL.get_feedback_response(self, state, pos_des, vel_des, acc_des, jerk_des, snap_des)

    K_x[AA, X] = fb_resp[AA, X]
    K_x[AA, V] = fb_resp[AA, V]
    K_x[AA, RPY] = fb_resp[AA, RPY]
    K_x[AA, OM] = fb_resp[AA, OM]

    skew_z = math_utils.skew_matrix(z)

    dzdotdang = -skew_z.dot(rot.as_dcm())

    start_acc = u * z - g3
    start_jerk = u * z_dot + udot * z

    pos_err = pos - pos_des
    vel_err = vel - vel_des
    acc_err = start_acc - acc_des
    jerk_err = start_jerk - jerk_des

    dzdotdrpy = skew_angvel_w.dot(dzdrpy)

    djerkdrpy = u * dzdotdrpy + udot * dzdrpy
    daccdrpy = u * dzdrpy

    dsnapdrpy = -k3.dot(daccdrpy) - k4.dot(djerkdrpy)

    snap = -k1.dot(pos_err) - k2.dot(vel_err) - k3.dot(acc_err) - k4.dot(jerk_err) + snap_des
    dv1drpy = dsnapdrpy.T.dot(z) + snap.dot(dzdrpy) + 2 * u * z_dot.T.dot(dzdotdrpy)

    #print(snap, z)
    #print(dsnapdrpy[:, 0])
    ##print(daccdrpy[:, 0])
    ##print(dzdrpy[:, 0])
    #input()

    djerkdang = u * dzdotdang
    dsnapdang = -k4.dot(djerkdang)
    dv1dang = dsnapdang.T.dot(z) + 2 * u * z_dot.T.dot(dzdotdang)

    K_x[V1, RPY] = dv1drpy
    K_x[V1, OM] = dv1dang

    v1 = snap.dot(z) + u * z_dot.dot(z_dot)
    dzddotdu = (1.0 / u) * (dsdu - dv1du * z) - (1.0 / u ** 2) * (snap - v1 * z - 2 * udot * z_dot)
    dalphadu = rot.inv().apply(skew_z.dot(dzddotdu))

    dzddotdudot = (1.0 / u) * (dsdudot - dv1dudot * z - 2 * z_dot)
    dalphadudot = rot.inv().apply(skew_z.dot(dzddotdudot))

    K_x[AA, Z1] = np.array([dalphadu]).T
    K_x[AA, Z2] = np.array([dalphadudot]).T

    return K_x
Пример #4
0
    def get_ABCD(self, state, control, dt):
        X = slice(0, 3)
        V = slice(3, 6)
        RPY = slice(6, 9)
        OM = slice(9, 12)
        U = slice(0, 1)
        AA = slice(1, 4)

        pos = state[X]
        vel = state[V]

        ind = self.iter - 1 if self.iter >= len(self.zs) - 1 else self.iter
        u, udot = self.zs[ind]

        rpy = state[RPY]
        angvel = state[OM]
        rot = Rotation.from_euler('ZYX', rpy[::-1])
        z = rot.apply(np.array((0, 0, 1)))

        z_dot = math_utils.skew_matrix(rot.apply(angvel)).dot(z)

        roll, pitch, yaw = rpy

        dzdrpy = np.array(((np.sin(yaw) * np.cos(roll) -
                            np.sin(roll) * np.cos(yaw) * np.sin(pitch),
                            np.cos(roll) * np.cos(yaw) * np.cos(pitch),
                            np.sin(roll) * np.cos(yaw) -
                            np.cos(roll) * np.sin(yaw) * np.sin(pitch)),
                           (-np.sin(roll) * np.sin(yaw) * np.sin(pitch) -
                            np.cos(yaw) * np.cos(roll),
                            np.cos(roll) * np.sin(yaw) * np.cos(pitch),
                            np.cos(roll) * np.cos(yaw) * np.sin(pitch) +
                            np.sin(yaw) * np.sin(roll)),
                           (-np.cos(pitch) * np.sin(roll),
                            -np.sin(pitch) * np.cos(roll), 0)))

        A = np.zeros((self.n_state, self.n_state))
        B = np.zeros((self.n_state, self.n_control))
        C = np.zeros((self.n_out, self.n_state))
        D = np.zeros((self.n_out, self.n_control))

        A[X, X] = np.eye(3)
        A[V, V] = np.eye(3)
        A[X, V] = dt * np.eye(3)

        A[RPY, RPY] = np.eye(3)
        A[OM, OM] = np.eye(3)

        #A[V, Z] = u * dt * np.eye(3)
        A[V, RPY] = u * dt * dzdrpy
        # TODO Need to fix this because om is in the body frame!
        #A[Z, OM] = -dt * math_utils.skew_matrix(z)

        # Below taken from Tal and Karaman 2018 - Accurate Tracking of ...
        A[RPY, OM] = dt * np.array(
            ((1, np.sin(roll) * np.tan(pitch), np.cos(roll) * np.tan(pitch)),
             (0, np.cos(roll), -np.sin(roll)),
             (0, np.sin(roll) / np.cos(pitch), np.cos(roll) / np.cos(pitch))))

        B[V, U] = dt * np.array([z]).T
        B[OM, AA] = dt * np.eye(3)

        # Trying 2D mats.......
        #ct = np.cos(rpy[0])
        #st = np.sin(rpy[0])
        #A[V, 6:7] = u * dt * np.array(((0, -ct, -st),)).T
        #A[6, 9] = dt
        #########################33

        C[X, X] = np.eye(3)

        if self.use_feedback:
            K_x = np.zeros((self.n_control, self.n_state))
            K_u = np.zeros((self.n_control, self.n_control))

            oldu = self.int_u
            oldudot = self.int_udot

            self.int_u = u
            self.int_udot = udot

            K_x = self.get_feedback_response(state, self.pos_des, self.vel_des,
                                             self.acc_des, self.jerk_des,
                                             self.snap_des)

            self.int_u = oldu
            self.int_udot = oldudot

            K_u[U, U] = 1
            K_u[AA, AA] = np.eye(3)

            A = A + B.dot(K_x)
            B = B.dot(K_u)

        return A, B, C, D
Пример #5
0
  def feedback(self, x, pos_des, vel_des, acc_des, jerk_des, snap_des, u_ff, angaccel_des, integrate=True):
    pos = x[:3]
    vel = x[3:6]
    rpy = x[6:9]
    ang_vel = x[9:]

    self.zs.append(np.array((self.int_u, self.int_udot)))

    rot = Rotation.from_euler('ZYX', rpy[::-1])
    ang_vel = x[9:]
    rot_m = rot.as_dcm()
    self.x_b_act = rot_m[:, 0]
    self.y_b_act = rot_m[:, 1]
    self.z_b_act = z_b_act = rot_m[:, 2]

    z_b_dot_act = math_utils.skew_matrix(rot.apply(ang_vel)).dot(z_b_act)

    u = self.int_u
    udot = self.int_udot

    if self.model_drag:
      drag_dist_control = self.drag_dist
    else:
      drag_dist_control = 0

    start_acc = u * z_b_act - g3 - drag_dist_control * vel
    start_jerk = u * z_b_dot_act + udot * z_b_act - drag_dist_control * start_acc

    self.z = z_b_act
    self.acc = start_acc

    pos_err = pos - pos_des
    vel_err = vel - vel_des
    acc_err = start_acc - acc_des
    jerk_err = start_jerk - jerk_des

    k1 = 840 * np.eye(3) / self.duration ** 4
    k2 = 480 * np.eye(3) / self.duration ** 3
    k3 = 120 * np.eye(3) / self.duration ** 2
    k4 = 16 * np.eye(3) / self.duration ** 1

    # Linear controller
    snap = -k1.dot(pos_err) - k2.dot(vel_err) - k3.dot(acc_err) - k4.dot(jerk_err) + snap_des

    self.snap = snap

    v1 = snap.dot(z_b_act) + u * z_b_dot_act.dot(z_b_dot_act) + drag_dist_control * start_jerk.dot(z_b_act) + u_ff

    self.v1 = v1

    z_ddot = (1 / u) * (snap - v1 * z_b_act - 2 * udot * z_b_dot_act + drag_dist_control * start_jerk)

    # TODO: How proper is this for x and y motion? And yaw motion?
    ang_acc_body = np.cross(z_b_act, z_ddot) + angaccel_des

    u_ret = self.int_u

    if integrate:
      self.int_u += self.int_udot * self.dt + 0.5 * v1 * self.dt ** 2
      self.int_udot += v1 * self.dt

    control = np.hstack((u_ret, ang_acc_body))
    return control