Skip to content

Instantly share code, notes, and snippets.

@nivekuil
Last active October 6, 2023 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nivekuil/ed032e1b889444631e2beb101333f836 to your computer and use it in GitHub Desktop.
Save nivekuil/ed032e1b889444631e2beb101333f836 to your computer and use it in GitHub Desktop.
animated value in electric
(def timer*
(->> e/<clock ;; produce time
(y/sample e/-get-system-time-ms) ;; label time
(y/reductions (fn([] {:t (e/-get-system-time-ms) :dt 0})
([acc next] ;; produce difference
{:t (e/-get-system-time-ms)
:dt (- next (:t acc))})))))
(defn pid [<setpoint {:keys [<force error-threshold k <clock]
:or {<force (y/watch (atom 10))
<clock (y/eduction (map :dt) timer*)
k 0.0005
error-threshold 0.2}}]
(y/cp
(let [!curr (atom 0)
!gate (atom true)]
(y/?< <setpoint)
(reset! !gate true)
(let [<gated-clock (if (y/?< (y/watch !gate)) <clock (y/ap))
[setpoint force curr dt]
(y/?< (y/sample vector
<setpoint <force (y/watch !curr) <gated-clock
<gated-clock))
err (- setpoint curr)]
(if (< (Math/abs err) error-threshold)
(do (reset! !gate false) setpoint)
(swap! !curr + (* err dt k force)))))))
(defmacro animated-value [setpoint & {:as args}]
`(let [!v# (atom 0)]
(reset! !v# ~setpoint)
(new (pid (y/watch !v#) ~args))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment