forked from acmerobotics/road-runner-quickstart
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTwoDeadWheelLocalizer.java
More file actions
146 lines (117 loc) · 5.9 KB
/
TwoDeadWheelLocalizer.java
File metadata and controls
146 lines (117 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package org.firstinspires.ftc.teamcode;
import com.acmerobotics.dashboard.config.Config;
import com.acmerobotics.roadrunner.DualNum;
import com.acmerobotics.roadrunner.Pose2d;
import com.acmerobotics.roadrunner.PoseVelocity2d;
import com.acmerobotics.roadrunner.Rotation2d;
import com.acmerobotics.roadrunner.Time;
import com.acmerobotics.roadrunner.Twist2dDual;
import com.acmerobotics.roadrunner.Vector2d;
import com.acmerobotics.roadrunner.Vector2dDual;
import com.acmerobotics.roadrunner.ftc.Encoder;
import com.acmerobotics.roadrunner.ftc.FlightRecorder;
import com.acmerobotics.roadrunner.ftc.OverflowEncoder;
import com.acmerobotics.roadrunner.ftc.PositionVelocityPair;
import com.acmerobotics.roadrunner.ftc.RawEncoder;
import com.qualcomm.robotcore.hardware.DcMotorEx;
import com.qualcomm.robotcore.hardware.DcMotorSimple;
import com.qualcomm.robotcore.hardware.HardwareMap;
import com.qualcomm.robotcore.hardware.IMU;
import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit;
import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity;
import org.firstinspires.ftc.robotcore.external.navigation.UnnormalizedAngleUnit;
import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles;
import org.firstinspires.ftc.teamcode.messages.TwoDeadWheelInputsMessage;
@Config
public final class TwoDeadWheelLocalizer implements Localizer {
public static class Params {
public double parYTicks = 12017.115427890993; // y position of the parallel encoder (in tick units)
public double perpXTicks = -9270.416405666692; // x position of the perpendicular encoder (in tick units)
}
public static Params PARAMS = new Params();
public final Encoder par, perp;
public final IMU imu;
private int lastParPos, lastPerpPos;
private Rotation2d lastHeading;
private final double inPerTick;
private double lastRawHeadingVel, headingVelOffset;
private boolean initialized;
private Pose2d pose;
public TwoDeadWheelLocalizer(HardwareMap hardwareMap, IMU imu, double inPerTick, Pose2d pose) {
// TODO: make sure your config has **motors** with these names (or change them)
// the encoders should be plugged into the slot matching the named motor
// see https://ftc-docs.firstinspires.org/en/latest/hardware_and_software_configuration/configuring/index.html
par = new OverflowEncoder(new RawEncoder(hardwareMap.get(DcMotorEx.class, "backRightDrive")));
perp = new OverflowEncoder(new RawEncoder(hardwareMap.get(DcMotorEx.class, "frontRightDrive")));
par.setDirection(DcMotorSimple.Direction.REVERSE);
// TODO: reverse encoder directions if needed
// par.setDirection(DcMotorSimple.Direction.REVERSE);
this.imu = imu;
this.inPerTick = inPerTick;
FlightRecorder.write("TWO_DEAD_WHEEL_PARAMS", PARAMS);
this.pose = pose;
}
@Override
public void setPose(Pose2d pose) {
this.pose = pose;
}
@Override
public Pose2d getPose() {
return pose;
}
@Override
public PoseVelocity2d update() {
PositionVelocityPair parPosVel = par.getPositionAndVelocity();
PositionVelocityPair perpPosVel = perp.getPositionAndVelocity();
YawPitchRollAngles angles = imu.getRobotYawPitchRollAngles();
// Use degrees here to work around https://github.com/FIRST-Tech-Challenge/FtcRobotController/issues/1070
AngularVelocity angularVelocityDegrees = imu.getRobotAngularVelocity(AngleUnit.DEGREES);
AngularVelocity angularVelocity = new AngularVelocity(
UnnormalizedAngleUnit.RADIANS,
(float) Math.toRadians(angularVelocityDegrees.xRotationRate),
(float) Math.toRadians(angularVelocityDegrees.yRotationRate),
(float) Math.toRadians(angularVelocityDegrees.zRotationRate),
angularVelocityDegrees.acquisitionTime
);
FlightRecorder.write("TWO_DEAD_WHEEL_INPUTS", new TwoDeadWheelInputsMessage(parPosVel, perpPosVel, angles, angularVelocity));
Rotation2d heading = Rotation2d.exp(angles.getYaw(AngleUnit.RADIANS));
// see https://github.com/FIRST-Tech-Challenge/FtcRobotController/issues/617
double rawHeadingVel = angularVelocity.zRotationRate;
if (Math.abs(rawHeadingVel - lastRawHeadingVel) > Math.PI) {
headingVelOffset -= Math.signum(rawHeadingVel) * 2 * Math.PI;
}
lastRawHeadingVel = rawHeadingVel;
double headingVel = headingVelOffset + rawHeadingVel;
if (!initialized) {
initialized = true;
lastParPos = parPosVel.position;
lastPerpPos = perpPosVel.position;
lastHeading = heading;
return new PoseVelocity2d(new Vector2d(0.0, 0.0), 0.0);
}
int parPosDelta = parPosVel.position - lastParPos;
int perpPosDelta = perpPosVel.position - lastPerpPos;
double headingDelta = heading.minus(lastHeading);
Twist2dDual<Time> twist = new Twist2dDual<>(
new Vector2dDual<>(
new DualNum<Time>(new double[] {
parPosDelta - PARAMS.parYTicks * headingDelta,
parPosVel.velocity - PARAMS.parYTicks * headingVel,
}).times(inPerTick),
new DualNum<Time>(new double[] {
perpPosDelta - PARAMS.perpXTicks * headingDelta,
perpPosVel.velocity - PARAMS.perpXTicks * headingVel,
}).times(inPerTick)
),
new DualNum<>(new double[] {
headingDelta,
headingVel,
})
);
lastParPos = parPosVel.position;
lastPerpPos = perpPosVel.position;
lastHeading = heading;
pose = pose.plus(twist.value());
return twist.velocity().value();
}
}