Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 44 additions & 41 deletions limelight/build.gradle
Original file line number Diff line number Diff line change
@@ -1,72 +1,75 @@
plugins {
id 'java-library'
id "edu.wpi.first.GradleRIO" version "2025.1.1"
id 'idea'
// Spotless code formatter.
id 'com.diffplug.spotless' version '6.25.0'
id 'java-library'
id "edu.wpi.first.GradleRIO" version "2025.1.1"
id 'idea'
// Spotless code formatter.
id 'com.diffplug.spotless' version '6.25.0'
}

idea {
module {
downloadJavadoc = true
downloadSources = true
}
module {
downloadJavadoc = true
downloadSources = true
}
}

java {
sourceCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
implementation wpi.java.deps.wpilib()
implementation wpi.java.vendor.java()
implementation wpi.java.deps.wpilib()
implementation wpi.java.vendor.java()

api "org.json:json:20240205"
api "org.json:json:20240205"

testImplementation 'junit:junit:4.13.2'
testImplementation 'com.google.truth:truth:1.4.4'
implementation 'com.google.code.gson:gson:2.12.1'
testImplementation 'junit:junit:4.13.2'
testImplementation 'com.google.truth:truth:1.4.4'
implementation 'com.google.code.gson:gson:2.12.1'

nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
simulationDebug wpi.sim.enableDebug()
nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
simulationDebug wpi.sim.enableDebug()

nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop)
nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop)
simulationRelease wpi.sim.enableRelease()
nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop)
simulationRelease wpi.sim.enableRelease()
}

wpi.java.configureTestTasks(test)

tasks.named('test') {
// Use JUnit 4 for tests
useJUnit()
// Use JUnit 4 for tests
useJUnit()
}

spotless {
// See https://github.com/diffplug/spotless/tree/main/plugin-gradle
format 'misc', {
// define the files to apply `misc` to
target '.gitattributes', '.gitignore'
// See https://github.com/diffplug/spotless/tree/main/plugin-gradle
format 'misc', {
// define the files to apply `misc` to
target '.gitattributes', '.gitignore'

// define the steps to apply to those files
trimTrailingWhitespace()
indentWithSpaces()
endWithNewline()
}
java {
// importOrder() // Use the default importOrder configuration (can override)
removeUnusedImports()
// define the steps to apply to those files
trimTrailingWhitespace()
indentWithSpaces()
endWithNewline()
}
groovyGradle {
greclipse().configFile('greclipse-gradle.properties')
}
java {
importOrder() // Use the default importOrder configuration (can override)
removeUnusedImports()

// Use Google Java Format
// - aosp() causes it to use a four-space indent
// googleJavaFormat('1.24.0').reflowLongStrings()
// Use Google Java Format
// - aosp() causes it to use a four-space indent
googleJavaFormat('1.24.0').reflowLongStrings()

formatAnnotations() // fix formatting of type annotations
}
formatAnnotations() // fix formatting of type annotations
}
}
1 change: 1 addition & 0 deletions limelight/greclipse-gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.eclipse.jdt.core.formatter.tabulation.char=space
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.team2813.lib2813.limelight.apriltag_map.Fiducial;
import com.team2813.lib2813.limelight.apriltag_map.FiducialRetriever;
import edu.wpi.first.math.geometry.Pose3d;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -19,13 +18,16 @@
class AprilTagMapPoseHelper {
private final LimelightClient limelightClient;
private FiducialRetriever retriever;
private static final HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofMillis(20))
.executor(Executors.newFixedThreadPool(1)).build();

private static final HttpClient client =
HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(20))
.executor(Executors.newFixedThreadPool(1))
.build();

public AprilTagMapPoseHelper(LimelightClient client) {
this.limelightClient = client;
}

public void setFieldMap(InputStream stream, boolean updateLimelight) throws IOException {
if (!updateLimelight) {
retriever = new FiducialRetriever(stream);
Expand All @@ -34,12 +36,15 @@ public void setFieldMap(InputStream stream, boolean updateLimelight) throws IOEx
retriever = new FiducialRetriever(new ByteArrayInputStream(bytes));
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArray(bytes);

HttpRequest request = limelightClient.newRequestBuilder("/upload-fieldmap").POST(publisher).build();
HttpRequest request =
limelightClient.newRequestBuilder("/upload-fieldmap").POST(publisher).build();
try {
client.send(request, HttpResponse.BodyHandlers.discarding());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(String.format("Thread interrupted while trying to send request to %s", request.uri()), e);
throw new RuntimeException(
String.format("Thread interrupted while trying to send request to %s", request.uri()),
e);
}
}
}
Expand All @@ -49,15 +54,15 @@ public List<Pose3d> getVisibleTagPoses(Set<Integer> ids) {
return List.of();
}
return retriever.getFiducialMap().values().stream()
.filter(fidicual -> ids.contains(fidicual.getId()))
.map(Fiducial::getPosition).toList();
.filter(fidicual -> ids.contains(fidicual.getId()))
.map(Fiducial::getPosition)
.toList();
}

