コード例 #1
0
ファイル: vectors.cpp プロジェクト: brewpoo/multifly
void vector_difference_to_euler_angles(fixedpointnum *v1, fixedpointnum *v2, fixedpointnum *euler) {
    // take the difference between the two attitudes and return the euler angles between them
    // find the axis of rotation and angle between the two downVectors
   // the cross products of the two vectors will give us the axis of rotation from one to the other
   fixedpointnum axisofrotation[3];
   vector_cross_product(v1, v2, axisofrotation);

   fixedpointnum axislength=lib_fp_sqrt(normalize_vector(axisofrotation));
   
   // get the angle of rotation between the two vectors
   fixedpointnum angle=lib_fp_atan2(axislength, vector_dot_product(v1, v2));

   fixedpointnum unitvector[3];
   unitvector[0]=0;
   unitvector[1]=FIXEDPOINTONE;
   unitvector[2]=0;
   
   euler[0]=lib_fp_multiply(vector_dot_product(axisofrotation, unitvector), angle);

   unitvector[0]=FIXEDPOINTONE;
   unitvector[1]=0;
   unitvector[2]=0;
   
   euler[1]=lib_fp_multiply(vector_dot_product(axisofrotation, unitvector), angle);
}
コード例 #2
0
ファイル: vectors.cpp プロジェクト: brewpoo/multifly
void rotate_vector_by_axis_small_angle(fixedpointnum *v1, fixedpointnum *axisvector, fixedpointnum angle) {
     // rotates vector by small angle angle around axis vector.
   fixedpointnum angleinradians=lib_fp_multiply(angle, FIXEDPOINTPIOVER180);
   
   fixedpointnum crossproductvector[3];
   vector_cross_product(axisvector,v1, crossproductvector);
      
   v1[0]+=lib_fp_multiply(crossproductvector[0],angleinradians);
   v1[1]+=lib_fp_multiply(crossproductvector[1],angleinradians);
   v1[2]+=lib_fp_multiply(crossproductvector[2],angleinradians);
}
コード例 #3
0
void resetpilotcontrol(void)
{                               // called when switching from navigation control to pilot control or when idling on the ground.
    // keeps us from accumulating yaw error that we can't correct.
    desiredcompassheading = global.currentestimatedeulerattitude[YAWINDEX];
    // Same for yaw hold mode
    accumulatedyawerror = 0;

    // calculate our max rotation rates based on usersettings
    highyawrate = lib_fp_multiply(usersettings.maxyawrate, FP_HIGH_RATES_MULTILIER);
    highpitchandrollrate = lib_fp_multiply(usersettings.maxpitchandrollrate, FP_HIGH_RATES_MULTILIER);
}
コード例 #4
0
ファイル: aircraft.cpp プロジェクト: brewpoo/bradwii
void compute_mix(fixedpointnum throttle, fixedpointnum pid[]) {
#if (AIRCRAFT_CONFIGURATION==QUADX)
    global.motor[QUADX_REAR_RIGHT_MOTOR] =throttle-pid[ROLL_INDEX]+pid[PITCH_INDEX]-pid[YAW_INDEX];
    global.motor[QUADX_FRONT_RIGHT_MOTOR]=throttle-pid[ROLL_INDEX]-pid[PITCH_INDEX]+pid[YAW_INDEX];
    global.motor[QUADX_REAR_LEFT_MOTOR]  =throttle+pid[ROLL_INDEX]+pid[PITCH_INDEX]+pid[YAW_INDEX];
    global.motor[QUADX_FRONT_LEFT_MOTOR] =throttle+pid[ROLL_INDEX]-pid[PITCH_INDEX]-pid[YAW_INDEX];
#elif (AIRCRAFT_CONFIGURATION==TRI)
    global.motor[TRI_REAR_MOTOR]=throttle+lib_fp_multiply(FIXEDPOINT_FOUR_THIRDS,pid[PITCH_INDEX]);
    global.motor[TRI_LEFT_MOTOR]=throttle-pid[ROLL_INDEX]-lib_fp_multiply(FIXEDPOINT_TWO_THIRDS,pid[PITCH_INDEX]);
    global.motor[TRI_RIGHT_MOTOR]=throttle=pid[ROLL_INDEX]-lib_fp_multiply(FIXEDPOINT_TWO_THIRDS,pid[PITCH_INDEX]);
    global.servo[TRI_REAR_SERVO]=SERVO_DIR(TRI_REAR_SERVO)*pid[YAW_INDEX]+SERVO_MID(TRI_REAR_SERVO);
#else
    #error "Must define mix for aircraft"
#endif
}
コード例 #5
0
ファイル: vectors.cpp プロジェクト: brewpoo/multifly
fixedpointnum normalize_vector(fixedpointnum *v) {
    fixedpointnum vectorlengthsquared=lib_fp_multiply(v[0],v[0])+lib_fp_multiply(v[1],v[1])+lib_fp_multiply(v[2],v[2]);
   
    // if we are near zero length, choose any unit length vector
    if (vectorlengthsquared<10) {
        v[0]=FIXEDPOINTONE;
        v[1]=v[2]=0;
    } else {
        fixedpointnum multiplier=lib_fp_invsqrt(vectorlengthsquared);

        v[0]=lib_fp_multiply(v[0], multiplier);
        v[1]=lib_fp_multiply(v[1], multiplier);
        v[2]=lib_fp_multiply(v[2], multiplier);
    }
    return(vectorlengthsquared);
}
コード例 #6
0
ファイル: gps.cpp プロジェクト: sbstnp/bradwii_arduino
fixedpointnum gpsstringtoangle(char *string)
   { // takes a gps string and converts it to a fixedpointnum angle
   // "4807.123" means 48 degrees, 7.123 minutes, south
   // how many digits are there before the decimal point?
   int index=0;
   while (string[index]>='0' && string[index]<='9') ++index;
   
   // convert the minutes part
   fixedpointnum minutes=lib_fp_stringtofixedpointnum(&string[index-2]);

   string[index-2]='\0';
   fixedpointnum degrees=lib_fp_stringtofixedpointnum(string);
   return((degrees<<LATLONGEXTRASHIFT)+lib_fp_multiply(minutes,69905L));  // 69905L is (1/60) * 2^16 * 2^6
   }
