Line data Source code
1 : /* 2 : This program is free software: you can redistribute it and/or modify 3 : it under the terms of the GNU General Public License as published by 4 : the Free Software Foundation, either version 3 of the License, or 5 : (at your option) any later version. 6 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : 16 : #include <AP_HAL/AP_HAL.h> 17 : #include <AP_AHRS/AP_AHRS.h> 18 : #include "AP_OpticalFlow_MSP.h" 19 : 20 : #if HAL_MSP_OPTICALFLOW_ENABLED 21 : 22 : #define OPTFLOW_MSP_TIMEOUT_SEC 0.5f // 2Hz 23 : 24 : extern const AP_HAL::HAL& hal; 25 : 26 : using namespace MSP; 27 : 28 : // detect the device 29 0 : AP_OpticalFlow_MSP *AP_OpticalFlow_MSP::detect(AP_OpticalFlow &_frontend) 30 : { 31 : // we assume msp messages will be sent into this driver 32 0 : return NEW_NOTHROW AP_OpticalFlow_MSP(_frontend); 33 : } 34 : 35 : // read latest values from sensor and fill in x,y and totals. 36 0 : void AP_OpticalFlow_MSP::update(void) 37 : { 38 : // record gyro values as long as they are being used 39 : // the sanity check of dt below ensures old gyro values are not used 40 0 : if (gyro_sum_count < 1000) { 41 0 : const Vector3f& gyro = AP::ahrs().get_gyro(); 42 0 : gyro_sum.x += gyro.x; 43 0 : gyro_sum.y += gyro.y; 44 0 : gyro_sum_count++; 45 : } 46 : 47 : // return without updating state if no readings 48 0 : if (count == 0) { 49 0 : return; 50 : } 51 : 52 0 : struct AP_OpticalFlow::OpticalFlow_state state {}; 53 : 54 0 : state.surface_quality = quality_sum / count; 55 : 56 : // calculate dt 57 0 : const float dt = (latest_frame_us - prev_frame_us) * 1.0e-6; 58 0 : prev_frame_us = latest_frame_us; 59 : 60 : // sanity check dt 61 0 : if (is_positive(dt) && (dt < OPTFLOW_MSP_TIMEOUT_SEC)) { 62 : // calculate flow values 63 0 : const float flow_scale_factor_x = 1.0f + 0.001f * _flowScaler().x; 64 0 : const float flow_scale_factor_y = 1.0f + 0.001f * _flowScaler().y; 65 : 66 : // copy flow rates to state structure 67 0 : state.flowRate = { ((float)flow_sum.x / count) * flow_scale_factor_x * dt, 68 0 : ((float)flow_sum.y / count) * flow_scale_factor_y * dt}; 69 : 70 : // copy average body rate to state structure 71 0 : state.bodyRate = { gyro_sum.x / gyro_sum_count, gyro_sum.y / gyro_sum_count }; 72 : 73 : // invert flow vector to align it with default sensor orientation (required on matek 3901) 74 0 : state.flowRate *= -1; 75 : 76 : // we only apply yaw to flowRate as body rate comes from AHRS 77 0 : _applyYaw(state.flowRate); 78 : } else { 79 : // first frame received in some time so cannot calculate flow values 80 0 : state.flowRate.zero(); 81 0 : state.bodyRate.zero(); 82 : } 83 : 84 0 : _update_frontend(state); 85 : 86 : // reset local buffers 87 0 : flow_sum.zero(); 88 0 : quality_sum = 0; 89 0 : count = 0; 90 : 91 : // reset gyro sum 92 0 : gyro_sum.zero(); 93 0 : gyro_sum_count = 0; 94 : } 95 : 96 : // handle OPTICAL_FLOW msp messages 97 0 : void AP_OpticalFlow_MSP::handle_msp(const MSP::msp_opflow_data_message_t &pkt) 98 : { 99 : // record time message was received 100 : // ToDo: add jitter correction 101 0 : latest_frame_us = AP_HAL::micros64(); 102 : 103 : // add sensor values to sum 104 0 : flow_sum.x += pkt.motion_x; 105 0 : flow_sum.y += pkt.motion_y; 106 0 : quality_sum += (int)pkt.quality * 100 / 255; 107 0 : count++; 108 0 : } 109 : 110 : #endif // HAL_MSP_OPTICALFLOW_ENABLED