@@ -33,70 +33,44 @@ AP_OpticalFlow_MAV *AP_OpticalFlow_MAV::detect(AP_OpticalFlow &_frontend)
3333// read latest values from sensor and fill in x,y and totals.
3434void AP_OpticalFlow_MAV::update (void )
3535{
36- // gyroscope integration is not required for OPTICAL_FLOW_RAD
37- #if !AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
3836 // record gyro values as long as they are being used
3937 // the sanity check of dt below ensures old gyro values are not used
40- if (gyro_sum_count < 1000 ) {
38+ if (gyro_sum_count < 1000 ) {
4139 const Vector3f& gyro = AP::ahrs ().get_gyro ();
4240 gyro_sum.x += gyro.x ;
4341 gyro_sum.y += gyro.y ;
4442 gyro_sum_count++;
4543 }
46- #endif
4744
48- // return without updating state if no readings
49- if (count == 0 ) {
50- return ;
51- }
52-
53- struct AP_OpticalFlow ::OpticalFlow_state state {};
54-
55- state.surface_quality = quality_sum / count;
56-
57- // calculate dt
58- const float dt = (latest_frame_us - prev_frame_us) * 1.0e-6 ;
59- prev_frame_us = latest_frame_us;
60-
61- // sanity check dt
62- if (is_positive (dt) && (dt < OPTFLOW_MAV_TIMEOUT_SEC)) {
63- // calculate flow values
64- const float flow_scale_factor_x = 1 .0f + 0 .001f * _flowScaler ().x ;
65- const float flow_scale_factor_y = 1 .0f + 0 .001f * _flowScaler ().y ;
45+ struct AP_OpticalFlow ::OpticalFlow_state state{};
46+ if (count != 0 ) {
47+ // obtain data from OPTICAL_FLOW mavlink message
48+ state = update_msg_optical_flow ();
6649
67- // scale and copy flow rates to state structure
68- // if using flow_rates these are in rad/s (as opposed to pixels) and do not need to be multiplied by dt
69- const float dt_used = flow_sum_is_rads ? 1 .0f : dt;
70- state.flowRate = { ((float )flow_sum.x / count) * flow_scale_factor_x * dt_used,
71- ((float )flow_sum.y / count) * flow_scale_factor_y * dt_used };
72-
73- // copy body-rates from gyro or set to zero
74- if (option_is_enabled (Option::Stabilised)) {
75- // if the sensor is stabilised then body rates are always zero
76- state.bodyRate .zero ();
77- } else {
78- // copy average body rate to state structure
79- state.bodyRate = { gyro_sum.x / gyro_sum_count, gyro_sum.y / gyro_sum_count };
80- }
50+ // reset local variables for OPTICAL_FLOW
51+ flow_sum.zero ();
52+ quality_sum = 0 ;
53+ count = 0 ;
54+ gyro_sum.zero ();
55+ gyro_sum_count = 0 ;
56+ }
8157
82- // we only apply yaw to flowRate as body rate comes from AHRS
83- _applyYaw (state.flowRate );
84- } else {
85- // first frame received in some time so cannot calculate flow values
86- state.flowRate .zero ();
87- state.bodyRate .zero ();
58+ #ifdef AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
59+ if (count_rad != 0 && (quality_rad_sum / count_rad) > state.surface_quality ) {
60+ // state quality is better from OPTICAL_FLOW_RAD, so we can take it instead
61+ state = update_msg_optical_flow_rad ();
62+
63+ // reset local variables for OPTICAL_FLOW_RAD
64+ flow_rad_integral_sum.zero ();
65+ rate_gyro_rad_integral_sum.zero ();
66+ count_rad = 0 ;
67+ quality_rad_sum = 0 ;
68+ integration_time_sum_rad_us = 0 ;
8869 }
70+ #endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
8971
9072 _update_frontend (state);
9173
92- // reset local buffers
93- flow_sum.zero ();
94- quality_sum = 0 ;
95- count = 0 ;
96-
97- // reset gyro sum
98- gyro_sum.zero ();
99- gyro_sum_count = 0 ;
10074}
10175
10276// handle OPTICAL_FLOW mavlink messages
@@ -134,33 +108,91 @@ void AP_OpticalFlow_MAV::handle_msg(const mavlink_message_t &msg)
134108 sensor_id = packet.sensor_id ;
135109}
136110
111+ AP_OpticalFlow::OpticalFlow_state AP_OpticalFlow_MAV::update_msg_optical_flow ()
112+ {
113+ struct AP_OpticalFlow ::OpticalFlow_state state;
114+
115+ state.surface_quality = quality_sum / count;
116+
117+ // calculate dt
118+ const float dt = (latest_frame_us - prev_frame_us) * 1.0e-6 ;
119+ prev_frame_us = latest_frame_us;
120+
121+ // sanity check dt
122+ if (is_positive (dt) && (dt < OPTFLOW_MAV_TIMEOUT_SEC)) {
123+ // calculate flow values
124+ const float flow_scale_factor_x = 1 .0f + 0 .001f * _flowScaler ().x ;
125+ const float flow_scale_factor_y = 1 .0f + 0 .001f * _flowScaler ().y ;
126+
127+ // scale and copy flow rates to state structure
128+ // if using flow_rates these are in rad/s (as opposed to pixels) and do not need to be multiplied by dt
129+ const float dt_used = flow_sum_is_rads ? 1 .0f : dt;
130+ state.flowRate = { ((float )flow_sum.x / count) * flow_scale_factor_x * dt_used,
131+ ((float )flow_sum.y / count) * flow_scale_factor_y * dt_used };
132+
133+ // copy body-rates from gyro or set to zero
134+ if (option_is_enabled (Option::Stabilised)) {
135+ // if the sensor is stabilised then body rates are always zero
136+ state.bodyRate .zero ();
137+ } else {
138+ // copy average body rate to state structure
139+ state.bodyRate = { gyro_sum.x / gyro_sum_count, gyro_sum.y / gyro_sum_count };
140+ }
141+
142+ // we only apply yaw to flowRate as body rate comes from AHRS
143+ _applyYaw (state.flowRate );
144+ } else {
145+ // first frame received in some time so cannot calculate flow values
146+ state.flowRate .zero ();
147+ state.bodyRate .zero ();
148+ }
149+
150+ return state;
151+ }
152+
137153#if AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
138- void AP_OpticalFlow_MAV::handle_msg_rad (const mavlink_message_t &msg)
154+ void AP_OpticalFlow_MAV::handle_msg_optical_flow_rad (const mavlink_message_t &msg)
139155{
140156 mavlink_optical_flow_rad_t packet;
141157 mavlink_msg_optical_flow_rad_decode (&msg, &packet);
142158
143- // record time message was received
144- // TODO: dt between frames which is calculated in update state function
145- // is already stored in OPTICAL_FLOW_RAD message and can be taken from there
146- // instead of calculating it manually
147- latest_frame_us = AP_HAL::micros64 ();
159+ flow_rad_integral_sum.x += packet.integrated_x ;
160+ flow_rad_integral_sum.y += packet.integrated_y ;
161+
162+ rate_gyro_rad_integral_sum.x += packet.integrated_xgyro ;
163+ rate_gyro_rad_integral_sum.y += packet.integrated_ygyro ;
164+
165+ quality_rad_sum += packet.quality ;
166+ sensor_id_rad = packet.sensor_id ;
167+
168+ integration_time_sum_rad_us += packet.integration_time_us ;
148169
149- flow_sum_is_rads = true ;
170+ count_rad++ ;
150171
151- // OPTICAL_FLOW_RAD contains already calculated integrated values
152- // so it is not required to integrate them in msg handling
153- quality_sum = packet.quality ;
154- flow_sum = Vector2f (packet.integrated_x , packet.integrated_y );
155- gyro_sum = Vector2f (packet.integrated_xgyro , packet.integrated_ygyro );
156- sensor_id = packet.sensor_id ;
172+ }
173+
174+ AP_OpticalFlow::OpticalFlow_state AP_OpticalFlow_MAV::update_msg_optical_flow_rad () {
175+ struct AP_OpticalFlow ::OpticalFlow_state state;
176+ const Vector2f flowScaler = _flowScaler ();
177+
178+ float scale_factorx = 1 .0f + 0 .001f * flowScaler.x ;
179+ float scale_factory = 1 .0f + 0 .001f * flowScaler.y ;
157180
158- // flow is already integrated so flow samples count will be equal to one
159- count = 1 ;
160- gyro_sum_count = 1 ;
181+ float integral_to_rate = 1 .0f / (integration_time_sum_rad_us * 1e-6 ) / count_rad;
182+ state.flowRate = Vector2f{
183+ flow_rad_integral_sum.x * scale_factorx,
184+ flow_rad_integral_sum.y * scale_factory,
185+ } / count_rad * integral_to_rate;
186+ state.bodyRate = rate_gyro_rad_integral_sum / count_rad * integral_to_rate;
187+ state.surface_quality = quality_rad_sum / count_rad;
161188
189+ _applyYaw (state.flowRate );
190+ _applyYaw (state.bodyRate );
191+
192+ return state;
162193
163194}
164- #endif
195+
196+ #endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
165197
166198#endif // AP_OPTICALFLOW_MAV_ENABLED
0 commit comments