56
August 2002 1 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak Yale University Dept. of Computer Science Copyright © Paul Hudak, August 2002; all rights reserved.

August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

  • View
    221

  • Download
    2

Embed Size (px)

Citation preview

Page 1: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 1

Arrows, FRP, and Functional Reactive Programming

Lecture slides from theOxford Summer School on Advanced Functional

Programming

Paul HudakYale University

Dept. of Computer Science

Copyright © Paul Hudak, August 2002; all rights reserved.

Page 2: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 2

Acknowledgements

Thanks to:

The Yale Haskell Group, especiallyAntony Courtney, Henrik Nilsson,

and John Peterson.

Grants from the National Science Foundation(CCR9900957 and CCR-9706747) and

the Defense Advanced Research Projects Agency(F33615-99-C-3013 and DABT63-00-1-0002).

Page 3: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 3

Embedded Domain-Specific Languages

Functional Programming

FRP

Functions, types, etc.(Haskell)

Continuous behaviorsand discrete reactivity

Specialized languages

Fran

FV

isio

n

Graphics, Robotics, GUIs, Vision Applications

Fran

Tk

Frob

Fru

it

Page 4: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 4

Embedded Domain-Specific Languages

Functional Programming

Arrowized FRP (AFRP)

Functions, types, etc.(Haskell)

Continuous behaviorsand discrete reactivity

Specialized languages

Fran

FV

isio

n

Graphics, Robotics, GUIs, Vision Applications

Fran

Tk

AFr

ob

Fru

it

Page 5: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 5

A Different Perspective

Fact: I used FRP to teach Yale’s Autonomous Systems course. Students were able to quickly write programs for real and simulated robots.Problem: Some students wrote programs with space and time leaks – and in many cases I was unable to give them a good explanation of how to rewrite the program to avoid these leaks.Goal: I’d be happy to spend more time teaching AFRP if it resulted in fewer space and time leaks.Question: Can I teach you all how to program simulated robots using AFRP in only three lectures?

Page 6: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 6

Part I

Arrowized FRP (AFRP) Basics

Page 7: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 7

Functional Reactive Programming

FRP (functional reactive programming) is the essence of several DSL’s: Fran = FRP + graphics engine + library Frob = FRP + robot controller + library FranTk = FRP + Tk substrate + library Fruit = FRP + Java GUI/graphics + library

FRP has two key abstractions: Continuous time-varying behaviors. Discrete streams of events.

Page 8: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 8

Behaviors

Continuous behaviors capture any time-varying quantity, whether: input (sonar, temperature, video, etc.), output (actuator voltage, velocity vector, etc.), or intermediate values internal to a program.

Operations on behaviors include: Generic operations such as arithmetic,

integration, differentiation, and time-transformation.

Domain-specific operations such as edge-detection and filtering for vision, scaling and rotation for animation and graphics, etc.

Page 9: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 9

Events

Discrete event streams include user input as well as domain-specific sensors, asynchronous messages, interrupts, etc.They also include tests for dynamic constraints on behaviors (temperature too high, level too low, etc.)Operations on event streams include: Mapping, filtering, reduction, etc. Reactive behavior modification (next slide).

Page 10: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 10

An Example from Graphics (Fran)

A single animation example that demonstrates key aspects of FRP:

growFlower = stretch size flower where size = 1 + integral bSign

bSign = 0 `until` (lbp ==> -1 `until` lbr ==> bSign) .|. (rbp ==> 1 `until` rbr ==> bSign)

Page 11: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 11

Differential Drive Mobile Robot

θ

l

vl

vr

y

x

Our software includes a robot simulator. Its robots are differential drive, and we refer to them as simbots.

Page 12: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 12

An Example from Robotics

The equations governing the x position of a differential drive robot are:

The corresponding FRP code is:

x = (1/2) * (integral ((vr + vl) * cos theta) theta = (1/l) * (integral (vr - vl))

(Note the lack of explicit time.)

Page 13: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 13

Time and Space Leaks

Behaviors in FRP are what we now call signals, whose (abstract) type is: Signal a = Time -> aUnfortunately, unrestricted access to signals makes it far too easy to generate both 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.)Fran, Frob, and FRP all suffer from this problem to some degree.

Page 14: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 14

Solution: no signals!

