gpt4 book ai didi

haskell - 使用 Reactive Banana 做一些基本的微积分

转载 作者:行者123 更新时间:2023-12-04 14:15:57 29 4
gpt4 key购买 nike

设置 :

我正在使用 Reactive Banana 和 OpenGL,并且我有一个想要旋转的齿轮。我有以下信号:

bTime :: Behavior t Int -- the time in ms from start of rendering
bAngularVelosity :: Behavior t Double -- the angular velocity
-- which can be increase or
-- decreased by the user
eDisplay :: Event t () -- need to redraw the screen
eKey :: Event t KeyState -- user input

最终,我需要计算 bAngle然后传递给绘图功能:
reactimate $ (draw gears) <$> (bAngle <@ eDisp)

角度很容易计算: a = ∫v(t) dt
问题 :

我想我想做的是将这个积分近似为 a = ∑ v Δt对于每个 eDisplay 事件(或者如果需要,可以更频繁)。这是解决这个问题的正确方法吗?如果是这样,我如何获得 Δt来自 bTime ?

另见 :
我怀疑答案使用 mapAccum功能。如果是这样,另请参阅 my other question也是。

最佳答案

编辑:回答这个问题,是的,你使用你正在使用的近似值是正确的,它是欧拉求解一阶微分方程的方法,并且对于你的目的来说足够准确,特别是因为用户没有周围的角速度的绝对值来判断你反对。减少你的时间间隔会使它更准确,但这并不重要。

你可以用更少、更大的步骤来做到这一点(见下文),但这种方式对我来说似乎是最清楚的,我希望你也是。

为什么要打扰这个更长的解决方案?即使 eDisplay以不规则的时间间隔发生,因为它计算 eDeltaT .

让我们给自己一个时间事件:

eTime :: Event t Int
eTime = bTime <@ eDisplay

要获得 DeltaT,我们需要跟踪耗时间隔:
type TimeInterval = (Int,Int) -- (previous time, current time)

所以我们可以将它们转换为增量:
delta :: TimeInterval -> Int
delta (t0,t1) = t1 - t0

当我们得到一个新的时我们应该如何更新一个时间间隔 t2 ?
tick :: Int -> TimeInterval -> TimeInterval
tick t2 (t0,t1) = (t1,t2)

因此,让我们将其部分应用于时间,为我们提供一个间隔更新器:
eTicker :: Event t (TimeInterval->TimeInterval)
eTicker = tick <$> eTime

然后我们可以 accumE -在初始时间间隔上累积该函数:
eTimeInterval :: Event t TimeInterval
eTimeInterval = accumE (0,0) eTicker

由于 eTime 是从渲染开始开始测量的,因此初始 (0,0)是合适的。

最后,我们可以通过应用 ( fmap ping) delta 来进行 DeltaT 事件。在时间间隔上。
eDeltaT :: Event t Int
eDeltaT = delta <$> eTimeInterval

现在我们需要更新角度,使用类似的想法。

我将制作一个角度更新器,只需转动 bAngularVelocity成乘数:
bAngleMultiplier :: Behaviour t (Double->Double)
bAngleMultiplier = (*) <$> bAngularVelocity

那么我们可以用它来制作 eDeltaAngle : (编辑:更改为 (+) 并转换为 Double )
eDeltaAngle :: Event t (Double -> Double)
eDeltaAngle = (+) <$> (bAngleMultiplier <@> ((fromInteger.toInteger) <$> eDeltaT)

并累积得到角度:
eAngle :: Event t Double
eAngle = accumE 0.0 eDeltaAngle

如果你喜欢单行,你可以写
eDeltaT = delta <$> (accumE (0,0) $ tick <$> (bTime <@ eDisplay)) where
delta (t0,t1) = t1 - t0
tick t2 (t0,t1) = (t1,t2)

eAngle = accumE 0.0 $ (+) <$> ((*) <$> bAngularVelocity <@> eDeltaT) =

但我不认为这是非常有启发性的,老实说,我不确定我的修复是否正确,因为我没有在 ghci 中测试过。

当然,既然我做了 eAngle而不是 bAngle , 你需要
reactimate $ (draw gears) <$> eAngle

而不是你原来的
reactimate $ (draw gears) <$> (bAngle <@ eDisp)

关于haskell - 使用 Reactive Banana 做一些基本的微积分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12327517/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com