mirror of
https://github.com/OpenSolo/OpenSolo.git
synced 2025-04-29 22:24:32 +02:00
148 lines
4.9 KiB
Python
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 = 6
|
|
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
|