To minimize time and space leaks, do not provide signals as first-class values.Instead, provide signal transformers, or what we prefer to call signal functions: SF a b = Signal a -> Signal bSF is an abstract type. Operations on it provide a disciplined way to compose signals.Use arrows to structure the composition operations on SF, and domain-specific operations for standard FRP concepts.

Page 15: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 15

Analogy to Monads

A Haskell IO program is a composition of actions, or commands, in which the details of the state are hidden from the user. It is “run” at the top level by an interpreter that interfaces to the OS.Analogously, an AFRP program is a composition of signal functions in which the details of signals are hidden from the user. It is “run” at the top-level by a suitable interpreter.The main difference is that monad composition must be linear to ensure single-threadedness, whereas arrow composition is not so constrained. Indeed, arrows are a generalization of monads.

Page 16: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 16

Arrow Operators

Composition operations are best-motivated by “point-free” functional programming.Consider:

g x = f2 (f1 x)In a point-free style, using function composition:

g = f2 . f1At the level of arrows, we need function lifting:

arr :: (a->b) -> SF a band composition:

(>>>) :: SF a b -> SF b c -> SF a cto yield:

g’ = arr f1 >>> arr f2 = arr g(note: (>>>) is actually reverse composition)

Page 17: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 17

Arrow Operators, cont’d

But linear composition is not good enough – we want to “wire together” signal functions in arbitrary ways.For example, consider (using ordinary functions):

h x = (f1 x, f2 x)To make this point-free, define:

(f1 & f2) x = (f1 x, f2 x)And thus:

h = f1 & f2Using an analogous operator (&&&) for signal functions, we can write:

h’ = arr f1 &&& arr f2 = arr h

Page 18: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 18

Arrow Operators, cont’d

Now consider:i (x,y) = (f1 x, f2 y)

Using (&) defined earlier:i = (f1 . fst) & (f2 . snd)

Analogously, at the level of signal functions:i’ = arr (f1 . fst) &&& arr (f2 . snd)

which is the same as:i’ = (arr fst >>> arr f1) &&& (arr snd >>>

arr f2) = arr iThis “argument wiring” pattern is so common that AFRP defines:

f *** g = (arr fst >>> f) &&& (arr snd >>> g)

Page 19: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 19

The Arrow Class

When do we have enough combinators?In fact: arr, (>>>), and (&&&) form a universal set: we can define all “wirings” with them alone. (E.g., note that (***) was defined in terms of them.)However, this is not the only universal set. Hughes chose a different set in defining his Arrow class:

class Arrow a wherearr :: (b -> c) -> a b c(>>>) :: a b c -> a c d -> a b dfirst :: a b c -> a (b,d) (c,d)

where first is analogous to:firstfun f (x,y) = (f x, y)

Page 20: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 20

Graphical Depiction of Arrows

sf1

sf2

sf1sf

sf

sf2

sf1

sf2

sf1 >>> sf2 first sf arr sf

sf1 &&& sf2 sf1 *** sf2 loop sf

sf

Page 21: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 21

Exercise 1

Define:

• first in terms of just arr, (>>>), and (&&&).

• (***) in terms of just first, second, and (>>>).

• (&&&) in terms of just arr, (>>>), and (***).

Page 22: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 22

Some Primitive Signal Functions

identity :: SF a aidentity = arr idconstant :: b -> SF a bconstant = arr . consttime :: SF a Timetime = constant 1 >>> integralintegral :: VectorSpace a => SF a a< definition omitted >arr2 :: (a->b->c) -> SF (a,b) c)arr2 = arr . uncurryNumeric and other functions achieved via lifting:arr sin, arr cos, arr2 (+), arr2 (*), etc.

Page 23: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 23

A Larger Example

Recall this FRP definition:x = (1/2) (integral ((vr + vl) * cos theta))Assume that:vrSF, vlSF :: SF SimbotInput Speedtheta :: SF SimbotInput Anglethen we can rewrite x in AFRP like this:xSF :: SF SimbotInput DistancexSF = let v = (vrSF &&& vlSF) >>> arr2 (+) t = thetaSF >>> arr cos in (v &&& t) >>> arr2 (*) >>> integral >>> arr (/2)Yikes!!! Is this as clear as the original code??

Page 24: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 24

Arrow SyntaxUsing Paterson’s arrow syntax, we can instead write:

xSF' :: SF SimbotInput DistancexSF' = proc inp -> do vr <- vrSF -< inp vl <- vlSF -< inp theta <- thetaSF -< inp i <- integral -< (vr+vl) * cos theta returnA -< (i/2)

