Пример #1
0
    def move(self, channels, cruiseSpeed, newroi=None, roiVel=None):
        '''Handles RC channels and a given strafeSpeed to return a position and velocity command
        location: location object, lat (deg), lon (deg), alt (meters)
        velocity: vector3 object, x, y, z (m/s) command'''

        if roiVel is None:
            roiVel = Vector3(0,0,0)

        # Approach
        approachVel = self._approach(-channels[PITCH])

        # Strafe
        strafeVel = self._strafe(channels[ROLL], cruiseSpeed)
 
        # Climb
        climbVel = self._climb(channels[THROTTLE])

        # calculate new LLA position
        if newroi is not None:
            self.roi = newroi
        currentPos = location_helpers.newLocationFromAzimuthAndDistance(self.roi, self.azimuth, self.radius)

        # set altitude (This is for generality with follow. In the Orbit shot, roi.alt should be zero.)
        currentPos.alt = self.roi.alt + self.zOffset

        # check altitude limit
        if self.maxAlt is not None:
            currentPos.alt = min(currentPos.alt, self.maxAlt)

        # sum velocities
        currentVel = approachVel + strafeVel + climbVel + roiVel

        return currentPos, currentVel
Пример #2
0
 def setUp(self):
     self.v = mock.create_autospec(Vehicle)
     self.v.location.global_relative_frame = LocationGlobalRelative(
         -48.5468695, 5.68464, 10.5)
     self.v.mount_status = [-80]
     self.mockMgr = Mock()
     self.mockMgr.buttonManager = Mock()
     self.mockMgr.getParam = Mock(return_value=500.0)
     self.controller = CableCamShot(self.v, self.mockMgr)
     loc2 = location_helpers.newLocationFromAzimuthAndDistance(
         self.v.location.global_relative_frame, 23.4, 25.0)
     self.startYaw = 12.4
     self.startPitch = -16.7
     waypt1 = cable_cam.Waypoint(loc2, self.startYaw, self.startPitch)
     self.controller.waypoints.append(waypt1)
     self.endYaw = 175.4
     self.endPitch = -83.4
     waypt2 = cable_cam.Waypoint(self.v.location.global_relative_frame,
                                 self.endYaw, self.endPitch)
     self.controller.waypoints.append(waypt2)
     self.controller.deadReckoningTicks = 0
     self.controller.accel = 0.0
     self.controller.totalDistance = location_helpers.getDistanceFromPoints3d(
         self.v.location.global_relative_frame, loc2)
     self.v.message_factory = Mock()
     # turn off dead reckoning
     self.v.groundspeed = 0.0
     self.controller.desiredSpeed = 0.0
Пример #3
0
 def __init__(self, roi, radius, azimuth, zOffset):
     super(LeashController, self).__init__(roi, radius, azimuth, zOffset)
     #initialize location
     self.currentLoc = location_helpers.newLocationFromAzimuthAndDistance(
         self.roi, self.azimuth, self.radius)
     self.currentLoc.altitude = roi.alt + zOffset
     self.distance = radius
Пример #4
0
 def testSecondLocation(self):
     """ Test that newLocationFromAzimuthAndDistance works """
     az = 84.546
     dist = 37.5464
     loc = LocationGlobalRelative(-22.65465, 4.351654, 0.0)
     newloc = location_helpers.newLocationFromAzimuthAndDistance(
         loc, az, dist)
     calcDist = location_helpers.getDistanceFromPoints3d(loc, newloc)
     self.assertTrue(abs(dist - calcDist) < ERROR)
     calcAz = location_helpers.calcAzimuthFromPoints(loc, newloc)
     self.assertTrue(abs(az - calcAz) < ERROR)
Пример #5
0
 def testFirstLocation(self):
     """ Test that newLocationFromAzimuthAndDistance works """
     az = 17.234
     dist = 45.23643
     loc = LocationGlobalRelative(-43.2346234, 15.2385, 0.0)
     newloc = location_helpers.newLocationFromAzimuthAndDistance(
         loc, az, dist)
     calcDist = location_helpers.getDistanceFromPoints3d(loc, newloc)
     self.assertTrue(abs(dist - calcDist) < ERROR)
     calcAz = location_helpers.calcAzimuthFromPoints(loc, newloc)
     self.assertTrue(abs(az - calcAz) < ERROR)
