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 : /* 17 : driver for UPixel UPFLOW optical flow sensor 18 : 19 : UPFLOW serial packet description 20 : byte0: header0 (0xFE) 21 : byte1: header1 (0x0A) 22 : byte2: x-motion low byte; 23 : byte3: x-motion high byte; 24 : byte4: y-motion low byte; 25 : byte5: y-motion high byte; 26 : byte6: dt low byte; 27 : byte7: dt high byte; 28 : byte8: reserved; 29 : byte9: reserved; 30 : byte10: surface quality 31 : byte11: hardware version 32 : byte12:checksum 33 : byte13:footer (0x55) 34 : */ 35 : 36 : #include "AP_OpticalFlow_UPFLOW.h" 37 : 38 : #if AP_OPTICALFLOW_UPFLOW_ENABLED 39 : 40 : #include <AP_HAL/AP_HAL.h> 41 : #include <AP_AHRS/AP_AHRS.h> 42 : #include <AP_SerialManager/AP_SerialManager.h> 43 : #include <utility> 44 : #include "AP_OpticalFlow.h" 45 : #include <stdio.h> 46 : 47 : #define UPFLOW_HEADER0 (uint8_t)0xFE 48 : #define UPFLOW_HEADER1 (uint8_t)0x0A 49 : #define UPFLOW_FOOTER (uint8_t)0x55 50 : #define UPFLOW_PIXEL_SCALING (1e-4) 51 : #define UPFLOW_TIMEOUT_SEC 0.3f 52 : 53 : extern const AP_HAL::HAL& hal; 54 : 55 : // constructor 56 0 : AP_OpticalFlow_UPFLOW::AP_OpticalFlow_UPFLOW(AP_OpticalFlow &_frontend, AP_HAL::UARTDriver *_uart) : 57 : OpticalFlow_backend(_frontend), 58 0 : uart(_uart) 59 : { 60 0 : } 61 : 62 : // detect the device 63 0 : AP_OpticalFlow_UPFLOW *AP_OpticalFlow_UPFLOW::detect(AP_OpticalFlow &_frontend) 64 : { 65 0 : AP_SerialManager *serial_manager = AP::serialmanager().get_singleton(); 66 0 : if (serial_manager == nullptr) { 67 0 : return nullptr; 68 : } 69 : 70 : // look for first serial driver with protocol defined as OpticalFlow 71 0 : AP_HAL::UARTDriver *uart = serial_manager->find_serial(AP_SerialManager::SerialProtocol_OpticalFlow, 0); 72 0 : if (uart == nullptr) { 73 0 : return nullptr; 74 : } 75 : 76 : // we have found a serial port so use it 77 0 : AP_OpticalFlow_UPFLOW *sensor = NEW_NOTHROW AP_OpticalFlow_UPFLOW(_frontend, uart); 78 0 : return sensor; 79 : } 80 : 81 : // initialise the sensor 82 0 : void AP_OpticalFlow_UPFLOW::init() 83 : { 84 : // sanity check uart 85 0 : if (uart == nullptr) { 86 0 : return; 87 : } 88 : // open serial port with baud rate of 19200 89 0 : uart->begin(19200); 90 : } 91 : 92 : // read latest values from sensor and fill in x,y and totals. 93 0 : void AP_OpticalFlow_UPFLOW::update(void) 94 : { 95 : // sanity check uart 96 0 : if (uart == nullptr) { 97 0 : return; 98 : } 99 : 100 : // record gyro values as long as they are being used 101 : // the sanity check of dt below ensures old gyro values are not used 102 0 : if (gyro_sum_count >= 1000) { 103 0 : gyro_sum.zero(); 104 0 : gyro_sum_count = 0; 105 : } 106 0 : const Vector3f& gyro = AP::ahrs().get_gyro(); 107 0 : gyro_sum.x += gyro.x; 108 0 : gyro_sum.y += gyro.y; 109 0 : gyro_sum_count++; 110 : 111 : 112 0 : bool phrased = false; 113 : // read any available characters in the serial buffer 114 0 : uint32_t nbytes = MIN(uart->available(), 1024u); 115 0 : while (nbytes-- > 0) { 116 0 : int16_t r = uart->read(); 117 0 : if (r < 0) { 118 0 : break; 119 : } 120 0 : uint8_t c = (uint8_t)r; 121 0 : if (recv_count == 0) { 122 : //Header0 123 0 : if (c == UPFLOW_HEADER0) { 124 0 : recv_count++; 125 0 : sum = 0; 126 : } 127 0 : } else if (recv_count == 1) { 128 : //Header1 129 0 : if (c != UPFLOW_HEADER1) { 130 0 : recv_count = 0; 131 : } else { 132 0 : recv_count++; 133 : } 134 0 : } else if (recv_count < 12) { 135 : //actual data 136 0 : ((uint8_t*)&updata)[recv_count - 2] = c; 137 0 : sum ^= c; 138 0 : recv_count++; 139 0 : } else if (recv_count == 12) { 140 : //checksum 141 0 : if (sum != c) { 142 0 : recv_count = 0; 143 : } else { 144 0 : recv_count++; 145 : } 146 : } else { //footer 147 0 : if (c == UPFLOW_FOOTER) { 148 0 : phrased=true; 149 : } 150 0 : recv_count = 0; 151 : } 152 : } 153 : 154 : // return without updating state if no readings 155 0 : if (phrased == false) { 156 0 : return; 157 : } 158 : 159 0 : struct AP_OpticalFlow::OpticalFlow_state state {}; 160 : 161 0 : state.surface_quality = updata.quality; 162 : 163 0 : float dt = updata.integration_timespan * 1.0e-6; 164 : 165 : // sanity check dt 166 0 : if (is_positive(dt) && (dt < UPFLOW_TIMEOUT_SEC)) { 167 : // calculate flow values 168 0 : const Vector2f flowScaler = _flowScaler(); 169 0 : Vector2f flowScaleFactor = Vector2f(1.0f, 1.0f) + flowScaler * 0.001f; 170 : 171 : // copy flow rates to state structure 172 0 : state.flowRate = Vector2f((float)(-updata.flow_x_integral) * flowScaleFactor.x, 173 0 : (float)(-updata.flow_y_integral) * flowScaleFactor.y); 174 0 : state.flowRate *= UPFLOW_PIXEL_SCALING / dt; 175 : 176 : // copy average body rate to state structure 177 0 : state.bodyRate = Vector2f{gyro_sum.x / gyro_sum_count, gyro_sum.y / gyro_sum_count}; 178 : 179 : // we only apply yaw to flowRate as body rate comes from AHRS 180 0 : _applyYaw(state.flowRate); 181 : } else { 182 : // first frame received in some time so cannot calculate flow values 183 0 : state.flowRate.zero(); 184 0 : state.bodyRate.zero(); 185 : } 186 : 187 0 : _update_frontend(state); 188 : 189 : // reset gyro sum 190 0 : gyro_sum.zero(); 191 0 : gyro_sum_count = 0; 192 : } 193 : 194 : #endif // AP_OPTICALFLOW_UPFLOW_ENABLED