Feel better? Note that vr, vl, theta, and i are signal samples, and not the signals themselves. Similarly, expressions to the right of “-<” denote signal samples.Read “proc inp -> …” as “\ inp -> …” in Haskell.Read “vr <- vrSF -< inp” as “vr = vrSF inp” in Haskell.

Page 25: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 25

Graphical Depiction

&&&

>>>

>>>

>>>

>>>

>>>

&&&xSF' :: SF SimbotInput DistancexSF' = proc inp -> do

vr <- vrSF -< inp vl <- vlSF -< inp theta <- thetaSF -< inp i <- integral -< (vr+vl) *

cos theta returnA -< (i/2)

xSF = let v = (vrSF &&& vlSF) >>> arr2 (+) t = thetaSF >>> arr cos in (v &&& t) >>> arr2 (*) >>> integral >>> arr (/2)

+vrSF

vlSF

costhetaSF

integral* /2

vr

vl

theta

iinp

Page 26: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 26

Exercises 2 & 3

Define signal functions ySF and thetaSF in AFRP that correspond to the definitions of y and theta, respectively, in FRP.

Rewrite these definitions using the arrow syntax. Also draw their signal flow diagrams.

Page 27: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 27

Conditionals in AFRP

Consider:sf = proc i -> do

x <- sfx -< iy <- sfy -< ib <- flag -< ireturnA -< if b then x else y

sf alternates between sfx and sfy depending on the pointwise value of the boolean signal function flag.But this isn’t good enough: we sometimes want a signal function to switch into another signal function, and furthermore to start from time zero.

Page 28: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 28

AFRP Events

Events in AFRP are isomorphic to the Maybe data type in Haskell.An event stream has type Signal (Event b).At any point it time, it yield either nothing, or an event carrying value of type b.An event source is a signal function of typeSF a (Event b). For example:

rsStuck :: SF SimbotInput (Event ())generates an event stream whose events correspond to the simbot getting stuck (which happens when it runs into something).

Page 29: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 29

Operations on Events

fmap :: (a->b) -> Event a -> Event btag :: Event a -> b -> Event blMerge, rMerge ::

Event a -> Event a -> Event anever :: SF a (Event b)now :: b -> SF a (Event b)after :: Time -> b -> SF a (Event b)repeatedly :: Time -> b -> SF a (Event b)edge :: SF Bool (Event ())Example of edge:

alarmSF :: SF SimbotInput (Event ())alarmSF = tempSF >>> arr (>100) >>> edge

Page 30: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 30

Switching

Events induce switching via a family of switching combinators. The simplest is:switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a bRead “(sf1 &&& es) `switch` \e -> sf2” as:“Behave as sf1 until the first event in es occurs, at which point bind the event’s value to e and behave as sf2.”For example:

xspd :: Speed -> SF SimbotInput Speedxspd v = (constant v &&& rsStuck)

`switch` \() -> constant 0xspd is initially v, but drops to zero when the simbot gets stuck.

Page 31: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 31

Exercises 4 & 5

Rather than set the wheel speed to zero when the robot gets stuck, negate it instead. Then define xspd recursively so that the velocity gets negated every time the robot gets stuck.

Let v :: SF SimbotInput Velocity represent the scalar velocity of a simbot. If we integrate this velocity, we get a measure of how far the simbot has traveled. Define an alarm that generates an event when either the simbot has traveled more than d meters, or it has gotten stuck.

Page 32: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 32

Switching 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?Different answers result in four different switchers:

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

Page 33: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 33

Time to Start Over

Consider: (time &&& rsStuck) `switch` const timeThe two occurrences of time are different: the second one yields zero at the time of the first rsStuck event.If this is changed to: let evSF = rsStuck >>> arr (`tag` time) in (id &&& evSF) >>> rSwitch timeor if you prefer: proc inp -> do

e <- rsStuck -< inprSwitch time -< (inp, e `tag` time)

then the time restarts on every rsStuck event.

Page 34: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 34

Time to Continue

How do we get time to continue? Instead of this:proc inp -> do e <- rsStuck -< inp rSwitch time -< (inp, e `tag` time)

We do this:proc inp -> do t <- time -< inp e <- rsStuck -< inp rSwitch time -< (inp, e `tag` time >>> arr (+t))

t0

ev1

ev2

t0

ev1

ev2

Page 35: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 35

Recursive Signal Functions

