void PlanetViewController::move(vec3d &oldp, vec3d &p)
{
    oldp = oldp.normalize();
    p = p.normalize();
    double oldlat = safe_asin(oldp.z);
    double oldlon = atan2(oldp.y, oldp.x);
    double lat = safe_asin(p.z);
    double lon = atan2(p.y, p.x);
    x0 -= lon - oldlon;
    y0 -= lat - oldlat;
    y0 = max(-M_PI / 2.0, min(M_PI / 2.0, y0));
}
// set_linear_servo_out - sets swashplate servo output to be linear
float AP_MotorsHeli_Swash::get_linear_servo_output(float input) const
{

    input = constrain_float(input, -1.0f, 1.0f);

    //servo output is calculated by normalizing input to 50 deg arm rotation as full input for a linear throw
    return safe_asin(0.766044f * input) * 1.145916;

}
Example #3
0
// calculate euler angles from a rotation matrix
// this is based on http://gentlenav.googlecode.com/files/EulerAngles.pdf
void Matrix3f_to_euler(Matrix3f *matrix3,float *roll, float *pitch, float *yaw){
    if (pitch != NULL) {
        *pitch = -safe_asin(matrix3->c.x);
    }
    if (roll != NULL) {
        *roll = atan2f(matrix3->c.y, matrix3->c.z);
    }
    if (yaw != NULL) {
        *yaw = atan2f(matrix3->b.x, matrix3->a.x);
    }
}
void Matrix3<T>::to_euler(float *roll, float *pitch, float *yaw) const
{
    if (pitch != NULL) {
        *pitch = -safe_asin(c.x);
    }
    if (roll != NULL) {
        *roll = atan2f(c.y, c.z);
    }
    if (yaw != NULL) {
        *yaw = atan2f(b.x, a.x);
    }
}
//static void get_of_angles(int16_t roll_in, int16_t pitch_in, int16_t &roll_out, int16_t &pitch_out)
void AC_OpticalFlowPX4::get_of_angles(float vx_in,float vy_in, int16_t &pitch_out, int16_t &roll_out, float G_Dt)
{
    Vector3f vel_of_error,angles_target;
	
	
    vx_in = constrain_float(vx_in, -200, 200);//max velocity
    vy_in = constrain_float(vy_in, -200, 200);

	//filtering of
	vel_of_x=vel_of_x*_alpha_of+((1-_alpha_of)*(flow_comp_m_x*100));//en cm
    vel_of_y=vel_of_y*_alpha_of+((1-_alpha_of)*(flow_comp_m_y*100));//en cm
	
	pos_of_x+=vel_of_x*G_Dt;
    pos_of_y+=vel_of_y*G_Dt;
	
	vel_of_error.x = (vx_in - vel_of_x);
    vel_of_error.y =(vy_in - vel_of_y);
  
    angles_target.x = _pid_optflow.get_pid(vel_of_error.x, G_Dt);
    angles_target.y = _pid_optflow.get_pid(vel_of_error.y, G_Dt);

    target_roll = constrain_float(safe_asin(angles_target.y)*(18000/M_PI), -1500, 1500);
    target_pitch = constrain_float(safe_asin(-angles_target.x)*(18000/M_PI),-1500, 1500);

    
    //targetsAng_XY.x=roll_target;
    //targetsAng_XY.y=pitch_target;
  
  tmr_of_rst=hal.scheduler->millis();
  if(tmr_of_rst>=tmr_of_rst_n+40000){
    pos_of_x=0;
    pos_of_y=0;
    tmr_of_rst_n=hal.scheduler->millis();
  }
  
  
    roll_out = (int16_t)target_roll;
    pitch_out = (int16_t)target_pitch;
}
void PlanetViewController::moveForward(double distance)
{
    double co = cos(x0); // x0 = longitude
    double so = sin(x0);
    double ca = cos(y0); // y0 = latitude
    double sa = sin(y0);
    vec3d po = vec3d(co*ca, so*ca, sa) * R;
    vec3d px = vec3d(-so, co, 0.0);
    vec3d py = vec3d(-co*sa, -so*sa, ca);
    vec3d pd = (po - px * sin(phi) * distance + py * cos(phi) * distance).normalize();
    x0 = atan2(pd.y, pd.x);
    y0 = safe_asin(pd.z);
}
Example #7
0
// create eulers from a quaternion
void Quaternion::to_vector312(float &roll, float &pitch, float &yaw) const
{    
    Matrix3f m;
    rotation_matrix(m);
    float T21 = m.a.y;
    float T22 = m.b.y;
    float T23 = m.c.y;
    float T13 = m.c.x;
    float T33 = m.c.z;
    yaw = atan2f(-T21, T22);
    roll = safe_asin(T23);
    pitch = atan2f(-T13, T33);
}
// create eulers from a quaternion
void Quaternion_D::to_euler(float *roll, float *pitch, float *yaw)
{
    if (roll) {
        *roll = (atan2f(2.0f*(q4*q1 + q2*q3),
                       1 - 2.0f*(q1*q1 + q2*q2)));
    }
    if (pitch) {
        // we let safe_asin() handle the singularities near 90/-90 in pitch
        *pitch = safe_asin(2.0f*(q4*q2 - q3*q1));
    }
    if (yaw) {
        *yaw = atan2f(2.0f*(q4*q3 + q1*q2),
                      1 - 2.0f*(q2*q2 + q3*q3));
    }
}
void PlanetViewController::turn(double angle)
{
    double co = cos(x0); // x0 = longitude
    double so = sin(x0);
    double ca = cos(y0); // y0 = latitude
    double sa = sin(y0);
    double l = d * sin(theta);
    vec3d po = vec3d(co*ca, so*ca, sa) * R;
    vec3d px = vec3d(-so, co, 0.0);
    vec3d py = vec3d(-co*sa, -so*sa, ca);
    vec3d f = -px * sin(phi) + py * cos(phi);
    vec3d r = px * cos(phi) + py * sin(phi);
    vec3d pd = (po + f * (cos(angle) - 1.0) * l - r * sin(angle) * l).normalize();
    x0 = atan2(pd.y, pd.x);
    y0 = safe_asin(pd.z);
    phi += angle;
}
Example #10
0
/*
 * Update AOA and SSA estimation based on airspeed, velocity vector and wind vector
 *
 * Based on:
 * "On estimation of wind velocity, angle-of-attack and sideslip angle of small UAVs using standard sensors" by
 * Tor A. Johansen, Andrea Cristofaro, Kim Sorensen, Jakob M. Hansen, Thor I. Fossen
 *
 * "Multi-Stage Fusion Algorithm for Estimation of Aerodynamic Angles in Mini Aerial Vehicle" by
 * C.Ramprasadh and Hemendra Arya
 *
 * "ANGLE OF ATTACK AND SIDESLIP ESTIMATION USING AN INERTIAL REFERENCE PLATFORM" by
 * JOSEPH E. ZEIS, JR., CAPTAIN, USAF
 */
