5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
查看: 21360|回复: 46
打印 上一主题 下一主题

导航基本算法

[复制链接]
跳转到指定楼层
楼主
发表于 2009-9-8 14:53 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
点击查看详情


    有了位置、高度、地速、空速、姿态,我们就可以根据这些参数来进行计算,控制飞机给出相应舵面,实现导航、定高的目的。

    最简单的导航算法只考虑当前飞机所在点和目标点。设想一下,飞机在空中飞行时,当前点和目标点的连线指定了飞机应该飞行的航向(即目标航向),如果要使飞机朝向目标点飞行,必须控制飞机转弯,使飞机航向与目标航向一致。

   为了准确描述航向,我们定义以正北为0度,顺时针起航向与正北的夹角为正,逆时针起航向与正北的夹角为负,这样将航向定义在-180度到+180度之间。这样,上例中,飞机的航向为90度,目标航向为120度左右。








    好了,当前飞机的航向我们可以从GPS航向里提取,我们记其为Hangxiang。下面我们怎么根据目标点和当前点的坐标来计算目标航向呢?我们把目标航向记为beta,于是航向偏差为beta-Hangxiang。
    记当前的经纬度为CurLongi、CurLatti,单位为度;目标点经纬度为tgtLongi、tgtLatti,单位为度。由平面几何的知识,我们计算反正切atan((tgtLongi-CurLongi)/(tgtLatti-CurLatti)),再经过象限处理,就可得到目标航向。



在实际程序中,我们是这样做的:
vectorLatti = tgtLatti - CurLatti;
vectorLongi = tgtLongi - CurLongi;
beta = CalAtanVector();   //计算vectorLongi、vectorLatti向量与正北的夹角
而CalAtanVector()函数如下:
float CalAtanVector(void) //计算vectorLongi/vectorLatti的反正切函数,返回范围在-PI~PI之间
{
float beta;
float lTemp;
if(vectorLatti > 0)
  bNorth = 1;
else
  bNorth = 0;

if(vectorLongi > 0)
  bEast = 1;
else
  bEast = 0;

vectorLatti = fabsf(vectorLatti);
vectorLongi = fabsf(vectorLongi);
vectorLongi = vectorLongi * COS_FACTOR;
if(vectorLongi > vectorLatti)
{
  lTemp = vectorLongi;
  vectorLongi = vectorLatti;
  vectorLatti = lTemp;
  bGT45 = 1;
}
else
{
  bGT45 = 0;
}
if (vectorLatti!=0)
  beta= atan(vectorLongi/vectorLatti);    //0~PI/4范围
else
  beta = PI/2;
if(bGT45)
  beta = PI/2 - beta;     //PI/4~PI/2范围
if(bNorth && bEast)
  beta = beta;      //0~PI/4范围
if(bNorth && !bEast)
  beta = 0 - beta;     //-PI/4~0范围
if(!bNorth && !bEast)
  beta = beta - PI;     //-PI~-3PI/4范围
if(!bNorth && bEast)
  beta = PI - beta;     //3PI/4~PI范围
return beta;
}
    其中出现了一个因数COS_FACTOR,这是当前纬度的余弦值。这是因为两点经度之差要乘以当前纬度的余弦值,才代表了两点水平距离之差。也就是说,同样的经度差,在赤道附近表征很大的距离,而在北极附近表征的距离就相对较小,这一点大家应该能理解。

    好了,现在已经得到了alpha = beta – Hangxiang,即为当前航向与目标航向的偏差角,当不需要压航线进行控制的时候,比如进行所点即所到、临时改变航点的时候,就可以用alpha作为PID控制的误差输入量,去计算应该给出的方向舵控制量(方向舵转弯时)或横滚坡度量(副翼转弯时)了。

    当需要压航线进行飞行的时候呢?同样,我们可以根据航线的上一个点(坐标记为tgtLongi_s,tgtLatti_s)和航线的当前点,按照同上的算法计算出当前航线与正北的夹角,记为beta2,如下:

  vectorLatti = tgtLatti - tgtLatti_s;
  vectorLongi = tgtLongi - tgtLongi_s;
  beta2 = CalAtanVector();  //航线与正北的夹角

    然后我们需要再计算一个重要的量——偏航距,即飞机所在点到航线的距离。需要压航线时,飞机需要尽快的回到航线上,而不仅仅是朝着目标点。

    我们用一个newdistance()函数来计算偏航距。大家可以回忆一下高中数学里的点到直线的距离公式:
float newdistance(void)  //计算当前点与当前航线的距离

