Ejemplo n.º 1
0
    def generate_code(generated_dir):
        name = LiveKalman.name
        dim_state = LiveKalman.initial_x.shape[0]
        dim_state_err = LiveKalman.initial_P_diag.shape[0]

        state_sym = sp.MatrixSymbol('state', dim_state, 1)
        state = sp.Matrix(state_sym)
        x, y, z = state[States.ECEF_POS, :]
        q = state[States.ECEF_ORIENTATION, :]
        v = state[States.ECEF_VELOCITY, :]
        vx, vy, vz = v
        omega = state[States.ANGULAR_VELOCITY, :]
        vroll, vpitch, vyaw = omega
        roll_bias, pitch_bias, yaw_bias = state[States.GYRO_BIAS, :]
        acceleration = state[States.ACCELERATION, :]
        acc_bias = state[States.ACC_BIAS, :]

        dt = sp.Symbol('dt')

        # calibration and attitude rotation matrices
        quat_rot = quat_rotate(*q)

        # Got the quat predict equations from here
        # A New Quaternion-Based Kalman Filter for
        # Real-Time Attitude Estimation Using the Two-Step
        # Geometrically-Intuitive Correction Algorithm
        A = 0.5 * sp.Matrix(
            [[0, -vroll, -vpitch, -vyaw], [vroll, 0, vyaw, -vpitch],
             [vpitch, -vyaw, 0, vroll], [vyaw, vpitch, -vroll, 0]])
        q_dot = A * q

        # Time derivative of the state as a function of state
        state_dot = sp.Matrix(np.zeros((dim_state, 1)))
        state_dot[States.ECEF_POS, :] = v
        state_dot[States.ECEF_ORIENTATION, :] = q_dot
        state_dot[States.ECEF_VELOCITY, 0] = quat_rot * acceleration

        # Basic descretization, 1st order intergrator
        # Can be pretty bad if dt is big
        f_sym = state + dt * state_dot

        state_err_sym = sp.MatrixSymbol('state_err', dim_state_err, 1)
        state_err = sp.Matrix(state_err_sym)
        quat_err = state_err[States.ECEF_ORIENTATION_ERR, :]
        v_err = state_err[States.ECEF_VELOCITY_ERR, :]
        omega_err = state_err[States.ANGULAR_VELOCITY_ERR, :]
        acceleration_err = state_err[States.ACCELERATION_ERR, :]

        # Time derivative of the state error as a function of state error and state
        quat_err_matrix = euler_rotate(quat_err[0], quat_err[1], quat_err[2])
        q_err_dot = quat_err_matrix * quat_rot * (omega + omega_err)
        state_err_dot = sp.Matrix(np.zeros((dim_state_err, 1)))
        state_err_dot[States.ECEF_POS_ERR, :] = v_err
        state_err_dot[States.ECEF_ORIENTATION_ERR, :] = q_err_dot
        state_err_dot[
            States.ECEF_VELOCITY_ERR, :] = quat_err_matrix * quat_rot * (
                acceleration + acceleration_err)
        f_err_sym = state_err + dt * state_err_dot

        # Observation matrix modifier
        H_mod_sym = sp.Matrix(np.zeros((dim_state, dim_state_err)))
        H_mod_sym[States.ECEF_POS,
                  States.ECEF_POS_ERR] = np.eye(States.ECEF_POS.stop -
                                                States.ECEF_POS.start)
        H_mod_sym[States.ECEF_ORIENTATION,
                  States.ECEF_ORIENTATION_ERR] = 0.5 * quat_matrix_r(
                      state[3:7])[:, 1:]
        H_mod_sym[States.ECEF_ORIENTATION.stop:,
                  States.ECEF_ORIENTATION_ERR.stop:] = np.eye(
                      dim_state - States.ECEF_ORIENTATION.stop)

        # these error functions are defined so that say there
        # is a nominal x and true x:
        # true x = err_function(nominal x, delta x)
        # delta x = inv_err_function(nominal x, true x)
        nom_x = sp.MatrixSymbol('nom_x', dim_state, 1)
        true_x = sp.MatrixSymbol('true_x', dim_state, 1)
        delta_x = sp.MatrixSymbol('delta_x', dim_state_err, 1)

        err_function_sym = sp.Matrix(np.zeros((dim_state, 1)))
        delta_quat = sp.Matrix(np.ones((4)))
        delta_quat[1:, :] = sp.Matrix(0.5 *
                                      delta_x[States.ECEF_ORIENTATION_ERR, :])
        err_function_sym[States.ECEF_POS, :] = sp.Matrix(
            nom_x[States.ECEF_POS, :] + delta_x[States.ECEF_POS_ERR, :])
        err_function_sym[States.ECEF_ORIENTATION, 0] = quat_matrix_r(
            nom_x[States.ECEF_ORIENTATION, 0]) * delta_quat
        err_function_sym[States.ECEF_ORIENTATION.stop:, :] = sp.Matrix(
            nom_x[States.ECEF_ORIENTATION.stop:, :] +
            delta_x[States.ECEF_ORIENTATION_ERR.stop:, :])

        inv_err_function_sym = sp.Matrix(np.zeros((dim_state_err, 1)))
        inv_err_function_sym[States.ECEF_POS_ERR,
                             0] = sp.Matrix(-nom_x[States.ECEF_POS, 0] +
                                            true_x[States.ECEF_POS, 0])
        delta_quat = quat_matrix_r(
            nom_x[States.ECEF_ORIENTATION,
                  0]).T * true_x[States.ECEF_ORIENTATION, 0]
        inv_err_function_sym[States.ECEF_ORIENTATION_ERR,
                             0] = sp.Matrix(2 * delta_quat[1:])
        inv_err_function_sym[States.ECEF_ORIENTATION_ERR.stop:, 0] = sp.Matrix(
            -nom_x[States.ECEF_ORIENTATION.stop:, 0] +
            true_x[States.ECEF_ORIENTATION.stop:, 0])

        eskf_params = [[err_function_sym, nom_x, delta_x],
                       [inv_err_function_sym, nom_x, true_x], H_mod_sym,
                       f_err_sym, state_err_sym]
        #
        # Observation functions
        #
        h_gyro_sym = sp.Matrix(
            [vroll + roll_bias, vpitch + pitch_bias, vyaw + yaw_bias])

        pos = sp.Matrix([x, y, z])
        gravity = quat_rot.T * ((EARTH_GM /
                                 ((x**2 + y**2 + z**2)**(3.0 / 2.0))) * pos)
        h_acc_sym = (gravity + acceleration + acc_bias)
        h_acc_stationary_sym = acceleration
        h_phone_rot_sym = sp.Matrix([vroll, vpitch, vyaw])
        h_pos_sym = sp.Matrix([x, y, z])
        h_vel_sym = sp.Matrix([vx, vy, vz])
        h_orientation_sym = q
        h_relative_motion = sp.Matrix(quat_rot.T * v)

        obs_eqs = [
            [h_gyro_sym, ObservationKind.PHONE_GYRO, None],
            [h_phone_rot_sym, ObservationKind.NO_ROT, None],
            [h_acc_sym, ObservationKind.PHONE_ACCEL, None],
            [h_pos_sym, ObservationKind.ECEF_POS, None],
            [h_vel_sym, ObservationKind.ECEF_VEL, None],
            [
                h_orientation_sym, ObservationKind.ECEF_ORIENTATION_FROM_GPS,
                None
            ],
            [h_relative_motion, ObservationKind.CAMERA_ODO_TRANSLATION, None],
            [h_phone_rot_sym, ObservationKind.CAMERA_ODO_ROTATION, None],
            [h_acc_stationary_sym, ObservationKind.NO_ACCEL, None]
        ]

        # this returns a sympy routine for the jacobian of the observation function of the local vel
        in_vec = sp.MatrixSymbol('in_vec', 6,
                                 1)  # roll, pitch, yaw, vx, vy, vz
        h = euler_rotate(in_vec[0], in_vec[1], in_vec[2]).T * (sp.Matrix(
            [in_vec[3], in_vec[4], in_vec[5]]))
        extra_routines = [('H', h.jacobian(in_vec), [in_vec])]

        gen_code(generated_dir,
                 name,
                 f_sym,
                 dt,
                 state_sym,
                 obs_eqs,
                 dim_state,
                 dim_state_err,
                 eskf_params,
                 extra_routines=extra_routines)

        # write constants to extra header file for use in cpp
        live_kf_header = "#pragma once\n\n"
        live_kf_header += "#include <unordered_map>\n"
        live_kf_header += "#include <eigen3/Eigen/Dense>\n\n"
        for state, slc in inspect.getmembers(States,
                                             lambda x: type(x) == slice):
            assert (slc.step is None)  # unsupported
            live_kf_header += f'#define STATE_{state}_START {slc.start}\n'
            live_kf_header += f'#define STATE_{state}_END {slc.stop}\n'
            live_kf_header += f'#define STATE_{state}_LEN {slc.stop - slc.start}\n'
        live_kf_header += "\n"

        for kind, val in inspect.getmembers(ObservationKind,
                                            lambda x: type(x) == int):
            live_kf_header += f'#define OBSERVATION_{kind} {val}\n'
        live_kf_header += "\n"

        live_kf_header += f"static const Eigen::VectorXd live_initial_x = {numpy2eigenstring(LiveKalman.initial_x)};\n"
        live_kf_header += f"static const Eigen::VectorXd live_initial_P_diag = {numpy2eigenstring(LiveKalman.initial_P_diag)};\n"
        live_kf_header += f"static const Eigen::VectorXd live_fake_gps_pos_cov_diag = {numpy2eigenstring(LiveKalman.fake_gps_pos_cov_diag)};\n"
        live_kf_header += f"static const Eigen::VectorXd live_fake_gps_vel_cov_diag = {numpy2eigenstring(LiveKalman.fake_gps_vel_cov_diag)};\n"
        live_kf_header += f"static const Eigen::VectorXd live_reset_orientation_diag = {numpy2eigenstring(LiveKalman.reset_orientation_diag)};\n"
        live_kf_header += f"static const Eigen::VectorXd live_Q_diag = {numpy2eigenstring(LiveKalman.Q_diag)};\n"
        live_kf_header += "static const std::unordered_map<int, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> live_obs_noise_diag = {\n"
        for kind, noise in LiveKalman.obs_noise_diag.items():
            live_kf_header += f"  {{ {kind}, {numpy2eigenstring(noise)} }},\n"
        live_kf_header += "};\n\n"

        open(os.path.join(generated_dir, "live_kf_constants.h"),
             'w').write(live_kf_header)
Ejemplo n.º 2
0
def gen_code(name,
             f_sym,
             dt_sym,
             x_sym,
             obs_eqs,
             dim_x,
             dim_err,
             eskf_params=None,
             msckf_params=None,
             maha_test_kinds=[]):
    # optional state transition matrix, H modifier
    # and err_function if an error-state kalman filter (ESKF)
    # is desired. Best described in "Quaternion kinematics
    # for the error-state Kalman filter" by Joan Sola

    if eskf_params:
        err_eqs = eskf_params[0]
        inv_err_eqs = eskf_params[1]
        H_mod_sym = eskf_params[2]
        f_err_sym = eskf_params[3]
        x_err_sym = eskf_params[4]
    else:
        nom_x = sp.MatrixSymbol('nom_x', dim_x, 1)
        true_x = sp.MatrixSymbol('true_x', dim_x, 1)
        delta_x = sp.MatrixSymbol('delta_x', dim_x, 1)
        err_function_sym = sp.Matrix(nom_x + delta_x)
        inv_err_function_sym = sp.Matrix(true_x - nom_x)
        err_eqs = [err_function_sym, nom_x, delta_x]
        inv_err_eqs = [inv_err_function_sym, nom_x, true_x]

        H_mod_sym = sp.Matrix(np.eye(dim_x))
        f_err_sym = f_sym
        x_err_sym = x_sym

    # This configures the multi-state augmentation
    # needed for EKF-SLAM with MSCKF (Mourikis et al 2007)
    if msckf_params:
        msckf = True
        dim_main = msckf_params[0]  # size of the main state
        dim_augment = msckf_params[1]  # size of one augment state chunk
        dim_main_err = msckf_params[2]
        dim_augment_err = msckf_params[3]
        N = msckf_params[4]
        feature_track_kinds = msckf_params[5]
        assert dim_main + dim_augment * N == dim_x
        assert dim_main_err + dim_augment_err * N == dim_err
    else:
        msckf = False
        dim_main = dim_x
        dim_augment = 0
        dim_main_err = dim_err
        dim_augment_err = 0
        N = 0

    # linearize with jacobians
    F_sym = f_err_sym.jacobian(x_err_sym)
    for sym in x_err_sym:
        F_sym = F_sym.subs(sym, 0)
    for i in xrange(len(obs_eqs)):
        obs_eqs[i].append(obs_eqs[i][0].jacobian(x_sym))
        if msckf and obs_eqs[i][1] in feature_track_kinds:
            obs_eqs[i].append(obs_eqs[i][0].jacobian(obs_eqs[i][2]))
        else:
            obs_eqs[i].append(None)

    # collect sympy functions
    sympy_functions = []

    # error functions
    sympy_functions.append(('err_fun', err_eqs[0], [err_eqs[1], err_eqs[2]]))
    sympy_functions.append(
        ('inv_err_fun', inv_err_eqs[0], [inv_err_eqs[1], inv_err_eqs[2]]))

    # H modifier for ESKF updates
    sympy_functions.append(('H_mod_fun', H_mod_sym, [x_sym]))

    # state propagation function
    sympy_functions.append(('f_fun', f_sym, [x_sym, dt_sym]))
    sympy_functions.append(('F_fun', F_sym, [x_sym, dt_sym]))

    # observation functions
    for h_sym, kind, ea_sym, H_sym, He_sym in obs_eqs:
        sympy_functions.append(('h_%d' % kind, h_sym, [x_sym, ea_sym]))
        sympy_functions.append(('H_%d' % kind, H_sym, [x_sym, ea_sym]))
        if msckf and kind in feature_track_kinds:
            sympy_functions.append(('He_%d' % kind, He_sym, [x_sym, ea_sym]))

    # Generate and wrap all th c code
    header, code = sympy_into_c(sympy_functions)
    extra_header = "#define DIM %d\n" % dim_x
    extra_header += "#define EDIM %d\n" % dim_err
    extra_header += "#define MEDIM %d\n" % dim_main_err
    extra_header += "typedef void (*Hfun)(double *, double *, double *);\n"

    extra_header += "\nvoid predict(double *x, double *P, double *Q, double dt);"

    extra_post = ""

    for h_sym, kind, ea_sym, H_sym, He_sym in obs_eqs:
        if msckf and kind in feature_track_kinds:
            He_str = 'He_%d' % kind
            ea_dim = ea_sym.shape[0]
        else:
            He_str = 'NULL'
            ea_dim = 1  # not really dim of ea but makes c function work
        maha_thresh = chi2.ppf(0.95, int(
            h_sym.shape[0]))  # mahalanobis distance for outlier detection
        maha_test = kind in maha_test_kinds
        extra_post += """
      void update_%d(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea) {
        update<%d,%d,%d>(in_x, in_P, h_%d, H_%d, %s, in_z, in_R, in_ea, MAHA_THRESH_%d);
      }
    """ % (kind, h_sym.shape[0], 3, maha_test, kind, kind, He_str, kind)
        extra_header += "\nconst static double MAHA_THRESH_%d = %f;" % (
            kind, maha_thresh)
        extra_header += "\nvoid update_%d(double *, double *, double *, double *, double *);" % kind

    code += "\n" + extra_header
    code += "\n" + open(os.path.join(EXTERNAL_PATH, "ekf_c.c")).read()
    code += "\n" + extra_post
    header += "\n" + extra_header
    compile_code(name, code, header, EXTERNAL_PATH)
