搜索
bottom↓
回复: 158

PX4 FLOW光流 应用关键问题讲解

  [复制链接]

出0入0汤圆

发表于 2015-6-12 18:38:35 | 显示全部楼层 |阅读模式
本帖最后由 golaced 于 2015-6-13 09:09 编辑

最近在做新的迷你8轴 ,想往里面加上光流传感器,淘宝上有许多价格不等有的500多 有的800多非常的坑,贵的主要原因就是超声波传感器,但是有些店光传感器就500非常坑和其他店区别就是提供技术支持,但我怀疑估计他们也搞不懂光流算法是什么并且PX4 FLOW光流不直接提供stm32工程文件需要用PX4 console 编译无法在线调试,有时间的人可以把开源文件用keil新建个工程编译下载试试还行不行,楼主暂时还不打算研究光流算法所有就不就行这个工作了。
我买的光流传感器为X宝上最便宜的大概280左右,同时也买了那个很贵的超声波传感器所以也花了500多,但是比那些800,1000的可便宜了不少如果有兴趣可以买网上10元左右的那种超声波传感器更改开源程序,但我觉得还不如用另外的stm32来完成超声波的采集,PX4 FLOW光流中貌似只是多了个卡尔曼滤波器而已,网上那些超声定高的四轴不是也挺好的而且能查到的资料也很多。
刚买来的PX4 FLOW光流自带的是官方程序,效果不怎么好,原来没用过PX4 的产品一开始一头雾水,上网查阅了很多帖子都说效果不好,无意中在某论坛上发现一个人用PX4 FLOW光流定点的视频效果不错还提供固件,于是满怀激动的下载并烧入传感器中实验了一下效果比自带的好了很多这个附件就是网上找到的那个。



第二天再测试就发现坑爹了这个固件测出来的x,y轴数居然一样,我以为是传感器坏了又重新烧了官方程序发现虽然效果不好但是x,y方向是分离的,上网找到了这个提供这个固件的淘宝店询问了回答是要用他们生产的传感器,我就纳闷了本来就是用别人开源的资料,原理图 代码都是别人提供的结果自己赚那么多钱,跑到论坛上上传固件吸引了那么多人,我以为是大神造福我们这些菜鸟结果还只适用自己的板子。

我虽然做的东西不多但是在别人东西上改改还是可以的,再次浏览PX4 FLOW光流的资料我认为上面固件好使只不过是调整了一些参数而已,而其他店的传感器输出数据x,y轴一样估计是店主动了点小手脚,PX4 FLOW光流可以调整的参数如下:
Name         Default         Access         Comment
BFLOW_F_THLD         5000         RW         This parameter is a feature threashold and limits the quality of patterns that are used to calculate the bottom flow. For low values (e.g. 10) almost every pattern is taken, for higher values (e.g. 100) only significant patters are taken.
BFLOW_V_THLD         30         RW         This is a pattern correlation threashold for filtering bad matches. Lower means only strong correlations are accepted.
BFLOW_HIST_FIL         0         RW         1: Flow histogram filter is ON, 0: OFF
BFLOW_GYRO_COM         1         RW         1: Gyro compensation is ON, 0: OFF
BFLOW_LP_FIL         0         RW         1: Lowpass filter on flow output is ON, 0: OFF
BFLOW_W_NEW         0.3         RW         Flow lowpass filter gain
DEBUG         1         RW         1: Debug messages ON, 0: OFF
GYRO_SENS_DPS         250         RW         Gyroscope sensitivity: 250, 500, 2000 (dps)
GYRO_COMP_THR         0.01         RW         Gyro compensation threshold (dps): Gyro data lower than this threshold is not compensated to prevent drift
IMAGE_WIDTH         64         R         Image width (pixels)
IMAGE_HEIGHT         64         R         Image height (pixels)
IMAGE_L_LIGHT         0         RW         1: Image sensor low light mode ON, 0: OFF
IMAGE_NOISE_C         1         RW         1: Image sensor noise correction ON, 0: OFF
IMAGE_TEST_PAT         0         RW         1: Gray-shaded test pattern mode ON, 0: OFF
LENS_FOCAL_LEN         16         RW         Focal length of lens (mm)
POSITION         0         RW         0: Only position 0 is used (Bottom: 0, Front: 1, Top: 2, Back: 3, Right: 4, Left: 5)
SONAR_FILTERED         0         RW         1: Kalman filter on sonar output is ON, 0: OFF
SONAR_KAL_L1         0.8461         RW         Sonar Kalman gain L1
SONAR_KAL_L2         6.2034         RW         Sonar Kalman gain L2
SYS_ID         81         RW        MAVLink System ID
SYS_COMP_ID         50         RW        MAVLink Component ID
SYS_SENSOR_ID         77         RW        MAVLink Sensor ID
SYS_TYPE         0         RW        MAVLink System Type
SYS_AP_TYPE         1         RW        MAVLink Autopilot Type
SYS_SW_VER         13XX         R         Software Version
SYS_SEND_STATE         1         RW         1: Send MAVLink Heartbeat, 0: Not
USART_2_BAUD         115200         R         Baudrate USART 2
USART_3_BAUD         115200         R         Baudrate USART 3 (Data Output)
USB_SEND_VIDEO         1         RW         1: Send video over USB, 0: Not
USB_SEND_FLOW         1         RW         1: Send flow over USB, 0: Not
USB_SEND_GYRO         1         RW         1: Send gyro data over USB, 0: Not
USB_SEND_FWD         0         RW         1: Send forwarded flow over USB, 0: Not
USB_SEND_DEBUG         1         RW         1: Send debug msgs over USB, 0: Not
VIDEO_RATE         150         RW         Time in milliseconds between images of video transmission
VIDEO_ONLY         0         RW         1: High resolution video mode is ON, 0: OFF


其中BFLOW_F_THLD   BFLOW_V_THLD  BFLOW_W_NEW三个参数对定位效果影响较大,经过楼主尝试得出三个参数为19   20  0.1时对我的传感器效果较好下面是几个波形:


左右周期运动

匀速运动

上下运动高度波形


这个参数的效果和上面固件的结果基本差不多,如果在经过滤波和加速度融合处理效果估计会更好,当然你也可以自己调整其他参数方法如下pdf所示

我调试出的固件如下:

该固件效果和上面的差不多而且xy分离测量。还有在调整传感器参数是在qground中使用set貌似无法把参数写入rom中,我使用的方法是直接在源码中修改其文件为src/settings.c 每次调试时先连上USB在线修改参数比较结果,满意后就到settings.c中修改对应参数,然后按照上面pdf中方法编译获得固件下载即可。

对于传感器数据接收来说,新手对mavlink那坑爹的协议估计都一头雾水,而且在https://pixhawk.ethz.ch/mavlink/#OPTICAL_FLOW提供的顺序并不是传感器发送帧的顺序,楼主一开始也被这个误导,导致接收到数据缺无法正确解码,正确的顺序应该是:


楼主的接收程序是:


  typedef struct
{
        uint64_t  time_sec;
        u8   id;
        int16_t flow_x;
        int16_t flow_y;
        float flow_comp_x;//Flow in m in x-sensor direction, angular-speed compensated
        float flow_comp_y;
        u8 quality; //Optical flow quality / confidence. 0: bad, 255: maximum quality
        float hight;//ground_distance        float        Ground distance in m. Positive value: distance known. Negative value: Unknown distance      
   
            
}FLOW;

FLOW flow;

   float ByteToFloat(unsigned char* byteArry)
{
  return *((float*)byteArry);
}

