Python 代码类似于划船笔划

Python 代码类似于划船笔划,python,plot,spline,smoothing,Python,Plot,Spline,Smoothing,我正在制作一个显示移动划艇的小程序。下面显示了一个简单的示例代码(Python 2.x): 正如你所看到的,一艘船有一个速度,每分钟划几下。每次调用方法move(deltaT)时,它都会根据速度移动一定距离 上面的船只是以恒定的速度行驶,这是不现实的。一艘真正的划艇在划水开始时加速,然后在桨叶离开水面后减速。网上有许多图表显示了典型的划船曲线(此处显示的力,速度看起来类似): 资料来源: 随着时间的推移,配速应保持不变,但在划水过程中应发生变化 将恒定速度转化为(至少基本上)类似于更真实划船划

我正在制作一个显示移动划艇的小程序。下面显示了一个简单的示例代码(Python 2.x):

正如你所看到的,一艘船有一个速度,每分钟划几下。每次调用方法
move(deltaT)
时,它都会根据速度移动一定距离

上面的船只是以恒定的速度行驶,这是不现实的。一艘真正的划艇在划水开始时加速,然后在桨叶离开水面后减速。网上有许多图表显示了典型的划船曲线(此处显示的力,速度看起来类似):

资料来源:

随着时间的推移,配速应保持不变,但在划水过程中应发生变化

将恒定速度转化为(至少基本上)类似于更真实划船划水的曲线的最佳方法是什么


注意:关于如何更好地标记这个问题,有什么想法吗?这是一个算法问题吗?

你可以把这样一条曲线转换成速度的多项式方程

有关如何执行此操作的说明/示例,请访问:

这将向您展示如何获取一组x,y坐标(可以通过检查现有绘图或实际数据获得),并创建多项式函数


如果对每个船对象使用相同的曲线,则可以将其硬编码到程序中。但是,假设每个划船者或船只具有不同的轮廓,您也可以为每个船只对象建立单独的多项式方程。

您可以对运动微分方程执行简单的积分。(这就是你已经在做的,以恒定的速度,将空间作为时间的函数,
x'=x+V.dt

假设一个简单的模型,在冲程中有恒定的力,在滑行中没有力,阻力与速度成比例

因此,在冲程期间加速度为
a=p-D.v
,在滑行(减速)期间加速度为
-D.v

速度近似为
v'=v+a.dt

空间近似为
x'=x+v.dt

如果
dt
足够小,这个运动应该看起来很逼真。你可以用更精确的力定律和更好的积分技术(如龙格库塔)来完善模型,但我不确定它是否值得

下面是使用此技术绘制的速度和空间与时间的示例图。它显示了快速建立周期性区域的速度振荡和波动的准线性位移


如果你的目标是简单地提出一些视觉上可行的东西,而不是进行完整的物理模拟,你可以简单地在位置上添加一个正弦波

class Boat:
    def __init__(self, pace, spm, var=0.5):
        self.pace = pace    #average velocity of the boat in m/s
        self.sps = spm/60.0 #strokes per second
        self.var = var      #variation in speed from 0-1
        self.totalT = 0     #total time
        self.distance = 0   #distance traveled

    def move(self, deltaT):
        self.totalT += deltaT
        self.distance = self.pace * (self.totalT + self.var * math.sin(self.totalT * self.sps * 2*math.pi)

你需要小心变异
var
,如果它变得太高,船可能会倒退并破坏错觉。

使用样条插值,例如从SciPy。另请参阅SE站点,了解统计信息和ggplot库中的平滑变换stat_smooth。刚刚注意到你的图形在y轴上有力。力是质量*加速度。因为你的质量是恒定的,它本质上是一个加速度图(不是速度)。这是一个很好的高级方法,现在可能有点复杂。当我的应用程序需要一个更复杂的解决方案时,我会考虑这一点。代码的结果是有效的,因为我测试了一个划船运动员,划船速度为10m/s,SPM为20排,划船速度为30m:但是划船过程中的速度似乎前后跳跃。你知道计算出了什么问题吗?难道我们不需要把速度变成正弦波而不是时间吗?@MOnsDaR抱歉,我做了一个更正,但没有复制到答案中。
/self.sps
应该是
*self.sps
。实现了这一技巧,值现在沿正弦波递增/递减:但是曲线与我预期的正好相反:它开始快,走慢,结束快。应该是相反的。我尝试了一下这个等式,但无法使它正确运行,你能帮我最后一次吗?@MOnsDaR尝试使用
(1-cos(…)*0.5
而不是
sin(…)
。编辑:从头开始,只需反转
sin
效果更好。你需要减少变化,以防止倒退。看到哈,刚刚发现我自己,想把它贴在这里:)非常感谢你的帮助,船现在正在划船,同时看起来很现实。我想这是一个足够好的整体解决方案。然而,我的问题更多的是想问“我怎样才能使曲线像划船一样,但保持整体速度?”。
class Boat:
    def __init__(self, pace, spm, var=0.5):
        self.pace = pace    #average velocity of the boat in m/s
        self.sps = spm/60.0 #strokes per second
        self.var = var      #variation in speed from 0-1
        self.totalT = 0     #total time
        self.distance = 0   #distance traveled

    def move(self, deltaT):
        self.totalT += deltaT
        self.distance = self.pace * (self.totalT + self.var * math.sin(self.totalT * self.sps * 2*math.pi)