download infrared.c
Language: C
License: GPL
Copyright: (C) 2003 Pascal Brisset, Antoine Drouin
LOC: 221
Project Info
paparazzi
Server: Savannah NonGNU
Type: cvs
...zzi\paparazzi3\sw\airborne\
   3dmg.c
   3dmg.h
   actuators.c
   actuators.h
   adc.h
   adc_generic.c
   adc_generic.h
   ahrs.c
   ahrs.h
   ahrs_new.c
   ahrs_new.h
   anemotaxis.c
   anemotaxis.h
   ap_downlink.h
   autopilot.h
   bomb.c
   bomb.h
   cam.c
   cam.h
   cam_roll.c
   cam_roll.h
   chemo_detect.c
   chemo_detect.h
   chemotaxis.c
   chemotaxis.h
   commands.c
   commands.h
   control_grz.c
   control_grz.h
   datalink.c
   datalink.h
   dc.c
   dc.h
   discsurvey.c
   discsurvey.h
   downlink.c
   downlink.h
   dpicco.c
   dpicco.h
   enose.c
   enose.h
   estimator.c
   estimator.h
   fbw_downlink.h
   frames.h
   fw_h_ctl.c
   fw_h_ctl.h
   fw_v_ctl.c
   fw_v_ctl.h
   gps.c
   gps.h
   gps_ubx.c
   gps_ubx.h
   gyro.c
   gyro.h
   i2c.c
   i2c.h
   imu.c
   imu.h
   imu_v3.c
   imu_v3.h
   infrared.c
   infrared.h
   inter_mcu.c
   inter_mcu.h
   latlong.c
   latlong.h
   led.h
   link_imu.c
   link_imu.h
   link_mcu.c
   link_mcu.h
   main.c
   main_antenna.c
   main_ap.c
   main_ap.h
   main_demo1.c
   main_demo2.c
   main_demo3.c
   main_demo4.c
   main_demo5.c
   main_demo6.c
   main_fbw.c
   main_fbw.h
   main_grz.c
   main_imu.c
   main_motor_bench.c
   modem.h
   nav.c
   nav.h
   nav_line.c
   nav_line.h
   nav_survey_rectangle.c
   nav_survey_rectangle.h
   paparazzi.h
   point.c
   point.h
   ppm.h
   pprz_transport.c
   pprz_transport.h
   print.h
   radio_control.c
   radio_control.h
   rc_settings.c
   rc_settings.h
   setup_actuators.c
   spi.c
   spi.h
   srf08.c
   srf08.h
   sys_time.c
   sys_time.h
   test_adcs.c
   traffic_info.c
   traffic_info.h
   uart.h
   usb_serial.h
   wavecard.c
   wavecard.h
   xbee.c
   xbee.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/*
 * Paparazzi mcu0 $Id: infrared.c,v 1.28 2007/01/27 00:38:29 poine Exp $
 *  
 * Copyright (C) 2003  Pascal Brisset, Antoine Drouin
 *
 * This file is part of paparazzi.
 *
 * paparazzi is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * paparazzi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with paparazzi; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA. 
 *
 */
/** \file infrared.c
 *  \brief Regroup all functions link to \a ir
 */

#include <stdlib.h>

#include "adc.h"
#include "infrared.h"
#include "gps.h"
#include "autopilot.h"
#include "estimator.h"
#include "ap_downlink.h"
#include "sys_time.h"
#include "airframe.h"

int16_t ir_roll;
int16_t ir_pitch;
int16_t ir_top;

float z_contrast_mode;

float ir_roll_neutral;
float ir_pitch_neutral;

bool_t ir_360;
float ir_estimated_phi_pi_4, ir_estimated_phi_minus_pi_4;
float ir_estimated_theta_pi_4, ir_estimated_theta_minus_pi_4;

#ifndef IR_ESTIMATED_PHI_PI_4
#define IR_ESTIMATED_PHI_PI_4 M_PI_4
#endif

#ifndef IR_ESTIMATED_PHI_MINUS_PI_4
#define IR_ESTIMATED_PHI_MINUS_PI_4 IR_ESTIMATED_PHI_PI_4
#endif

#ifndef IR_ESTIMATED_THETA_PI_4
#define IR_ESTIMATED_THETA_PI_4 IR_ESTIMATED_PHI_PI_4
#endif