u8 FLOW_STATE[4];
u8 flow_buf[30];
void FLOW_MAVLINK(unsigned char data)
{
/*
红色的是起始标志位(stx),在v1.0版本中以“FE”作为起始标志。这个标志位在mavlink消息帧接收端进行消息解码时有用处。

第二个格子代表的是灰色部分(payload,称作有效载荷,要用的数据在有效载荷里面)的字节长度(len),范围从0到255之间。在mavlink消息帧接收端可以用它和实际收到的有效载荷的长度比较,以验证有效载荷的长度是否正确。

第三个格子代表的是本次消息帧的序号(seq),每次发完一个消息,这个字节的内容会加1,加到255后会从0重新开始。这个序号用于mavlink消息帧接收端计算消息丢失比例用的,相当于是信号强度。

第四个格子代表了发送本条消息帧的设备的系统编号(sys),使用PIXHAWK刷PX4固件时默认的系统编号为1,用于mavlink消息帧接收端识别是哪个设备发来的消息。

第五个格子代表了发送本条消息帧的设备的单元编号(comp),使用PIXHAWK刷PX4固件时默认的单元编号为50,用于mavlink消息帧接收端识别是设备的哪个单元发来的消息(暂时没什么用) 。

第六个格子代表了有效载荷中消息包的编号(msg),注意它和序号是不同的,这个字节很重要,mavlink消息帧接收端要根据这个编号来确定有效载荷里到底放了什么消息包并根据编号选择对应的方式来处理有效载荷里的信息包。
      26*/                 
// FE 1A| A2 X X| 64

static u8 s_flow=0,data_cnt=0;
u8 cnt_offset=0;       
u8 get_one_fame=0;
char floattobyte[4];
                switch(s_flow)
         {
    case 0: if(data==0xFE)
                        s_flow=1;
                        break;
                case 1: if(data==0x1A)
                                { s_flow=2;}
                        else
                        s_flow=0;
                        break;
          case 2:
                        if(data_cnt<4)
                        {s_flow=2; FLOW_STATE[data_cnt++]=data;}
                  else
                        {data_cnt=0;s_flow=3;flow_buf[data_cnt++]=data;}
                 break;
                case 3:
                 if(FLOW_STATE[3]=100){
                        if(data_cnt<26)
                        {s_flow=3; flow_buf[data_cnt++]=data;}
                  else
                        {data_cnt=0;s_flow=4;}
                }
                else
                        {data_cnt=0;s_flow=0;}
                         break;
                case 4:get_one_fame=1;s_flow=0;data_cnt=0;break;
                default:s_flow=0;data_cnt=0;break;
         }//--end of s_uart
               

         if(get_one_fame)
         {
                flow.time_sec=(flow_buf[7]<<64)|(flow_buf[6]<<56)|(flow_buf[5]<<48)|(flow_buf[4]<<40)
                 |(flow_buf[3]<<32)|(flow_buf[2]<<16)|(flow_buf[1]<<8)|(flow_buf[0]);
           floattobyte[0]=flow_buf[8];
                 floattobyte[1]=flow_buf[9];
                 floattobyte[2]=flow_buf[10];
                 floattobyte[3]=flow_buf[11];
                flow.flow_comp_x =ByteToFloat(floattobyte);
                 floattobyte[0]=flow_buf[12];
                 floattobyte[1]=flow_buf[13];
                 floattobyte[2]=flow_buf[14];
                 floattobyte[3]=flow_buf[15];
                flow.flow_comp_y =ByteToFloat(floattobyte);
                 floattobyte[0]=flow_buf[16];
                 floattobyte[1]=flow_buf[17];
                 floattobyte[2]=flow_buf[18];
                 floattobyte[3]=flow_buf[19];
           flow.hight=ByteToFloat(floattobyte);//ground_distance        float        Ground distance in m. Positive value: distance known. Negative value: Unknown distance     
           flow.flow_x=(int16_t)((flow_buf[20])|(flow_buf[21]<<8));
           flow.flow_y=(int16_t)((flow_buf[22])|(flow_buf[23]<<8));
                 flow.id=flow_buf[24];
           flow.quality=flow_buf[25]; //Optical flow quality / confidence. 0: bad, 255: maximum quality
       
                }
}

写的不好,也没有校验,不过结果正确,代码里面也包括了串口接收四位数据转换单精度浮点的部分(估计很多新手也很头疼的部分)。

以上内容不敢说全部原创,如有问题望指正。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2015-7-22 20:30:42 | 显示全部楼层
Simon_起誓 发表于 2015-7-22 14:15
成功读取..楼主能解释一下 flow_x,flow_y, flow_comp_x,flow_comp_y具体含义么怎么融合到定点PID里 ...

前两个貌似是像素位移速度  后面是融合高度后的真实速度    定点apm里貌似用光流输出速度积分换算成了GPS坐标 然后给到导航里了你可以看下firmware-master里例子中flow_postion_estimator 那个
/****************************************************************************
*
*   Copyright (C) 2008-2013 PX4 Development Team. All rights reserved.
*   Author: Samuel Zihlmann <samuezih@ee.ethz.ch>
*                    Lorenz Meier <lm@inf.ethz.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
*    used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/

/**
* @file flow_position_estimator_main.c
*
* Optical flow position estimator
*/

#include <px4_config.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <fcntl.h>
#include <float.h>
#include <nuttx/sched.h>
#include <sys/prctl.h>
#include <drivers/drv_hrt.h>
#include <termios.h>
#include <errno.h>
#include <limits.h>
#include <math.h>
#include <uORB/uORB.h>
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/actuator_armed.h>
#include <uORB/topics/vehicle_control_mode.h>
#include <uORB/topics/vehicle_attitude.h>
#include <uORB/topics/vehicle_attitude_setpoint.h>
#include <uORB/topics/vehicle_local_position.h>
#include <uORB/topics/sensor_combined.h>
#include <uORB/topics/optical_flow.h>
#include <uORB/topics/filtered_bottom_flow.h>
#include <systemlib/perf_counter.h>
#include <systemlib/systemlib.h>
#include <poll.h>
#include <platforms/px4_defines.h>

#include "flow_position_estimator_params.h"

__EXPORT int flow_position_estimator_main(int argc, char *argv[]);
static bool thread_should_exit = false;                /**< Daemon exit flag */
static bool thread_running = false;                /**< Daemon status flag */
static int daemon_task;                                /**< Handle of daemon task / thread */

int flow_position_estimator_thread_main(int argc, char *argv[]);
static void usage(const char *reason);

static void usage(const char *reason)
{
        if (reason) {
                fprintf(stderr, "%s\n", reason);
        }

        fprintf(stderr, "usage: daemon {start|stop|status} [-p <additional params>]\n\n");
        exit(1);
}

/**
* The daemon app only briefly exists to start
* the background job. The stack size assigned in the
* Makefile does only apply to this management task.
*
* The actual stack size should be set in the call
* to px4_task_spawn_cmd().
*/
int flow_position_estimator_main(int argc, char *argv[])
{
        if (argc < 2) {
                usage("missing command");
        }

        if (!strcmp(argv[1], "start")) {
                if (thread_running) {
                        printf("flow position estimator already running\n");
                        /* this is not an error */
                        exit(0);
                }

                thread_should_exit = false;
                daemon_task = px4_task_spawn_cmd("flow_position_estimator",
                                             SCHED_DEFAULT,
                                             SCHED_PRIORITY_MAX - 5,
                                             4000,
                                             flow_position_estimator_thread_main,
                                             (argv) ? (char * const *)&argv[2] : (char * const *)NULL);
                exit(0);
        }

        if (!strcmp(argv[1], "stop")) {
                thread_should_exit = true;
                exit(0);
        }

        if (!strcmp(argv[1], "status")) {
                if (thread_running) {
                        printf("\tflow position estimator is running\n");

                } else {
                        printf("\tflow position estimator not started\n");
                }

                exit(0);
        }

        usage("unrecognized command");
        exit(1);
}

