YFrob-0.4: afp-demos/AFPDemos.hs
{-# LANGUAGE Arrows #-}
module AFPDemos where
import FRP.YFrob.RobotSim
----------------------------------------------------------------------
-- Template illustrating how to select specific controller based on the
-- robot identity.
rcA :: SimbotController
rcA rProps =
case rpId rProps of
1 -> rcA1 rProps
2 -> rcA2 rProps
3 -> rcA3 rProps
rcA1, rcA2, rcA3 :: SimbotController
rcA1 = undefined
rcA2 = undefined
rcA3 = undefined
----------------------------------------------------------------------
rcStop :: SimbotController
rcStop _ = constant (mrFinalize ddBrake)
rcBlind1 _ = constant (mrFinalize $ ddVelDiff 10 10)
rcBlind2 rps =
let max = rpWSMax rps
in constant (mrFinalize $ ddVelDiff (max/2) (max/2))
rcTurn :: Velocity -> SimbotController
rcTurn vel rps =
let vMax = rpWSMax rps
rMax = 2 * (vMax - vel) / rpDiameter rps
in constant (mrFinalize $ ddVelTR vel rMax)
rcReverse :: Velocity -> SimbotController
rcReverse 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)
rcReverse' v rps =
(rsStuck >>> arr fun) `dSwitch` const (rcReverse' (-v) rps)
where fun stuckE =
let mr = ddVelDiff v v `mrMerge`
tcoPrintMessage (tag stuckE "Ouch!!")
in (mrFinalize mr, stuckE)
rcHeading :: Velocity -> Heading -> SimbotController
rcHeading vel hd rps =
let vMax = rpWSMax rps
vel' = lim vMax vel
k = 2
in proc sbi -> do
let phi = normalizeAngle (hd - odometryHeading sbi)
let vel'' = (1 - abs phi / pi) * vel'
returnA -< mrFinalize (ddVelTR vel'' (k*phi))
rcHeading' :: Velocity -> Heading -> SimbotController
rcHeading' vel hd rps =
proc sbi -> do
rcHeadingAux rps -< (sbi, vel, hd)
rcHeadingAux :: SimbotProperties ->
SF (SimbotInput,Velocity,Heading) SimbotOutput
rcHeadingAux rps =
let vMax = rpWSMax rps
k = 2
in proc (sbi,vel,hd) -> do
let vel' = lim vMax vel
let phi = normalizeAngle (hd - odometryHeading sbi)
let vel'' = (1 - abs phi / pi) * vel'
returnA -< mrFinalize (ddVelTR vel'' (k*phi))
rcMoveTo :: Velocity -> Position2 -> SimbotController
rcMoveTo 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)
rcGoToBall :: Velocity -> SimbotController
rcGoToBall vd rps = proc sbi -> do
let (phi, d) = head (aotBalls sbi ++ [(0.0,0.0)])
h = odometryHeading sbi
rcHeadingAux rps -< (sbi, vd, h + phi)
rcGoToBall2 :: Velocity -> SimbotController
rcGoToBall2 vd rps =
let loop = switch (rcGoToBall vd rps &&& rsStuck) $ \_ ->
switch (constant (mrFinalize (ddVelTR (-vd) 0.3))
&&& after 2.5 ()) $ \_ ->
loop
in
loop
lim m y = max (-m) (min m y)
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
returnA -< mrFinalize (ddVelTR v (lim 0.2 omega))
rcAlign :: Velocity -> SimbotController
rcAlign v rps = proc sbi -> do
let neighbors = aotOtherRobots sbi
vs = map (\(_,_,a,d) -> vector2Polar d a) neighbors
avg = if vs==[] then zeroVector
else foldl1 (^+^) vs ^/ fromInteger (toInteger (length vs))
heading = vector2Theta avg + odometryHeading sbi
rcHeadingAux rps -< (sbi, v, heading)
-- o <- rcHeadingAux' rps -< (sbi, v, heading)
-- printE <- repeatedly 1.0 () -< ()
-- returnA -< mrFinalize (mrMerge o
-- (tcoPrintMessage (tag printE (show (vs,heading)))))