#ifndef IR_ESTIMATED_THETA_MINUS_PI_4
#define IR_ESTIMATED_THETA_MINUS_PI_4 IR_ESTIMATED_THETA_PI_4
#endif


#if defined IR_CORRECTION_LEFT && defined IR_CORRECTION_RIGHT
float ir_correction_left;
float ir_correction_right;
#endif

#if defined IR_CORRECTION_UP && defined IR_CORRECTION_DOWN
float ir_correction_up;
float ir_correction_down;
#endif

/** Initialized to \a IR_DEFAULT_CONTRAST. Changed with calibration */
int16_t ir_contrast;
/** Initialized to \a IR_DEFAULT_CONTRAST.
 *  Changed with @@@@@ EST-CE QUE CA CHANGE @@@@@ */

/** \def RadOfIrFromContrast(c)
 *  \brief Contrast measurement
 *  \note <b>Plane must be nose down !</b>
 */
#define RadOfIrFromContrast(c) ir_rad_of_ir = IR_RAD_OF_IR_CONTRAST / c;

/** rad_of_ir variable factor: let convert \a ir value in radian.
 *  Initialized with airframe \a IR_RAD_OF_IR_CONTRAST and \a IR_DEFAULT_CONTRAST constants. \n
 *  Change when \a lls work.
 */
float ir_rad_of_ir;

float estimator_rad_of_ir, estimator_ir, estimator_rad;

static struct adc_buf buf_ir1;
static struct adc_buf buf_ir2;
#ifdef ADC_CHANNEL_IR_TOP
static struct adc_buf buf_ir_top;
#endif

#ifndef ADC_CHANNEL_IR_NB_SAMPLES
#define ADC_CHANNEL_IR_NB_SAMPLES DEFAULT_AV_NB_SAMPLE
#endif

#ifndef Z_CONTRAST_DEFAULT
#define Z_CONTRAST_DEFAULT 1
#endif
#ifdef Z_CONTRAST_START
#warning "Z_CONTRAST_START deprecated !! z_contrast mode now defaults to Z_CONTRAST_DEFAULT or 1"
#endif



/** \brief Initialisation of \a ir */
/** Initialize \a ir with the \a IR_DEFAULT_CONTRAST \n
 *  Initialize \a adc_buf_channel
 */
void ir_init(void) {
  RadOfIrFromContrast(IR_DEFAULT_CONTRAST);
  adc_buf_channel(ADC_CHANNEL_IR1, &buf_ir1, ADC_CHANNEL_IR_NB_SAMPLES);
  adc_buf_channel(ADC_CHANNEL_IR2, &buf_ir2, ADC_CHANNEL_IR_NB_SAMPLES);
#ifdef ADC_CHANNEL_IR_TOP
  adc_buf_channel(ADC_CHANNEL_IR_TOP, &buf_ir_top, ADC_CHANNEL_IR_NB_SAMPLES);
  z_contrast_mode = Z_CONTRAST_DEFAULT;
#else
  z_contrast_mode = 0;
#endif
 
  ir_roll_neutral  = RadOfDeg(IR_ROLL_NEUTRAL_DEFAULT);
  ir_pitch_neutral = RadOfDeg(IR_PITCH_NEUTRAL_DEFAULT);

  estimator_rad_of_ir = ir_rad_of_ir;

#if defined IR_CORRECTION_LEFT && defined IR_CORRECTION_RIGHT
  ir_correction_left = IR_CORRECTION_LEFT;
  ir_correction_right = IR_CORRECTION_RIGHT;
#endif

#if defined IR_CORRECTION_UP && defined IR_CORRECTION_DOWN
  ir_correction_up = IR_CORRECTION_UP;
  ir_correction_down = IR_CORRECTION_DOWN;
#endif

  ir_360 = TRUE;
  ir_estimated_phi_pi_4 = IR_ESTIMATED_PHI_PI_4;
  ir_estimated_phi_minus_pi_4 = IR_ESTIMATED_PHI_MINUS_PI_4;
  ir_estimated_theta_pi_4 = IR_ESTIMATED_THETA_PI_4;
  ir_estimated_theta_minus_pi_4 = IR_ESTIMATED_THETA_MINUS_PI_4;

  ir_contrast = IR_DEFAULT_CONTRAST;
  ir_rad_of_ir = IR_RAD_OF_IR_CONTRAST / IR_DEFAULT_CONTRAST;
}

/** \brief Update \a ir_roll and ir_pitch from ADCs or from simulator
 * message in HITL and SITL modes
 */
void ir_update(void) {
#if ! (defined SITL || defined HITL)
  int16_t x1_mean = buf_ir1.sum/buf_ir1.av_nb_sample;
  int16_t x2_mean = buf_ir2.sum/buf_ir2.av_nb_sample;
  ir_roll = IR_RollOfIrs(x1_mean, x2_mean);
  ir_pitch = IR_PitchOfIrs(x1_mean, x2_mean);
#ifdef ADC_CHANNEL_IR_TOP
  ir_top =  IR_TopOfIr(buf_ir_top.sum/buf_ir_top.av_nb_sample - IR_ADC_TOP_NEUTRAL);
#endif

  /** neutrals are not taken into account in SITL and HITL */
  ir_roll -= IR_ADC_ROLL_NEUTRAL;
  ir_pitch -= IR_ADC_PITCH_NEUTRAL;
#endif /* !SITL && !HITL */
/** #else ir_roll set by simulator in sim_ir.c */
}

/** \brief Contrast measurement
 *  \note <b>Plane must be nose down !</b>
 */
static void ir_gain_calib(void) {
  /* plane nose down -> negativ value */
  ir_contrast = abs(ir_pitch);
  RadOfIrFromContrast(ir_contrast);
}

/** Maximal delay waits before calibration.
		After, no more calibration is possible */
#define MAX_DELAY_FOR_CALIBRATION 10

uint8_t calib_status = NO_CALIB;

/** \brief Calibrate contrast if paparazzi mode is
 * set to auto1 before MAX_DELAY_FOR_CALIBRATION secondes */
/**User must put verticaly the uav (nose bottom) and push
 * radio roll stick to get new calibration
 * If not, the default calibration is used.
 */
void ground_calibrate( bool_t triggered ) {
  switch (calib_status) {
  case NO_CALIB:
    if (cpu_time_sec < MAX_DELAY_FOR_CALIBRATION && pprz_mode == PPRZ_MODE_AUTO1 ) {
      calib_status = WAITING_CALIB_CONTRAST;
      DOWNLINK_SEND_CALIB_START();
    }
    break;
  case WAITING_CALIB_CONTRAST:
    if (triggered) {
      ir_gain_calib();
      estimator_rad_of_ir = ir_rad_of_ir;
      calib_status = CALIB_DONE;
      DOWNLINK_SEND_CALIB_CONTRAST(&ir_contrast);
    }
    break;
  case CALIB_DONE:
    break;
  }
}

#define INIT_WEIGHT 100. /* The number of times the initial value has to be taken */
#define RHO 0.995 /* The higher, the slower the estimation is changing */

#define G 9.81

void estimator_update_ir_estim( void ) {
  static float last_hspeed_dir;
  static uint32_t last_t; /* ms */
  static bool_t initialized = FALSE;
  static float sum_xy, sum_xx;

  if (initialized) {
    float dt = (float)(gps_itow - last_t) / 1e3;
    if (dt > 0.1) { // Against division by zero
      float dpsi = (estimator_hspeed_dir - last_hspeed_dir); 
      NormRadAngle(dpsi);
      estimator_rad = dpsi/dt*NOMINAL_AIRSPEED/G; /* tan linearized */
      NormRadAngle(estimator_rad);
      estimator_ir = (float)ir_roll;
      float absphi = fabs(estimator_rad);
      if (absphi < 1.0 && absphi > 0.05 && (- ir_contrast/2 < ir_roll && ir_roll < ir_contrast/2)) {
	sum_xy = estimator_rad * estimator_ir + RHO * sum_xy;
	sum_xx = estimator_ir * estimator_ir + RHO * sum_xx;
#if defined IR_RAD_OF_IR_MIN_VALUE & defined IR_RAD_OF_IR_MAX_VALUE
	float result = sum_xy / sum_xx;
	if (result < IR_RAD_OF_IR_MIN_VALUE)
	  estimator_rad_of_ir = IR_RAD_OF_IR_MIN_VALUE;
	else if (result > IR_RAD_OF_IR_MAX_VALUE)
	  estimator_rad_of_ir = IR_RAD_OF_IR_MAX_VALUE;
	else
	  estimator_rad_of_ir = result;
#else
	  estimator_rad_of_ir = sum_xy / sum_xx;
#endif
      }
    } 
  } else {
    initialized = TRUE;
    float init_ir2 = ir_contrast;
    init_ir2 = init_ir2*init_ir2;
    sum_xy = INIT_WEIGHT * estimator_rad_of_ir * init_ir2;
    sum_xx = INIT_WEIGHT * init_ir2;
  }

  last_hspeed_dir = estimator_hspeed_dir;
  last_t = gps_itow;
}


