OpenSolo/shotmanager/pathHandler.py
Matt 39743a9be0 SHOTS: Update for buttons, AC Master, & speeds
Update to all smart shots for some or all of the following:
- Button handling for the new Open Solo button handling rework
- Copter yaw compatibility with ArduCopter master
- Accelleration fixes and standardization
2017-12-18 18:04:56 -05:00

148 lines
4.9 KiB
Python

#
# Code common across shots to handle movement on paths
#
from pymavlink import mavutil
import location_helpers
import shotLogger
from shotManagerConstants import *
import math
import shots
logger = shotLogger.logger
#Path accel/decel constants
PATH_ACCEL = 2
ACCEL_PER_TICK = PATH_ACCEL * UPDATE_TIME
class PathHandler():
def __init__(self, vehicle, shotmgr):
self.vehicle = vehicle
self.shotMgr = shotmgr
# Automatic cruising of the cable
self.cruiseSpeed = 0.0
self.resumeSpeed = 0.0
def pause(self):
self.resumeSpeed = self.cruiseSpeed
self.setCruiseSpeed(0.0)
logger.log("[%s]: Pausing cruise" % shots.SHOT_NAMES[self.shotMgr.currentShot].lower())
def togglePause(self):
if self.isPaused():
self.resume()
else:
self.pause()
def resume(self):
self.setCruiseSpeed(0.0) # self.resumeSpeed to enable actual resume speed
logger.log("[%s]: Resuming cruise." % shots.SHOT_NAMES[self.shotMgr.currentShot].lower())
def isPaused(self):
return self.cruiseSpeed == 0.0
def setCruiseSpeed(self, speed):
self.cruiseSpeed = speed
# special case of PathHandler
class TwoPointPathHandler(PathHandler):
def __init__(self, pt1, pt2, vehicle, shotmgr):
PathHandler.__init__(self, vehicle, shotmgr)
self.pt1 = pt1
self.pt2 = pt2
self.curTarget = None
#for simulated acceleration
self.currentSpeed = 0.0
self.desiredSpeed = 0.0
# given RC input, calculate a speed and use it to
# move towards one of our endpoints
# return the speed we set for the copter
def MoveTowardsEndpt( self, channels ):
# allow both up/down and left/right to move along the cable
# use the max of them
if abs(channels[1]) > abs(channels[2]):
value = channels[1]
else:
value = -channels[2]
# user controls speed
if self.cruiseSpeed == 0.0:
self.desiredSpeed = value * MAX_SPEED
# cruise control
else:
speed = abs(self.cruiseSpeed)
# if sign of stick and cruiseSpeed don't match then...
if math.copysign(1,value) != math.copysign(1,self.cruiseSpeed): # slow down
speed *= (1.0 - abs(value))
else: # speed up
speed += (MAX_SPEED - speed) * abs(value)
# carryover user input sign
if self.cruiseSpeed < 0:
speed = -speed
# limit speed
if speed > MAX_SPEED:
speed = MAX_SPEED
elif -speed > MAX_SPEED:
speed = -MAX_SPEED
self.desiredSpeed = speed
# Synthetic acceleration
if self.desiredSpeed > self.currentSpeed:
self.currentSpeed += ACCEL_PER_TICK
self.currentSpeed = min(self.currentSpeed, self.desiredSpeed)
elif self.desiredSpeed < self.currentSpeed:
self.currentSpeed -= ACCEL_PER_TICK
self.currentSpeed = max(self.currentSpeed, self.desiredSpeed)
else:
self.currentSpeed = self.desiredSpeed
#Check direction of currentSpeed
goingForwards = self.currentSpeed > 0.0
if goingForwards:
target = self.pt2
else:
target = self.pt1
if target != self.curTarget: #switching target and logging
self.vehicle.simple_goto(target)
self.curTarget = target
logger.log("[%s]: Going to pt %d"%(shots.SHOT_NAMES[self.shotMgr.currentShot].lower(), 2 if goingForwards else 1 ) )
logger.log("[%s]: Target is %.12f, %.12f, %.12f."%
(shots.SHOT_NAMES[self.shotMgr.currentShot].lower(), target.lat, target.lon,
target.alt))
# should replace with a dronekit command when it gets in there
msg = self.vehicle.message_factory.command_long_encode(
0, 1, # target system, target component
mavutil.mavlink.MAV_CMD_DO_CHANGE_SPEED, # frame
0, # confirmation
1, abs(self.currentSpeed), -1, # params 1-3
0.0, 0.0, 0.0, 0.0 ) # params 4-7 (not used)
# send command to vehicle
self.vehicle.send_mavlink(msg)
return abs(self.currentSpeed), goingForwards
# returns if we're near our target or not
def isNearTarget(self):
if self.desiredSpeed > 0.0 and \
location_helpers.getDistanceFromPoints3d( \
self.vehicle.location.global_relative_frame, \
self.pt2 ) < WAYPOINT_NEARNESS_THRESHOLD:
return True
elif self.desiredSpeed < 0.0 and \
location_helpers.getDistanceFromPoints3d( \
self.vehicle.location.global_relative_frame, \
self.pt1 ) < WAYPOINT_NEARNESS_THRESHOLD:
return True
return False