Paparazzi UAS  v5.14.0_stable-0-g3f680d1
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
px4flow_i2c.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Gautier Hattenberger
3  * 2016 Michal Podhradsky <michal.podhradsky@aggiemail.usu.edu>
4  *
5  * This file is part of paparazzi.
6  *
7  * paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, write to
19  * the Free Software Foundation, 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  */
23 
31 #include "subsystems/abi.h"
32 #include "filters/median_filter.h"
33 
34 // State interface for rotation compensation
35 #include "state.h"
36 
37 // Messages
38 #include "pprzlink/messages.h"
40 
41 /*
42  * acceptable quality of optical flow (0-min,1-max)
43  * higher threshold means fewer measurements will be available
44  * but they will be more precise. Generally it is probably a better
45  * idea to have lower threshold, and propagate the noise (1-quality)
46  * to the INS
47  */
48 #ifndef PX4FLOW_QUALITY_THRESHOLD
49 #define PX4FLOW_QUALITY_THRESHOLD 0.1
50 #endif
51 
53 
55 
56 #define PX4FLOW_I2C_FRAME 0x0
57 #define PX4FLOW_I2C_INTEGRAL_FRAME 0x16
58 #define PX4FLOW_I2C_FRAME_LENGTH 22
59 #define PX4FLOW_I2C_INTEGRAL_FRAME_LENGTH 25
60 #define PX4FLOW_I2C_ID 0x4D
61 
65 static inline void px4flow_i2c_frame_cb(void)
66 {
67  static float quality = 0;
68  static float noise = 0;
69  quality = ((float)px4flow.i2c_frame.qual) / 255.0;
70  noise = px4flow.stddev + (1 - quality) * px4flow.stddev * 10;
71  noise = noise * noise; // square the noise to get variance of the measurement
72 
73  static float timestamp = 0;
74  static uint32_t time_usec = 0;
75 
76  static float flow_comp_m_x = 0.0;
77  static float flow_comp_m_y = 0.0;
78 
79  if (quality > PX4FLOW_QUALITY_THRESHOLD) {
80  timestamp = get_sys_time_float();
81  time_usec = (uint32_t)(timestamp * 1e6);
82 
83  flow_comp_m_x = ((float)px4flow.i2c_frame.flow_comp_m_x) / 1000.0;
84  flow_comp_m_y = ((float)px4flow.i2c_frame.flow_comp_m_y) / 1000.0;
85 
86  // flip the axis (if the PX4FLOW is mounted as shown in
87  // https://pixhawk.org/modules/px4flow
88  AbiSendMsgVELOCITY_ESTIMATE(VEL_PX4FLOW_ID,
89  time_usec,
90  flow_comp_m_y,
91  flow_comp_m_x,
92  0.0f,
93  noise,
94  noise,
95  -1.f);
96  }
97 
98  // distance is always positive - use median filter to remove outliers
99  static int32_t ground_distance = 0;
100  static float ground_distance_float = 0.0;
101 
102  // update filter
104  ground_distance_float = ((float)ground_distance) / 1000.0;
105 
106  // compensate AGL measurement for body rotation
108  float phi = stateGetNedToBodyEulers_f()->phi;
109  float theta = stateGetNedToBodyEulers_f()->theta;
110  float gain = (float)fabs( (double) (cosf(phi) * cosf(theta)));
111  ground_distance_float = ground_distance_float / gain;
112  }
113 
114  if (px4flow.update_agl) {
115  AbiSendMsgAGL(AGL_SONAR_PX4FLOW_ID, ground_distance_float);
116  }
117 }
118 
119 
120 
124 static inline void px4flow_i2c_int_frame_cb(void)
125 {
126 
127 }
128 
129 
134 {
136  px4flow.addr = PX4FLOW_I2C_ADDR;
137 #if REQUEST_INT_FRAME
139 #else
141 #endif
142  px4flow.update_agl = USE_PX4FLOW_AGL;
143  px4flow.compensate_rotation = PX4FLOW_COMPENSATE_ROTATION;
144  px4flow.stddev = PX4FLOW_NOISE_STDDEV;
145 
146  init_median_filter_i(&sonar_filter, PX4FLOW_MEDIAN_LENGTH);
147 }
148 
155 {
156  switch (px4flow.status) {
157  case PX4FLOW_FRAME_REQ:
158  // ask for i2c frame
160  if (i2c_transceive(&PX4FLOW_I2C_DEV, &px4flow.trans, px4flow.addr, 1, PX4FLOW_I2C_FRAME_LENGTH)) {
161  // transaction OK, increment status
163  }
164  break;
165  case PX4FLOW_FRAME_REC:
166  // check if the transaction was successful
168  // retrieve data
169  uint8_t idx = 0;
171  idx += sizeof(uint16_t);
173  idx += sizeof(int16_t);
175  idx += sizeof(int16_t);
177  idx += sizeof(int16_t);
179  idx += sizeof(int16_t);
180  px4flow.i2c_frame.qual = (px4flow.trans.buf[idx + 1] << 8 | px4flow.trans.buf[idx]);
181  idx += sizeof(int16_t);
183  idx += sizeof(int16_t);
185  idx += sizeof(int16_t);
187  idx += sizeof(int16_t);
189  idx += sizeof(uint8_t);
191  idx += sizeof(uint8_t);
193 
194  // propagate measurements
196  }
197  // increment status
198  // ask for regular frame again
200  break;
202  // Send the command to begin a measurement.
204  if (i2c_transmit(&PX4FLOW_I2C_DEV, &px4flow.trans, px4flow.addr, 1)) {
205  // transaction OK, increment status
207  }
208  break;
210  // ask for integral frame
213  // transaction OK, increment status
215  }
216  break;
218  // check if the transaction was successful
220  // retrieve data
221  uint8_t idx = 0;
223  idx += sizeof(uint16_t);
225  idx += sizeof(int16_t);
227  idx += sizeof(uint16_t);
229  idx += sizeof(int16_t);
231  idx += sizeof(int16_t);
233  idx += sizeof(int16_t);
234  px4flow.i2c_int_frame.integration_timespan = (px4flow.trans.buf[idx + 3] << 24 | px4flow.trans.buf[idx + 2] << 16
235  | px4flow.trans.buf[idx + 1] << 8 | px4flow.trans.buf[idx]);
236  idx += sizeof(uint32_t);
237  px4flow.i2c_int_frame.sonar_timestamp = (px4flow.trans.buf[idx + 3] << 24 | px4flow.trans.buf[idx + 2] << 16
238  | px4flow.trans.buf[idx + 1] << 8 | px4flow.trans.buf[idx]);
239  idx += sizeof(uint32_t);
241  idx += sizeof(int16_t);
243  idx += sizeof(int16_t);
245 
246  // propagate measurements
248  }
249  // increment status
251  break;
252  default:
253  break;
254  }
255 }
256 
257 
258 
264 {
265  // Convert i2c_frame into PX4FLOW message
266  uint8_t id = PX4FLOW_I2C_ID;
267 
268  float timestamp = get_sys_time_float();
269 
270 #if REQUEST_INT_FRAME
273 
274  float flow_comp_m_x = 0.0;
275  float flow_comp_m_y = 0.0;
276 
277  uint8_t quality = px4flow.i2c_int_frame.qual;
278  float ground_distance = ((float)px4flow.i2c_int_frame.ground_distance) / 1000.0;
279 #else
282 
283  float flow_comp_m_x = ((float)px4flow.i2c_frame.flow_comp_m_x) / 1000.0;
284  float flow_comp_m_y = ((float)px4flow.i2c_frame.flow_comp_m_y) / 1000.0;
285 
286  uint8_t quality = px4flow.i2c_frame.qual;
287  float ground_distance = ((float)px4flow.i2c_frame.ground_distance) / 1000.0;
288 #endif
289 
290  DOWNLINK_SEND_PX4FLOW(DefaultChannel, DefaultDevice,
291  &timestamp,
292  &id,
293  &flow_x,
294  &flow_y,
295  &flow_comp_m_x,
296  &flow_comp_m_y,
297  &quality,
298  &ground_distance);
299 }
uint8_t addr
Definition: px4flow_i2c.h:80
unsigned short uint16_t
Definition: types.h:16
#define PX4FLOW_I2C_INTEGRAL_FRAME_LENGTH
Definition: px4flow_i2c.c:59
static uint32_t idx
int16_t gyro_x_rate
Definition: px4flow_i2c.h:52
float phi
in radians
int16_t flow_comp_m_y
Definition: px4flow_i2c.h:50
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
Definition: i2c.h:122
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition: state.h:1143
transaction successfully finished by I2C driver
Definition: i2c.h:57
int16_t pixel_flow_y_sum
Definition: px4flow_i2c.h:48
#define PX4FLOW_I2C_FRAME
Definition: px4flow_i2c.c:56
#define AGL_SONAR_PX4FLOW_ID
uint8_t gyro_range
Definition: px4flow_i2c.h:55
Main include for ABI (AirBorneInterface).
#define PX4FLOW_I2C_INTEGRAL_FRAME
Definition: px4flow_i2c.c:57
uint16_t frame_count_since_last_readout
Definition: px4flow_i2c.h:62
struct i2c_transaction trans
Definition: px4flow_i2c.h:79
static int32_t update_median_filter_i(struct MedianFilterInt *filter, int32_t new_data)
Definition: median_filter.h:68
static void px4flow_i2c_int_frame_cb(void)
Propagate itegral frame.
Definition: px4flow_i2c.c:124
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition: sys_time.h:129
#define PX4FLOW_I2C_ID
Definition: px4flow_i2c.c:60
int16_t gyro_y_rate
Definition: px4flow_i2c.h:53
void px4flow_i2c_init(void)
Initialization function.
Definition: px4flow_i2c.c:133
#define PX4FLOW_I2C_FRAME_LENGTH
Definition: px4flow_i2c.c:58
float theta
in radians
uint8_t sonar_timestamp
Definition: px4flow_i2c.h:56
float stddev
Definition: px4flow_i2c.h:81
transaction set to done by user level
Definition: i2c.h:59
unsigned long uint32_t
Definition: types.h:18
signed short int16_t
Definition: types.h:17
uint16_t frame_count
Definition: px4flow_i2c.h:46
enum Px4FlowStatus status
Definition: px4flow_i2c.h:82
struct px4flow_data px4flow
Definition: px4flow_i2c.c:52
bool i2c_transceive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len_w, uint16_t len_r)
Submit a write/read transaction.
Definition: i2c.c:280
enum I2CTransactionStatus status
Transaction status.
Definition: i2c.h:126
bool i2c_transmit(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len)
Submit a write only transaction.
Definition: i2c.c:260
signed long int32_t
Definition: types.h:19
static void px4flow_i2c_frame_cb(void)
Propagate optical flow information.
Definition: px4flow_i2c.c:65
bool update_agl
Definition: px4flow_i2c.h:83
#define VEL_PX4FLOW_ID
unsigned char uint8_t
Definition: types.h:14
API to get/set the generic vehicle states.
#define PX4FLOW_QUALITY_THRESHOLD
Definition: px4flow_i2c.c:49
static void init_median_filter_i(struct MedianFilterInt *filter, uint8_t size)
Definition: median_filter.h:39
int16_t flow_comp_m_x
Definition: px4flow_i2c.h:49
struct px4flow_i2c_frame i2c_frame
Definition: px4flow_i2c.h:77
int16_t ground_distance
Definition: px4flow_i2c.h:57
struct MedianFilterInt sonar_filter
Definition: px4flow_i2c.c:54
void px4flow_i2c_downlink(void)
Downlink message for debug Copy volatile variables from the px4_i2c_frame for safety.
Definition: px4flow_i2c.c:263
struct px4flow_i2c_integral_frame i2c_int_frame
Definition: px4flow_i2c.h:78
void px4flow_i2c_periodic(void)
Poll px4flow for data 152 i2c frames are created per second, so the PX4FLOW can be polled at up to 15...
Definition: px4flow_i2c.c:154
bool compensate_rotation
Definition: px4flow_i2c.h:84
int16_t gyro_z_rate
Definition: px4flow_i2c.h:54
int16_t pixel_flow_x_sum
Definition: px4flow_i2c.h:47