Presentation is loading. Please wait.

Presentation is loading. Please wait.

Christof Douma Functional Reactive Programming. What are reactive systems? Transformational vs. Reactive ● Transformational systems compute output from.

Similar presentations


Presentation on theme: "Christof Douma Functional Reactive Programming. What are reactive systems? Transformational vs. Reactive ● Transformational systems compute output from."— Presentation transcript:

1 Christof Douma Functional Reactive Programming

2 What are reactive systems? Transformational vs. Reactive ● Transformational systems compute output from an input and then terminate. Examples: UUAG, GHC, Latex. ● Reactive systems respond to stimuli in order to bring about desirable effects in their environment. Examples: Proxima, Mozilla, Quake, Space Invaders.

3 Why Functional Reactive Programming? ● Functional programming has usually been applied to build transformational systems. ● Usually imperative paradigms are adopted when building reactive systems. ● FRP is a new paradigm to program reactive systems in a functional language. ● Useful for Embedded Domain Specific Languages

4 What is FRP Good for? ● Applications of FRP (EDSL) – FVision [Reid, Peterson, Hudak and Hager] Visiual tracking – Fran [Elliott and Hudak] Interactive animation – FranTk [Sage], Fruit [Courtney] GUI – Frob [Peterson, Hager, Hudak and Elliott] Robotics moveXY (sin time) 0 charlotte charlotte = importBitmap “charlotte.bmp”

5 FRP Pardigm ● FRP has two key abstractions ● Continuous time-varying values ● Discrete streams of events ● Uses combinators that hide detail about timing and synchronization Signal a = Time -> a

6 Signal Functions ● Signals can be manipulated directly ● Problem: Time- and space-leaks – Time leaks occur in real-time systems when a computation does not “keep up” with the current time, this requiring “catching up” at a later time. ● Solution: Use Signal Functions – Signals are not fist class values anymore SF a b = Signal a -> Signal b

7 Signal Function Example ● An example, the sin function: Floating a => SF a a time

8 Composing FRP programs ● Complex programs can be build by composing simpler programs ● Current implementation uses the Arrow class – change of name: AFRP arr :: (a -> b) -> SF a b (>>>) :: SF a b -> SF b c -> SF a c first :: SF a b -> SF (a,c) -> SF (b,c)

9 AFRP Example ● Travel returns a SF that generates a constant signal v while the distance d hasn't yet been travelled. travel :: Distance -> Velocity -> SF Velocity Velocity travel d v = integral >>> arr (\d2 -> if d2 < d then v else 0) (note the lack of explicite time)

10 Composing AFRP programs ● more Arrow combinators second :: SF a b -> SF (c,a) (c,b) ( SF a b -> SF a c (&&&) :: SF a b -> SF a c -> SF a (b,c) (***) :: SF a b -> SF c d -> SF (a,c) (b,d) loop :: SF (a,c) (b,c) -> SF a b

11 Arrows vs Monads ● IO Programs are a composition of actions with the details of the state are hidden from the user. It is ran at the top level by an interpreter ● AFRP programs is a composition of signal function with the details of the signals hidden from the user. It is ran at the top level by an interpreter ● Monads composition must be linear ● Arrows composition is not linear

12 AFRP Primitive Signal Functions identity :: SF a a constant :: n -> SF a b integral :: SF Double Double derivative:: SF Double Double time :: SF a Time arr2 :: (a -> b -> c) -> SF (a,b) c

13 Discrete Events ● Events can be user input as well as domain- specific sensors, interrupts, etc. ● Events are represented as signals of the Event datatype Event a = NoEvent | Event a edge :: SF Bool (Event ()) hold :: SF (Event a) a

14 Discrete events (2) ● Operations on event streams include – mapping, filtering, merging, etc. – Switching of reactive behavior (next slide) tag :: Event a -> b -> Event b mergeBy :: (a->a->a) -> Event a -> Event a -> Event a accum :: a -> SF (Event (a->a)) (Event a) after :: Time -> b -> SF a (Event b) repeatedly :: Time -> b -> SF a (Event b)

15 Switching ● read as: 'Behave as sf1 until the first event in es occurs. Then bind the event value to e and behave as sf2.' ● Note: The time flow restart when switch is made into the new SF. switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b sf1 && es `switch` (\e -> sf2)

16 Switch Example travel :: Distance -> Velocity -> SF Velocity Velocity travel d v = switch (constant v &&& wayTooFar) (\_ -> constant 0) where wayTooFar = integral >>> arr (>=d) >>> edge switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b (&&&) :: SF a b -> SF a c -> SF a (b,c)

17 Arrow Syntax tr avel d v = forward `switch` stop where stop _ = contant 0 forward = proc iv -> do td <- integral -< iv e = d) returnA -< (v,e) ● Preprocessor translate arrow symtax into Haskell with first, arr, (<<<) and loop Arrow operators