{
float dis,sin_t,cos_t;
dis = sqrt( (tgtLatti - tgtLatti_s) * (tgtLatti - tgtLatti_s) + (tgtLongi - tgtLongi_s) * (tgtLongi - tgtLongi_s) * COS_FACTOR * COS_FACTOR );
if (dis!=0)
  {
   sin_t = (tgtLatti - tgtLatti_s) / dis;
   cos_t = (tgtLongi - tgtLongi_s) * COS_FACTOR / dis;
}
  else
  {
   sin_t = 0;
   cos_t = 0;
  }
dis = (CurLongi - tgtLongi) * sin_t * COS_FACTOR + (tgtLatti - CurLatti) * cos_t;
dis = fabsf(dis * 110000);
return dis;
}

    最后将dis乘以110000是因为在赤道上经纬度的1度对应110公里左右。

    有了偏航距,我们需要来判断,当偏航距大于一定域值时,目标航向不再是目标点与当前点连线与正北的夹角,而是航线与正北的夹角,再附加上一个修正量,这个修正量的目的是是飞机尽快回到航线上,并且大小与偏航距有关。根据这个逻辑,我们有以下的程序:

  tempj1 = beta - beta2;    //目标航向-航线航线,用以判断飞机在航线的左侧还是右侧
  tempj2 = Hangxiang - beta2;  //当前航线-航线航线,用以判断机头是否大致朝向目标点
  if (tempj1 > PI)  tempj1 = tempj1 - 2*PI; //将其化为-pi到pi之间;
  if (tempj1 < -PI) tempj1 = 2*PI + tempj1;
  if (tempj2 > PI)  tempj2 = tempj2 - 2*PI;
  if (tempj2 < -PI) tempj2 = 2*PI + tempj2;
  if ((fabsf(lDistance) > ParaDataInUse[15])&&(fabsf(tempj2) < 80*PI/180))  //如果飞机偏航距超过了域值,且大致方向正确,即机头已转过来了
  {
   BP = fabsf(lDistance)*ParaDataInUse[21]/64; //ParaDataInUse数组为可实时用地面站调整的参数
   if (BP > 60) BP = 60;  //航线航向上叠加的修正量限幅
   if (tempj1 < 0) //当前点在航线右边
    beta = beta2 - BP*PI/180;
   else     //当前点在航线左边
    beta = beta2 + BP*PI/180;   
  }
  else      //否则不考虑偏航距
  {
   beta = beta;
  }






   最后,航向偏差角alpha = beta – Hangxiang,再将alpha作为偏差量输入到PID函数里去,解算出当前的控制量,控制方向舵或副翼进行转弯。

评分

参与人数 2威望 +4 收起 理由
切风40.83 + 2 你发帖时我还不知道单片机,现在觉得你的资 ...
小布丁 + 2 【发贴鼓励】感谢分享,希望继续努力发更多 ...

查看全部评分

欢迎继续阅读楼主其他信息

47
发表于 2012-11-20 19:21 | 只看该作者
参观实习!
46
发表于 2012-6-9 08:29 | 只看该作者
赶紧记录,图片看不到
45
发表于 2012-5-29 21:31 | 只看该作者
不懂来学习的
44
发表于 2012-4-18 01:21 | 只看该作者
顶…
43
发表于 2012-3-25 22:42 | 只看该作者
不懂。学习
42
发表于 2012-3-24 08:57 | 只看该作者
简单入门
41
发表于 2011-5-29 00:10 | 只看该作者
:em24:
40
发表于 2011-5-18 11:34 | 只看该作者
你这个思想正是航线控制最经典的,不过再智能点的,还得加上姿态仪、陀螺仪、电源管理,你的思想我借鉴了,理论指导实践吗!!!
39
发表于 2011-5-14 14:04 | 只看该作者
太专业,太牛
38
发表于 2011-4-21 20:34 | 只看该作者
:em22:  新手   求基础知识!!!
37
发表于 2011-4-21 13:50 | 只看该作者
参考了.
36
发表于 2011-4-21 11:09 | 只看该作者
:em21:
35
发表于 2011-4-18 14:05 | 只看该作者
顶32楼的,very good.
34
发表于 2011-4-15 17:29 | 只看该作者

刚注册,留个脚印。

学习下,这个是智能的吗?
33
发表于 2011-3-31 22:52 | 只看该作者
:em26:
32
发表于 2011-3-17 20:00 | 只看该作者

回复 31楼 dancerindark 的帖子

嘿嘿 最简单的控制方法只是解决了能飞的问题,说出来大家都能看的懂,其实自控并没有那么难得。好多带返航的OSD都是用这样的方法。要避免侧风的影响就要用轨迹保持,让飞机始终保持在一条轨迹上飞行(暂时只考虑平面上的动作不讨论高度)。由航轨规划算法得出航行轨迹,不说转弯时的情况,在直线飞行的时候假设有侧风让飞机的飞行方向没发生变化的情况下平移了,那么我们首先算出飞机实际位置到规划直线的距离和飞行实际直线之后,在规划沿飞行方向在规划直线上距飞机位置X处找一点C,过点C作规划直线的垂线D。那么我们的飞行直线与D有交点这个交点和C就截取出一条线段E,计算E的长度。之后我们假设飞机向右转向了1°,我们继续计算新产生的E的长度,比两E作差(原来的减新的),我们就可以得出这次调整飞行该向哪个方向转向(正值的话向右,负值向左)之后开始转向并计算飞机到调整直线的距离在此距离小于一定值(还要注意飞行方向和调整直线的夹角)时开始反方向转向、当飞行方向和调整方向相同时保持此方向就行了。飞行方向发生变化的情况下首先调整飞行方向,让飞行方向和调整方向相同之后再进行上面的调整。
这样飞机的航行轨迹就被保持在一条有宽度的直线上了。。
31
发表于 2011-3-17 09:34 | 只看该作者

xesable

xesable兄,你那样做可能风一吹就差很远了,横偏距会越来越大
30
发表于 2011-3-15 14:27 | 只看该作者
直接做直线(初始点、终了点),算斜率,比较此斜率和飞行直线斜率大小就能知道该向那边转。。之后根据所差斜率与飞行距离确定转弯半径,实时计算飞行直线当目标点距离,当此距离达到一个值的时候改出转弯就行。。。简单的一个反馈控制而已。做简单了都不用姿态量的直接用GY401锁住副翼用方向舵进行转弯也没有危险。

[ 本帖最后由 xesable 于 2011-3-15 14:37 编辑 ]
29
发表于 2011-3-6 04:39 | 只看该作者
x y z θ φ ψ 先弄清楚
风轴系,体轴系,地面坐标系之间的坐标变换?
动力学方程?如何离散?
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /2 下一条

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