Advertisement
Guest User

robo-mine with Observables

a guest
Jun 26th, 2014
200
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 4.79 KB | None | 0 0
  1. package uebung03
  2.  
  3. import robomine.Simulation
  4. import scala.util.Try
  5. import robomine.RobotControls
  6. import scala.Array.canBuildFrom
  7. import rx.lang.scala.Observable
  8. import rx.lang.scala.Subscription
  9. import scala.concurrent.duration._
  10. import rx.lang.scala.Subject
  11. import rx.lang.scala.Observer
  12. import scala.concurrent.duration._
  13. import scala.language.postfixOps
  14. import scala.util.Random
  15.  
  16. object Uebung03 extends App {  
  17.   val mine = Simulation.start(teams = 1)  
  18.  
  19.   val t0 = System.currentTimeMillis()
  20.        
  21.   mine.onReady { robots =>
  22.     val eventBus = Subject[Double]()
  23.     RobotBehavior.create(eventBus)(robots.last)    
  24.   }
  25.  
  26.   mine.onGoldCollected { amount =>
  27.     if (amount > 100) {
  28.       val time = (System.currentTimeMillis() - t0).toDouble / 1000
  29.       println(f"yeehaw! it took $time%.3f seconds")
  30.       mine.stop()
  31.     }
  32.   }
  33. }
  34.  
  35. case class Length(val m: Double) extends AnyVal {
  36.   def -(that: Length) = Length(this.m - that.m)
  37.   def +(that: Length) = Length(this.m + that.m)
  38. }
  39.  
  40. case class Angle(val rad: Double) extends AnyVal {
  41.   def normal = rad + (Math.PI % (2 * Math.PI) + (2 * Math.PI)) % (2 * Math.PI) - Math.PI
  42.   def unit = Vector(Length(Math.cos(rad)),Length(Math.sin(rad)))  
  43.   def +(that: Angle) = Angle(this.rad + that.rad)
  44.   def -(that: Angle) = Angle(this.rad - that.rad)
  45. }
  46.  
  47. object Angle {
  48.   def fromDeg(deg: Double) = Angle(deg / (180 / Math.PI))  
  49. }
  50.  
  51. case class Vector(north: Length, west: Length) {
  52.   def to (that: Vector) = Vector(that.north - this.north, that.west - this.west)
  53.   def angle = Angle(Math.atan2(west.m, north.m) - Math.PI * 0.5)
  54. }
  55.  
  56. case class Laser(left: Double, center: Double, right: Double)
  57.  
  58. object RobotBehavior {  
  59.   implicit class PimpedObservable[T](val underlying: Observable[T]) extends AnyVal {    
  60.     def foreach(f: T => Unit) = underlying.subscribe(f,e => println(e),() => println("completed"))
  61.   }
  62.  
  63.   def create(eventBus: Subject[Double])(controls: RobotControls) {
  64.       object sensors {
  65.         def powerSave[T](delay: Duration)(sensor: => Observable[T]) = Observable.defer(sensor).delaySubscription(delay).first.repeat
  66.        
  67.         val sensorScheduler = rx.lang.scala.schedulers.TrampolineScheduler()
  68.        
  69.         private def sensor[T](name: String)(f: String => T) = Observable.create[T]{ obs =>
  70.             val handler = (x: String) => obs.onNext(f(x))
  71.             controls.addEventListener(name, handler)
  72.             Subscription(controls.removeEventListener(name, handler))
  73.           }.observeOn(sensorScheduler)
  74.        
  75.           def gps = sensor[Vector]("gps"){ raw =>
  76.             val Array(n,w) = raw.split(" ")
  77.             Vector(Length(n.init.toDouble), Length(w.init.toDouble))
  78.           }
  79.          
  80.           def batteryLevel  = sensor[Double]("batteryLevel")(raw => raw.init.toDouble / 100)
  81.          
  82.           def compass       = sensor[Angle]("compass")(raw => Angle.fromDeg(raw.init.toDouble))
  83.          
  84.           def gyroscope     = sensor[Angle]("gyroscope")(raw => Angle.fromDeg(raw.toDouble))
  85.          
  86.           def accelerometer = sensor[Vector]("accelerometer"){ raw =>
  87.             val Array(n,w) = raw.split(" ")
  88.             Vector(Length(n.toDouble), Length(w.toDouble))
  89.           }
  90.          
  91.           def laser = sensor[Laser]("laser"){ raw =>
  92.             val Array(l,c,r) = raw.split(" ")
  93.             Laser(l.toDouble, c.toDouble, r.toDouble)
  94.           }
  95.          
  96.           def goldDetector = sensor[Double]("goldDetector")(raw => raw.toDouble)         
  97.       }
  98.      
  99.       object outputs {
  100.         private def output(name: String) = Observer[Double](
  101.             (level: Double) => controls.setPowerLevel(name, level),
  102.             () => controls.setPowerLevel(name, 0.0))
  103.            
  104.         def leftWheel = output("leftWheel")    
  105.         def rightWheel = output("rightWheel")
  106.        
  107.         object laser {
  108.           def left = output("laserL")
  109.           def center = output("laserC")
  110.           def right = output("laserR")
  111.         }
  112.       }
  113.  
  114.       val orientation =  
  115.         sensors.powerSave(2 seconds)(sensors.compass).map(keyframe => sensors.gyroscope.scan(keyframe)(_ + _)).switch
  116.                        
  117.       def steer(speed: Observable[Double], desiredDirection: Observable[Angle]) = {
  118.         val c = orientation.combineLatest[Angle,Double](desiredDirection, ((a,r) => (r-a).normal / Math.PI ))      
  119.         speed.combineLatest[Double,Double](c, (s,c) => s + s * -c).subscribe(outputs.leftWheel)
  120.         speed.combineLatest[Double,Double](c, (s,c) => s + s * c).subscribe(outputs.rightWheel)    
  121.       }
  122.          
  123.       def goTo(pos: Observable[Vector]) = {
  124.         def desiredDirection = sensors.gps.combineLatest[Vector,Angle](pos, (gps,pos) => (pos to gps).angle)
  125.         steer(Observable.items(1),desiredDirection)
  126.       }
  127.      
  128.       def criticalBattery =
  129.         sensors.batteryLevel.filter(x => x < 0.4 || x > 0.95).map(_ < 0.5)
  130.         .distinctUntilChanged    
  131.        
  132.       val basePosition = Vector(Length(60),Length(60))
  133.      
  134.       goTo(criticalBattery.map(if (_) basePosition else Vector(Length(0),Length(0))))
  135.   }  
  136. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement