mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Added saving for selected pipeline
This commit is contained in:
@@ -23,7 +23,7 @@ public class SettingsManager {
|
||||
private static SettingsManager instance;
|
||||
|
||||
private SettingsManager() {
|
||||
InitiateGeneralSettings();
|
||||
InitiateSavedSettings();
|
||||
InitiateCamerasInfo();
|
||||
InitiateUsbCameras();
|
||||
InitiateCameras();
|
||||
@@ -57,9 +57,11 @@ public class SettingsManager {
|
||||
private Path CamsPath = Paths.get(SettingsPath.toString(), "Cams");
|
||||
|
||||
|
||||
private void InitiateGeneralSettings() {
|
||||
private void InitiateSavedSettings() {
|
||||
CheckPath(SettingsPath);
|
||||
try {
|
||||
CamerasCurrentPipeline = new Gson().fromJson(new FileReader(Paths.get(SettingsPath.toString(),"SelectedPipelines.json").toString()),HashMap.class);
|
||||
// CamerasCurrentPipeline = new JSONArray(Paths.get(SettingsPath.toString(),"SelectedPipelines.json")).toList();
|
||||
GeneralSettings = new Gson().fromJson(new FileReader(Paths.get(SettingsPath.toString(), "Settings.json").toString()), com.chameleonvision.vision.GeneralSettings.class);
|
||||
} catch (FileNotFoundException e) {
|
||||
GeneralSettings = new GeneralSettings();
|
||||
@@ -152,16 +154,13 @@ public class SettingsManager {
|
||||
cam.FOV = 60.8;
|
||||
Cameras.put(CameraName, cam);
|
||||
|
||||
CreateNewPipeline(null, CameraName);
|
||||
CreateNewPipeline(null, CameraName);//Created 2 pipeline for testing TODO add a create pipeline button
|
||||
CreateNewPipeline(null,cam);
|
||||
CreateNewPipeline(null,cam);//Created 2 pipeline for testing TODO add a create pipeline button
|
||||
CamerasCurrentPipeline.put(CameraName,"pipeline0");//sets pipeline0 as the default pipeline
|
||||
|
||||
}
|
||||
|
||||
private void CreateNewPipeline(String PipeName, String CamName) {
|
||||
if (CamName == null) {
|
||||
CamName = GeneralSettings.curr_camera;
|
||||
}
|
||||
var cam = Cameras.get(CamName);
|
||||
public void CreateNewPipeline(String PipeName,Camera cam) {
|
||||
if (PipeName == null) {
|
||||
var suffix = 0;
|
||||
PipeName = "pipeline" + suffix;
|
||||
@@ -248,6 +247,7 @@ public class SettingsManager {
|
||||
public void SaveSettings() {
|
||||
SaveCameras();
|
||||
SaveGeneralSettings();
|
||||
SaveSelectedPipelines();
|
||||
}
|
||||
|
||||
private void SaveCameras() {
|
||||
@@ -266,7 +266,6 @@ public class SettingsManager {
|
||||
|
||||
private void SaveGeneralSettings() {
|
||||
try {
|
||||
Gson gson = new Gson();
|
||||
FileWriter writer = new FileWriter(Paths.get(SettingsPath.toString(), "Settings.json").toString());
|
||||
new Gson().toJson(GeneralSettings, writer);
|
||||
writer.flush();
|
||||
@@ -276,5 +275,15 @@ public class SettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveSelectedPipelines() {
|
||||
try {
|
||||
FileWriter writer = new FileWriter(Paths.get(SettingsPath.toString(), "SelectedPipelines.json").toString());
|
||||
new Gson().toJson(CamerasCurrentPipeline, writer);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,44 +14,46 @@ import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class CameraProcess implements Runnable {
|
||||
private String CameraName;
|
||||
|
||||
private CameraServer cs = CameraServer.getInstance();
|
||||
private NetworkTableEntry ntPipelineEntry, ntDriverModeEntry,ntYawEntry,ntPitchEntry,ntDistanceEntry,ntTimeStampEntry,ntValidEntry;
|
||||
private NetworkTableEntry ntPipelineEntry, ntDriverModeEntry, ntYawEntry, ntPitchEntry, ntDistanceEntry, ntTimeStampEntry, ntValidEntry;
|
||||
|
||||
private MemoryManager memManager = new MemoryManager(125);
|
||||
|
||||
private int imgWidth, imgHeight;
|
||||
private void ChangeCameraValues(int Exposure, int Brightness){
|
||||
|
||||
private void ChangeCameraValues(int Exposure, int Brightness) {
|
||||
SettingsManager.getInstance().UsbCameras.get(CameraName).setBrightness(Brightness);
|
||||
SettingsManager.getInstance().UsbCameras.get(CameraName).setExposureManual(Exposure);
|
||||
}
|
||||
private void DriverModeListener(EntryNotification entryNotification){
|
||||
if (entryNotification.value.getBoolean()){
|
||||
ChangeCameraValues(25,15);
|
||||
} else{
|
||||
|
||||
private void DriverModeListener(EntryNotification entryNotification) {
|
||||
if (entryNotification.value.getBoolean()) {
|
||||
ChangeCameraValues(25, 15);
|
||||
} else {
|
||||
Pipeline pipeline = SettingsManager.Cameras.get(CameraName).pipelines.get(SettingsManager.CamerasCurrentPipeline.get(CameraName));
|
||||
ChangeCameraValues(pipeline.exposure, pipeline.brightness);
|
||||
}
|
||||
}
|
||||
private void PipelineListener(EntryNotification entryNotification){
|
||||
if (SettingsManager.Cameras.get(CameraName).pipelines.containsKey(entryNotification.value.getString())){
|
||||
SettingsManager.CamerasCurrentPipeline.put(CameraName,entryNotification.value.getString());
|
||||
|
||||
private void PipelineListener(EntryNotification entryNotification) {
|
||||
if (SettingsManager.Cameras.get(CameraName).pipelines.containsKey(entryNotification.value.getString())) {
|
||||
SettingsManager.CamerasCurrentPipeline.put(CameraName, entryNotification.value.getString());
|
||||
Pipeline pipeline = SettingsManager.Cameras.get(CameraName).pipelines.get(SettingsManager.CamerasCurrentPipeline.get(CameraName));
|
||||
ChangeCameraValues(pipeline.exposure, pipeline.brightness);
|
||||
//TODO Send Pipeline change using websocket to client
|
||||
} else{
|
||||
} else {
|
||||
ntPipelineEntry.setString(SettingsManager.CamerasCurrentPipeline.get(CameraName));
|
||||
}
|
||||
}
|
||||
|
||||
public CameraProcess(String CameraName) {
|
||||
this.CameraName = CameraName;
|
||||
|
||||
// add pipeline
|
||||
SettingsManager.CamerasCurrentPipeline.put(CameraName, SettingsManager.Cameras.get(CameraName).pipelines.keySet().toArray()[0].toString());
|
||||
|
||||
// NetworkTables
|
||||
NetworkTable ntTable = NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + CameraName);
|
||||
ntPipelineEntry = ntTable.getEntry("Pipeline");
|
||||
@@ -93,7 +95,7 @@ public class CameraProcess implements Runnable {
|
||||
double processTimeMs;
|
||||
double fps;
|
||||
//camera results
|
||||
double CalibratedX,CalibratedY , Pitch, Yaw;
|
||||
double CalibratedX, CalibratedY, Pitch, Yaw;
|
||||
boolean isValid;
|
||||
|
||||
while (!Thread.interrupted()) {
|
||||
@@ -103,6 +105,7 @@ public class CameraProcess implements Runnable {
|
||||
|
||||
currentPipeline = SettingsManager.Cameras.get(CameraName).pipelines.get(SettingsManager.CamerasCurrentPipeline.get(CameraName));
|
||||
|
||||
// System.out.println(SettingsManager.CamerasCurrentPipeline.get(CameraName));
|
||||
// start fps counter right before grabbing input frame
|
||||
startTime = System.nanoTime();
|
||||
cv_sink.grabFrame(inputMat);
|
||||
@@ -128,14 +131,14 @@ public class CameraProcess implements Runnable {
|
||||
GroupedContours = visionProcess.GroupTargets(FilteredContours, currentPipeline.target_intersection, currentPipeline.target_group);
|
||||
if (GroupedContours.size() > 0) {
|
||||
var finalRect = visionProcess.SortTargetsToOne(GroupedContours, currentPipeline.sort_mode);
|
||||
if (!currentPipeline.is_calibrated){
|
||||
if (!currentPipeline.is_calibrated) {
|
||||
CalibratedX = camVals.CenterX;
|
||||
CalibratedY = camVals.CenterY;
|
||||
} else{
|
||||
CalibratedX = (finalRect.center.y - currentPipeline.B) / currentPipeline.M;
|
||||
CalibratedY = finalRect.center.x * currentPipeline.M + currentPipeline.B;
|
||||
Pitch = camVals.CalculatePitch(finalRect.center.y, CalibratedY);
|
||||
Yaw = camVals.CalculateYaw(finalRect.center.x, CalibratedX);
|
||||
} else {
|
||||
CalibratedX = (finalRect.center.y - currentPipeline.B) / currentPipeline.M;
|
||||
CalibratedY = finalRect.center.x * currentPipeline.M + currentPipeline.B;
|
||||
Pitch = camVals.CalculatePitch(finalRect.center.y, CalibratedY);
|
||||
Yaw = camVals.CalculateYaw(finalRect.center.x, CalibratedX);
|
||||
}
|
||||
isValid = true;
|
||||
// Send calc using networktables
|
||||
@@ -148,7 +151,7 @@ public class CameraProcess implements Runnable {
|
||||
Imgproc.drawContours(outputMat, a, 0, contourColor, 3);
|
||||
}
|
||||
|
||||
} else{
|
||||
} else {
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
@@ -158,7 +161,7 @@ public class CameraProcess implements Runnable {
|
||||
// calculate FPS after publishing output frame
|
||||
processTimeMs = (System.nanoTime() - startTime) * 1e-6;
|
||||
fps = 1000 / processTimeMs;
|
||||
System.out.printf("%s Process time: %fms, FPS: %.2f, FoundContours: %d, FilteredContours: %d, GroupedContours: %d\n",CameraName ,processTimeMs, fps, FoundContours.size(), FilteredContours.size(), GroupedContours.size());
|
||||
// System.out.printf("%s Process time: %fms, FPS: %.2f, FoundContours: %d, FilteredContours: %d, GroupedContours: %d\n",CameraName ,processTimeMs, fps, FoundContours.size(), FilteredContours.size(), GroupedContours.size());
|
||||
|
||||
inputMat.release();
|
||||
hsvThreshMat.release();
|
||||
|
||||
@@ -2,9 +2,7 @@ package com.chameleonvision.web;
|
||||
|
||||
import com.chameleonvision.NoCameraException;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.GeneralSettings;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.google.gson.JsonObject;
|
||||
import edu.wpi.cscore.VideoException;
|
||||
import io.javalin.Javalin;
|
||||
import io.javalin.websocket.WsContext;
|
||||
|
||||
@@ -34,8 +32,7 @@ public class Server {
|
||||
SettingsManager.getInstance().SaveSettings();
|
||||
});
|
||||
ws.onMessage(ctx -> {
|
||||
// System.out.println(SettingsManager.getInstance().GetCurrentPipeline().);
|
||||
broadcastMessage(ctx, ctx.message());
|
||||
broadcastMessage(ctx.message(), ctx);
|
||||
JSONObject jsonObject = new JSONObject(ctx.message());
|
||||
String key = null;
|
||||
var jsonKeySetArray = jsonObject.keySet().toArray();
|
||||
@@ -47,7 +44,7 @@ public class Server {
|
||||
if (key == null) return;
|
||||
Object value = jsonObject.get(key);
|
||||
// System.out.printf("Got websocket json data: [%s, %s]\n", key, value);
|
||||
if (!setField(SettingsManager.getInstance().GetCurrentPipeline(), key, value)) {
|
||||
if (!allFieldsToMap(SettingsManager.getInstance().GetCurrentPipeline()).containsKey(key)) {
|
||||
//If field not in pipeline
|
||||
switch (key) {
|
||||
case "change_general_settings_values":
|
||||
@@ -59,13 +56,14 @@ public class Server {
|
||||
System.out.printf("Changing camera to %s\n", newCamera);
|
||||
SettingsManager.getInstance().SetCurrentCamera(newCamera);
|
||||
//broadcastMessage((Map<String, Object>) new HashMap<String, Object>(){}.put("port",SettingsManager.CameraPorts.get(SettingsManager.GeneralSettings.curr_camera)));
|
||||
//broadcastMessage(ctx, SettingsManager.getInstance().GetCurrentCamera()); //TODO CHECK JSON FOR CAMERA CHANGE
|
||||
broadcastMessage(SettingsManager.getInstance().GetCurrentCamera()); //TODO CHECK JSON FOR CAMERA CHANGE
|
||||
break;
|
||||
case "curr_pipeline":
|
||||
String newPipeline = (String) value;
|
||||
System.out.printf("Changing pipeline to %s\n", newPipeline);
|
||||
SettingsManager.getInstance().SetCurrentPipeline(newPipeline);
|
||||
SettingsManager.CamerasCurrentPipeline.put(SettingsManager.GeneralSettings.curr_camera, newPipeline);
|
||||
broadcastMessage(allFieldsToMap(SettingsManager.getInstance().GetCurrentPipeline()));
|
||||
break;
|
||||
case "resolution":
|
||||
int newResolution = (int) value;
|
||||
@@ -76,7 +74,7 @@ public class Server {
|
||||
break;
|
||||
case "fov":
|
||||
double newFov = (double) value;
|
||||
System.out.printf("Changing FOV to %d\n", newFov);
|
||||
System.out.printf("Changing FOV to %f\n", newFov);
|
||||
SettingsManager.getInstance().GetCurrentCamera().FOV = newFov;
|
||||
SettingsManager.getInstance().SaveSettings();
|
||||
break;
|
||||
@@ -84,21 +82,29 @@ public class Server {
|
||||
System.out.printf("Unexpected value from websocket: [%s, %s]\n", key, value);
|
||||
break;
|
||||
}
|
||||
} else { //
|
||||
} else {
|
||||
setField(SettingsManager.getInstance().GetCurrentPipeline(), key, value);
|
||||
//Special cases for exposure and brightness
|
||||
//TODO maybe add listener for value changes instead of this special case
|
||||
switch (key) {
|
||||
case "exposure":
|
||||
int newExposure = (int) value;
|
||||
System.out.printf("Changing exposure to %d\n", newExposure);
|
||||
SettingsManager.getInstance().GetCurrentPipeline().exposure = newExposure;
|
||||
SettingsManager.getInstance().GetCurrentUsbCamera().setExposureManual(newExposure);
|
||||
SettingsManager.getInstance().SaveSettings();
|
||||
try {
|
||||
SettingsManager.getInstance().GetCurrentUsbCamera().setExposureManual(newExposure);
|
||||
}
|
||||
catch ( VideoException e)
|
||||
{
|
||||
System.out.println("Exposure changes is not supported on your webcam/webcam's driver");
|
||||
}
|
||||
//TODO check if this crash occurs on linux
|
||||
break;
|
||||
case "brightness":
|
||||
int newBrightness = (int) value;
|
||||
System.out.printf("Changing brightness to %d\n", newBrightness);
|
||||
SettingsManager.getInstance().GetCurrentPipeline().brightness = newBrightness;
|
||||
SettingsManager.getInstance().GetCurrentUsbCamera().setBrightness(newBrightness);
|
||||
SettingsManager.getInstance().SaveSettings();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -107,14 +113,11 @@ public class Server {
|
||||
app.start(port);
|
||||
}
|
||||
|
||||
|
||||
public static boolean setField(Object obj, String fieldName, Object value) {
|
||||
boolean successful = false;
|
||||
private static void setField(Object obj, String fieldName, Object value) {
|
||||
try {
|
||||
Field[] fields = obj.getClass().getFields();
|
||||
for (Field f : fields) {
|
||||
if (f.getName().equals(fieldName)) {
|
||||
successful = true;
|
||||
if (BeanUtils.isSimpleValueType(value.getClass())) {
|
||||
f.set(obj, value);
|
||||
} else if (value.getClass() == JSONArray.class) {
|
||||
@@ -123,33 +126,20 @@ public class Server {
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
return false;
|
||||
System.out.println("IllegalAccessException ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
||||
public static boolean setFields(Object obj, JSONObject data) {
|
||||
boolean successful = false;
|
||||
try {
|
||||
Field[] fields = obj.getClass().getFields();
|
||||
for (Field f : fields) {
|
||||
if (data.has(f.getName())) {
|
||||
Object value = data.get(f.getName());
|
||||
if (BeanUtils.isSimpleValueType(value.getClass())) {
|
||||
successful = true;
|
||||
f.set(obj, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
return false;
|
||||
}
|
||||
return successful;
|
||||
private static void setFields(Object obj, JSONObject data) {
|
||||
Map<String,Object> map = data.toMap();
|
||||
map.forEach((s, o) -> setField(obj,s,o));
|
||||
}
|
||||
|
||||
public static void broadcastMessage(WsContext sendingUser, Object obj) {//TODO chekc if session id is a good way to differentiate users
|
||||
|
||||
private static void broadcastMessage(Object obj, WsContext userToSkip) {//TODO chekc if session id is a good way to differentiate users
|
||||
for (var user : users) {
|
||||
if (sendingUser!=null&& user.getSessionId().equals(sendingUser.getSessionId())) {
|
||||
if (userToSkip != null && user.getSessionId().equals(userToSkip.getSessionId())) {
|
||||
continue;
|
||||
}
|
||||
if (obj.getClass() == String.class)
|
||||
@@ -161,7 +151,12 @@ public class Server {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addAllFieldsToMap(Map<String, Object> map, Object obj) {
|
||||
private static void broadcastMessage(Object obj) {
|
||||
broadcastMessage(obj, null);//Broadcasts the message to ever user
|
||||
}
|
||||
|
||||
private static Map<String, Object> allFieldsToMap(Object obj) {
|
||||
Map map = new HashMap<>();
|
||||
try {
|
||||
Field[] fields = obj.getClass().getFields();
|
||||
for (Field field : fields)
|
||||
@@ -169,15 +164,16 @@ public class Server {
|
||||
} catch (IllegalAccessException e) {
|
||||
System.err.println("Illegal Access error:" + e.getStackTrace().toString());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static void sendFullSettings() {
|
||||
Map<String, Object> fullSettings = new HashMap<>();
|
||||
//General settings
|
||||
addAllFieldsToMap(fullSettings, SettingsManager.GeneralSettings);
|
||||
fullSettings.putAll(allFieldsToMap(SettingsManager.GeneralSettings));
|
||||
fullSettings.put("cameraList", SettingsManager.Cameras.keySet());
|
||||
try {
|
||||
addAllFieldsToMap(fullSettings, SettingsManager.getInstance().GetCurrentPipeline());
|
||||
fullSettings.putAll(allFieldsToMap(SettingsManager.getInstance().GetCurrentPipeline()));
|
||||
fullSettings.put("pipelineList", SettingsManager.getInstance().GetCurrentCamera().pipelines.keySet());
|
||||
fullSettings.put("resolutionList", SettingsManager.getInstance().GetResolutionList());
|
||||
fullSettings.put("resolution", SettingsManager.getInstance().GetCurrentCamera().resolution);
|
||||
@@ -187,7 +183,7 @@ public class Server {
|
||||
System.err.println("No camera found!");
|
||||
//TODO: add message to ui to inform that there are no cameras
|
||||
}
|
||||
broadcastMessage(null, fullSettings);
|
||||
broadcastMessage(fullSettings);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user