PX4 Firmware
PX4 Autopilot Software http://px4.io
flow.cpp
Go to the documentation of this file.
1 #include "../BlockLocalPositionEstimator.hpp"
3 #include <matrix/math.hpp>
4 
5 // mavlink pub
7 
8 // required number of samples for sensor
9 // to initialize
10 static const uint32_t REQ_FLOW_INIT_COUNT = 10;
11 static const uint32_t FLOW_TIMEOUT = 1000000; // 1 s
12 
14 {
15  // measure
17 
18  if (flowMeasure(y) != OK) {
20  return;
21  }
22 
23  // if finished
25  mavlink_and_console_log_info(&mavlink_log_pub, "[lpe] flow init: "
26  "quality %d std %d",
27  int(_flowQStats.getMean()(0)),
28  int(_flowQStats.getStdDev()(0)));
31  }
32 }
33 
35 {
37 
38  // check for sane pitch/roll
39  if (euler.phi() > 0.5f || euler.theta() > 0.5f) {
40  return -1;
41  }
42 
43  // check for agl
45  return -1;
46  }
47 
48  // check quality
49  float qual = _sub_flow.get().quality;
50 
51  if (qual < _param_lpe_flw_qmin.get()) {
52  return -1;
53  }
54 
55  // calculate range to center of image for flow
56  if (!(_estimatorInitialized & EST_TZ)) {
57  return -1;
58  }
59 
60  float d = agl() * cosf(euler.phi()) * cosf(euler.theta());
61 
62  // optical flow in x, y axis
63  // TODO consider making flow scale a states of the kalman filter
64  float flow_x_rad = _sub_flow.get().pixel_flow_x_integral * _param_lpe_flw_scale.get();
65  float flow_y_rad = _sub_flow.get().pixel_flow_y_integral * _param_lpe_flw_scale.get();
66  float dt_flow = _sub_flow.get().integration_timespan / 1.0e6f;
67 
68  if (dt_flow > 0.5f || dt_flow < 1.0e-6f) {
69  return -1;
70  }
71 
72  // angular rotation in x, y axis
73  float gyro_x_rad = 0;
74  float gyro_y_rad = 0;
75 
76  if (_param_lpe_fusion.get() & FUSE_FLOW_GYRO_COMP) {
77  gyro_x_rad = _flow_gyro_x_high_pass.update(
79  gyro_y_rad = _flow_gyro_y_high_pass.update(
81  }
82 
83  //warnx("flow x: %10.4f y: %10.4f gyro_x: %10.4f gyro_y: %10.4f d: %10.4f",
84  //double(flow_x_rad), double(flow_y_rad), double(gyro_x_rad), double(gyro_y_rad), double(d));
85 
86  // compute velocities in body frame using ground distance
87  // note that the integral rates in the optical_flow uORB topic are RH rotations about body axes
88  Vector3f delta_b(
89  +(flow_y_rad - gyro_y_rad) * d,
90  -(flow_x_rad - gyro_x_rad) * d,
91  0);
92 
93  // rotation of flow from body to nav frame
94  Vector3f delta_n = _R_att * delta_b;
95 
96  // imporant to timestamp flow even if distance is bad
98 
99  // measurement
100  y(Y_flow_vx) = delta_n(0) / dt_flow;
101  y(Y_flow_vy) = delta_n(1) / dt_flow;
102 
104 
105  return OK;
106 }
107 
109 {
110  // measure flow
112 
113  if (flowMeasure(y) != OK) { return; }
114 
115  // flow measurement matrix and noise matrix
117  C.setZero();
118  C(Y_flow_vx, X_vx) = 1;
119  C(Y_flow_vy, X_vy) = 1;
120 
122  R.setZero();
123 
124  // polynomial noise model, found using least squares fit
125  // h, h**2, v, v*h, v*h**2
126  const float p[5] = {0.04005232f, -0.00656446f, -0.26265873f, 0.13686658f, -0.00397357f};
127 
128  // prevent extrapolation past end of polynomial fit by bounding independent variables
129  float h = agl();
130  float v = y.norm();
131  const float h_min = 2.0f;
132  const float h_max = 8.0f;
133  const float v_min = 0.5f;
134  const float v_max = 1.0f;
135 
136  if (h > h_max) {
137  h = h_max;
138  }
139 
140  if (h < h_min) {
141  h = h_min;
142  }
143 
144  if (v > v_max) {
145  v = v_max;
146  }
147 
148  if (v < v_min) {
149  v = v_min;
150  }
151 
152  // compute polynomial value
153  float flow_vxy_stddev = p[0] * h + p[1] * h * h + p[2] * v + p[3] * v * h + p[4] * v * h * h;
154 
155  const Vector3f rates{_sub_angular_velocity.get().xyz};
156  float rotrate_sq = rates(0) * rates(0)
157  + rates(1) * rates(1)
158  + rates(2) * rates(2);
159 
161  float rot_sq = euler.phi() * euler.phi() + euler.theta() * euler.theta();
162 
163  R(Y_flow_vx, Y_flow_vx) = flow_vxy_stddev * flow_vxy_stddev +
164  _param_lpe_flw_r.get() * _param_lpe_flw_r.get() * rot_sq +
165  _param_lpe_flw_rr.get() * _param_lpe_flw_rr.get() * rotrate_sq;
167 
168  // residual
169  Vector<float, 2> r = y - C * _x;
170 
171  // residual covariance
173 
174  // publish innovations
175  _pub_innov.get().flow_innov[0] = r(0);
176  _pub_innov.get().flow_innov[1] = r(1);
177  _pub_innov.get().flow_innov_var[0] = S(0, 0);
178  _pub_innov.get().flow_innov_var[1] = S(1, 1);
179 
180  // residual covariance, (inverse)
181  Matrix<float, n_y_flow, n_y_flow> S_I = inv<float, n_y_flow>(S);
182 
183  // fault detection
184  float beta = (r.transpose() * (S_I * r))(0, 0);
185 
186  if (beta > BETA_TABLE[n_y_flow]) {
187  if (!(_sensorFault & SENSOR_FLOW)) {
188  mavlink_and_console_log_info(&mavlink_log_pub, "[lpe] flow fault, beta %5.2f", double(beta));
190  }
191 
192  } else if (_sensorFault & SENSOR_FLOW) {
193  _sensorFault &= ~SENSOR_FLOW;
195  }
196 
197  if (!(_sensorFault & SENSOR_FLOW)) {
199  m_P * C.transpose() * S_I;
200  Vector<float, n_x> dx = K * r;
201  _x += dx;
202  m_P -= K * C * m_P;
203  }
204 }
205 
207 {
209  if (!(_sensorTimeout & SENSOR_FLOW)) {
211  _flowQStats.reset();
212  mavlink_log_critical(&mavlink_log_pub, "[lpe] flow timeout ");
213  }
214  }
215 }
orb_advert_t mavlink_log_pub
static const float BETA_TABLE[7]
static const uint32_t REQ_FLOW_INIT_COUNT
Definition: flow.cpp:10
Type theta() const
Definition: Euler.hpp:132
float gyro_x_rate_integral
Definition: optical_flow.h:56
matrix::Vector< Type, M > getMean()
Definition: BlockStats.hpp:85
float pixel_flow_y_integral
Definition: optical_flow.h:55
uORB::SubscriptionData< optical_flow_s > _sub_flow
static const uint32_t FLOW_TIMEOUT
Definition: flow.cpp:11
uORB::SubscriptionData< vehicle_angular_velocity_s > _sub_angular_velocity
float min_ground_distance
Definition: optical_flow.h:63
float pixel_flow_x_integral
Definition: optical_flow.h:54
Type phi() const
Definition: Euler.hpp:128
Quaternion class.
Definition: Dcm.hpp:24
Matrix< Type, N, M > transpose() const
Definition: Matrix.hpp:353
uORB::SubscriptionData< vehicle_attitude_s > _sub_att
Scalar< float > Scalarf
Definition: Scalar.hpp:53
float update(float input)
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
int flowMeasure(Vector< float, n_y_flow > &y)
Definition: flow.cpp:34
Euler angles class.
Definition: AxisAngle.hpp:18
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
const T & get() const
matrix::Vector< Type, M > getStdDev()
Definition: BlockStats.hpp:90
uint32_t integration_timespan
Definition: optical_flow.h:60
#define OK
Definition: uavcan_main.cpp:71
Type norm() const
Definition: Vector.hpp:73
void setZero()
Definition: Matrix.hpp:416
float gyro_y_rate_integral
Definition: optical_flow.h:57
uORB::PublicationData< ekf2_innovations_s > _pub_innov
uint8_t quality
Definition: optical_flow.h:68
void update(const matrix::Vector< Type, M > &u)
Definition: BlockStats.hpp:71