Skip to content

Commit a8d8cd0

Browse files
committed
AP_OpticalFlow: separated states between OPTICAL_FLOW and OPTICAL_FLOW_RAD and added support for handling both messages at a time
1 parent 09730b4 commit a8d8cd0

File tree

8 files changed

+132
-80
lines changed

8 files changed

+132
-80
lines changed

libraries/AP_OpticalFlow/AP_OpticalFlow.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,18 +228,18 @@ void AP_OpticalFlow::handle_msg(const mavlink_message_t &msg)
228228

229229
#if AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
230230

231-
void AP_OpticalFlow::handle_msg_rad(const mavlink_message_t &msg)
231+
void AP_OpticalFlow::handle_msg_optical_flow_rad(const mavlink_message_t &msg)
232232
{
233233
// exit immediately if not enabled
234234
if (!enabled()){
235235
return;
236236
}
237237

238238
if (backend != nullptr) {
239-
backend->handle_msg_rad(msg);
239+
backend->handle_msg_optical_flow_rad(msg);
240240
}
241241
}
242-
#endif
242+
#endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
243243

244244
#if HAL_MSP_OPTICALFLOW_ENABLED
245245
void AP_OpticalFlow::handle_msp(const MSP::msp_opflow_data_message_t &pkt)

libraries/AP_OpticalFlow/AP_OpticalFlow.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ class AP_OpticalFlow
9191

9292
#if AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
9393
// handle optical flow rad mavlink message
94-
void handle_msg_rad(const mavlink_message_t &msg);
95-
#endif
94+
void handle_msg_optical_flow_rad(const mavlink_message_t &msg);
95+
#endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
9696

9797
#if HAL_MSP_OPTICALFLOW_ENABLED
9898
// handle optical flow msp messages

libraries/AP_OpticalFlow/AP_OpticalFlow_Backend.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ class OpticalFlow_backend
4444

4545
#if AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
4646
// handle optical flow rad mavlink messages
47-
virtual void handle_msg_rad(const mavlink_message_t &msg) {}
48-
#endif
47+
virtual void handle_msg_optical_flow_rad(const mavlink_message_t &msg) {}
48+
#endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
4949

5050
#if HAL_MSP_OPTICALFLOW_ENABLED
5151
// handle optical flow msp messages

libraries/AP_OpticalFlow/AP_OpticalFlow_MAV.cpp

Lines changed: 99 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
3434
void 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

libraries/AP_OpticalFlow/AP_OpticalFlow_MAV.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,47 @@ class AP_OpticalFlow_MAV : public OpticalFlow_backend
1818

1919
// read latest values from sensor and fill in x,y and totals.
2020
void update(void) override;
21+
AP_OpticalFlow::OpticalFlow_state update_msg_optical_flow();
2122

2223
// get update from mavlink
2324
void handle_msg(const mavlink_message_t &msg) override;
2425

2526
#if AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
26-
void handle_msg_rad(const mavlink_message_t &msg) override;
27-
#endif
27+
void handle_msg_optical_flow_rad(const mavlink_message_t &msg) override;
28+
AP_OpticalFlow::OpticalFlow_state update_msg_optical_flow_rad();
29+
#endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
2830

2931
// detect if the sensor is available
3032
static AP_OpticalFlow_MAV *detect(AP_OpticalFlow &_frontend);
3133

3234
private:
3335

36+
// OPTICAL_FLOW state variables
3437
uint64_t prev_frame_us; // system time of last message when update was last called
3538
uint64_t latest_frame_us; // system time of most recent messages processed
3639
Vector2f flow_sum; // sum of sensor's flow_x and flow_y values since last call to update
3740
bool flow_sum_is_rads; // true if flow_sum holds values in rad/s, if false flow_sum holds dpi
3841
uint16_t quality_sum; // sum of sensor's quality values since last call to update
3942
uint16_t count; // number of sensor readings since last call to update
40-
uint8_t sensor_id; // sensor_id received in latest mavlink message
43+
uint8_t sensor_id; // sensor_id received in latest OPTICAL_FLOW message
4144
Vector2f gyro_sum; // sum of gyro sensor values since last frame from flow sensor
4245
uint16_t gyro_sum_count; // number of gyro sensor values in sum
46+
47+
48+
49+
#if AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
50+
51+
// OPTICAL_FLOW_RAD state variables
52+
Vector2f flow_rad_integral_sum; // sum of all integrated_x and integrated_y values since last call to update
53+
Vector2f rate_gyro_rad_integral_sum; // sum of all integrated_xgyro/integrated_ygyro values since last update
54+
uint32_t integration_time_sum_rad_us; // sum of all integratation_time_us values used to obtain average flow
55+
uint16_t quality_rad_sum; // sum of sensor quality values since last call to update
56+
uint16_t count_rad; // number of sensor readings since last call to update
57+
uint8_t sensor_id_rad; // sensor_id received in last OPTICAL_FLOW_RAD message
58+
59+
60+
61+
#endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
4362
};
4463

4564
#endif // AP_OPTICALFLOW_MAV_ENABLED

libraries/AP_OpticalFlow/AP_OpticalFlow_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@
5151
#ifndef AP_OPTICALFLOW_UPFLOW_ENABLED
5252
#define AP_OPTICALFLOW_UPFLOW_ENABLED AP_OPTICALFLOW_BACKEND_DEFAULT_ENABLED
5353
#endif
54+

libraries/GCS_MAVLink/GCS_Common.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4200,7 +4200,7 @@ void GCS_MAVLINK::handle_optical_flow_rad(const mavlink_message_t &msg)
42004200
if (optflow == nullptr) {
42014201
return;
42024202
}
4203-
optflow->handle_msg_rad(msg);
4203+
optflow->handle_msg_optical_flow_rad(msg);
42044204
}
42054205
#endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
42064206

libraries/GCS_MAVLink/GCS_config.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
#endif
6262

6363
#ifndef AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
64-
#define AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED 1
65-
#endif
64+
#define AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED (AP_OPTICALFLOW_ENABLED && HAL_PROGRAM_SIZE_LIMIT_KB >= 2048)
65+
#endif // AP_MAVLINK_MSG_OPTICAL_FLOW_RAD_ENABLED
6666

6767
// allow removal of developer-centric mavlink commands
6868
#ifndef AP_MAVLINK_FAILURE_CREATION_ENABLED

0 commit comments

Comments
 (0)