Пример #1
0
 def place_cube(self):
     pos = combinedPose(self.robot.localisation.pose(), (0.2, 0, 0))[:2]  # TODO check proper offset
     print "place cube at ({:.2f}, {:.2f} (time = {:.1f}))".format(pos[0], pos[1], self.robot.time - self.start_time)
     viewlog.dumpBeacon(pos, color=(255, 255, 255))
     viewlog.dumpObstacles([[pos]])
     gripperOpen(self.robot)
     self.driver.goStraight(-0.4, timeout=30)
Пример #2
0
  def updateExtension( self, robot, id, data ):
    global g_weedReportEnabled
    if id == 0x80:
      self.counter += 1
      if len(self.lastCamera)> 0:
#        print self.counter, self.lastCamera
        cmd = self.lastCamera[0]
        if self.counter >= cmd[0]:
          self.lastCamera = self.lastCamera[1:]
          if cmd[1] or cmd[2]:
            robot.beep  = 1
          else:
            robot.beep  = 0
          sprayer( robot, cmd[1], cmd[2] )
    if id == 'camera':
      if self.verbose and len(data) > 1:
        print data[1]
      cc = [int(x) for x in data[0].split()]
      leftPip = (cc[0] > BALL_SIZE_LIMIT_MIN and cc[0] < BALL_SIZE_LIMIT_MAX)
      rightPip = (cc[1] > BALL_SIZE_LIMIT_MIN and cc[1] < BALL_SIZE_LIMIT_MAX)
      if leftPip or rightPip:
        print "WEED:", leftPip, rightPip, g_weedReportEnabled
        if leftPip and g_weedReportEnabled:
          xy = combinedPose(robot.localisation.pose(), (0,0.35,0))[:2]
#          reportBall( robot.gpsData )
          viewlog.dumpBeacon( xy, color=(255,255,0) )
        if rightPip and g_weedReportEnabled:
          xy = combinedPose(robot.localisation.pose(), (0,-0.35,0))[:2]
#          reportBall( robot.gpsData )
          viewlog.dumpBeacon( xy, color=(255,255,0) )
        if g_weedReportEnabled:
          self.lastCamera.append( (self.counter + 0, leftPip, rightPip ) )
      else:
        self.lastCamera.append( (self.counter + 0+4, False, False) )
Пример #3
0
  def reset( self, pose = (0,0,0), offsetDeg=0 ):
    global g_weedReportEnabled
    g_weedReportEnabled = True
    print "RESET ROW (%0.2f, %0.2f, %0.1f), offset=" % (pose[0], pose[1], math.degrees(pose[2])), offsetDeg 
    viewlog.dumpBeacon( pose[:2], color=(128,128,128) )
    self.preference = None
    self.center = None
    if self.rowHeading:
      self.directionAngle = normalizeAnglePIPI(self.rowHeading-pose[2])
      if abs(self.directionAngle) > math.radians(90):
        self.directionAngle = normalizeAnglePIPI(self.rowHeading-pose[2]+math.radians(180))
      if self.verbose:
        print "RESET_DIFF %.1f" % math.degrees(self.directionAngle)
    else:
      self.directionAngle = 0.0 # if you do not know, go ahead
    goal = combinedPose( (pose[0], pose[1], pose[2]+self.directionAngle), (self.radius, 0, 0) )
    self.line = Line( pose, goal )
# self.line = Line( (0.0, 0.0), (1.0, 0.0) )
    self.newData = False
    self.endOfRow = False
    self.cornLeft = 10.0 # far
    self.cornRight = 10.0
    self.collisionAhead = 10.0,10.0,False,False # far (wide, narrow, override, danger)
    self.lastLeft, self.lastRight = None, None
    self.prevLR = None
    self.poseHistory = []
Пример #4
0
 def reset(self, pose=(0, 0, 0), offsetDeg=0):
     print "RESET ROW (%0.2f, %0.2f, %0.1f), offset=" % (
         pose[0], pose[1], math.degrees(pose[2])), offsetDeg
     viewlog.dumpBeacon(pose[:2], color=(128, 128, 128))
     self.preference = None
     self.center = None
     if self.rowHeading:
         self.directionAngle = normalizeAnglePIPI(self.rowHeading - pose[2])
         if abs(self.directionAngle) > math.radians(90):
             self.directionAngle = normalizeAnglePIPI(self.rowHeading -
                                                      pose[2] +
                                                      math.radians(180))
         if self.verbose:
             print "RESET_DIFF %.1f" % math.degrees(self.directionAngle)
     else:
         self.directionAngle = 0.0  # if you do not know, go ahead
     goal = combinedPose((pose[0], pose[1], pose[2] + self.directionAngle),
                         (self.radius, 0, 0))
     self.line = Line(pose, goal)
     # self.line = Line( (0.0, 0.0), (1.0, 0.0) )
     self.newData = False
     self.endOfRow = False
     self.cornLeft = 10.0  # far
     self.cornRight = 10.0
     self.collisionAhead = 10.0, 10.0, False  # far (wide, narrow, override)
     self.lastLeft, self.lastRight = None, None
     self.prevLR = None
     self.poseHistory = []
Пример #5
0
def draw_cubes_extension(robot, id, data):
    if id == 'laser':
#        cd = CubeDetector(robot.laser.pose)
#        cubes = cd.detect_cubes_xy(data, limit=4)
        # Jakub's alternative
        cubes = cubesFromScan(data)
        for cube_x, cube_y in cubes:
            goal = combinedPose(robot.localisation.pose(), (cube_x, cube_y, 0))[:2]
            viewlog.dumpBeacon(goal, color=(128, 255, 128))
Пример #6
0
    def find_cube(self, timeout):
        print "find_cube-v1"
        prev = None
        cd = CubeDetector(self.robot.laser.pose)
        startTime = self.robot.time
        while self.robot.time < startTime + timeout:
            self.robot.update()
            if prev != self.robot.laserData:
                prev = self.robot.laserData
                cubes = cd.detect_cubes_xy(self.robot.laserData, limit=4)
                if len(cubes) > 0:
                    for i, (cube_x, cube_y) in enumerate(cubes):
                        goal = combinedPose(self.robot.localisation.pose(), (cube_x, cube_y, 0))[:2]
                        viewlog.dumpBeacon(goal, color=(200, 200, 0) if i > 0 else (255, 255, 0))
                    cube_x, cube_y = cubes[0]
                    cube_y += 0.05  # hack for bended(?) laser
                    print "{:.2f}\t{:.2f}".format(cube_x, cube_y)
                    speed = 0.0

                    tolerance = 0.01
                    if cube_x > 0.5:
                        tolerance = 0.05

                    angle = math.atan2(cube_y, cube_x)
                    turnStep = math.radians(10)
                    if abs(angle) > math.radians(10):
                        turnStep = math.radians(50)

                    if cube_y > tolerance:
                        angularSpeed = turnStep
                    elif cube_y < -tolerance:
                        angularSpeed = -turnStep
                    else:
                        angularSpeed = 0
                        speed = 0.1
                        if cube_x > 0.5:
                            speed = 0.3  # move faster toward further goals
                        if cube_x < 0.30:
                            return True
                    self.robot.setSpeedPxPa(speed, angularSpeed)
                else:
                    self.robot.setSpeedPxPa(0.0, 0.0)

        print "TIMEOUT"
        return False
Пример #7
0
    def ver0( self, verbose=False ):
        # Go straight for 2 meters
        print "ver0", self.robot.battery

        prevRFID = None
        self.load_cube()
        for cmd in self.driver.goStraightG(2.0):
            self.robot.setSpeedPxPa(*cmd)

            if prevRFID != self.robot.rfu620Data:
                prevRFID = self.robot.rfu620Data
                posXY = combinedPose(self.robot.localisation.pose(), (-0.35, 0.14, 0))[:2]
                for d in self.robot.rfu620Data[1]:
                    i = d[0]  # i.e. 0x1000 0206 0000
                    x, y, zone = (i >> 24)&0xFF, (i >> 16)&0xFF, i&0xFF
                    print hex(i), (x, y)
                    if x == 1:
                        viewlog.dumpBeacon(posXY, color=(0, 0, 255))
                    elif x == 2:
                        viewlog.dumpBeacon(posXY, color=(255, 0, 255))
                    else:
                        viewlog.dumpBeacon(posXY, color=(255, 255, 255))
            self.robot.update()
        self.place_cube()
        self.game_over()
