mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Added driver mode exposure and brightness
This commit is contained in:
@@ -4,6 +4,7 @@ import com.chameleonvision.Main;
|
||||
import com.chameleonvision.settings.Platform;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.web.Server;
|
||||
import com.chameleonvision.web.ServerHandler;
|
||||
import edu.wpi.cscore.*;
|
||||
import edu.wpi.first.cameraserver.CameraServer;
|
||||
@@ -12,10 +13,7 @@ import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import java.nio.channels.Pipe;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@@ -23,12 +21,15 @@ public class Camera {
|
||||
|
||||
private static final double DEFAULT_FOV = 60.8;
|
||||
private static final StreamDivisor DEFAULT_STREAMDIVISOR = StreamDivisor.none;
|
||||
private static final int DEFAULT_EXPOSURE = 50;
|
||||
private static final int DEFAULT_BRIGHTNESS = 50;
|
||||
private static final int MINIMUM_FPS = 30;
|
||||
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;
|
||||
|
||||
@@ -48,6 +49,11 @@ public class Camera {
|
||||
private int currentPipelineIndex;
|
||||
private List<Pipeline> pipelines;
|
||||
|
||||
//Driver mode camera settings
|
||||
public int driverExposure;
|
||||
public int driverBrightness;
|
||||
public boolean isDriver;
|
||||
|
||||
public Camera(String cameraName) {
|
||||
this(cameraName, DEFAULT_FOV);
|
||||
}
|
||||
@@ -61,18 +67,18 @@ public class Camera {
|
||||
}
|
||||
|
||||
public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, StreamDivisor divisor) {
|
||||
this(cameraName, usbCamInfo, fov, new ArrayList<>(), 0, divisor);
|
||||
this(cameraName, usbCamInfo, fov, new ArrayList<>(), 0, divisor, DEFAULT_EXPOSURE, DEFAULT_BRIGHTNESS);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, double fov, List<Pipeline> pipelines, int videoModeIndex, StreamDivisor divisor) {
|
||||
this(cameraName, CameraManager.AllUsbCameraInfosByName.get(cameraName), fov, pipelines, videoModeIndex, divisor);
|
||||
public Camera(String cameraName, double fov, List<Pipeline> pipelines, int videoModeIndex, StreamDivisor divisor, int driverExposure, int driverBrightness) {
|
||||
this(cameraName, CameraManager.AllUsbCameraInfosByName.get(cameraName), fov, pipelines, videoModeIndex, divisor, driverExposure, driverBrightness);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, double fov, int videoModeIndex, StreamDivisor divisor) {
|
||||
this(cameraName, fov, new ArrayList<>(), videoModeIndex, divisor);
|
||||
public Camera(String cameraName, double fov, int videoModeIndex, StreamDivisor divisor, int driverExposure, int driverBrightness) {
|
||||
this(cameraName, fov, new ArrayList<>(), videoModeIndex, divisor, driverExposure, driverBrightness);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, List<Pipeline> pipelines, int videoModeIndex, StreamDivisor divisor) {
|
||||
public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, List<Pipeline> pipelines, int videoModeIndex, StreamDivisor divisor, int driverExposure, int driverBrightness) {
|
||||
FOV = fov;
|
||||
name = cameraName;
|
||||
|
||||
@@ -115,6 +121,9 @@ public class Camera {
|
||||
|
||||
cvSink = cs.getVideo(UsbCam);
|
||||
cvSource = cs.putVideo(name, camVals.ImageWidth, camVals.ImageHeight);
|
||||
isDriver = false;
|
||||
this.driverBrightness=driverBrightness;
|
||||
this.driverExposure=driverExposure;
|
||||
}
|
||||
|
||||
VideoMode[] getAvailableVideoModes() {
|
||||
@@ -217,22 +226,55 @@ public class Camera {
|
||||
camVals = new CameraValues(this);
|
||||
}
|
||||
|
||||
public void setDriverMode(boolean state)
|
||||
{
|
||||
Map<String,Integer> data = new HashMap<>();
|
||||
isDriver=state;
|
||||
if(isDriver){
|
||||
UsbCam.setBrightness(driverBrightness);
|
||||
UsbCam.setBrightness(driverBrightness);
|
||||
try{UsbCam.setExposureManual(driverExposure);}
|
||||
catch (VideoException e)
|
||||
{
|
||||
System.out.println("Exposure change isnt supported");
|
||||
}
|
||||
data.put("brightness",getBrightness());
|
||||
data.put("exposure",driverExposure);
|
||||
}
|
||||
else{
|
||||
UsbCam.setBrightness(getCurrentPipeline().brightness);
|
||||
UsbCam.setBrightness(getCurrentPipeline().brightness);
|
||||
try{UsbCam.setExposureManual(getCurrentPipeline().exposure);}
|
||||
catch (VideoException e)
|
||||
{
|
||||
System.out.println("Exposure change isnt supported");
|
||||
}
|
||||
data.put("brightness",getBrightness());
|
||||
data.put("exposure",getCurrentPipeline().exposure);
|
||||
}
|
||||
ServerHandler.broadcastMessage(data);
|
||||
}
|
||||
|
||||
public int getBrightness() {
|
||||
return getCurrentPipeline().brightness;
|
||||
return UsbCam.getBrightness();
|
||||
}
|
||||
|
||||
public void setBrightness(int brightness) {
|
||||
getCurrentPipeline().brightness = brightness;
|
||||
if (isDriver)
|
||||
driverBrightness=brightness;
|
||||
else
|
||||
getCurrentPipeline().brightness = brightness;
|
||||
UsbCam.setBrightness(brightness);
|
||||
}
|
||||
|
||||
public void setExposure(int exposure) {
|
||||
getCurrentPipeline().exposure = exposure;
|
||||
if (isDriver)
|
||||
driverExposure=exposure;
|
||||
else
|
||||
getCurrentPipeline().exposure = exposure;
|
||||
try {
|
||||
UsbCam.setExposureManual(exposure);
|
||||
}
|
||||
catch (VideoException e)
|
||||
{
|
||||
} catch (VideoException e) {
|
||||
System.err.println("Camera Does not support exposure change");
|
||||
}
|
||||
}
|
||||
@@ -259,7 +301,7 @@ public class Camera {
|
||||
|
||||
public void setNickname(String newNickname) {
|
||||
//Deletes old camera nt table
|
||||
NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + this.nickname).getInstance().deleteAllEntries();
|
||||
NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + this.nickname).getInstance().deleteAllEntries();
|
||||
nickname = newNickname;
|
||||
if (CameraManager.AllVisionProcessesByName.containsKey(this.name)) {
|
||||
NetworkTable newNT = NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + this.nickname);
|
||||
|
||||
@@ -17,26 +17,37 @@ import java.util.List;
|
||||
public class CameraDeserializer implements JsonDeserializer<Camera> {
|
||||
@Override
|
||||
public Camera deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
|
||||
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");
|
||||
List<Pipeline> actualPipelines = new ArrayList<>();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
TypeFactory typeFactory = mapper.getTypeFactory();
|
||||
JavaType arrayType = typeFactory.constructCollectionType(List.class, Pipeline.class);
|
||||
try {
|
||||
actualPipelines = mapper.readValue(pipelines.toString(), arrayType);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
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 driverExposure = jsonObj.get("driverExposure").getAsInt();
|
||||
var driverBrightness = jsonObj.get("driverBrightness").getAsInt();
|
||||
var divisor = StreamDivisor.values()[jsonObj.get("streamDivisor").getAsInt()];
|
||||
|
||||
var newCamera = actualPipelines != null ? new Camera(camName, camFOV, actualPipelines, videoModeIndex, divisor) : new Camera(camName, camFOV, videoModeIndex, divisor);
|
||||
newCamera.setNickname(camNickname != null ? camNickname : "");
|
||||
return newCamera;
|
||||
var pipelines = jsonObj.get("pipelines");
|
||||
List<Pipeline> actualPipelines = new ArrayList<>();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
TypeFactory typeFactory = mapper.getTypeFactory();
|
||||
JavaType arrayType = typeFactory.constructCollectionType(List.class, Pipeline.class);
|
||||
try {
|
||||
actualPipelines = mapper.readValue(pipelines.toString(), arrayType);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
var newCamera = actualPipelines != null ? new Camera(camName, camFOV, actualPipelines, videoModeIndex, divisor, driverExposure, driverBrightness) : new Camera(camName, camFOV, videoModeIndex, divisor, driverExposure, driverBrightness);
|
||||
newCamera.setNickname(camNickname != null ? camNickname : "");
|
||||
return newCamera;
|
||||
}
|
||||
catch (NullPointerException e)
|
||||
{
|
||||
System.err.println("Error while reading json, value doesnt exist!");
|
||||
System.err.println("Try to delete the camera settings in settings/cameras/YOURCAMERA.json");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,12 @@ public class CameraSerializer implements JsonSerializer<Camera> {
|
||||
obj.addProperty("name", camera.name);
|
||||
obj.addProperty("nickname", camera.getNickname());
|
||||
obj.addProperty("streamDivisor", camera.getStreamDivisor().ordinal());
|
||||
|
||||
var pipelines = context.serialize(camera.getPipelines());
|
||||
obj.add("pipelines", pipelines);
|
||||
|
||||
obj.addProperty("resolution", camera.getVideoModeIndex());
|
||||
obj.add("camVideoMode", context.serialize(camera.getVideoMode()));
|
||||
|
||||
obj.add("driverExposure",context.serialize(camera.driverExposure));
|
||||
obj.add("driverBrightness",context.serialize(camera.driverBrightness));
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +49,6 @@ public class VisionProcess implements Runnable {
|
||||
camera = processCam;
|
||||
this.cameraName = camera.name;
|
||||
|
||||
// NetworkTables
|
||||
// NetworkTable ntTable = NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + cameraName);
|
||||
// NetworkTable ntTable = camera.getNtTable();
|
||||
initNT(NetworkTableInstance.getDefault().getTable("/chameleon-vision/"+processCam.getNickname()));
|
||||
|
||||
// camera settings
|
||||
@@ -60,14 +57,7 @@ public class VisionProcess implements Runnable {
|
||||
}
|
||||
|
||||
private void driverModeListener(EntryNotification entryNotification) {
|
||||
if (entryNotification.value.getBoolean()) {
|
||||
camera.setExposure(25);
|
||||
camera.setBrightness(15);
|
||||
} else {
|
||||
Pipeline pipeline = camera.getCurrentPipeline();
|
||||
camera.setExposure(pipeline.exposure);
|
||||
camera.setBrightness(pipeline.brightness);
|
||||
}
|
||||
camera.setDriverMode(entryNotification.value.getBoolean());
|
||||
}
|
||||
|
||||
private void pipelineListener(EntryNotification entryNotification) {
|
||||
@@ -158,22 +148,22 @@ public class VisionProcess implements Runnable {
|
||||
var finalRect = cvProcess.sortTargetsToOne(groupedContours, currentPipeline.sortMode);
|
||||
pipelineResult.RawPoint = finalRect;
|
||||
pipelineResult.IsValid = true;
|
||||
switch (currentPipeline.calibrationMode){
|
||||
case None:
|
||||
///use the center of the camera to find the pitch and yaw difference
|
||||
pipelineResult.CalibratedX = camera.getCamVals().CenterX;
|
||||
pipelineResult.CalibratedY = camera.getCamVals().CenterY;
|
||||
break;
|
||||
case Single:
|
||||
// use the static point as a calibration method instead of the center
|
||||
pipelineResult.CalibratedX = currentPipeline.point.get(0).doubleValue();
|
||||
pipelineResult.CalibratedY = currentPipeline.point.get(1).doubleValue();
|
||||
break;
|
||||
case Dual:
|
||||
// use the calculated line to find the difference in length between the point and the line
|
||||
pipelineResult.CalibratedX = (finalRect.center.y - currentPipeline.b) / currentPipeline.m;
|
||||
pipelineResult.CalibratedY = (finalRect.center.x * currentPipeline.m) + currentPipeline.b;
|
||||
break;
|
||||
switch (currentPipeline.calibrationMode) {
|
||||
case None:
|
||||
///use the center of the camera to find the pitch and yaw difference
|
||||
pipelineResult.CalibratedX = camera.getCamVals().CenterX;
|
||||
pipelineResult.CalibratedY = camera.getCamVals().CenterY;
|
||||
break;
|
||||
case Single:
|
||||
// use the static point as a calibration method instead of the center
|
||||
pipelineResult.CalibratedX = currentPipeline.point.get(0).doubleValue();
|
||||
pipelineResult.CalibratedY = currentPipeline.point.get(1).doubleValue();
|
||||
break;
|
||||
case Dual:
|
||||
// use the calculated line to find the difference in length between the point and the line
|
||||
pipelineResult.CalibratedX = (finalRect.center.y - currentPipeline.b) / currentPipeline.m;
|
||||
pipelineResult.CalibratedY = (finalRect.center.x * currentPipeline.m) + currentPipeline.b;
|
||||
break;
|
||||
}
|
||||
pipelineResult.Pitch = camera.getCamVals().CalculatePitch(finalRect.center.y, pipelineResult.CalibratedY);
|
||||
pipelineResult.Yaw = camera.getCamVals().CalculateYaw(finalRect.center.x, pipelineResult.CalibratedX);
|
||||
@@ -248,7 +238,7 @@ public class VisionProcess implements Runnable {
|
||||
point.put("calculated", calculated);
|
||||
point.put("rawPoint", center);
|
||||
WebSend.put("point", point);
|
||||
ServerHandler.broadcastMessage(WebSend);
|
||||
// ServerHandler.broadcastMessage(WebSend);
|
||||
}
|
||||
|
||||
cameraProcess.updateFrame(streamOutputMat);
|
||||
@@ -265,26 +255,26 @@ public class VisionProcess implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the old value change listeners
|
||||
* calls {@link #initNT}
|
||||
* @param newTable passed to {@link #initNT}
|
||||
* Removes the old value change listeners
|
||||
* calls {@link #initNT}
|
||||
*
|
||||
* @param newTable passed to {@link #initNT}
|
||||
*/
|
||||
public void resetNT(NetworkTable newTable)
|
||||
{
|
||||
public void resetNT(NetworkTable newTable) {
|
||||
ntDriverModeEntry.removeListener(ntDriveModeListenerID);
|
||||
ntPipelineEntry.removeListener(ntPipelineListenerID);
|
||||
initNT(newTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebases the writing location for the vision process - pipeline output
|
||||
* Rebases the writing location for the vision process - pipeline output
|
||||
*
|
||||
* @param newTable the new writing location
|
||||
*/
|
||||
private void initNT(NetworkTable newTable)
|
||||
{
|
||||
private void initNT(NetworkTable newTable) {
|
||||
ntPipelineEntry = newTable.getEntry("pipeline");
|
||||
ntDriverModeEntry = newTable.getEntry("driver_mode");
|
||||
ntPitchEntry = newTable.getEntry("pitch");
|
||||
|
||||
Reference in New Issue
Block a user