Пример #6
0
    def setupWaypoints(self):
        '''setup our two waypoints'''
        # we want two points that are far apart
        # both in the direction we're looking and the opposite direction

        # get vehicle state
        self.start_loc = self.vehicle.location.global_relative_frame

        self.triggerDist = self.start_loc.alt * OVERLAP
        self.triggerDist = max(self.triggerDist, MIN_TRIGGER_DIST)
        
        # calculate the foward point
        forwardPt = location_helpers.newLocationFromAzimuthAndDistance(self.start_loc, self.camYaw, self.transectLength)
        
        # create a new pathHandler obejct with our new points
        # this will automatically reset resumeSpeed, cruiseSpeed etc...
        self.pathHandler = pathHandler.TwoPointPathHandler(self.start_loc, forwardPt, self.vehicle, self.shotmgr)
Пример #7
0
    def handleSpotLock(self, channels):
        '''handle spot lock'''
        # we rotate this value for re-pointing
        dist = location_helpers.getDistanceFromPoints(
            self.vehicle.location.global_relative_frame, self.roi)

        # rotate the ROI point
        if abs(channels[YAW]) > 0:
            self.needsUpdate = True
            tmp = self.roi.alt
            az = location_helpers.calcAzimuthFromPoints(
                self.vehicle.location.global_relative_frame, self.roi)
            az += (channels[YAW] * YAW_NUDGE_SPEED * UPDATE_TIME)
            newRoi = location_helpers.newLocationFromAzimuthAndDistance(
                self.vehicle.location.global_relative_frame, az, dist)
            newRoi.alt = tmp
            self.addLocation(newRoi)

        self.updateROIAlt(channels[RAW_PADDLE])

        # nothing to do if no user interaction
        if not self.needsUpdate:
            return

        # clear update flag
        self.needsUpdate = False

        # Tell Gimbal ROI Location
        msg = self.vehicle.message_factory.command_int_encode(
            0,
            1,  # target system, target component
            mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT,  #frame
            mavutil.mavlink.MAV_CMD_DO_SET_ROI,  #command
            0,  #current
            0,  #autocontinue
            0,
            0,
            0,
            0,  #params 1-4
            self.roi.lat * 1.E7,
            self.roi.lon * 1.E7,
            self.roi.alt)

        self.vehicle.send_mavlink(msg)
Пример #8
0
    def move(self, channels, newroi=None, roiVel=None):
        '''Handles RC channels to return a position and velocity command
        location: location object, lat (deg), lon (deg), alt (meters)
        velocity: vector3 object, x, y, z (m/s) command'''

        # If we are inside of the circle, we overide the radius
        # with our position to prevent sudden flight to or away from pilot
        if self.approachSpeed != 0 and self.distance < self.radius:
            self.radius = self.distance

        if roiVel is None:
            roiVel = Vector3(0, 0, 0)

        # Approach
        approachVel = self._approach(-channels[PITCH])

        # Climb
        climbVel = self._climb(channels[THROTTLE])

        # ROI heading is calculated and flipped 180deg to determine leash angle
        roiHeading = location_helpers.calcAzimuthFromPoints(self.roi, newroi)
        roiHeading += 180
        roiHeading = location_helpers.wrapTo360(roiHeading)

        # roiSpeed is used to determine if we apply crosstrack error correction
        roiSpeed = location_helpers.getDistanceFromPoints(self.roi,
                                                          newroi) / UPDATE_TIME

        if roiSpeed < CROSSTRACK_MINSPEED or self.approachSpeed != 0:
            # we are not moving very fast, don't crosstrack
            # prevents swinging while we are still.
            crosstrackGain = 0
        else:
            crosstrackGain = CROSSTRACK_GAIN

        # Used to test are we inside the radius or on it?
        # we use old ROI because current location is not set yet
        # and wont be for the test function
        self.distance = location_helpers.getDistanceFromPoints(
            self.roi, self.currentLoc)

        # overwrite old ROI with new
        self.roi = newroi

        # new Az from ROI to current position
        self.azimuth = location_helpers.calcAzimuthFromPoints(
            self.roi, self.currentLoc)

        # angle error of ROI Heading vs Azimuth
        headingError = roiHeading - self.azimuth
        headingError = location_helpers.wrapTo180(headingError)

        # used to determine if the copter in front of us or behind
        angleErrorTest = abs(headingError)

        # limit error
        if headingError > 90:
            headingError = 90
        elif headingError < -90:
            headingError = -90

        if self.distance < (self.radius - 1) and self.approachSpeed == 0:
            # we are inside the circle with a margin of error to prevent small jerks
            # -1 on z is used as a dataflag for no desired velocity
            currentVel = Vector3(0, 0, 0)

        elif angleErrorTest > 90 and self.approachSpeed == 0:
            # We are outside the circle
            # We are walking toward copter
            currentVel = Vector3(0, 0, 0)

        else:
            # Follow leash and manage crosstrack
            # bring in the Az to match the ROI heading
            crosstrack = headingError * crosstrackGain * UPDATE_TIME
            crosstrack = min(crosstrack, CROSSTRACK_MAX)

            # scale down the crosstracking with the distance (min 1m to avoid div/0)
            self.azimuth += crosstrack / max(self.distance - 1, 1)

            # for calculating velocity vector (unpack and then pack object to copy the values not the reference)
            oldPos = LocationGlobalRelative(self.currentLoc.lat,
                                            self.currentLoc.lon,
                                            self.currentLoc.alt)

            # get new location from Az and radius
            self.currentLoc = location_helpers.newLocationFromAzimuthAndDistance(
                self.roi, self.azimuth, self.radius)

            # calc velocity to new position
            currentVel = location_helpers.getVectorFromPoints(
                oldPos, self.currentLoc)

            # convert to speed
            currentVel = (currentVel * UPDATE_TIME) + approachVel + roiVel

        # Climb/descend in all cases, even if holding still translationally
        currentVel += climbVel

        # set altitude
        self.currentLoc.alt = self.roi.alt + self.zOffset

        # check altitude limit
        if self.maxAlt is not None:
            self.currentLoc.alt = min(self.currentLoc.alt, self.maxAlt)

        return self.currentLoc, currentVel