Пример #8
0
 def updateExtension(self, robot, id, data):
     global g_weedReportEnabled
     if id == 0x80:
         self.counter += 1
         if len(self.lastCamera) > 0:
             #        print self.counter, self.lastCamera
             cmd = self.lastCamera[0]
             if self.counter >= cmd[0]:
                 self.lastCamera = self.lastCamera[1:]
                 if cmd[1] or cmd[2]:
                     robot.beep = 1
                 else:
                     robot.beep = 0
                 sprayer(robot, cmd[1], cmd[2])
     if id == 'camera':
         if self.verbose and len(data) > 1:
             print data[1]
         cc = [int(x) for x in data[0].split()]
         leftPip = (cc[0] > BALL_SIZE_LIMIT_MIN
                    and cc[0] < BALL_SIZE_LIMIT_MAX)
         rightPip = (cc[1] > BALL_SIZE_LIMIT_MIN
                     and cc[1] < BALL_SIZE_LIMIT_MAX)
         if leftPip or rightPip:
             print "WEED:", leftPip, rightPip, g_weedReportEnabled
             if leftPip and g_weedReportEnabled:
                 xy = combinedPose(robot.localisation.pose(),
                                   (0, 0.35, 0))[:2]
                 #          reportBall( robot.gpsData )
                 viewlog.dumpBeacon(xy, color=(255, 255, 0))
             if rightPip and g_weedReportEnabled:
                 xy = combinedPose(robot.localisation.pose(),
                                   (0, -0.35, 0))[:2]
                 #          reportBall( robot.gpsData )
                 viewlog.dumpBeacon(xy, color=(255, 255, 0))
             if g_weedReportEnabled:
                 self.lastCamera.append(
                     (self.counter + 0, leftPip, rightPip))
         else:
             self.lastCamera.append((self.counter + 0 + 4, False, False))
Пример #9
0
def draw_rfu620_extension(robot, id, data):
    if id=='rfu620':
        posXY = combinedPose(robot.localisation.pose(), RFU620_POSE)[:2]
        for index, d in enumerate(data[1], start=1):
            robot.last_valid_rfid = d, posXY
            i, rssi = d[:2]  # i.e. 0x1000 0206 0000
            x, y, zone = (i >> 24)&0xFF, (i >> 16)&0xFF, i&0xFF
            print hex(i), (x, y), rssi, '({}/{})'.format(index, len(data[1]))
            if (x + y) % 2 == 0:
                if rssi > -60:
                    viewlog.dumpBeacon(posXY, color=(0, 0, 255))
                else:
                    viewlog.dumpBeacon(posXY, color=(0, 0, 128))
            else:
                if rssi > -60:
                    viewlog.dumpBeacon(posXY, color=(255, 0, 255))
                else:
                    viewlog.dumpBeacon(posXY, color=(128, 0, 128))
Пример #10
0
    def approachFeeder(self, timeout=60, digitHelper=None, verifyTarget=True):
        "robot should be within 1m of the feeder"
        print "Approaching Feeder"
        verified = False
        desiredDist = 0.4  #0.2
        countOK = 0
        startTime = self.robot.time
        angularSpeed = 0
        prevPose = None
        prevName = None
        prevLaser = None
        target = None
        frontDist, minDistL, minDistR = None, None, None
        while startTime + timeout > self.robot.time:
            if self.robot.cameraData is not None and len(
                    self.robot.cameraData
            ) > 0 and self.robot.cameraData[0] is not None:
                if prevName != self.robot.cameraData[1]:
                    #          print prevName, self.robot.localisation.pose()
                    prevName = self.robot.cameraData[1]
                    if prevPose is None:
                        prevPose = self.robot.localisation.pose()
                        prevLaser = self.robot.laserData[:]
                    arr = eval(self.robot.cameraData[0])
                    angularSpeed = None
                    for a in arr:
                        for digit, (x, y, dx, dy) in a:
                            if digit == 'X':
                                verified = True
                                angularSpeed = (320 - (x + dx / 2)) / 100.0
                                #                print "angularSpeed", math.degrees(angularSpeed), self.robot.cameraData[1], (x,y,dx,dy)
                                centerX = 320
                                angle = (centerX -
                                         (x + dx / 2)) * 0.002454369260617026
                                dist = prevLaser[int(angle / 2.) + 271] / 1000.
                                print "Target at", dist, self.robot.cameraData[
                                    1]
                                t = combinedPose((prevPose[0], prevPose[1],
                                                  prevPose[2] + angle),
                                                 (dist, 0, 0))
                                target = (t[0], t[1])
                                viewlog.dumpBeacon(target, color=(255, 128, 0))
                                break
                    if target is None and digitHelper is not None:
                        # if you do not have goal try to re-search old number
                        for a in arr:
                            for digit, (x, y, dx, dy) in a:
                                if digit == 'X':
                                    angularSpeed = (320 - (x + dx / 2)) / 100.0
                                    centerX = 320
                                    angle = (
                                        centerX -
                                        (x + dx / 2)) * 0.002454369260617026
                                    dist = prevLaser[int(angle / 2.) +
                                                     271] / 1000.
                                    t = combinedPose((prevPose[0], prevPose[1],
                                                      prevPose[2] + angle),
                                                     (dist, 0, 0))
                                    target = (t[0], t[1])
                                    viewlog.dumpBeacon(target,
                                                       color=(255, 0, 255))
                                    break

                    prevPose = self.robot.localisation.pose()
                    prevLaser = self.robot.laserData[:]
                if angularSpeed is None:
                    angularSpeed = 0

            if target is None or distance(
                    target, self.robot.localisation.pose()) < 0.3:
                angularSpeed = 0.0
            else:
                pose = self.robot.localisation.pose()
                angularSpeed = normalizeAnglePIPI(
                    angleTo(pose, target) - pose[2])


#        print "target:", target, math.degrees(angularSpeed)

            if self.robot.laserData == None or len(
                    self.robot.laserData) != 541:
                self.robot.setSpeedPxPa(0, 0)
            else:
                minDistR = min(
                    [10000] +
                    [x for x in self.robot.laserData[180:541 / 2]
                     if x > 0]) / 1000.
                minDistL = min(
                    [10000] +
                    [x for x in self.robot.laserData[541 / 2:-180]
                     if x > 0]) / 1000.
                minDist = min(minDistL, minDistR)
                frontDist = min(
                    [10000] +
                    [x
                     for x in self.robot.laserData[265:-265] if x > 0]) / 1000.
                self.robot.setSpeedPxPa(
                    min(self.driver.maxSpeed, minDist - desiredDist),
                    angularSpeed)
                #        print min(self.driver.maxSpeed, minDist - desiredDist)
                #        self.robot.setSpeedPxPa( 0, angularSpeed )
                if abs(minDist - desiredDist) < 0.01:
                    countOK += 1
                else:
                    countOK = 0
                if countOK >= 10:
                    break
            self.robot.update()
        self.robot.setSpeedPxPa(0, 0)
        self.robot.update()
        print "done."

        if verifyTarget and not verified:
            print "TARGET not verified!"
            return False

        # compute proper rotation and backup distance
        toTurn, toBackup = computeLoadManeuver(minDistL, frontDist, minDistR)
        print "Suggestion: ", math.degrees(toTurn), toBackup
        self.driver.turn(toTurn,
                         angularSpeed=math.radians(20),
                         timeout=30,
                         verbose=True)
        self.driver.goStraight(toBackup, timeout=30)
        return True
Пример #11
0
def competeRobotemRovne( drone, desiredHeight = 1.5 ):
  drone.speed = 0.1
  maxVideoDelay = 0.0
  maxControlGap = 0.0
  desiredSpeed = MAX_ALLOWED_SPEED
  refLine = DEFAULT_REF_LINE
  
  try:
    drone.wait(1.0)
    drone.setVideoChannel( front=True )
    downloadOldVideo( drone, timeout=20.0 )
    drone.takeoff()
    poseHistory = []
    startTime = drone.time
    while drone.time < startTime + 1.0:
      drone.update("AT*PCMD=%i,0,0,0,0,0\r") # drone.hover(1.0)
      # TODO sonar/vision altitude
      poseHistory.append( (drone.time, (drone.coord[0], drone.coord[1], drone.heading), (drone.angleFB, drone.angleLR), None) )
    magnetoOnStart = drone.magneto[:3]
    print "NAVI-ON"
    startTime = drone.time
    sx,sy,sz,sa = 0,0,0,0
    lastUpdate = None
    while drone.time < startTime + 600.0:

      altitude = desiredHeight
      if drone.altitudeData != None:
        altVision = drone.altitudeData[0]/1000.0
        altSonar = drone.altitudeData[3]/1000.0
        altitude = (altSonar+altVision)/2.0
        # TODO selection based on history? panic when min/max too far??
        if abs(altSonar-altVision) > 0.5:
          print altSonar, altVision
          altitude = max( altSonar, altVision ) # sonar is 0.0 sometimes (no ECHO)

      sz = max( -0.2, min( 0.2, desiredHeight - altitude ))
      if altitude > 2.5:
        # wind and "out of control"
        sz = max( -0.5, min( 0.5, desiredHeight - altitude ))

      sx = max( 0, min( drone.speed, desiredSpeed - drone.vx ))

      if drone.lastImageResult:
        lastUpdate = drone.time
        assert len( drone.lastImageResult ) == 2 and len( drone.lastImageResult[0] ) == 2, drone.lastImageResult
        (frameNumber, timestamp), rects = drone.lastImageResult
        viewlog.dumpVideoFrame( frameNumber, timestamp )

        # keep history small
        videoTime = correctTimePeriod( timestamp/1000., ref=drone.time )
        videoDelay = drone.time - videoTime
        if videoDelay > 1.0:
          print "!DANGER! - video delay", videoDelay
        maxVideoDelay = max( videoDelay, maxVideoDelay )
        toDel = 0
        for oldTime, oldPose, oldAngles, oldAltitude in poseHistory:
          toDel += 1
          if oldTime >= videoTime:
            break
        poseHistory = poseHistory[:toDel]

        tiltCompensation = Pose(desiredHeight*oldAngles[0], desiredHeight*oldAngles[1], 0) # TODO real height?
        print "FRAME", frameNumber/15, "[%.1f %.1f]" % (math.degrees(oldAngles[0]), math.degrees(oldAngles[1])),
