Esempio n. 1
0
def hoverAboveRoundel( drone, timeout=6000.0 ):
    startTime = drone.time
    maxSpeed = 0.1
    maxSpeedUpDown = 0.3
    frac = 0.1
    scaleX, scaleY = 0.38, 0.38 # camera FOW at 1m above the ground
    detectedCount = 0
    goal = (0.0, 0.0) #None
    goalHeading = None
    while drone.time - startTime < timeout:
        sx, sy, sz, sa = 0.0, 0.0, 0.0, 0.0
        if drone.visionTag:
            # xc[i], yc[i]: X and Y coordinates of detected tag or oriented roundel #i inside the picture,
            # with (0; 0) being the top-left corner, and (1000; 1000) the right-bottom corner regardless
            # the picture resolution or the source camera
            x, y = drone.visionTag[0][:2]
            dist = drone.visionTag[0][4]/100.
            angle = math.radians(drone.visionTag[0][5] - 270) # we use circle for the body and line for the tail -> 270deg offset
            detectedCount = min(100, detectedCount + 1)
            # TODO verify signs and scale
            dx = dist*(scaleY*(500-y)/500.0 + drone.angleFB)
            dy = dist*(scaleX*(500-x)/500.0) # - drone.angleLR)
            c = math.cos(drone.heading)
            s = math.sin(drone.heading)
            goal = (drone.coord[0] + c*dx - s*dy, 
                    drone.coord[1] + s*dx + c*dy )
            goalHeading = normalizeAnglePIPI( drone.heading + angle ) # TODO check sign
#            print drone.visionTag, "%.2f %.2f %.1f %.1f" % (dx, dy, math.degrees(drone.angleFB), math.degrees(drone.angleLR))
        else:
            detectedCount = max(0, detectedCount - 1)

        if goal:
            sx,sy,sz,sa = getXYZAGoalCmd( drone, goal, goalHeading=goalHeading )

        sz = 0.0
        if drone.altitudeData != None:
            altVision = drone.altitudeData[0]/1000.0
            altSonar = drone.altitudeData[3]/1000.0
            if drone.altitudeData[3] == 0:
                # no sonar echo
                minAlt = altVision
            else:
                minAlt = min(altSonar, altVision)

            if minAlt > MAX_ALTITUDE:
                # too high to reliably detect anything
                sz = -maxSpeedUpDown

#            print altSonar, altVision,
            if detectedCount == 0:
                # try to move up
                if max(altSonar, altVision) < 2.0:
                    sz = maxSpeedUpDown
            elif detectedCount == 100:
                if minAlt > 1.0:
                    sz = -maxSpeedUpDown
#        print "\t%.2f %.2f %.2f %.2f" % (sx, sy, sz, sa)
        drone.moveXYZA( sx, sy, sz, sa )
    drone.hover(0.1) # stop motion
Esempio n. 2
0
 def diff2pathType( self, dx, dy, da ):
   da = normalizeAnglePIPI(da)
   if (0.25 < dx < 0.48) and abs(da) < math.radians(50) and (abs(dy) < 0.25):
     if abs(da) < math.radians(10):
       return PATH_STRAIGHT
     elif da > 0:
       return PATH_TURN_LEFT
     else:
       return PATH_TURN_RIGHT
   return None
Esempio n. 3
0
def getXYZAGoalCmd( drone, goal, goalHeading=None, maxSpeed=0.3 ):
    frac = 0.3
    dxWorld = goal[0] - drone.coord[0]
    dyWorld = goal[1] - drone.coord[1]
    c = math.cos(drone.heading)
    s = math.sin(drone.heading)
    dx = c*dxWorld + s*dyWorld   # inverse rotation
    dy = -s*dxWorld + c*dyWorld
    sx = max( -maxSpeed, min( maxSpeed, frac*(dx - drone.vx) ))
    sy = max( -maxSpeed, min( maxSpeed, frac*(dy - drone.vy) ))
    sa = 0.0
    if goalHeading:
        sa = max( -maxSpeed, min( maxSpeed, frac*(normalizeAnglePIPI(goalHeading - drone.heading)) ))
    return sx, sy, 0.0, sa