int flow_position_estimator_thread_main(int argc, char *argv[])
{
        /* welcome user */
        thread_running = true;
        printf("[flow position estimator] starting\n");

        /* rotation matrix for transformation of optical flow speed vectors */
        static const int8_t rotM_flow_sensor[3][3] =   {{  0, -1, 0 },
                { 1, 0, 0 },
                {  0, 0, 1 }
        }; // 90deg rotated
        const float time_scale = powf(10.0f, -6.0f);
        static float speed[3] = {0.0f, 0.0f, 0.0f};
        static float flow_speed[3] = {0.0f, 0.0f, 0.0f};
        static float global_speed[3] = {0.0f, 0.0f, 0.0f};
        static uint32_t counter = 0;
        static uint64_t time_last_flow = 0; // in ms
        static float dt = 0.0f; // seconds
        static float sonar_last = 0.0f;
        static bool sonar_valid = false;
        static float sonar_lp = 0.0f;

        /* subscribe to vehicle status, attitude, sensors and flow*/
        struct actuator_armed_s armed;
        memset(&armed, 0, sizeof(armed));
        struct vehicle_control_mode_s control_mode;
        memset(&control_mode, 0, sizeof(control_mode));
        struct vehicle_attitude_s att;
        memset(&att, 0, sizeof(att));
        struct vehicle_attitude_setpoint_s att_sp;
        memset(&att_sp, 0, sizeof(att_sp));
        struct optical_flow_s flow;
        memset(&flow, 0, sizeof(flow));

        /* subscribe to parameter changes */
        int parameter_update_sub = orb_subscribe(ORB_ID(parameter_update));

        /* subscribe to armed topic */
        int armed_sub = orb_subscribe(ORB_ID(actuator_armed));

        /* subscribe to safety topic */
        int control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));

        /* subscribe to attitude */
        int vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));

        /* subscribe to attitude setpoint */
        int vehicle_attitude_setpoint_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));

        /* subscribe to optical flow*/
        int optical_flow_sub = orb_subscribe(ORB_ID(optical_flow));

        /* init local position and filtered flow struct */
        struct vehicle_local_position_s local_pos = {
                .x = 0.0f,
                .y = 0.0f,
                .z = 0.0f,
                .vx = 0.0f,
                .vy = 0.0f,
                .vz = 0.0f
        };
        struct filtered_bottom_flow_s filtered_flow = {
                .sumx = 0.0f,
                .sumy = 0.0f,
                .vx = 0.0f,
                .vy = 0.0f
        };

        /* advert pub messages */
        orb_advert_t local_pos_pub = orb_advertise(ORB_ID(vehicle_local_position), &local_pos);
        orb_advert_t filtered_flow_pub = orb_advertise(ORB_ID(filtered_bottom_flow), &filtered_flow);

        /* vehicle flying status parameters */
        bool vehicle_liftoff = false;
        bool sensors_ready = false;

        /* parameters init*/
        struct flow_position_estimator_params params;
        struct flow_position_estimator_param_handles param_handles;
        parameters_init(&param_handles);
        parameters_update(&param_handles, &params);

        perf_counter_t mc_loop_perf = perf_alloc(PC_ELAPSED, "flow_position_estimator_runtime");
        perf_counter_t mc_interval_perf = perf_alloc(PC_INTERVAL, "flow_position_estimator_interval");
        perf_counter_t mc_err_perf = perf_alloc(PC_COUNT, "flow_position_estimator_err");

        while (!thread_should_exit) {

                if (sensors_ready) {
                        /*This runs at the rate of the sensors */
                        struct pollfd fds[2] = {
                                { .fd = optical_flow_sub, .events = POLLIN },
                                { .fd = parameter_update_sub,   .events = POLLIN }
                        };

                        /* wait for a sensor update, check for exit condition every 500 ms */
                        int ret = poll(fds, 2, 500);

                        if (ret < 0) {
                                /* poll error, count it in perf */
                                perf_count(mc_err_perf);

                        } else if (ret == 0) {
                                /* no return value, ignore */
//                                printf("[flow position estimator] no bottom flow.\n");
                        } else {

                                /* parameter update available? */
                                if (fds[1].revents & POLLIN) {
                                        /* read from param to clear updated flag */
                                        struct parameter_update_s update;
                                        orb_copy(ORB_ID(parameter_update), parameter_update_sub, &update);

                                        parameters_update(&param_handles, &params);
                                        printf("[flow position estimator] parameters updated.\n");
                                }

                                /* only if flow data changed */
                                if (fds[0].revents & POLLIN) {
                                        perf_begin(mc_loop_perf);

                                        orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);
                                        /* got flow, updating attitude and status as well */
                                        orb_copy(ORB_ID(vehicle_attitude), vehicle_attitude_sub, &att);
                                        orb_copy(ORB_ID(vehicle_attitude_setpoint), vehicle_attitude_setpoint_sub, &att_sp);
                                        orb_copy(ORB_ID(actuator_armed), armed_sub, &armed);
                                        orb_copy(ORB_ID(vehicle_control_mode), control_mode_sub, &control_mode);

                                        /* vehicle state estimation */
                                        float sonar_new = flow.ground_distance_m;

                                        /* set liftoff boolean
                                         * -> at bottom sonar sometimes does not work correctly, and has to be calibrated (distance higher than 0.3m)
                                         * -> accept sonar measurements after reaching calibration distance (values between 0.3m and 1.0m for some time)
                                         * -> minimum sonar value 0.3m
                                         */

                                        if (!vehicle_liftoff) {
                                                if (armed.armed && att_sp.thrust > params.minimum_liftoff_thrust && sonar_new > 0.3f && sonar_new < 1.0f) {
                                                        vehicle_liftoff = true;
                                                }

                                        } else {
                                                if (!armed.armed || (att_sp.thrust < params.minimum_liftoff_thrust && sonar_new <= 0.3f)) {
                                                        vehicle_liftoff = false;
                                                }
                                        }

                                        /* calc dt between flow timestamps */
                                        /* ignore first flow msg */
                                        if (time_last_flow == 0) {
                                                time_last_flow = flow.timestamp;
                                                continue;
                                        }

                                        dt = (float)(flow.timestamp - time_last_flow) * time_scale ;
                                        time_last_flow = flow.timestamp;

                                        /* only make position update if vehicle is lift off or DEBUG is activated*/
                                        if (vehicle_liftoff || params.debug) {
                                                /* copy flow */
                                                if (flow.integration_timespan > 0) {
                                                        flow_speed[0] = flow.pixel_flow_x_integral / (flow.integration_timespan / 1e6f) * flow.ground_distance_m;
                                                        flow_speed[1] = flow.pixel_flow_y_integral / (flow.integration_timespan / 1e6f) * flow.ground_distance_m;

                                                } else {
                                                        flow_speed[0] = 0;
                                                        flow_speed[1] = 0;
                                                }

                                                flow_speed[2] = 0.0f;

                                                /* convert to bodyframe velocity */
                                                for (uint8_t i = 0; i < 3; i++) {
                                                        float sum = 0.0f;

                                                        for (uint8_t j = 0; j < 3; j++) {
                                                                sum = sum + flow_speed[j] * rotM_flow_sensor[j];
                                                        }

                                                        speed = sum;
                                                }

                                                /* update filtered flow */
                                                filtered_flow.sumx = filtered_flow.sumx + speed[0] * dt;
                                                filtered_flow.sumy = filtered_flow.sumy + speed[1] * dt;
                                                filtered_flow.vx = speed[0];
                                                filtered_flow.vy = speed[1];

                                                // TODO add yaw rotation correction (with distance to vehicle zero)

                                                /* convert to globalframe velocity
                                                 * -> local position is currently not used for position control
                                                 */
                                                for (uint8_t i = 0; i < 3; i++) {
                                                        float sum = 0.0f;

                                                        for (uint8_t j = 0; j < 3; j++) {
                                                                sum = sum + speed[j] * PX4_R(att.R, i, j);
                                                        }

                                                        global_speed = sum;
                                                }

                                                local_pos.x = local_pos.x + global_speed[0] * dt;
                                                local_pos.y = local_pos.y + global_speed[1] * dt;
                                                local_pos.vx = global_speed[0];
                                                local_pos.vy = global_speed[1];
                                                local_pos.xy_valid = true;
                                                local_pos.v_xy_valid = true;

                                        } else {
                                                /* set speed to zero and let position as it is */
                                                filtered_flow.vx = 0;
                                                filtered_flow.vy = 0;
                                                local_pos.vx = 0;
                                                local_pos.vy = 0;
                                                local_pos.xy_valid = false;
                                                local_pos.v_xy_valid = false;
                                        }

                                        /* filtering ground distance */
                                        if (!vehicle_liftoff || !armed.armed) {
                                                /* not possible to fly */
                                                sonar_valid = false;
                                                local_pos.z = 0.0f;
                                                local_pos.z_valid = false;

                                        } else {
                                                sonar_valid = true;
                                        }

                                        if (sonar_valid || params.debug) {
                                                /* simple lowpass sonar filtering */
                                                /* if new value or with sonar update frequency */
                                                if (sonar_new != sonar_last || counter % 10 == 0) {
                                                        sonar_lp = 0.05f * sonar_new + 0.95f * sonar_lp;
                                                        sonar_last = sonar_new;
                                                }

                                                float height_diff = sonar_new - sonar_lp;

                                                /* if over 1/2m spike follow lowpass */
                                                if (height_diff < -params.sonar_lower_lp_threshold || height_diff > params.sonar_upper_lp_threshold) {
                                                        local_pos.z = -sonar_lp;

                                                } else {
                                                        local_pos.z = -sonar_new;
                                                }

                                                local_pos.z_valid = true;
                                        }

                                        filtered_flow.timestamp = hrt_absolute_time();
                                        local_pos.timestamp = hrt_absolute_time();

                                        /* publish local position */
                                        if (isfinite(local_pos.x) && isfinite(local_pos.y) && isfinite(local_pos.z)
                                            && isfinite(local_pos.vx) && isfinite(local_pos.vy)) {
                                                orb_publish(ORB_ID(vehicle_local_position), local_pos_pub, &local_pos);
                                        }

                                        /* publish filtered flow */
                                        if (isfinite(filtered_flow.sumx) && isfinite(filtered_flow.sumy) && isfinite(filtered_flow.vx)
                                            && isfinite(filtered_flow.vy)) {
                                                orb_publish(ORB_ID(filtered_bottom_flow), filtered_flow_pub, &filtered_flow);
                                        }

                                        /* measure in what intervals the position estimator runs */
                                        perf_count(mc_interval_perf);
                                        perf_end(mc_loop_perf);

                                }
                        }

                } else {
                        /* sensors not ready waiting for first attitude msg */

                        /* polling */
                        struct pollfd fds[1] = {
                                { .fd = vehicle_attitude_sub, .events = POLLIN },
                        };

                        /* wait for a attitude message, check for exit condition every 5 s */
                        int ret = poll(fds, 1, 5000);

                        if (ret < 0) {
                                /* poll error, count it in perf */
                                perf_count(mc_err_perf);

                        } else if (ret == 0) {
                                /* no return value, ignore */
                                printf("[flow position estimator] no attitude received.\n");

                        } else {
                                if (fds[0].revents & POLLIN) {
                                        sensors_ready = true;
                                        printf("[flow position estimator] initialized.\n");
                                }
                        }
                }

                counter++;
        }

        printf("[flow position estimator] exiting.\n");
        thread_running = false;

        close(vehicle_attitude_setpoint_sub);
        close(vehicle_attitude_sub);
        close(armed_sub);
        close(control_mode_sub);
        close(parameter_update_sub);
        close(optical_flow_sub);

        perf_print_counter(mc_loop_perf);
        perf_free(mc_loop_perf);

        fflush(stdout);
        return 0;
}


