Source code for seamonsters.drive
__author__ = "seamonsters"
import math
import seamonsters as sea
class AccelerationFilter:
"""
Calculates acceleration filtering for drive inputs (magnitude, direction, turn).
"""
[docs] def __init__(self, linearAccel, angularAccel):
"""
:param linearAccel: Linear acceleration, in feet per second per second
:param angularAccel: Angular acceleration, in radians per second per second
"""
self.linearAccelPerFrame = linearAccel / sea.ITERATIONS_PER_SECOND
self.angularAccelPerFrame = angularAccel / sea.ITERATIONS_PER_SECOND
self.previousX = 0.0
self.previousY = 0.0
self.previousTurn = 0.0
[docs] def filter(self, magnitude, direction, turn):
"""
:param magnitude: linear velocity in feet per second
:param direction: linear direction in radians
:param turn: angular velocity in radians per second
:return: tuple of filtered magnitude, direction, turn
"""
if abs(self.previousTurn - turn) <= self.angularAccelPerFrame:
filteredTurn = turn
else:
if turn > self.previousTurn:
filteredTurn = self.previousTurn + self.angularAccelPerFrame
else:
filteredTurn = self.previousTurn - self.angularAccelPerFrame
x = magnitude * math.cos(direction)
y = magnitude * math.sin(direction)
distanceFromPrev = math.sqrt((x - self.previousX) ** 2
+ (y - self.previousY) ** 2)
if distanceFromPrev <= self.linearAccelPerFrame:
filteredX = x
filteredY = y
filteredMag = magnitude
filteredDir = direction
else:
filteredX = self.previousX \
+ (x - self.previousX) * self.linearAccelPerFrame / distanceFromPrev
filteredY = self.previousY \
+ (y - self.previousY) * self.linearAccelPerFrame / distanceFromPrev
filteredMag = math.sqrt(filteredX ** 2 + filteredY ** 2)
filteredDir = math.atan2(filteredY, filteredX)
self.previousX = filteredX
self.previousY = filteredY
self.previousTurn = filteredTurn
return filteredMag, filteredDir, filteredTurn
class MultiDrive:
"""
Wraps a SuperHolonomicDrive, and allows ``drive()`` to be called multiple
times in a loop. The values for all of these calls are added together,
and sent to the SuperHolonomicDrive when ``update()`` is called.
"""
[docs] def __init__(self, superDrive):
super().__init__()
self.superDrive = superDrive
self._reset()
def _reset(self):
self.totalX = 0
self.totalY = 0
self.totalTurn = 0
[docs] def drive(self, magnitude, direction, turn):
self.totalX += magnitude * math.cos(direction)
self.totalY += magnitude * math.sin(direction)
self.totalTurn += turn
[docs] def update(self):
magnitude = math.sqrt(self.totalX ** 2 + self.totalY ** 2)
direction = math.atan2(self.totalY, self.totalX)
scale = self.superDrive.drive(magnitude, direction, self.totalTurn)
self._reset()
return scale
if __name__ == "__main__":
# test acceleration filter drive
accelFilter = AccelerationFilter(2.0, 2.0)
for i in range(0, 25):
print(accelFilter.filter(1.0, math.radians(45), 1.0))
print("--------")
for i in range(0, 25):
print(accelFilter.filter(1.0, math.radians(90), 1.0))