#        print "angle", math.degrees(drone.angleFB-oldAngles[0]), math.degrees(drone.angleLR-oldAngles[1])
        if rects != None and len(rects) > 0:
          # note, that "rects" could be None, when video processing is OFF (g_processingEnabled==False)
          if oldAltitude == None:
            oldAltitude = altitude
          debugImg = None
          if drone.replayLog != None:
            debugFilename = "tmp_%04d.jpg" % (frameNumber/FRAMES_PER_INDEX)            
            debugImg = cv2.imread( debugFilename )
          line = chooseBestWidth( rects, coord=oldPose[:2], height=oldAltitude, 
              heading=oldPose[2], angleFB=oldAngles[0], angleLR=oldAngles[1], debugImg=debugImg )
          if line:
            rejected = False
            if refLine != None:
              print "%.1fdeg %.2fm" % (math.degrees(normalizeAnglePIPI(refLine.angle - line.angle)), refLine.signedDistance( line.start ))
              if abs(normalizeAnglePIPI(refLine.angle - line.angle)) < MAX_REF_LINE_ANGLE and \
                  abs(refLine.signedDistance( line.start )) < MAX_REF_LINE_DIST:
                refLine = line
              else:
                rejected = True
            else:
              refLine = line
            viewlog.dumpBeacon( line.start, index=3 )
            viewlog.dumpBeacon( line.end, index=3 )
            if drone.replayLog != None:
              if rejected:
                # redraw image with yellow color
                chooseBestWidth( rects, coord=oldPose[:2], height=oldAltitude, 
                    heading=oldPose[2], angleFB=oldAngles[0], angleLR=oldAngles[1], debugImg=debugImg, color=(0,255,255) )
              cv2.imwrite( debugFilename, debugImg )
        else:
          print rects

        desiredSpeed = MAX_ALLOWED_SPEED
        if videoDelay > MAX_ALLOWED_VIDEO_DELAY:
          desiredSpeed = 0.0

        if drone.battery < 10:
          print "BATTERY LOW!", drone.battery

        # height debugging
        #print "HEIGHT\t%d\t%d\t%.2f\t%d\t%d\t%d\t%d\t%d\t%d" % tuple([max([0]+[w for ((x,y),(w,h),a) in rects])] + list(drone.altitudeData[:4]) + list(drone.pressure) )

      # error definition ... if you substract that you get desired position or angle
      # error is taken from the path point of view, x-path direction, y-positive left, angle-anticlockwise
      errY, errA = 0.0, 0.0
      if refLine:
        errY = refLine.signedDistance( drone.coord )
        errA = normalizeAnglePIPI( drone.heading - refLine.angle )

      # get the height first
      if drone.coord[2] < desiredHeight - 0.1 and drone.time-startTime < 5.0:
        sx = 0.0
      # error correction
      # the goal is to have errY and errA zero in 1 second -> errY defines desired speed at given distance from path
      sy = max( -0.2, min( 0.2, -errY-drone.vy ))/2.0
      
      # there is no drone.va (i.e. derivative of heading) available at the moment ... 
      sa = max( -0.1, min( 0.1, -errA/2.0 ))*1.35*(desiredSpeed/0.4) # originally set for 0.4=OK

#      print "%0.2f\t%d\t%0.2f\t%0.2f\t%0.2f" % (errY, int(math.degrees(errA)), drone.vy, sy, sa)
      prevTime = drone.time
      drone.moveXYZA( sx, sy, sz, sa )
      maxControlGap = max( drone.time - prevTime, maxControlGap )
      poseHistory.append( (drone.time, (drone.coord[0], drone.coord[1], drone.heading), (drone.angleFB, drone.angleLR), altitude) )
    print "NAVI-OFF", drone.time - startTime
    drone.hover(0.5)
    drone.land()
    drone.setVideoChannel( front=True )    
  except ManualControlException, e:
    print "ManualControlException"
    if drone.ctrlState == 3: # CTRL_FLYING=3 ... i.e. stop the current motion
      drone.hover(0.1)
    drone.land()
Пример #12
0
  def approachFeeder( self, timeout=60, digitHelper=None, verifyTarget=True ):
    "robot should be within 1m of the feeder"
    print "Approaching Feeder"
    verified = False
    desiredDist = 0.4 #0.2
    countOK = 0
    startTime = self.robot.time
    angularSpeed = 0
    prevPose = None
    prevName = None
    prevLaser = None
    target = None
    frontDist, minDistL, minDistR = None, None, None
    while startTime + timeout > self.robot.time:
      if self.robot.cameraData is not None and len(self.robot.cameraData)> 0 and self.robot.cameraData[0] is not None:
        if prevName != self.robot.cameraData[1]:
#          print prevName, self.robot.localisation.pose()
          prevName = self.robot.cameraData[1]
          if prevPose is None:
            prevPose = self.robot.localisation.pose()
            prevLaser = self.robot.laserData[:]
          arr = eval(self.robot.cameraData[0])
          angularSpeed = None
          for a in arr:
            for digit, (x,y,dx,dy) in a:
              if digit == 'X':
                verified = True
                angularSpeed = (320-(x+dx/2))/100.0
#                print "angularSpeed", math.degrees(angularSpeed), self.robot.cameraData[1], (x,y,dx,dy)
                centerX = 320
                angle = (centerX-(x+dx/2))*0.002454369260617026
                dist = prevLaser[int(angle/2.)+271]/1000.
                print "Target at", dist, self.robot.cameraData[1]
                t = combinedPose( (prevPose[0], prevPose[1], prevPose[2]+angle), (dist,0,0) )
                target = (t[0],t[1])
                viewlog.dumpBeacon( target, color=(255,128,0) )
                break
          if target is None and digitHelper is not None:
            # if you do not have goal try to re-search old number
            for a in arr:
              for digit, (x,y,dx,dy) in a:
                if digit == 'X':
                  angularSpeed = (320-(x+dx/2))/100.0
                  centerX = 320
                  angle = (centerX-(x+dx/2))*0.002454369260617026
                  dist = prevLaser[int(angle/2.)+271]/1000.
                  t = combinedPose( (prevPose[0], prevPose[1], prevPose[2]+angle), (dist,0,0) )
                  target = (t[0],t[1])
                  viewlog.dumpBeacon( target, color=(255,0,255) )
                  break

          prevPose = self.robot.localisation.pose()
          prevLaser = self.robot.laserData[:]
        if angularSpeed is None:
          angularSpeed = 0

      if target is None or distance( target, self.robot.localisation.pose() ) < 0.3:
        angularSpeed = 0.0
      else:
        pose = self.robot.localisation.pose()
        angularSpeed = normalizeAnglePIPI( angleTo( pose, target) - pose[2] )
#        print "target:", target, math.degrees(angularSpeed)


      if self.robot.laserData == None or len(self.robot.laserData) != 541:
        self.robot.setSpeedPxPa( 0, 0 )
      else:
        minDistR = min([10000]+[x for x in self.robot.laserData[180:541/2] if x > 0])/1000.
        minDistL = min([10000]+[x for x in self.robot.laserData[541/2:-180] if x > 0])/1000.
        minDist = min(minDistL, minDistR)
        frontDist = min([10000]+[x for x in self.robot.laserData[265:-265] if x > 0])/1000.
        self.robot.setSpeedPxPa( min(self.driver.maxSpeed, minDist - desiredDist), angularSpeed )
#        print min(self.driver.maxSpeed, minDist - desiredDist)
#        self.robot.setSpeedPxPa( 0, angularSpeed )
        if abs(minDist - desiredDist) < 0.01:
          countOK += 1
        else:
          countOK = 0
        if countOK >= 10:
          break
      self.robot.update()
    self.robot.setSpeedPxPa( 0, 0 )
    self.robot.update()
    print "done."

    if verifyTarget and not verified:
      print "TARGET not verified!"
      return False

    # compute proper rotation and backup distance
    toTurn, toBackup = computeLoadManeuver( minDistL, frontDist, minDistR )
    print "Suggestion: ", math.degrees(toTurn), toBackup
    self.driver.turn( toTurn, angularSpeed = math.radians(20), timeout=30, verbose=True )
    self.driver.goStraight( toBackup, timeout=30 )
    return True