コード例 #7
0
ファイル: vectors.cpp プロジェクト: brewpoo/multifly
void rotate_vector_by_axis_angle(fixedpointnum *v1, fixedpointnum *axisvector, fixedpointnum angle, fixedpointnum *v2) {
   fixedpointnum cosineofangle=lib_fp_cosine(angle);
   fixedpointnum sineofangle=lib_fp_sine(angle);
   
   fixedpointnum crossproductvector[3];
   vector_cross_product(axisvector,v1, crossproductvector);
   
   fixedpointnum dotproducttimesoneminuscosineofangle=lib_fp_multiply(vector_dot_product(axisvector,v1),FIXEDPOINTONE-cosineofangle);
   
   v2[0]=lib_fp_multiply(v1[0], cosineofangle)+lib_fp_multiply(crossproductvector[0],sineofangle)+lib_fp_multiply(axisvector[0],dotproducttimesoneminuscosineofangle);
   v2[1]=lib_fp_multiply(v1[1], cosineofangle)+lib_fp_multiply(crossproductvector[1],sineofangle)+lib_fp_multiply(axisvector[1],dotproducttimesoneminuscosineofangle);
   v2[2]=lib_fp_multiply(v1[2], cosineofangle)+lib_fp_multiply(crossproductvector[2],sineofangle)+lib_fp_multiply(axisvector[2],dotproducttimesoneminuscosineofangle);
}
コード例 #8
0
ファイル: vectors.cpp プロジェクト: brewpoo/multifly
void rotate_vector_with_small_angles(fixedpointnum *v, fixedpointnum rolldeltaangle, fixedpointnum pitchdeltaangle, fixedpointnum yawdeltaangle) {
   // rotate the attitude by the delta angles.
   // assumes that the delta angles are small angles in degrees and that they are shifted left by TIMESLIVEREXTRASHIFT
   fixedpointnum v_tmp_x=v[X_INDEX];
   fixedpointnum v_tmp_y=v[Y_INDEX];
   fixedpointnum v_tmp_z=v[Z_INDEX];

   // remember that our delta angles are shifted left by TIMESLIVEREXTRASHIFT for resolution.  Take it out here
   v[X_INDEX] += (lib_fp_multiply(rolldeltaangle ,v_tmp_z) - lib_fp_multiply(yawdeltaangle,v_tmp_y))>>(TIMESLIVEREXTRASHIFT);
   v[Y_INDEX] += (lib_fp_multiply(pitchdeltaangle,v_tmp_z) + lib_fp_multiply(yawdeltaangle ,v_tmp_x))>>(TIMESLIVEREXTRASHIFT);
   v[Z_INDEX] -= (lib_fp_multiply(rolldeltaangle,v_tmp_x) + lib_fp_multiply(pitchdeltaangle ,v_tmp_y))>>(TIMESLIVEREXTRASHIFT);
}
コード例 #9
0
fixedpointnum navigation_getdistanceandbearing(fixedpointnum lat1,fixedpointnum lon1,fixedpointnum lat2,fixedpointnum lon2,fixedpointnum *bearing)
   { // returns fixedpointnum distance in meters and bearing in fixedpointnum degrees from point 1 to point 2
   fixedpointnum latdiff=lat2-lat1;
   fixedpointnum londiff=lib_fp_multiply(lon2-lon1,lib_fp_cosine(lat1>>LATLONGEXTRASHIFT));
      
   *bearing = FIXEDPOINT90 + lib_fp_atan2(-latdiff, londiff);
   if (*bearing >FIXEDPOINT180) *bearing -= FIXEDPOINT360;
   
   // distance is 111319 meters per degree. This factor needs to be shifted 16 to make it a fixedpointnum.
   // Since lat and lon are already shifted by 6,
   // we will shift by 10 more total.  Shift lat and long by 8 and the constant by 2 to get the extra 10.
   // The squaring will overflow our fixedpointnum at distances greater than 1000 meters or so, so test for size and shift accordingly
   if (lib_fp_abs(latdiff)+lib_fp_abs(londiff)>40000L)
      { // for big distances, don't shift lat and long.  Instead shift the constant by 10.
      // this will get us to 32 kilometers at which point our fixedpoingnum can't hold a larger distance.
      return(lib_fp_multiply(lib_fp_sqrt(lib_fp_multiply(latdiff,latdiff)+lib_fp_multiply(londiff,londiff)),113990656L));
      }
   else
      {
      latdiff=latdiff<<8;
      londiff=londiff<<8;
      return(lib_fp_multiply(lib_fp_sqrt(lib_fp_multiply(latdiff,latdiff)+lib_fp_multiply(londiff,londiff)),445276L));
      }
   }
