@@ -10,8 +10,6 @@ import pioneer.helpers.PIDController
1010import pioneer.helpers.Pose
1111import pioneer.localization.Localizer
1212import pioneer.pathing.motionprofile.*
13- import pioneer.pathing.motionprofile.constraints.AccelerationConstraint
14- import pioneer.pathing.motionprofile.constraints.VelocityConstraint
1513import pioneer.pathing.paths.Path
1614import kotlin.math.*
1715import kotlin.time.DurationUnit
@@ -23,9 +21,14 @@ class Follower(
2321 private val timer = ElapsedTime ()
2422 private val chrono = Chrono (autoUpdate = false , units = DurationUnit .MILLISECONDS )
2523
26- private val pidX = PIDController (Constants .Follower .X_KP , Constants .Follower .X_KI , Constants .Follower .X_KD )
27- private val pidY = PIDController (Constants .Follower .Y_KP , Constants .Follower .Y_KI , Constants .Follower .Y_KD )
28- private val pidHeading = PIDController (Constants .Follower .THETA_KP , Constants .Follower .THETA_KI , Constants .Follower .THETA_KD )
24+ private val pidVX = PIDController (Constants .Follower .X_KP , Constants .Follower .X_KI , Constants .Follower .X_KD )
25+ private val pidVY = PIDController (Constants .Follower .Y_KP , Constants .Follower .Y_KI , Constants .Follower .Y_KD )
26+ private val pidVHeading = PIDController (Constants .Follower .THETA_KP , Constants .Follower .THETA_KI , Constants .Follower .THETA_KD )
27+
28+ // Second set of PIDs for direct position control to be used when path is done (if needed)
29+ private val pidXPos = PIDController (Constants .Follower .POS_X_KP , Constants .Follower .POS_X_KI , Constants .Follower .POS_X_KD )
30+ private val pidYPos = PIDController (Constants .Follower .POS_Y_KP , Constants .Follower .POS_Y_KI , Constants .Follower .POS_Y_KD )
31+ private val pidHeadingPos = PIDController (Constants .Follower .POS_THETA_KP , Constants .Follower .POS_THETA_KI , Constants .Follower .POS_THETA_KD )
2932
3033 private var path: Path ? = null
3134 private var profile: MotionProfile ? = null
@@ -68,9 +71,9 @@ class Follower(
6871 this .path = path
6972 this .profile = calculateMotionProfile(path)
7073 // Reset PID controllers and timer
71- pidX .reset()
72- pidY .reset()
73- pidHeading .reset()
74+ pidVX .reset()
75+ pidVY .reset()
76+ pidVHeading .reset()
7477 timer.reset()
7578
7679 FileLogger .debug(" Follower" , " Profile duration=${profile?.duration()} " )
@@ -79,9 +82,9 @@ class Follower(
7982 fun reset () {
8083 path = null
8184 profile = null
82- pidX .reset()
83- pidY .reset()
84- pidHeading .reset()
85+ pidVX .reset()
86+ pidVY .reset()
87+ pidVHeading .reset()
8588 drive.stop()
8689 }
8790
@@ -93,6 +96,30 @@ class Follower(
9396 val profile = profile ? : return true
9497 val t = timer.seconds()
9598
99+ // if (timer.seconds() > t) { // Untested
100+ // // If path is done but not within tolerances
101+ // if (!done) {
102+ // // Switch to position PID control to correct final pose
103+ // val errorX = path.endPose.x - localizer.pose.x
104+ // val errorY = path.endPose.y - localizer.pose.y
105+ // val errorHeading = MathUtils.normalizeRadians(path.endPose.theta - localizer.pose.theta)
106+ // val vxCorrect = pidXPos.update(errorX, chrono.dt)
107+ // val vyCorrect = pidYPos.update(errorY, chrono.dt)
108+ // val omegaCorrect = pidHeadingPos.update(errorHeading, chrono.dt)
109+ // val driveCommand = Pose(
110+ // vx = vxCorrect,
111+ // vy = vyCorrect,
112+ // omega = omegaCorrect,
113+ // ax = 0.0,
114+ // ay = 0.0,
115+ // alpha = 0.0,
116+ // )
117+ // FileLogger.debug("Follower", "Final Pose Correction Drive Command: $driveCommand")
118+ // drive.setDriveVA(driveCommand)
119+ // return false
120+ // }
121+ // }
122+
96123 if (done) {
97124 reset()
98125 drive.stop()
@@ -134,9 +161,9 @@ class Follower(
134161 val (errorX, errorY) = MathUtils .rotateVector(errorFieldX, errorFieldY, - localizer.pose.theta)
135162
136163 // PID corrections
137- val vxCorrect = pidX .update(errorX, chrono.dt)
138- val vyCorrect = pidY .update(errorY, chrono.dt)
139- val omegaCorrect = pidHeading .update(errorHeading, chrono.dt)
164+ val vxCorrect = pidVX .update(errorX, chrono.dt)
165+ val vyCorrect = pidVY .update(errorY, chrono.dt)
166+ val omegaCorrect = pidVHeading .update(errorHeading, chrono.dt)
140167
141168 // final drive command
142169 val driveCommand = Pose (
0 commit comments