Ejemplo n.º 3
0
    def generate_code(generated_dir):
        name = LiveKalman.name
        dim_state = LiveKalman.initial_x.shape[0]
        dim_state_err = LiveKalman.initial_P_diag.shape[0]

        state_sym = sp.MatrixSymbol('state', dim_state, 1)
        state = sp.Matrix(state_sym)
        x, y, z = state[States.ECEF_POS, :]
        q = state[States.ECEF_ORIENTATION, :]
        v = state[States.ECEF_VELOCITY, :]
        vx, vy, vz = v
        omega = state[States.ANGULAR_VELOCITY, :]
        vroll, vpitch, vyaw = omega
        roll_bias, pitch_bias, yaw_bias = state[States.GYRO_BIAS, :]
        odo_scale = state[States.ODO_SCALE, :][0, :]
        acceleration = state[States.ACCELERATION, :]
        imu_angles = state[States.IMU_OFFSET, :]

        dt = sp.Symbol('dt')

        # calibration and attitude rotation matrices
        quat_rot = quat_rotate(*q)

        # Got the quat predict equations from here
        # A New Quaternion-Based Kalman Filter for
        # Real-Time Attitude Estimation Using the Two-Step
        # Geometrically-Intuitive Correction Algorithm
        A = 0.5 * sp.Matrix(
            [[0, -vroll, -vpitch, -vyaw], [vroll, 0, vyaw, -vpitch],
             [vpitch, -vyaw, 0, vroll], [vyaw, vpitch, -vroll, 0]])
        q_dot = A * q

        # Time derivative of the state as a function of state
        state_dot = sp.Matrix(np.zeros((dim_state, 1)))
        state_dot[States.ECEF_POS, :] = v
        state_dot[States.ECEF_ORIENTATION, :] = q_dot
        state_dot[States.ECEF_VELOCITY, 0] = quat_rot * acceleration

        # Basic descretization, 1st order intergrator
        # Can be pretty bad if dt is big
        f_sym = state + dt * state_dot

        state_err_sym = sp.MatrixSymbol('state_err', dim_state_err, 1)
        state_err = sp.Matrix(state_err_sym)
        quat_err = state_err[States.ECEF_ORIENTATION_ERR, :]
        v_err = state_err[States.ECEF_VELOCITY_ERR, :]
        omega_err = state_err[States.ANGULAR_VELOCITY_ERR, :]
        acceleration_err = state_err[States.ACCELERATION_ERR, :]

        # Time derivative of the state error as a function of state error and state
        quat_err_matrix = euler_rotate(quat_err[0], quat_err[1], quat_err[2])
        q_err_dot = quat_err_matrix * quat_rot * (omega + omega_err)
        state_err_dot = sp.Matrix(np.zeros((dim_state_err, 1)))
        state_err_dot[States.ECEF_POS_ERR, :] = v_err
        state_err_dot[States.ECEF_ORIENTATION_ERR, :] = q_err_dot
        state_err_dot[
            States.ECEF_VELOCITY_ERR, :] = quat_err_matrix * quat_rot * (
                acceleration + acceleration_err)
        f_err_sym = state_err + dt * state_err_dot

        # Observation matrix modifier
        H_mod_sym = sp.Matrix(np.zeros((dim_state, dim_state_err)))
        H_mod_sym[States.ECEF_POS,
                  States.ECEF_POS_ERR] = np.eye(States.ECEF_POS.stop -
                                                States.ECEF_POS.start)
        H_mod_sym[States.ECEF_ORIENTATION,
                  States.ECEF_ORIENTATION_ERR] = 0.5 * quat_matrix_r(
                      state[3:7])[:, 1:]
        H_mod_sym[States.ECEF_ORIENTATION.stop:,
                  States.ECEF_ORIENTATION_ERR.stop:] = np.eye(
                      dim_state - States.ECEF_ORIENTATION.stop)

        # these error functions are defined so that say there
        # is a nominal x and true x:
        # true x = err_function(nominal x, delta x)
        # delta x = inv_err_function(nominal x, true x)
        nom_x = sp.MatrixSymbol('nom_x', dim_state, 1)
        true_x = sp.MatrixSymbol('true_x', dim_state, 1)
        delta_x = sp.MatrixSymbol('delta_x', dim_state_err, 1)

        err_function_sym = sp.Matrix(np.zeros((dim_state, 1)))
        delta_quat = sp.Matrix(np.ones((4)))
        delta_quat[1:, :] = sp.Matrix(0.5 *
                                      delta_x[States.ECEF_ORIENTATION_ERR, :])
        err_function_sym[States.ECEF_POS, :] = sp.Matrix(
            nom_x[States.ECEF_POS, :] + delta_x[States.ECEF_POS_ERR, :])
        err_function_sym[States.ECEF_ORIENTATION, 0] = quat_matrix_r(
            nom_x[States.ECEF_ORIENTATION, 0]) * delta_quat
        err_function_sym[States.ECEF_ORIENTATION.stop:, :] = sp.Matrix(
            nom_x[States.ECEF_ORIENTATION.stop:, :] +
            delta_x[States.ECEF_ORIENTATION_ERR.stop:, :])

        inv_err_function_sym = sp.Matrix(np.zeros((dim_state_err, 1)))
        inv_err_function_sym[States.ECEF_POS_ERR,
                             0] = sp.Matrix(-nom_x[States.ECEF_POS, 0] +
                                            true_x[States.ECEF_POS, 0])
        delta_quat = quat_matrix_r(
            nom_x[States.ECEF_ORIENTATION,
                  0]).T * true_x[States.ECEF_ORIENTATION, 0]
        inv_err_function_sym[States.ECEF_ORIENTATION_ERR,
                             0] = sp.Matrix(2 * delta_quat[1:])
        inv_err_function_sym[States.ECEF_ORIENTATION_ERR.stop:, 0] = sp.Matrix(
            -nom_x[States.ECEF_ORIENTATION.stop:, 0] +
            true_x[States.ECEF_ORIENTATION.stop:, 0])

        eskf_params = [[err_function_sym, nom_x, delta_x],
                       [inv_err_function_sym, nom_x, true_x], H_mod_sym,
                       f_err_sym, state_err_sym]
        #
        # Observation functions
        #
        #imu_rot = euler_rotate(*imu_angles)
        h_gyro_sym = sp.Matrix(
            [vroll + roll_bias, vpitch + pitch_bias, vyaw + yaw_bias])

        pos = sp.Matrix([x, y, z])
        gravity = quat_rot.T * ((EARTH_GM /
                                 ((x**2 + y**2 + z**2)**(3.0 / 2.0))) * pos)
        h_acc_sym = (gravity + acceleration)
        h_phone_rot_sym = sp.Matrix([vroll, vpitch, vyaw])

        speed = sp.sqrt(vx**2 + vy**2 + vz**2 + 1e-6)
        h_speed_sym = sp.Matrix([speed * odo_scale])

        h_pos_sym = sp.Matrix([x, y, z])
        h_vel_sym = sp.Matrix([vx, vy, vz])
        h_orientation_sym = q
        h_imu_frame_sym = sp.Matrix(imu_angles)

        h_relative_motion = sp.Matrix(quat_rot.T * v)

        obs_eqs = [
            [h_speed_sym, ObservationKind.ODOMETRIC_SPEED, None],
            [h_gyro_sym, ObservationKind.PHONE_GYRO, None],
            [h_phone_rot_sym, ObservationKind.NO_ROT, None],
            [h_acc_sym, ObservationKind.PHONE_ACCEL, None],
            [h_pos_sym, ObservationKind.ECEF_POS, None],
            [h_vel_sym, ObservationKind.ECEF_VEL, None],
            [
                h_orientation_sym, ObservationKind.ECEF_ORIENTATION_FROM_GPS,
                None
            ],
            [h_relative_motion, ObservationKind.CAMERA_ODO_TRANSLATION, None],
            [h_phone_rot_sym, ObservationKind.CAMERA_ODO_ROTATION, None],
            [h_imu_frame_sym, ObservationKind.IMU_FRAME, None]
        ]

        gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state,
                 dim_state_err, eskf_params)
x = sympy.symbols("x")
y = sympy.Function("y")
f = y(x)**2 + x
f_np = sympy.lambdify((y(x), x), f)
y0 = 0
xp = np.linspace(0, 1.9, 100)
yp = sp.integrate.odeint(f_np, y0, xp)
xm = np.linspace(0, -5, 100)
ym = sp.integrate.odeint(f_np, y0, xm)
fig, ax = plt.subplots(1, 1, figsize=(4, 4))
plot_direction_field(x, y(x), f, ax=ax)
ax.plot(xm, ym, 'b', lw=2)
ax.plot(xp, yp, 'r', lw=2)

A = sympy.MatrixSymbol('A', 3, 3)
M = sympy.MatrixSymbol('M', 3, 3)
beta = sympy.symbols("beta")


def rk4(f, x0, y0, x1, n):
    vx = [0] * (n + 1)
    vy = [0] * (n + 1)
    h = (x1 - x0) / float(n)
    vx[0] = x = x0
    vy[0] = y = y0
    for i in range(1, n + 1):
        k1 = h * f(x, y)
        k2 = h * f(x + 0.5 * h, y + 0.5 * k1)
        k3 = h * f(x + 0.5 * h, y + 0.5 * k2)
        k4 = h * f(x + h, y + k3)
Ejemplo n.º 5
0
Archivo: agi3D.py Proyecto: TKNRK/AGI
        Ys[i] = np.dot(p0, E[1])
    boundingH = max([np.amax(Xs), np.amin(Xs)]) * 2
    boundingV = max([np.amax(Ys), np.amin(Ys)]) * 2
    for i in range(node_num):
        Xs_scaled[i] = scale(Xs[i], True)
        Ys_scaled[i] = scale(Ys[i], False)


update_points()

print("init: ready")

# sympy
a1, b1, c1, a2, b2, c2, t, s = sp.symbols('a1 b1 c1 a2 b2 c2 t s')  # variables
x2_s, y2_s = sp.symbols('x2_s y2_s')  # values
P_i = sp.MatrixSymbol('P_i', high_dim, 1)
E1 = sp.MatrixSymbol('E1', high_dim, 1)
E2 = sp.MatrixSymbol('E2', high_dim, 1)
var = (x2_s, y2_s, P_i, E1, E2, a1, b1, c1, a2, b2, c2, t, s)

_E1 = sp.Matrix(a1 * E1 + b1 * E2 + c1 * P_i)
_E2 = sp.Matrix(a2 * E1 + b2 * E2 + c2 * P_i)
R = sp.Matrix(s * E1 + t * E2)

f = Matrix([
    _E1.T * _E1 - Matrix([1]), _E2.T * _E2 - Matrix([1]), _E1.T * _E2,
    R.T * R - Matrix([1]), _E1.T * R - sp.Matrix(E1).T * R,
    _E2.T * R - sp.Matrix(E2).T * R,
    sp.Matrix(P_i).T * (_E1) - Matrix([x2_s]),
    sp.Matrix(P_i).T * (_E2) - Matrix([y2_s])
])
Ejemplo n.º 6
0
    if compile_pdf:
        cur_dir = os.path.abspath(os.path.curdir)
        os.chdir(makefile_trunk)
        import subprocess
        tex_out = subprocess.check_output(
            ['pdflatex', '--interaction=nonstopmode',
             os.path.split(tex_filename)[-1]],stderr=subprocess.STDOUT)
        os.chdir(cur_dir)

if __name__== "__main__":    
    import sympy as sp
    s0 = sp.Symbol('\sigma_0^2')
    s1 = sp.Symbol('\sigma_1^2')
    a01 = sp.Symbol('a_{01}')
    a02 = sp.Symbol('a_{02}')
    a12 = sp.Symbol('a_{12}')

    y = sp.Symbol('y')
    x = sp.Matrix([[sp.Symbol('x_0')],[sp.Symbol('x_1')]])

    Sxx = sp.Matrix([[s0,a01*s0],[a01*s0,s1]])
    a = sp.Matrix([[a02],[a12]])
    print(Sxx)
    print((a.T*Sxx*a)[0,0])
    from pyapprox.sympy_utilities import convert_sympy_equations_to_latex
    convert_sympy_equations_to_latex([
        sp.Eq(sp.MatrixSymbol('\Sigma_{xx}',2,2),Sxx),
        sp.Eq(y,(a.T*x)[0]),
        sp.simplify((a.T*Sxx*a)[0,0]),],'temp/temp.tex')
Ejemplo n.º 7
0
    def generate_code(generated_dir):
        dim_state = CarKalman.initial_x.shape[0]
        name = CarKalman.name

        # globals
        m, j, aF, aR, cF_orig, cR_orig = CarKalman.global_vars

        # make functions and jacobians with sympy
        # state variables
        state_sym = sp.MatrixSymbol('state', dim_state, 1)
        state = sp.Matrix(state_sym)

        # Vehicle model constants
        x = state[States.STIFFNESS, :][0, 0]

        cF, cR = x * cF_orig, x * cR_orig
        angle_offset = state[States.ANGLE_OFFSET, :][0, 0]
        angle_offset_fast = state[States.ANGLE_OFFSET_FAST, :][0, 0]
        sa = state[States.STEER_ANGLE, :][0, 0]

        sR = state[States.STEER_RATIO, :][0, 0]
        u, v = state[States.VELOCITY, :]
        r = state[States.YAW_RATE, :][0, 0]

        A = sp.Matrix(np.zeros((2, 2)))
        A[0, 0] = -(cF + cR) / (m * u)
        A[0, 1] = -(cF * aF - cR * aR) / (m * u) - u
        A[1, 0] = -(cF * aF - cR * aR) / (j * u)
        A[1, 1] = -(cF * aF**2 + cR * aR**2) / (j * u)

        B = sp.Matrix(np.zeros((2, 1)))
        B[0, 0] = cF / m / sR
        B[1, 0] = (cF * aF) / j / sR

        x = sp.Matrix([v, r])  # lateral velocity, yaw rate
        x_dot = A * x + B * (sa - angle_offset - angle_offset_fast)

        dt = sp.Symbol('dt')
        state_dot = sp.Matrix(np.zeros((dim_state, 1)))
        state_dot[States.VELOCITY.start + 1, 0] = x_dot[0]
        state_dot[States.YAW_RATE.start, 0] = x_dot[1]

        # Basic descretization, 1st order integrator
        # Can be pretty bad if dt is big
        f_sym = state + dt * state_dot

        #
        # Observation functions
        #
        obs_eqs = [
            [sp.Matrix([r]), ObservationKind.ROAD_FRAME_YAW_RATE, None],
            [sp.Matrix([u, v]), ObservationKind.ROAD_FRAME_XY_SPEED, None],
            [sp.Matrix([u]), ObservationKind.ROAD_FRAME_X_SPEED, None],
            [sp.Matrix([sa]), ObservationKind.STEER_ANGLE, None],
            [
                sp.Matrix([angle_offset_fast]),
                ObservationKind.ANGLE_OFFSET_FAST, None
            ],
            [sp.Matrix([sR]), ObservationKind.STEER_RATIO, None],
            [sp.Matrix([x]), ObservationKind.STIFFNESS, None],
        ]

        gen_code(generated_dir,
                 name,
                 f_sym,
                 dt,
                 state_sym,
                 obs_eqs,
                 dim_state,
                 dim_state,
                 global_vars=CarKalman.global_vars)
