예제 #1
0
void BillboardSprite::draw(Vec3 v)
{
    v = quadrant_translate_position(current_camera_position, v);
    if (!point_fulstrum_test(v.x, v.y, v.z))
        return;

    Vec3 up = vec3_init(model_view_matrix[0]*this->scale,
                        model_view_matrix[4]*this->scale,
                        model_view_matrix[8]*this->scale);
    Vec3 right = vec3_init(model_view_matrix[1]*this->scale,
                           model_view_matrix[5]*this->scale,
                           model_view_matrix[9]*this->scale);

    float tx_min, tx_max, ty_min, ty_max;
    tx_min = (float)(this->texture_index%16)* (1.0f/16.0f);
    tx_max = tx_min + (1.0f/16.0f);
    ty_min = (float)(this->texture_index/16)* (1.0f/16.0f);
    ty_max = ty_min + (1.0f/16.0f);

    Vec3 p = vec3_sub(v, vec3_add(right, up));
    glTexCoord2f(tx_min,ty_max);
    glVertex3f(p.x, p.y, p.z);

    p = vec3_add(v, vec3_sub(up, right));
    glTexCoord2f(tx_max,ty_max);
    glVertex3f(p.x, p.y, p.z);

    p = vec3_add(v, vec3_add(up, right));
    glTexCoord2f(tx_max,ty_min);
    glVertex3f(p.x, p.y, p.z);

    p = vec3_add(v, vec3_sub(right, up));
    glTexCoord2f(tx_min,ty_min);
    glVertex3f(p.x, p.y, p.z);
}
예제 #2
0
bool hitscan_sprite_mobs(const Vec3& position, const Vec3& direction, float range,
                         SpriteMobID& id, float& distance, Vec3& collision_point)
{
    SpriteMobID nearest_mob = NULL_SPRITE_MOB;
    float nearest_distance = 100000.0f;
    Vec3 nearest_collision_point = vec3_init(0);
    const float range_sq = range * range;
    const Vec3 up = vec3_init(0, 0, 1);
    for (size_t i=0, j=0; i<sprite_mob_list->max && j<sprite_mob_list->count; i++)
    {   // TODO
        // do a line-plane intersection test against the mob, if its in frustum
        SpriteMob* m = sprite_mob_list->objects[i];
        if (m == NULL) continue;
        j++;

        Vec3 p = m->get_center();
        p = quadrant_translate_position(position, p);

        if (vec3_distance_squared(position, p) > range_sq)
            continue;

        float rad_sq = 10000.0f;
        Vec3 line_point = vec3_init(0);
        if (!sphere_line_distance(position, direction, p, line_point, rad_sq))
            continue;

        Vec3 forward = vec3_sub(position, p);
        forward.z = 0.0f;
        if (unlikely(vec3_length_squared(forward) == 0))
            continue;
        forward = vec3_normalize(forward);
        const Vec3 right = vec3_normalize(vec3_cross(forward, up));

        float d = 1000000.0f;
        float width = get_mob_width(m->type) * 0.5f;
        float height = get_mob_height(m->type) * 0.5f;
        if (!line_plane_intersection(position, direction, p, width, height,
                                     forward, right, up, d))
            continue;

        if (d >= nearest_distance)
            continue;

        nearest_distance = d;
        nearest_mob = m->id;
        nearest_collision_point = line_point;
    }

    id = nearest_mob;
    distance = nearest_distance;
    collision_point = translate_position(nearest_collision_point);
    return (nearest_mob != NULL_SPRITE_MOB);
}
예제 #3
0
 WorldHitscanResult() :
     type(HITSCAN_TARGET_NONE), distance(FAR_AWAY), collision_point(vec3_init(FAR_AWAY)),
     start_position(vec3_init(0)), direction(vec3_init(0, 0, 1)), range(128),
     block_hit(false), block_position(vec3i_init(0)),
     block_open_position(vec3i_init(0)), block_side(vec3i_init(0, 0, 1)),
     cube_type(ERROR_CUBE), block_distance(FAR_AWAY), voxel_hit(false),
     voxel_distance(FAR_AWAY), voxel_collision_point(vec3_init(0)),
     mech_hit(false), mech_id(NULL_MECH_ID), mech_distance(FAR_AWAY),
     sprite_mob_hit(false), sprite_mob_id(NULL_SPRITE_MOB),
     sprite_mob_entity_id(NULL_ENTITY), sprite_mob_entity_type(NULL_ENTITY_TYPE),
     sprite_mob_distance(FAR_AWAY), sprite_mob_collision_point(vec3_init(0))
 {}
