Example #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)
Example #2
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()
Example #3
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()