Ejemplo n.º 8
0
    def __init__(self, scheme, sorder, generator, settings=None):
        xx, yy, zz = sp.symbols('xx, yy, zz')
        self.symb_coord_local = [xx, yy, zz]
        self.symb_coord = scheme.symb_coord
        self.dim = scheme.dim
        self.ns = scheme.stencil.nv_ptr[-1]
        self.M = scheme.M.subs(scheme.param.items())
        self.invM = scheme.invM.subs(scheme.param.items())
        self.all_velocities = scheme.stencil.get_all_velocities()
        self.mv = sp.MatrixSymbol('m', self.ns, 1)

        if scheme.rel_vel is not None:
            self.rel_vel_symb = [rel_ux, rel_uy, rel_uz][:self.dim]
            self.rel_vel = sp.Matrix(scheme.rel_vel)

            self.Tu = scheme.Tu.subs(scheme.param.items())
            self.Tmu = scheme.Tmu.subs(scheme.param.items())

            self.Mu = self.Tu * self.M
            self.invMu = self.invM * self.Tmu
            alltogether(self.Mu, nsimplify=True)
            alltogether(self.invMu, nsimplify=True)
        else:
            self.rel_vel_symb = None

        self.consm = {}
        for k, v in scheme.consm.items():
            self.consm[str(k)] = v

        self.sorder = sorder
        self.generator = generator

        subs_coords = list(zip(self.symb_coord, self.symb_coord_local))
        subs_moments = list(zip(scheme.consm.keys(), [self.mv[int(i), 0] for i in scheme.consm.values()]))
        to_subs = subs_coords + list(scheme.param.items())
        to_subs_full = to_subs + subs_moments

        self.eq = recursive_sub(scheme.EQ, to_subs_full)
        self.s = recursive_sub(scheme.s, to_subs_full)
        alltogether(self.eq, nsimplify=True)
        alltogether(self.s)

        if self.rel_vel_symb:
            self.rel_vel = recursive_sub(self.rel_vel, to_subs_full)
            alltogether(self.rel_vel)

        self.source_eq = []
        for source in scheme._source_terms:
            if source:
                for k, v in source.items():
                    lhs = recursive_sub(k, to_subs_full)
                    if isinstance(v, (float, int)):
                        rhs = v
                    else:
                        rhs = recursive_sub(v, to_subs)
                    self.source_eq.append((lhs, rhs))

        self.vmax = [0]*3
        self.vmax[:scheme.dim] = scheme.stencil.vmax
        self.local_vars = self.symb_coord_local[:self.dim]
        self.settings = settings if settings else {}
def ekf_generate_c_code(f, F, h, H, x, u, f_additional_in=[], h_additional_in=[]):

    # generated C code matrix access is in row-major order
    # [source: sympy/printing/ccode.py:215, _print_MatrixElement()]
    # Since Eigen uses column-major by default we transpose the matrices before
    # generating the C code
    H = H.transpose()
    F = F.transpose()

    f_additional_in_sym = [sp.symbols('in{}_{}'.format(i+2, var.name)) for i, var in enumerate(f_additional_in)]
    f_add_subs_tab = list(zip(f_additional_in, f_additional_in_sym))
    h_additional_in_sym = [sp.symbols('in{}_{}'.format(i+1, var.name)) for i, var in enumerate(h_additional_in)]
    h_add_subs_tab = list(zip(h_additional_in, h_additional_in_sym))
    x_sym = sp.MatrixSymbol('in0_x', len(x), 1)
    x_subs_tab = [(elem_sym, x_sym[i, 0]) for i, elem_sym in enumerate(x)]
    u_sym = sp.MatrixSymbol('in1_u', len(u), 1)
    u_subs_tab = [(elem_sym, u_sym[i, 0]) for i, elem_sym in enumerate(u)]

    subs_tab = x_subs_tab + u_subs_tab + f_add_subs_tab + h_add_subs_tab

    # c_code  = generate_c_code('f', f.subs(subs_tab)) + '\n'
    # c_code += generate_c_code('F', F.subs(subs_tab)) + '\n'
    # c_code += generate_c_code('h', h.subs(subs_tab)) + '\n'
    # c_code += generate_c_code('H', H.subs(subs_tab)) + '\n'

    no_return_val = []
    no_local_vars = []

    f_additional_in_arg = [cg.InputArgument(sym) for sym in f_additional_in_sym]
    h_additional_in_arg = [cg.InputArgument(sym) for sym in h_additional_in_sym]

    f_out_sym = sp.MatrixSymbol('f_out', len(x), 1)
    f_arg_list = [cg.InputArgument(x_sym, dimensions=x_sym.shape),
                  cg.InputArgument(u_sym, dimensions=u_sym.shape)]
    f_arg_list += f_additional_in_arg
    f_arg_list += [cg.OutputArgument(f_out_sym, f_out_sym, f.subs(subs_tab), dimensions=f_out_sym.shape)]

    F_out_sym = sp.MatrixSymbol('F_out', F.shape[0], F.shape[1])
    F_arg_list = [cg.InputArgument(x_sym, dimensions=x_sym.shape),
                  cg.InputArgument(u_sym, dimensions=u_sym.shape)]
    F_arg_list += f_additional_in_arg
    F_arg_list += [cg.OutputArgument(F_out_sym, F_out_sym, F.subs(subs_tab), dimensions=F_out_sym.shape)]

    h_out_sym = sp.MatrixSymbol('h_out', len(h), 1)
    h_arg_list = [cg.InputArgument(x_sym, dimensions=x_sym.shape)]
    h_arg_list += h_additional_in_arg
    h_arg_list += [cg.OutputArgument(h_out_sym, h_out_sym, h.subs(subs_tab), dimensions=h_out_sym.shape)]

    H_out_sym = sp.MatrixSymbol('H_out', H.shape[0], H.shape[1])
    H_arg_list = [cg.InputArgument(x_sym, dimensions=x_sym.shape)]
    H_arg_list += h_additional_in_arg
    H_arg_list += [cg.OutputArgument(H_out_sym, H_out_sym, H.subs(subs_tab), dimensions=H_out_sym.shape)]

    routines = [cg.Routine("f", f_arg_list, no_return_val, no_local_vars),
                cg.Routine("F", F_arg_list, no_return_val, no_local_vars),
                cg.Routine("h", h_arg_list, no_return_val, no_local_vars),
                cg.Routine("H", H_arg_list, no_return_val, no_local_vars)]
    code_gen = cg.get_code_generator("C", "projectname")
    [(c_name, c_code), (h_name, c_header)] = code_gen.write(routines, "prefix", header=False)

    c_code = clean_c_code(c_code, use_single_float=True)

    c_code_head = '// This file has been automatically generated\n'
    c_code_head += '// DO NOT EDIT!\n\n'
    c_code_head += '#include <math.h>\n\n'
    c_code_head += 'const int STATE_DIM = {};\n'.format(len(x))
    c_code_head += 'const int CONTROL_DIM = {};\n'.format(len(u))
    c_code_head += 'const int MEASURE_DIM = {};\n'.format(len(h))
    c_code_head += '\n\n'

    return c_code_head + c_code
Ejemplo n.º 10
0
Archivo: t3d.py Proyecto: wakita/symdoc
def VEC(name: str, n: int) -> sp.MatrixSymbol:
    'n次元ベクトルを表す記号を返す'
    return sp.MatrixSymbol(name, n, 1)
Ejemplo n.º 11
0
Archivo: t3d.py Proyecto: wakita/symdoc
def Vec(n: int, name: str) -> sp.MatrixSymbol:
    'n次元ベクトルの記号を与える'
    return sp.MatrixSymbol(sp.Symbol(name), n, 1)
Ejemplo n.º 12
0
def build_module_autowrap(expr,syms,module_name,tmp_dir,out_dir,dummify=False,cse=False,cse_ordering="canonical",build_vectorized=False,pretty_dummy_symbol_names=False,verbose=False,request_delete_tmp_dir=True):

    tmp_dir_exists_before_call = os.path.exists(tmp_dir)

    is_matrix_expr = isinstance(expr,sympy.Matrix) or isinstance(expr,sympy.MutableMatrix) or isinstance(expr,sympy.ImmutableMatrix)

    if dummify:
        if verbose: print "flashlight.sympy: Generating dummy symbols for %s..." % module_name        
        expr,syms = _dummify(expr,syms,pretty_dummy_symbol_names)
        if verbose: print "flashlight.sympy: Finished generating dummy symbols for %s." % module_name

    if cse:
        include_str,subexpr_eval_str = generate_c_code_cse(expr,syms,module_name,tmp_dir,out_dir,cse_ordering=cse_ordering,verbose=verbose,request_delete_tmp_dir=request_delete_tmp_dir)

        if is_matrix_expr:
            expr = sympy.Matrix.zeros(expr.rows,expr.cols)
        else:
            expr = 0

    syms = list(syms)

    if is_matrix_expr:
        out_sym = sympy.MatrixSymbol('out_%s' % abs(hash(sympy.ImmutableMatrix(expr))), *expr.shape)
        syms    = syms + [out_sym]

    if verbose: print "flashlight.sympy: Generating Cython code for %s..." % module_name
    _autowrap_skip_compile(expr=expr,backend="cython",verbose=verbose,args=syms,tempdir=tmp_dir)
    if verbose: print "flashlight.sympy: Modifying autogenerated Cython files for %s" % module_name

    with open("%s/setup.py" % tmp_dir, "r") as f:
        setup_py_str = f.read()
        tmp_module_name        = re.findall("wrapper_module_[0-9]*", setup_py_str)
        tmp_autofunc_code_name = re.findall("wrapped_code_[0-9]*",   setup_py_str)
        assert len(tmp_module_name)        == 2
        assert len(tmp_autofunc_code_name) == 1
        assert tmp_module_name[0] == tmp_module_name[1]
        tmp_module_name        = tmp_module_name[0]
        tmp_autofunc_code_name = tmp_autofunc_code_name[0]
    with open("%s/%s.pyx" % (tmp_dir,tmp_module_name), "r") as f:
        wrapper_module_pyx_str = f.read()
    with open("%s/%s.c" % (tmp_dir,tmp_autofunc_code_name), "r") as f:
        autofunc_c_str = f.read()
    with open("%s/%s.h" % (tmp_dir,tmp_autofunc_code_name), "r") as f:
        autofunc_h_str = f.read()

    with open("%s/%s_setup.py" % (tmp_dir,module_name), "w") as f:
        setup_py_str_mod = setup_py_str
        setup_py_str_mod = setup_py_str_mod.replace("from Cython.Distutils import build_ext","from Cython.Distutils import build_ext\n\nimport numpy\nimport os\n\nos.environ['CC']  = '%s'\nos.environ['CXX'] = '%s'\n\n" % (cc_compiler, cxx_compiler))
        setup_py_str_mod = setup_py_str_mod.replace("extra_compile_args=['-std=c99']","extra_compile_args=['-std=c99','-fno-var-tracking','-fno-var-tracking-assignments'], include_dirs=[numpy.get_include()]")
        setup_py_str_mod = setup_py_str_mod.replace("%s" % tmp_module_name,        "%s"          % module_name)
        setup_py_str_mod = setup_py_str_mod.replace("%s" % tmp_autofunc_code_name, "%s_autofunc" % module_name)
        f.write(setup_py_str_mod)
    with open("%s/%s.pyx" % (tmp_dir,module_name), "w") as f:
        wrapper_module_pyx_str_mod = wrapper_module_pyx_str
        wrapper_module_pyx_str_mod = wrapper_module_pyx_str_mod.replace("%s" % tmp_autofunc_code_name, "%s_autofunc" % module_name)
        f.write(wrapper_module_pyx_str_mod)

    if not cse:
        with open("%s/%s_autofunc.c" % (tmp_dir,module_name), "w") as f:
            autofunc_c_str_mod = autofunc_c_str
            autofunc_c_str_mod = autofunc_c_str_mod.replace('#include "%s.h"' % tmp_autofunc_code_name, '#include "%s.h"' % (module_name+"_autofunc"))
            f.write(autofunc_c_str_mod)
        with open("%s/%s_autofunc.h" % (tmp_dir,module_name), "w") as f:
            autofunc_h_str_mod = autofunc_h_str
            autofunc_h_str_mod = autofunc_h_str_mod.replace("AUTOWRAP__%s__H" % tmp_autofunc_code_name.upper(), "%s_H" % (module_name+"_autofunc").upper())
            f.write(autofunc_h_str_mod)

    if build_vectorized:
        if verbose: print "flashlight.sympy: Generating Cython code for %s_vectorized..." % module_name
        if is_matrix_expr:
            c_return_type_str     = "void"
            c_out_var_str         = "out_123456789"
            c_func_signature_str  = str( [ "double %s" % str(sym) for sym in syms[:-1] ] )[1:-1].replace("'","") + ", double *%s" % syms[-1]
            cython_out_type_str   = "numpy.ndarray[FLOAT64_DTYPE_t, ndim=3]"
            cython_out_shape_str  = "(args.shape[0],%s,%s)" % (expr.rows,expr.cols)
            cython_out_v_type_str = "FLOAT64_DTYPE_t [:,:,:]"
            cython_args_str       = str( [ "args[i,%d]" % i for i in range(len(syms[:-1])) ] )[1:-1].replace("'","") + ", &out_v[i,0,0]"
            cython_loop_body_str  = "autofunc(%s)" % cython_args_str
        else:
            c_return_type_str     = "double"
            c_func_signature_str  = str( [ "double %s" % str(sym) for sym in syms ] )[1:-1].replace("'","")
            cython_out_type_str   = "numpy.ndarray[FLOAT64_DTYPE_t, ndim=1]"
            cython_out_shape_str  = "(args.shape[0])"
            cython_out_v_type_str = "FLOAT64_DTYPE_t [:]"
            cython_args_str       = str( [ "args[i,%d]" % i for i in range(len(syms)) ] )[1:-1].replace("'","")
            cython_loop_body_str  = "out_v[i] = autofunc(%s)" % cython_args_str
        vectorized_setup_py_str_eval = vectorized_setup_py_str % (cc_compiler, cxx_compiler, module_name, module_name, module_name)
        vectorized_pyx_str_eval      = vectorized_pyx_str % (module_name, c_return_type_str, c_func_signature_str, cython_out_type_str, cython_out_shape_str, cython_out_v_type_str, cython_loop_body_str)
        with open("%s/%s_vectorized_setup.py" % (tmp_dir,module_name), "w") as f:
            vectorized_setup_py_str_mod = vectorized_setup_py_str_eval
            f.write(vectorized_setup_py_str_mod)
        with open("%s/%s_vectorized.pyx" % (tmp_dir,module_name), "w") as f:
            vectorized_pyx_str_mod = vectorized_pyx_str_eval
            f.write(vectorized_pyx_str_mod)

    cwd = os.getcwd()
    try:
        os.chdir(tmp_dir)

        if verbose: print "flashlight.sympy: Building Cython code for %s..." % module_name
        cmd = "python %s_setup.py build_ext --inplace" % module_name
        if verbose: print cmd
        output = subprocess.check_output(cmd, shell=True)
        if verbose and len(output) > 0: print output

        if build_vectorized:
            if verbose: print "flashlight.sympy: Building Cython code for %s_vectorized..." % module_name
            cmd = "python %s_vectorized_setup.py build_ext --inplace" % module_name
            if verbose: print cmd
            output = subprocess.check_output(cmd, shell=True)
            if verbose and len(output) > 0: print output

    finally:
        os.chdir(cwd)

    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    cmd = "cp %s/%s.so %s/%s.so" % (tmp_dir,module_name,out_dir,module_name)
    if verbose: print cmd
    output = subprocess.check_output(cmd, shell=True)
    if verbose and len(output) > 0: print output

    if build_vectorized:
        cmd = "cp %s/%s_vectorized.so %s/%s_vectorized.so" % (tmp_dir,module_name,out_dir,module_name)
        if verbose: print cmd
        output = subprocess.check_output(cmd, shell=True)
        if verbose and len(output) > 0: print output

    # cmd = "cp %s/%s_autofunc.c %s/%s_autofunc.c" % (tmp_dir,module_name,out_dir,module_name)
    # if verbose: print cmd
    # output = subprocess.check_output(cmd, shell=True)
    # if verbose and len(output) > 0: print output

    # cmd = "cp %s/%s_autofunc.h %s/%s_autofunc.h" % (tmp_dir,module_name,out_dir,module_name)
    # if verbose: print cmd
    # output = subprocess.check_output(cmd, shell=True)
    # if verbose and len(output) > 0: print output

    if not tmp_dir_exists_before_call and request_delete_tmp_dir:
        cmd = "rm -rf %s" % tmp_dir
        if verbose: print cmd
        output = subprocess.check_output(cmd, shell=True)
        if verbose and len(output) > 0: print output