出0入0汤圆

 楼主| 发表于 2015-7-29 13:12:29 | 显示全部楼层
更新RAD帧读取:

FLOW flow;
FLOW_RAD flow_rad;
FLOW_FIX flow_fix;
u8 FLOW_STATE[4];
u8 flow_buf[27];
u8 flow_buf_rad[45];
   float ByteToFloat(unsigned char* byteArry)
{
  return *((float*)byteArry);
}

#define  IIR_ORDER     4      //使用IIR滤波器的阶数
static double b_IIR[IIR_ORDER+1] ={0.0008f, 0.0032f, 0.0048f, 0.0032f, 0.0008f};  //系数b
static double a_IIR[IIR_ORDER+1] ={1.0000f, -3.0176f, 3.5072f, -1.8476f, 0.3708f};//系数a
static double InPut_IIR[4][IIR_ORDER+1] = {0};
static double OutPut_IIR[4][IIR_ORDER+1] = {0};



void FLOW_MAVLINK(unsigned char data)
{
/*
红色的是起始标志位(stx),在v1.0版本中以“FE”作为起始标志。这个标志位在mavlink消息帧接收端进行消息解码时有用处。

第二个格子代表的是灰色部分(payload,称作有效载荷,要用的数据在有效载荷里面)的字节长度(len),范围从0到255之间。在mavlink消息帧接收端可以用它和实际收到的有效载荷的长度比较,以验证有效载荷的长度是否正确。

第三个格子代表的是本次消息帧的序号(seq),每次发完一个消息,这个字节的内容会加1,加到255后会从0重新开始。这个序号用于mavlink消息帧接收端计算消息丢失比例用的,相当于是信号强度。

第四个格子代表了发送本条消息帧的设备的系统编号(sys),使用PIXHAWK刷PX4固件时默认的系统编号为1,用于mavlink消息帧接收端识别是哪个设备发来的消息。

第五个格子代表了发送本条消息帧的设备的单元编号(comp),使用PIXHAWK刷PX4固件时默认的单元编号为50,用于mavlink消息帧接收端识别是设备的哪个单元发来的消息(暂时没什么用) 。

第六个格子代表了有效载荷中消息包的编号(msg),注意它和序号是不同的,这个字节很重要,mavlink消息帧接收端要根据这个编号来确定有效载荷里到底放了什么消息包并根据编号选择对应的方式来处理有效载荷里的信息包。
      26*/                 
// FE 1A| A2 X X| 64

static u8 s_flow=0,data_cnt=0;
u8 cnt_offset=0;       
u8 get_one_fame=0;
char floattobyte[4];
                switch(s_flow)
         {
    case 0: if(data==0xFE)
                        s_flow=1;
                        break;
                case 1: if(data==0x1A||data==0x2C)
                                { s_flow=2;}
                        else
                        s_flow=0;
                        break;
          case 2:
                        if(data_cnt<4)
                        {s_flow=2; FLOW_STATE[data_cnt++]=data;}
                  else
                        {data_cnt=0;s_flow=3;flow_buf[data_cnt++]=data;}
                 break;
                case 3:
                 if(FLOW_STATE[3]==100){
                        if(data_cnt<26)
                        {s_flow=3; flow_buf[data_cnt++]=data;}
                  else
                        {data_cnt=0;s_flow=4;}
                }
                else if(FLOW_STATE[3]==106){
                        if(data_cnt<44)
                        {s_flow=3; flow_buf_rad[data_cnt++]=data;}
                  else
                        {data_cnt=0;s_flow=4;}
                }
                else
                        {data_cnt=0;s_flow=0;}
                         break;
                case 4:get_one_fame=1;s_flow=0;data_cnt=0;break;
                default:s_flow=0;data_cnt=0;break;
         }//--end of s_uart
               

         if(get_one_fame)
         {
                 if(FLOW_STATE[3]==100){
                flow.time_sec=(flow_buf[7]<<64)|(flow_buf[6]<<56)|(flow_buf[5]<<48)|(flow_buf[4]<<40)
                 |(flow_buf[3]<<32)|(flow_buf[2]<<16)|(flow_buf[1]<<8)|(flow_buf[0]);
           floattobyte[0]=flow_buf[8];
                 floattobyte[1]=flow_buf[9];
                 floattobyte[2]=flow_buf[10];
                 floattobyte[3]=flow_buf[11];
                flow.flow_comp_x.originf =ByteToFloat(floattobyte);
                 floattobyte[0]=flow_buf[12];
                 floattobyte[1]=flow_buf[13];
                 floattobyte[2]=flow_buf[14];
                 floattobyte[3]=flow_buf[15];
                flow.flow_comp_y.originf =ByteToFloat(floattobyte);
                 floattobyte[0]=flow_buf[16];
                 floattobyte[1]=flow_buf[17];
                 floattobyte[2]=flow_buf[18];
                 floattobyte[3]=flow_buf[19];
           flow.hight.originf=ByteToFloat(floattobyte);//ground_distance        float        Ground distance in m. Positive value: distance known. Negative value: Unknown distance     
           flow.flow_x.origin=(int16_t)((flow_buf[20])|(flow_buf[21]<<8));
           flow.flow_y.origin=(int16_t)((flow_buf[22])|(flow_buf[23]<<8));
                 flow.id=flow_buf[24];
           flow.quality=flow_buf[25]; //Optical flow quality / confidence. 0: bad, 255: maximum quality
                flow_fix.flow_x.average                  = IIR_I_Filter(flow_fix.flow_x.origin , InPut_IIR[0], OutPut_IIR[0], b_IIR, IIR_ORDER+1, a_IIR, IIR_ORDER+1);
                flow.flow_y.average                  = IIR_I_Filter(flow.flow_y.origin , InPut_IIR[1], OutPut_IIR[1], b_IIR, IIR_ORDER+1, a_IIR, IIR_ORDER+1);
                flow.flow_comp_x.average = IIR_I_Filter(flow.flow_comp_x.originf , InPut_IIR[2], OutPut_IIR[2], b_IIR, IIR_ORDER+1, a_IIR, IIR_ORDER+1);
                flow.flow_comp_y.average = IIR_I_Filter(flow.flow_comp_y.originf , InPut_IIR[3], OutPut_IIR[3], b_IIR, IIR_ORDER+1, a_IIR, IIR_ORDER+1);
                }
         else if(FLOW_STATE[3]==106)
         {
                 flow_rad.time_usec=(flow_buf_rad[7]<<64)|(flow_buf_rad[6]<<56)|(flow_buf_rad[5]<<48)|(flow_buf_rad[4]<<40)
                 |(flow_buf_rad[3]<<32)|(flow_buf_rad[2]<<16)|(flow_buf_rad[1]<<8)|(flow_buf_rad[0]);
           flow_rad.integration_time_us=(flow_buf_rad[11]<<32)|(flow_buf_rad[10]<<16)|(flow_buf_rad[9]<<8)|(flow_buf_rad[8]);
                 floattobyte[0]=flow_buf_rad[12];
                 floattobyte[1]=flow_buf_rad[13];
                 floattobyte[2]=flow_buf_rad[14];
                 floattobyte[3]=flow_buf_rad[15];
                 flow_rad.integrated_x=ByteToFloat(floattobyte);
                 floattobyte[0]=flow_buf_rad[16];
                 floattobyte[1]=flow_buf_rad[17];
                 floattobyte[2]=flow_buf_rad[18];
                 floattobyte[3]=flow_buf_rad[19];
                 flow_rad.integrated_y=ByteToFloat(floattobyte);
                 floattobyte[0]=flow_buf_rad[20];
                 floattobyte[1]=flow_buf_rad[21];
                 floattobyte[2]=flow_buf_rad[22];
                 floattobyte[3]=flow_buf_rad[23];
                 flow_rad.integrated_xgyro=ByteToFloat(floattobyte);
                 floattobyte[0]=flow_buf_rad[24];
                 floattobyte[1]=flow_buf_rad[25];
                 floattobyte[2]=flow_buf_rad[26];
                 floattobyte[3]=flow_buf_rad[27];
                 flow_rad.integrated_ygyro=ByteToFloat(floattobyte);
                 floattobyte[0]=flow_buf_rad[28];
                 floattobyte[1]=flow_buf_rad[29];
                 floattobyte[2]=flow_buf_rad[30];
                 floattobyte[3]=flow_buf_rad[31];
                 flow_rad.integrated_zgyro=ByteToFloat(floattobyte);
                 flow_rad.time_delta_distance_us=(flow_buf_rad[35]<<32)|(flow_buf_rad[34]<<16)|(flow_buf_rad[33]<<8)|(flow_buf_rad[32]);
                 floattobyte[0]=flow_buf_rad[36];
                 floattobyte[1]=flow_buf_rad[37];
                 floattobyte[2]=flow_buf_rad[38];
                 floattobyte[3]=flow_buf_rad[39];
                 flow_rad.distance=ByteToFloat(floattobyte);
                 flow_rad.temperature=(flow_buf_rad[41]<<8)|(flow_buf_rad[40]);
                 flow_rad.sensor_id=(flow_buf_rad[42]);
                 flow_rad.quality==(flow_buf_rad[43]);
                 
                 flow_fix.flow_x.origin =flow.flow_x.origin + flow_rad.integrated_ygyro*flow_fix.scale_rad_fix;
                 flow_fix.flow_y.origin =flow.flow_y.origin - flow_rad.integrated_xgyro*flow_fix.scale_rad_fix;
                 flow_fix.flow_comp_x.originf =flow.flow_comp_x.originf - flow_rad.integrated_ygyro*flow_fix.scale_rad_fix_comp;
                 flow_fix.flow_comp_y.originf =flow.flow_comp_y.originf + flow_rad.integrated_xgyro*flow_fix.scale_rad_fix_comp;
         }       
         }
}


