Esempio n. 1
0
void
bot_trans_set_from_velocities(BotTrans *dest, const double angular_rate[3],
    const double velocity[3], double dt)
{
  //see Frazolli notes, Aircraft Stability and Control, lecture 2, page 15
  if (dt == 0) {
    bot_trans_set_identity(dest);
    return;
  }

  double identity_quat[4] = { 1, 0, 0, 0 };
  double norm_angular_rate = bot_vector_magnitude_3d(angular_rate);

  if (norm_angular_rate == 0) {
    double delta[3];
    memcpy(delta, velocity, 3 * sizeof(double));
    bot_vector_scale_3d(delta, dt);
    bot_trans_set_from_quat_trans(dest, identity_quat, delta);
    return;
  }

  //"exponential of a twist: R=exp(skew(omega*t));
  //rescale vel, omega, t so ||omega||=1
  //trans =  (I-R)*(omega \cross v) + (omega \dot v) *omega* t
  //                term2                       term3
  // R*(omega \cross v)
  //     term1
  //rescale
  double t = dt * norm_angular_rate;
  double omega[3], vel[3];
  memcpy(omega, angular_rate, 3 * sizeof(double));
  memcpy(vel, velocity, 3 * sizeof(double));
  bot_vector_scale_3d(omega, 1.0/norm_angular_rate);
  bot_vector_scale_3d(vel, 1.0/norm_angular_rate);

  //compute R (quat in our case)
  bot_angle_axis_to_quat(t, omega, dest->rot_quat);

  //cross and dot products
  double omega_cross_vel[3];
  bot_vector_cross_3d(omega, vel, omega_cross_vel);
  double omega_dot_vel = bot_vector_dot_3d(omega, vel);


  double term1[3];
  double term2[3];
  double term3[3];

  //(I-R)*(omega \cross v) = term2
  memcpy(term1, omega_cross_vel, 3 * sizeof(double));
  bot_quat_rotate(dest->rot_quat, term1);
  bot_vector_subtract_3d(omega_cross_vel, term1, term2);

  //(omega \dot v) *omega* t
  memcpy(term3, omega, 3 * sizeof(double));
  bot_vector_scale_3d(term3, omega_dot_vel * t);

  bot_vector_add_3d(term2, term3, dest->trans_vec);
}
Esempio n. 2
0
void 
bot_angle_axis_to_roll_pitch_yaw (double theta, const double axis[3],
        double rpy[3])
{
    double q[4];
    bot_angle_axis_to_quat (theta, axis, q);
    bot_quat_to_roll_pitch_yaw (q, rpy);
}
Esempio n. 3
0
/* ================ general ============== */
int bot_param_get_quat(BotParam *param, const char *name, double quat[4])
{
  char key[2048];
  sprintf(key, "%s.quat", name);
  if (bot_param_has_key(param, key)) {
    int sz = bot_param_get_double_array(param, key, quat, 4);
    assert(sz == 4);
    return 0;
  }

  sprintf(key, "%s.rpy", name);
  if (bot_param_has_key(param, key)) {
    double rpy[3];
    int sz = bot_param_get_double_array(param, key, rpy, 3);
    assert(sz == 3);
    for (int i = 0; i < 3; i++)
      rpy[i] = bot_to_radians (rpy[i]);
    bot_roll_pitch_yaw_to_quat(rpy, quat);
    return 0;
  }

  sprintf(key, "%s.rodrigues", name);
  if (bot_param_has_key(param, key)) {
    double rod[3];
    int sz = bot_param_get_double_array(param, key, rod, 3);
    assert(sz == 3);
    bot_rodrigues_to_quat(rod, quat);
    return 0;
  }

  sprintf(key, "%s.angleaxis", name);
  if (bot_param_has_key(param, key)) {
    double aa[4];
    int sz = bot_param_get_double_array(param, key, aa, 4);
    assert(sz == 4);

    bot_angle_axis_to_quat(aa[0], aa + 1, quat);
    return 0;
  }
  return -1;
}
Esempio n. 4
0
static void update_follow_target(BotViewHandler *vhandler, const double pos[3], const double quat[4])
{
    BotDefaultViewHandler *dvh = (BotDefaultViewHandler*) vhandler->user;

    if (dvh->have_last && (vhandler->follow_mode & BOT_FOLLOW_YAW)) {

        // compute the vectors from the vehicle to the lookat and eye
        // point and then project them given the new position of the car/
        double v2eye[3];
        bot_vector_subtract_3d(dvh->lastpos, dvh->eye, v2eye);
        double v2look[3];
        bot_vector_subtract_3d(dvh->lastpos, dvh->lookat, v2look);

        double vxy[3] = { 1, 0, 0 };
        bot_quat_rotate (quat, vxy);
        vxy[2] = 0;

        // where was the car pointing last time?
        double oxy[3] = { 1, 0, 0 };
        bot_quat_rotate (dvh->lastquat, oxy);
        oxy[2] = 0;
        double theta = bot_vector_angle_2d (oxy, vxy);

        double zaxis[3] = { 0, 0, 1 };
        double q[4];
        bot_angle_axis_to_quat (theta, zaxis, q);

        bot_quat_rotate(q, v2look);
        bot_vector_subtract_3d(pos, v2look, dvh->lookat);

        bot_quat_rotate(q, v2eye);
        bot_vector_subtract_3d(pos, v2eye, dvh->eye);
        bot_quat_rotate (q, dvh->up);

        // the above algorithm "builds in" a BOT_FOLLOW_POS behavior.

    } else if (dvh->have_last && (vhandler->follow_mode & BOT_FOLLOW_POS)) {

        double dpos[3];
        for (int i = 0; i < 3; i++)
            dpos[i] = pos[i] - dvh->lastpos[i];

        for (int i = 0; i < 3; i++) {
            dvh->eye[i] += dpos[i];
            dvh->lookat[i] += dpos[i];
        }
    } else {

        // when the follow target moves, we want rotations to still behave
        // correctly. Rotations use the lookat point as the center of rotation,
        // so adjust the lookat point so that it is on the same plane as the
        // follow target.

        double look_dir[3];
        bot_vector_subtract_3d(dvh->lookat, dvh->eye, look_dir);
        bot_vector_normalize_3d(look_dir);

        if (fabs(look_dir[2]) > 0.0001) {
            double dist = (dvh->lastpos[2] - dvh->lookat[2]) / look_dir[2];
            for (int i = 0; i < 3; i++)
                dvh->lookat[i] += dist * look_dir[i];
        }
    }

    look_at_changed(dvh);

    dvh->have_last = 1;
    memcpy(dvh->lastpos, pos, 3 * sizeof(double));
    memcpy(dvh->lastquat, quat, 4 * sizeof(double));
}
Esempio n. 5
0
static int mouse_motion  (BotViewer *viewer, BotEventHandler *ehandler,
                          const double ray_start[3], const double ray_dir[3], const GdkEventMotion *event)
{
    BotDefaultViewHandler *dvh = (BotDefaultViewHandler*) ehandler->user;

    double dy = event->y - dvh->last_mouse_y;
    double dx = event->x - dvh->last_mouse_x;
    double look[3];
    bot_vector_subtract_3d (dvh->lookat, dvh->eye, look);

    if (event->state & GDK_BUTTON3_MASK) {
        double xy_len = bot_vector_magnitude_2d (look);
        double init_elevation = atan2 (look[2], xy_len);

        double left[3];
        bot_vector_cross_3d (dvh->up, look, left);
        bot_vector_normalize_3d (left);

        double delevation = -dy * 0.005;
        if (delevation + init_elevation < -M_PI/2) {
            delevation = -M_PI/2 - init_elevation;
        }
        if (delevation + init_elevation > M_PI/8) {
            delevation = M_PI/8 - init_elevation;
        }

        double q[4];
        bot_angle_axis_to_quat(-delevation, left, q);
        double newlook[3];
        memcpy (newlook, look, sizeof (newlook));
        bot_quat_rotate (q, newlook);

        double dazimuth = -dx * 0.01;
        double zaxis[] = { 0, 0, 1 };
        bot_angle_axis_to_quat (dazimuth, zaxis, q);
        bot_quat_rotate (q, newlook);
        bot_quat_rotate (q, left);

        bot_vector_subtract_3d (dvh->lookat, newlook, dvh->eye);
        bot_vector_cross_3d (newlook, left, dvh->up);
        look_at_changed(dvh);
    }
    else if (event->state & GDK_BUTTON2_MASK) {
        double init_eye_dist = bot_vector_magnitude_3d (look);

        double ded = pow (10, dy * 0.01);
        double eye_dist = init_eye_dist * ded;
        if (eye_dist > EYE_MAX_DIST)
            eye_dist = EYE_MAX_DIST;
        else if (eye_dist < EYE_MIN_DIST)
            eye_dist = EYE_MIN_DIST;

        double le[3];
        memcpy (le, look, sizeof (le));
        bot_vector_normalize_3d (le);
        bot_vector_scale_3d (le, eye_dist);

        bot_vector_subtract_3d (dvh->lookat, le, dvh->eye);
        look_at_changed(dvh);
    }
    else if (event->state & GDK_BUTTON1_MASK) {

        double dx = event->x - dvh->last_mouse_x;
        double dy = event->y - dvh->last_mouse_y;

        window_space_pan(dvh, dvh->manipulation_point, dx, dy, 1);
    }
    dvh->last_mouse_x = event->x;
    dvh->last_mouse_y = event->y;

    bot_viewer_request_redraw(viewer);
    return 1;
}
Esempio n. 6
0
int
bot_quaternion_test()
{
#define FAIL_TEST { fprintf(stderr, "bot_quaternion_test failed at line %d\n", \
        __LINE__); return 0; }

    fprintf(stderr, "running quaternion test\n");
    double theta = 0;
    double rvec[] = { 0, 0, 1 };
    double q[4];
    double rpy[3];
    double roll, pitch, yaw;

    bot_angle_axis_to_quat(theta, rvec, q);

    if (! qeq (q, 1, 0, 0, 0)) FAIL_TEST;

    bot_quat_to_roll_pitch_yaw (q, rpy);
    roll = rpy[0]; pitch = rpy[1]; yaw = rpy[2];

    if (! rpyeq (roll,pitch,yaw, 0,0,0)) FAIL_TEST;

    // quat_from_angle_axis
    theta = M_PI;
    bot_angle_axis_to_quat(theta, rvec, q);

    fprintf(stderr,"<%.3f, %.3f, %.3f, %.3f>\n", q[0], q[1], q[2], q[3]);
    if (! qeq (q, 0, 0, 0, 1)) FAIL_TEST;

    // bot_quat_to_angle_axis
    bot_quat_to_angle_axis (q, &theta, rvec);
    if (!feq (theta, M_PI)) FAIL_TEST;
    if (!feq(rvec[0], 0) || !feq(rvec[1], 0) || !feq(rvec[2], 1)) FAIL_TEST;

    bot_quat_to_roll_pitch_yaw (q, rpy);

    if (! rpyeq (roll,pitch,yaw, 0,0,M_PI)) FAIL_TEST;

    double q2[4];
    double q3[4];
    double axis1[] = { 0, 1, 0 };
    double axis2[] = { 0, 0, 1 };
    bot_angle_axis_to_quat (M_PI/2, axis1, q);
    bot_angle_axis_to_quat (M_PI/2, axis2, q);
    bot_quat_mult (q3, q, q2);
    rvec[0] = 0; rvec[1] = 0; rvec[2] = 1;
    bot_quat_rotate (q, rvec);
    fprintf(stderr, "by q: [ %.2f, %.2f, %.2f ]\n", rvec[0], rvec[1], rvec[2]);
    rvec[0] = 0; rvec[1] = 0; rvec[2] = 1;
    bot_quat_rotate (q2, rvec);
    fprintf(stderr, "by q2: [ %.2f, %.2f, %.2f ]\n", rvec[0], rvec[1], rvec[2]);
    rvec[0] = 0; rvec[1] = 0; rvec[2] = 1;
    bot_quat_rotate (q3, rvec);
    fprintf(stderr, "by q*q2: [ %.2f, %.2f, %.2f ]\n", 
            rvec[0], rvec[1], rvec[2]);
    rvec[0] = 0; rvec[1] = 0; rvec[2] = 1;
    bot_quat_mult (q3, q2, q);
    bot_quat_rotate (q3, rvec);
    fprintf(stderr, "by q2*q: [ %.2f, %.2f, %.2f ]\n", 
            rvec[0], rvec[1], rvec[2]);

    // TODO

#undef FAIL_TEST

    fprintf(stderr, "bot_quaternion_test complete\n");
    return 1;
}