艾巴生活网

您现在的位置是:主页>科技 >内容

科技

基于python的目标跟踪(Python的自动追踪算法)

2024-12-02 17:35:04科技帅气的蚂蚁
这涉及到拦截导弹的自动跟踪。最近看到一个有趣的自动跟踪算法,一个Python的简单模拟版,分享给大家。在我们设计2D射击游戏时,经常会用到

基于python的目标跟踪(Python的自动追踪算法)

这涉及到拦截导弹的自动跟踪。最近看到一个有趣的自动跟踪算法,一个Python的简单模拟版,分享给大家。

在我们设计2D射击游戏时,经常会用到自动跟踪算法。这个听起来很高大上的东西,其实并不是军事专利。如果用数学方法求解,需要解微分方程。

它没有一些数学基础是很难算出来的。然而,当我们有一台电脑时,情况就不同了。依靠计算机极快的计算速度,利用微分的思想和一点三角学的知识就可以实现。

好了,事不宜迟,让看一下它的算法原理,看图:

后面会用到pygame来演示,他的坐标系是Y轴向下的,所以这里我们也用Y轴向下的坐标系。

算法的大致思路是根据上图将时间T分成足够小的段(例如1/1000,时间段越小越精确),每段构造成上图的三角形,从而计算出导弹下一个时间段的方向(即a)和距离(即vt=|AC|)。此时目标在第二时间段内移动,计算刚刚完成。

假设初始状态下导弹和目标的坐标分别为(x1,y1)和(x,y),构造一个直角三角形ABE。这个三角形用来求 a的正弦和余弦值,因为vt是我们自己设定的,所以我们需要计算A到C点的X和Y坐标移动了多少,移动的值就是AD和CD的长度,可以分别乘以cosa和sina乘以vt。

计算sina和cosa,正弦对比是斜的,余弦相邻对比是斜的,斜边可以用两点距离公式计算,即:

因此

AC的长度就是导弹的速度乘以时间|AC|=vt,然后就可以计算出AD和CD的长度。所以这个时间片过去后,导弹应该出现在新的位置C,它的坐标是旧点A的X加AD,Y减CD。

所以,C点的新坐标是:

就一直重复这个操作。好吧,为了更形象,把第一个时间片和第二个时间片放在一起看一下:

首先是时间片构建的三角形是ABE。一个时间片后,目标从B点到D点,此时导弹在C点,那么构造一个新的三角形CDF,重复刚才的计算过程。

图中的角度b是导弹需要旋转的角度。实际上,只需要在每个时间片上校正导弹的方向。如何让导弹改变方向,不是我们需要研究的问题。

好吧,既然Python 最近用s pygame库做小游戏玩,接下来我们就用pygame来演示这个效果。效果如下:

简单的代码如下:

importpygame,sysfrommathimport * py game . init()screen=py game . display . set _ mode((800,700),0,32)missile=py game . image . load(element/red _ pointer . png ).convert_alpha()x1,y1=100,初始发射位置60 #导弹速度=800#导弹速度时间=1/1000#每个时间片的长度Clock=py game . time . Clock()old _ angle=0 while true:forevent inpygame . event . Get():if event . type==py game . quit:sys . exit()Clock . tick(300)x,y=pygame.mouse.get _ pos () #获取鼠标位置,鼠标为要打击的目标。Distance=sqrt (power (x1-x,2) power (y1-1) 2) #两点距离公式section=velocity * time # distance Sina=(Y1-y)/distance cosa=(x-x1)/distance angle=atan2(y-Y1,x-x1) # radian value x1,y1=(x1 section*cosa,Y1-section * Sina)d _ angle=degrees(angle)# radian to angle screen . blit(miss,(x1-miss . get _ width),Y1-miss。get _ height()/2))dis _ angle=d _ angle-old _ angle # dis _ angle是需要换到下一个位置的角度。old_angle=d_angle#更新初始角度pygame.display.update()

如果只把导弹看成一个质点,那么上面的算法就足够了。我没有不要旋转导弹,因为一个粒子不会不管它的头和尾,都不需要旋转。当然,这预先假定它不会如果你加载的导弹图像很小,这看起来不是问题。

但是它在pygame中旋转不容易(或者可能我我很无知)。好吧,让先把图片换成长方形的,再加上旋转功能,看看效果如何。

missiled=pygame . transform . rotate(missile,-(d _ angle))screen . blit(missiled,(x1-missile.get_width()、y1-missile.get_height()/2))

因为图片的坐标点是其左上角的点,如果我们想让图片的坐标固定在箭头的尖点,那么就把图片的实际打印位置X减少图片的长度,y减少一半的宽度。

但实际操作效果并不好:

方向大致相同,但图中箭头的尖点没有不要总是跟着鼠标走。为什么?经过我的研究(它还没有因为这个问题还没有发表。尚未解决),

我发现是这张图旋转的机制。让让我们看看旋转后的图片是什么样的:

在旋转后的图像变为蓝色的范围内,图像的尺寸根据旋转角度而变得不同。让让我们看看90度的旋转:

我们发现旋转后的图像不仅放大了区域,还改变了导弹头部的位置。那么应该如何解决这个问题呢?其思路是,每次旋转图片后,找出旋转图片头部的位置(图中绿色箭头点),然后移动绿色图片的打印位置,使旋转后的导弹头部与我们实际参与计算的导弹头部位置对齐。运动之后,应该是这样的:

这样两个导弹头的点就重合了。接下来,我们分析寻找旋转的导弹头的算法。根据旋转角度的不同,不同象限的旋转角度的参数是不同的,所以我们可以分为这四种情况。

1、2象限:

象限3,4,它的旋转只有正负0-180,所以象限3,4为负角。

当图片显示时,我们移动它。

screen.blit(missiled,(x1-width (x1-C[0]),y1-height/2 (y1-C[1]))

这里的(x1-宽度,y1-高度/2)其实就是上图中的(x1,y1)。

所以最后我们加上相关的算法代码,效果很完美。

你我们结束了。最后附上所有算法代码:

importpygame,sysfrommathimport * py game . init()font 1=py game . font . sys font(微软microsoftyaheimicrosoftyaheiui ,23)textc=font 1 . render(*'True,(250,0,0))screen=py game . display . set _ mode((800,700),0,32)missile=py game . image . load(element/rect 1 . png ).convert _ alpha()height=Missile . Get _ height()width=Missile . Get _ width()pygame . mouse . set _ visible(0)x1,y1=100,初始发射位置60 #导弹速度=800#导弹速度时间=1/1000#每个时间片的长度Clock=pygame . time . Clock()A=()B=()C=()while true:foreventinpygame . event . Get():if event . type==pygame . quit:sys . exit()Clock . tick(300距离=sqrt (power (x1-x,2) power (y1-1) 2) #两点距离公式section=velocity * time # distance Sina=(Y1-Y)/distance cosa=(X-X1)/distance angle=atan2(Y-Y1,X-X1) #两点间线段的弧度值方了=度(角度)#弧度转角x1 y1=(x1 section*cosa,Y1-section * Sina)missiled=py game . transform . rotate(导弹,-(方了))if0=-方了=90:A=(角

最后

这是一个用Python实现的简单的自动跟踪算法。真正的导弹拦截跟踪算法要复杂得多。

审计彭静