Suppose incrVelEvs :: SF SimbotInput (Event ()) generates “commands” to increment the velocity.Consider:vel :: Velocity -> SF SimbotInput Velocityvel v0 = proc inp -> do rec e <- incrVelEvs -< inp v <- drSwitch (constant v0) -< (inp, e `tag` constant (v+1)) returnA -< vNote that vel is recursively defined, which requires: The use of the rec keyword The use of a delayed switch (drSwitch)

Page 36: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 36

Exercise 6

Redefine vel using dSwitch instead of drSwitch, and without using the rec keyword. (Hint: define vel recursively instead of defining v recursively.)

Page 37: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 37

Part II

Programming Robots with AFRP

Page 38: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 38

The Big Picture

Our simulated robots (i.e. simbots) are controlled by a controller of type:type SimbotController = SimbotProperties -> SF SimbotInput SimbotOutputSimbotProperties specifies static properties of a simbot (max speed, id number, etc).SimbotInput is dynamic data into the controller from the simbot; SimbotOutput is the data out of the controller and into the simbot.The three of these are instances of certain type classes that provide different kinds of functionality (see the paper for details).

Page 39: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 39

Running in a Virtual WorldTo run a controller: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

Page 40: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 40

Top Level of Programmodule MyRobotShow whereimport AFrob -- AFrob libraryimport AFrobRobotSim -- the simulator

main :: IO ()main = runSim (Just world) rcA rcB

world :: WorldTemplateworld = ...

rcA, rcB :: SimbotControllerrcA = ... -- controller for simbot A’s

rcB rProps = case rpId rProps of -- controller for simbot B’s 1 -> rcA1 rProps -- (showing here how to

deal 2 -> rcA2 rProps -- with multiple simbots) 3 -> rcA3 rProps

rcA1, rcA2, rcA3 :: SimbotControllerrcA1 = ... ; rcA2 = … ; rcA3 = …

Page 41: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 41

A Detail about SimbotOutputBrake both wheels:ddBrake :: MR SimbotOutputSet each wheel velocity:ddVelDiff :: Velocity -> Velocity -> MR SimbotOutputSet velocity and rotation:ddVelTR :: Velocity -> RotVel -> MR SimbotOutputPrint message to console:tcoPrintMessage :: Event String -> MR SimbotOutput

Then to merge the results:mrMerge :: MR SimbotOutput -> MR SimbotOutput -> MR SimbotOutputmrFinalize :: MR SimbotOutput -> SimbotOutput

Page 42: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 42

Some Simple Robot Controllers

A stationary simbot:rcStop :: SimbotControllerrcStop _ = constant (mrFinalize ddBrake)A moving but otherwise blind simbot:rcBlind1 :: SimbotController rcBlind1 _ = constant (mrFinalize $ ddVelDiff 10 10)Or, better, one that goes ½ of the maximum speed:rcBlind2 :: SimbotController rcBlind2 rps = let max = rpWSMax rps in constant (mrFinalize $

ddVelDiff (max/2) (max/2))

Page 43: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 43

Running in Circles

Simbots cannot turn arbitrarily fast – it depends on their speed. The maximum rotational velocity is:

where vmax is the max wheel speed, vf is the forward velocity, and l is the distance between wheels.

rcTurn :: Velocity -> SimbotControllerrcTurn vel rps = let vMax = rpWSMax rps rMax = 2 * (vMax - vel) / rpDiameter rps in constant (mrFinalize $ ddVelTR vel rMax)

Page 44: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 44

Exercise 7

Link rcBlind2, rcTurn, and rcStop together in the following way: Perform rcBlind2 for 2 seconds, then rcTurn for three seconds, and then do rcStop. (Hint: use after to generate an event after a given time interval.)

Page 45: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 45

A Talking Simbot

A simbot that says “Ouch!!” and reverses its direction everytime it gets stuck:

rcReverse :: Velocity -> SimbotControllerrcReverse v rps = beh `dSwitch` const (rcReverse (-v) rps) where beh = proc sbi -> do

stuckE <- rsStuck -< sbi let mr = ddVelDiff v v `mrMerge` tcoPrintMessage (tag stuckE

"Ouch!!") returnA -< (mrFinalize mr, stuckE)

Page 46: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 46

Exercise 8

Write a version of rcReverse that, instead of knowing in advance what its velocity is, takes a “snapshot” of the velocity, as described earlier, at the moment the stuck event happens, and then negates this value to continue.