예제 #4
0
 void start(const Vec3& position, const Vec3& direction, float range)
 {
     this->start_position = position;
     this->direction = direction;
     IF_ASSERT(vec3_length_squared(direction) == 0)
         this->direction = vec3_init(0, 0, 1);
     this->range = range;
 }
예제 #5
0
/* find the two endpoints of a line segment that are inside a given sphere
   http://stackoverflow.com/a/17499940 */
int sphere_line_segment_intersection(const union vec3 *v0, const union vec3 *v1, const union vec3 *center, double r, union vec3 *vo0, union vec3 *vo1)
{
	double cx = center->v.x;
	double cy = center->v.y;
	double cz = center->v.z;

	double px = v0->v.x;
	double py = v0->v.y;
	double pz = v0->v.z;

	double vx = v1->v.x - px;
	double vy = v1->v.y - py;
	double vz = v1->v.z - pz;

	double A = vx * vx + vy * vy + vz * vz;
	double B = 2.0 * (px * vx + py * vy + pz * vz - vx * cx - vy * cy - vz * cz);
	double C = px * px - 2 * px * cx + cx * cx + py * py - 2 * py * cy + cy * cy +
		pz * pz - 2 * pz * cz + cz * cz - r * r;
	double D = B * B - 4.0 * A * C;

	/* outside or tanget to sphere, no segment intersection */
	if (D <= 0)
		return -1;

	double t1 = (-B - sqrt(D)) / (2.0 * A);
	double t2 = (-B + sqrt(D)) / (2.0 * A);

	/* infinte line intersects but this segment doesn't */
	if ((t1 < 0 && t2 < 0) || (t1 > 1 && t2 > 1))
		return -1;

	if (t1 < 0)
		vec3_copy(vo0, v0);
	else if (t1 > 1)
		vec3_copy(vo1, v1);
	else
		vec3_init(vo0, v0->v.x * (1.0 - t1) + t1 * v1->v.x, v0->v.y * (1.0 - t1) + t1 * v1->v.y, v0->v.z * (1.0 - t1) + t1 * v1->v.z);

	if (t2 < 0)
		vec3_copy(vo0, v0);
	else if (t2 > 1)
		vec3_copy(vo1, v1);
	else
		vec3_init(vo1, v0->v.x * (1.0 - t2) + t2 * v1->v.x, v0->v.y * (1.0 - t2) + t2 * v1->v.y, v0->v.z * (1.0 - t2) + t2 * v1->v.z);
	return 2;
}
예제 #6
0
void vec3_attach(PyObject * m)
{
	vec3_init();

	if (PyType_Ready(&vec3_type) < 0)
		return; // TODO error?

	Py_INCREF(&vec3_type);
	PyModule_AddObject(m, "vec3", (PyObject *)&vec3_type);
}
예제 #7
0
Vertex * vertex_init_float(GLfloat x, GLfloat y,
						   GLfloat z)
{
	Vertex *vertex = NULL;
	vertex = malloc(sizeof(Vertex));
	if (vertex)
	{
		vertex->size = 3;
		vertex->pos = vec3_init(x, y, z);
	}

	return(vertex);
}
예제 #8
0
/* This function implements the mandel box fractal.
 * It's quite expensive and not used anywhere yet.
 */
