void stabilisation_copter_send_outputs(stabilisation_copter_t* stabilisation_copter, const mavlink_stream_t* mavlink_stream, mavlink_message_t* msg)
{
	aero_attitude_t attitude_yaw_inverse;
	quat_t q_rot,qtmp;
	
	attitude_yaw_inverse = coord_conventions_quat_to_aero(stabilisation_copter->ahrs->qe);
	attitude_yaw_inverse.rpy[0] = 0.0f;
	attitude_yaw_inverse.rpy[1] = 0.0f;
	attitude_yaw_inverse.rpy[2] = attitude_yaw_inverse.rpy[2];

	q_rot = coord_conventions_quaternion_from_aero(attitude_yaw_inverse);
	qtmp=quaternions_create_from_vector(stabilisation_copter->stabiliser_stack.velocity_stabiliser.output.rpy);
	quat_t rpy_local;
	quaternions_rotate_vector(quaternions_inverse(q_rot), qtmp.v, rpy_local.v);
	
	mavlink_msg_debug_vect_pack(	mavlink_stream->sysid,
									mavlink_stream->compid,
									msg,
									"OutVel",
									time_keeper_get_micros(),
									-rpy_local.v[X] * 1000,
									rpy_local.v[Y] * 1000,
									stabilisation_copter->stabiliser_stack.velocity_stabiliser.output.rpy[YAW] * 1000);
	mavlink_stream_send(mavlink_stream,msg);
	
	mavlink_msg_debug_vect_pack(	mavlink_stream->sysid,
									mavlink_stream->compid,
									msg,
									"OutAtt",
									time_keeper_get_micros(),
									stabilisation_copter->stabiliser_stack.attitude_stabiliser.output.rpy[ROLL] * 1000,
									stabilisation_copter->stabiliser_stack.attitude_stabiliser.output.rpy[PITCH] * 1000,
									stabilisation_copter->stabiliser_stack.attitude_stabiliser.output.rpy[YAW] * 1000);
	mavlink_stream_send(mavlink_stream,msg);
	
	mavlink_msg_debug_vect_pack(	mavlink_stream->sysid,
									mavlink_stream->compid,
									msg,
									"OutRate",
									time_keeper_get_micros(),
									stabilisation_copter->stabiliser_stack.rate_stabiliser.output.rpy[ROLL] * 1000,
									stabilisation_copter->stabiliser_stack.rate_stabiliser.output.rpy[PITCH] * 1000,
									stabilisation_copter->stabiliser_stack.rate_stabiliser.output.rpy[YAW] * 1000);
	mavlink_stream_send(mavlink_stream,msg);
}
Beispiel #2
0
static void acoustic_set_waypoint_command(audio_t* audio_data)
{
    quat_t qtmp1, qtmp2;
    float target_vect_global[3];
    float speed_gain;

    qtmp1 = quaternions_create_from_vector(target_vect);
    qtmp2 = quaternions_local_to_global(attitude_previous, qtmp1);

    //unit vector to target
    target_vect_global[0] = qtmp2.v[0];
    target_vect_global[1] = qtmp2.v[1];
    target_vect_global[2] = qtmp2.v[2];

    //distance to target on ground (computed from the hight of robot)
    //speed_gain = f_abs(position_previous[2]/target_vect_global[2]);
    //speed_gain = f_abs(1.0-target_vect_global[2])*15.0

    speed_gain = maths_f_abs(quick_trig_acos(target_vect_global[2])) * 20.0f;

    if (speed_gain > 20.0f)
    {
        speed_gain = 20.0f;
    }
    else if (speed_gain < 3.0f)
    {
        speed_gain = 0.0f;
    }

    audio_data->waypoint_handler->waypoint_hold_coordinates.pos[0] = speed_gain * target_vect_global[0] + position_previous[0];
    audio_data->waypoint_handler->waypoint_hold_coordinates.pos[1] = speed_gain * target_vect_global[1] + position_previous[1];
    //centralData->controls_nav.theading=audio_data->azimuth*PI/180;

    if (speed_gain > 3.0f)
    {
        audio_data->waypoint_handler->waypoint_hold_coordinates.heading = atan2(target_vect_global[Y], target_vect_global[X]);
    }
}
Beispiel #3
0
void qfilter_update(qfilter_t *qf)
{
	static uint32_t convergence_update_count = 0;
	float  omc[3], omc_mag[3] , tmp[3], snorm, norm, s_acc_norm, acc_norm, s_mag_norm, mag_norm;
	quat_t qed, qtmp1, up, up_bf;
	quat_t mag_global, mag_corrected_local;
	quat_t front_vec_global = 
	{
		.s = 0.0f, 
		.v = {1.0f, 0.0f, 0.0f}
	};

	float kp 	 = qf->kp;
	float kp_mag = qf->kp_mag;
	float ki 	 = qf->ki;
	float ki_mag = qf->ki_mag;

	// Update time in us
	float now_us 	= time_keeper_get_micros();
	
	// Delta t in seconds
	float dt     = 1e-6 * (float)(now_us - qf->ahrs->last_update);
	
	// Write to ahrs structure
	qf->ahrs->dt 		  = dt;
	qf->ahrs->last_update = now_us;

	
	// up_bf = qe^-1 *(0,0,0,-1) * qe
	up.s = 0; up.v[X] = UPVECTOR_X; up.v[Y] = UPVECTOR_Y; up.v[Z] = UPVECTOR_Z;
	up_bf = quaternions_global_to_local(qf->ahrs->qe, up);
	
	// calculate norm of acceleration vector
	s_acc_norm = qf->imu->scaled_accelero.data[X] * qf->imu->scaled_accelero.data[X] + qf->imu->scaled_accelero.data[Y] * qf->imu->scaled_accelero.data[Y] + qf->imu->scaled_accelero.data[Z] * qf->imu->scaled_accelero.data[Z];
	if ( (s_acc_norm > 0.7f * 0.7f) && (s_acc_norm < 1.3f * 1.3f) ) 
	{
		// approximate square root by running 2 iterations of newton method
		acc_norm = maths_fast_sqrt(s_acc_norm);

		tmp[X] = qf->imu->scaled_accelero.data[X] / acc_norm;
		tmp[Y] = qf->imu->scaled_accelero.data[Y] / acc_norm;
		tmp[Z] = qf->imu->scaled_accelero.data[Z] / acc_norm;

		// omc = a x up_bf.v
		CROSS(tmp, up_bf.v, omc);
	}
	else
	{
		omc[X] = 0;
		omc[Y] = 0;
		omc[Z] = 0;
	}

	// Heading computation
	// transfer 
	qtmp1 = quaternions_create_from_vector(qf->imu->scaled_compass.data); 
	mag_global = quaternions_local_to_global(qf->ahrs->qe, qtmp1);
	
	// calculate norm of compass vector
	//s_mag_norm = SQR(mag_global.v[X]) + SQR(mag_global.v[Y]) + SQR(mag_global.v[Z]);
	s_mag_norm = SQR(mag_global.v[X]) + SQR(mag_global.v[Y]);

	if ( (s_mag_norm > 0.004f * 0.004f) && (s_mag_norm < 1.8f * 1.8f) ) 
	{
		mag_norm = maths_fast_sqrt(s_mag_norm);

		mag_global.v[X] /= mag_norm;
		mag_global.v[Y] /= mag_norm;
		mag_global.v[Z] = 0.0f;   // set z component in global frame to 0

		// transfer magneto vector back to body frame 
		qf->ahrs->north_vec = quaternions_global_to_local(qf->ahrs->qe, front_vec_global);		
		
		mag_corrected_local = quaternions_global_to_local(qf->ahrs->qe, mag_global);		
		
		// omc = a x up_bf.v
		CROSS(mag_corrected_local.v, qf->ahrs->north_vec.v,  omc_mag);
		
	}
	else
	{
		omc_mag[X] = 0;
		omc_mag[Y] = 0;
		omc_mag[Z] = 0;
	}


	// get error correction gains depending on mode
	switch (qf->ahrs->internal_state)
	{
		case AHRS_UNLEVELED:
			kp = qf->kp * 10.0f;
			kp_mag = qf->kp_mag * 10.0f;
			
			ki = 0.5f * qf->ki;
			ki_mag = 0.5f * qf->ki_mag;
			
			convergence_update_count += 1;
			if( convergence_update_count > 2000 )
			{
				convergence_update_count = 0;
				qf->ahrs->internal_state = AHRS_CONVERGING;
				print_util_dbg_print("End of AHRS attitude initialization.\r\n");
			}
			break;
			
		case AHRS_CONVERGING:
			kp = qf->kp;
			kp_mag = qf->kp_mag;
			
			ki = qf->ki * 3.0f;
			ki_mag = qf->ki_mag * 3.0f;
			
			convergence_update_count += 1;
			if( convergence_update_count > 2000 )
			{
				convergence_update_count = 0;
				qf->ahrs->internal_state = AHRS_READY;
				print_util_dbg_print("End of AHRS leveling.\r\n");
			}
			break;

		case AHRS_READY:
			kp = qf->kp;
			kp_mag = qf->kp_mag;
			ki = qf->ki;
			ki_mag = qf->ki_mag;
			break;
	}

	// apply error correction with appropriate gains for accelerometer and compass

	for (uint8_t i = 0; i < 3; i++)
	{
		qtmp1.v[i] = 0.5f * (qf->imu->scaled_gyro.data[i] + kp * omc[i] + kp_mag * omc_mag[i]);
	}
	qtmp1.s = 0;

	// apply step rotation with corrections
	qed = quaternions_multiply(qf->ahrs->qe,qtmp1);

	// TODO: correct this formulas! 
	qf->ahrs->qe.s = qf->ahrs->qe.s + qed.s * dt;
	qf->ahrs->qe.v[X] += qed.v[X] * dt;
	qf->ahrs->qe.v[Y] += qed.v[Y] * dt;
	qf->ahrs->qe.v[Z] += qed.v[Z] * dt;

	snorm = qf->ahrs->qe.s * qf->ahrs->qe.s + qf->ahrs->qe.v[X] * qf->ahrs->qe.v[X] + qf->ahrs->qe.v[Y] * qf->ahrs->qe.v[Y] + qf->ahrs->qe.v[Z] * qf->ahrs->qe.v[Z];
	if (snorm < 0.0001f)
	{
		norm = 0.01f;
	}
	else
	{
		// approximate square root by running 2 iterations of newton method
		norm = maths_fast_sqrt(snorm);
	}
	qf->ahrs->qe.s /= norm;
	qf->ahrs->qe.v[X] /= norm;
	qf->ahrs->qe.v[Y] /= norm;
	qf->ahrs->qe.v[Z] /= norm;

	// bias estimate update
	qf->imu->calib_gyro.bias[X] += - dt * ki * omc[X] / qf->imu->calib_gyro.scale_factor[X];
	qf->imu->calib_gyro.bias[Y] += - dt * ki * omc[Y] / qf->imu->calib_gyro.scale_factor[Y];
	qf->imu->calib_gyro.bias[Z] += - dt * ki * omc[Z] / qf->imu->calib_gyro.scale_factor[Z];
	
	qf->imu->calib_gyro.bias[X] += - dt * ki_mag * omc_mag[X] / qf->imu->calib_compass.scale_factor[X];
	qf->imu->calib_gyro.bias[Y] += - dt * ki_mag * omc_mag[Y] / qf->imu->calib_compass.scale_factor[Y];
	qf->imu->calib_gyro.bias[Z] += - dt * ki_mag * omc_mag[Z] / qf->imu->calib_compass.scale_factor[Z];
	
	// set up-vector (bodyframe) in attitude
	qf->ahrs->up_vec.v[X] = up_bf.v[X];
	qf->ahrs->up_vec.v[Y] = up_bf.v[Y];
	qf->ahrs->up_vec.v[Z] = up_bf.v[Z];

	// Update linear acceleration
	qf->ahrs->linear_acc[X] = 9.81f * (qf->imu->scaled_accelero.data[X] - qf->ahrs->up_vec.v[X]) ;							// TODO: review this line!
	qf->ahrs->linear_acc[Y] = 9.81f * (qf->imu->scaled_accelero.data[Y] - qf->ahrs->up_vec.v[Y]) ;							// TODO: review this line!
	qf->ahrs->linear_acc[Z] = 9.81f * (qf->imu->scaled_accelero.data[Z] - qf->ahrs->up_vec.v[Z]) ;							// TODO: review this line!

	//update angular_speed.
	qf->ahrs->angular_speed[X] = qf->imu->scaled_gyro.data[X];
	qf->ahrs->angular_speed[Y] = qf->imu->scaled_gyro.data[Y];
	qf->ahrs->angular_speed[Z] = qf->imu->scaled_gyro.data[Z];
}
void stabilisation_copter_cascade_stabilise(stabilisation_copter_t* stabilisation_copter)
{
	float rpyt_errors[4];
	control_command_t input;
	int32_t i;
	quat_t qtmp, q_rot;
	aero_attitude_t attitude_yaw_inverse;
	
	// set the controller input
	input= *stabilisation_copter->controls;
	switch (stabilisation_copter->controls->control_mode) 
	{
	case VELOCITY_COMMAND_MODE:
		
		attitude_yaw_inverse = coord_conventions_quat_to_aero(stabilisation_copter->ahrs->qe);
		attitude_yaw_inverse.rpy[0] = 0.0f;
		attitude_yaw_inverse.rpy[1] = 0.0f;
		attitude_yaw_inverse.rpy[2] = attitude_yaw_inverse.rpy[2];
		
		//qtmp=quaternions_create_from_vector(input.tvel);
		//quat_t input_global = quaternions_local_to_global(stabilisation_copter->ahrs->qe, qtmp);
		
		q_rot = coord_conventions_quaternion_from_aero(attitude_yaw_inverse);
		
		quat_t input_global;
		quaternions_rotate_vector(q_rot, input.tvel, input_global.v);
		
		input.tvel[X] = input_global.v[X];
		input.tvel[Y] = input_global.v[Y];
		input.tvel[Z] = input_global.v[Z];
		
		rpyt_errors[X] = input.tvel[X] - stabilisation_copter->pos_est->vel[X];
		rpyt_errors[Y] = input.tvel[Y] - stabilisation_copter->pos_est->vel[Y];
		rpyt_errors[3] = -(input.tvel[Z] - stabilisation_copter->pos_est->vel[Z]);
		
		if (stabilisation_copter->controls->yaw_mode == YAW_COORDINATED) 
		{
			float rel_heading_coordinated;
			if ((maths_f_abs(stabilisation_copter->pos_est->vel_bf[X])<0.001f)&&(maths_f_abs(stabilisation_copter->pos_est->vel_bf[Y])<0.001f))
			{
				rel_heading_coordinated = 0.0f;
			}
			else
			{
				rel_heading_coordinated = atan2(stabilisation_copter->pos_est->vel_bf[Y], stabilisation_copter->pos_est->vel_bf[X]);
			}
			
			float w = 0.5f * (maths_sigmoid(vectors_norm(stabilisation_copter->pos_est->vel_bf)-stabilisation_copter->stabiliser_stack.yaw_coordination_velocity) + 1.0f);
			input.rpy[YAW] = (1.0f - w) * input.rpy[YAW] + w * rel_heading_coordinated;
		}

		rpyt_errors[YAW]= input.rpy[YAW];
		
		// run PID update on all velocity controllers
		stabilisation_run(&stabilisation_copter->stabiliser_stack.velocity_stabiliser, stabilisation_copter->imu->dt, rpyt_errors);
		
		//velocity_stabiliser.output.thrust = maths_f_min(velocity_stabiliser.output.thrust,stabilisation_param.controls->thrust);
		stabilisation_copter->stabiliser_stack.velocity_stabiliser.output.thrust += stabilisation_copter->thrust_hover_point;
		stabilisation_copter->stabiliser_stack.velocity_stabiliser.output.theading = input.theading;
		input = stabilisation_copter->stabiliser_stack.velocity_stabiliser.output;
		
		qtmp=quaternions_create_from_vector(stabilisation_copter->stabiliser_stack.velocity_stabiliser.output.rpy);
		//quat_t rpy_local = quaternions_global_to_local(stabilisation_copter->ahrs->qe, qtmp);
		
		quat_t rpy_local;
		quaternions_rotate_vector(quaternions_inverse(q_rot), qtmp.v, rpy_local.v);
		
		input.rpy[ROLL] = rpy_local.v[Y];
		input.rpy[PITCH] = -rpy_local.v[X];
		//input.thrust = stabilisation_copter->controls->tvel[Z];
		
	// -- no break here  - we want to run the lower level modes as well! -- 
	
	case ATTITUDE_COMMAND_MODE:
		// run absolute attitude_filter controller
		rpyt_errors[0]= input.rpy[0] - ( - stabilisation_copter->ahrs->up_vec.v[1] ); 
		rpyt_errors[1]= input.rpy[1] - stabilisation_copter->ahrs->up_vec.v[0];
		
		if ((stabilisation_copter->controls->yaw_mode == YAW_ABSOLUTE) ) 
		{
			rpyt_errors[2] =maths_calc_smaller_angle(input.theading- stabilisation_copter->pos_est->local_position.heading);
		}
		else
		{ // relative yaw
			rpyt_errors[2]= input.rpy[2];
		}
		
		rpyt_errors[3]= input.thrust;       // no feedback for thrust at this level
		
		// run PID update on all attitude_filter controllers
		stabilisation_run(&stabilisation_copter->stabiliser_stack.attitude_stabiliser, stabilisation_copter->imu->dt, rpyt_errors);
		
		// use output of attitude_filter controller to set rate setpoints for rate controller 
		input = stabilisation_copter->stabiliser_stack.attitude_stabiliser.output;
	
	// -- no break here  - we want to run the lower level modes as well! -- 
	
	case RATE_COMMAND_MODE: // this level is always run
		// get rate measurements from IMU (filtered angular rates)
		for (i=0; i<3; i++)
		{
			rpyt_errors[i]= input.rpy[i]- stabilisation_copter->ahrs->angular_speed[i];
		}
		rpyt_errors[3] = input.thrust ;  // no feedback for thrust at this level
		
		// run PID update on all rate controllers
		stabilisation_run(&stabilisation_copter->stabiliser_stack.rate_stabiliser, stabilisation_copter->imu->dt, rpyt_errors);
	}
	
	// mix to servo outputs depending on configuration
	if( stabilisation_copter->motor_layout == QUADCOPTER_MOTOR_LAYOUT_DIAG )
	{
		stabilisation_copter_mix_to_servos_diag_quad(&stabilisation_copter->stabiliser_stack.rate_stabiliser.output, stabilisation_copter->servos);
	}
	else if( stabilisation_copter->motor_layout == QUADCOPTER_MOTOR_LAYOUT_CROSS )
	{
		stabilisation_copter_mix_to_servos_cross_quad(&stabilisation_copter->stabiliser_stack.rate_stabiliser.output, stabilisation_copter->servos);

	}
}