from sympy.codegen.ast import real, float32
from sympy.printing.ccode import C99CodePrinter
printer = C99CodePrinter()


# custom code printer that will not generate such nonesene as x^2 -> pow(x, 2)
class CustomCodePrinter(C99CodePrinter):
    def _print_Pow(self, expr):
        if expr.exp.is_integer and expr.exp > 0 and expr.exp < 5:
            return '*'.join([self._print(expr.base) for i in range(expr.exp)])
        else:
            return super()._print_Pow(expr)


customprinter = CustomCodePrinter()
customprinter.type_aliases[real] = float32  # cosf instead of cos
default_datatypes["float"].cname = "float"  # float instead of double
params = [
    theta, tx0, ty0, tz0, tx1, ty1, tz1, qw0, qx0, qy0, qz0, qw1, qx1, qy1,
    qz1, s000, s001, s002, s003, s011, s012, s013, s022, s023, s100, s101,
    s102, s103, s111, s112, s113, s122, s123
]
R = sp.MatrixSymbol("coeff", A.shape[0], A.shape[1])
P = sp.MatrixSymbol('p', len(params), 1)
param_map = dict(zip(params, P))
B = A.xreplace(param_map)
codegen(('motion_derivative_coefficients', sp.Eq(R, B)),
        language='c',
        printer=customprinter,
        prefix='motion_derivative_coefficients',
        to_files=True)
Ejemplo n.º 14
0
    def generate_code(N=4):
        dim_augment = LocKalman.dim_augment
        dim_augment_err = LocKalman.dim_augment_err

        dim_main = LocKalman.x_initial.shape[0]
        dim_main_err = LocKalman.P_initial.shape[0]
        dim_state = dim_main + dim_augment * N
        dim_state_err = dim_main_err + dim_augment_err * N
        maha_test_kinds = LocKalman.maha_test_kinds

        name = f"{LocKalman.name}_{N}"

        # make functions and jacobians with sympy
        # state variables
        state_sym = sp.MatrixSymbol('state', dim_state, 1)
        state = sp.Matrix(state_sym)
        x, y, z = state[States.ECEF_POS, :]
        q = state[States.ECEF_ORIENTATION, :]
        v = state[States.ECEF_VELOCITY, :]
        vx, vy, vz = v
        omega = state[States.ANGULAR_VELOCITY, :]
        vroll, vpitch, vyaw = omega
        #cb = state[States.CLOCK_BIAS, :][0, 0]
        #cd = state[States.CLOCK_DRIFT, :][0, 0]
        cb, cd = state[13:15, :]
        roll_bias, pitch_bias, yaw_bias = state[States.GYRO_BIAS, :]
        #odo_scale = state[States.ODO_SCALE, :][0,0]
        odo_scale = state[18, :]
        acceleration = state[States.ACCELERATION, :]
        #focal_scale = state[States.FOCAL_SCALE, :][0,0]
        focal_scale = state[22, :]
        imu_angles = state[States.IMU_OFFSET, :]
        glonass_bias, glonass_freq_slope = state[26:28, :]
        ca = state[28, 0]
        #glonass_bias = state[States.GLONASS_BIAS, :][0,0]
        #glonass_freq_slope = state[States.GLONASS_FREQ_SLOPE, :][0,0]
        #ca = state[States.CLOCK_ACCELERATION, :][0,0]

        dt = sp.Symbol('dt')

        # calibration and attitude rotation matrices
        quat_rot = quat_rotate(*q)

        # Got the quat predict equations from here
        # A New Quaternion-Based Kalman Filter for
        # Real-Time Attitude Estimation Using the Two-Step
        # Geometrically-Intuitive Correction Algorithm
        A = 0.5 * sp.Matrix(
            [[0, -vroll, -vpitch, -vyaw], [vroll, 0, vyaw, -vpitch],
             [vpitch, -vyaw, 0, vroll], [vyaw, vpitch, -vroll, 0]])
        q_dot = A * q

        # Time derivative of the state as a function of state
        state_dot = sp.Matrix(np.zeros((dim_state, 1)))
        state_dot[States.ECEF_POS, :] = v
        state_dot[States.ECEF_ORIENTATION, :] = q_dot
        state_dot[States.ECEF_VELOCITY, 0] = quat_rot * acceleration
        state_dot[13, 0] = cd
        state_dot[14, 0] = ca
        #state_dot[States.CLOCK_BIAS, 0][0,0] = cd
        state_dot[States.CLOCK_DRIFT, 0][0, 0] = ca

        # Basic descretization, 1st order intergrator
        # Can be pretty bad if dt is big
        f_sym = state + dt * state_dot

        state_err_sym = sp.MatrixSymbol('state_err', dim_state_err, 1)
        state_err = sp.Matrix(state_err_sym)
        quat_err = state_err[States.ECEF_ORIENTATION_ERR, :]
        v_err = state_err[States.ECEF_VELOCITY_ERR, :]
        omega_err = state_err[States.ANGULAR_VELOCITY_ERR, :]
        #cd_err = state_err[States.CLOCK_DRIFT_ERR, :][0,:]
        cd_err = state_err[13, :]
        acceleration_err = state_err[States.ACCELERATION_ERR, :]
        ca_err = state_err[27, :]

        # Time derivative of the state error as a function of state error and state
        quat_err_matrix = euler_rotate(quat_err[0], quat_err[1], quat_err[2])
        q_err_dot = quat_err_matrix * quat_rot * (omega + omega_err)
        state_err_dot = sp.Matrix(np.zeros((dim_state_err, 1)))
        state_err_dot[States.ECEF_POS_ERR, :] = v_err
        state_err_dot[States.ECEF_ORIENTATION_ERR, :] = q_err_dot
        state_err_dot[
            States.ECEF_VELOCITY_ERR, :] = quat_err_matrix * quat_rot * (
                acceleration + acceleration_err)
        #state_err_dot[States.CLOCK_BIAS_ERR, :][0,:] = cd_err
        #state_err_dot[States.CLOCK_DRIFT_ERR, :][0,:] = ca_err
        state_err_dot[12, :][0, :] = cd_err
        state_err_dot[13, :][0, :] = ca_err
        f_err_sym = state_err + dt * state_err_dot

        # convenient indexing
        # q idxs are for quats and p idxs are for other
        q_idxs = [[3, dim_augment]] + [[
            dim_main + n * dim_augment + 3, dim_main + (n + 1) * dim_augment
        ] for n in range(N)]
        q_err_idxs = [[3, dim_augment_err]] + [[
            dim_main_err + n * dim_augment_err + 3, dim_main_err +
            (n + 1) * dim_augment_err
        ] for n in range(N)]
        p_idxs = [[0, 3]] + [[dim_augment, dim_main]] + [[
            dim_main + n * dim_augment, dim_main + n * dim_augment + 3
        ] for n in range(N)]
        p_err_idxs = [[0, 3]] + [[dim_augment_err, dim_main_err]] + [[
            dim_main_err + n * dim_augment_err,
            dim_main_err + n * dim_augment_err + 3
        ] for n in range(N)]

        # Observation matrix modifier
        H_mod_sym = sp.Matrix(np.zeros((dim_state, dim_state_err)))
        for p_idx, p_err_idx in zip(p_idxs, p_err_idxs):
            H_mod_sym[p_idx[0]:p_idx[1],
                      p_err_idx[0]:p_err_idx[1]] = np.eye(p_idx[1] - p_idx[0])
        for q_idx, q_err_idx in zip(q_idxs, q_err_idxs):
            H_mod_sym[q_idx[0]:q_idx[1],
                      q_err_idx[0]:q_err_idx[1]] = 0.5 * quat_matrix_r(
                          state[q_idx[0]:q_idx[1]])[:, 1:]

        # these error functions are defined so that say there
        # is a nominal x and true x:
        # true x = err_function(nominal x, delta x)
        # delta x = inv_err_function(nominal x, true x)
        nom_x = sp.MatrixSymbol('nom_x', dim_state, 1)
        true_x = sp.MatrixSymbol('true_x', dim_state, 1)
        delta_x = sp.MatrixSymbol('delta_x', dim_state_err, 1)

        err_function_sym = sp.Matrix(np.zeros((dim_state, 1)))
        for q_idx, q_err_idx in zip(q_idxs, q_err_idxs):
            delta_quat = sp.Matrix(np.ones(4))
            delta_quat[1:, :] = sp.Matrix(
                0.5 * delta_x[q_err_idx[0]:q_err_idx[1], :])
            err_function_sym[q_idx[0]:q_idx[1], 0] = quat_matrix_r(
                nom_x[q_idx[0]:q_idx[1], 0]) * delta_quat
        for p_idx, p_err_idx in zip(p_idxs, p_err_idxs):
            err_function_sym[p_idx[0]:p_idx[1], :] = sp.Matrix(
                nom_x[p_idx[0]:p_idx[1], :] +
                delta_x[p_err_idx[0]:p_err_idx[1], :])

        inv_err_function_sym = sp.Matrix(np.zeros((dim_state_err, 1)))
        for p_idx, p_err_idx in zip(p_idxs, p_err_idxs):
            inv_err_function_sym[p_err_idx[0]:p_err_idx[1],
                                 0] = sp.Matrix(-nom_x[p_idx[0]:p_idx[1], 0] +
                                                true_x[p_idx[0]:p_idx[1], 0])
        for q_idx, q_err_idx in zip(q_idxs, q_err_idxs):
            delta_quat = quat_matrix_r(
                nom_x[q_idx[0]:q_idx[1], 0]).T * true_x[q_idx[0]:q_idx[1], 0]
            inv_err_function_sym[q_err_idx[0]:q_err_idx[1],
                                 0] = sp.Matrix(2 * delta_quat[1:])

        eskf_params = [[err_function_sym, nom_x, delta_x],
                       [inv_err_function_sym, nom_x, true_x], H_mod_sym,
                       f_err_sym, state_err_sym]
        #
        # Observation functions
        #

        # extra args
        sat_pos_freq_sym = sp.MatrixSymbol('sat_pos', 4, 1)
        sat_pos_vel_sym = sp.MatrixSymbol('sat_pos_vel', 6, 1)
        sat_los_sym = sp.MatrixSymbol('sat_los', 3, 1)
        orb_epos_sym = sp.MatrixSymbol('orb_epos_sym', 3, 1)

        # expand extra args
        sat_x, sat_y, sat_z, glonass_freq = sat_pos_freq_sym
        sat_vx, sat_vy, sat_vz = sat_pos_vel_sym[3:]
        los_x, los_y, los_z = sat_los_sym
        orb_x, orb_y, orb_z = orb_epos_sym

        h_pseudorange_sym = sp.Matrix(
            [sp.sqrt((x - sat_x)**2 + (y - sat_y)**2 + (z - sat_z)**2) + cb])

        h_pseudorange_glonass_sym = sp.Matrix([
            sp.sqrt((x - sat_x)**2 + (y - sat_y)**2 + (z - sat_z)**2) + cb +
            glonass_bias + glonass_freq_slope * glonass_freq
        ])

        los_vector = (sp.Matrix(sat_pos_vel_sym[0:3]) - sp.Matrix([x, y, z]))
        los_vector = los_vector / sp.sqrt(los_vector[0]**2 + los_vector[1]**2 +
                                          los_vector[2]**2)
        h_pseudorange_rate_sym = sp.Matrix([
            los_vector[0] * (sat_vx - vx) + los_vector[1] * (sat_vy - vy) +
            los_vector[2] * (sat_vz - vz) + cd
        ])

        imu_rot = euler_rotate(*imu_angles)
        h_gyro_sym = imu_rot * sp.Matrix(
            [vroll + roll_bias, vpitch + pitch_bias, vyaw + yaw_bias])

        pos = sp.Matrix([x, y, z])
        gravity = quat_rot.T * ((EARTH_GM /
                                 ((x**2 + y**2 + z**2)**(3.0 / 2.0))) * pos)
        h_acc_sym = imu_rot * (gravity + acceleration)
        h_phone_rot_sym = sp.Matrix([vroll, vpitch, vyaw])

        speed = sp.sqrt(vx**2 + vy**2 + vz**2)
        h_speed_sym = sp.Matrix([speed * odo_scale])

        # orb stuff
        orb_pos_sym = sp.Matrix([orb_x - x, orb_y - y, orb_z - z])
        orb_pos_rot_sym = quat_rot.T * orb_pos_sym
        s = orb_pos_rot_sym[0]
        h_orb_point_sym = sp.Matrix([(1 / s) * (orb_pos_rot_sym[1]),
                                     (1 / s) * (orb_pos_rot_sym[2])])

        h_pos_sym = sp.Matrix([x, y, z])
        h_imu_frame_sym = sp.Matrix(imu_angles)

        h_relative_motion = sp.Matrix(quat_rot.T * v)

        obs_eqs = [
            [h_speed_sym, ObservationKind.ODOMETRIC_SPEED, None],
            [h_gyro_sym, ObservationKind.PHONE_GYRO, None],
            [h_phone_rot_sym, ObservationKind.NO_ROT, None],
            [h_acc_sym, ObservationKind.PHONE_ACCEL, None],
            [
                h_pseudorange_sym, ObservationKind.PSEUDORANGE_GPS,
                sat_pos_freq_sym
            ],
            [
                h_pseudorange_glonass_sym, ObservationKind.PSEUDORANGE_GLONASS,
                sat_pos_freq_sym
            ],
            [
                h_pseudorange_rate_sym, ObservationKind.PSEUDORANGE_RATE_GPS,
                sat_pos_vel_sym
            ],
            [
                h_pseudorange_rate_sym,
                ObservationKind.PSEUDORANGE_RATE_GLONASS, sat_pos_vel_sym
            ], [h_pos_sym, ObservationKind.ECEF_POS, None],
            [h_relative_motion, ObservationKind.CAMERA_ODO_TRANSLATION, None],
            [h_phone_rot_sym, ObservationKind.CAMERA_ODO_ROTATION, None],
            [h_imu_frame_sym, ObservationKind.IMU_FRAME, None],
            [h_orb_point_sym, ObservationKind.ORB_POINT, orb_epos_sym]
        ]

        # MSCKF configuration
        if N > 0:
            focal_scale = 1
            # Add observation functions for orb feature tracks
            track_epos_sym = sp.MatrixSymbol('track_epos_sym', 3, 1)
            track_x, track_y, track_z = track_epos_sym
            h_track_sym = sp.Matrix(np.zeros(((1 + N) * 2, 1)))
            track_pos_sym = sp.Matrix([track_x - x, track_y - y, track_z - z])
            track_pos_rot_sym = quat_rot.T * track_pos_sym
            h_track_sym[-2:, :] = sp.Matrix([
                focal_scale * (track_pos_rot_sym[1] / track_pos_rot_sym[0]),
                focal_scale * (track_pos_rot_sym[2] / track_pos_rot_sym[0])
            ])

            h_msckf_test_sym = sp.Matrix(np.zeros(((1 + N) * 3, 1)))
            h_msckf_test_sym[-3:, :] = sp.Matrix(
                [track_x - x, track_y - y, track_z - z])

            for n in range(N):
                idx = dim_main + n * dim_augment
                # err_idx = dim_main_err + n * dim_augment_err  # FIXME: Why is this not used?
                x, y, z = state[idx:idx + 3]
                q = state[idx + 3:idx + 7]
                quat_rot = quat_rotate(*q)
                track_pos_sym = sp.Matrix(
                    [track_x - x, track_y - y, track_z - z])
                track_pos_rot_sym = quat_rot.T * track_pos_sym
                h_track_sym[n * 2:n * 2 + 2, :] = sp.Matrix([
                    focal_scale *
                    (track_pos_rot_sym[1] / track_pos_rot_sym[0]),
                    focal_scale * (track_pos_rot_sym[2] / track_pos_rot_sym[0])
                ])
                h_msckf_test_sym[n * 3:n * 3 + 3, :] = sp.Matrix(
                    [track_x - x, track_y - y, track_z - z])

            obs_eqs.append(
                [h_msckf_test_sym, ObservationKind.MSCKF_TEST, track_epos_sym])
            obs_eqs.append(
                [h_track_sym, ObservationKind.ORB_FEATURES, track_epos_sym])
            obs_eqs.append([
                h_track_sym, ObservationKind.FEATURE_TRACK_TEST, track_epos_sym
            ])
            msckf_params = [
                dim_main, dim_augment, dim_main_err, dim_augment_err, N,
                [ObservationKind.MSCKF_TEST, ObservationKind.ORB_FEATURES]
            ]
        else:
            msckf_params = None
        gen_code(name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state_err,
                 eskf_params, msckf_params, maha_test_kinds)