Esempio n. 4
0
def getXYZAGoalCmd(drone, goal, goalHeading=None, maxSpeed=0.3):
    frac = 0.3
    dxWorld = goal[0] - drone.coord[0]
    dyWorld = goal[1] - drone.coord[1]
    c = math.cos(drone.heading)
    s = math.sin(drone.heading)
    dx = c * dxWorld + s * dyWorld  # inverse rotation
    dy = -s * dxWorld + c * dyWorld
    sx = max(-maxSpeed, min(maxSpeed, frac * (dx - drone.vx)))
    sy = max(-maxSpeed, min(maxSpeed, frac * (dy - drone.vy)))
    sa = 0.0
    if goalHeading:
        sa = max(
            -maxSpeed,
            min(maxSpeed,
                frac * (normalizeAnglePIPI(goalHeading - drone.heading))))
    return sx, sy, 0.0, sa
Esempio n. 5
0
  def updateFrame( self, pose, frameStrips, verbose=False ):
    if verbose:
      print pose, [str(p) for p in frameStrips]
    self.pathUpdated = False
    self.crossing = False
    for i in xrange(len(frameStrips)):
      for j in xrange(len(frameStrips)):
        if i != j:
          (dx,dy,da) = frameStrips[i].sub(frameStrips[j])
          pt = self.diff2pathType( dx, dy, da )
          if pt:
            sPose = pose.add( frameStrips[i] )
            if pt != PATH_STRAIGHT or self.refLine == None or \
                  abs(normalizeAnglePIPI( self.refLine.angle - sPose.heading )) < REF_LINE_CROSSING_ANGLE:
              self.pathType = pt
              self.pathPose = sPose # also j should be OK
              self.pathUpdated = True
              break
            else:
              print "SKIPPED2"
              self.crossing = True

    if (len(frameStrips) >= 1 and not self.pathUpdated) and self.lastStripPose != None:
      for fs in frameStrips:
        for lsp in self.lastStripPose:
          sPose = pose.add( fs )
          (dx,dy,da) = sPose.sub( lsp )
          pt = self.diff2pathType( dx, dy, da )
          if pt:
            if pt != PATH_STRAIGHT or self.refLine == None or \
                  abs(normalizeAnglePIPI( self.refLine.angle - sPose.heading )) < REF_LINE_CROSSING_ANGLE:
              self.pathType = pt
              self.pathPose = sPose
              self.pathUpdated = True
              break
            else:
              print "SKIPPED1"

    if not self.pathUpdated:
      if len(frameStrips) == 1 and self.lastStripPose != None:
        fs = frameStrips[0]
        sPose = pose.add( fs )
        for lsp in self.lastStripPose:
          if self.isSameStrip( sPose, lsp ):
            # the self.pathType is the same only the pose is updated
            self.pathPose = sPose
            self.pathUpdated = True
        if not self.pathUpdated:
          for lsp in self.lastStripPose:
            print sPose.sub(lsp)

    if len(frameStrips) > 0:
      self.lastStripPose = []
      for fs in frameStrips:
        sPose = pose.add( fs )
        if verbose and self.lastStripPose != None:
          print [str(sPose.sub( lsp )) for lsp in self.lastStripPose]
        self.lastStripPose.append( sPose )

    if self.pathType == PATH_TURN_LEFT:
      self.countLR = max( -NUM_TRANSITION_STEPS, self.countLR - 1 )
    if self.pathType == PATH_TURN_RIGHT:
      self.countLR = min( NUM_TRANSITION_STEPS, self.countLR + 1 )

    if self.pathPose:
      sPose = self.pathPose
      if self.pathType == PATH_TURN_LEFT:
        circCenter = sPose.add( Pose(0.0, REF_CIRCLE_RADIUS, 0 )).coord()
        self.refCircle = circCenter, REF_CIRCLE_RADIUS - MAX_CIRCLE_OFFSET*self.countLR/float(NUM_TRANSITION_STEPS)
      elif self.pathType == PATH_TURN_RIGHT:
        circCenter = sPose.add( Pose(0.0, -REF_CIRCLE_RADIUS, 0 )).coord()
        self.refCircle = circCenter, REF_CIRCLE_RADIUS + MAX_CIRCLE_OFFSET*self.countLR/float(NUM_TRANSITION_STEPS)
      else:
        self.refCircle = None
      if self.pathType == PATH_STRAIGHT:
        if self.refLine == None or abs(normalizeAnglePIPI( self.refLine.angle - sPose.heading )) < REF_LINE_CROSSING_ANGLE:
          offset = Pose()
          if self.countLR > 0:
            offset = Pose( 0, LINE_OFFSET, 0 )
          if self.countLR < 0:
            offset = Pose( 0, -LINE_OFFSET, 0 )
          sPose = sPose.add( offset )
          self.refLine = Line( (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)) )
      else:
        self.refLine = None
    return self.pathUpdated