void vol_draw_mandel_box (double xc, double yc, double zc, double xsc, double ysc, double zsc, double s, double r, double f, int it, double cfact)
{

  int x, y, z;
  for (z = 0; z < DRAW_CTX.size; z++)
    for (y = 0; y < DRAW_CTX.size; y++)
      for (x = 0; x < DRAW_CTX.size; x++)
        {
          vec3_init (c, x, y, z);
          vec3_s_div (c, DRAW_CTX.size);
          c[0] += xsc;
          c[1] += ysc;
          c[2] += zsc;
          vec3_s_mul (c, cfact);

          c[0] += -xsc * cfact;
          c[1] += -ysc * cfact;
          c[2] += -zsc * cfact;
          c[0] += xc;
          c[1] += yc;
          c[2] += zc;

          int i;
          int escape = 0;
          vec3_init (v, 0, 0, 0);
          for (i = 0; i < it; i++)
            {
              double d = _vol_draw_mandel_box_equation (v, s, r, f, c);
              if (d > 1024)
                {
                  escape = 1;
                  break;
                }
            }

          if (!escape)
            vol_draw_op (x, y, z, 0.5);
        }
}
예제 #9
0
void vol_draw_fill_sphere (float x, float y, float z, float size)
{
  float cntr = size / 2;
  vec3_init (center, x + cntr, y + cntr, z + cntr);

  float j, k, l;
  for (j = 0; j < size; j++)
    for (k = 0; k < size; k++)
      for (l = 0; l < size; l++)
        {
          vec3_init (cur, x + j, y + k, z + l);
          vec3_sub (cur, center);
          float vlen = vec3_len (cur);
          float diff = vlen - (cntr - (size / 10));

          if (diff < 0)
            {
              double sphere_val = (-diff / cntr);
              vol_draw_op (x + j, y + k, z + l, sphere_val);
            }
        }
}
예제 #10
0
void RailTrailEffect::draw_quad(const Vec3& p, float r, float theta, float phi) // quadratic radius
{   // with no rotation modifications, it faces upwards
    static const float tx_min = 0.0f;
    static const float tx_max = 1.0f;
    static const float ty_min = 0.0f;
    static const float ty_max = 1.0f;

    Vec3 bl, tl, tr, br;
    bl = tl = tr = br = vec3_init(0.0f);

    // FIXME: MOVE SHIT LIKE THIS TO BE CALC'ED ONLY ONCE then applied to all the interpolated points
    // rotate the y & z (pitch) .... prob need to reverse/mirror the y
    float radian = phi*PI;

    // first setup up-facing quad with correct PITCH
    // bottom edge
    bl.y = br.y = -r*sinf(radian);
    bl.z = br.z = r*cosf(radian);
    //printf("bl.y: %8.2f  bl.z: %8.2f \n", bl.y, bl.z);

    // top edge
    tl.y = tr.y = r*sinf(radian);
    tl.z = tr.z = -r*cosf(radian);
    //printf("tl.y: %8.2f  tl.z: %8.2f \n", tl.y, tl.z);

    // sides
    bl.x = tl.x = -r;
    br.x = tr.x = r;

    // do YAW
    bl = vec3_euler_rotation(bl, theta-0.5f, 0, 0);
    tl = vec3_euler_rotation(tl, theta-0.5f, 0, 0);
    tr = vec3_euler_rotation(tr, theta-0.5f, 0, 0);
    br = vec3_euler_rotation(br, theta-0.5f, 0, 0);

    // translate to world space
    bl = vec3_add(p, bl);
    tl = vec3_add(p, tl);
    tr = vec3_add(p, tr);
    br = vec3_add(p, br);

    // draw
    glTexCoord2f(tx_max, ty_max);
    glVertex3f(bl.x, bl.y, bl.z);  // Bottom left
    glTexCoord2f(tx_min, ty_max);
    glVertex3f(tl.x, tl.y, tl.z);  // Top left
    glTexCoord2f(tx_min, ty_min);
    glVertex3f(tr.x, tr.y, tr.z);  // Top right
    glTexCoord2f(tx_max, ty_min);
    glVertex3f(br.x, br.y, br.z);  // Bottom right
}
예제 #11
0
Transform * transform_init()
{
	Transform *transform = NULL;
	transform = malloc(sizeof(Transform));

	if (transform)
	{
		// Methods
		transform->get_transformation = get_transformation;

		transform->set_scaling = set_scaling;
		transform->set_scaling_vec3 = set_scaling_vec3;

		transform->set_rotation = set_rotation;
		transform->set_rotation_vec3 = set_rotation_vec3;

		transform->set_translation = set_translation;
		transform->set_translation_vec3 = set_translation_vec3;	

		// Attributes
		transform->translation = NULL;
		transform->translation = vec3_init(0.0f,
										   0.0f,
										   0.0f);
		transform->rotation = NULL;
		transform->rotation = vec3_init(0.0f,
										0.0f,
										0.0f);

		transform->scaling = NULL;
		transform->scaling = vec3_init(1.0f,
										1.0f,
										1.0f);
	}
	return(transform);
}
예제 #12
0
/* for a plane defined by n=normal, return a u and v vector that is on that plane and perpendictular */
void plane_vector_u_and_v_from_normal(union vec3 *u, union vec3 *v, const union vec3 *n)
{
	union vec3 basis = { { 1, 0, 0 } };

	/* find a vector we can use for our basis to define v */
	float dot = vec3_dot(n, &basis);
	if (fabs(dot) >= 1.0 - ZERO_TOLERANCE) {
		/* if forward is parallel, we can use up */
		vec3_init(&basis, 0, 1, 0);
	}

	/* find the right vector from our basis and the normal */
	vec3_cross(v, &basis, n);
	vec3_normalize_self(v);

	/* now the final forward vector is perpendicular n and v */
	vec3_cross(u, n, v);
	vec3_normalize_self(u);
}
예제 #13
0
static union vec3 compute_triangle_normal(struct triangle *t)
{
	union vec3 v1, v2, cross;