Пример #13
0
  def crossRows2( self, row, num, rowsOnLeft ):
    IGNORE_NEIGHBORS = 2
    ROWS_OFFSET = 0.7 #0.5

#    if row.lastLeft:
#      viewlog.dumpBeacon(row.lastLeft[:2], color=(0,128,0))
#    if row.lastRight:
#      viewlog.dumpBeacon(row.lastRight[:2], color=(0,128,50))
    start = self.robot.localisation.pose()[:2]
    viewlog.dumpBeacon( start, color=(255,128,0))

    goal = combinedPose( self.robot.localisation.pose(), (1.0, 0, 0) )    
    line = Line( self.robot.localisation.pose(), goal )
    lastA, lastB = None, None
    ends = []
    while True:
      for cmd in self.driver.followLineG( line ):
        self.robot.setSpeedPxPa( *cmd ) 
        self.robot.update()
        if row.newData:
          row.newData = False
          break
      else:
        print "END OF LINE REACHED!"

      if self.robot.preprocessedLaser != None:
        tmp = self.robot.preprocessedLaser[:]
        tlen = len(tmp)
        if rowsOnLeft:
          tmp = tmp[:tlen/2] + [3.0]*(tlen-tlen/2)
        else:
          tmp = [3.0]*(tlen-tlen/2) + tmp[tlen/2:]
        sarr = sorted([(x,i) for (i,x) in enumerate(tmp)])[:5]
        ax,ai = sarr[0]
        for bx,bi in sarr[1:]:
          if abs(ai-bi) > IGNORE_NEIGHBORS:
            break
        else:
          print "NO 2nd suitable minimum"
        print (ax,ai), (bx,bi)
        if rowsOnLeft:
          offset = -ROWS_OFFSET
          if ai > bi:
            (ax,ai), (bx,bi) = (bx,bi), (ax,ai)
        else:
          offset = ROWS_OFFSET
          if ai < bi: # rows on right
            (ax,ai), (bx,bi) = (bx,bi), (ax,ai)
        p = self.robot.localisation.pose()
        A = combinedPose( (p[0], p[1], p[2]+math.radians(135-5*ai) ), (ax,0,0) )
        B = combinedPose( (p[0], p[1], p[2]+math.radians(135-5*bi) ), (bx,0,0) )
        if lastA == None:
          ends.extend( [A,B] )
          lastA, lastB = A, B
        if self.verbose:
          print "DIST", distance(lastA, A), distance(lastB, B), distance(lastB,A)
        if distance(lastB,A) < 0.2:
          dist = distance(start, self.robot.localisation.pose())
          print "NEXT ROW", dist
          if dist > 0.4:
            ends.append( B ) # new one
          lastA, lastB = A, B
        line = Line(A,B) # going through the ends of rows
        A2 = combinedPose( (A[0], A[1], line.angle), (0, offset, 0) )
        B2 = combinedPose( (B[0], B[1], line.angle), (2.0, offset, 0) )
        line = Line(A2, B2)
        viewlog.dumpBeacon( A[:2], color=(200,0,0) )
        viewlog.dumpBeacon( B[:2], color=(200,128,0) )
        viewlog.dumpBeacon( A2[:2], color=(255,0,0) )
        viewlog.dumpBeacon( B2[:2], color=(255,128,0) )
        if len(ends) > num + 1:
          break
      else:
        print "BACKUP solution!!!"
        goal = combinedPose( self.robot.localisation.pose(), (1.0, 0, 0) )    
        line = Line( self.robot.localisation.pose(), goal )
Пример #14
0
  def updateExtension( self, robot, id, data ):
    global g_weedReportEnabled
    if id == 'remission' and len(data) > 0:
      pass # ignored for FRE 2014

    if id == 'laser' and len(data) > 0:
      self.poseHistory.append( robot.localisation.pose()[:2] )
      if len(self.poseHistory) > 20:
        self.poseHistory = self.poseHistory[-20:]
      step = 10
      data2 = [x == 0 and 10000 or x for x in data]
      arr = [min(i)/1000.0 for i in [itertools.islice(data2, start, start+step) for start in range(0,len(data2),step)]]
      arr.reverse()
      robot.preprocessedLaser = arr

      limit = self.radius
      danger = False
      prevCenter = self.center
      if self.center != None:
#        if center > 0 and center < len(arr)-1 and arr[center] < limit and arr[center-1] < limit and arr[center+1] < limit:
        if self.center > 0 and self.center < len(arr)-1 and arr[self.center] < limit:
          print "!!!DANGER!!! PATH BLOCKED!!!", self.center
          danger = True
      if self.center==None or danger:
        # offset is not set - find nearest
        if self.center == None:
          self.center = len(arr)/2
        if arr[self.center] < limit:
          i = 0
          while i < self.center:
            if arr[self.center - i] >= limit:
              break
            i += 1
          left = i
          i = 0
          while i + self.center < len(arr):
            if arr[self.center + i] >= limit:
              break
            i += 1
          right = i
          print "HACK", left, right
          if left < right:
            self.center += -left
          else:
            self.center += right

      i = 0
      if self.center < 0 or self.center >= len(arr):
        self.center = prevCenter
      if self.center == None:
        self.center = len(arr)/2
      while i <= self.center:
        if arr[self.center - i] < limit:
          break
        i += 1
      left = i # arr is already reversed
      i = 0
      while i + self.center < len(arr):
        if arr[self.center + i] < limit:
          break
        i += 1
      right = i

      p = robot.localisation.pose()
      if self.center-left >= 0:
        self.lastLeft = combinedPose( (p[0], p[1], p[2]+math.radians(135-5*(self.center-left)) ), (arr[self.center-left],0,0) )
#        viewlog.dumpBeacon(self.lastLeft[:2], color=(0,128,0))
      if self.center+right < len(arr):
        self.lastRight = combinedPose( (p[0], p[1], p[2]+math.radians(135-5*(self.center+right)) ), (arr[self.center+right],0,0) )
#        viewlog.dumpBeacon(self.lastRight[:2], color=(0,128,50))

      if self.verbose:
        if danger and left+right < MIN_GAP_SIZE:
          print "MIN GAP SIZE danger:", left+right
        s = ''
        for i in arr:
          s += (i < 0.5 and 'X' or (i<1.0 and 'x' or (i<1.5 and '.' or ' ')))
        s = "".join( list(s)[:self.center] + ['C'] + list(s)[self.center:] )
        print "'" + s + "'"      
#        print "LRLR\t%d\t%d\t%d" % (left, right, left+right)
#        if self.prevLR :
#          print "LRDIFF", left-self.prevLR[0], right-self.prevLR[1]

      self.line = None # can be defined inside
      if left+right <= MAX_GAP_SIZE: # TODO limit based on minSize, radius and sample angle
        self.center += (right-left)/2
        offset = self.center-len(arr)/2
        self.directionAngle = math.radians( -offset*step/2.0 )
        self.collisionAhead = min(arr[54/3:2*54/3]), min(arr[4*54/9:5*54/9]), (left+right < MIN_GAP_SIZE), danger
        if False: #self.verbose:
          if self.collisionAhead[0] < 0.25:
            print "!!! COLISSION AHEAD !!!", self.collisionAhead
          else:
            print "free space", self.collisionAhead
      elif left < 3 or right < 3:
        # wide row & collision ahead
        if self.verbose:
          print "NEAR", left, right, left+right
        offset = self.center-len(arr)/2
        if left < right:
          offset += 3
        else:
          offset -= 3
        self.directionAngle = math.radians( -offset*step/2.0 )
      else:
        if self.verbose:
          print "OFF", left, right #, left+right, robot.compass
        if False: # hacked, ignoring compass   self.rowHeading:
          self.directionAngle = normalizeAnglePIPI(self.rowHeading-robot.localisation.pose()[2])
          if abs(self.directionAngle) > math.radians(90):
            self.directionAngle = normalizeAnglePIPI(self.rowHeading-robot.localisation.pose()[2]+math.radians(180))
          if self.verbose:
            print "DIFF %.1f" % math.degrees(self.directionAngle)
        else:
          if self.verbose:
            print "PATH GAP"    
          A, B = self.poseHistory[0][:2], self.poseHistory[-1][:2]
          viewlog.dumpBeacon( A, color=(0,0,180) )
          viewlog.dumpBeacon( B, color=(0,30,255) )
          self.line = Line( B, (2*B[0]-A[0], 2*B[1]-A[1]) ) # B+(B-A)
          if self.line and self.line.length < 0.5:
            self.line = None
          else:
            self.center = len(arr)/2
            # reset center
          """if self.prevLR:
            if abs(left-self.prevLR[0]) > 4 and abs(right-self.prevLR[1]) < 3:
              left = self.prevLR[0]
              self.center += (right-left)/2
              offset = self.center-len(arr)/2
              self.directionAngle = math.radians( -offset*step/2.0 )
            elif abs(right-self.prevLR[1]) > 4 and abs(left-self.prevLR[0]) < 3:
              right = self.prevLR[1]
              self.center += (right-left)/2
              offset = self.center-len(arr)/2
              self.directionAngle = math.radians( -offset*step/2.0 )
            else:
              self.directionAngle = 0.0 # if you do not know, go ahead
          else:
            self.directionAngle = 0.0 # if you do not know, go ahead"""
          self.directionAngle = 0.0 # default
          
        if left >= 17 and right >= 17 or left+right >= 40:
          self.endOfRow = True
          g_weedReportEnabled = False
          if self.verbose and robot.insideField:
            print "laser: END OF ROW"
      self.prevLR = left, right

      pose = robot.localisation.pose()
      goal = combinedPose( (pose[0], pose[1], pose[2]+self.directionAngle), (self.radius, 0, 0) )
      if self.line == None:
        self.line = Line( pose, goal )
      self.newData = True
      self.cornLeft = min(arr[5:9])
      self.cornRight = min(arr[40:44])
