For the best driving experience from our PS4 controller, we want to have smooth intuitive commands from the analog stick.
There's the common-as-muck robot-relative steering method. You know the one: push up on the joystick and the robot goes forward. Pull back and the robot goes back. Left turns to the left, and right turns to the right. Boring.
Then this popped up on the Whatsapp Group a few days ago:
So rather than just thinking of forward and backward, we're actually pushing the steck in the direction we want the bot to travel. Up is North, Down is South, Left is West, Right is East, and any angle is literally that angle. That's right. Push the stick in a direction, and the robot turns in that direction and drives. It's so genius that Elon Musk would be baffled by it.
We have a gyro sensor built into our robot, so that takes care of some of the hard work. We knew that absolute steering had the potential to be more intuitive in a small square arena, and might get rid of any weird jankiness associated with rotating the joystick past 90°, but might be marginally harder to implement.
We already had program that allowed for a bearing to be put in and the robot to face that direction, so I decided to implement a vector-based solution; the magnitude would represent the power supplied to the engine, and the direction would represent, well, the direction.
I applied my incredible intellect to this and was able to program it applying trigonometry and a bit of spaghetti coding to calculate these values. We could then feed this into our other program, giving (relatively) fine tuned steering.
import math
from typing import List
deadspace = 0.1
maxval = 1
#This places the coords on a value from 100 to -100
def standardizedCoOrds(x, y):
x = x/30000
y = y/30000
return(x,y)
#converts coordinates into a value returning magnitude and angle
def coordinatesToVector(xval,yval):
tuple = standardizedCoOrds(xval,yval)
(x, y) = tuple
magnitudeOfVector = math.sqrt(x**2 + y**2)
if magnitudeOfVector <= deadspace:
magnitudeOfVector = 0
if magnitudeOfVector >= maxval:
magnitudeOfVector = 1
directionOfVector = abs(math.degrees(math.atan(y/x)))
return (magnitudeOfVector, directionOfVector)
#converts coordinates into a 3 figure bearing with magnitude
def coordinatesToBearing(joyX, joyY):
tuple = coordinatesToVector(joyX, joyY)
magnitude = tuple[0]
angle = abs(tuple[1])
if joyX >= 0 and joyY >= 0:
bearing = 90 - angle
elif joyX >= 0 and joyY <= 0:
bearing = 180 - angle
elif joyX <= 0 and joyY <= 0:
bearing = 270 - angle
elif joyX >= 0 and joyY <= 0:
bearing = 360 - angle
return(magnitude * 100, int(bearing))
Now it's up to Kevin to hook it up to the actual robot, so we can see my genius at work.
Comments