1
1
package jaci .pathfinder .followers ;
2
2
3
- import jaci .pathfinder .PathfinderJNI ;
4
3
import jaci .pathfinder .Trajectory ;
5
4
5
+ /**
6
+ * The EncoderFollower is an object designed to follow a trajectory based on encoder input. This class can be used
7
+ * for Tank or Swerve drive implementations.
8
+ *
9
+ * @author Jaci
10
+ */
6
11
public class EncoderFollower {
7
12
8
13
int encoder_offset , encoder_tick_count ;
@@ -21,26 +26,56 @@ public EncoderFollower(Trajectory traj) {
21
26
22
27
public EncoderFollower () { }
23
28
29
+ /**
30
+ * Set a new trajectory to follow, and reset the cumulative errors and segment counts
31
+ */
24
32
public void setTrajectory (Trajectory traj ) {
25
33
this .trajectory = traj ;
26
34
reset ();
27
35
}
28
36
37
+ /**
38
+ * Configure the PID/VA Variables for the Follower
39
+ * @param kp The proportional term. This is usually quite high (0.8 - 1.0 are common values)
40
+ * @param ki The integral term. Currently unused.
41
+ * @param kd The derivative term. Adjust this if you are unhappy with the tracking of the follower. 0.0 is the default
42
+ * @param kv The velocity ratio. This should be 1 over your maximum velocity @ 100% throttle.
43
+ * This converts m/s given by the algorithm to a scale of -1..1 to be used by your
44
+ * motor controllers
45
+ * @param ka The acceleration term. Adjust this if you want to reach higher or lower speeds faster. 0.0 is the default
46
+ */
29
47
public void configurePIDVA (double kp , double ki , double kd , double kv , double ka ) {
30
48
this .kp = kp ; this .ki = ki ; this .kd = kd ;
31
49
this .kv = kv ; this .ka = ka ;
32
50
}
33
51
52
+ /**
53
+ * Configure the Encoders being used in the follower.
54
+ * @param initial_position The initial 'offset' of your encoder. This should be set to the encoder value just
55
+ * before you start to track
56
+ * @param ticks_per_revolution How many ticks per revolution the encoder has
57
+ * @param wheel_diameter The diameter of your wheels (or pulleys for track systems) in meters
58
+ */
34
59
public void configureEncoder (int initial_position , int ticks_per_revolution , double wheel_diameter ) {
35
60
encoder_offset = initial_position ;
36
61
encoder_tick_count = ticks_per_revolution ;
37
62
wheel_circumference = Math .PI * wheel_diameter ;
38
63
}
39
64
65
+ /**
66
+ * Reset the follower to start again. Encoders must be reconfigured.
67
+ */
40
68
public void reset () {
41
69
last_error = 0 ; segment = 0 ;
42
70
}
43
71
72
+ /**
73
+ * Calculate the desired output for the motors, based on the amount of ticks the encoder has gone through.
74
+ * This does not account for heading of the robot. To account for heading, add some extra terms in your control
75
+ * loop for realignment based on gyroscope input and the desired heading given by this object.
76
+ * @param encoder_tick The amount of ticks the encoder has currently measured.
77
+ * @return The desired output for your motor controller
78
+ */
44
79
public double calculate (int encoder_tick ) {
45
80
// Number of Revolutions * Wheel Circumference
46
81
double distance_covered = ((double )(encoder_tick - encoder_offset ) / encoder_tick_count )
@@ -60,14 +95,23 @@ public double calculate(int encoder_tick) {
60
95
} else return 0 ;
61
96
}
62
97
98
+ /**
99
+ * @return the desired heading of the current point in the trajectory
100
+ */
63
101
public double getHeading () {
64
102
return heading ;
65
103
}
66
104
105
+ /**
106
+ * @return the current segment being operated on
107
+ */
67
108
public Trajectory .Segment getSegment () {
68
109
return trajectory .get (segment );
69
110
}
70
111
112
+ /**
113
+ * @return whether we have finished tracking this trajectory or not.
114
+ */
71
115
public boolean isFinished () {
72
116
return segment >= trajectory .length ();
73
117
}
0 commit comments