3d, camera calibration, backend settings hookup (#80)

* Implement new UI backend stuff

* Kinda partially add resolution accuracy list

* camera calibration go brrrrrrrr

* ayyyy calibration works

* Maybe fix grouping

* Reorganize camera view

* Fix settings not getting sent

* Make pretty (#4)

* Reorganize camera view

* Apply some cosmetic layout changes to the cameras page

* Fix pipeline rollback bug when starting on non-dashboard pages

Co-authored-by: Matt <matthew.morley.ca@gmail.com>

* Fix naming mismatch

* Mostly make stuff work

* rename robot-relative pose to camera-relative pose

* SolvePNP memes, fix isFovConfigurable

* Change config path to photonvision_config

* netmask go poof, fix zip download?

* Update index.js

* Fix multi cam stuff?

* Use LinearFilter instead

* Fix multicam

* aaa

* start adding restart device and restart program, fix square size bug

* Add some debug stuff

* oop

* Start fixing tests

* Fix tests

* Make target box proportinal

* run spotless

* Make crosshair h o t p i n k

* Address review comments

* Address review 2 electric booaloo

* Possibly implement vendor FOV?

* Make centroid crosshair gren

* actually use FOV

* Fix tests

* actually fix tests

Co-authored-by: Declan Freeman-Gleason <declanfreemangleason@gmail.com>
This commit is contained in:
Matt
2020-08-14 12:39:21 -07:00
committed by GitHub
parent 86ea661ed9
commit b3436765e1
86 changed files with 2106 additions and 1173 deletions

View File

@@ -17,46 +17,136 @@
package org.photonvision.server;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.wpi.first.wpilibj.geometry.Rotation2d;
import io.javalin.http.Context;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.photonvision.common.configuration.ConfigManager;
import org.photonvision.common.configuration.NetworkConfig;
import org.photonvision.common.dataflow.networktables.NetworkTablesManager;
import org.photonvision.common.hardware.HardwareManager;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
import org.photonvision.common.networking.NetworkManager;
import org.photonvision.vision.processes.VisionModuleManager;
public class RequestHandler {
private static final Logger logger = new Logger(RequestHandler.class, LogGroup.WebServer);
private static final ObjectMapper kObjectMapper = new ObjectMapper();
/** Parses and saves general settings to the config manager. */
public static void onGeneralSettings(Context context) {
return;
public static void onSettingUpload(Context ctx) {
var file = ctx.uploadedFile("zipData");
if (file != null) {
var tempZipPath =
new File(Path.of(System.getProperty("java.io.tmpdir"), file.getFilename()).toString());
tempZipPath.getParentFile().mkdirs();
try {
FileUtils.copyInputStreamToFile(file.getContent(), tempZipPath);
} catch (IOException e) {
logger.error("Exception uploading settings file!");
e.printStackTrace();
}
ConfigManager.saveUploadedSettingsZip(tempZipPath);
// restartDevice();
} else {
logger.error("Couldn't read uploaded settings ZIP! Ignoring.");
}
}
/** Parses and saves camera settings (FOV and tilt) to the current camera. */
public static void onCameraSettings(Context context) {
return;
@SuppressWarnings("unchecked")
public static void onGeneralSettings(Context context) throws JsonProcessingException {
Map<String, Object> map =
(Map<String, Object>) kObjectMapper.readValue(context.body(), Map.class);
var networking =
(Map<String, Object>)
map.get("networkSettings"); // teamNumber (int), supported (bool), connectionType (int),
// staticIp (str), netmask (str), gateway (str), hostname (str)
var lighting =
(Map<String, Object>) map.get("lighting"); // supported (true/false), brightness (int)
// TODO do stuff with lighting
var networkConfig = NetworkConfig.fromHashMap(networking);
ConfigManager.getInstance().setNetworkSettings(networkConfig);
ConfigManager.getInstance().save();
NetworkManager.getInstance().reinitialize();
NetworkTablesManager.setClientMode(null); // TODO
logger.info("Responding to general settings with http 200");
context.status(200);
}
/** Duplicates the selected camera */
public static void onDuplicatePipeline(Context context) {
return;
@SuppressWarnings("unchecked")
public static void onCameraSettingsSave(Context context) {
try {
var settingsAndIndex = kObjectMapper.readValue(context.body(), Map.class);
logger.info("Got cam setting json from frontend!\n" + settingsAndIndex.toString());
var settings = (HashMap<String, Object>) settingsAndIndex.get("settings");
int index = (Integer) settingsAndIndex.get("index");
// The only settings we actually care about are FOV and pitch
var fov = Double.parseDouble(settings.get("fov").toString());
var pitch =
Rotation2d.fromDegrees(Double.parseDouble(settings.get("tiltDegrees").toString()));
logger.info(
String.format(
"Setting camera %s's fov to %s w/pitch %s", index, fov, pitch.getDegrees()));
var module = VisionModuleManager.getInstance().getModule(index);
module.setFovAndPitch(fov, pitch);
module.saveModule();
} catch (JsonProcessingException e) {
logger.error("Got invalid camera setting JSON from frontend!");
e.printStackTrace();
}
}
public static void onCalibrationStart(Context context) {
return;
public static void onSettingsDownload(Context ctx) {
logger.info("exporting settings to download...");
try {
var zip = ConfigManager.getInstance().getSettingsFolderAsZip();
var stream = new FileInputStream(zip);
logger.info("Uploading settings with size " + stream.available());
ctx.result(stream);
ctx.contentType("application/zip");
ctx.header("Content-Disposition: attachment; filename=\"photonvision-settings-export.zip\"");
ctx.status(200);
} catch (IOException e) {
e.printStackTrace();
ctx.status(501);
logger.error("Got bad recode from zip to byte");
}
}
public static void onSnapshot(Context context) {
return;
public static void onCalibrationEnd(Context ctx) {
var index = Integer.parseInt(ctx.body());
var calData = VisionModuleManager.getInstance().getModule(index).endCalibration();
if (calData == null) {
ctx.status(500);
return;
}
ctx.result(String.valueOf(calData.standardDeviation));
ctx.status(200);
}
public static void onCalibrationEnding(Context context) {
return;
public static void restartDevice(Context ctx) {
ctx.status(HardwareManager.getInstance().restartDevice() ? 200 : 500);
}
/** Parses and saves the current 3d settings to the current pipeline. */
public static void onPnpModel(Context context) {
return;
}
public static void onInstallOrUpdate(Context context) {
return;
/**
* Note that this doesn't actually restart the program itself -- instead, it relies on systemd or
* an equivalent.
*/
public static void restartProgram(Context ctx) {
ctx.status(200);
System.exit(0);
}
}