头文件:
  typedef struct
{
        float average;//Flow in m in x-sensor direction, angular-speed compensated
        float originf;
        int16_t origin;
}FLOW_DATA;


  typedef struct
{
        uint64_t  time_sec;
        u8   id;
        FLOW_DATA flow_x;
        FLOW_DATA flow_y;
        FLOW_DATA flow_comp_x;//Flow in m in x-sensor direction, angular-speed compensated
        FLOW_DATA flow_comp_y;
        u8 quality; //Optical flow quality / confidence. 0: bad, 255: maximum quality
        FLOW_DATA hight;//ground_distance        float        Ground distance in m. Positive value: distance known. Negative value: Unknown distance               
}FLOW;

typedef struct
{
uint64_t time_usec; ///< Timestamp (microseconds, synced to UNIX time or since system boot)
uint32_t integration_time_us; ///< Integration time in microseconds. Divide integrated_x and integrated_y by the integration time to obtain average flow. The integration time also indicates the.
float integrated_x; ///< Flow in radians around X axis (Sensor RH rotation about the X axis induces a positive flow. Sensor linear motion along the positive Y axis induces a negative flow.)
float integrated_y; ///< Flow in radians around Y axis (Sensor RH rotation about the Y axis induces a positive flow. Sensor linear motion along the positive X axis induces a positive flow.)
float integrated_xgyro; ///< RH rotation around X axis (rad)
float integrated_ygyro; ///< RH rotation around Y axis (rad)
float integrated_zgyro; ///< RH rotation around Z axis (rad)
uint32_t time_delta_distance_us; ///< Time in microseconds since the distance was sampled.
float distance; ///< Distance to the center of the flow field in meters. Positive value (including zero): distance known. Negative value: Unknown distance.
int16_t temperature; ///< Temperature * 100 in centi-degrees Celsius
uint8_t sensor_id; ///< Sensor ID
uint8_t quality; ///< Optical flow quality / confidence. 0: no valid flow, 255: maximum quality
}FLOW_RAD;

  typedef struct
{
        FLOW_DATA flow_x;
        FLOW_DATA flow_y;
        FLOW_DATA flow_comp_x;//Flow in m in x-sensor direction, angular-speed compensated
        FLOW_DATA flow_comp_y;
        float scale_rad_fix;
        float scale_rad_fix_comp;
        FLOW_DATA hight;//ground_distance        float        Ground distance in m. Positive value: distance known. Negative value: Unknown distance               
}FLOW_FIX;

出0入0汤圆

 楼主| 发表于 2017-5-23 16:09:31 | 显示全部楼层
新贴连接https://www.amobbs.com/thread-5673935-1-1.html   提供px4flow 光流串口接受和预处理库函数 头文件里有调用方法

出0入0汤圆

发表于 2015-6-12 18:50:54 | 显示全部楼层
赞一个,支持

出0入0汤圆

发表于 2015-6-12 19:21:05 | 显示全部楼层
写的不错,就是字体太大了!

出0入0汤圆

发表于 2015-6-12 19:25:58 | 显示全部楼层
楼主牛人,支持楼主,打击JS!

出0入12汤圆

发表于 2015-6-12 19:29:58 | 显示全部楼层
自己赶紧改一下吧,看起来太费劲了。

出0入0汤圆

发表于 2015-6-12 20:54:43 | 显示全部楼层
不错的帖子

出0入0汤圆

发表于 2015-6-12 21:04:55 | 显示全部楼层
字体太大,改改吧

出0入0汤圆

发表于 2015-6-12 21:55:25 | 显示全部楼层
我已经移植到MDK下了

出0入0汤圆

发表于 2015-6-12 23:18:10 | 显示全部楼层
我也在入门,你是用PX4带的eclipse开发的吗

出0入0汤圆

 楼主| 发表于 2015-6-13 00:12:22 | 显示全部楼层
本质 发表于 2015-6-12 23:18
我也在入门,你是用PX4带的eclipse开发的吗

没有 我还没对那个有接触

出0入0汤圆

发表于 2015-6-13 10:24:15 | 显示全部楼层
PX4FLOW-FX版光流传感器,好像很不错,就是不知道有多精准