Пример #15
0
def competeRobotemRovne(drone, desiredHeight=1.5):
    drone.speed = 0.1
    maxVideoDelay = 0.0
    maxControlGap = 0.0
    desiredSpeed = MAX_ALLOWED_SPEED
    refLine = DEFAULT_REF_LINE

    try:
        drone.wait(1.0)
        drone.setVideoChannel(front=True)
        downloadOldVideo(drone, timeout=20.0)
        drone.takeoff()
        poseHistory = []
        startTime = drone.time
        while drone.time < startTime + 1.0:
            drone.update("AT*PCMD=%i,0,0,0,0,0\r")  # drone.hover(1.0)
            # TODO sonar/vision altitude
            poseHistory.append(
                (drone.time, (drone.coord[0], drone.coord[1], drone.heading),
                 (drone.angleFB, drone.angleLR), None))
        magnetoOnStart = drone.magneto[:3]
        print "NAVI-ON"
        startTime = drone.time
        sx, sy, sz, sa = 0, 0, 0, 0
        lastUpdate = None
        while drone.time < startTime + 600.0:

            altitude = desiredHeight
            if drone.altitudeData != None:
                altVision = drone.altitudeData[0] / 1000.0
                altSonar = drone.altitudeData[3] / 1000.0
                altitude = (altSonar + altVision) / 2.0
                # TODO selection based on history? panic when min/max too far??
                if abs(altSonar - altVision) > 0.5:
                    print altSonar, altVision
                    altitude = max(
                        altSonar,
                        altVision)  # sonar is 0.0 sometimes (no ECHO)

            sz = max(-0.2, min(0.2, desiredHeight - altitude))
            if altitude > 2.5:
                # wind and "out of control"
                sz = max(-0.5, min(0.5, desiredHeight - altitude))

            sx = max(0, min(drone.speed, desiredSpeed - drone.vx))

            if drone.lastImageResult:
                lastUpdate = drone.time
                assert len(drone.lastImageResult) == 2 and len(
                    drone.lastImageResult[0]) == 2, drone.lastImageResult
                (frameNumber, timestamp), rects = drone.lastImageResult
                viewlog.dumpVideoFrame(frameNumber, timestamp)

                # keep history small
                videoTime = correctTimePeriod(timestamp / 1000.,
                                              ref=drone.time)
                videoDelay = drone.time - videoTime
                if videoDelay > 1.0:
                    print "!DANGER! - video delay", videoDelay
                maxVideoDelay = max(videoDelay, maxVideoDelay)
                toDel = 0
                for oldTime, oldPose, oldAngles, oldAltitude in poseHistory:
                    toDel += 1
                    if oldTime >= videoTime:
                        break
                poseHistory = poseHistory[:toDel]

                tiltCompensation = Pose(desiredHeight * oldAngles[0],
                                        desiredHeight * oldAngles[1],
                                        0)  # TODO real height?
                print "FRAME", frameNumber / 15, "[%.1f %.1f]" % (math.degrees(
                    oldAngles[0]), math.degrees(oldAngles[1])),
                #        print "angle", math.degrees(drone.angleFB-oldAngles[0]), math.degrees(drone.angleLR-oldAngles[1])
                if rects != None and len(rects) > 0:
                    # note, that "rects" could be None, when video processing is OFF (g_processingEnabled==False)
                    if oldAltitude == None:
                        oldAltitude = altitude
                    debugImg = None
                    if drone.replayLog != None:
                        debugFilename = "tmp_%04d.jpg" % (frameNumber /
                                                          FRAMES_PER_INDEX)
                        debugImg = cv2.imread(debugFilename)
                    line = chooseBestWidth(rects,
                                           coord=oldPose[:2],
                                           height=oldAltitude,
                                           heading=oldPose[2],
                                           angleFB=oldAngles[0],
                                           angleLR=oldAngles[1],
                                           debugImg=debugImg)
                    if line:
                        rejected = False
                        if refLine != None:
                            print "%.1fdeg %.2fm" % (math.degrees(
                                normalizeAnglePIPI(refLine.angle - line.angle)
                            ), refLine.signedDistance(line.start))
                            if abs(normalizeAnglePIPI(refLine.angle - line.angle)) < MAX_REF_LINE_ANGLE and \
                                abs(refLine.signedDistance( line.start )) < MAX_REF_LINE_DIST:
                                refLine = line
                            else:
                                rejected = True
                        else:
                            refLine = line
                        viewlog.dumpBeacon(line.start, index=3)
                        viewlog.dumpBeacon(line.end, index=3)
                        if drone.replayLog != None:
                            if rejected:
                                # redraw image with yellow color
                                chooseBestWidth(rects,
                                                coord=oldPose[:2],
                                                height=oldAltitude,
                                                heading=oldPose[2],
                                                angleFB=oldAngles[0],
                                                angleLR=oldAngles[1],
                                                debugImg=debugImg,
                                                color=(0, 255, 255))
                            cv2.imwrite(debugFilename, debugImg)
                else:
                    print rects

                desiredSpeed = MAX_ALLOWED_SPEED
                if videoDelay > MAX_ALLOWED_VIDEO_DELAY:
                    desiredSpeed = 0.0

                if drone.battery < 10:
                    print "BATTERY LOW!", drone.battery

                # height debugging
                #print "HEIGHT\t%d\t%d\t%.2f\t%d\t%d\t%d\t%d\t%d\t%d" % tuple([max([0]+[w for ((x,y),(w,h),a) in rects])] + list(drone.altitudeData[:4]) + list(drone.pressure) )

            # error definition ... if you substract that you get desired position or angle
            # error is taken from the path point of view, x-path direction, y-positive left, angle-anticlockwise
            errY, errA = 0.0, 0.0
            if refLine:
                errY = refLine.signedDistance(drone.coord)
                errA = normalizeAnglePIPI(drone.heading - refLine.angle)

            # get the height first
            if drone.coord[
                    2] < desiredHeight - 0.1 and drone.time - startTime < 5.0:
                sx = 0.0
            # error correction
            # the goal is to have errY and errA zero in 1 second -> errY defines desired speed at given distance from path
            sy = max(-0.2, min(0.2, -errY - drone.vy)) / 2.0

            # there is no drone.va (i.e. derivative of heading) available at the moment ...
            sa = max(-0.1, min(0.1, -errA / 2.0)) * 1.35 * (
                desiredSpeed / 0.4)  # originally set for 0.4=OK

            #      print "%0.2f\t%d\t%0.2f\t%0.2f\t%0.2f" % (errY, int(math.degrees(errA)), drone.vy, sy, sa)
            prevTime = drone.time
            drone.moveXYZA(sx, sy, sz, sa)
            maxControlGap = max(drone.time - prevTime, maxControlGap)
            poseHistory.append(
                (drone.time, (drone.coord[0], drone.coord[1], drone.heading),
                 (drone.angleFB, drone.angleLR), altitude))
        print "NAVI-OFF", drone.time - startTime
        drone.hover(0.5)
        drone.land()
        drone.setVideoChannel(front=True)
    except ManualControlException, e:
        print "ManualControlException"
        if drone.ctrlState == 3:  # CTRL_FLYING=3 ... i.e. stop the current motion
            drone.hover(0.1)
        drone.land()
