示例#1
0
文件: state.c 项目: opalmirror/av3-fc
/**
 * Recieve data from the IMU, and integrate to a state estimation
 */
void state_receive_imu(const char *ID, uint8_t *timestamp, uint16_t len, void *buf) {
    const uint64_t now = from_psas_time(timestamp);
    ADIS16405Data *imu = buf;

    // Convert raw IMU data to MKS/degrees unit system
    const double accel = ADIS_GLSB * (int16_t) ntohs(imu->acc_x);
    const double roll_rate = ADIS_RLSB * (int16_t) ntohs(imu->gyro_x);

    if (!has_launched && fabs(accel) > 40) {
        has_launched = true;
        launch_time = now;
    }

    if (last_time == 0)
        last_time = now;
    if (has_launched) {
        const double dt = (now - last_time) / 1.0e9;
        // Integrate sensors
        current_state.time = (now - launch_time) / 1.0e9;
        current_state.acc_up = accel - 9.81; // Subtract gravity (Remember, IMU is upside down)
        current_state.vel_up += current_state.acc_up*dt;
        current_state.altitude += current_state.vel_up*dt;
        current_state.roll_rate = -roll_rate; //Sensor coordinate frame is rotated 180
        current_state.roll_angle += roll_rate*dt; //This is wrong (negative) but we don't care, nothing uses it.
    }

    // Send data
    state_send_message("VSTE", timestamp, sizeof(StateData), &current_state);

    last_time = now;
}
示例#2
0
/* Moves the game agent in its current direction, assuming the
   given amount of time has passed.  Returns 1 if the move was
   successful, 0 otherwise. */
int agent_move(GameAgent *ga, Uint32 time)
{
	int last_block_x, last_block_y, next_block_x, next_block_y;
	int last_block_x2, last_block_y2, next_block_x2, next_block_y2;

	int block_changed;
	FixedVector v1, v2, ga_loc2;

	/* Scale the normalized movement vector relative to the game agent's speed. */
	v1 = fixed_vector_scale(&ga->curr_move, ga->speed);

	/* Now scale that vector to the amount of time that's passed. */
	v1 = fixed_vector_scale(&v1, FIXED_SET_INT(time));

	/* Now add that delta vector to the game agent's current position to
	   get their predicted new position. */
	v1 = fixed_vector_add(&ga->loc, &v1);

	/* If we've crossed a block boundary and we're not on the
	   first pixel of the block boundary, put us on it. */

	/* Block coordinates of the game agent's "last" (actually current) position,
	   relative to the top-right of the game agent. */
	last_block_x = GET_BLOCK_FIXED(ga->loc.x);
	last_block_y = GET_BLOCK_FIXED(ga->loc.y);	

	/* Block coordinates of the game agent's "next" (predicted) position, relative
	   to the top-left of the game agent. */
	next_block_x = GET_BLOCK_FIXED(v1.x);
	next_block_y = GET_BLOCK_FIXED(v1.y);

	/* Now calculate the same info for the bottom-right corner of the game agent. 
	   This is used if the player is moving left or up. */

	ga_loc2 = fixed_vector_add(&ga->loc, &ga->physical_dim);
	v2 = fixed_vector_add(&v1, &ga->physical_dim);

	last_block_x2 = GET_BLOCK_FIXED(ga_loc2.x);
	last_block_y2 = GET_BLOCK_FIXED(ga_loc2.y);	

	next_block_x2 = GET_BLOCK_FIXED(v2.x);
	next_block_y2 = GET_BLOCK_FIXED(v2.y);

	/* block_changed is a boolean that tells us whether the game agent
	   has crossed a block boundary or not. */
	block_changed = 0;
	/* Figure out if we've passed a block boundary.  If we have, we may need
	   to change our next position if it's not exactly on a block boundary.  If
	   this happens, v1 will be changed. */
	if (last_block_x < next_block_x) {
		/* If we're moving to the right (our next block is more than our last one)... */
		block_changed = 1;
		if (FIXED_GET_INT(v1.x) > next_block_x * BLOCK_SIZE)
			v1.x = FIXED_SET_INT(next_block_x * BLOCK_SIZE);
	} else if (last_block_x2 > next_block_x2) {
		/* If we're moving to the left... */
		block_changed = 1;
		if (FIXED_GET_INT(v1.x) < next_block_x2 * BLOCK_SIZE)
			v1.x = FIXED_SET_INT(next_block_x2 * BLOCK_SIZE);
	} else if (last_block_y < next_block_y) {
		/* If we're moving down... */
		block_changed = 1;
		if (FIXED_GET_INT(v1.y) > next_block_y * BLOCK_SIZE)
			v1.y = FIXED_SET_INT(next_block_y * BLOCK_SIZE);
	} else if (last_block_y2 > next_block_y2) {
		/* If we're moving up... */
		block_changed = 1;
		if (FIXED_GET_INT(v1.y) < next_block_y2 * BLOCK_SIZE)
			v1.y = FIXED_SET_INT(next_block_y2 * BLOCK_SIZE);
	}

	if (agent_is_position_viable(ga, &v1)) {
			ga->last_loc = ga->loc;
			ga->loc = v1;
			/* If we passed into a new block, alert the game agent's state machine (FSM). */
			if (block_changed) {
				if (FIXED_GET_INT(ga->loc.x) == (BOARD_WIDTH+2)*BLOCK_SIZE) {
					/* If we've gone through a tunnel to the right, wrap around
					   to the left side of the screen. */
					fixed_vector_set(&ga->loc, -1*BLOCK_SIZE, FIXED_GET_INT(ga->loc.y));
					ga->last_loc = ga->loc;
				} else if (FIXED_GET_INT(ga->loc.x) == -1*BLOCK_SIZE) {
					/* If we've gone through a tunnel to the left, wrap around
					   to the right side of the screen. */
					fixed_vector_set(&ga->loc, (BOARD_WIDTH+2)*BLOCK_SIZE, FIXED_GET_INT(ga->loc.y));
					ga->last_loc = ga->loc;
				}
				state_send_message(GAME_AGENT_MSG_BLOCK_CHANGE, 0, ga->state.state_id, 0, 0);
			}
			return 1;
	} else return 0;
}