出0入0汤圆

发表于 2015-6-14 12:20:55 | 显示全部楼层
正准备用PX4 FLOW,好东西

出0入0汤圆

发表于 2015-6-14 21:43:10 | 显示全部楼层
楼主研究的很深入了,我一开始买了个开源固件的光流,但是效果真的好差,后来又买了一个应该是你说的那家动了手脚的,主要是急着用就没有研究,现在是用串口接收,楼主用I2C实现了吗?我看I2C很简单,但是不行,不就是先写地址0X42,再写0,再读数据吗?

出0入0汤圆

发表于 2015-6-14 23:10:39 | 显示全部楼层
楼主研究PixHawk飞控吗?  看了好久现在还没太整明白飞控的程序架构   想做二次开发,可迟迟不能上手

出0入0汤圆

发表于 2015-6-15 00:27:20 | 显示全部楼层
我估计是固件的问题,刷了继续

出0入0汤圆

发表于 2015-6-15 00:31:40 | 显示全部楼层
fengshao1370 发表于 2015-6-14 21:43
楼主研究的很深入了,我一开始买了个开源固件的光流,但是效果真的好差,后来又买了一个应该是你说的那家动 ...

0X42是读的地址,他是7位地址。末尾代表读或者写。 给0X43那就是向SLAVE(从)里面写数据了。 表示没弄出来

出0入0汤圆

