Exemple #1
0
// input : degree
void stablize_mode(float ef_desire_roll, float ef_desire_pitch, float bf_desire_yaw_rate, float hover){
	float d_q[4], e_q[4];
	float bf_desire_rate[3];
	float norm, angle_error;
	float phi = ef_desire_roll*0.008726646;  // degree to radian
	float theta = ef_desire_pitch*0.008726646;

	float c_phi = cosf(phi); float s_phi = sinf(phi);
	float c_theta = cosf(theta); float s_theta = sinf(theta);

	d_q[0] =  c_phi*c_theta;
	d_q[1] =  s_phi*c_theta;
	d_q[2] =  c_phi*s_theta;
	d_q[3] = -s_phi*s_theta;

	e_q[0] = d_q[0]*_quaternion[0] + d_q[1]*_quaternion[1] + d_q[2]*_quaternion[2] + d_q[3]*_quaternion[3];
	e_q[1] = d_q[1]*_quaternion[0] - d_q[0]*_quaternion[1] + d_q[3]*_quaternion[2] - d_q[2]*_quaternion[3];
	e_q[2] = d_q[2]*_quaternion[0] - d_q[3]*_quaternion[1] - d_q[0]*_quaternion[2] + d_q[1]*_quaternion[3];
	e_q[3] = d_q[3]*_quaternion[0] + d_q[2]*_quaternion[1] - d_q[1]*_quaternion[2] - d_q[0]*_quaternion[3];

	norm = sqrtf(e_q[0]*e_q[0]+e_q[1]*e_q[1]+e_q[2]*e_q[2]+e_q[3]*e_q[3]);
	e_q[0] /= norm;

	if(e_q[0] < 0){
		e_q[0] *= -1;
		e_q[1] *= -1;
		e_q[2] *= -1;
		e_q[3] *= -1;
	}

	angle_error = acosf(e_q[0])*180.0/3.14159;

	if(_prev_angle_error - angle_error > 3){
		angle_error = _prev_angle_error - 3;
	}else if(angle_error - _prev_angle_error > 3){
		angle_error = _prev_angle_error + 3;
	}

	_prev_angle_error = angle_error;

	norm = sqrtf(e_q[1]*e_q[1]+e_q[2]*e_q[2]+e_q[3]*e_q[3]);
	bf_desire_rate[0] = e_q[1]/norm;
	bf_desire_rate[1] = e_q[2]/norm;
	bf_desire_rate[2] = e_q[3]/norm;


	angle_error = stable_Kp*angle_error*2; // Kp*2*angle*180/3.14
	angle_error = constraints(angle_error,0.0, 45.0);  // max 20deg/s

	bf_desire_rate[0] *= angle_error;
	bf_desire_rate[1] *= angle_error;
	//bf_desire_rate[2] *= angle_error;
	bf_desire_rate[2] *= bf_desire_yaw_rate;

	rate_controller(bf_desire_rate, 0, hover);
}
/* Called from main context */
static void adjust_rates(struct userdata *u) {
    size_t buffer;
    uint32_t old_rate, base_rate, new_rate;
    int32_t latency_difference;
    pa_usec_t current_buffer_latency, snapshot_delay, current_source_sink_latency, current_latency, latency_at_optimum_rate;
    pa_usec_t final_latency;

    pa_assert(u);
    pa_assert_ctl_context();

    /* Rates and latencies*/
    old_rate = u->sink_input->sample_spec.rate;
    base_rate = u->source_output->sample_spec.rate;

    buffer = u->latency_snapshot.sink_input_buffer;
    if (u->latency_snapshot.recv_counter <= u->latency_snapshot.send_counter)
        buffer += (size_t) (u->latency_snapshot.send_counter - u->latency_snapshot.recv_counter);
    else
        buffer = PA_CLIP_SUB(buffer, (size_t) (u->latency_snapshot.recv_counter - u->latency_snapshot.send_counter));

    current_buffer_latency = pa_bytes_to_usec(buffer, &u->sink_input->sample_spec);
    snapshot_delay = u->latency_snapshot.source_timestamp - u->latency_snapshot.sink_timestamp;
    current_source_sink_latency = u->latency_snapshot.sink_latency + u->latency_snapshot.source_latency - snapshot_delay;

    /* Current latency */
    current_latency = current_source_sink_latency + current_buffer_latency;

    /* Latency at base rate */
    latency_at_optimum_rate = current_source_sink_latency + current_buffer_latency * old_rate / base_rate;

    final_latency = u->latency;
    latency_difference = (int32_t)((int64_t)latency_at_optimum_rate - final_latency);

    pa_log_debug("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms",
                (double) u->latency_snapshot.sink_latency / PA_USEC_PER_MSEC,
                (double) current_buffer_latency / PA_USEC_PER_MSEC,
                (double) u->latency_snapshot.source_latency / PA_USEC_PER_MSEC,
                (double) current_latency / PA_USEC_PER_MSEC);

    pa_log_debug("Loopback latency at base rate is %0.2f ms", (double)latency_at_optimum_rate / PA_USEC_PER_MSEC);

    /* Calculate new rate */
    new_rate = rate_controller(base_rate, u->adjust_time, latency_difference);

    /* Set rate */
    pa_sink_input_set_rate(u->sink_input, new_rate);
    pa_log_debug("[%s] Updated sampling rate to %lu Hz.", u->sink_input->sink->name, (unsigned long) new_rate);
}