-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Q: Signal-dependent sampling schedules? #152
Comments
Yes, please do ask :) and thanks for asking! After all, I want the library to be useful not only for me, but for many people, so I always like to know what use cases and requirements others have. In fact you can cobble something like this together already with the existing tools. Let me write some code which I haven't tested, but which I'm sure can be made to work.
Something like this was in fact proposed by @ivanperez-keera but we never published it, I believe. It could be implemented roughly like so (heavily inspired by Ivan's ideas): -- Using https://hackage.haskell.org/package/monoid-extras-0.5.1/docs/Data-Monoid-Inf.html#t:Inf
-- This is a monoid that selects the earlier of two timestamps. Its neutral element is positive infinity.
type CollisionDetectionTimeDomain td = (Inf Pos td)
-- | In this state we remember when we need to sample the next step.
type CollisionDetectionT td m a = StateT (CollisionDetectionTimeDomain td) m a
-- | Decrease the next needed sampling time such that we sample at `td` or earlier.
needSampleAt :: td -> CollisionDetectionT td m ()
needSampleAt td = modify $ (<> Finite td)
-- | Use this in your signal functions whenever you have an indicator when to sample.
needSampleAtS :: BehaviourF (CollisionDetectionT td m a) td td ()
needSampleAtS = arrMCl needSampleAt
-- | Listens to the next necessary sampling time and samples there.
data CollisionDetectionClock td = CollisionDetectionClock
{ maxStep :: td -- ^ Even if no earlier sampling was requested, two steps should never be further apart than this.
}
instance Num td => Clock (CollisionDetectionT td m a) (CollisionDetectionClock td) where
type Time td = td
type Tag td = ()
initClock CollisionDetectionClock { .. } = do
let runningClock = proc _ -> do
nextTime <- constM get -< () -- Collect the minimum of all the votes when the next sample should happen
arrM put -< nextTime + maxStep -- Latest possible time to sample the next step
returnA -< (nextTime, ()) -- Return earliest time when to sample now
return (runningClock, 0) This would implement a pure clock. For a realtime clock, you'd need to add the appropriate If this is what you were looking for, and you have some motivation, feel free to make a pull request out of it, and we can make it work :)
Similar in spirit to the previous example, you could use a
Not directly. That's more a refactoring, to make type signatures and combinators simpler. (In my opinion one of the biggest improvements in |
Fantastic! I'm wondering if, once polished, things like this should be in a |
No, I think they should go to the main library. My layout is: Everything that needs only core dependencies (base, well-established packages, no external libraries) goes into |
From what I understand in the paper, clocks probably couldn't be coordinated if the sampling-rate were signal-dependent. But I thought I'd ask!
Ex 1. If simulating a collision, you could increase the sampling frequency as 2 objects near each other to make sure they don't pass through each other.
Ex 2. If working with high-frequency signals, you could change the sample-rate as a function of the highest-frequency component in the signal for the last 2 seconds. If slow-waves abound, sample infrequently.
EDIT: perhaps this is related? https://github.com/turion/rhine/pull/148/filesThe text was updated successfully, but these errors were encountered: