在日益发展的无人机、机器人及其他自主导航领域,光流技术以其独特的优势成为了实现精准定位和导航的关键技术之一。最近,我在一个项目中使用了湖南优象光流T1 Plus光流激光二合一模块,这款模块以其高效稳定的表现给我留下了深刻的印象。
首先,湖南优象光流T1 Plus模块的集成过程相当简便。模块与主控制器的接口设计合理,连接稳定可靠。通过简单的接口对接和电源连接,即可实现模块的快速集成。此外,模块还提供了详细的配置和指导,使得开发者能够迅速上手,无需花费过多的时间和精力在模块的集成和调试上。
在实际使用中,湖南优象光流T1 Plus模块的性能表现令人满意。光流模块通过捕捉地面纹理的变化,能够精确计算出无人机的速度和方向信息,为飞行控制提供了可靠的数据支持。激光模块则通过测量与障碍物的距离,实现了对周围环境的感知和避障功能。这两个功能的结合,使得无人机在飞行过程中能够自主规划路径,避开障碍物,实现了更加智能化的飞行控制。
UART 数据格式为 1 个起始位,8 个数据位,1 个停止位,无校验位,波特率为 115200。 VCC 为 5.0V 供电电源输入。5.0V 供电时最大功耗 0.5W。
此外,湖南优象光流T1 Plus模块还具备较高的稳定性和耐用性。在复杂的飞行环境中,模块能够保持稳定的性能输出,不易受到外部干扰的影响。同时,模块的结构设计合理,外壳坚固耐用,能够有效抵抗外界的冲击和振动。这使得模块在长期使用中能够保持良好的工作状态,为项目的稳定运行提供了有力的保障。
值得一提的是,湖南优象光流T1 Plus模块还提供了丰富的技术支持和售后服务。在使用过程中,我遇到了一些问题,通过联系公司的技术支持团队,我得到了及时有效的解答和帮助。此外,公司还提供了详细的文档和教程,帮助开发者更好地理解和使用模块。这种贴心的服务让我在使用过程中感受到了公司的专业和用心。
当然,湖南优象光流T1 Plus模块也并非完美无缺。在使用过程中,我发现模块的功耗稍高,对于某些对功耗要求较为严格的应用场景来说,可能需要考虑更加节能的解决方案。此外,模块的价格相对于其他同类产品来说略高,这也可能对部分预算有限的开发者造成一定的压力。
总的来说,湖南优象光流T1 Plus光流激光二合一模块是一款性能出色、易于集成和使用的光流模块。它以其高效稳定的表现和丰富的技术支持,为无人机、机器人等自主导航领域的开发者提供了有力的支持。虽然存在一些不足之处,但总体来说,它的优点远大于缺点,是一款值得推荐的产品。
通过这次使用体验,我深刻感受到了湖南优象光流T1 Plus模块在自主导航领域的重要性和优势。它不仅能够提供精确的定位和导航数据,还能够实现智能避障和路径规划,为无人机等设备的智能化发展提供了强大的动力。我相信,在未来的发展中,湖南优象光流T1 Plus模块将会得到更广泛的应用和推广,为无人机、机器人等领域的进步贡献更多的力量。
最后,我要感谢湖南优象公司提供如此出色的产品和技术支持。通过这次合作,我不仅获得了宝贵的实践经验,还深刻体会到了公司对产品质量的严格把控和对客户服务的用心。如果未来还有类似的项目需求,我一定会首先考虑使用湖南优象光流T1 Plus模块,并推荐给更多的同行和朋友。
如果您对湖南优象光流T1 Plus模块感兴趣,可以访问我们公司的淘宝店铺链接https://m.tb.cn/h.5AdxzVP?tk=7jMQWKz6yc8 CA6496
点击链接直接打开 或者 淘宝搜索直接打开,了解更多产品详情和购买信息。同时,我们也欢迎各位开发者在论坛等平台上分享自己的使用体验和技术心得,共同推动自主导航技术的发展和应用。
综上所述,湖南优象光流T1 Plus模块以其卓越的性能和稳定的表现,在自主导航领域展现了强大的潜力和优势。我相信,在未来的发展中,它将会继续为行业的进步和发展贡献更多的力量。
光流的安装方向必须是和机头保持水平或者垂直,具体方向可以根据飞机坐标系定义来修改原始数据的方向,我这里为了方便,就把光流模块上面的人形图的头为机头朝向;
视频效果:
下面是具体使用步骤
一、通过串口获取光流原始数据方法:
1:首先通过以字节为单位采用中断接收,14个字节为一包;
void OFGetByte(uint8_t data)
{
static uint8_t in_p=0,head_p = 0;
//
com_getdata[in_p++] = data;
in_p %= OF_BUFFER_NUM;
if(in_p == head_p)
{
if(
(com_getdata[CIRCLE_P(head_p ,0,OF_BUFFER_NUM)] == 0xFE)
&& (com_getdata[CIRCLE_P(head_p+1 ,0,OF_BUFFER_NUM)] == 0x0A)
&& (com_getdata[CIRCLE_P(head_p+13,0,OF_BUFFER_NUM)] == 0x55)
)
{
for(uint8_t i=0; i<OF_BUFFER_NUM; i++)
{
OF_DATA[i] = com_getdata[CIRCLE_P(head_p+i,0,OF_BUFFER_NUM)];
}
of_buf_update_cnt++;
}
else
{
head_p ++;
head_p %= OF_BUFFER_NUM;
}
}
}
2:得到数据包后,通过该函数解析数据包,先进行校验,校验通过后将光流原始数据取出;
static void ANO_OF_Data_Get(float *dT_s,u8 *of_data_buf)
{
static float offline_delay_time_s;
u8 XOR = 0;
if(of_buf_update_flag != BUF_UPDATE_CNT)
{
//
of_buf_update_flag = BUF_UPDATE_CNT;
//
XOR = of_data_buf[2];
for(u8 i = 3;i<12;i++)
{
XOR ^= of_data_buf[i];
}
//
if(XOR == of_data_buf[12])
{
//
of_data.updata ++;
//
of_data.valid = of_data_buf[10];
//
if(of_data.valid != 0xf5)
{
//
of_data.flow_x_integral = of_data.flow_y_integral = 0;
}
else
{
//
of_data.flow_x_integral = -(s16)(of_data_buf[4]|(of_data_buf[5]<<8));
//
of_data.flow_y_integral = -(s16)(of_data_buf[2]|(of_data_buf[3]<<8));
Laser_height_cm=(s16)(of_data_buf[8]|(of_data_buf[9]<<8))*0.1f;
}
//
of_data.it_ms = ((u16)(of_data_buf[6]|(of_data_buf[7]<<8)))/1000;
}
//
offline_delay_time_s = 0;
of_data.online = 1;
}
else
{
//null
if(offline_delay_time_s<1.0f)
{
offline_delay_time_s += *dT_s;
}
else//掉线
{
of_data.online = 0;
}
}
}
二、将获取到的原始数据进行融合imu信息和激光高度,得到估计的水平速度;
1:获取无人机的imu数据,并通过低通滤波使数据相位滞后以对齐光流数据的相位(调节滤波系数使得无人机在测试架上旋转时角速度和光流像素速度的波形相位基本对齐),并且对加速度机数据进行积分,得到速度;
static void OF_INS_Get(float *dT_s,float rad_ps_x,float rad_ps_y,float acc_wx,float acc_wy)//惯性数据获取
{
static float rad_ps_lpf[2];
//====RD
//低通滤波
//故意滞后为了对齐相位,这里换成零阶保持+FIFO效果更好。
LPF_1_(5.0f,*dT_s,rad_ps_x,rad_ps_lpf[0]);
LPF_1_(5.0f,*dT_s,rad_ps_y,rad_ps_lpf[1]);
// rad_ps_lpf[0] += 0.2f *(rad_ps_x - rad_ps_lpf[0]);
// rad_ps_lpf[1] += 0.2f *(rad_ps_y - rad_ps_lpf[1]);
//
of_rot_d_degs[0] = rad_ps_lpf[0] *DEG_PER_RAD ;
of_rot_d_degs[1] = rad_ps_lpf[1] *DEG_PER_RAD ;
//
// test_calibration[0] += OF_ROT_KA *rad_ps_x *DEG_PER_RAD *dT_s;
//====INS
//低通滤波
LPF_1_(5.0f,*dT_s,acc_wx,of_rdf.gnd_acc_est_w[X]);
LPF_1_(5.0f,*dT_s,acc_wy,of_rdf.gnd_acc_est_w[Y]);
//
for(u8 i = 0;i<2;i++)
{
//融合估计部分
of_rdf.gnd_vel_est_w[i] += of_rdf.gnd_acc_est_w[i] *(*dT_s);
}
}
2:对原始像素变化速度进行进行横滚和俯仰的旋转解耦(通过测试架调节参数使得旋转带来的光流数据变化基本消除),抵消无人机绕轴旋转引起的光流像素变化;
static void ANO_OF_Decouple(u8 *dT_ms)//旋转解耦
{
if(of_data.valid != 0xf5)
{
//
of_rdf.of_vel[X] = of_rdf.of_vel[Y] = 0;
//quality
if(of_rdf.quality>=5)
{
of_rdf.quality -= 5;
}
}
else
{
//
if(UPOF_UP_DW==0)
{
of_rdf.of_vel[X] = (1000/of_data.it_ms *of_data.flow_x_integral + UPOF_PIXELPDEG_X *of_rot_d_degs[Y] );
of_rdf.of_vel[Y] = (1000/of_data.it_ms *of_data.flow_y_integral - UPOF_PIXELPDEG_Y *of_rot_d_degs[X] );
}
else
{
of_rdf.of_vel[X] = -(1000/of_data.it_ms *of_data.flow_x_integral + UPOF_PIXELPDEG_X *of_rot_d_degs[Y] );
of_rdf.of_vel[Y] = (1000/of_data.it_ms *of_data.flow_y_integral + UPOF_PIXELPDEG_Y *of_rot_d_degs[X] );
}
//quality
if(of_rdf.quality<=250)
{
of_rdf.quality += 5;
}
}
}
3:高度解耦得到估计的水平航向速度,然后与加速度积分得到的速度数值进行PI互补融合,注意:这里由于加速度的坐标系为地理坐标系,所以需要把 光流估计得到的水平航向速度(即机头方向的水平速度和垂直于机头方向的水平速度)通过偏航数据转成地理坐标系的数据,再与加速度积分得到的速度进行互补融合,最后,因为控制程序需要的反馈数据还是水平航向坐标系的,故此,需要将融合出的水平速度转到水平航向坐标系下。
static void ANO_OF_Fusion(u8 *dT_ms,s32 ref_height_cm)//高度解耦得到估计速度,并且融合imu
{
static float F_KP,F_KI;
float dT_s = (*dT_ms)*1e-3f;
//
if(UPOF_UP_DW==0)
{
of_rdf.of_ref_height = LIMIT(ref_height_cm,20,500);//限制到20cm-500cm
}
else
{
of_rdf.of_ref_height = LIMIT((OBJREF_HEIGHT_CM - ref_height_cm),20,500);//限制到20cm-500cm
}
//
of_rdf.gnd_vel_obs_h[X] = UPOF_CMPPIXEL_X *of_rdf.of_vel[X] *of_rdf.of_ref_height;
of_rdf.gnd_vel_obs_h[Y] = UPOF_CMPPIXEL_Y *of_rdf.of_vel[Y] *of_rdf.of_ref_height;
//
h2w_2d_trans(of_rdf.gnd_vel_obs_h,imu_data.hx_vec,of_rdf.gnd_vel_obs_w);
//
switch(of_rdf.state)
{
case 0:
{
//
of_rdf.state = 1;
//
F_KP = FUS_KP;
//
F_KI = FUS_KI;
//
OF_INS_Reset();
//
}
break;
case 1:
{
//融合修正部分
//(这里开源最简单并且好用的PI互补融合,注意这里修正即取低频,取高频的估计的部分不在此处)
//==
//原始值无效时不修正
if(of_data.valid == 0xf5)
{
//
for(u8 i =0;i<2;i++)
{
//
of_fus_err[i] = of_rdf.gnd_vel_obs_w[i] - of_rdf.gnd_vel_est_w[i];
//
of_fus_err_i[i] += F_KI *of_fus_err[i] *dT_s;
of_fus_err_i[i] = LIMIT(of_fus_err_i[i],-100,100);
//
of_rdf.gnd_vel_est_w[i] += (of_fus_err[i] *F_KP + of_fus_err_i[i]) *dT_s;
}
}
//
w2h_2d_trans(of_rdf.gnd_vel_est_w,imu_data.hx_vec,of_rdf.gnd_vel_est_h);
//
}
break;
default://case 2:
{
//
// of_rdf.state = 1;
OF_INS_Reset();
}
break;
// default:break;
}
}