18 Switch Semantics ● Two questions arise about switching semantics: – Does the switch happen exactly at the event time, or infinitesimally after? – Does the switch happen just for the first event, or for every event in an event stream? switch, dSwitch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b rSwitch, drSwitch :: SF a b -> SF (a, Event (SF a b)) b

19 Recursive Signal Functions ● Suppose incrVel :: SF RobotInput (Event ()) generates 'commands' to increments the velocity of a robot. ● concider: vel :: Velocity -> SF RobotInput Velocity vel v0 = proc inp -> do rec e <- incrVel -< inp v <- drSwitch (constant v0) -< (inp, e `tag` constant (v+1)) returnA -< v ● Note that vel is recursively defined, which requires: – The use of the rec keyword – The use of a delayed switch (drSwitch)

20 Running the program ● To execute a program we need to connect the SF to the outside world ● Approximate the Continuous-time model reactimate :: IO (DTime,a)-- sense -> (b -> IO ())-- actuate -> SF a b -> IO ()

21 AFrob Programming Robots with AFRP

22 AFrob ● AFRob is an EDSL - written in AFRP - for programming robots. It includes a robot simulator. ● AFRob models robots with two wheels and two independent motors. These are called SimBots. ● Each SimBot has a bumper switch, a range object finder, an animate object tracker. ● Each SimBot is controlled by a Signal Function

23 Differential Drive Mobile Robot θ l vlvl vrvr y x ● The Equations for the x position are:

24 Simbot X position ● Assume that: xSF :: SF SimbotInput Distance xSF = proc inp -> do vr <- vrSF -< inp vl <- vlSF -< inp theta <- thetaSF -< inp i <- integral -< (vr+vl) * cos theta returnA -< (i/2) vrSF,vlSF :: SF SimbotInput Speed thetaSF :: SF SimbotInput Angle ● we can write x(t) in AFRP as:

25 Robot Input Signals class HasRobotStatus i where rsBattStat :: i -> BatteryStatus rsStuck :: i -> Bool class HasOdometry i where odometryPosition :: i -> Position2 odometryHeading :: i -> Heading instance HasRobotStatus SimbotInput instance HasOdometry SimbotInput

26 Robot Output Signals class MergeableRecord o => HasDiffDrive o where ddBrake :: MR o ddVelDiff :: Velocity -> Velocity -> MR o ddVelTR :: Velocity -> RotVel -> MR o class MergeableRecord o => HasTextConsole o where tcoPrintMessage :: Event String -> MR o mrFinalize :: MergeableRecord o => MR o -> o mrMerge :: MergeableRecord o => MR o -> MR o -> MR o instance HasDiffDrive SimbotOutput instance HasTextConsole SimbotOutput

27 Robot Properties class HasRobotProperties i where rpType :: i -> RobotType rpId :: i -> RobotId rpDiameter :: i -> Length rpAccMax :: i -> Acceleration rpWSMax :: i -> Speed instance HasRobotProperties SimbotProperties ● Static information about the capabilities of a robot

28 Robot Controllers Type SimbotController = SimbotProperties -> SF SimbotInput SimbotOutput rcStop :: SimbotController rcStop rps = constant (mrFinalize ddBrake) rcBlind :: SimbotController rcBlind rps = let max = rpWSMax rps in constant (mrFinalize $ ddVelDiff (max/2) (max/2)) ● A stationary simbot: ● A simbot that goes at ½ of the maximum speed:

29 Running in Circles rcTurn :: Velocity -> SimbotController rcTurn vel rps = let vMax = rpWSMax rps rMax = 2 * (vMax – vel) / rpDiameter rps in constant (mrFinalize $ ddVelTR vel rMax) ● A simbot that goes at ½ of the maximum speed: ● Simbots cannot turn arbitrarily fast – it depends on their speed. The maximum rotational velocity is:

30 Another Example Robot Controller rdDumb :: RobotController rcDumb rps = proc sbi -> do iAmStuck <- rsStuck -< sbi rec let sig = (sbi, iAmStuck `tag` constant (-velo)) velo <- drSwitch (constant maxVel) -< sig returnA -< mrFinalize $ ddVelDiff velo velo where maxVel = rpWSMax rps drSwitch :: SF a b -> SF (a,Event (SF a b)) b tag :: Event a -> b -> Event b ● A simbot which reverses when hitting something

31 Running in a Virtual World runSim :: Maybe WorldTemplate ->-- virtual world SimbotController ->-- simbot A’s SimbotController ->-- simbot B’s IO ()-- does the work type WorldTemplate = [ObjectTemplate] data ObjectTemplate = OTBlock { otPos :: Position2 }-- Square obstacle | OTVWall { otPos :: Position2 }-- Vertical wall | OTHWall { otPos :: Position2 }-- Horizontal wall | OTBall { otPos :: Position2 }-- Ball | OTSimbotA { otRId :: RobotId,-- Simbot A robot otPos :: Position2, otHdng :: Heading } | OTSimbotB {... }-- Simbot B robot

32 Demo Program module MyRobotShow where import AFrob-- AFrob library import AFrobRobotSim-- the simulator main :: IO () main = runSim (Just world) rcA rcB world :: WorldTemplate world =... rcA, rcB, rcB1, rcB2:: SimbotController rcA =...-- controller for simbot A’s rcB rProps = case rpId rProps of-- controller for simbot B’s 1 -> rcB1 rProps-- (showing here how to deal 2 -> rcB2 rProps-- with multiple simbots)

33 ● where r is the range-finder reading, d is the desired distance, and K p and K d are the proportionate and derivative gains, respectively. Follow the Wall ● To follow a wall, we use a range finder to sense the distance to the wall. ● It can be shown (for small deviations) that the rotational velocity should be:

34 More Robot Input Signals class Has RangeFinder i where rfRange :: i -> Angle -> Distance rfMaxRange :: i -> Distance -- derived range finders rfFront, rfBack, rfLeft, rfRight :: HasRangeFinder i => i -> Distance instance HasRangeFinder SimbotInput ● A simbot has a range finder ● A range finder finds the nearest object in a given direction

35 Follow the Wall Controller ● This leads to the controller: rcFollowLeftWall :: Velocity -> Distance -> SimbotController rcFollowLeftWall v d _ = proc sbi -> do let r = rfLeft sbi dr <- derivative -< r let omega = kp*(r-d) + kd*dr kd = 5 kp = v*(kd^2)/4-- achieves “critical damping” returnA -< mrFinalize (ddVelTR v (lim 0.2 omega))

36 Systems with Dynamic Structure ● All objects are Signal Functions ● Objects can be added and removed ● We need combinators that can change the signal network at runtime – So far we modelled systems where the signal network is static

37 Dynamic Collections in AFRP ● AFRP has special combinators for this purpose parB :: Functor col => col (SF a b) -> SF a (col b) par :: Functor col => (forall sf.(a->col sf->col (b,sf))) -> col (SF b c) -> SF a (col c) pSwitch :: Functor col => (forall sf.(a->col sf->col (b,sf))) -> col (SF b c) -> SF (a,col c) (Event d) -> (col (SF b c) -> d -> SF a (col c)) -> SF a (col c)

38 Learn more? ● Look at the webiste – http://www.haskell.org/yampa/ http://www.haskell.org/yampa/ – http://www.haskell.org/frp/ http://www.haskell.org/frp/ ● example application – The Yampa Arcade [Antony Courtney, Henrik Nilsson and John Peterson, 2003] – Robot Soccer (included in the yampa package)


Download ppt "Christof Douma Functional Reactive Programming. What are reactive systems? Transformational vs. Reactive ● Transformational systems compute output from."

Similar presentations


Ads by Google