Skip to content

Commit e3203df

Browse files
Merge pull request #25 from EMU4729/localisationsubsystem
Add LocalisationSubsystem
2 parents 3bcdac5 + bd82544 commit e3203df

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package org.firstinspires.ftc.teamcode.lib.subsystems;
2+
3+
import com.qualcomm.hardware.sparkfun.SparkFunOTOS;
4+
import com.qualcomm.robotcore.hardware.HardwareMap;
5+
6+
import org.firstinspires.ftc.robotcore.external.Telemetry;
7+
import org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection;
8+
import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName;
9+
import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit;
10+
import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit;
11+
import org.firstinspires.ftc.robotcore.external.navigation.Position;
12+
import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles;
13+
import org.firstinspires.ftc.vision.VisionPortal;
14+
import org.firstinspires.ftc.vision.apriltag.AprilTagDetection;
15+
import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor;
16+
17+
import java.util.List;
18+
19+
public class LocalisationSubsystem {
20+
private static final boolean USE_WEBCAM = true;
21+
private static final double OTOS_LINEAR_SCALAR = 1.0; // todo: find exact value, need robot physically
22+
private static final double OTOS_ANGULAR_SCALAR = 1.0; // todo: find exact value, need robot physically
23+
private static final SparkFunOTOS.Pose2D OTOS_OFFSET = new SparkFunOTOS.Pose2D(0, 0, 0); // todo: find exact values, need robot physically
24+
25+
private static final Position CAMERA_POSITION = new Position(DistanceUnit.METER,
26+
0, 0, 0, 0);
27+
28+
// pitch was init'd as -90 in demo, but set to 0 here for now (-90 made no sense)
29+
private static final YawPitchRollAngles CAMERA_ORIENTATION = new YawPitchRollAngles(AngleUnit.DEGREES,
30+
0, -90, 0, 0);
31+
32+
private final SparkFunOTOS otosSensor;
33+
private final Telemetry telemetry;
34+
private AprilTagProcessor aprilTag;
35+
private VisionPortal visionPortal;
36+
HardwareMap hardwareMap;
37+
38+
// ROBOT X, Y and HDG
39+
public double robotX = 0.0;
40+
public double robotY = 0.0;
41+
public double robotH = 0.0;
42+
43+
// STATES
44+
public final boolean hasPositionedFromCamera = false; // public, as there can be no turret rotation until the first camera reading has been made, and this var determines this.
45+
46+
47+
48+
public LocalisationSubsystem(HardwareMap hardwareMap, Telemetry telemetry) {
49+
this.telemetry = telemetry;
50+
this.hardwareMap = hardwareMap;
51+
52+
configureAprilTag();
53+
54+
otosSensor = hardwareMap.get(SparkFunOTOS.class, "sensor_otos");
55+
configureOTOS();
56+
57+
telemetry.addLine("Localisation Subsystem Configured");
58+
telemetry.update();
59+
}
60+
61+
public void periodic() {
62+
if (!hasPositionedFromCamera) {
63+
List<AprilTagDetection> freshDetections = aprilTag.getFreshDetections();
64+
65+
if (!freshDetections.isEmpty()) {
66+
// we cannot assume that there is only one detection, but we do know the last one is the latest. therefore, by going through all of them, we can know we are up to date.
67+
for (AprilTagDetection detection : freshDetections) {
68+
// as shown by demo code - no "Obelisk" tags can be used for positioning
69+
if (!detection.metadata.name.contains("Obelisk")) {
70+
robotX = detection.robotPose.getPosition().x;
71+
robotY = detection.robotPose.getPosition().y;
72+
robotH = detection.robotPose.getOrientation().getYaw(AngleUnit.DEGREES);
73+
}
74+
}
75+
76+
// update the OTOS's position data
77+
updateOTOS();
78+
telemetry.addData("AprilUpdate", true);
79+
80+
hasPositionedFromCamera = true;
81+
}
82+
}
83+
84+
positionFromOTOS();
85+
telemetry.addData("AprilUpdate", false);
86+
87+
telemetry.addData("RobotX", robotX);
88+
telemetry.addData("RobotY", robotY);
89+
telemetry.addData("RobotHDG", robotH);
90+
telemetry.update();
91+
}
92+
93+
/**
94+
* Updates the OTOS sensor to be at the camera's reported position.
95+
*/
96+
private void updateOTOS() {
97+
SparkFunOTOS.Pose2D currentPosition = new SparkFunOTOS.Pose2D(
98+
robotX,
99+
robotY,
100+
robotH
101+
);
102+
otosSensor.setPosition(currentPosition);
103+
}
104+
105+
/**
106+
* Updates the robot's position from the OTOS's reported position.
107+
*/
108+
private void positionFromOTOS() {
109+
SparkFunOTOS.Pose2D currentPosition = otosSensor.getPosition();
110+
robotX = currentPosition.x;
111+
robotY = currentPosition.y;
112+
robotH = currentPosition.h;
113+
}
114+
115+
private void configureOTOS() {
116+
// UNIT CALIBRATION
117+
otosSensor.setLinearUnit(DistanceUnit.METER);
118+
otosSensor.setAngularUnit(AngleUnit.DEGREES);
119+
120+
// OFFSET ON ROBOT
121+
otosSensor.setOffset(OTOS_OFFSET);
122+
123+
// SCALAR CALIBRATION
124+
otosSensor.setLinearScalar(OTOS_LINEAR_SCALAR);
125+
otosSensor.setAngularScalar(OTOS_ANGULAR_SCALAR);
126+
127+
// CALIBRATE IMU
128+
otosSensor.calibrateImu();
129+
otosSensor.resetTracking();
130+
131+
// starting position, will be updated by april tag positioning.
132+
SparkFunOTOS.Pose2D currentPosition = new SparkFunOTOS.Pose2D(0, 0, 0);
133+
otosSensor.setPosition(currentPosition);
134+
135+
telemetry.addLine("OTOS Configured");
136+
telemetry.update();
137+
}
138+
139+
140+
private void configureAprilTag() {
141+
// april tag processor
142+
aprilTag = new AprilTagProcessor.Builder()
143+
.setCameraPose(CAMERA_POSITION, CAMERA_ORIENTATION)
144+
.build();
145+
146+
// vision portal
147+
VisionPortal.Builder builder = new VisionPortal.Builder();
148+
149+
// NOTE: USE_WEBCAM is set at top of class. idk what to set it, so it is currently true as the example code used that.
150+
if (USE_WEBCAM) {
151+
builder.setCamera(hardwareMap.get(WebcamName.class, "webcam"));
152+
} else {
153+
builder.setCamera(BuiltinCameraDirection.FRONT); // used to be BACK in e.g. code
154+
}
155+
156+
// enable the processor
157+
builder.addProcessor(aprilTag);
158+
visionPortal = builder.build();
159+
telemetry.addLine("April Tag Process Configured");
160+
telemetry.update();
161+
}
162+
}

TeamCode/src/main/java/org/firstinspires/ftc/teamcode/lib/subsystems/SubsystemBase.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ public abstract class SubsystemBase {
99
* continuously, such as updating telemetry, or PID controllers.
1010
*/
1111
public void periodic() {
12+
1213
}
1314
}

0 commit comments

Comments
 (0)