Upload
patrick-crawford
View
218
Download
1
Embed Size (px)
Citation preview
Overview• Background• Risk Management• Final Design• Algorithms
– Stability– Optical Flow– Servo / Sensor ISR Code
• Progress to Date• Current Budget• Deliverables
Background• Project goal: Autonomous flying helicopter
• Onboard vision processing (Beagleboard)
• Stabilizing flight controller (Arduino)
• Extendable guidance interface
Risk Management• Limited budget, no room for malfunction
– Flight tether system has been developed– Extra caution taken when performing tests
• Limited precision of sensors can make flight algorithms unstable– Camera provides a secondary guidance
source. Sensors are low-pass filtered
• 6-channel RC helicopter– 4 servos are manipulated to control helicopter
• Layered guidance architecture– HelicopterArduinoBeagleboardBase Station
• Hardware– Servos: PWM controller, 45.5hz, interrupt– Sensors: Analog signal, interrupt (300mV/g)
(3.33mV·s/deg)– PWM interrupts override ADC interrupts, ensures
smooth servo motion
Final Design
Servo Manipulation• Take three points (120° apart) on a
circle and calculate their new location based off of rotations
void leftRoll(int amount){
int val1, val2;
val1 = incPulse( servoAil.read(), amount);
val2 = incPulse( servoAux.read(), amount);
servoAil.write(val1);
servoAux.write(val2); }
void forwardElevation(int amount){
int val1, val2, val3;
val1 = incPulse( servoEle.read(), amount);
val2 = decPulse( servoAil.read(), amount/2);
val3 = incPulse( servoAux.read(), amount/2);
servoEle.write(val1);
servoAil.write(val2);
servoAux.write(val3); }
void bladePitchUp(int amount){
int val1, val2, val3;
val1 = decPulse( servoAil.read(), amount);
val2 = incPulse( servoAux.read(), amount);
val3 = decPulse( servoEle.read(), amount);
servoAil.write(val1);
servoAux.write(val2);
servoEle.write(val3); }
Algorithms - Stability
Elevator vs. Throttle
0.000
0.500
1.000
1.500
2.000
2.500
0.000 2.000 4.000
Throttle servo pos width (ms)
Ele
vato
r se
rvo
po
s w
idth
(m
s)
max (ms)
neut (ms)
min (ms)
Aileron vs. Throttle
0.000
0.500
1.000
1.500
2.000
2.500
0.000 2.000 4.000
Throttle servo pos width (ms)
Ele
vato
r se
rvo
po
s w
idth
(m
s)
min (ms)
max (ms)
neut (ms)
AUX vs. Throttle
0.000
0.500
1.000
1.500
2.000
2.500
0.000 2.000 4.000
Throttle servo pos width (ms)
Ele
vato
r se
rvo
po
s w
idth
(m
s)
min (ms)
max (ms)
neut (ms)
• Depending on orientation readings, a combination of previous functions are called to keep helicopter stable
• Motion (forward, sideways) will change an offset value in the “stable” orientation – PID Controller
Optical Flow• Optical flow method used is based on Lucas-
Kanade optical flow• Uses Shi-Tomasi corner detection for finding
features• Three assumptions:
– Motion is Small– Pixel intensity is constant– Local flow is constant
• Using a 30fps camera will allow good estimation of motion
Optical Flow• Three steps
– Obtain two temporally separated frames
– Find features (corners) in the first image
– Use Lucas-Kanadeto calculate flow field
• Shi-Tomasi FeaturescvGoodFeaturesToTrack(frame1_1C, eig_image, temp_image, frame1_features, &number_of_features, 0.01, 0.01, NULL, 7, 7, 0);
• Lucas-Kanade Opt. FlowcvCalcOpticalFlowPyrLK(frame1_1C, frame2_1C, pyramid1,
pyramid2, frame1_features, frame2_features, number_of_features, optical_flow_window, 5, optical_flow_found_feature, optical_flow_feature_error, optical_flow_termination_criteria, 0 );
Servo Control ISR CodeInterrupt Vector Function
ISR (TIMER2_OVF_vect){
++ISRCount; // increment the overlflow counter
if (ISRCount == servos[Channel].counter ) { // are we on the final iteration for this channel
TCNT2 = servos[Channel].remainder; // yes, set count for overflow after remainder ticks
}
else if(ISRCount > servos[Channel].counter){
// we have finished timing the channel so pulse it low and move on
if(servos[Channel].Pin.isActive == true) // check if activated
digitalWrite( servos[Channel].Pin.nbr,LOW); // pulse this channel low if active
Channel++; // increment to the next channel
ISRCount = 0; // reset the isr iteration counter
TCNT2 = 0; // reset the clock counter register
if( (Channel != FRAME_SYNC_INDEX) && (Channel <= NBR_CHANNELS) ){ // check if we need to pulse this channel
if(servos[Channel].Pin.isActive == true) // check if activated
digitalWrite( servos[Channel].Pin.nbr,HIGH); // its an active channel so pulse it high
}
else if(Channel > NBR_CHANNELS){
Channel = 0; // all done so start over
} } }
Write Out to Servo Function
static void writeChan(uint8_t chan, int pulsewidth)
{
if( (chan > 0) && (chan <= NBR_CHANNELS) ) // ensure channel is valid {
if( pulsewidth < MIN_PULSE_WIDTH ) // ensure pulse width is valid
pulsewidth = MIN_PULSE_WIDTH;
else if( pulsewidth > MAX_PULSE_WIDTH )
pulsewidth = MAX_PULSE_WIDTH;
pulsewidth -=DELAY_ADJUST; // subtract the time it takes to process the start and end pulses (mostly from digitalWrite)
servos[chan].counter = pulsewidth / 128;
servos[chan].remainder = 255 - (2 * (pulsewidth - ( servos[chan].counter * 128))); // the number of 0.5us ticks for timer overflow
}}
Sensor ISR CodeInterrupt Vector FunctionISR(ADC_vect){ switch(channel){ case 0b00000001: totalZ += ((ADCL) | ((ADCH)<<8)); set(ADMUX, MUX0); channel<<=1; break;…case 0b00000100: totalY += ((ADCL) | ((ADCH)<<8)); set(ADMUX, MUX0); channel<<=1; break; case 0b00001000: totalGyroY += ((ADCL) | ((ADCH)<<8)); clr(ADMUX, MUX0); clr(ADMUX, MUX1); set(ADMUX, MUX2); channel<<=1; break; case 0b00001000:
totalGyroYArray[3] = totalGyroYArray[2];
totalGyroYArray[2] = totalGyroYArray[1];
totalGyroYArray[1] = totalGyroYArray[0];
totalGyroYArray[0] = ((ADCL) | ((ADCH)<<8));
totalGyroY = totalGyroY + 0.1666*totalGyroYArray[0] + 0.3333*totalGyroYArray[1] + 0.3333*totalGyroYArray[2] + 0.1666*totalGyroYArray[3];
channel<<=1;
break; …
default: channel = 0b00000001; // bad state restart break; }
• Interrupt driven code guarantees us fresh data at 333kHz
• Gyros are integrated using the Runge-Kutta– Achieves the effect of low pass
filtering.
Safety Tether• New design consists of a 35° swivel
ball joint – Allows for safer testing of stability code
Component Proposed Expenditure Current Expenditure Difference
Electrical
Beagleboard Microcontroller $150 $158.21 $8.21
Arduino Microcontroller - $20.10 $20.10
LAN USB Adapter $50 - -
USB Hub $5 In-Kind ($5.00)
Voltage Regulators - In-Kind -
SD Card - In-Kind -
Multiplexers - $10.88 $10.88
Helicopter
Blade 400 3D Helicopter $470 $489.99 $19.99
Replacement Blade $15 $13.99 ($1.01)
Tail Rotor Shaft $15 $5.49 ($9.51)
Sensors
2.0MP Camera $100 - -
IMU 6DOF Acc/Gyro $90 $95.43 $5.43
GPS Controller $90 $63.60 ($26.40)
IR Sensors x 2 - In-Kind -
Other
Webhosting $8 $8 -
Presentation Materials $100 - -
Programming Cable - $22.66 $22.66
Pins - In-Kind -
PSU - In-Kind -
Shipping - $43.81 $43.81
Taxes $30 $86.64 $56.64
Total $1,123 $1018.80 $145.80
Currently $145.80 Over Proposed Expenditure Available Funds: $1400 Buffer Fund Left: $131.20