Ejemplo n.º 15
0
    def __call__(self, equations, variables=None, method_options=None):
        method_options = extract_method_options(method_options,
                                                {'simplify': True})

        if equations.is_stochastic:
            raise UnsupportedEquationsException('Cannot solve stochastic '
                                                'equations with this state '
                                                'updater.')
        if variables is None:
            variables = {}

        # Get a representation of the ODE system in the form of
        # dX/dt = M*X + B
        varnames, matrix, constants = get_linear_system(equations, variables)

        # No differential equations, nothing to do (this occurs sometimes in the
        # test suite where the whole model is nothing more than something like
        # 'v : 1')
        if matrix.shape == (0, 0):
            return ''

        # Make sure that the matrix M is constant, i.e. it only contains
        # external variables or constant variables
        t = Symbol('t', real=True, positive=True)

        # Check for time dependence
        dt_value = variables['dt'].get_value(
        )[0] if 'dt' in variables else None

        # This will raise an error if we meet the symbol "t" anywhere
        # except as an argument of a locally constant function
        for entry in itertools.chain(matrix, constants):
            if not is_constant_over_dt(entry, variables, dt_value):
                raise UnsupportedEquationsException(
                    ('Expression "{}" is not guaranteed to be constant over a '
                     'time step').format(sympy_to_str(entry)))

        symbols = [Symbol(variable, real=True) for variable in varnames]
        solution = sp.solve_linear_system(matrix.row_join(constants), *symbols)
        if solution is None or set(symbols) != set(solution.keys()):
            raise UnsupportedEquationsException('Cannot solve the given '
                                                'equations with this '
                                                'stateupdater.')
        b = sp.ImmutableMatrix([solution[symbol] for symbol in symbols])

        # Solve the system
        dt = Symbol('dt', real=True, positive=True)
        try:
            A = (matrix * dt).exp()
        except NotImplementedError:
            raise UnsupportedEquationsException('Cannot solve the given '
                                                'equations with this '
                                                'stateupdater.')
        if method_options['simplify']:
            A = A.applyfunc(
                lambda x: sp.factor_terms(sp.cancel(sp.signsimp(x))))
        C = sp.ImmutableMatrix(A * b) - b
        _S = sp.MatrixSymbol('_S', len(varnames), 1)
        updates = A * _S + C
        updates = updates.as_explicit()

        # The solution contains _S[0, 0], _S[1, 0] etc. for the state variables,
        # replace them with the state variable names
        abstract_code = []
        for idx, (variable, update) in enumerate(zip(varnames, updates)):
            rhs = update
            if rhs.has(I, re, im):
                raise UnsupportedEquationsException(
                    'The solution to the linear system '
                    'contains complex values '
                    'which is currently not implemented.')
            for row_idx, varname in enumerate(varnames):
                rhs = rhs.subs(_S[row_idx, 0], varname)

            # Do not overwrite the real state variables yet, the update step
            # of other state variables might still need the original values
            abstract_code.append('_' + variable + ' = ' + sympy_to_str(rhs))

        # Update the state variables
        for variable in varnames:
            abstract_code.append(
                '{variable} = _{variable}'.format(variable=variable))
        return '\n'.join(abstract_code)
Ejemplo n.º 16
0
def gen_model(name, dim_state, maha_test_kinds):

  # check if rebuild is needed
  try:
    dir_path = os.path.dirname(__file__)
    deps = [dir_path + '/' + 'ekf_c.c',
            dir_path + '/' + 'ekf_sym.py',
            dir_path + '/' + 'gnss_model.py',
            dir_path + '/' + 'gnss_kf.py']

    outs = [dir_path + '/' + name + '.o',
            dir_path + '/' + name + '.so',
            dir_path + '/' + name + '.cpp']
    out_times = list(map(os.path.getmtime, outs))
    dep_times = list(map(os.path.getmtime, deps))
    rebuild = os.getenv("REBUILD", False)
    if min(out_times) > max(dep_times) and not rebuild:
      return
    list(map(os.remove, outs))
  except OSError as e:
    pass

  # make functions and jacobians with sympy
  # state variables
  state_sym = sp.MatrixSymbol('state', dim_state, 1)
  state = sp.Matrix(state_sym)
  x,y,z = state[0:3,:]
  v = state[3:6,:]
  vx, vy, vz = v
  cb, cd, ca = state[6:9,:]
  glonass_bias, glonass_freq_slope = state[9:11,:]

  dt = sp.Symbol('dt')

  state_dot = sp.Matrix(np.zeros((dim_state, 1)))
  state_dot[:3,:] = v
  state_dot[6,0] = cd
  state_dot[7,0] = ca

  # Basic descretization, 1st order intergrator
  # Can be pretty bad if dt is big
  f_sym = state + dt*state_dot


  #
  # Observation functions
  #

  # extra args
  sat_pos_freq_sym = sp.MatrixSymbol('sat_pos', 4, 1)
  sat_pos_vel_sym = sp.MatrixSymbol('sat_pos_vel', 6, 1)
  sat_los_sym = sp.MatrixSymbol('sat_los', 3, 1)
  orb_epos_sym = sp.MatrixSymbol('orb_epos_sym', 3, 1)

  # expand extra args
  sat_x, sat_y, sat_z, glonass_freq = sat_pos_freq_sym
  sat_vx, sat_vy, sat_vz = sat_pos_vel_sym[3:]
  los_x, los_y, los_z = sat_los_sym
  orb_x, orb_y, orb_z = orb_epos_sym

  h_pseudorange_sym = sp.Matrix([sp.sqrt(
                                  (x - sat_x)**2 +
                                  (y - sat_y)**2 +
                                  (z - sat_z)**2) +
                                  cb])

  h_pseudorange_glonass_sym = sp.Matrix([sp.sqrt(
                                  (x - sat_x)**2 +
                                  (y - sat_y)**2 +
                                  (z - sat_z)**2) +
                                  cb + glonass_bias + glonass_freq_slope*glonass_freq])

  los_vector = (sp.Matrix(sat_pos_vel_sym[0:3]) - sp.Matrix([x, y, z]))
  los_vector = los_vector / sp.sqrt(los_vector[0]**2 + los_vector[1]**2 + los_vector[2]**2)
  h_pseudorange_rate_sym = sp.Matrix([los_vector[0]*(sat_vx - vx) +
                                         los_vector[1]*(sat_vy - vy) +
                                         los_vector[2]*(sat_vz - vz) +
                                         cd])

  obs_eqs = [[h_pseudorange_sym, ObservationKind.PSEUDORANGE_GPS, sat_pos_freq_sym],
             [h_pseudorange_glonass_sym, ObservationKind.PSEUDORANGE_GLONASS, sat_pos_freq_sym],
             [h_pseudorange_rate_sym, ObservationKind.PSEUDORANGE_RATE_GPS, sat_pos_vel_sym],
             [h_pseudorange_rate_sym, ObservationKind.PSEUDORANGE_RATE_GLONASS, sat_pos_vel_sym]]

  gen_code(name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state, maha_test_kinds=maha_test_kinds)
Ejemplo n.º 17
0
print(Numbering)
T = sympy.Matrix(numpy.zeros((6, 6)))

for i in range(3):
    for j in range(3):
        # if i==j:
        #     alpha = j
        # else:
        #     alpha = 9 - i - j
        alpha = Numbering[i, j]
        for p in range(3):
            for q in range(3):
                beta = Numbering[p, q]
                if alpha < 3 and beta < 3:
                    T[alpha, beta] = a[i, p] * a[i, p]
                if alpha >= 3 and beta < 3:
                    T[alpha, beta] = a[i, p] * a[j, p]
                if alpha < 3 and beta >= 3:
                    T[alpha, beta] = a[i, q] * a[i, p] + a[i, p] * a[i, q]
                if alpha >= 3 and beta >= 3:
                    T[alpha, beta] = a[i, p] * a[j, q] + a[i, q] * a[j, p]
print(T)

R = sympy.eye(6)  #Reuter matrix
R[3, 3] = R[4, 4] = R[5, 5] = 2
Tbar = R * T * R**-1
print(Tbar)

v = sympy.MatrixSymbol('v', 6, 1).as_explicit()
print(Tbar * v)
Ejemplo n.º 18
0
def test_MatAdd():
    X = sympy.MatrixSymbol('X', 4, 4)
    Y = sympy.MatrixSymbol('X', 4, 4)
    Z = sympy.MatrixSymbol('X', 4, 4)
    expr = X+Y+Z
    assert isinstance(theano_code(expr).owner.op, tt.Elemwise)
Ejemplo n.º 19
0
P = np.genfromtxt('csv/mdSpace.csv', delimiter=",")
n = len(P)
L = np.genfromtxt('csv/eigVals.csv', delimiter=",")
L_pos = np.array([L[i] if L[i] > 0 else 0 for i in range(n)])
d = np.count_nonzero(L_pos)  # d ... the number of positive values
Ln = np.sqrt(L_pos)

f2 = np.array(Ln[0:d])
f2[::2] = 0
f1 = Ln[0:d] - f2
e1 = f1 / np.linalg.norm(f1)
e2 = f2 / np.linalg.norm(f2)

a1, b1, c1, a2, b2, c2, t, s = sp.symbols('a1 b1 c1 a2 b2 c2 t s')  # variables
x2_s, y2_s = sp.symbols('x2_s y2_s')  # values
P_i = sp.MatrixSymbol('P_i', d, 1)
E1 = sp.MatrixSymbol('E1', d, 1)
E2 = sp.MatrixSymbol('E2', d, 1)
var = (x2_s, y2_s, P_i, E1, E2, a1, b1, c1, a2, b2, c2, t, s)

_E1 = a1 * sp.Matrix(E1) + b1 * sp.Matrix(E2) + c1 * sp.Matrix(P_i)
_E2 = a2 * sp.Matrix(E1) + b2 * sp.Matrix(E2) + c2 * sp.Matrix(P_i)
R = s * sp.Matrix(E1) + t * sp.Matrix(E2)