Пример #16
0
def competeAirRace(drone, desiredHeight=1.7):
    loops = []
    drone.speed = 0.1
    maxVideoDelay = 0.0
    maxControlGap = 0.0
    loc = StripsLocalisation()

    remainingFastStrips = 0
    desiredSpeed = TRANSITION_SPEED
    updateFailedCount = 0

    try:
        drone.wait(1.0)
        drone.setVideoChannel(front=False)
        drone.takeoff()
        poseHistory = []
        startTime = drone.time
        while drone.time < startTime + 1.0:
            drone.update("AT*PCMD=%i,0,0,0,0,0\r")  # drone.hover(1.0)
            poseHistory.append(
                (drone.time, (drone.coord[0], drone.coord[1], drone.heading),
                 (drone.angleFB, drone.angleLR)))
        magnetoOnStart = drone.magneto[:3]
        print "NAVI-ON"
        pathType = PATH_TURN_LEFT
        virtualRefCircle = None
        startTime = drone.time
        sx, sy, sz, sa = 0, 0, 0, 0
        lastUpdate = None
        while drone.time < startTime + 600.0:
            sz = max(-0.2, min(0.2, desiredHeight - drone.coord[2]))
            sx = max(0, min(drone.speed, desiredSpeed - drone.vx))

            if drone.lastImageResult:
                lastUpdate = drone.time
                assert len(drone.lastImageResult) == 2 and len(
                    drone.lastImageResult[0]) == 2, drone.lastImageResult
                (frameNumber, timestamp), rects = drone.lastImageResult
                viewlog.dumpCamera("tmp_%04d.jpg" % (frameNumber / 15, ), 0)

                # keep history small
                videoTime = correctTimePeriod(timestamp / 1000.,
                                              ref=drone.time)
                videoDelay = drone.time - videoTime
                if videoDelay > 1.0:
                    print "!DANGER! - video delay", videoDelay
                maxVideoDelay = max(videoDelay, maxVideoDelay)
                toDel = 0
                for oldTime, oldPose, oldAngles in poseHistory:
                    toDel += 1
                    if oldTime >= videoTime:
                        break
                poseHistory = poseHistory[:toDel]

                tiltCompensation = Pose(desiredHeight * oldAngles[0],
                                        desiredHeight * oldAngles[1],
                                        0)  # TODO real height?
                print "FRAME", frameNumber / 15, "[%.1f %.1f]" % (math.degrees(
                    oldAngles[0]), math.degrees(oldAngles[1])),
                loc.updateFrame(
                    Pose(*oldPose).add(tiltCompensation),
                    allStripPoses(rects,
                                  highResolution=drone.videoHighResolution))
                if loc.pathType != pathType:
                    print "TRANS", pathType, "->", loc.pathType
                    if pathType == PATH_TURN_LEFT and loc.pathType == PATH_STRAIGHT:
                        if len(loops) > 0:
                            print "Loop %d, time %d" % (len(loops),
                                                        drone.time - loops[-1])
                        print "-----------------------------------------------"
                        loops.append(drone.time)
                    if drone.magneto[:3] == magnetoOnStart:
                        print "!!!!!!!! COMPASS FAILURE !!!!!!!!"
                    pathType = loc.pathType
                    print "----"
                    remainingFastStrips = NUM_FAST_STRIPS

                if loc.crossing:
                    print "X", True, remainingFastStrips
                else:
                    print pathType, loc.pathUpdated, remainingFastStrips
                if not loc.pathUpdated:
                    updateFailedCount += 1
                    if updateFailedCount > 1:
                        print "UPDATE FAILED", updateFailedCount
                else:
                    updateFailedCount = 0

                if remainingFastStrips > 0:
                    remainingFastStrips -= 1
                    desiredSpeed = MAX_ALLOWED_SPEED
                    if not loc.pathUpdated and not loc.crossing:
                        desiredSpeed = STRIPS_FAILURE_SPEED
                else:
                    desiredSpeed = TRANSITION_SPEED
                if videoDelay > MAX_ALLOWED_VIDEO_DELAY:
                    desiredSpeed = 0.0

                if drone.battery < 10:
                    print "BATTERY LOW!", drone.battery

                # height debugging
                #print "HEIGHT\t%d\t%d\t%.2f\t%d\t%d\t%d\t%d\t%d\t%d" % tuple([max([0]+[w for ((x,y),(w,h),a) in rects])] + list(drone.altitudeData[:4]) + list(drone.pressure) )

                for sp in allStripPoses(
                        rects, highResolution=drone.videoHighResolution):
                    sPose = Pose(*oldPose).add(tiltCompensation).add(sp)
                    viewlog.dumpBeacon(sPose.coord(), index=3)
                    viewlog.dumpObstacles([[
                        (sPose.x - 0.15 * math.cos(sPose.heading),
                         sPose.y - 0.15 * math.sin(sPose.heading)),
                        (sPose.x + 0.15 * math.cos(sPose.heading),
                         sPose.y + 0.15 * math.sin(sPose.heading))
                    ]])

            refCircle, refLine = loc.getRefCircleLine(
                Pose(drone.coord[0], drone.coord[1], drone.heading))
            if refCircle == None and refLine == None and virtualRefCircle != None:
                refCircle = virtualRefCircle
            # error definition ... if you substract that you get desired position or angle
            # error is taken from the path point of view, x-path direction, y-positive left, angle-anticlockwise
            errY, errA = 0.0, 0.0
            assert refCircle == None or refLine == None  # they cannot be both active at the same time
            if refCircle:
                if pathType == PATH_TURN_LEFT:
                    errY = refCircle[1] - math.hypot(
                        drone.coord[0] - refCircle[0][0],
                        drone.coord[1] - refCircle[0][1])
                    errA = normalizeAnglePIPI(
                        -math.atan2(refCircle[0][1] - drone.coord[1],
                                    refCircle[0][0] - drone.coord[0]) -
                        math.radians(-90) + drone.heading)
                if pathType == PATH_TURN_RIGHT:
                    errY = math.hypot(
                        drone.coord[0] - refCircle[0][0],
                        drone.coord[1] - refCircle[0][1]) - refCircle[1]
                    errA = normalizeAnglePIPI(
                        -math.atan2(refCircle[0][1] - drone.coord[1],
                                    refCircle[0][0] - drone.coord[0]) -
                        math.radians(90) + drone.heading)
            if refLine:
                errY = refLine.signedDistance(drone.coord)
                errA = normalizeAnglePIPI(drone.heading - refLine.angle)

            # get the height first
            if drone.coord[
                    2] < desiredHeight - 0.1 and drone.time - startTime < 5.0:
                sx = 0.0
            if refCircle == None and refLine == None and virtualRefCircle == None:
                sx = 0.0  # wait for Z-up
                if drone.coord[2] > desiredHeight - 0.1:
                    print "USING VIRTUAL LEFT TURN CIRCLE!"
                    circCenter = Pose(drone.coord[0], drone.coord[1],
                                      drone.heading).add(
                                          Pose(0.0, REF_CIRCLE_RADIUS,
                                               0)).coord()
                    viewlog.dumpBeacon(circCenter, index=0)
                    virtualRefCircle = circCenter, REF_CIRCLE_RADIUS

            # error correction
            # the goal is to have errY and errA zero in 1 second -> errY defines desired speed at given distance from path
            sy = max(-0.2, min(0.2, -errY - drone.vy)) / 2.0

            # there is no drone.va (i.e. derivative of heading) available at the moment ...
            sa = max(-0.1, min(0.1, -errA / 2.0)) * 1.35 * (
                desiredSpeed / 0.4)  # originally set for 0.4=OK

            #      print "%0.2f\t%d\t%0.2f\t%0.2f\t%0.2f" % (errY, int(math.degrees(errA)), drone.vy, sy, sa)
            prevTime = drone.time
            drone.moveXYZA(sx, sy, sz, sa)
            maxControlGap = max(drone.time - prevTime, maxControlGap)
            poseHistory.append(
                (drone.time, (drone.coord[0], drone.coord[1], drone.heading),
                 (drone.angleFB, drone.angleLR)))
        print "NAVI-OFF", drone.time - startTime
        drone.hover(0.5)
        drone.land()
        drone.setVideoChannel(front=True)
    except ManualControlException, e:
        print "ManualControlException"
        if drone.ctrlState == 3:  # CTRL_FLYING=3 ... i.e. stop the current motion
            drone.hover(0.1)
        drone.land()