发表于 2015-6-15 00:50:41 | 显示全部楼层
  if(FLOW_STATE[3]=100){
                        if(data_cnt<26)  这里是写错了吧。。。  该是  if(FLOW_STATE[3]==100)吧。。。

出0入0汤圆

 楼主| 发表于 2015-6-15 10:32:38 | 显示全部楼层
面向大海 发表于 2015-6-14 23:10
楼主研究PixHawk飞控吗?  看了好久现在还没太整明白飞控的程序架构   想做二次开发,可迟迟不能上手 ...

我没用过 都是自己尝试开发  但是做的也不好

出0入0汤圆

 楼主| 发表于 2015-6-15 10:42:04 | 显示全部楼层
fengshao1370 发表于 2015-6-14 21:43
楼主研究的很深入了,我一开始买了个开源固件的光流,但是效果真的好差,后来又买了一个应该是你说的那家动 ...

没用i2c 板子上串口多 用起来方便

出0入0汤圆

 楼主| 发表于 2015-6-15 10:42:45 | 显示全部楼层
Hgww_MKV 发表于 2015-6-15 00:50
if(FLOW_STATE[3]=100){
                        if(data_cnt

是的是的是的是的是的是的是的是的是的

出0入0汤圆

发表于 2015-6-15 10:43:47 | 显示全部楼层
楼主好人,有时间看看

出0入0汤圆

发表于 2015-6-15 10:45:21 | 显示全部楼层
楼主绝对是牛人

出0入0汤圆

发表于 2015-6-15 10:52:42 | 显示全部楼层
楼主好人
好帖留名。

出0入0汤圆

 楼主| 发表于 2015-6-15 11:06:00 | 显示全部楼层
通过光流测试波形可以看到,光流传感器非常容易受外界干扰,传感器上下移动,倾斜和左右旋转都会造成读数大幅移动,原因第一是本身图形的变化第二是光流算法中用到了陀螺仪读数和高度对图像光流的变化进行的修正,因此我感觉光流传感器只能用于定点悬停,想超过惯性导航无GPS下自主巡航貌似不太靠谱,需要一套非常完整的机制来确定什么时候该用光流传感器输出的速度和对特殊情况下的(光流数据容易受干扰)的滤波

出0入0汤圆

发表于 2015-6-18 17:36:02 | 显示全部楼层
楼主威武!!!正在调

出0入0汤圆

发表于 2015-6-19 12:53:05 | 显示全部楼层
楼主 我用你的固件和官方的固件没有 FLOW_m_COMP_x, 和 FLOW_m_COMP_x输出  只有FLOW_X 和FLOW_y输出。 不知道是哪里没有使能还是怎么的。   楼主的光流能给个图片看看吗

出0入0汤圆

 楼主| 发表于 2015-6-19 16:34:42 | 显示全部楼层
Hgww_MKV 发表于 2015-6-19 12:53
楼主 我用你的固件和官方的固件没有 FLOW_m_COMP_x, 和 FLOW_m_COMP_x输出  只有FLOW_X 和FLOW_y输出。 不 ...

你如果没装超声模块 没有那个数据是正常的 因为光流算法中用到高度值来计算位移速度  没有高度值 只能输出图形中光流像素的位移量 你可以参考源码在主控制器外围添加淘宝上便宜的传感器 计算出速度

出0入0汤圆

发表于 2015-6-24 22:05:43 | 显示全部楼层
楼主的固件刷新率只有10到20HZ  完全不能满足需要啊  

出0入0汤圆

发表于 2015-6-27 08:59:10 来自手机 | 显示全部楼层
刷官方固件,用楼主参数,不行呀

出0入0汤圆

发表于 2015-7-3 20:01:55 | 显示全部楼层
感谢楼主分享啊,本来都快对光流放弃了,现在感觉又有阳光了

出0入0汤圆

发表于 2015-7-3 20:03:06 | 显示全部楼层
还有我想问下楼主这个px4flow怎么下程序那,用串口的mcuisp下吗

出0入0汤圆

发表于 2015-7-3 20:39:53 | 显示全部楼层
呵呵,找到哦怎么修改了,跟改apm参数差不多,逗比了。

出0入0汤圆

发表于 2015-7-10 16:54:59 | 显示全部楼层
请问左右周期运动是指左右平移还是原地左右转动?我尝试了下左右平移时波形变化不大,左右转动倒是波形和楼主差不多

出0入0汤圆

发表于 2015-7-10 17:11:52 | 显示全部楼层
我已经把光流的代码移植到MDK下面了,并做了优化

出0入0汤圆

 楼主| 发表于 2015-7-11 10:47:27 | 显示全部楼层
quzhanguang3 发表于 2015-7-10 16:54
请问左右周期运动是指左右平移还是原地左右转动?我尝试了下左右平移时波形变化不大,左右转动倒是波形和楼 ...

平移平移平移平移

出0入0汤圆

 楼主| 发表于 2015-7-11 10:47:50 | 显示全部楼层
nongxiaoming 发表于 2015-7-10 17:11
我已经把光流的代码移植到MDK下面了,并做了优化

能分享下工程吗

出0入0汤圆

发表于 2015-7-11 17:36:30 | 显示全部楼层
虽然看不懂。但是觉得很厉害。。

出0入0汤圆

发表于 2015-7-12 00:02:08 | 显示全部楼层
楼主,刚上手这个模块想请问下光流用作定点悬浮应该大概是一个怎么样的思路?能从里面读出flow_x和flow_y的读数,但从qground看波形扰动太大了…真的能做定点悬浮吗?那个平移距离应该怎么算?谢谢赐教!

出0入0汤圆

 楼主| 发表于 2015-7-15 09:29:27 | 显示全部楼层
开放实验室小组 发表于 2015-7-12 00:02
楼主,刚上手这个模块想请问下光流用作定点悬浮应该大概是一个怎么样的思路?能从里面读出flow_x和flow_y的 ...

我还没弄 ,要悬停先要消除左右倾斜时也会输出速度,我开启了模块里的角度修正但是没什么卵子用,如果你给角度控制量限幅的很小然后只在悬停状态来使用应该直接用光流输出速度做反馈加上一个速度闭环就行,但是我想还是把光流像素位移量读出来自己做修正计算速度具体方法可以参照:http://copter.ardupilot.cn/wiki/optical-flow-sensor/#_APM25

出0入0汤圆

发表于 2015-7-16 14:27:50 | 显示全部楼层
楼主你好,我是新手刚学习px4flow模块,用你的固件可以读出flow_x和flow_y,可以分享下楼主的工程吗?想修改一下固件代码

出0入0汤圆

发表于 2015-7-18 02:19:56 | 显示全部楼层
楼主你好,我用你的px4flow接收程序可以读出你的固件里面flow_x和flow_y的值但是却读不出官方固件的值,想问一下楼主是改了源程序里面的发送格式吗,可是我对着看的官方程序的发送格式和你的接收程序是对应的啊,谢谢楼主指点

出0入0汤圆

 楼主| 发表于 2015-7-18 15:56:55 | 显示全部楼层
yangchang66 发表于 2015-7-18 02:19
楼主你好,我用你的px4flow接收程序可以读出你的固件里面flow_x和flow_y的值但是却读不出官方固件的值,想 ...

没改  读不出哪个值

出0入0汤圆

发表于 2015-7-18 16:34:23 | 显示全部楼层
golaced 发表于 2015-7-18 15:56
没改  读不出哪个值

就是用你的px4flow接收程序读不出官方固件的flow_x和flow_y值,但是可以读出你的固件里面flow_x和flow_y的值,是因为传感器参数的原因吗

出0入0汤圆

 楼主| 发表于 2015-7-18 22:25:16 | 显示全部楼层
yangchang66 发表于 2015-7-18 16:34
就是用你的px4flow接收程序读不出官方固件的flow_x和flow_y值,但是可以读出你的固件里面flow_x和flow_y ...

在v1.0版本中以“FE”作为起始标志  不知道你的版本是什么的V0.9  是0x55

出0入0汤圆

发表于 2015-7-19 23:55:08 | 显示全部楼层
golaced 发表于 2015-7-18 22:25
在v1.0版本中以“FE”作为起始标志  不知道你的版本是什么的V0.9  是0x55

谢谢楼主了,我们找到原因了,是因为参数给的不对导致接收的数据有问题,换了楼主的参数就可以接收数据了,现在正在修改超声波代码,准备装一个廉价超声波上去。

出0入0汤圆

发表于 2015-7-20 15:44:11 | 显示全部楼层
楼主的飞控板是什么芯片《光流和飞控是用串口通信么?

出0入0汤圆

 楼主| 发表于 2015-7-20 18:40:20 | 显示全部楼层
Simon_起誓 发表于 2015-7-20 15:44
楼主的飞控板是什么芯片《光流和飞控是用串口通信么?

我的飞控是stm32f407Vgt 是串口通信

出0入0汤圆

发表于 2015-7-20 19:49:37 | 显示全部楼层
golaced 发表于 2015-7-20 18:40
我的飞控是stm32f407Vgt 是串口通信

171215925@qq.com串口通信的.c文件能给我参考一下么 本人学生

出0入0汤圆

发表于 2015-7-21 09:57:04 | 显示全部楼层
up!!!!

出0入0汤圆

 楼主| 发表于 2015-7-21 15:00:11 | 显示全部楼层
Simon_起誓 发表于 2015-7-20 19:49
串口通信的.c文件能给我参考一下么 本人学生

前面有代码

出0入0汤圆

发表于 2015-7-22 14:15:07 | 显示全部楼层
成功读取..楼主能解释一下 flow_x,flow_y, flow_comp_x,flow_comp_y具体含义么怎么融合到定点PID里

出0入0汤圆

发表于 2015-7-25 15:33:24 | 显示全部楼层
楼主试过用I2C读取数据吗?还有就是我买的不带超声波的版本,我准备外接一个便宜超声波传感器。然后再飞控里面来计算真是移动速度。摄像头焦距是16mm吧,我看到一个文献说的,真实移动速度=光流像素速度X(高度/焦距)。具体算法是什么呢

出0入0汤圆

发表于 2015-7-27 18:10:34 | 显示全部楼层
楼主你好,我用的这个软件V2.60的,怎么把你的固件刷进去看看效果呀

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-7-29 11:30:15 | 显示全部楼层
学习了,谢谢楼主

出0入0汤圆

 楼主| 发表于 2015-7-29 13:11:24 | 显示全部楼层
正十七 发表于 2015-7-27 18:10
楼主你好,我用的这个软件V2.60的,怎么把你的固件刷进去看看效果呀

setup里的固件更新

出0入0汤圆

发表于 2015-7-29 13:13:59 | 显示全部楼层
楼主,你编译px4flow代码的环境是什么?

出0入0汤圆

 楼主| 发表于 2015-7-29 13:20:57 | 显示全部楼层
jssk01 发表于 2015-7-29 13:13
楼主,你编译px4flow代码的环境是什么?

我还没编译过  只是那模块直接用

出0入0汤圆

 楼主| 发表于 2015-7-29 13:22:25 | 显示全部楼层
cdut 发表于 2015-7-25 15:33
楼主试过用I2C读取数据吗?还有就是我买的不带超声波的版本,我准备外接一个便宜超声波传感器。然后再飞控 ...

FLOW  src 文件下 main。c里有像素换算速度的部分
const float focal_length_px = (12) / (4.0f * 6.0f) * 1000.0f; //original focal lenght: 12mm pixelsize: 6um, binning 4 enabled
         flow_compx = flow_fix.flow_x.origin / focal_length_px / (flow_rad.integration_time_us / 1000000.0f);

出0入0汤圆

发表于 2015-7-29 23:21:36 | 显示全部楼层
楼主的滤波处理函数IIR_I_Filter可以参考一下吗,谢谢

出0入0汤圆

 楼主| 发表于 2015-7-30 14:26:10 | 显示全部楼层
yangchang66 发表于 2015-7-29 23:21
楼主的滤波处理函数IIR_I_Filter可以参考一下吗,谢谢


/*====================================================================================================*/
/*====================================================================================================*
** 函数名称: IIR_I_Filter
** 功能描述: IIR直接I型滤波器
** 输    入: InData 为当前数据
**           *x     储存未滤波的数据
**           *y     储存滤波后的数据
**           *b     储存系数b
**           *a     储存系数a
**           nb     数组*b的长度
**           na     数组*a的长度
**           LpfFactor
** 输    出: OutData         
** 说    明: 无
** 函数原型: y(n) = b0*x(n) + b1*x(n-1) + b2*x(n-2) -
                    a1*y(n-1) - a2*y(n-2)
**====================================================================================================*/
/*====================================================================================================*/
double IIR_I_Filter(double InData, double *x, double *y, double *b, short nb, double *a, short na)
{
  double z1,z2;
  short i;
  double OutData;
  
  for(i=nb-1; i>0; i--)
  {
    x=x[i-1];
  }
  
  x[0] = InData;
  
  for(z1=0,i=0; i<nb; i++)
  {
    z1 += x*b;
  }
  
  for(i=na-1; i>0; i--)
  {
    y=y[i-1];
  }
  
  for(z2=0,i=1; i<na; i++)
  {
    z2 += y*a;
  }
  
  y[0] = z1 - z2;
  OutData = y[0];
   
  return OutData;
}

出0入0汤圆

发表于 2015-8-1 17:36:35 | 显示全部楼层
楼主的光流固件效果不错

出0入0汤圆

发表于 2015-8-3 20:32:41 | 显示全部楼层
开放实验室小组 发表于 2015-7-12 00:02
楼主,刚上手这个模块想请问下光流用作定点悬浮应该大概是一个怎么样的思路?能从里面读出flow_x和flow_y的 ...

你好,请问你的光流能实现悬停了么?效果怎么样呢?

出0入0汤圆

发表于 2015-8-3 23:16:38 | 显示全部楼层
ohyeahh 发表于 2015-8-1 17:36
楼主的光流固件效果不错

你好,能交流一下光流使用心得么?刚上手,望指导,感谢!594250997@qq.com

出0入0汤圆

发表于 2015-8-4 03:08:54 | 显示全部楼层
楼主,你好,请问参考手册中的《PX4、
PIXhawk(PIXRaptor)编译环境的建立及源码的下载编译》一文,百度了,没找到,在哪可以找到啊?如何打开源代码进行编译啊?

出0入0汤圆

 楼主| 发表于 2015-8-4 21:48:38 | 显示全部楼层
勤奋的MCU 发表于 2015-8-4 03:08
楼主,你好,请问参考手册中的《PX4、
PIXhawk(PIXRaptor)编译环境的建立及源码的下载编译》一文,百度了 ...

我还没试过

出0入0汤圆

发表于 2015-8-4 22:22:23 | 显示全部楼层
不知道发送出去的数据是什么数据,i2c读取的地址不知道怎么写

出0入0汤圆

发表于 2015-8-5 01:11:44 | 显示全部楼层

楼主,请问你程序里面的32的采样频率和CMOS的刷新频率是多少啊?

出0入0汤圆

发表于 2015-8-5 01:24:51 | 显示全部楼层

还有7天前更新的更新RAD帧读取里,关于IIR滤波的程序,固件里面是没有的吧?还有那个超声波与PX4FLOW是怎么连接的啊?感谢楼主,不吝赐教!

出0入0汤圆

发表于 2015-8-8 12:47:26 | 显示全部楼层
楼主,你更新的RAD帧读取的那段代码,后半段的代码程序里面读不出任何值。。。只有你最开始的代码读出了和你一样的值。。。但是看波形。。左右平移的时候波形变化好像没有啊。。。只有左右晃动才有波形。。。请问楼主这是何原因

出0入0汤圆

发表于 2015-8-20 09:00:39 | 显示全部楼层
好贴,感谢楼主,收藏了。

出0入0汤圆

发表于 2015-8-28 17:30:10 | 显示全部楼层
怎么我用console 老是编译出错了

出0入0汤圆

发表于 2015-9-25 16:03:12 | 显示全部楼层
你好,用了你的固件,顶不住啊。ps:我没用超声波,只用了一个光流模块。

出0入0汤圆

发表于 2015-9-25 18:14:01 | 显示全部楼层
勤奋的MCU 发表于 2015-8-3 20:32
你好,请问你的光流能实现悬停了么?效果怎么样呢?

你好,请问你现在实现光流定点了吗?有没有结合超声波使用?

出0入0汤圆

发表于 2015-10-28 14:41:10 | 显示全部楼层
好东西,mark了!

出0入0汤圆

发表于 2015-10-28 14:48:12 | 显示全部楼层
支持一个,收藏了

出0入0汤圆

发表于 2015-10-28 18:53:27 | 显示全部楼层
yuwangwangyu 发表于 2015-6-12 21:55
我已经移植到MDK下了

能把你的工程分享下吗?谢谢啦

出0入0汤圆

发表于 2015-10-28 19:15:59 | 显示全部楼层
顶一个,楼主研究的很认真,看似花了不少时间和心思

出0入0汤圆

发表于 2015-10-28 19:20:46 | 显示全部楼层
golaced 发表于 2015-6-15 11:06
通过光流测试波形可以看到,光流传感器非常容易受外界干扰,传感器上下移动,倾斜和左右旋转都会造成读数大 ...

这个数据本身就容易收到干扰,确实需要外围的传感器数据用来纠正,不过相对就复杂了很多

出0入0汤圆

发表于 2015-10-28 19:22:54 | 显示全部楼层
yuwangwangyu 发表于 2015-6-12 21:55
我已经移植到MDK下了

漂亮,对pix家的那种指令行的make方式确实反感,移植都需要哪些注意的呢,复杂程度如何,一直想移植,但是代码比较大,想找一个相对小一点的工程移植试试

出0入0汤圆

发表于 2015-10-29 13:19:52 | 显示全部楼层
问问十几块的那种能装到pix上用吗

出0入0汤圆

发表于 2015-10-29 22:06:19 | 显示全部楼层
意义不大用GPS就可以定的很稳

出0入0汤圆

 楼主| 发表于 2015-11-10 11:14:47 | 显示全部楼层

更新 光流定位测试视频 ,死区有点大定位调整不足
http://pan.baidu.com/s/1ntIS4fn

出0入0汤圆

 楼主| 发表于 2015-11-11 10:13:39 | 显示全部楼层
光棍节更新 光流定点视频 http://pan.baidu.com/s/15bO2E

出0入0汤圆

发表于 2015-11-14 10:31:33 | 显示全部楼层
光流悬停的飞控用的啥?apm吗

出0入0汤圆

 楼主| 发表于 2015-11-15 12:45:11 | 显示全部楼层
hemeizhi 发表于 2015-11-14 10:31
光流悬停的飞控用的啥?apm吗

自己的飞控 OLD-X

出0入0汤圆

发表于 2015-11-20 11:03:37 | 显示全部楼层
golaced 发表于 2015-11-11 10:13
光棍节更新 光流定点视频 http://pan.baidu.com/s/15bO2E

楼主,可以发最新的Flow固件测试吗?飞控代码flow_postion_estimat.c有修改吗?我室内测试过你的 “px4flow.zip (43.96 KB, 下载次数: 110) ”,在Loiter模式与STABILIZE模式差不多,定位效果不是很好,比室外GPS模式的(Loiter)模式差。

出0入0汤圆

 楼主| 发表于 2015-11-20 11:59:14 | 显示全部楼层
molys 发表于 2015-11-20 11:03
楼主,可以发最新的Flow固件测试吗?飞控代码flow_postion_estimat.c有修改吗?我室内测试过你的 “px4fl ...

你试试这个行不行

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-11-20 13:33:58 | 显示全部楼层
golaced 发表于 2015-11-20 11:59
你试试这个行不行

谢谢楼主!我先测试过,体验体验,再与你分享!

出0入0汤圆

发表于 2015-11-20 14:27:03 | 显示全部楼层
楼主,比以前改善了很多的,可以共享一下源代码?

出0入0汤圆

发表于 2015-11-20 22:56:20 | 显示全部楼层
golaced 发表于 2015-11-20 11:59
你试试这个行不行

楼主,新的固件,室内定位效果不错,请教楼主你在Flow-master 代码修改了哪些东西,可以详细说说吗?正在做课题报告,过几天上交;请楼主帮帮忙,我的邮箱1841523243@qq.com

出0入0汤圆

 楼主| 发表于 2015-11-21 15:48:08 | 显示全部楼层
molys 发表于 2015-11-20 22:56
楼主,新的固件,室内定位效果不错,请教楼主你在Flow-master 代码修改了哪些东西,可以详细说说吗?正在 ...

我也是在网上下的 你可以看看国外的论坛有没有人改过

出0入0汤圆

发表于 2015-11-22 09:46:22 | 显示全部楼层
golaced 发表于 2015-11-21 15:48
我也是在网上下的 你可以看看国外的论坛有没有人改过

无人机大神,请教大神国外哪一个网站,麻烦指点迷津!

出0入0汤圆

发表于 2015-11-23 16:32:09 | 显示全部楼层
golaced 发表于 2015-11-21 15:48
我也是在网上下的 你可以看看国外的论坛有没有人改过

楼主,新的固件,室内定位Loiter模式还是会漂,Loiter模式没有GPGS稳定。

出0入0汤圆

 楼主| 发表于 2015-11-23 20:14:22 | 显示全部楼层
molys 发表于 2015-11-23 16:32
楼主,新的固件,室内定位Loiter模式还是会漂,Loiter模式没有GPGS稳定。

zzzzzzzzzzzzzzzzzzzzzzzzzzz

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-11-24 09:14:50 | 显示全部楼层
golaced 发表于 2015-11-23 20:14
zzzzzzzzzzzzzzzzzzzzzzzzzzz

楼主,你好!你的这个固件将Flow-master的I2C关掉了吗?怎么I2C无数据出来呢?

出0入0汤圆

发表于 2015-11-24 09:52:20 | 显示全部楼层
golaced 发表于 2015-11-23 20:14
zzzzzzzzzzzzzzzzzzzzzzzzzzz

楼主,麻烦你不要关掉I2C通信,我的飞控板与flow-master是I2C通信的,飞控板测不了光流数据

出0入0汤圆

发表于 2015-11-24 15:20:13 | 显示全部楼层
本帖最后由 molys 于 2015-11-24 16:17 编辑
golaced 发表于 2015-11-23 20:14
zzzzzzzzzzzzzzzzzzzzzzzzzzz


楼主,在QGC上看图像质量,固件px4flow_hao1比固件pxflow_hao12好一些,但固件px4flow_hao1没有I2C通信,PIXHAWK 飞控光流通信是I2C,无法测试到实际结果,请不要屏蔽I2C.谢谢楼主,谢谢大神!

出0入0汤圆

 楼主| 发表于 2015-11-24 21:42:26 | 显示全部楼层
molys 发表于 2015-11-24 16:41
楼主,是加了如下文件吗:
#include
#include

同学  抱歉我也不怎么清楚光流的程序 那个hao1是飞行试验室的但是不用他们的光流硬件xy读数只是反了下向  你可以试试加上滤波会不会好一点,欢迎交流飞控其他方面的知识
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 08:39

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表