f = Matrix([
    _E1.dot(_E1) - 1,
    _E2.dot(_E2) - 1,
    _E1.dot(_E2),
    R.dot(R) - 1,
    _E1.dot(R) - sp.Matrix(E1).dot(R),
    _E2.dot(R) - sp.Matrix(E2).dot(R),
Ejemplo n.º 20
0
def test_MatrixSymbol():
    X = sympy.MatrixSymbol('X', 4, 5)
    Xt = theano_code(X)
    assert isinstance(Xt, tt.TensorVariable)
    assert Xt.broadcastable == (False, False)
Ejemplo n.º 21
0
    def generate_code(generated_dir, N=4):
        dim_augment = LocKalman.dim_augment
        dim_augment_err = LocKalman.dim_augment_err

        dim_main = LocKalman.x_initial.shape[0]
        dim_main_err = LocKalman.P_initial.shape[0]
        dim_state = dim_main + dim_augment * N
        dim_state_err = dim_main_err + dim_augment_err * N
        maha_test_kinds = LocKalman.maha_test_kinds

        name = f"{LocKalman.name}_{N}"

        # make functions and jacobians with sympy
        # state variables
        state_sym = sp.MatrixSymbol('state', dim_state, 1)
        state = sp.Matrix(state_sym)
        x, y, z = state[States.ECEF_POS, :]
        q = state[States.ECEF_ORIENTATION, :]
        v = state[States.ECEF_VELOCITY, :]
        vx, vy, vz = v
        omega = state[States.ANGULAR_VELOCITY, :]
        vroll, vpitch, vyaw = omega
        cb = state[States.CLOCK_BIAS, :]
        cd = state[States.CLOCK_DRIFT, :]
        roll_bias, pitch_bias, yaw_bias = state[States.GYRO_BIAS, :]
        acceleration = state[States.ACCELERATION, :]
        imu_from_device_euler = state[States.IMU_FROM_DEVICE_EULER, :]
        imu_from_device_euler[0, 0] = 0  # not observable enough
        imu_from_device_euler[2, 0] = 0  # not observable enough
        glonass_bias = state[States.GLONASS_BIAS, :]
        glonass_freq_slope = state[States.GLONASS_FREQ_SLOPE, :]
        ca = state[States.CLOCK_ACCELERATION, :]
        accel_bias = state[States.ACCELEROMETER_BIAS, :]
        wide_from_device_euler = state[States.WIDE_FROM_DEVICE_EULER, :]
        wide_from_device_euler[0, 0] = 0  # not observable enough

        dt = sp.Symbol('dt')

        # calibration and attitude rotation matrices
        quat_rot = quat_rotate(*q)

        # Got the quat predict equations from here
        # A New Quaternion-Based Kalman Filter for
        # Real-Time Attitude Estimation Using the Two-Step
        # Geometrically-Intuitive Correction Algorithm
        A = 0.5 * sp.Matrix(
            [[0, -vroll, -vpitch, -vyaw], [vroll, 0, vyaw, -vpitch],
             [vpitch, -vyaw, 0, vroll], [vyaw, vpitch, -vroll, 0]])
        q_dot = A * q

        # Time derivative of the state as a function of state
        state_dot = sp.Matrix(np.zeros((dim_state, 1)))
        state_dot[States.ECEF_POS, :] = v
        state_dot[States.ECEF_ORIENTATION, :] = q_dot
        state_dot[States.ECEF_VELOCITY, 0] = quat_rot * acceleration
        state_dot[States.CLOCK_BIAS, :] = cd
        state_dot[States.CLOCK_DRIFT, :] = ca

        # Basic descretization, 1st order intergrator
        # Can be pretty bad if dt is big
        f_sym = state + dt * state_dot

        state_err_sym = sp.MatrixSymbol('state_err', dim_state_err, 1)
        state_err = sp.Matrix(state_err_sym)
        quat_err = state_err[States.ECEF_ORIENTATION_ERR, :]
        v_err = state_err[States.ECEF_VELOCITY_ERR, :]
        omega_err = state_err[States.ANGULAR_VELOCITY_ERR, :]
        cd_err = state_err[States.CLOCK_DRIFT_ERR, :]
        acceleration_err = state_err[States.ACCELERATION_ERR, :]
        ca_err = state_err[States.CLOCK_ACCELERATION_ERR, :]

        # Time derivative of the state error as a function of state error and state
        quat_err_matrix = euler_rotate(quat_err[0], quat_err[1], quat_err[2])
        q_err_dot = quat_err_matrix * quat_rot * (omega + omega_err)
        state_err_dot = sp.Matrix(np.zeros((dim_state_err, 1)))
        state_err_dot[States.ECEF_POS_ERR, :] = v_err
        state_err_dot[States.ECEF_ORIENTATION_ERR, :] = q_err_dot
        state_err_dot[
            States.ECEF_VELOCITY_ERR, :] = quat_err_matrix * quat_rot * (
                acceleration + acceleration_err)
        state_err_dot[States.CLOCK_BIAS_ERR, :] = cd_err
        state_err_dot[States.CLOCK_DRIFT_ERR, :] = ca_err
        f_err_sym = state_err + dt * state_err_dot

        # convenient indexing
        # q idxs are for quats and p idxs are for other
        q_idxs = [[3, dim_augment]] + [[
            dim_main + n * dim_augment + 3, dim_main + (n + 1) * dim_augment
        ] for n in range(N)]
        q_err_idxs = [[3, dim_augment_err]] + [[
            dim_main_err + n * dim_augment_err + 3, dim_main_err +
            (n + 1) * dim_augment_err
        ] for n in range(N)]
        p_idxs = [[0, 3]] + [[dim_augment, dim_main]] + [[
            dim_main + n * dim_augment, dim_main + n * dim_augment + 3
        ] for n in range(N)]
        p_err_idxs = [[0, 3]] + [[dim_augment_err, dim_main_err]] + [[
            dim_main_err + n * dim_augment_err,
            dim_main_err + n * dim_augment_err + 3
        ] for n in range(N)]

        # Observation matrix modifier
        H_mod_sym = sp.Matrix(np.zeros((dim_state, dim_state_err)))
        for p_idx, p_err_idx in zip(p_idxs, p_err_idxs):
            H_mod_sym[p_idx[0]:p_idx[1],
                      p_err_idx[0]:p_err_idx[1]] = np.eye(p_idx[1] - p_idx[0])
        for q_idx, q_err_idx in zip(q_idxs, q_err_idxs):
            H_mod_sym[q_idx[0]:q_idx[1],
                      q_err_idx[0]:q_err_idx[1]] = 0.5 * quat_matrix_r(
                          state[q_idx[0]:q_idx[1]])[:, 1:]

        # these error functions are defined so that say there
        # is a nominal x and true x:
        # true x = err_function(nominal x, delta x)
        # delta x = inv_err_function(nominal x, true x)
        nom_x = sp.MatrixSymbol('nom_x', dim_state, 1)
        true_x = sp.MatrixSymbol('true_x', dim_state, 1)
        delta_x = sp.MatrixSymbol('delta_x', dim_state_err, 1)

        err_function_sym = sp.Matrix(np.zeros((dim_state, 1)))
        for q_idx, q_err_idx in zip(q_idxs, q_err_idxs):
            delta_quat = sp.Matrix(np.ones(4))
            delta_quat[1:, :] = sp.Matrix(
                0.5 * delta_x[q_err_idx[0]:q_err_idx[1], :])
            err_function_sym[q_idx[0]:q_idx[1], 0] = quat_matrix_r(
                nom_x[q_idx[0]:q_idx[1], 0]) * delta_quat
        for p_idx, p_err_idx in zip(p_idxs, p_err_idxs):
            err_function_sym[p_idx[0]:p_idx[1], :] = sp.Matrix(
                nom_x[p_idx[0]:p_idx[1], :] +
                delta_x[p_err_idx[0]:p_err_idx[1], :])

        inv_err_function_sym = sp.Matrix(np.zeros((dim_state_err, 1)))
        for p_idx, p_err_idx in zip(p_idxs, p_err_idxs):
            inv_err_function_sym[p_err_idx[0]:p_err_idx[1],
                                 0] = sp.Matrix(-nom_x[p_idx[0]:p_idx[1], 0] +
                                                true_x[p_idx[0]:p_idx[1], 0])
        for q_idx, q_err_idx in zip(q_idxs, q_err_idxs):
            delta_quat = quat_matrix_r(
                nom_x[q_idx[0]:q_idx[1], 0]).T * true_x[q_idx[0]:q_idx[1], 0]
            inv_err_function_sym[q_err_idx[0]:q_err_idx[1],
                                 0] = sp.Matrix(2 * delta_quat[1:])

        eskf_params = [[err_function_sym, nom_x, delta_x],
                       [inv_err_function_sym, nom_x, true_x], H_mod_sym,
                       f_err_sym, state_err_sym]
        #
        # Observation functions
        #

        # extra args
        sat_pos_freq_sym = sp.MatrixSymbol('sat_pos', 4, 1)
        sat_pos_vel_sym = sp.MatrixSymbol('sat_pos_vel', 6, 1)
        # sat_los_sym = sp.MatrixSymbol('sat_los', 3, 1)

        # expand extra args
        sat_x, sat_y, sat_z, glonass_freq = sat_pos_freq_sym
        sat_vx, sat_vy, sat_vz = sat_pos_vel_sym[3:]

        h_pseudorange_sym = sp.Matrix([
            sp.sqrt((x - sat_x)**2 + (y - sat_y)**2 + (z - sat_z)**2) + cb[0]
        ])

        h_pseudorange_glonass_sym = sp.Matrix([
            sp.sqrt((x - sat_x)**2 + (y - sat_y)**2 + (z - sat_z)**2) + cb[0] +
            glonass_bias[0] + glonass_freq_slope[0] * glonass_freq
        ])

        los_vector = (sp.Matrix(sat_pos_vel_sym[0:3]) - sp.Matrix([x, y, z]))
        los_vector = los_vector / sp.sqrt(los_vector[0]**2 + los_vector[1]**2 +
                                          los_vector[2]**2)
        h_pseudorange_rate_sym = sp.Matrix([
            los_vector[0] * (sat_vx - vx) + los_vector[1] * (sat_vy - vy) +
            los_vector[2] * (sat_vz - vz) + cd[0]
        ])

        imu_from_device = euler_rotate(*imu_from_device_euler)
        h_gyro_sym = imu_from_device * sp.Matrix(
            [vroll + roll_bias, vpitch + pitch_bias, vyaw + yaw_bias])

        pos = sp.Matrix([x, y, z])
        # add 1 for stability, prevent division by 0
        gravity = quat_rot.T * ((EARTH_GM / (
            (x**2 + y**2 + z**2 + 1)**(3.0 / 2.0))) * pos)
        h_acc_sym = imu_from_device * (gravity + acceleration + accel_bias)
        h_acc_stationary_sym = acceleration
        h_phone_rot_sym = sp.Matrix([vroll, vpitch, vyaw])
        h_relative_motion = sp.Matrix(quat_rot.T * v)

        obs_eqs = [
            [h_gyro_sym, ObservationKind.PHONE_GYRO, None],
            [h_phone_rot_sym, ObservationKind.NO_ROT, None],
            [h_acc_sym, ObservationKind.PHONE_ACCEL, None],
            [
                h_pseudorange_sym, ObservationKind.PSEUDORANGE_GPS,
                sat_pos_freq_sym
            ],
            [
                h_pseudorange_glonass_sym, ObservationKind.PSEUDORANGE_GLONASS,
                sat_pos_freq_sym
            ],
            [
                h_pseudorange_rate_sym, ObservationKind.PSEUDORANGE_RATE_GPS,
                sat_pos_vel_sym
            ],
            [
                h_pseudorange_rate_sym,
                ObservationKind.PSEUDORANGE_RATE_GLONASS, sat_pos_vel_sym
            ],
            [h_relative_motion, ObservationKind.CAMERA_ODO_TRANSLATION, None],
            [h_phone_rot_sym, ObservationKind.CAMERA_ODO_ROTATION, None],
            [h_acc_stationary_sym, ObservationKind.NO_ACCEL, None]
        ]

        wide_from_device = euler_rotate(*wide_from_device_euler)
        # MSCKF configuration
        if N > 0:
            # experimentally found this is correct value for imx298 with 910 focal length
            # this is a variable so it can change with focus, but we disregard that for now
            # TODO: this isn't correct for tici
            focal_scale = 1.01
            # Add observation functions for orb feature tracks
            track_epos_sym = sp.MatrixSymbol('track_epos_sym', 3, 1)
            track_x, track_y, track_z = track_epos_sym
            h_track_sym = sp.Matrix(np.zeros(((1 + N) * 2, 1)))
            h_track_wide_cam_sym = sp.Matrix(np.zeros(((1 + N) * 2, 1)))

            track_pos_sym = sp.Matrix([track_x - x, track_y - y, track_z - z])
            track_pos_rot_sym = quat_rot.T * track_pos_sym
            track_pos_rot_wide_cam_sym = wide_from_device * track_pos_rot_sym
            h_track_sym[-2:, :] = sp.Matrix([
                focal_scale * (track_pos_rot_sym[1] / track_pos_rot_sym[0]),
                focal_scale * (track_pos_rot_sym[2] / track_pos_rot_sym[0])
            ])
            h_track_wide_cam_sym[-2:, :] = sp.Matrix([
                focal_scale * (track_pos_rot_wide_cam_sym[1] /
                               track_pos_rot_wide_cam_sym[0]), focal_scale *
                (track_pos_rot_wide_cam_sym[2] / track_pos_rot_wide_cam_sym[0])
            ])

            h_msckf_test_sym = sp.Matrix(np.zeros(((1 + N) * 3, 1)))
            h_msckf_test_sym[-3:, :] = track_pos_sym

            for n in range(N):
                idx = dim_main + n * dim_augment
                # err_idx = dim_main_err + n * dim_augment_err  # FIXME: Why is this not used?
                x, y, z = state[idx:idx + 3]
                q = state[idx + 3:idx + 7]
                quat_rot = quat_rotate(*q)
                track_pos_sym = sp.Matrix(
                    [track_x - x, track_y - y, track_z - z])
                track_pos_rot_sym = quat_rot.T * track_pos_sym
                track_pos_rot_wide_cam_sym = wide_from_device * track_pos_rot_sym
                h_track_sym[n * 2:n * 2 + 2, :] = sp.Matrix([
                    focal_scale *
                    (track_pos_rot_sym[1] / track_pos_rot_sym[0]),
                    focal_scale * (track_pos_rot_sym[2] / track_pos_rot_sym[0])
                ])
                h_track_wide_cam_sym[n * 2:n * 2 + 2, :] = sp.Matrix([
                    focal_scale * (track_pos_rot_wide_cam_sym[1] /
                                   track_pos_rot_wide_cam_sym[0]),
                    focal_scale * (track_pos_rot_wide_cam_sym[2] /
                                   track_pos_rot_wide_cam_sym[0])
                ])
                h_msckf_test_sym[n * 3:n * 3 + 3, :] = track_pos_sym

            obs_eqs.append(
                [h_msckf_test_sym, ObservationKind.MSCKF_TEST, track_epos_sym])
            obs_eqs.append(
                [h_track_sym, ObservationKind.ORB_FEATURES, track_epos_sym])
            obs_eqs.append([
                h_track_wide_cam_sym, ObservationKind.ORB_FEATURES_WIDE,
                track_epos_sym
            ])
            obs_eqs.append([
                h_track_sym, ObservationKind.FEATURE_TRACK_TEST, track_epos_sym
            ])
            msckf_params = [
                dim_main, dim_augment, dim_main_err, dim_augment_err, N,
                [
                    ObservationKind.MSCKF_TEST, ObservationKind.ORB_FEATURES,
                    ObservationKind.ORB_FEATURES_WIDE
                ]
            ]
        else:
            msckf_params = None
        gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state,
                 dim_state_err, eskf_params, msckf_params, maha_test_kinds)
Ejemplo n.º 22
0
def test_MatMul():
    X = sympy.MatrixSymbol('X', 4, 4)
    Y = sympy.MatrixSymbol('X', 4, 4)
    Z = sympy.MatrixSymbol('X', 4, 4)
    expr = X*Y*Z
    assert isinstance(theano_code(expr).owner.op, tt.Dot)
Ejemplo n.º 23
0
def gen_model(name, dim_state, dim_state_err, maha_test_kinds):
    # check if rebuild is needed
    try:
        dir_path = os.path.dirname(__file__)
        deps = [
            dir_path + '/' + 'ekf_c.c', dir_path + '/' + 'ekf_sym.py',
            dir_path + '/' + name + '_model.py',
            dir_path + '/' + name + '_kf.py'
        ]

        outs = [
            dir_path + '/' + name + '.o',
            dir_path + '/' + name + sysconfig.get_config_var('EXT_SUFFIX'),
            dir_path + '/' + name + '.cpp'
        ]
        out_times = list(map(os.path.getmtime, outs))
        dep_times = list(map(os.path.getmtime, deps))
        rebuild = os.getenv("REBUILD", False)
        if min(out_times) > max(dep_times) and not rebuild:
            return
        list(map(os.remove, outs))
    except OSError as e:
        print('HAHAHA')
        print(e)
        pass

    # make functions and jacobians with sympy
    # state variables
    state_sym = sp.MatrixSymbol('state', dim_state, 1)
    state = sp.Matrix(state_sym)
    x, y, z = state[States.ECEF_POS, :]
    q = state[States.ECEF_ORIENTATION, :]
    v = state[States.ECEF_VELOCITY, :]
    vx, vy, vz = v
    omega = state[States.GYRO_BIAS, :]
    vroll, vpitch, vyaw = omega
    roll_bias, pitch_bias, yaw_bias = state[States.GYRO_BIAS, :]
    odo_scale = state[16, :]
    acceleration = state[States.ACCELERATION, :]
    imu_angles = state[States.IMU_OFFSET, :]

    dt = sp.Symbol('dt')

    # calibration and attitude rotation matrices
    quat_rot = quat_rotate(*q)

    # Got the quat predict equations from here
    # A New Quaternion-Based Kalman Filter for
    # Real-Time Attitude Estimation Using the Two-Step
    # Geometrically-Intuitive Correction Algorithm
    A = 0.5 * sp.Matrix([[0, -vroll, -vpitch, -vyaw], [
        vroll, 0, vyaw, -vpitch
    ], [vpitch, -vyaw, 0, vroll], [vyaw, vpitch, -vroll, 0]])
    q_dot = A * q

    # Time derivative of the state as a function of state
    state_dot = sp.Matrix(np.zeros((dim_state, 1)))
    state_dot[States.ECEF_POS, :] = v
    state_dot[States.ECEF_ORIENTATION, :] = q_dot
    state_dot[States.ECEF_VELOCITY, 0] = quat_rot * acceleration

    # Basic descretization, 1st order intergrator
    # Can be pretty bad if dt is big
    f_sym = state + dt * state_dot

    state_err_sym = sp.MatrixSymbol('state_err', dim_state_err, 1)
    state_err = sp.Matrix(state_err_sym)
    quat_err = state_err[States.ECEF_ORIENTATION_ERR, :]
    v_err = state_err[States.ECEF_VELOCITY_ERR, :]
    omega_err = state_err[States.ANGULAR_VELOCITY_ERR, :]
    acceleration_err = state_err[States.ACCELERATION_ERR, :]

    # Time derivative of the state error as a function of state error and state
    quat_err_matrix = euler_rotate(quat_err[0], quat_err[1], quat_err[2])
    q_err_dot = quat_err_matrix * quat_rot * (omega + omega_err)
    state_err_dot = sp.Matrix(np.zeros((dim_state_err, 1)))
    state_err_dot[States.ECEF_POS_ERR, :] = v_err
    state_err_dot[States.ECEF_ORIENTATION_ERR, :] = q_err_dot
    state_err_dot[States.ECEF_VELOCITY_ERR, :] = quat_err_matrix * quat_rot * (
        acceleration + acceleration_err)
    f_err_sym = state_err + dt * state_err_dot

    # Observation matrix modifier
    H_mod_sym = sp.Matrix(np.zeros((dim_state, dim_state_err)))
    H_mod_sym[0:3, 0:3] = np.eye(3)

    H_mod_sym[3:7, 3:6] = 0.5 * quat_matrix_r(state[3:7])[:, 1:]

    # these error functions are defined so that say there
    # is a nominal x and true x:
    # true x = err_function(nominal x, delta x)
    # delta x = inv_err_function(nominal x, true x)
    nom_x = sp.MatrixSymbol('nom_x', dim_state, 1)
    true_x = sp.MatrixSymbol('true_x', dim_state, 1)
    delta_x = sp.MatrixSymbol('delta_x', dim_state_err, 1)

    err_function_sym = sp.Matrix(np.zeros((dim_state, 1)))
    delta_quat = sp.Matrix(np.ones((4)))
    delta_quat[1:, :] = sp.Matrix(0.5 * delta_x[3:6, :])
    err_function_sym[3:7, 0] = quat_matrix_r(nom_x[3:7, 0]) * delta_quat
    err_function_sym[0:3, :] = sp.Matrix(nom_x[0:3, :] + delta_x[0:3, :])

    inv_err_function_sym = sp.Matrix(np.zeros((dim_state_err, 1)))
    inv_err_function_sym[0:3, 0] = sp.Matrix(-nom_x[0:3, 0] + true_x[0:3, 0])
    delta_quat = quat_matrix_r(nom_x[3:7, 0]).T * true_x[3:7, 0]
    inv_err_function_sym[3:6, 0] = sp.Matrix(2 * delta_quat[1:])

    eskf_params = [[err_function_sym, nom_x, delta_x],
                   [inv_err_function_sym, nom_x, true_x], H_mod_sym, f_err_sym,
                   state_err_sym]

    #
    # Observation functions
    #

    imu_rot = euler_rotate(*imu_angles)
    h_gyro_sym = imu_rot * sp.Matrix(
        [vroll + roll_bias, vpitch + pitch_bias, vyaw + yaw_bias])

    pos = sp.Matrix([x, y, z])
    gravity = quat_rot.T * ((EARTH_GM /
                             ((x**2 + y**2 + z**2)**(3.0 / 2.0))) * pos)
    h_acc_sym = imu_rot * (gravity + acceleration)
    h_phone_rot_sym = sp.Matrix([vroll, vpitch, vyaw])
    speed = vx**2 + vy**2 + vz**2
    h_speed_sym = sp.Matrix([sp.sqrt(speed) * odo_scale])

    h_pos_sym = sp.Matrix([x, y, z])
    h_imu_frame_sym = sp.Matrix(imu_angles)

    h_relative_motion = sp.Matrix(quat_rot.T * v)

    obs_eqs = [[h_speed_sym, ObservationKind.ODOMETRIC_SPEED, None],
               [h_gyro_sym, ObservationKind.PHONE_GYRO, None],
               [h_phone_rot_sym, ObservationKind.NO_ROT, None],
               [h_acc_sym, ObservationKind.PHONE_ACCEL, None],
               [h_pos_sym, ObservationKind.ECEF_POS, None],
               [
                   h_relative_motion, ObservationKind.CAMERA_ODO_TRANSLATION,
                   None
               ], [h_phone_rot_sym, ObservationKind.CAMERA_ODO_ROTATION, None],
               [h_imu_frame_sym, ObservationKind.IMU_FRAME, None]]

    gen_code(name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state_err,
             eskf_params)
Ejemplo n.º 24
0
def test_Transpose():
    X = sympy.MatrixSymbol('X', 4, 4)
    assert isinstance(theano_code(X.T).owner.op, tt.DimShuffle)
Ejemplo n.º 25
0
    def generate_code():
        dim_state = CarKalman.x_initial.shape[0]
        name = CarKalman.name
        maha_test_kinds = CarKalman.maha_test_kinds

        # make functions and jacobians with sympy
        # state variables
        state_sym = sp.MatrixSymbol('state', dim_state, 1)
        state = sp.Matrix(state_sym)

        # Vehicle model constants
        # TODO: Read from car params at runtime
        from selfdrive.controls.lib.vehicle_model import VehicleModel
        from selfdrive.car.toyota.interface import CarInterface
        from selfdrive.car.toyota.values import CAR

        CP = CarInterface.get_params(CAR.COROLLA_TSS2)
        VM = VehicleModel(CP)

        m = VM.m
        j = VM.j
        aF = VM.aF
        aR = VM.aR

        x = state[States.STIFFNESS, :][0, 0]

        cF, cR = x * VM.cF, x * VM.cR
        angle_offset = state[States.ANGLE_OFFSET, :][0, 0]
        angle_offset_fast = state[States.ANGLE_OFFSET_FAST, :][0, 0]
        sa = state[States.STEER_ANGLE, :][0, 0]

        sR = state[States.STEER_RATIO, :][0, 0]
        u, v = state[States.VELOCITY, :]
        r = state[States.YAW_RATE, :][0, 0]

        A = sp.Matrix(np.zeros((2, 2)))
        A[0, 0] = -(cF + cR) / (m * u)
        A[0, 1] = -(cF * aF - cR * aR) / (m * u) - u
        A[1, 0] = -(cF * aF - cR * aR) / (j * u)
        A[1, 1] = -(cF * aF**2 + cR * aR**2) / (j * u)

        B = sp.Matrix(np.zeros((2, 1)))
        B[0, 0] = cF / m / sR
        B[1, 0] = (cF * aF) / j / sR

        x = sp.Matrix([v, r])  # lateral velocity, yaw rate
        x_dot = A * x + B * (sa - angle_offset - angle_offset_fast)

        dt = sp.Symbol('dt')
        state_dot = sp.Matrix(np.zeros((dim_state, 1)))
        state_dot[States.VELOCITY.start + 1, 0] = x_dot[0]
        state_dot[States.YAW_RATE.start, 0] = x_dot[1]

        # Basic descretization, 1st order integrator
        # Can be pretty bad if dt is big
        f_sym = state + dt * state_dot

        #
        # Observation functions
        #
        obs_eqs = [
            [sp.Matrix([r]), ObservationKind.ROAD_FRAME_YAW_RATE, None],
            [sp.Matrix([u, v]), ObservationKind.ROAD_FRAME_XY_SPEED, None],
            [sp.Matrix([sa]), ObservationKind.STEER_ANGLE, None],
            [
                sp.Matrix([angle_offset_fast]),
                ObservationKind.ANGLE_OFFSET_FAST, None
            ],
            [sp.Matrix([sR]), ObservationKind.STEER_RATIO, None],
            [sp.Matrix([x]), ObservationKind.STIFFNESS, None],
        ]

        gen_code(name,
                 f_sym,
                 dt,
                 state_sym,
                 obs_eqs,
                 dim_state,
                 dim_state,
                 maha_test_kinds=maha_test_kinds)
Ejemplo n.º 26
0
    def generate_code():
        dim_state = GNSSKalman.x_initial.shape[0]
        name = GNSSKalman.name
        maha_test_kinds = GNSSKalman.maha_test_kinds

        # make functions and jacobians with sympy
        # state variables
        state_sym = sp.MatrixSymbol('state', dim_state, 1)
        state = sp.Matrix(state_sym)
        x, y, z = state[0:3, :]
        v = state[3:6, :]
        vx, vy, vz = v
        cb, cd, ca = state[6:9, :]
        glonass_bias, glonass_freq_slope = state[9:11, :]

        dt = sp.Symbol('dt')

        state_dot = sp.Matrix(np.zeros((dim_state, 1)))
        state_dot[:3, :] = v
        state_dot[6, 0] = cd
        state_dot[7, 0] = ca

        # Basic descretization, 1st order integrator
        # Can be pretty bad if dt is big
        f_sym = state + dt * state_dot

        #
        # Observation functions
        #

        # extra args
        sat_pos_freq_sym = sp.MatrixSymbol('sat_pos', 4, 1)
        sat_pos_vel_sym = sp.MatrixSymbol('sat_pos_vel', 6, 1)
        sat_los_sym = sp.MatrixSymbol('sat_los', 3, 1)
        orb_epos_sym = sp.MatrixSymbol('orb_epos_sym', 3, 1)

        # expand extra args
        sat_x, sat_y, sat_z, glonass_freq = sat_pos_freq_sym
        sat_vx, sat_vy, sat_vz = sat_pos_vel_sym[3:]
        los_x, los_y, los_z = sat_los_sym
        orb_x, orb_y, orb_z = orb_epos_sym

        h_pseudorange_sym = sp.Matrix(
            [sp.sqrt((x - sat_x)**2 + (y - sat_y)**2 + (z - sat_z)**2) + cb])

        h_pseudorange_glonass_sym = sp.Matrix([
            sp.sqrt((x - sat_x)**2 + (y - sat_y)**2 + (z - sat_z)**2) + cb +
            glonass_bias + glonass_freq_slope * glonass_freq
        ])

        los_vector = (sp.Matrix(sat_pos_vel_sym[0:3]) - sp.Matrix([x, y, z]))
        los_vector = los_vector / sp.sqrt(los_vector[0]**2 + los_vector[1]**2 +
                                          los_vector[2]**2)
        h_pseudorange_rate_sym = sp.Matrix([
            los_vector[0] * (sat_vx - vx) + los_vector[1] * (sat_vy - vy) +
            los_vector[2] * (sat_vz - vz) + cd
        ])

        obs_eqs = [[
            h_pseudorange_sym, ObservationKind.PSEUDORANGE_GPS,
            sat_pos_freq_sym
        ],
                   [
                       h_pseudorange_glonass_sym,
                       ObservationKind.PSEUDORANGE_GLONASS, sat_pos_freq_sym
                   ],
                   [
                       h_pseudorange_rate_sym,
                       ObservationKind.PSEUDORANGE_RATE_GPS, sat_pos_vel_sym
                   ],
                   [
                       h_pseudorange_rate_sym,
                       ObservationKind.PSEUDORANGE_RATE_GLONASS,
                       sat_pos_vel_sym
                   ]]

        gen_code(name,
                 f_sym,
                 dt,
                 state_sym,
                 obs_eqs,
                 dim_state,
                 dim_state,
                 maha_test_kinds=maha_test_kinds)
Ejemplo n.º 27
0
def generate_code(order,
                  name,
                  precision='double',
                  cython=False,
                  CSE=False,
                  harmonic_derivs=False,
                  include_dir=None,
                  src_dir=None,
                  potential=True,
                  field=True,
                  source_order=0,
                  atomic=False,
                  gpu=False,
                  minpow=0,
                  language='c',
                  save_opscounts=None):
    """
    Inputs:

    order, int:
        Expansion order of the FMM operators.

    name, str:
        Name of generated files.

        Note: Cython compiles *.pyx files to the *.c files with the same name,
        which means that we have to use a different name for the cython file.
        We therefore append "wrap" to the end of the name for the cython file,
        and this is therefore the name of the Python module which must be
        imported if using pyximport.

    cython_wrapper, bool:
        Enable generation of a Cython wrapper for the C files.

    CSE, bool:
        Enable common subexpression elimination, to reduce the op count in
        the generated code.

    harmonic_derivs, bool:
        The harmonicity of the Laplace means that at order p, there are only
        2p - 1 independent derivatives. Enabling this option therefore computes
        some derivatives as combinations of others.

    source_order, int:
        If source_order > 0 then we set certain multipole terms to zero
        in the local expansion, and hence they are not used. This is useful if,
        for example, we only have pure dipoles or quadrupoles in the system.

    minpow, int:
        If minpow is set, pow(x, n) expressions are expanded such that
        if n < minpow, the expression in code is printed as multiplications.

        e.g. if a sympy expression is pow(x, 2) + pow(y, 6) and minpow is 5,
        the printed version will be x*x + pow(y, 6)

    save_opcounts, string:
        Filename to save opcounts in
    """
    if save_opscounts:
        f = open(save_opscounts, 'w')

    assert language in ['c', 'c++'], "Language must be 'c' or 'c++'"
    if language == 'c':
        fext = 'c'
        hext = 'h'
    if language == 'c++':
        fext = 'cpp'
        hext = 'h'

    logger.info(f"Generating FMM operators to order {order}")
    assert precision in ['double',
                         'float'], "Precision must be float or double"
    logger.info(f"Precision = {precision}")
    if CSE:
        logger.info(f"CSE Enabled")
        p = FunctionPrinter(precision=precision, debug=False, minpow=minpow)
    else:
        logger.info(f"CSE Disabled")
        p = FunctionPrinter(precision=precision, debug=True, minpow=minpow)

    header = ""
    body = ""

    x, y, z, q = sp.symbols('x y z q')
    symbols = (x, y, z)
    coords = [x, y, z]

    start = source_order
    if field:
        # No point starting at source_order
        # because no field calculation can be done
        # at this multipole order - the L2P derivative
        # is 0. This is true whether or not we
        # calculate potential, so we always increment
        # by 1 here the start order, such that the
        # field is always calculated.
        #
        # It may be preferable to instead compute
        # the field using a finite-difference approximation,
        # or to enable this as a general option.
        # However, this would be fairly sensitive, would
        # require another user parameter (lengths over which
        # to take the f.d. approximation), a decision on
        # whether to use forward/backward/central differencing,
        # and the order of the approximation. For now, we
        # leave it as a simple symbolic derivative.
        start += 1

    for i in range(start, order):
        print(f"Generating Order {i} operators")
        M_dict, _ = generate_mappings(i,
                                      symbols,
                                      'grevlex',
                                      source_order=source_order)
        L_dict, _ = generate_mappings(i - source_order,
                                      symbols,
                                      'grevlex',
                                      source_order=0)

        M = sp.Matrix(generate_M_operators(i, symbols, M_dict))

        head, code, P2M_opscount = p.generate(f'P2M_{i}',
                                              'M',
                                              M,
                                              coords + [q],
                                              operator='+=')
        print(f"P2M_{i} opscount = {P2M_opscount}")
        header += head
        body += code
        Ms = sp.Matrix(
            generate_M_shift_operators(i,
                                       symbols,
                                       M_dict,
                                       source_order=source_order))

        head, code, M2M_opscount = p.generate(f'M2M_{i}', 'Ms', Ms,
                                list(symbols) + \
                                [sp.MatrixSymbol('M', Nterms(i), 1)],
                                operator="+=", atomic=atomic)
        header += head
        body += code + '\n'
        print(f"M2M_{i} opscount = {M2M_opscount}")
        # Two stages here; generate derivs and then the L matrix. Both
        # must be passed to the function printer.
        derivs = sp.Matrix(
            generate_derivs(i,
                            symbols,
                            M_dict,
                            source_order,
                            harmonic_derivs=harmonic_derivs))
        L = sp.Matrix(
            generate_L_operators(i,
                                 symbols,
                                 M_dict,
                                 L_dict,
                                 source_order=source_order))

        head, code, M2L_opscount = p.generate(f'M2L_{i}', 'L', L,
                               list(symbols) +  \
                               [sp.MatrixSymbol('M', Nterms(i), 1)],
                                operator="+=", atomic=atomic, internal=[('D', derivs)])
        header += head
        body += code + '\n'
        print(f"M2L_{i} opscount = {M2L_opscount}")

        Ls = sp.Matrix(
            generate_L_shift_operators(i,
                                       symbols,
                                       L_dict,
                                       source_order=source_order))
        head, code, L2L_opscount = p.generate(f'L2L_{i}', 'Ls', Ls,
                               list(symbols) + \
                               [sp.MatrixSymbol('L', Nterms(i), 1)],
                                operator="+=", atomic=atomic)

        header += head
        body += code + '\n'
        print(f"L2L_{i} opscount = {L2L_opscount}")
        L2P = generate_L2P_operators(i,
                                     symbols,
                                     L_dict,
                                     potential=potential,
                                     field=field)

        Fs = sp.Matrix(L2P)
        head, code, L2P_opscount = p.generate(f'L2P_{i}', 'F', Fs,
                               list(symbols) + \
                               [sp.MatrixSymbol('L', Nterms(i), 1)],
                                operator="+=", atomic=atomic)

        header += head
        body += code + '\n'
        print(f"L2P_{i} opscount = {L2P_opscount}")
        M2P = generate_M2P_operators(i,
                                     symbols,
                                     M_dict,
                                     potential=potential,
                                     field=field,
                                     source_order=source_order,
                                     harmonic_derivs=harmonic_derivs)
        Fs = sp.Matrix(M2P)
        head, code, M2P_opscount = p.generate(f'M2P_{i}', 'F', Fs,
                                list(symbols) + \
                                [sp.MatrixSymbol('M', Nterms(i), 1)],
                                operator="+=", atomic=atomic)
        header += head
        body += code + '\n'
        print(f"M2P_{i} opscount = {M2P_opscount}")
        if i == start:
            P2P = sp.Matrix(
                generate_P2P_operators(symbols,
                                       M_dict,
                                       potential=potential,
                                       field=field,
                                       source_order=source_order))

            head, code, P2P_opscount = p.generate(f'P2P', 'F', P2P,
                                    list(symbols) + \
                                    [sp.MatrixSymbol('S', Nterms(i), 1)],
                                    operator="+=", atomic=atomic
                                    )
            print(f"P2P opscount = {P2P_opscount}")
            header += head
            body += code + '\n'

        if save_opscounts:
            if i == start:
                f.write(f'P2P,{P2P_opscount}\n')
            f.write(f'P2M_{i},{P2M_opscount}\n')
            f.write(f'M2M_{i},{M2M_opscount}\n')
            f.write(f'M2L_{i},{M2L_opscount}\n')
            f.write(f'L2P_{i},{L2P_opscount}\n')
            f.write(f'L2L_{i},{L2L_opscount}\n')
            f.write(f'M2P_{i},{M2P_opscount}\n')

# We now generate wrapper functions that cover all orders generated.
    unique_funcs = []
    func_definitions = header.split(';\n')
    # print(f"func_defs = {func_definitions}")
    for func in func_definitions:
        # Must do it this way in order to avoid breaking
        # for expansions > 10.
        function_name = func.split('(')[0]
        # print(f"Function_name = {function_name}")
        end_string = f'_{start}'
        if end_string == function_name[-len(end_string):]:
            # print("Unique!")
            unique_funcs.append(func)
        else:
            pass
            # print(f"{func} not unique")
            # print(f"  {end_string}  {function_name[-len(end_string)-1:]}")

    wrapper_funcs = [
        f.replace(')', ', int order)').replace(f'_{start}', '')
        for f in unique_funcs
    ]

    #  print(wrapper_funcs)

    func_definitions += wrapper_funcs
    # print('\n'.join(func_definitions))

    for wfunc, func in zip(wrapper_funcs, unique_funcs):
        # Add to header file
        header += wfunc + ';\n'
        # Create a switch statement that covers all functions:
        code = wfunc + " {\n"
        code += 'switch (order) {\n'
        for i in range(start, order):
            code += '  case {}:\n'.format(i)
            # print(func)
            replaced_code = func.replace(f'_{start}', f'_{i}').replace(
                '* ', '').replace('double ',
                                  '').replace('float ',
                                              '').replace('void ', '')
            # print(f"replaced_code: {replaced_code}")
            code += '    ' + replaced_code + ';\n    break;\n'
        code += "  }\n}\n"
        # print(code)
        body += code

    if not include_dir:
        f = open(f"{name}.{hext}", 'w')
    else:
        f = open(f"{include_dir.rstrip('/')}/{name}.{hext}", 'w')
    f.write(f"#pragma once\n")
    f.write(f"#define FMMGEN_MINORDER {start}\n")
    f.write(f"#define FMMGEN_MAXORDER {order}\n")
    f.write(f"#define FMMGEN_SOURCEORDER {source_order}\n")
    f.write(
        f"#define FMMGEN_SOURCESIZE {Nterms(source_order) - Nterms(source_order - 1)}\n"
    )
    if potential and not field:
        osize = 1
    elif field and not potential:
        osize = 3
    elif field and potential:
        osize = 4
    f.write(f"#define FMMGEN_OUTPUTSIZE {osize}\n")
    f.write(header)
    f.close()

    if not src_dir:
        f = open(f"{name}.{fext}", 'w')
    else:
        f = open(f"{src_dir.rstrip('/')}/{name}.{fext}", 'w')

    f.write(f'#include "{name}.{hext}"\n')
    if language == 'c':
        f.write(f'#include "math.h"\n')
    elif language == 'c++':
        f.write(f'#include<cmath>\n')

    f.write(body)
    f.close()

    if cython and gpu:
        raise Warning("Cannot write a Cython wrapper for GPU code; skipping")

    elif cython:
        logger.info(f"Generating Cython wrapper: {name}_wrap.pyx")
        library = f"{name}"

        f = open(f"{name}_decl.pxd", "w")
        pxdcode = textwrap.dedent("""\
        cdef extern from "{}.h":
            cdef int FMMGEN_MINORDER
            cdef int FMMGEN_MAXORDER
            cdef int FMMGEN_SOURCEORDER
            cdef int FMMGEN_SOURCESIZE
            cdef int FMMGEN_OUTPUTSIZE
            {}
        """)
        f.write(pxdcode.format(name, '\n    '.join(func_definitions)))

        f.close()

        f = open(f"{name}_wrap.pyx", "w")
        # expose the C functions from the header file.
        pyxcode = textwrap.dedent("""\
        # cython: language_level=3
        cimport numpy as np
        cimport {}

        FMMGEN_MINORDER = {}.FMMGEN_MINORDER
        FMMGEN_MAXORDER = {}.FMMGEN_MAXORDER
        FMMGEN_SOURCEORDER = {}.FMMGEN_SOURCEORDER
        FMMGEN_SOURCESIZE = {}.FMMGEN_SOURCESIZE
        FMMGEN_OUTPUTSIZE = {}.FMMGEN_OUTPUTSIZE
        """).format(*[name + '_decl'] * 6)

        subsdict = {" *": "[:]", "void": "cpdef", "_": ""}

        # Generate the actual wrapper code
        for funcname in func_definitions:
            # print(funcname)
            if not funcname:
                continue
            pyfuncname = funcname
            for key, value in subsdict.items():
                pyfuncname = pyfuncname.replace(key, value)
            pyxcode += pyfuncname + ':\n'

            function_name = funcname.split("(")[0].split(" ")[1]
            args = funcname.split("(")[1][:-1].split(",")
            processed_args = []

            for arg in args:
                if "*" in arg:
                    arg = arg.replace("* ", "&") + "[0]"
                processed_args.append(arg.split(" ")[-1])

            pyxcode += '    ' + \
                       name + '_decl.' + function_name + \
                       "(" + ', '.join(processed_args) + ')\n\n'

        f.write(pyxcode)
        f.close()

        f = open(f"{name}_wrap.pyxbld", "w")

        # print(library)

        logger.info(f"Generating Cython buildfile: {name}_wrap.pyxbld")
        bldcode = textwrap.dedent("""\
        import numpy as np

        def make_ext(modname, pyxfilename):
            from distutils.extension import Extension
            return Extension(name = modname,
                             sources=[pyxfilename, '{}'],
                             include_dirs=[np.get_include(), '.'],
                             library_dirs=['.'],
                             extra_link_args=[],
                             extra_compile_args=['-O3', '-fopenmp'])
        """).format(library + '.c', library)

        f.write(bldcode)
        f.close()
def ode_dVdt_expr():
    ''' integrate the problem vector, which is defined as:

        V = [x(14),
                Phi_A(14x14), B_bar(14x3), C_bar(14x3), S_bar(14), z_bar(14)]

        V has no correlation to v (velocity) except that it contains v inside
    '''

    import sympy
    from old.dynamics_functions_sympy import Dynamics as Dynamics_sympy

    matrix_functions = Dynamics_sympy()
    matrix_functions.set_parameters({
        'alpha': sympy.Symbol('alpha'),
        'g_I': sympy.MatrixSymbol('g_I', 3, 1),
        'rTB': sympy.MatrixSymbol('rTB', 3, 1),
        'J': sympy.MatrixSymbol('J', 3, 3),
    })

    V = sympy.MatrixSymbol('V', idx[-1], 1)
    t = sympy.Symbol('t')
    u_t = sympy.MatrixSymbol('u_t', 3, 1)
    u_t1 = sympy.MatrixSymbol('u_t1', 3, 1)
    sigma = sympy.Symbol('sigma')
    dt = sympy.Symbol('dt')

    A, B, f = (matrix_functions.A, matrix_functions.B, matrix_functions.f)

    alpha = (t / dt)
    beta = (1 - t / dt)
    # Gather x and u
    x = V[0:idx[0]]
    u = u_t + alpha * (u_t1 - u_t)
    ''' Since PhiA(t) * A(t) = Phi(t_end), PhiA(t) = Phi(t_end) * A.inverse '''
    #Phi      = sympy.Matrix(V[idx[0] : idx[1]]).reshape(14, 14)
    Phi = sympy.MatrixSymbol('Phi', 14, 14)
    #Phi_A_xi = Phi.inv()
    Phi_A_xi = sympy.MatrixSymbol('Phi_A_xi', 14, 14)

    A_xus = A(x, u, sigma)
    B_xus = B(x, u, sigma)
    f_xu = f(x, u)

    z_t = -(A_xus * x)
    z_t += -(B_xus * u)

    #print((sigma * f_xu).shape)
    #mul_flat = sympy.Matrix(Phi_A_xi* B_xus).reshape(14 * 3, 1)
    mul_ab = Phi_A_xi * B_xus
    res_x = sigma * f_xu
    #    res_phi = sympy.Matrix(A_xus* Phi)
    #    res_b = sympy.Matrix(mul_ab * alpha)
    #    res_c = sympy.Matrix(mul_ab * beta)
    #    res_s= sympy.Matrix(Phi_A_xi* f_xu)
    #    res_z = sympy.Matrix(Phi_A_xi* z_t)

    res_phi = (A_xus * Phi)
    res_b = (mul_ab * alpha)
    res_c = (mul_ab * beta)
    res_s = (Phi_A_xi * f_xu)
    res_z = (Phi_A_xi * z_t)

    #print(dV_dt)
    return (res_x, res_phi, res_b, res_c, res_s, res_z)
Ejemplo n.º 29
0
    tt = theano.tensor
    xt, yt, zt = [tt.scalar(name, 'floatX') for name in 'xyz']
    Xt, Yt, Zt = [tt.tensor('floatX', (False, False), name=n) for n in 'XYZ']
else:
    #bin/test will not execute any tests now
    disabled = True

import sympy as sy
from sympy import S
from sympy.abc import x, y, z, t
from sympy.printing.theanocode import (theano_code, dim_handling,
                                       theano_function)

# Default set of matrix symbols for testing - make square so we can both
# multiply and perform elementwise operations between them.
X, Y, Z = [sy.MatrixSymbol(n, 4, 4) for n in 'XYZ']

# For testing AppliedUndef
f_t = sy.Function('f')(t)


def theano_code_(expr, **kwargs):
    """ Wrapper for theano_code that uses a new, empty cache by default. """
    kwargs.setdefault('cache', {})
    with warns_deprecated_sympy():
        return theano_code(expr, **kwargs)


def theano_function_(inputs, outputs, **kwargs):
    """ Wrapper for theano_function that uses a new, empty cache by default. """
    kwargs.setdefault('cache', {})
Ejemplo n.º 30
0
# %%
eq_zrv_0 = sym.Eq(sym.Integral(f_h(t)*sym.exp(z_n*w_n*t)*sym.cos(t*w_n*sym.sqrt(1-z_n**2)), t))
eq_zrv_1 = eq_zrv_0.replace(sym.cos, sym.sin)
display(eq_zrv_0)
display(eq_zrv_1)

# %%
T = sym.symbols("T")
k_0, k_1 = sym.symbols("k_0, k_1")
eq_convolve_ref_disc = sym.Eq(f_p_star_r(m*T),T*sym.Sum(f_h(k*t)*f_p_r((m-k)*T), (k,k_0, k_1)))
display(eq_convolve_ref_disc)

# %%
f_m = sym.Function(r"\mathbf{m}")
d = sym.MatrixSymbol(r"\mathbf{d}", 1, 6)
eq_constraints_disc = sym.Eq(sym.Sum(f_m(k)*f_h(k*T), (k, k_0, k_1)), d, evaluate=False)
display(eq_constraints_disc)

# %%
eq_m_k = sym.Eq(f_m(k), sym.Matrix([
    1,
    k*T,
    k**2*T**2,
    k**3*T**3,
    sym.exp(z_n*w_n*k*T)*sym.cos(k*T*w_n*sym.sqrt(1-z_n**2)),
    sym.exp(z_n*w_n*k*T)*sym.cos(k*T*t*w_n*sym.sqrt(1-z_n**2))]),
    evaluate=False)
display(eq_m_k)

# %%