Esempio n. 6
0
 def isSameStrip( self, pose1, pose2 ):
   dx,dy,da = pose1.sub(pose2)
   da = normalizeAnglePIPI(da)
   if abs(dx) < 0.2 and abs(dy) < 0.1 and abs(da) < math.radians(10):
     return True
   return False
Esempio n. 7
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()
Esempio n. 8
0
def hoverAboveRoundel(drone, timeout=6000.0):
    startTime = drone.time
    maxSpeed = 0.1
    maxSpeedUpDown = 0.3
    frac = 0.1
    scaleX, scaleY = 0.38, 0.38  # camera FOW at 1m above the ground
    detectedCount = 0
    goal = (0.0, 0.0)  #None
    goalHeading = None
    while drone.time - startTime < timeout:
        sx, sy, sz, sa = 0.0, 0.0, 0.0, 0.0
        if drone.visionTag:
            # xc[i], yc[i]: X and Y coordinates of detected tag or oriented roundel #i inside the picture,
            # with (0; 0) being the top-left corner, and (1000; 1000) the right-bottom corner regardless
            # the picture resolution or the source camera
            x, y = drone.visionTag[0][:2]
            dist = drone.visionTag[0][4] / 100.
            angle = math.radians(
                drone.visionTag[0][5] - 270
            )  # we use circle for the body and line for the tail -> 270deg offset
            detectedCount = min(100, detectedCount + 1)
            # TODO verify signs and scale
            dx = dist * (scaleY * (500 - y) / 500.0 + drone.angleFB)
            dy = dist * (scaleX * (500 - x) / 500.0)  # - drone.angleLR)
            c = math.cos(drone.heading)
            s = math.sin(drone.heading)
            goal = (drone.coord[0] + c * dx - s * dy,
                    drone.coord[1] + s * dx + c * dy)
            goalHeading = normalizeAnglePIPI(drone.heading +
                                             angle)  # TODO check sign
#            print drone.visionTag, "%.2f %.2f %.1f %.1f" % (dx, dy, math.degrees(drone.angleFB), math.degrees(drone.angleLR))
        else:
            detectedCount = max(0, detectedCount - 1)

        if goal:
            sx, sy, sz, sa = getXYZAGoalCmd(drone,
                                            goal,
                                            goalHeading=goalHeading)

        sz = 0.0
        if drone.altitudeData != None:
            altVision = drone.altitudeData[0] / 1000.0
            altSonar = drone.altitudeData[3] / 1000.0
            if drone.altitudeData[3] == 0:
                # no sonar echo
                minAlt = altVision
            else:
                minAlt = min(altSonar, altVision)

            if minAlt > MAX_ALTITUDE:
                # too high to reliably detect anything
                sz = -maxSpeedUpDown

#            print altSonar, altVision,
            if detectedCount == 0:
                # try to move up
                if max(altSonar, altVision) < 2.0:
                    sz = maxSpeedUpDown
            elif detectedCount == 100:
                if minAlt > 1.0:
                    sz = -maxSpeedUpDown


#        print "\t%.2f %.2f %.2f %.2f" % (sx, sy, sz, sa)
        drone.moveXYZA(sx, sy, sz, sa)
    drone.hover(0.1)  # stop motion