Пример #17
0
    def updateExtension(self, robot, id, data):
        if id == 'remission' and len(data) > 0:
            pass  # ignored for FRE 2014

        if id == 'laser' and len(data) > 0:
            self.poseHistory.append(robot.localisation.pose()[:2])
            if len(self.poseHistory) > 20:
                self.poseHistory = self.poseHistory[-20:]
            step = 10
            data2 = [x == 0 and 10000 or x for x in data]
            arr = [
                min(i) / 1000.0 for i in [
                    itertools.islice(data2, start, start + step)
                    for start in range(0, len(data2), step)
                ]
            ]
            arr.reverse()
            robot.preprocessedLaser = arr

            limit = self.radius
            danger = False
            prevCenter = self.center
            if self.center != None:
                #        if center > 0 and center < len(arr)-1 and arr[center] < limit and arr[center-1] < limit and arr[center+1] < limit:
                if self.center > 0 and self.center < len(arr) - 1 and arr[
                        self.center] < limit:
                    print "!!!DANGER!!! PATH BLOCKED!!!", self.center
                    danger = True
            if self.center == None or danger:
                # offset is not set - find nearest
                if self.center == None:
                    self.center = len(arr) / 2
                if arr[self.center] < limit:
                    i = 0
                    while i < self.center:
                        if arr[self.center - i] >= limit:
                            break
                        i += 1
                    left = i
                    i = 0
                    while i + self.center < len(arr):
                        if arr[self.center + i] >= limit:
                            break
                        i += 1
                    right = i
                    print "HACK", left, right
                    if left < right:
                        self.center += -left
                    else:
                        self.center += right

            i = 0
            if self.center < 0 or self.center >= len(arr):
                self.center = prevCenter
            if self.center == None:
                self.center = len(arr) / 2
            while i <= self.center:
                if arr[self.center - i] < limit:
                    break
                i += 1
            left = i  # arr is already reversed
            i = 0
            while i + self.center < len(arr):
                if arr[self.center + i] < limit:
                    break
                i += 1
            right = i

            p = robot.localisation.pose()
            if self.center - left >= 0:
                self.lastLeft = combinedPose(
                    (p[0], p[1], p[2] + math.radians(135 - 5 *
                                                     (self.center - left))),
                    (arr[self.center - left], 0, 0))
#        viewlog.dumpBeacon(self.lastLeft[:2], color=(0,128,0))
            if self.center + right < len(arr):
                self.lastRight = combinedPose(
                    (p[0], p[1], p[2] + math.radians(135 - 5 *
                                                     (self.center + right))),
                    (arr[self.center + right], 0, 0))
#        viewlog.dumpBeacon(self.lastRight[:2], color=(0,128,50))

            if self.verbose:
                if danger and left + right < MIN_GAP_SIZE:
                    print "MIN GAP SIZE danger:", left + right
                s = ''
                for i in arr:
                    s += (i < 0.5 and 'X'
                          or (i < 1.0 and 'x' or (i < 1.5 and '.' or ' ')))
                s = "".join(
                    list(s)[:self.center] + ['C'] + list(s)[self.center:])
                print "'" + s + "'"
#        print "LRLR\t%d\t%d\t%d" % (left, right, left+right)
#        if self.prevLR :
#          print "LRDIFF", left-self.prevLR[0], right-self.prevLR[1]

            self.line = None  # can be defined inside
            if left + right <= MAX_GAP_SIZE:  # TODO limit based on minSize, radius and sample angle
                self.center += (right - left) / 2
                offset = self.center - len(arr) / 2
                self.directionAngle = math.radians(-offset * step / 2.0)
                self.collisionAhead = min(arr[54 / 3:2 * 54 / 3]), min(
                    arr[4 * 54 / 9:5 * 54 / 9]), (left + right < MIN_GAP_SIZE)
                if False:  #self.verbose:
                    if self.collisionAhead[0] < 0.25:
                        print "!!! COLISSION AHEAD !!!", self.collisionAhead
                    else:
                        print "free space", self.collisionAhead
            elif left < 3 or right < 3:
                # wide row & collision ahead
                if self.verbose:
                    print "NEAR", left, right, left + right
                offset = self.center - len(arr) / 2
                if left < right:
                    offset += 3
                else:
                    offset -= 3
                self.directionAngle = math.radians(-offset * step / 2.0)
            else:
                if self.verbose:
                    print "OFF", left, right  #, left+right, robot.compass
                if False:  # hacked, ignoring compass   self.rowHeading:
                    self.directionAngle = normalizeAnglePIPI(
                        self.rowHeading - robot.localisation.pose()[2])
                    if abs(self.directionAngle) > math.radians(90):
                        self.directionAngle = normalizeAnglePIPI(
                            self.rowHeading - robot.localisation.pose()[2] +
                            math.radians(180))
                    if self.verbose:
                        print "DIFF %.1f" % math.degrees(self.directionAngle)
                else:
                    if self.verbose:
                        print "PATH GAP"
                    A, B = self.poseHistory[0][:2], self.poseHistory[-1][:2]
                    viewlog.dumpBeacon(A, color=(0, 0, 180))
                    viewlog.dumpBeacon(B, color=(0, 30, 255))
                    self.line = Line(
                        B, (2 * B[0] - A[0], 2 * B[1] - A[1]))  # B+(B-A)
                    if self.line and self.line.length < 0.5:
                        self.line = None
                    else:
                        self.center = len(arr) / 2
                        # reset center
                    """if self.prevLR:
            if abs(left-self.prevLR[0]) > 4 and abs(right-self.prevLR[1]) < 3:
              left = self.prevLR[0]
              self.center += (right-left)/2
              offset = self.center-len(arr)/2
              self.directionAngle = math.radians( -offset*step/2.0 )
            elif abs(right-self.prevLR[1]) > 4 and abs(left-self.prevLR[0]) < 3:
              right = self.prevLR[1]
              self.center += (right-left)/2
              offset = self.center-len(arr)/2
              self.directionAngle = math.radians( -offset*step/2.0 )
            else:
              self.directionAngle = 0.0 # if you do not know, go ahead
          else:
            self.directionAngle = 0.0 # if you do not know, go ahead"""
                    self.directionAngle = 0.0  # default

                if left >= 17 and right >= 17 or left + right >= 40:
                    self.endOfRow = True
                    if self.verbose and robot.insideField:
                        print "laser: END OF ROW"
            self.prevLR = left, right

            pose = robot.localisation.pose()
            goal = combinedPose(
                (pose[0], pose[1], pose[2] + self.directionAngle),
                (self.radius, 0, 0))
            if self.line == None:
                self.line = Line(pose, goal)
            self.newData = True
            self.cornLeft = min(arr[5:9])
            self.cornRight = min(arr[40:44])
Пример #18
0
    def crossRows2(self, row, num, rowsOnLeft):
        IGNORE_NEIGHBORS = 2
        ROWS_OFFSET = 0.7  #0.5

        #    if row.lastLeft:
        #      viewlog.dumpBeacon(row.lastLeft[:2], color=(0,128,0))
        #    if row.lastRight:
        #      viewlog.dumpBeacon(row.lastRight[:2], color=(0,128,50))
        start = self.robot.localisation.pose()[:2]
        viewlog.dumpBeacon(start, color=(255, 128, 0))

        goal = combinedPose(self.robot.localisation.pose(), (1.0, 0, 0))
        line = Line(self.robot.localisation.pose(), goal)
        lastA, lastB = None, None
        ends = []
        while True:
            for cmd in self.driver.followLineG(line):
                self.robot.setSpeedPxPa(*cmd)
                self.robot.update()
                if row.newData:
                    row.newData = False
                    break
            else:
                print "END OF LINE REACHED!"

            if self.robot.preprocessedLaser != None:
                tmp = self.robot.preprocessedLaser[:]
                tlen = len(tmp)
                if rowsOnLeft:
                    tmp = tmp[:tlen / 2] + [3.0] * (tlen - tlen / 2)
                else:
                    tmp = [3.0] * (tlen - tlen / 2) + tmp[tlen / 2:]
                sarr = sorted([(x, i) for (i, x) in enumerate(tmp)])[:5]
                ax, ai = sarr[0]
                for bx, bi in sarr[1:]:
                    if abs(ai - bi) > IGNORE_NEIGHBORS:
                        break
                else:
                    print "NO 2nd suitable minimum"
                print(ax, ai), (bx, bi)
                if rowsOnLeft:
                    offset = -ROWS_OFFSET
                    if ai > bi:
                        (ax, ai), (bx, bi) = (bx, bi), (ax, ai)
                else:
                    offset = ROWS_OFFSET
                    if ai < bi:  # rows on right
                        (ax, ai), (bx, bi) = (bx, bi), (ax, ai)
                p = self.robot.localisation.pose()
                A = combinedPose(
                    (p[0], p[1], p[2] + math.radians(135 - 5 * ai)),
                    (ax, 0, 0))
                B = combinedPose(
                    (p[0], p[1], p[2] + math.radians(135 - 5 * bi)),
                    (bx, 0, 0))
                if lastA == None:
                    ends.extend([A, B])
                    lastA, lastB = A, B
                if self.verbose:
                    print "DIST", distance(lastA,
                                           A), distance(lastB,
                                                        B), distance(lastB, A)
                if distance(lastB, A) < 0.2:
                    dist = distance(start, self.robot.localisation.pose())
                    print "NEXT ROW", dist
                    if dist > 0.4:
                        ends.append(B)  # new one
                    lastA, lastB = A, B
                line = Line(A, B)  # going through the ends of rows
                A2 = combinedPose((A[0], A[1], line.angle), (0, offset, 0))
                B2 = combinedPose((B[0], B[1], line.angle), (2.0, offset, 0))
                line = Line(A2, B2)
                viewlog.dumpBeacon(A[:2], color=(200, 0, 0))
                viewlog.dumpBeacon(B[:2], color=(200, 128, 0))
                viewlog.dumpBeacon(A2[:2], color=(255, 0, 0))
                viewlog.dumpBeacon(B2[:2], color=(255, 128, 0))
                if len(ends) > num + 1:
                    break
            else:
                print "BACKUP solution!!!"
                goal = combinedPose(self.robot.localisation.pose(),
                                    (1.0, 0, 0))
                line = Line(self.robot.localisation.pose(), goal)