public Optional<Pose3d> getTagPose(int id) {
if (retriever == null) {
return Optional.empty();
}
return Optional.ofNullable(retriever.getFiducialMap().get(id))
.map(Fiducial::getPosition);
return Optional.ofNullable(retriever.getFiducialMap().get(id)).map(Fiducial::getPosition);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.team2813.lib2813.limelight;

import edu.wpi.first.math.geometry.Pose2d;

import java.util.Set;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.team2813.lib2813.limelight;

import static com.ctre.phoenix6.Utils.getCurrentTimeSeconds;

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
Expand All @@ -12,62 +14,64 @@
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.Executors;

import org.json.JSONObject;

import static com.ctre.phoenix6.Utils.getCurrentTimeSeconds;

class DataCollection implements Runnable {
private static final HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofMillis(20))
.executor(Executors.newFixedThreadPool(2)).build();
private final HttpRequest dumpRequest;
private static final HttpClient client =
HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(20))
.executor(Executors.newFixedThreadPool(2))
.build();
private final HttpRequest dumpRequest;

public DataCollection(LimelightClient limelightClient) {
lastResult = Optional.empty();
try {
dumpRequest = limelightClient.newRequestBuilder("/results").GET().build();
} catch (LimelightClient.HttpRequestException e) {
throw new RuntimeException(e);
}
}
public DataCollection(LimelightClient limelightClient) {
lastResult = Optional.empty();
try {
dumpRequest = limelightClient.newRequestBuilder("/results").GET().build();
} catch (LimelightClient.HttpRequestException e) {
throw new RuntimeException(e);
}
}

record Result(JSONObject json, double responseTimestamp) {}
record Result(JSONObject json, double responseTimestamp) {}

private volatile Optional<Result> lastResult;
private volatile Optional<Result> lastResult;

private static class JSONHandler implements BodyHandler<Result> {
@Override
public BodySubscriber<Result> apply(ResponseInfo responseInfo) {
// Get the timestamp before we parse the JSON.
double responseTimestamp = getCurrentTimeSeconds();
private static class JSONHandler implements BodyHandler<Result> {
@Override
public BodySubscriber<Result> apply(ResponseInfo responseInfo) {
// Get the timestamp before we parse the JSON.
double responseTimestamp = getCurrentTimeSeconds();

return BodySubscribers.mapping(BodyHandlers.ofString(Charset.defaultCharset()).apply(responseInfo), body -> {
return new Result(new JSONObject(body), responseTimestamp);
});
}
}
return BodySubscribers.mapping(
BodyHandlers.ofString(Charset.defaultCharset()).apply(responseInfo),
body -> {
return new Result(new JSONObject(body), responseTimestamp);
});
}
}

private static final JSONHandler handler = new JSONHandler();
private static final JSONHandler handler = new JSONHandler();

private void updateJSON(HttpResponse<Result> obj) {
Result result = obj.body();
lastResult = Optional.of(result);
}
private void updateJSON(HttpResponse<Result> obj) {
Result result = obj.body();
lastResult = Optional.of(result);
}

@Override
public void run() {
try {
updateJSON(client.send(dumpRequest, handler));
} catch (InterruptedException e) {
lastResult = Optional.empty();
// background thread canceled
Thread.currentThread().interrupt();
} catch (Exception e) {
lastResult = Optional.empty();
}
}
@Override
public void run() {
try {
updateJSON(client.send(dumpRequest, handler));
} catch (InterruptedException e) {
lastResult = Optional.empty();
// background thread canceled
Thread.currentThread().interrupt();
} catch (Exception e) {
lastResult = Optional.empty();
}
}

public Optional<Result> getMostRecent() {
return lastResult;
}
}
public Optional<Result> getMostRecent() {
return lastResult;
}
}
Loading
Loading