Page 47: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 47

The Value of Feedback

The most effective controllers use feedback to test the accuracy of the desired result.The difference between the desired result and the actual result is called the error.A typical controller will feedback the error proportionately, as its integral, as its derivative, or as some combination of these three. (The most general is thus called a PID (proportion/integral/ derivative) controller.The field of control theory studies the issues of accuracy, stability, and so on, of such systems.

Page 48: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 48

Heading in the Right DirectionA controller to head in a particular direction, using proportionate feedback for accuracy:

rcHeading :: Velocity -> Heading -> SimbotControllerrcHeading vel hd rps = let rMax = 2 * (rpWSMax rps - vel) / rpDiameter rps k = 2 in proc sbi -> do let he = normalizeAngle (hd - odometryHeading sbi) rotV = lim rMax (k*he) returnA -< mrFinalize (ddVelTR vel rotV)

Note the use of odometry: in this case, heading.The parameter k is the proportionate gain of the system.

Page 49: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 49

Thinking Ahead …Let’s rewrite rcHeading as:

rcHeading' :: Velocity -> Heading -> SimbotControllerrcHeading' vel hd rps = proc sbi -> do rcHeadingAux rps -< (sbi, vel, hd)

rcHeadingAux :: SimbotProperties -> SF (SimbotInput,Velocity,Heading) SimbotOutputrcHeadingAux rps = let k = 2 in proc (sbi,vel,hd) -> do let rMax = 2 * (rpWSMax rps - vel)/rpDiameter rps he = normalizeAngle (hd - odometryHeading sbi) rotV = lim rMax (k*he) returnA -< mrFinalize (ddVelTR vel rotV))

Page 50: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 50

Moving On

Controller to move simbot to a specific location:

rcMoveTo :: Velocity -> Position2 -> SimbotControllerrcMoveTo vd pd rps = proc sbi -> do let (d,h) = vector2RhoTheta (pd .-. odometryPosition sbi) vel = if d>2 then vd else vd*(d/2) rcHeadingAux rps -< (sbi, vel, h)

Note the use of rcHeadingAux.Also note how the simbot slows down as it approaches its target, using positional odometry as feedback.

Page 51: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 51

Exercises 9, 10, and 11

9) rcMoveTo may behave a little bit funny once the simbot reaches its destination, because a differential drive robot is not able to maneuver well at slow velocities. Modify rcMove so that once it gets reasonably close to its target, it stops using rcStop.

10) Define a controller to cause a robot to follow a sinusoidal path. (Hint: feed a sinusoidal signal into rcHeadingAux.)

11) Define a controller that takes a list of points and causes the robot to move to each point successively in turn.

Page 52: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 52

Follow that 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:

where r is the range-finder reading, d is the desired distance, and Kp and Kd are the proportionate and derivative gains, respectively.

Page 53: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 53

Wall Follower

This leads to:

rcFollowLeftWall :: Velocity -> Distance -> SimbotControllerrcFollowLeftWall 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))

Page 54: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 54

Exercise 12

Enhance the wall-follower so that it can make left and right turns in a maze constructed only of horizontal and vertical walls. Specifically:

• If the simbot sees a wall directly in front, it should slow down as it approaches, stopping at distance d from the wall. Then it should turn right and continue following the wall which should now be on its left. (This is an inside-corner right turn.)

• If the simbot loses track of the wall on its left, it continues straight ahead for a distance d, turns left, goes straight for distance d again, and then follows the wall which should again be on its left. (This is an outside-corner left turn.)

Page 55: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 55

Your Mission(Exercise 15, should you decide to accept it…)

Be a nerd and do all the exercises in the paper, orBe cool and write a program to play Robocup Soccer!To make it easier for you, we have set up the field (world template) and a skeleton of the code to drop in six controllers (three per team).For example, you may write controllers for a goalkeeper, striker, defender, etc.

But there is one other thing to tell you about first…

Page 56: August 20021 Arrows, FRP, and Functional Reactive Programming Lecture slides from the Oxford Summer School on Advanced Functional Programming Paul Hudak

August 2002 AFP Summer School Lectures 56

Big Brother is Watching

Our simbots are equipped with one other device: an animate object tracker that provides perfect knowledge of the relative positions of the other simbots and balls. Specifically:

aotOtherRobots :: SimbotInput -> [(RobotType, RobotId, Angle, Distance)]aotBalls :: SimbotInput -> [(Angle, Distance)]