mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Added command handling for camera name, pipeline name pipeline duplication
This commit is contained in:
@@ -23,4 +23,5 @@ public class Pipeline {
|
||||
public double m = 1;
|
||||
public double b = 0;
|
||||
public boolean isCalibrated = false;
|
||||
public String nickname;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.chameleonvision.vision.camera;
|
||||
|
||||
import com.chameleonvision.Main;
|
||||
import com.chameleonvision.settings.Platform;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.web.ServerHandler;
|
||||
import edu.wpi.cscore.*;
|
||||
@@ -9,6 +11,8 @@ import org.opencv.core.Mat;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Camera {
|
||||
@@ -19,10 +23,13 @@ public class Camera {
|
||||
private static final int MINIMUM_WIDTH = 320;
|
||||
private static final int MINIMUM_HEIGHT = 200;
|
||||
private static final int MAX_INIT_MS = 1500;
|
||||
private static final List<VideoMode.PixelFormat> ALLOWED_PIXEL_FORMATS = Arrays.asList(VideoMode.PixelFormat.kYUYV, VideoMode.PixelFormat.kMJPEG);
|
||||
|
||||
public final String name;
|
||||
public final String path;
|
||||
|
||||
private String nickname;
|
||||
|
||||
private final UsbCamera UsbCam;
|
||||
private final VideoMode[] availableVideoModes;
|
||||
|
||||
@@ -64,7 +71,14 @@ public class Camera {
|
||||
public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, HashMap<Integer, Pipeline> pipelines, int videoModeIndex, StreamDivisor divisor) {
|
||||
FOV = fov;
|
||||
name = cameraName;
|
||||
path = usbCamInfo.path;
|
||||
|
||||
if (Platform.getCurrentPlatform().isWindows()) {
|
||||
path = usbCamInfo.path;
|
||||
} else {
|
||||
var truePath = Arrays.stream(usbCamInfo.otherPaths).filter(x -> x.contains("/dev/v4l/by-path")).findFirst();
|
||||
path = truePath.isPresent() ? truePath.toString() : null;
|
||||
}
|
||||
|
||||
streamDivisor = divisor;
|
||||
UsbCam = new UsbCamera(name, path);
|
||||
|
||||
@@ -83,7 +97,8 @@ public class Camera {
|
||||
System.out.printf("Camera initialized in %.2fms\n", initTimeMs);
|
||||
}
|
||||
var trueVideoModes = UsbCam.enumerateVideoModes();
|
||||
availableVideoModes = Arrays.stream(trueVideoModes).filter(v -> v.fps >= MINIMUM_FPS && v.width >= MINIMUM_WIDTH && v.height >= MINIMUM_HEIGHT).toArray(VideoMode[]::new);
|
||||
availableVideoModes = Arrays.stream(trueVideoModes).filter(v ->
|
||||
v.fps >= MINIMUM_FPS && v.width >= MINIMUM_WIDTH && v.height >= MINIMUM_HEIGHT && ALLOWED_PIXEL_FORMATS.contains(v.pixelFormat)).toArray(VideoMode[]::new);
|
||||
if (availableVideoModes.length == 0) {
|
||||
System.err.println("Camera not supported!");
|
||||
throw new RuntimeException(new CameraException(CameraException.CameraExceptionType.BAD_CAMERA));
|
||||
@@ -130,17 +145,31 @@ public class Camera {
|
||||
addPipeline(pipelines.size());
|
||||
}
|
||||
|
||||
public void addPipeline(Pipeline pipeline) {
|
||||
int newPipelineIndex = pipelines.size();
|
||||
addPipeline(newPipelineIndex, pipeline);
|
||||
}
|
||||
|
||||
private void addPipeline(int pipelineNumber) {
|
||||
if (pipelines.containsKey(pipelineNumber)) return;
|
||||
pipelines.put(pipelineNumber, new Pipeline());
|
||||
}
|
||||
|
||||
private void addPipeline(int pipelineIndex, Pipeline pipeline) {
|
||||
if (pipelines.containsKey(pipelineIndex)) return;
|
||||
pipelines.put(pipelineIndex, pipeline);
|
||||
}
|
||||
|
||||
public void deleteCurrentPipeline() {
|
||||
pipelines.remove(getCurrentPipelineIndex());
|
||||
}
|
||||
|
||||
public Pipeline getCurrentPipeline() {
|
||||
return pipelines.get(currentPipelineIndex);
|
||||
return getPipelineByIndex(currentPipelineIndex);
|
||||
}
|
||||
|
||||
public Pipeline getPipelineByIndex(int pipelineIndex) {
|
||||
return pipelines.get(pipelineIndex);
|
||||
}
|
||||
|
||||
public int getCurrentPipelineIndex() {
|
||||
@@ -211,4 +240,18 @@ public class Camera {
|
||||
cvSource.putFrame(image);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getResolutionList() {
|
||||
return Arrays.stream(availableVideoModes)
|
||||
.map(res -> String.format("%sx%s@%sFPS, %s", res.width, res.height, res.fps, res.pixelFormat.toString()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void setNickname(String newNickname) {
|
||||
nickname = newNickname;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname == null ? name : nickname;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ public class CameraDeserializer implements JsonDeserializer<Camera> {
|
||||
var jsonObj = jsonElement.getAsJsonObject();
|
||||
var camFOV = jsonObj.get("FOV").getAsDouble();
|
||||
var camName = jsonObj.get("name").getAsString();
|
||||
var camNickname = jsonObj.get("nickname").getAsString();
|
||||
var videoModeIndex = jsonObj.get("resolution").getAsInt();
|
||||
var divisor = StreamDivisor.values()[jsonObj.get("streamDivisor").getAsInt()];
|
||||
|
||||
|
||||
var pipelines = jsonObj.get("pipelines");
|
||||
HashMap<Integer, Pipeline> actualPipelines = new HashMap<>();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
@@ -31,6 +31,8 @@ public class CameraDeserializer implements JsonDeserializer<Camera> {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return actualPipelines != null ? new Camera(camName, camFOV, actualPipelines, videoModeIndex,divisor) : new Camera(camName, camFOV, videoModeIndex, divisor);
|
||||
var newCamera = actualPipelines != null ? new Camera(camName, camFOV, actualPipelines, videoModeIndex, divisor) : new Camera(camName, camFOV, videoModeIndex, divisor);
|
||||
newCamera.setNickname(camNickname != null ? camNickname : "");
|
||||
return newCamera;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -22,7 +23,7 @@ public class CameraManager {
|
||||
|
||||
private static final Path CamConfigPath = Paths.get(SettingsManager.SettingsPath.toString(), "cameras");
|
||||
|
||||
private static HashMap<String, Camera> AllCamerasByName = new HashMap<>();
|
||||
private static LinkedHashMap<String, Camera> AllCamerasByName = new LinkedHashMap<>();
|
||||
private static HashMap<String, VisionProcess> AllVisionProcessesByName = new HashMap<>();
|
||||
|
||||
static HashMap<String, UsbCameraInfo> AllUsbCameraInfosByName = new HashMap<>() {{
|
||||
@@ -88,6 +89,10 @@ public class CameraManager {
|
||||
return AllCamerasByName.get(cameraName);
|
||||
}
|
||||
|
||||
public static Camera getCameraByIndex(int index) {
|
||||
return AllCamerasByName.get( (AllCamerasByName.keySet().toArray())[ index ] );
|
||||
}
|
||||
|
||||
public static Camera getCurrentCamera() throws CameraException {
|
||||
if (AllCamerasByName.size() == 0) throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA);
|
||||
var curCam = AllCamerasByName.get(SettingsManager.GeneralSettings.currentCamera);
|
||||
@@ -113,14 +118,7 @@ public class CameraManager {
|
||||
SettingsManager.updatePipelineSetting(pipelineNumber);
|
||||
}
|
||||
|
||||
public static List<String> getResolutionList() throws CameraException {
|
||||
if (!SettingsManager.GeneralSettings.currentCamera.equals("")) {
|
||||
return Arrays.stream(CameraManager.getCamera(SettingsManager.GeneralSettings.currentCamera).getAvailableVideoModes())
|
||||
.map(res -> String.format("%s X %s at %s fps using %s ", res.width, res.height, res.fps, res.pixelFormat.toString())).collect(Collectors.toList());
|
||||
}
|
||||
throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA);
|
||||
}
|
||||
public static VisionProcess getCurrentCameraProcess() throws CameraException{
|
||||
public static VisionProcess getCurrentCameraProcess() throws CameraException {
|
||||
if (!SettingsManager.GeneralSettings.currentCamera.equals("")){
|
||||
return AllVisionProcessesByName.get(SettingsManager.GeneralSettings.currentCamera);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ public class CameraSerializer implements JsonSerializer<Camera> {
|
||||
obj.addProperty("FOV", camera.getFOV());
|
||||
obj.addProperty("path", camera.path);
|
||||
obj.addProperty("name", camera.name);
|
||||
obj.addProperty("nickname", camera.getNickname());
|
||||
obj.addProperty("streamDivisor", camera.getStreamDivisor().ordinal());
|
||||
|
||||
var pipelines = context.serialize(camera.getPipelines());
|
||||
|
||||
@@ -64,23 +64,36 @@ public class ServerHandler {
|
||||
break;
|
||||
}
|
||||
case "changeCameraName": {
|
||||
// needs to be implemented
|
||||
CameraManager.getCurrentCamera().setNickname((String) entry.getValue());
|
||||
break;
|
||||
}
|
||||
case "changePipelineName": {
|
||||
// needs to be implemented
|
||||
CameraManager.getCurrentPipeline().nickname = (String) entry.getValue();
|
||||
break;
|
||||
}
|
||||
case "duplicatePipeline": {
|
||||
// needs to be implemented
|
||||
HashMap pipelineVals = (HashMap) entry.getValue();
|
||||
int pipelineIndex = (int) pipelineVals.get("pipeline");
|
||||
int cameraIndex = (int) pipelineVals.get("camera");
|
||||
|
||||
Pipeline origPipeline = CameraManager.getCurrentCamera().getPipelineByIndex(pipelineIndex);
|
||||
|
||||
if (cameraIndex != -1) {
|
||||
CameraManager.getCameraByIndex(cameraIndex).addPipeline(origPipeline);
|
||||
} else {
|
||||
CameraManager.getCurrentCamera().addPipeline(origPipeline);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "command": {
|
||||
var cam = CameraManager.getCurrentCamera();
|
||||
switch ((String) entry.getValue()) {
|
||||
case "addNewPipeline":
|
||||
CameraManager.getCurrentCamera().addPipeline();
|
||||
cam.addPipeline();
|
||||
break;
|
||||
case "deleteCurrentPipeline":
|
||||
var cam = CameraManager.getCurrentCamera();
|
||||
CameraManager.getCurrentCamera().deleteCurrentPipeline();
|
||||
CameraManager.getCurrentCamera().setCurrentPipelineIndex(cam.getCurrentPipelineIndex() - 1);
|
||||
cam.deleteCurrentPipeline();
|
||||
cam.setCurrentPipelineIndex(cam.getCurrentPipelineIndex() - 1);
|
||||
sendFullSettings();
|
||||
break;
|
||||
}
|
||||
@@ -89,11 +102,12 @@ public class ServerHandler {
|
||||
}
|
||||
case "currentCamera": {
|
||||
CameraManager.setCurrentCamera((String) entry.getValue());
|
||||
var cam = CameraManager.getCurrentCamera();
|
||||
HashMap<String, Object> tmp = new HashMap<>();
|
||||
tmp.put("pipeline", CameraManager.getCurrentCamera().getCurrentPipeline());
|
||||
tmp.put("pipelineList", CameraManager.getCurrentCamera().getPipelines().keySet());
|
||||
tmp.put("port", CameraManager.getCurrentCamera().getStreamPort());
|
||||
tmp.put("resolutionList", CameraManager.getResolutionList());
|
||||
tmp.put("pipeline", cam.getCurrentPipeline());
|
||||
tmp.put("pipelineList", cam.getPipelines().keySet());
|
||||
tmp.put("port", cam.getStreamPort());
|
||||
tmp.put("resolutionList", cam.getResolutionList());
|
||||
broadcastMessage(tmp);
|
||||
break;
|
||||
}
|
||||
@@ -212,7 +226,7 @@ public class ServerHandler {
|
||||
var currentCamera = CameraManager.getCurrentCamera();
|
||||
fullSettings.put("pipeline", getOrdinalPipeline());
|
||||
fullSettings.put("pipelineList", currentCamera.getPipelines().keySet());
|
||||
fullSettings.put("resolutionList", CameraManager.getResolutionList());
|
||||
fullSettings.put("resolutionList", currentCamera.getResolutionList());
|
||||
fullSettings.put("port", currentCamera.getStreamPort());
|
||||
} catch (CameraException | IllegalAccessException e) {
|
||||
System.err.println("No camera found!");
|
||||
|
||||
Reference in New Issue
Block a user