Esempio n. 9
0
def followRow(drone, desiredHeight=1.5, timeout=10.0):
    maxControlGap = 0.0
    maxVideoDelay = 0.0
    desiredSpeed = MAX_ALLOWED_SPEED
    startTime = drone.time
    sx, sy, sz, sa = 0, 0, 0, 0
    lastUpdate = None
    refLine = None
    while drone.time < startTime + timeout:
        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))

        if drone.lastImageResult:
            lastUpdate = drone.time
            assert len(drone.lastImageResult) == 2 and len(
                drone.lastImageResult[0]) == 2, drone.lastImageResult
            (frameNumber, timestamp), rowTopBottom = 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 in drone.poseHistory:
                toDel += 1
                if oldTime >= videoTime:
                    break
            drone.poseHistory = drone.poseHistory[:toDel]
            tiltCompensation = Pose(desiredHeight * oldAngles[0],
                                    desiredHeight * oldAngles[1],
                                    0)  # TODO real height?
            validRow = evalRowData(rowTopBottom)
            print "FRAME", frameNumber / 15, "[%.1f %.1f]" % (math.degrees(
                oldAngles[0]), math.degrees(oldAngles[1])), validRow
            if validRow:
                sp = groundPose(*rowTopBottom,
                                scale=ROW_WIDTH /
                                ((validRow[0] + validRow[1]) / 2.0))
                sPose = Pose(*oldPose).add(tiltCompensation).add(sp)
                refLine = Line((sPose.x, sPose.y),
                               (sPose.x + math.cos(sPose.heading),
                                sPose.y + math.sin(sPose.heading)))

        errY, errA = 0.0, 0.0
        if refLine:
            errY = refLine.signedDistance(drone.coord)
            errA = normalizeAnglePIPI(drone.heading - refLine.angle)

        sx = max(0, min(drone.speed, desiredSpeed - drone.vx))
        sy = max(-0.2, min(0.2, -errY - drone.vy)) / 2.0
        sa = max(-0.1, min(0.1, -errA / 2.0)) * 1.35 * (desiredSpeed / 0.4)
        prevTime = drone.time
        drone.moveXYZA(sx, sy, sz, sa)
        drone.poseHistory.append(
            (drone.time, (drone.coord[0], drone.coord[1], drone.heading),
             (drone.angleFB, drone.angleLR)))
        maxControlGap = max(drone.time - prevTime, maxControlGap)
    return maxControlGap
Esempio n. 10
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()
Esempio n. 11
0
def followRow( drone, desiredHeight = 1.5, timeout = 10.0 ): 
  maxControlGap = 0.0
  maxVideoDelay = 0.0
  desiredSpeed = MAX_ALLOWED_SPEED
  startTime = drone.time
  sx,sy,sz,sa = 0,0,0,0
  lastUpdate = None
  refLine = None
  while drone.time < startTime + timeout:
    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 ))

    if drone.lastImageResult:
      lastUpdate = drone.time
      assert len( drone.lastImageResult ) == 2 and len( drone.lastImageResult[0] ) == 2, drone.lastImageResult
      (frameNumber, timestamp), rowTopBottom = 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 in drone.poseHistory:
        toDel += 1
        if oldTime >= videoTime:
          break
      drone.poseHistory = drone.poseHistory[:toDel]
      tiltCompensation = Pose(desiredHeight*oldAngles[0], desiredHeight*oldAngles[1], 0) # TODO real height?      
      validRow = evalRowData( rowTopBottom )
      print "FRAME", frameNumber/15, "[%.1f %.1f]" % (math.degrees(oldAngles[0]), math.degrees(oldAngles[1])), validRow
      if validRow:
        sp = groundPose( *rowTopBottom, scale=ROW_WIDTH/((validRow[0]+validRow[1])/2.0))
        sPose = Pose( *oldPose ).add(tiltCompensation).add( sp )
        refLine = Line( (sPose.x,sPose.y), (sPose.x + math.cos(sPose.heading), sPose.y + math.sin(sPose.heading)) )

    errY, errA = 0.0, 0.0
    if refLine:
      errY = refLine.signedDistance( drone.coord )
      errA = normalizeAnglePIPI( drone.heading - refLine.angle )


    sx = max( 0, min( drone.speed, desiredSpeed - drone.vx ))
    sy = max( -0.2, min( 0.2, -errY-drone.vy ))/2.0
    sa = max( -0.1, min( 0.1, -errA/2.0 ))*1.35*(desiredSpeed/0.4)
    prevTime = drone.time
    drone.moveXYZA( sx, sy, sz, sa )
    drone.poseHistory.append( (drone.time, (drone.coord[0], drone.coord[1], drone.heading), (drone.angleFB, drone.angleLR)) )
    maxControlGap = max( drone.time - prevTime, maxControlGap )
  return maxControlGap
Esempio n. 12
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()
Esempio n. 13
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()