/* Correction of the infrared estimation roll angle: returns pi/4 for
   est_pi_4 */
static inline float correct_angle(float m_angle, float est_pi_4, float est_minus_pi_4) {
  if (m_angle >= 0 && m_angle < est_pi_4) 
    /* 0 .. est_pi_4 */
    return (m_angle * M_PI_4 / est_pi_4);
  else if (m_angle > M_PI - est_pi_4)
    /* pi-est_pi_4 .. pi */
    return (m_angle - (M_PI - est_pi_4))* M_PI_4 / est_pi_4 + 3*M_PI_4;
  else if (m_angle >= est_pi_4)
    /* est_pi_4 .. pi-est_pi_4 */
    return (m_angle - est_pi_4) * M_PI_4 / (M_PI_2 - est_pi_4) + M_PI_4;
  else if (m_angle <= 0 && m_angle > -est_minus_pi_4) 
    /* -est_pi_4 .. 0 */
    return (m_angle * M_PI_4 / est_minus_pi_4);
  else if (m_angle < - (M_PI - est_minus_pi_4))
    /* -pi .. -(pi-est_pi_4) */
    return (m_angle + M_PI)* M_PI_4 / est_minus_pi_4 + -M_PI;
  else
    /* -(pi-est_pi_4) .. -est_pi_4 */
    return (m_angle - (-M_PI+est_minus_pi_4)) * M_PI_4 / (M_PI_2 - est_minus_pi_4) - 3 * M_PI_4;
}





void estimator_update_state_infrared( void ) {
  float rad_of_ir = (ir_estim_mode == IR_ESTIM_MODE_ON ? 
		     estimator_rad_of_ir :
		     ir_rad_of_ir);

#ifdef IR_360
  if (ir_360) { /* 360 estimation */
    /* 250 us for the whole block */
    float tmp_ir_roll = ir_roll * IR_360_LATERAL_CORRECTION;
    float tmp_ir_pitch = ir_pitch * IR_360_LONGITUDINAL_CORRECTION;
    float tmp_ir_top = ir_top * IR_360_VERTICAL_CORRECTION;

    estimator_phi  = atan2(tmp_ir_roll, tmp_ir_top) - ir_roll_neutral;
    estimator_phi = correct_angle(estimator_phi, ir_estimated_phi_pi_4, ir_estimated_phi_minus_pi_4);

    estimator_theta  = atan2(tmp_ir_pitch, tmp_ir_top) - ir_pitch_neutral;
    estimator_theta = correct_angle(estimator_theta, ir_estimated_theta_pi_4, ir_estimated_theta_minus_pi_4);
    if (estimator_theta < -M_PI_2)
      estimator_theta += M_PI;
    else if (estimator_theta > M_PI_2)
      estimator_theta -= M_PI;
  } else
#endif /* IR_360 */
  {
    ir_top = Max(ir_top, 1);
    float c = rad_of_ir*(1-z_contrast_mode)+z_contrast_mode*((float)IR_RAD_OF_IR_CONTRAST/fabs(ir_top));
    estimator_phi  = c * ir_roll - ir_roll_neutral;
    estimator_theta = c * ir_pitch - ir_pitch_neutral;
    
    
    
    /* infrared compensation */
#if defined IR_CORRECTION_LEFT && defined IR_CORRECTION_RIGHT
    if (estimator_phi >= 0) 
      estimator_phi *= ir_correction_right;
    else
      estimator_phi *= ir_correction_left;
#endif
    
    
#if defined IR_CORRECTION_UP && defined IR_CORRECTION_DOWN
    if (estimator_theta >= 0)
      estimator_theta *= ir_correction_up;
    else
      estimator_theta *= ir_correction_down;
#endif
    
    Bound(estimator_phi, -M_PI_2, M_PI_2);
    Bound(estimator_theta, -M_PI_2, M_PI_2);
    
 } 
}

About Koders | Resources | Downloads | Support | Black Duck | Submit Project | Terms of Service | DMCA | Privacy Policy | Site Map| Contact Us