Пример #19
0
def competeAirRace( drone, desiredHeight = 1.7 ):
  loops = []
  drone.speed = 0.1
  maxVideoDelay = 0.0
  maxControlGap = 0.0
  loc = StripsLocalisation()
  
  remainingFastStrips = 0
  desiredSpeed = TRANSITION_SPEED
  updateFailedCount = 0

  try:
    drone.wait(1.0)
    drone.setVideoChannel( front=False )    
    drone.takeoff()
    poseHistory = []
    startTime = drone.time
    while drone.time < startTime + 1.0:
      drone.update("AT*PCMD=%i,0,0,0,0,0\r") # drone.hover(1.0)
      poseHistory.append( (drone.time, (drone.coord[0], drone.coord[1], drone.heading), (drone.angleFB, drone.angleLR)) )
    magnetoOnStart = drone.magneto[:3]
    print "NAVI-ON"
    pathType = PATH_TURN_LEFT
    virtualRefCircle = None
    startTime = drone.time
    sx,sy,sz,sa = 0,0,0,0
    lastUpdate = None
    while drone.time < startTime + 600.0:
      sz = max( -0.2, min( 0.2, desiredHeight - drone.coord[2] ))
      sx = max( 0, min( drone.speed, desiredSpeed - drone.vx ))

      if drone.lastImageResult:
        lastUpdate = drone.time
        assert len( drone.lastImageResult ) == 2 and len( drone.lastImageResult[0] ) == 2, drone.lastImageResult
        (frameNumber, timestamp), rects = drone.lastImageResult
        viewlog.dumpCamera( "tmp_%04d.jpg" % (frameNumber/15,), 0 )

        # keep history small
        videoTime = correctTimePeriod( timestamp/1000., ref=drone.time )
        videoDelay = drone.time - videoTime
        if videoDelay > 1.0:
          print "!DANGER! - video delay", videoDelay
        maxVideoDelay = max( videoDelay, maxVideoDelay )
        toDel = 0
        for oldTime, oldPose, oldAngles in poseHistory:
          toDel += 1
          if oldTime >= videoTime:
            break
        poseHistory = poseHistory[:toDel]

        tiltCompensation = Pose(desiredHeight*oldAngles[0], desiredHeight*oldAngles[1], 0) # TODO real height?
        print "FRAME", frameNumber/15, "[%.1f %.1f]" % (math.degrees(oldAngles[0]), math.degrees(oldAngles[1])),
        loc.updateFrame( Pose( *oldPose ).add(tiltCompensation), allStripPoses( rects, highResolution=drone.videoHighResolution ) )
        if loc.pathType != pathType:
          print "TRANS", pathType, "->", loc.pathType
          if pathType == PATH_TURN_LEFT and loc.pathType == PATH_STRAIGHT:
            if len(loops) > 0:
              print "Loop %d, time %d" % (len(loops), drone.time-loops[-1])
            print "-----------------------------------------------"
            loops.append( drone.time )
          if drone.magneto[:3] == magnetoOnStart:
            print "!!!!!!!! COMPASS FAILURE !!!!!!!!"
          pathType = loc.pathType
          print "----"
          remainingFastStrips = NUM_FAST_STRIPS

        if loc.crossing:
          print "X", True, remainingFastStrips
        else:
          print pathType, loc.pathUpdated, remainingFastStrips
        if not loc.pathUpdated:
          updateFailedCount += 1
          if updateFailedCount > 1:
            print "UPDATE FAILED", updateFailedCount
        else:
          updateFailedCount = 0

        if remainingFastStrips > 0:
          remainingFastStrips -= 1
          desiredSpeed = MAX_ALLOWED_SPEED
          if not loc.pathUpdated and not loc.crossing:
            desiredSpeed = STRIPS_FAILURE_SPEED
        else:
          desiredSpeed = TRANSITION_SPEED
        if videoDelay > MAX_ALLOWED_VIDEO_DELAY:
          desiredSpeed = 0.0

        if drone.battery < 10:
          print "BATTERY LOW!", drone.battery

        # height debugging
        #print "HEIGHT\t%d\t%d\t%.2f\t%d\t%d\t%d\t%d\t%d\t%d" % tuple([max([0]+[w for ((x,y),(w,h),a) in rects])] + list(drone.altitudeData[:4]) + list(drone.pressure) )

        for sp in allStripPoses( rects, highResolution=drone.videoHighResolution ):
          sPose = Pose( *oldPose ).add(tiltCompensation).add( sp )
          viewlog.dumpBeacon( sPose.coord(), index=3 )
          viewlog.dumpObstacles( [[(sPose.x-0.15*math.cos(sPose.heading), sPose.y-0.15*math.sin(sPose.heading)), 
                                       (sPose.x+0.15*math.cos(sPose.heading), sPose.y+0.15*math.sin(sPose.heading))]] )

      refCircle,refLine = loc.getRefCircleLine( Pose(drone.coord[0], drone.coord[1], drone.heading) )
      if refCircle == None and refLine == None and virtualRefCircle != None:
        refCircle = virtualRefCircle
      # error definition ... if you substract that you get desired position or angle
      # error is taken from the path point of view, x-path direction, y-positive left, angle-anticlockwise
      errY, errA = 0.0, 0.0
      assert refCircle == None or refLine == None # they cannot be both active at the same time
      if refCircle:
        if pathType == PATH_TURN_LEFT:
          errY = refCircle[1] - math.hypot( drone.coord[0]-refCircle[0][0], drone.coord[1]-refCircle[0][1] )
          errA = normalizeAnglePIPI( - math.atan2( refCircle[0][1] - drone.coord[1], refCircle[0][0] - drone.coord[0] ) 
                                      - math.radians(-90) + drone.heading )
        if pathType == PATH_TURN_RIGHT:
          errY = math.hypot( drone.coord[0]-refCircle[0][0], drone.coord[1]-refCircle[0][1] ) - refCircle[1]
          errA = normalizeAnglePIPI( - math.atan2( refCircle[0][1] - drone.coord[1], refCircle[0][0] - drone.coord[0] ) 
                                      - math.radians(90) + drone.heading )
      if refLine:
        errY = refLine.signedDistance( drone.coord )
        errA = normalizeAnglePIPI( drone.heading - refLine.angle )

      # get the height first
      if drone.coord[2] < desiredHeight - 0.1 and drone.time-startTime < 5.0:
        sx = 0.0
      if refCircle == None and refLine == None and virtualRefCircle == None:
        sx = 0.0 # wait for Z-up
        if drone.coord[2] > desiredHeight - 0.1:
          print "USING VIRTUAL LEFT TURN CIRCLE!"
          circCenter = Pose( drone.coord[0], drone.coord[1], drone.heading ).add( Pose(0.0, REF_CIRCLE_RADIUS, 0 )).coord()
          viewlog.dumpBeacon( circCenter, index=0 )
          virtualRefCircle = circCenter, REF_CIRCLE_RADIUS

      # error correction
      # the goal is to have errY and errA zero in 1 second -> errY defines desired speed at given distance from path
      sy = max( -0.2, min( 0.2, -errY-drone.vy ))/2.0
      
      # there is no drone.va (i.e. derivative of heading) available at the moment ... 
      sa = max( -0.1, min( 0.1, -errA/2.0 ))*1.35*(desiredSpeed/0.4) # originally set for 0.4=OK

#      print "%0.2f\t%d\t%0.2f\t%0.2f\t%0.2f" % (errY, int(math.degrees(errA)), drone.vy, sy, sa)
      prevTime = drone.time
      drone.moveXYZA( sx, sy, sz, sa )
      maxControlGap = max( drone.time - prevTime, maxControlGap )
      poseHistory.append( (drone.time, (drone.coord[0], drone.coord[1], drone.heading), (drone.angleFB, drone.angleLR)) )
    print "NAVI-OFF", drone.time - startTime
    drone.hover(0.5)
    drone.land()
    drone.setVideoChannel( front=True )    
  except ManualControlException, e:
    print "ManualControlException"
    if drone.ctrlState == 3: # CTRL_FLYING=3 ... i.e. stop the current motion
      drone.hover(0.1)
    drone.land()