コード例 #10
0
void navigation_setangleerror(unsigned char gotnewgpsreading,fixedpointnum *angleerror)
   { // calculate the angle errors between our current attitude and the one we wish to have
   // and adjust the angle errors that were passed to us.  They have already been set by pilot input.
   // For now, we just override any pilot input.
   
   // keep track of the time between good gps readings.
   navigation_time_sliver+=global.timesliver;

   if (gotnewgpsreading)
      {
      // unshift our timesliver since we are about to use it. Since we are accumulating time, it may get too large to use while shifted.
      navigation_time_sliver=navigation_time_sliver>>TIMESLIVEREXTRASHIFT;
      
      // get the new distance and bearing from our current location to our target position
      global.navigation_distance=navigation_getdistanceandbearing(global.gps_current_latitude,global.gps_current_longitude,target_latitude,target_longitude,&global.navigation_bearing);

      // split the distance into it's ontrack and crosstrack components
      // see the diagram above
      fixedpointnum angledifference=global.navigation_bearing-navigation_starttodestbearing;
      fixedpointnum crosstrack_distance=lib_fp_multiply(global.navigation_distance,lib_fp_sine(angledifference));
      fixedpointnum ontrack_distance=lib_fp_multiply(global.navigation_distance,lib_fp_cosine(angledifference));

      // accumulate integrated error for both ontrack and crosstrack
      navigation_crosstrack_integrated_error+=lib_fp_multiply(crosstrack_distance,navigation_time_sliver);
      navigation_ontrack_integrated_error+=lib_fp_multiply(ontrack_distance,navigation_time_sliver);
      lib_fp_constrain(&navigation_crosstrack_integrated_error,-NAVIGATIONINTEGRATEDERRORLIMIT,NAVIGATIONINTEGRATEDERRORLIMIT);
      lib_fp_constrain(&navigation_ontrack_integrated_error,-NAVIGATIONINTEGRATEDERRORLIMIT,NAVIGATIONINTEGRATEDERRORLIMIT);

      // calculate the ontrack and crosstrack velocities toward our target.
      // We want to put the navigation velocity (change in distance to target over time) into a low pass filter but
      // we don't want to divide by the time interval to get velocity (divide is expensive) to then turn around and
      // multiply by the same time interval. So the following is the same as the lib_fp_lowpassfilter code
      // except we eliminate the multiply.
      // note: if we use a different time period than FIXEDPOINTONEOVERONE, we need to multiply the distances by the new time period.
      fixedpointnum fraction=lib_fp_multiply(navigation_time_sliver,FIXEDPOINTONEOVERONE);
      navigation_crosstrack_velocity=(navigation_last_crosstrack_distance-crosstrack_distance+lib_fp_multiply((FIXEDPOINTONE)-fraction,navigation_crosstrack_velocity));
      navigation_ontrack_velocity=(navigation_last_ontrack_distance-ontrack_distance+lib_fp_multiply((FIXEDPOINTONE)-fraction,navigation_ontrack_velocity));
      navigation_last_crosstrack_distance=crosstrack_distance;
      navigation_last_ontrack_distance=ontrack_distance;
   
      // calculate the desired tilt in each direction independently using navigation PID
      fixedpointnum crosstracktiltangle=lib_fp_multiply(usersettings.pid_pgain[NAVIGATIONINDEX],crosstrack_distance)
                                    +lib_fp_multiply(usersettings.pid_igain[NAVIGATIONINDEX],navigation_crosstrack_integrated_error)
                                    -lib_fp_multiply(usersettings.pid_dgain[NAVIGATIONINDEX],navigation_crosstrack_velocity);
                     
      fixedpointnum ontracktiltangle   =lib_fp_multiply(usersettings.pid_pgain[NAVIGATIONINDEX],ontrack_distance)
                                    +lib_fp_multiply(usersettings.pid_igain[NAVIGATIONINDEX],navigation_ontrack_integrated_error)
                                    -lib_fp_multiply(usersettings.pid_dgain[NAVIGATIONINDEX],navigation_ontrack_velocity);
      
      // don't tilt more than MAX_TILT
      lib_fp_constrain(&crosstracktiltangle,-MAX_TILT,MAX_TILT);
      lib_fp_constrain(&ontracktiltangle,-MAX_TILT,MAX_TILT);

      // Translate the ontrack and cross track tilts into pitch and roll tilts.
      // Set angledifference equal to the difference between the aircraft's heading (the way it's currently pointing)
      // and the angle between waypoints and rotate our tilts by that much.   
      angledifference=global.currentestimatedeulerattitude[YAWINDEX]-navigation_starttodestbearing;
   
      fixedpointnum sineofangle=lib_fp_sine(angledifference);
      fixedpointnum cosineofangle=lib_fp_cosine(angledifference);
   
      navigation_desiredeulerattitude[ROLLINDEX]=lib_fp_multiply(crosstracktiltangle,cosineofangle)-lib_fp_multiply(ontracktiltangle,sineofangle);
      navigation_desiredeulerattitude[PITCHINDEX]=lib_fp_multiply(crosstracktiltangle,sineofangle)+lib_fp_multiply(ontracktiltangle,cosineofangle);
   
      // for now, don't rotate the aircraft in the direction of travel. Add this later.
      
      navigation_time_sliver=0;
      }
   
   // set the angle error as the difference between where we want to be and where we currently are angle wise.
   angleerror[ROLLINDEX]=navigation_desiredeulerattitude[ROLLINDEX]-global.currentestimatedeulerattitude[ROLLINDEX];
   angleerror[PITCHINDEX]=navigation_desiredeulerattitude[PITCHINDEX]-global.currentestimatedeulerattitude[PITCHINDEX];

   // don't set the yaw.  Let the pilot do yaw
//   angleerror[YAWINDEX]=navigation_desiredeulerattitude[YAWINDEX]-global.currentestimatedeulerattitude[YAWINDEX];

   // don't let the yaw angle error get too large for any one cycle in order to control the maximum yaw rate.
//   lib_fp_constrain180(&angleerror[YAWINDEX]);
//   lib_fp_constrain(&angleerror[YAWINDEX],-MAXYAWANGLEERROR,MAXYAWANGLEERROR);
   }