void AP_AHRS::update_AOA_SSA(void)
{
#if APM_BUILD_TYPE(APM_BUILD_ArduPlane)
    const uint32_t now = AP_HAL::millis();
    if (now - _last_AOA_update_ms < 50) {
        // don't update at more than 20Hz
        return;
    }
    _last_AOA_update_ms = now;
    
    Vector3f aoa_velocity, aoa_wind;

    // get velocity and wind
    if (get_velocity_NED(aoa_velocity) == false) {
        return;
    }

    aoa_wind = wind_estimate();

    // Rotate vectors to the body frame and calculate velocity and wind
    const Matrix3f &rot = get_rotation_body_to_ned();
    aoa_velocity = rot.mul_transpose(aoa_velocity);
    aoa_wind = rot.mul_transpose(aoa_wind);

    // calculate relative velocity in body coordinates
    aoa_velocity = aoa_velocity - aoa_wind;
    const float vel_len = aoa_velocity.length();

    // do not calculate if speed is too low
    if (vel_len < 2.0) {
        _AOA = 0;
        _SSA = 0;
        return;
    }

    // Calculate AOA and SSA
    if (aoa_velocity.x > 0) {
        _AOA = degrees(atanf(aoa_velocity.z / aoa_velocity.x));
    } else {
        _AOA = 0;
    }

    _SSA = degrees(safe_asin(aoa_velocity.y / vel_len));
#endif
}
Example #11
0
// output_armed - sends commands to the motors
// includes new scaling stability patch
void AP_MotorsTri::output_armed_stabilizing()
{
    float   roll_thrust;                // roll thrust input value, +/- 1.0
    float   pitch_thrust;               // pitch thrust input value, +/- 1.0
    float   yaw_thrust;                 // yaw thrust input value, +/- 1.0
    float   throttle_thrust;            // throttle thrust input value, 0.0 - 1.0
    float   throttle_thrust_best_rpy;   // throttle providing maximum roll, pitch and yaw range without climbing
    float   rpy_scale = 1.0f;           // this is used to scale the roll, pitch and yaw to fit within the motor limits
    float   rpy_low = 0.0f;             // lowest motor value
    float   rpy_high = 0.0f;            // highest motor value
    float   thr_adj;                    // the difference between the pilot's desired throttle and throttle_thrust_best_rpy

    // sanity check YAW_SV_ANGLE parameter value to avoid divide by zero
    _yaw_servo_angle_max_deg = constrain_float(_yaw_servo_angle_max_deg, AP_MOTORS_TRI_SERVO_RANGE_DEG_MIN, AP_MOTORS_TRI_SERVO_RANGE_DEG_MAX);

    // apply voltage and air pressure compensation
    roll_thrust = _roll_in * get_compensation_gain();
    pitch_thrust = _pitch_in * get_compensation_gain();
    yaw_thrust = _yaw_in * get_compensation_gain()*sinf(radians(_yaw_servo_angle_max_deg)); // we scale this so a thrust request of 1.0f will ask for full servo deflection at full rear throttle
    throttle_thrust = get_throttle() * get_compensation_gain();

    // calculate angle of yaw pivot
    _pivot_angle = safe_asin(yaw_thrust);
    if (fabsf(_pivot_angle) > radians(_yaw_servo_angle_max_deg)) {
        limit.yaw = true;
        _pivot_angle = constrain_float(_pivot_angle, -radians(_yaw_servo_angle_max_deg), radians(_yaw_servo_angle_max_deg));
    }

    float pivot_thrust_max = cosf(_pivot_angle);
    float thrust_max = 1.0f;

    // sanity check throttle is above zero and below current limited throttle
    if (throttle_thrust <= 0.0f) {
        throttle_thrust = 0.0f;
        limit.throttle_lower = true;
    }
    if (throttle_thrust >= _throttle_thrust_max) {
        throttle_thrust = _throttle_thrust_max;
        limit.throttle_upper = true;
    }

    _throttle_avg_max = constrain_float(_throttle_avg_max, throttle_thrust, _throttle_thrust_max);

    // The following mix may be offer less coupling between axis but needs testing
    //_thrust_right = roll_thrust * -0.5f + pitch_thrust * 1.0f;
    //_thrust_left = roll_thrust * 0.5f + pitch_thrust * 1.0f;
    //_thrust_rear = 0;

    _thrust_right = roll_thrust * -0.5f + pitch_thrust * 0.5f;
    _thrust_left = roll_thrust * 0.5f + pitch_thrust * 0.5f;
    _thrust_rear = pitch_thrust * -0.5f;

    // calculate roll and pitch for each motor
    // set rpy_low and rpy_high to the lowest and highest values of the motors

    // record lowest roll pitch command
    rpy_low = MIN(_thrust_right,_thrust_left);
    rpy_high = MAX(_thrust_right,_thrust_left);
    if (rpy_low > _thrust_rear){
        rpy_low = _thrust_rear;
    }
    // check to see if the rear motor will reach maximum thrust before the front two motors
    if ((1.0f - rpy_high) > (pivot_thrust_max - _thrust_rear)){
        thrust_max = pivot_thrust_max;
        rpy_high = _thrust_rear;
    }

    // calculate throttle that gives most possible room for yaw (range 1000 ~ 2000) which is the lower of:
    //      1. 0.5f - (rpy_low+rpy_high)/2.0 - this would give the maximum possible room margin above the highest motor and below the lowest
    //      2. the higher of:
    //            a) the pilot's throttle input
    //            b) the point _throttle_rpy_mix between the pilot's input throttle and hover-throttle
    //      Situation #2 ensure we never increase the throttle above hover throttle unless the pilot has commanded this.
    //      Situation #2b allows us to raise the throttle above what the pilot commanded but not so far that it would actually cause the copter to rise.
    //      We will choose #1 (the best throttle for yaw control) if that means reducing throttle to the motors (i.e. we favor reducing throttle *because* it provides better yaw control)
    //      We will choose #2 (a mix of pilot and hover throttle) only when the throttle is quite low.  We favor reducing throttle instead of better yaw control because the pilot has commanded it

    // check everything fits
    throttle_thrust_best_rpy = MIN(0.5f*thrust_max - (rpy_low+rpy_high)/2.0, _throttle_avg_max);
    if(is_zero(rpy_low)){
        rpy_scale = 1.0f;
    } else {
        rpy_scale = constrain_float(-throttle_thrust_best_rpy/rpy_low, 0.0f, 1.0f);
    }

    // calculate how close the motors can come to the desired throttle
    thr_adj = throttle_thrust - throttle_thrust_best_rpy;
    if(rpy_scale < 1.0f){
        // Full range is being used by roll, pitch, and yaw.
        limit.roll_pitch = true;
        if (thr_adj > 0.0f){
            limit.throttle_upper = true;
        }
        thr_adj = 0.0f;
    }else{
        if(thr_adj < -(throttle_thrust_best_rpy+rpy_low)){
            // Throttle can't be reduced to desired value
            thr_adj = -(throttle_thrust_best_rpy+rpy_low);
        }else if(thr_adj > thrust_max - (throttle_thrust_best_rpy+rpy_high)){
            // Throttle can't be increased to desired value
            thr_adj = thrust_max - (throttle_thrust_best_rpy+rpy_high);
            limit.throttle_upper = true;
        }
    }

    // add scaled roll, pitch, constrained yaw and throttle for each motor
    _thrust_right = throttle_thrust_best_rpy+thr_adj + rpy_scale*_thrust_right;
    _thrust_left = throttle_thrust_best_rpy+thr_adj + rpy_scale*_thrust_left;
    _thrust_rear = throttle_thrust_best_rpy+thr_adj + rpy_scale*_thrust_rear;

    // scale pivot thrust to account for pivot angle
    // we should not need to check for divide by zero as _pivot_angle is constrained to the 5deg ~ 80 deg range
    _thrust_rear = _thrust_rear/cosf(_pivot_angle);

    // constrain all outputs to 0.0f to 1.0f
    // test code should be run with these lines commented out as they should not do anything
    _thrust_right = constrain_float(_thrust_right, 0.0f, 1.0f);
    _thrust_left = constrain_float(_thrust_left, 0.0f, 1.0f);
    _thrust_rear = constrain_float(_thrust_rear, 0.0f, 1.0f);
}
Example #12
0
// get euler pitch angle
float Quaternion::get_euler_pitch() const
{
    return safe_asin(2.0f*(q1*q3 - q4*q2));
}
Example #13
0
// create eulers from a quaternion
void Quaternion::to_euler(float &roll, float &pitch, float &yaw) const
{
    roll = (atan2f(2.0f*(q1*q2 + q3*q4), 1 - 2.0f*(q2*q2 + q3*q3)));
    pitch = safe_asin(2.0f*(q1*q3 - q4*q2));
    yaw = atan2f(2.0f*(q1*q4 + q2*q3), 1 - 2.0f*(q3*q3 + q4*q4));
}