Пример #9
0
    def handleRCs(self, channels):

        # don't continue until an roi is set
        if not self.pathHandler or not self.roi:
            return

        # allow user to rotate the ROI about the vehicle
        if abs(channels[YAW]) > 0:
            # adding 180 flips the az (ROI to vehicle) to (vehicle to ROI)
            tmp = self.roi.alt
            self.pathController.azimuth += channels[
                YAW] * YAW_SPEED * UPDATE_TIME

            self.roi = location_helpers.newLocationFromAzimuthAndDistance(
                self.vehicle.location.global_relative_frame,
                180 + self.pathController.azimuth, self.pathController.radius)
            self.roi.alt = tmp
            self.roi_needsUpdate = True

        # call path controller
        pos, vel = self.pathController.move(channels,
                                            self.pathHandler.cruiseSpeed,
                                            self.roi)

        # mavlink expects 10^7 integer for accuracy
        latInt = int(pos.lat * 10000000)
        lonInt = int(pos.lon * 10000000)

        # create the SET_POSITION_TARGET_GLOBAL_INT command
        msg = self.vehicle.message_factory.set_position_target_global_int_encode(
            0,  # time_boot_ms (not used)
            0,
            1,  # target system, target component
            mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT,  # frame
            0b0000110111000000,  # type_mask - enable pos/vel
            latInt,
            lonInt,
            pos.alt,  # x, y, z positions
            vel.x,
            vel.y,
            vel.z,  # x, y, z velocity in m/s
            0,
            0,
            0,  # x, y, z acceleration (not used)
            0,
            0)  # yaw, yaw_rate (not used)

        # send command to vehicle
        self.vehicle.send_mavlink(msg)

        # pointing logic

        # Adjust the height of the ROI using the paddle
        # we pass in both the filtered gimbal paddle value as well as the raw one
        self.setROIAltitude(channels[5], channels[7])

        # set ROI
        msg = self.vehicle.message_factory.command_long_encode(
            0,
            1,  # target system, target component
            mavutil.mavlink.MAV_CMD_DO_SET_ROI,  #command
            0,  #confirmation
            0,
            0,
            0,
            0,  #params 1-4
            self.roi.lat,
            self.roi.lon,
            self.roi.alt + self.ROIAltitudeOffset)

        # send pointing message for either cam mode
        self.vehicle.send_mavlink(msg)
        self.updateApp()