コード例 #11
0
void getangleerrorfrompilotinput(fixedpointnum * angleerror)
{
    // sets the ange errors for roll, pitch, and yaw based on where the pilot has the tx sticks.
    fixedpointnum rxrollvalue;
    fixedpointnum rxpitchvalue;

    // if in headfree mode, rotate the pilot's stick inputs by the angle that is the difference between where we are currently heading and where we were heading when we armed.
    if (global.activecheckboxitems & CHECKBOXMASKHEADFREE) {
        fixedpointnum angledifference = global.currentestimatedeulerattitude[YAWINDEX] - global.heading_when_armed;

        fixedpointnum cosangledifference = lib_fp_cosine(angledifference);
        fixedpointnum sinangledifference = lib_fp_sine(angledifference);
        rxpitchvalue = lib_fp_multiply(global.rxvalues[PITCHINDEX], cosangledifference) + lib_fp_multiply(global.rxvalues[ROLLINDEX], sinangledifference);
        rxrollvalue = lib_fp_multiply(global.rxvalues[ROLLINDEX], cosangledifference) - lib_fp_multiply(global.rxvalues[PITCHINDEX], sinangledifference);
        #ifdef INVERTED
		rxrollvalue = - rxrollvalue;
		#endif
    } else {
        rxpitchvalue = global.rxvalues[PITCHINDEX];
        rxrollvalue = global.rxvalues[ROLLINDEX];
        #ifdef INVERTED
		rxrollvalue = - rxrollvalue;
		#endif
    }

    // first, calculate level mode values
    // how far is our estimated current attitude from our desired attitude?
    // desired angle is rxvalue (-1 to 1) times LEVEL_MODE_MAX_TILT
    // First, figure out which max angle we are using depending on aux switch settings.
    fixedpointnum levelmodemaxangle;
    if (global.activecheckboxitems & CHECKBOXMASKHIGHANGLE)
        levelmodemaxangle = FP_LEVEL_MODE_MAX_TILT_HIGH_ANGLE;
    else
        levelmodemaxangle = FP_LEVEL_MODE_MAX_TILT;

    // the angle error is how much our current angles differ from our desired angles.
    fixedpointnum levelmoderollangleerror = lib_fp_multiply(rxrollvalue, levelmodemaxangle) - global.currentestimatedeulerattitude[ROLLINDEX];
    fixedpointnum levelmodepitchangleerror = lib_fp_multiply(rxpitchvalue, levelmodemaxangle) - global.currentestimatedeulerattitude[PITCHINDEX];

    // In acro mode, we want the rotation rate to be proportional to the pilot's stick movement.  The desired rotation rate is
    // the stick movement * a multiplier.
    // Fill angleerror with acro values.  If we are currently rotating at rate X and
    // we want to be rotating at rate Y, then our angle should be off by (Y-X)*timesliver.  In theory, we should probably accumulate
    // this error over time, but our I term will do that anyway and we are talking about rates, which don't need to be perfect.
    // First figure out what max rotation rates we are using depending on our aux switch settings.
    fixedpointnum maxyawrate;
    fixedpointnum maxpitchandrollrate;
    if (global.activecheckboxitems & CHECKBOXMASKHIGHRATES) {
        maxyawrate = highyawrate;
        maxpitchandrollrate = highpitchandrollrate;
    } else {
        maxyawrate = usersettings.maxyawrate;
        maxpitchandrollrate = usersettings.maxpitchandrollrate;
    }

    angleerror[ROLLINDEX] = lib_fp_multiply(lib_fp_multiply(rxrollvalue, maxpitchandrollrate) - global.gyrorate[ROLLINDEX], global.timesliver);
    angleerror[PITCHINDEX] = lib_fp_multiply(lib_fp_multiply(rxpitchvalue, maxpitchandrollrate) - global.gyrorate[PITCHINDEX], global.timesliver);

    // put a low pass filter on the yaw gyro.  If we don't do this, things can get jittery.
    lib_fp_lowpassfilter(&filteredyawgyrorate, global.gyrorate[YAWINDEX], global.timesliver >> (TIMESLIVEREXTRASHIFT - 3), FIXEDPOINTONEOVERONESIXTYITH, 3);

    if(global.activecheckboxitems & CHECKBOXMASKYAWHOLD) {
        // Yaw hold: control yaw angle instead of yaw rate by accumulating the yaw errors.
        // This is similar to compass mode, but no hardware compass needed.
        if(!(global.previousactivecheckboxitems & CHECKBOXMASKYAWHOLD)) {
            // This mode was just switched on. Use current position as reference by setting error to zero.
            accumulatedyawerror = 0;
        }
        // Accumulate yaw angle error
        accumulatedyawerror += lib_fp_multiply(lib_fp_multiply(global.rxvalues[YAWINDEX], maxyawrate) - filteredyawgyrorate, global.timesliver) >> TIMESLIVEREXTRASHIFT;
        // Make sure it does not get too high
        lib_fp_constrain180(&accumulatedyawerror);
        angleerror[YAWINDEX] = accumulatedyawerror;
    } else {
コード例 #12
0
ファイル: gps.cpp プロジェクト: sbstnp/bradwii_arduino
char readgps()
   {
   while (lib_serial_numcharsavailable(GPS_SERIAL_PORT))
      {
      char c=lib_serial_getchar(GPS_SERIAL_PORT);

      if (c=='$') // start of a new message
         {
         gpsparameternumber=0;
         gpsdataindex=0;
         gpschecksum=0;
         gpsframetype=0;
         }
      else
         {
         if (c==',' || c=='*')
            { // we just finished loading a parameter, interpret it
            gpsdata[gpsdataindex]='\0';

            if (gpsparameternumber == 0) 
               { //frame identification
               if (gpsdata[0] == 'G' && gpsdata[1] == 'P' && gpsdata[2] == 'G' && gpsdata[3] == 'G' && gpsdata[4] == 'A') gpsframetype=FRAME_GGA;
               else if (gpsdata[0] == 'G' && gpsdata[1] == 'P' && gpsdata[2] == 'R' && gpsdata[3] == 'M' && gpsdata[4] == 'C') gpsframetype = FRAME_RMC;
               } 
            else if (gpsframetype == FRAME_GGA) 
               {
               if (gpsparameternumber == 2) 
                  {
                  gpslatitudedegrees = gpsstringtoangle(gpsdata);
                  }
               else if (gpsparameternumber == 3)
                  {
                  if ( gpsdata[0] == 'S') gpslatitudedegrees=-gpslatitudedegrees;
                  }
               else if (gpsparameternumber == 4)
                  {
                  gpslongitudedegrees = gpsstringtoangle(gpsdata);
                  }
               else if (gpsparameternumber == 5)
                  {
                  if ( gpsdata[0] == 'W') gpslongitudedegrees=-gpslongitudedegrees;
                  }
               else if (gpsparameternumber == 6)
                  {
                  gpsfix = gpsdata[0]-'0';
                  }
               else if (gpsparameternumber == 7)
                  {
                  global.gps_num_satelites = lib_fp_stringtolong(gpsdata);
                  }
               else if (gpsparameternumber == 9)
                  {
                  global.gps_current_altitude = lib_fp_stringtofixedpointnum(gpsdata);
                  }
               } 
            else if (gpsframetype == FRAME_RMC) 
               {
               if (gpsparameternumber == 7)
                  {
                  // 1 knot = 0.514444444 m / s
                  global.gps_current_speed=lib_fp_multiply(lib_fp_stringtofixedpointnum(gpsdata),33715L); // 33715L is .514444444 * 2^16
                  }
               else if (gpsparameternumber == 8) 
                  {
//                  GPS_ground_course = grab_fields(gpsdata,1); 
                  }                 //ground course deg*10 
               }
            
            ++gpsparameternumber;
            gpsdataindex = 0; // get read for the next parameter
            if (c == '*') gpsfinalchecksum=gpschecksum;
            }
         else if (c == '\r' || c == '\n') 
            { // end of the message
            unsigned char checksum = hextochar(gpsdata[0]);
            checksum <<= 4;
            checksum += hextochar(gpsdata[1]);

            if (checksum != gpsfinalchecksum || gpsframetype!=FRAME_GGA || !gpsfix) return(0);
            gpsframetype=0; // so we don't check again

            global.gps_current_latitude=gpslatitudedegrees;
            global.gps_current_longitude=gpslongitudedegrees;
            
            return(1); // we got a good frame
            }
         else if (gpsdataindex<GPSDATASIZE)
            {
            gpsdata[gpsdataindex++]=c;
            }
         gpschecksum^=c;
         }
      }
   return(0); // no complete data yet
   }
コード例 #13
0
ファイル: gps.cpp プロジェクト: sbstnp/bradwii_arduino
char readgps()
   { // returns 1 if new data was read
   if (lib_timers_gettimermicroseconds(gpstimer)<50000) return(0); // 20 hz

   gpstimer=lib_timers_starttimer();
   
   unsigned char shiftedaddress=I2C_GPS_ADDRESS<<1;
   lib_i2c_start_wait(shiftedaddress+I2C_WRITE);
   if (lib_i2c_write(I2C_GPS_STATUS_00))
      return(0); 

   lib_i2c_rep_start(shiftedaddress+I2C_READ);

   unsigned char gps_status= lib_i2c_readnak();
 
   global.gps_num_satelites = (gps_status & 0xf0) >> 4;
   if (gps_status & I2C_GPS_STATUS_3DFIX) 
      { //Check is we have a good 3d fix (numsats>5)
      long longvalue;
      unsigned char *ptr=(unsigned char *)&longvalue;
      
      lib_i2c_rep_start(shiftedaddress+I2C_WRITE);
      lib_i2c_write(I2C_GPS_LOCATION); 
      lib_i2c_rep_start(shiftedaddress+I2C_READ);

      *ptr++ = lib_i2c_readack();
      *ptr++ = lib_i2c_readack();
      *ptr++ = lib_i2c_readack();
      *ptr = lib_i2c_readack();

      global.gps_current_latitude=lib_fp_multiply(longvalue,27488L); // convert from 10,000,000 m to fixedpointnum
      
      ptr=(unsigned char *)&longvalue;
      
      *ptr++ = lib_i2c_readack();
      *ptr++ = lib_i2c_readack();
      *ptr++ = lib_i2c_readack();
      *ptr = lib_i2c_readnak();
      
      global.gps_current_longitude=lib_fp_multiply(longvalue,27488L); // convert from 10,000,000 m to fixedpointnum

      int intvalue;
      ptr= (unsigned char *)&intvalue;
      
      lib_i2c_rep_start(shiftedaddress+I2C_WRITE);
      lib_i2c_write(I2C_GPS_GROUND_SPEED); 
      lib_i2c_rep_start(shiftedaddress+I2C_READ);

      *ptr++ = lib_i2c_readack();
      *ptr++ = lib_i2c_readack();
      
      global.gps_current_speed=intvalue*665L; // convert fro cm/s to fixedpointnum to m/s
      
      ptr= (unsigned char *)&intvalue;
      *ptr++ = lib_i2c_readack();
      *ptr = lib_i2c_readnak();

      global.gps_current_altitude=((fixedpointnum)intvalue)<<FIXEDPOINTSHIFT;

      lib_i2c_stop();
      return(1);
      }
   lib_i2c_stop();

   return(0);
   }
コード例 #14
0
ファイル: bradwii.cpp プロジェクト: brewpoo/bradwii
// It all starts here:
int main(void) {
    // start with default user settings in case there's nothing in eeprom
    default_user_settings();
    // try to load settings from eeprom
    read_user_settings_from_eeprom();
   
    // set our LED as a digital output
    lib_digitalio_initpin(LED1_OUTPUT,DIGITALOUTPUT);

    //initialize the libraries that require initialization
    lib_timers_init();
    lib_i2c_init();

    // pause a moment before initializing everything. To make sure everything is powered up
    lib_timers_delaymilliseconds(100);
   
    // initialize all other modules
    init_rx();
    init_outputs();
    serial_init();
    init_gyro();
    init_acc();
    init_baro();
    init_compass();
    init_gps();
    init_imu();
   
    // set the default i2c speed to 400 KHz.  If a device needs to slow it down, it can, but it should set it back.
    lib_i2c_setclockspeed(I2C_400_KHZ);

    // initialize state
    global.state.armed=0;
    global.state.calibratingCompass=0;
    global.state.calibratingAccAndGyro=0;
    global.state.navigationMode=NAVIGATION_MODE_OFF;
    global.failsafeTimer=lib_timers_starttimer();

    // run loop
    for(;;) {
      // check to see what switches are activated
      check_checkbox_items();
      
      // check for config program activity
      serial_check_for_action();   
      
      calculate_timesliver();
      
      // run the imu to estimate the current attitude of the aircraft
      imu_calculate_estimated_attitude();

      // arm and disarm via rx aux switches
      if (global.rxValues[THROTTLE_INDEX]<FPSTICKLOW) { // see if we want to change armed modes
          if (!global.state.armed) {
             if (global.activeCheckboxItems & CHECKBOX_MASK_ARM) {
                 global.state.armed=1;
                #if (GPS_TYPE!=NO_GPS)
                 navigation_set_home_to_current_location();
                #endif
                 global.home.heading=global.currentEstimatedEulerAttitude[YAW_INDEX];
                 global.home.location.altitude=global.baroRawAltitude;
             }
          } else if (!(global.activeCheckboxItems & CHECKBOX_MASK_ARM)) global.state.armed=0;
      }

      #if (GPS_TYPE!=NO_GPS)
      // turn on or off navigation when appropriate
      if (global.state.navigationMode==NAVIGATION_MODE_OFF) {
          if (global.activeCheckboxItems & CHECKBOX_MASK_RETURNTOHOME) { // return to home switch turned on
              navigation_set_destination(global.home.location.latitude,global.home.location.longitude);
              global.state.navigationMode=NAVIGATION_MODE_RETURN_TO_HOME;
          } else if (global.activeCheckboxItems & CHECKBOX_MASK_POSITIONHOLD) { // position hold turned on
              navigation_set_destination(global.gps.currentLatitude,global.gps.currentLongitude);
              global.state.navigationMode=NAVIGATION_MODE_POSITION_HOLD;
          }
      } else { // we are currently navigating
          // turn off navigation if desired
          if ((global.state.navigationMode==NAVIGATION_MODE_RETURN_TO_HOME && !(global.activeCheckboxItems & CHECKBOX_MASK_RETURNTOHOME)) || (global.state.navigationMode==NAVIGATION_MODE_POSITION_HOLD && !(global.activeCheckboxItems & CHECKBOX_MASK_POSITIONHOLD))) {
              global.state.navigationMode=NAVIGATION_MODE_OFF;
            
              // we will be turning control back over to the pilot.
              reset_pilot_control();
          }
      }
        #endif
      
       // read the receiver
       read_rx();
      
       // turn on the LED when we are stable and the gps has 5 satelites or more
      #if (GPS_TYPE==NO_GPS)
       lib_digitalio_setoutput(LED1_OUTPUT, (global.state.stable==0)==LED1_ON);
      #else
       lib_digitalio_setoutput(LED1_OUTPUT, (!(global.state.stable && global.gps.numSatelites>=5))==LED1_ON);
      #endif
      
       // get the angle error.  Angle error is the difference between our current attitude and our desired attitude.
       // It can be set by navigation, or by the pilot, etc.
       fixedpointnum angleError[3];
      
       // let the pilot control the aircraft.
       get_angle_error_from_pilot_input(angleError);
      
#if (GPS_TYPE!=NO_GPS)
       // read the gps
       unsigned char gotNewGpsReading=read_gps();

       // if we are navigating, use navigation to determine our desired attitude (tilt angles)
       if (global.state.navigationMode!=NAVIGATION_MODE_OFF) { // we are navigating
           navigation_set_angle_error(gotNewGpsReading,angleError);
       }
#endif

       if (global.rxValues[THROTTLE_INDEX]<FPSTICKLOW) {
           // We are probably on the ground. Don't accumnulate error when we can't correct it
           reset_pilot_control();
         
           // bleed off integrated error by averaging in a value of zero
           lib_fp_lowpassfilter(&global.integratedAngleError[ROLL_INDEX],0L,global.timesliver>>TIMESLIVEREXTRASHIFT,FIXEDPOINTONEOVERONEFOURTH,0);
           lib_fp_lowpassfilter(&global.integratedAngleError[PITCH_INDEX],0L,global.timesliver>>TIMESLIVEREXTRASHIFT,FIXEDPOINTONEOVERONEFOURTH,0);
           lib_fp_lowpassfilter(&global.integratedAngleError[YAW_INDEX],0L,global.timesliver>>TIMESLIVEREXTRASHIFT,FIXEDPOINTONEOVERONEFOURTH,0);
       }

#ifndef NO_AUTOTUNE
       // let autotune adjust the angle error if the pilot has autotune turned on
       if (global.activeCheckboxItems & CHECKBOX_MASK_AUTOTUNE) {
           if (!(global.previousActiveCheckboxItems & CHECKBOX_MASK_AUTOTUNE)) {
               autotune(angleError,AUTOTUNE_STARTING); // tell autotune that we just started autotuning
           } else {
               autotune(angleError,AUTOTUNE_TUNING); // tell autotune that we are in the middle of autotuning
           }
       } else if (global.previousActiveCheckboxItems & CHECKBOX_MASK_AUTOTUNE) {
           autotune(angleError,AUTOTUNE_STOPPING); // tell autotune that we just stopped autotuning
       }
#endif

        // This gets reset every loop cycle
        // keep a flag to indicate whether we shoud apply altitude hold.  The pilot can turn it on or
        // uncrashability/autopilot mode can turn it on.
        global.state.altitudeHold=0;
        
        if (global.activeCheckboxItems & CHECKBOX_MASK_ALTHOLD) {
            global.state.altitudeHold=1;
            if (!(global.previousActiveCheckboxItems & CHECKBOX_MASK_ALTHOLD)) {
                // we just turned on alt hold.  Remember our current alt. as our target
                global.altitudeHoldDesiredAltitude=global.altitude;
                global.integratedAltitudeError=0;
            }
        }
        
        fixedpointnum throttleOutput;
        
#ifndef NO_AUTOPILOT
        // autopilot is available
        if (global.activeCheckboxItems & CHECKBOX_MASK_AUTOPILOT) {
            if (!(global.previousActiveCheckboxItems & CHECKBOX_MASK_AUTOPILOT)) {
                // let autopilot know to transition to the starting state
                autopilot(AUTOPILOT_STARTING);
            } else {
                // autopilot normal run state
                autopilot(AUTOPILOT_RUNNING);
            }
        } else if (global.previousActiveCheckboxItems & CHECKBOX_MASK_AUTOPILOT) {
            // tell autopilot that we just stopped autotuning
            autopilot(AUTOPILOT_STOPPING);
        } else {
            // get the pilot's throttle component
            // convert from fixedpoint -1 to 1 to fixedpoint 0 to 1
            throttleOutput=(global.rxValues[THROTTLE_INDEX]>>1)+FIXEDPOINTCONSTANT(.5)+FPTHROTTLETOMOTOROFFSET;
        }
#else

       // get the pilot's throttle component
       // convert from fixedpoint -1 to 1 to fixedpoint 0 to 1
       throttleOutput=(global.rxValues[THROTTLE_INDEX]>>1)+FIXEDPOINTCONSTANT(.5)+FPTHROTTLETOMOTOROFFSET;
#endif

#ifndef NO_UNCRASHABLE
        uncrashable(gotNewGpsReading,angleError,&throttleOutput);
#endif
        
#if (BAROMETER_TYPE!=NO_BAROMETER)
       // check for altitude hold and adjust the throttle output accordingly
       if (global.state.altitudeHold) {
           global.integratedAltitudeError+=lib_fp_multiply(global.altitudeHoldDesiredAltitude-global.altitude,global.timesliver);
           lib_fp_constrain(&global.integratedAltitudeError,-INTEGRATED_ANGLE_ERROR_LIMIT,INTEGRATED_ANGLE_ERROR_LIMIT); // don't let the integrated error get too high
         
           // do pid for the altitude hold and add it to the throttle output
           throttleOutput+=lib_fp_multiply(global.altitudeHoldDesiredAltitude-global.altitude,settings.pid_pgain[ALTITUDE_INDEX])-lib_fp_multiply(global.altitudeVelocity,settings.pid_dgain[ALTITUDE_INDEX])+lib_fp_multiply(global.integratedAltitudeError,settings.pid_igain[ALTITUDE_INDEX]);
       }
#endif

#ifndef NO_AUTOTHROTTLE
       if ((global.activeCheckboxItems & CHECKBOX_MASK_AUTOTHROTTLE) || global.state.altitudeHold) {
           if (global.estimatedDownVector[Z_INDEX]>FIXEDPOINTCONSTANT(.3)) {
               // Divide the throttle by the throttleOutput by the z component of the down vector
               // This is probaly the slow way, but it's a way to do fixed point division
               fixedpointnum recriprocal=lib_fp_invsqrt(global.estimatedDownVector[Z_INDEX]);
               recriprocal=lib_fp_multiply(recriprocal,recriprocal);
         
               throttleOutput=lib_fp_multiply(throttleOutput-AUTOTHROTTLE_DEAD_AREA,recriprocal)+AUTOTHROTTLE_DEAD_AREA;
           }
       }
#endif

#ifndef NO_FAILSAFE
       // if we don't hear from the receiver for over a second, try to land safely
       if (lib_timers_gettimermicroseconds(global.failsafeTimer)>1000000L) {
           throttleOutput=FPFAILSAFEMOTOROUTPUT;

           // make sure we are level!
           angleError[ROLL_INDEX]=-global.currentEstimatedEulerAttitude[ROLL_INDEX];
           angleError[PITCH_INDEX]=-global.currentEstimatedEulerAttitude[PITCH_INDEX];
       }
#endif
        
       // calculate output values.  Output values will range from 0 to 1.0
       // calculate pid outputs based on our angleErrors as inputs
       fixedpointnum pidOutput[3];
      
       // Gain Scheduling essentialy modifies the gains depending on
       // throttle level. If GAIN_SCHEDULING_FACTOR is 1.0, it multiplies PID outputs by 1.5 when at full throttle,
       // 1.0 when at mid throttle, and .5 when at zero throttle.  This helps
       // eliminate the wobbles when decending at low throttle.
       fixedpointnum gainSchedulingMultiplier=lib_fp_multiply(throttleOutput-FIXEDPOINTCONSTANT(.5),FIXEDPOINTCONSTANT(GAIN_SCHEDULING_FACTOR))+FIXEDPOINTONE;
      
       for (int x=0;x<3;++x) {
           global.integratedAngleError[x]+=lib_fp_multiply(angleError[x],global.timesliver);
         
           // don't let the integrated error get too high (windup)
           lib_fp_constrain(&global.integratedAngleError[x],-INTEGRATED_ANGLE_ERROR_LIMIT,INTEGRATED_ANGLE_ERROR_LIMIT);
         
           // do the attitude pid
           pidOutput[x]=lib_fp_multiply(angleError[x],settings.pid_pgain[x])-lib_fp_multiply(global.gyrorate[x],settings.pid_dgain[x])+(lib_fp_multiply(global.integratedAngleError[x],settings.pid_igain[x])>>4);
            
           // add gain scheduling.
           pidOutput[x]=lib_fp_multiply(gainSchedulingMultiplier,pidOutput[x]);
       }

       lib_fp_constrain(&throttleOutput,0,FIXEDPOINTONE); // Keep throttle output between 0 and 1

       compute_mix(throttleOutput, pidOutput); // aircraft type dependent mixes
       
#if (NUM_SERVOS>0)
       // do not update servos during unarmed calibration of sensors which are sensitive to vibration
       if (global.state.armed || (!global.state.calibratingAccAndGyro)) write_servo_outputs();
#endif
       
       write_motor_outputs();
   }
コード例 #15
0
ファイル: vectors.cpp プロジェクト: brewpoo/multifly
void vector_cross_product(fixedpointnum *v1, fixedpointnum *v2, fixedpointnum *v3) {
    v3[X_INDEX]=lib_fp_multiply(v1[Y_INDEX],v2[Z_INDEX])-lib_fp_multiply(v1[Z_INDEX],v2[Y_INDEX]);
    v3[Y_INDEX]=lib_fp_multiply(v1[Z_INDEX],v2[X_INDEX])-lib_fp_multiply(v1[X_INDEX],v2[Z_INDEX]);
    v3[Z_INDEX]=lib_fp_multiply(v1[X_INDEX],v2[Y_INDEX])-lib_fp_multiply(v1[Y_INDEX],v2[X_INDEX]);
}
コード例 #16
0
ファイル: vectors.cpp プロジェクト: brewpoo/multifly
fixedpointnum vector_dot_product(fixedpointnum *v1, fixedpointnum *v2) {
    return(lib_fp_multiply(v1[0], v2[0])+lib_fp_multiply(v1[1], v2[1])+lib_fp_multiply(v1[2], v2[2]));
}
コード例 #17
0
            // This mode was just switched on. Use current position as reference by setting error to zero.
            accumulatedyawerror = 0;
        }
        // Accumulate yaw angle error
        accumulatedyawerror += lib_fp_multiply(lib_fp_multiply(global.rxvalues[YAWINDEX], maxyawrate) - filteredyawgyrorate, global.timesliver) >> TIMESLIVEREXTRASHIFT;
        // Make sure it does not get too high
        lib_fp_constrain180(&accumulatedyawerror);
        angleerror[YAWINDEX] = accumulatedyawerror;
    } else {
        // Normal mode: control yaw rate
        // Calculate yaw angle error since last update based on desired and actual yaw rate.
        // TIMESLIVEREXTRASHIFT is not used here, so this value is 256 times higher than expected.
        // This is OK because timesliver is very small, making the angle error during this time
        // also very small. Using the amplified result the same yaw PID control parameters can be used
        // for all modes (normal, compass and yaw hold).
        angleerror[YAWINDEX] = lib_fp_multiply(lib_fp_multiply(global.rxvalues[YAWINDEX], maxyawrate) - filteredyawgyrorate, global.timesliver);
    }

    // handle compass control
    if (global.activecheckboxitems & CHECKBOXMASKCOMPASS) {
        if (!(global.previousactivecheckboxitems & CHECKBOXMASKCOMPASS)) {      // we just switched into compass mode
            // reset the angle error to zero so that we don't yaw because of the switch
            desiredcompassheading = global.currentestimatedeulerattitude[YAWINDEX];
        }
        // the compass holds only when right side up with throttle up (not sitting on the ground)
        // and the yaw stick is centered.  If it is centered, override the pilot's input
        if (global.estimateddownvector[ZINDEX] > 0 && global.rxvalues[THROTTLEINDEX] > FPSTICKLOW && global.rxvalues[YAWINDEX] > -YAWCOMPASSRXDEADBAND && global.rxvalues[YAWINDEX] < YAWCOMPASSRXDEADBAND) {
            angleerror[YAWINDEX] = desiredcompassheading - global.currentestimatedeulerattitude[YAWINDEX];
            lib_fp_constrain180(&angleerror[YAWINDEX]);
        } else                  // the pilot is controlling yaw, so update the desired heading
            desiredcompassheading = global.currentestimatedeulerattitude[YAWINDEX];