mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-19 00:41:41 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user