	v1.v.x = t->v[1]->x - t->v[0]->x;
	v1.v.y = t->v[1]->y - t->v[0]->y;
	v1.v.z = t->v[1]->z - t->v[0]->z;

	v2.v.x = t->v[2]->x - t->v[1]->x;
	v2.v.y = t->v[2]->y - t->v[1]->y;
	v2.v.z = t->v[2]->z - t->v[1]->z;

	vec3_cross(&cross, &v1, &v2);
	vec3_normalize_self(&cross);

	/* make sure we always have a valid normal */
	if (isnan(cross.v.x) || isnan(cross.v.y) || isnan(cross.v.z))
		vec3_init(&cross, 0, 1, 0);

	return cross;
}
예제 #14
0
void explode_landmine_damage_players(const Vec3i& position)
{
    printf("Landmine damaging players at "); vec3i_print(position);
    Vec3 p = vec3_add(vec3_init(position), vec3_init(0.5f));
    Hitscan::against_agents(p, vec3_init(0, 0, 1), 2);
}
예제 #15
0
    // check upper bounds
    // we should not be calling this function out of bounds, so assert
    IF_ASSERT(!is_boxed_position(position)) return;

    // constant for helping walk the axes
    static const int dir[2] = { -1, 1 };
    static const int sides[3][3] = {
        { 1, 0, 0 },
        { 0, 1, 0 },
        { 0, 0, 1 }};
    //static const struct Vec3 vsides[3] = {
        //vec3_init(1, 0, 0),
        //vec3_init(0, 1, 0),
        //vec3_init(0, 0, 1)};

    const struct Vec3 fp = vec3_add(vec3_init(position), vec3_init(0.5f));

    // notify clients
    Particle::plasmagen_explode_StoC msg;
    msg.position = fp;
    msg.broadcast();

    // boundaries for the explosion, which can be contained by iron and bedrock
    int bounds[3][2];
    CubeType cubes[3][2];
    for (int i=0; i<3; i++)
    for (int j=0; j<2; j++)
    {
        bounds[i][j] = PLASMAGEN_BLOCK_BLAST_RADIUS;
        cubes[i][j] = EMPTY_CUBE;
    }
