|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
| Thread Tools | Rate Thread | Display Modes |
|
#1
|
||||
|
||||
|
What is wrong with my Vision to Gyro code?!
Hi,
I have been trying to make a decent attempt at vision tracking for offseason competitions. During regional play, I would just do "if target to the left, go right" which is incredibly slow and just a bad practice. Now I am trying to use the NavX so that it will be quicker and better at aligning with the target. I wrote some code to do this by first finding the best target. Then it will calculate the gyro angle before finally having that gyro angle put into a PID loop. The problem I am having is that the PID loop is not going to where it should go. For example, I printed out the current Yaw angle before going to the target, the target angle, and then the yaw angle as it moves. What I found is that the target is -56 degrees, the current Yaw angle before moving is -70, and where the robot turns to is about 125 and it just oscillates there. This confused the heck out of me because I am telling the PID loop to go to -56 but then is stops at 125?! Why?! Here is the code(my apologies in advance for the spaghetti code): Code:
def vision(self):
try:
self.vision_table.retrieveValue('centerX', self.vision_x)
self.vision_table.retrieveValue('centerY', self.vision_y)
except KeyError:
self.turner=False
else:
if len(self.vision_x)>0 and self.auto_alineX.get() and self.vision_state == 3 or self.auto_aline_auto:
self.degrees=self.gyroMagic(self.find_bestX())
self.vision_state = 1
self.visionTurn()
def find_bestX(self):
#My attempt to find the best target by seeing which one is more in the center
if len(self.vision_x)==1:
self.vision_numberX=self.vision_x[0]
else:
good=self.vision_x[0]
normal=abs(self.vision_x[0]-110)
for i in self.vision_x[1:]:
total=abs(i-110)
if total <= normal:
normal=total
good=i
self.vision_numberX=good
return self.vision_numberX
def gyroMagic(self, x):
angle = ((x-110)*(60/320)) #110 seems to be about the center
yaw=self.navx.getYaw()
if yaw > 0:
self.desiredAngle=self.navx.getYaw()+(angle*(227/180)) #Times 227/180 because the gyro is very offset
if self.desiredAngle>179:
self.desiredAngle -= 360
else:
self.desiredAngle=self.navx.getYaw()+(angle*(133/180))
if self.desiredAngle<-179:
self.desiredAngle += 360
return self.desiredAngle
def visionTurn(self):
#Where the PID stuff happens
#Used a state machine because it was an easy way to have the setSetpoint run only once
if self.vision_state == 1:
self.turnController.setSetpoint(self.desiredAngle)
self.rotateReady = True
self.vision_state=2
elif self.vision_state == 2:
if self.turnController.onTarget() or self.cancel.get():
self.vision_state=3
self.rotateReady=False
EDIT: I realized it may help if I show the setup of the PID loop. Here it is: Code:
kP = 0.03
kI = 0.00
kD = 0.00
kF = 0.00
turnController = wpilib.PIDController(kP, kI, kD, kF, self.navx, output=self)
turnController.setInputRange(-180.0, 180.0)
turnController.setOutputRange(-.5, .5)
turnController.setAbsoluteTolerance(2.0)
turnController.setContinuous(True)
self.turnController = turnController
Last edited by team-4480 : 06-07-2016 at 17:54. |
|
#2
|
|||
|
|||
|
Re: What is wrong with my Vision to Gyro code?!
You indicated that your PID loop would rotate the robot to 125 degrees instead of the target of -56 degrees. Given that the robot then oscillates around 125 degrees, this sounds like a condition where you need to invert (negate) the output value produced by the PID before applying it to your motors.
When we run across this issue, we typically observe the following:
Try negating the power before applying it to your motors to see if that fixes the problem. It might also be useful to add a command that rotates the robot 90 degrees every time you press a button (to make sure you get the rotation PID figured out before adding the camera code). |
|
#3
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
Quote:
|
|
#4
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Your PID Controller is steadying to a 180-degree offset of where you put your setpoint (i.e. the 'back-end' of your robot is facing your target), e.g. -56 + 180 = 124, within the 2 degree tolerance you set
Before passing your setpoint to the PID controller, use "setpoint - 180" instead of just "setpoint", or find a way to reverse the angle (angle - 180) the NavX passes to the PIDController Quote:
|
|
#5
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
My point is, the NavX doesn't report 2 different things for the PID loop and SmartDashboard display. The operation (180 - angle) will fix the problem by changing the clockwise angles to counterclockwise ones, but OP probably doesn't want to do that because clockwise is the convention. Instead, it's a better idea to flip the output direction. |
|
#6
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
Flipping the output direction will not solve the problem, but instead cause the robot to steady by turning in the opposite direction. The error is calculated by the difference between where the gyro is versus where it wants to be. By changing the output variables, this does not change this calculated error. Either the setpoint or the feedback given by the NavX needs to be inverted (that is, whatever it is minus 180 degrees). 'Offsetting' the setpoint based on what the real-world offset is will account for what seems like the NavX being placed backwards. Flipping the output directions, however, does not change the real-world offset, but instead causes the robot to rotate away from its target, which will then wrap around due to the continuous option being set, and steady to the same angle as before. |
|
#7
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
Sorry if I'm not being clear with this. Does this make sense? |
|
#8
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
OP: I ran your python code using the values you provided. Here's what I found: In your gyroMagic function, angle and desiredAngle are both always zero. You're trying to divide an integer type by an integer. Use the float notation for the numbers you're dividing by (e.g. 110.0, 60.0, 227.0 etc). Where are you plugging your -56 into? |
|
#9
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
I am using the -56 for the visionTurn() function which is where the setSetpoint is located. Thanks! |
|
#10
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
|
|
#11
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
Code:
def visionTurn(self):
if self.vision_state == 1:
self.turnController.setSetpoint(self.desiredAngle)
self.rotateReady = True
self.vision_state=2
elif self.vision_state == 2:
print (self.navx.getYaw())
if self.turnController.onTarget() or self.cancel.get():
self.vision_state=3
self.rotateReady=False
|
|
#12
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Isn't that what negating the PID output would do?
|
|
#13
|
|||||
|
|||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
By reversing the angle, the physical orientation will move to the correct location, but it will continue to oscillate around that new point, for reasons given in post #2 - Even if it were started right at that physical point at rest, the PID is 180 degrees off target, and will push it one way or the other, starting an oscillation. If the PID output is negated (or the motor wires swapped), the motor will then be driven towards the desired set point, and the PID should (after a bit of tuning) function as desired, either approaching the set point asymptotically or slightly overshooting with a dampening oscillation. |
|
#14
|
||||
|
||||
|
Re: What is wrong with my Vision to Gyro code?!
Quote:
|
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|