예제 #16
0
namespace Voxels
{

void VoxelModel::set_skeleton_root(const Vec3& position, float theta)
{   //set offset and rotation
    IF_ASSERT(!this->skeleton_inited) return;
    Vec3 angles = vec3_init(theta, 0.0f, 0.0f);
    vox_skeleton_world_matrix[0] = affine_euler_rotation_and_translation(position, angles);
    vox_skeleton_world_matrix[0].c = translate_position(vox_skeleton_world_matrix[0].c);
}

void VoxelModel::set_skeleton_root(float *data)
{
    IF_ASSERT(!this->skeleton_inited) return;
    vox_skeleton_world_matrix[0] = affine_euler_rotation_and_translation(
        vec3_init(data[0], data[1], data[2]),
        vec3_init(data[3], data[4], data[5]));
    vox_skeleton_world_matrix[0].c = translate_position(vox_skeleton_world_matrix[0].c);
}

int VoxelModel::get_parent_node_index(int part)
{
    IF_ASSERT(part < 0 || part >= this->n_parts) return -1;
    VoxPart* vp = vox_dat->vox_part[part];
    if (vp == NULL) return -1;
    return vp->skeleton_parent_matrix;
}

void VoxelModel::set_node_rotation_by_part(int part, float theta, float phi, float rho)
{
    IF_ASSERT(!this->skeleton_inited) return;
예제 #17
0
void play_animation(AnimationType animation_type, struct Vec3 position)
{
    class AnimationProperty* data = get_animation_data(animation_type);
    IF_ASSERT(data == NULL) return;
    IF_ASSERT(data->callback == NULL || data->metadata == NULL) return;

    switch (data->metadata_type)
    {
        case AnimDataNone:
            break;

        case AnimDataSimple:
            ((class AnimationStateMetadata*)data->metadata)->position = position;
            ((class AnimationStateMetadata*)data->metadata)->velocity = vec3_scalar_mult(vec3_init(1), data->momentum);
            break;

        default:
            GS_ASSERT(false);
            break;
    }

    data->callback(animation_type, data->metadata);
}
예제 #18
0
void main_init(int argc, char *argv[])
{
   bool override_hw = false;
   if (argc > 1)
   {
      if (strcmp(argv[1], "calibrate") == 0)
         calibrate = true;
      else
         override_hw = true;
   }

   /* init data structures: */
   memset(&pos_in, 0, sizeof(pos_in_t));
   vec3_init(&pos_in.acc);

   /* init SCL subsystem: */
   syslog(LOG_INFO, "initializing signaling and communication link (SCL)");
   if (scl_init("pilot") != 0)
   {
      syslog(LOG_CRIT, "could not init scl module");
      die();
   }
   
   /* init params subsystem: */
   syslog(LOG_INFO, "initializing opcd interface");
   opcd_params_init("pilot.", 1);
   
   /* initialize logger: */
   syslog(LOG_INFO, "opening logger");
   if (logger_open() != 0)
   {
      syslog(LOG_CRIT, "could not open logger");
      die();
   }
   syslog(LOG_CRIT, "logger opened");
   
   LOG(LL_INFO, "initializing platform");
   if (arcade_quad_init(&platform, override_hw) < 0)
   {
      LOG(LL_ERROR, "could not initialize platform");
      die();
   }
   acc_mag_cal_init();
   cmc_init();
 
   const size_t array_len = sizeof(float) * platform.n_motors;
   setpoints = malloc(array_len);
   ASSERT_NOT_NULL(setpoints);
   memset(setpoints, 0, array_len);
   rpm_square = malloc(array_len);
   ASSERT_NOT_NULL(rpm_square);
   memset(rpm_square, 0, array_len);

   LOG(LL_INFO, "initializing model/controller");
   pos_init();
   ne_speed_ctrl_init(REALTIME_PERIOD);
   att_ctrl_init();
   yaw_ctrl_init();
   u_ctrl_init();
   u_speed_init();
   navi_init();

   LOG(LL_INFO, "initializing command interface");
   cmd_init();

   motors_state_init();
   blackbox_init();

   /* init flight logic: */
   flight_logic_init();

   /* init calibration data: */
   cal_init(&gyro_cal, 3, 1000);

   cal_ahrs_init();
   flight_state_init(50, 150, 4.0);
   
   piid_init(REALTIME_PERIOD);

   interval_init(&gyro_move_interval);
   gps_data_init(&gps_data);

   mag_decl_init();
   cal_init(&rc_cal, 3, 500);

   tsfloat_t acc_fg;
   opcd_param_t params[] =
   {
      {"acc_fg", &acc_fg},
      OPCD_PARAMS_END
   };
   opcd_params_apply("main.", params);
   filter1_lp_init(&lp_filter, tsfloat_get(&acc_fg), 0.06, 3);

   cm_init();
   mon_init();
   LOG(LL_INFO, "entering main loop");
}
예제 #19
0
void main_step(const float dt,
               const marg_data_t *marg_data,
               const gps_data_t *gps_data,
               const float ultra,
               const float baro,
               const float voltage,
               const float current,
               const float channels[MAX_CHANNELS],
               const uint16_t sensor_status,
               const bool override_hw)
{
   vec2_t ne_pos_err, ne_speed_sp, ne_spd_err;
   vec2_init(&ne_pos_err);
   vec2_init(&ne_speed_sp);
   vec2_init(&ne_spd_err);
   vec3_t mag_normal;
   vec3_init(&mag_normal);

   float u_pos_err = 0.0f;
   float u_spd_err = 0.0f;
   
   int bb_rate;
   if (calibrate)
   {
      ONCE(LOG(LL_INFO, "publishing calibration data; actuators disabled"));
      bb_rate = 20;
      goto out;
   }
   else
      bb_rate = 1;
   
   pos_in.dt = dt;
   pos_in.ultra_u = ultra;
   pos_in.baro_u = baro;
   
   if (!(sensor_status & MARG_VALID))
   {
      marg_err += 1;
      if (marg_err > 500)
      {
         /* we are in serious trouble */
         memset(setpoints, 0, sizeof(float) * platform.n_motors);
         platform_write_motors(setpoints);
         die();
      }
      goto out;
   }
   marg_err = 0;
   
   float cal_channels[MAX_CHANNELS];
   memcpy(cal_channels, channels, sizeof(cal_channels));
   if (sensor_status & RC_VALID)
   {
      /* apply calibration if remote control input is valid: */
      float cal_data[3] = {channels[CH_PITCH], channels[CH_ROLL], channels[CH_YAW]};
      cal_sample_apply(&rc_cal, cal_data);
      cal_channels[CH_PITCH] = cal_data[0];
      cal_channels[CH_ROLL] = cal_data[1];
      cal_channels[CH_YAW] = cal_data[2];
   }

   /* perform gyro calibration: */
   marg_data_t cal_marg_data;
   marg_data_init(&cal_marg_data);
   marg_data_copy(&cal_marg_data, marg_data);
   if (cal_sample_apply(&gyro_cal, cal_marg_data.gyro.ve) == 0 && gyro_moved(&marg_data->gyro))
   {
      if (interval_measure(&gyro_move_interval) > 1.0)
         LOG(LL_ERROR, "gyro moved during calibration, retrying");
      cal_reset(&gyro_cal);
   }

   /* update relative gps position, if we have a fix: */
   float mag_decl;
   if (sensor_status & GPS_VALID)
   {
      gps_util_update(&gps_rel_data, gps_data);
      pos_in.pos_n = gps_rel_data.dn;
      pos_in.pos_e = gps_rel_data.de;
      pos_in.speed_n = gps_rel_data.speed_n;
      pos_in.speed_e = gps_rel_data.speed_e;
      ONCE(gps_start_set(gps_data));
      mag_decl = mag_decl_get();
   }
   else
   {
      pos_in.pos_n = 0.0f;   
      pos_in.pos_e = 0.0f; 
      pos_in.speed_n = 0.0f;
      pos_in.speed_e = 0.0f;
      mag_decl = 0.0f;
   }

   /* apply acc/mag calibration: */
   acc_mag_cal_apply(&cal_marg_data.acc, &cal_marg_data.mag);
   vec_copy(&mag_normal, &cal_marg_data.mag);

   /* apply current magnetometer compensation: */
   cmc_apply(&cal_marg_data.mag, current);
   //printf("%f %f %f %f\n", current, cal_marg_data.mag.x, cal_marg_data.mag.y, cal_marg_data.mag.z);
   
   /* determine flight state: */
   bool flying = flight_state_update(&cal_marg_data.acc.ve[0]);
   if (!flying && pos_in.ultra_u == 7.0)
      pos_in.ultra_u = 0.2;
   
   /* compute orientation estimate: */
   euler_t euler;
   int ahrs_state = cal_ahrs_update(&euler, &cal_marg_data, mag_decl, dt);
   if (ahrs_state < 0 || !cal_complete(&gyro_cal))
      goto out;
   ONCE(init = 1; LOG(LL_DEBUG, "system initialized; orientation = yaw: %f pitch: %f roll: %f", euler.yaw, euler.pitch, euler.roll));

   /* rotate local ACC measurements into global NEU reference frame: */
   vec3_t world_acc;
   vec3_init(&world_acc);
   body_to_neu(&world_acc, &euler, &cal_marg_data.acc);
   
   /* center global ACC readings: */
   filter1_run(&lp_filter, &world_acc.ve[0], &acc_vec[0]);
   FOR_N(i, 3)
      pos_in.acc.ve[i] = world_acc.ve[i] - acc_vec[i];

   /* compute next 3d position estimate using Kalman filters: */
   pos_t pos_est;
   vec2_init(&pos_est.ne_pos);
   vec2_init(&pos_est.ne_speed);
   pos_update(&pos_est, &pos_in);

   /* execute flight logic (sets cm_x parameters used below): */
   bool hard_off = false;
   bool motors_enabled = flight_logic_run(&hard_off, sensor_status, flying, cal_channels, euler.yaw, &pos_est.ne_pos, pos_est.baro_u.pos, pos_est.ultra_u.pos, platform.max_thrust_n, platform.mass_kg, dt);
   
   /* execute up position/speed controller(s): */
   float a_u = 0.0f;
   if (cm_u_is_pos())
   {
      if (cm_u_is_baro_pos())
         a_u = u_ctrl_step(&u_pos_err, cm_u_sp(), pos_est.baro_u.pos, pos_est.baro_u.speed, dt);
      else /* ultra pos */
         a_u = u_ctrl_step(&u_pos_err, cm_u_sp(), pos_est.ultra_u.pos, pos_est.ultra_u.speed, dt);
   }
   else if (cm_u_is_spd())
      a_u = u_speed_step(&u_spd_err, cm_u_sp(), pos_est.baro_u.speed, dt);
   else
      a_u = cm_u_sp();
   
   /* execute north/east navigation and/or read speed vector input: */
   if (cm_att_is_gps_pos())
   {
      vec2_t pos_sp;
      vec2_init(&pos_sp);
      cm_att_sp(&pos_sp);
      navi_run(&ne_speed_sp, &ne_pos_err, &pos_sp, &pos_est.ne_pos, dt);
   }
   else if (cm_att_is_gps_spd())
      cm_att_sp(&ne_speed_sp);

   /* execute north/east speed controller: */
   vec2_t a_ne;
   vec2_init(&a_ne);
   ne_speed_ctrl_run(&a_ne, &ne_spd_err, &ne_speed_sp, dt, &pos_est.ne_speed);
   
   vec3_t a_neu;
   vec3_set(&a_neu, a_ne.x, a_ne.y, a_u);
   vec3_t f_neu;
   vec3_init(&f_neu);
   vec_scalar_mul(&f_neu, &a_neu, platform.mass_kg); /* f[i] = a[i] * m, makes ctrl device-independent */
   
   float hover_force = platform.mass_kg * 9.81f;
   f_neu.z += hover_force;

   /* execute NEU forces optimizer: */
   float thrust;
   vec2_t pr_pos_sp;
   vec2_init(&pr_pos_sp);
   att_thrust_calc(&pr_pos_sp, &thrust, &f_neu, euler.yaw, platform.max_thrust_n, 0);

   /* execute direct attitude angle control, if requested: */
   if (cm_att_is_angles())
      cm_att_sp(&pr_pos_sp);

   /* execute attitude angles controller: */
   vec2_t att_err;
   vec2_init(&att_err);
   vec2_t pr_spd;
   vec2_set(&pr_spd, -cal_marg_data.gyro.y, cal_marg_data.gyro.x);

   vec2_t pr_pos, pr_pos_ctrl;
   vec2_set(&pr_pos, -euler.pitch, euler.roll);
   vec2_init(&pr_pos_ctrl);
   att_ctrl_step(&pr_pos_ctrl, &att_err, dt, &pr_pos, &pr_spd, &pr_pos_sp);
 
   float piid_sp[3] = {0.0f, 0.0f, 0.0f};
   piid_sp[PIID_PITCH] = pr_pos_ctrl.ve[0];
   piid_sp[PIID_ROLL] = pr_pos_ctrl.ve[1];
 
   /* execute direct attitude rate control, if requested:*/
   if (cm_att_is_rates())
   {
      vec2_t rates_sp;
      vec2_init(&rates_sp);
      cm_att_sp(&rates_sp);
      piid_sp[PIID_PITCH] = rates_sp.ve[0];
      piid_sp[PIID_ROLL] = rates_sp.ve[1];
   }

   /* execute yaw position controller: */
   float yaw_speed_sp, yaw_err;
   if (cm_yaw_is_pos())
      yaw_speed_sp = yaw_ctrl_step(&yaw_err, cm_yaw_sp(), euler.yaw, cal_marg_data.gyro.z, dt);
   else
      yaw_speed_sp = cm_yaw_sp(); /* direct yaw speed control */
   //yaw_speed_sp = yaw_ctrl_step(&yaw_err, 0.0, euler.yaw, cal_marg_data.gyro.z, dt);
   piid_sp[PIID_YAW] = yaw_speed_sp;

   /* execute stabilizing PIID controller: */
   f_local_t f_local = {{thrust, 0.0f, 0.0f, 0.0f}};
   float piid_gyros[3] = {cal_marg_data.gyro.x, -cal_marg_data.gyro.y, cal_marg_data.gyro.z};
   piid_run(&f_local.ve[1], piid_gyros, piid_sp, dt);

   /* computate rpm ^ 2 out of the desired forces: */
   inv_coupling_calc(rpm_square, f_local.ve);

   /* compute motor setpoints out of rpm ^ 2: */
   piid_int_enable(platform_ac_calc(setpoints, motors_spinning(), voltage, rpm_square));

   /* enables motors, if flight logic requests it: */
   motors_state_update(flying, dt, motors_enabled);
   
   /* reset controllers, if motors are not controllable: */
   if (!motors_controllable())
   {
      navi_reset();
      ne_speed_ctrl_reset();
      u_ctrl_reset();
      att_ctrl_reset();
      piid_reset();
   }
 
   /* handle special cases for motor setpoints: */
   if (motors_starting())
      FOR_N(i, platform.n_motors) setpoints[i] = platform.ac.min;
   if (hard_off || motors_stopping())
      FOR_N(i, platform.n_motors) setpoints[i] = platform.ac.off_val;
   
   
   printf("%f %f %f\n", rad2deg(euler.pitch), rad2deg(euler.roll), rad2deg(euler.yaw));
   /* write motors: */
   if (!override_hw)
   {
      //platform_write_motors(setpoints);
   }

   /* set monitoring data: */
   mon_data_set(ne_pos_err.x, ne_pos_err.y, u_pos_err, yaw_err);

out:
   EVERY_N_TIMES(bb_rate, blackbox_record(dt, marg_data, gps_data, ultra, baro, voltage, current, channels, sensor_status, /* sensor inputs */
                          &ne_pos_err, u_pos_err, /* position errors */
                          &ne_spd_err, u_spd_err /* speed errors */,
                          &mag_normal));
}
예제 #20
0
void RailTrailEffect::tick()
{
    if (Options::animation_level <= 0) return;

    static const float span = 0.5f; // space between particle layers
    static const float spin_span = PI / 8;

    const float dist = vec3_distance(this->end, this->start);
    const float step = span / (dist);
    Vec3 fwd = vec3_sub(this->end, this->start);
    //this->start = vec3_add(this->start, vec3_scalar_mult(vec3_normalize(this->start), 0.005f));

    // RIGHT SETTINGS WOULD LOOK GOOD ON MOB IMPACTS ---> voxel_explode(this->end, /*min*/ 4, /*max*/ 14, /*size*/ 0.2f, /*force*/ 0.1f, COLOR_GREEN);

    float theta, phi;
    vec3_to_angles(fwd, &theta, &phi);

    float curr_spin = 0.0f;
    //float curr_spin = (PI/16) * this->ttl;
    for (float fl=0.0f; fl<=1.0f; fl+=step)
    {
        Vec3 curr = vec3_interpolate(this->start, this->end, fl);
        //float r = 0.17f; // quadratic radius
        float r = 0.08f; // quadratic radius

        Vec3 spiral = vec3_init(
                          r * cosf(curr_spin),
                          0,
                          r * sinf(curr_spin)
                      );
        Vec3 spiral2 = vec3_init(
                           r * cosf(curr_spin + PI),
                           0,
                           r * sinf(curr_spin + PI)
                       );

        spiral = vec3_euler_rotation(spiral, theta-0.5f, 0, phi-0.5f);
        spiral2 = vec3_euler_rotation(spiral2, theta-0.5f, 0, phi-0.5f);
        spiral = vec3_add(curr, spiral);
        spiral2 = vec3_add(curr, spiral2);

        spiral = translate_position(spiral);
        spiral2 = translate_position(spiral2);

        //float anim_scale = float(Options::animation_level)/3.0f;
        //n = anim_scale*float(n);
        Particle::Shrapnel *s;

        s = Particle::create_shrapnel(spiral, /*vel*/ vec3_init(0,0,0));
        if (s == NULL) return;

        //s->ttl = randrange(8, 15);
        //s->scale = 0.1f;
        //s->texture_index = 54;
        s->ttl = randrange(2, 4);
        //s->ttl = 2;
        s->scale = 0.06f;
        s->texture_index = 22;

        s = Particle::create_shrapnel(spiral2, /*vel*/ vec3_init(0,0,0));
        if (s == NULL) return;

        //s->ttl = randrange(8, 15);
        //s->scale = 0.1f;
        s->texture_index = 54;
        s->ttl = randrange(2, 4);
        //s->ttl = 2;
        s->scale = 0.06f;
        s->texture_index = 22;

        //draw_quad(curr, span, theta, phi);
        curr_spin += spin_span;
        if (curr_spin >= PI*2)
            curr_spin = 0.0f;
    }
}