Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to using Absolute Exposure Range #1352

Merged
merged 40 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
66b82bd
wip - tied to libcamera PR to remove some of the hacks associated wit…
gerth2 Jun 24, 2024
9c0a322
WIP changing all camera settings to be absolute time
gerth2 Jun 26, 2024
3d43a15
bugfix
gerth2 Jun 26, 2024
b1d4d5f
picam cleanup, better lifecam support
gerth2 Jun 27, 2024
d46efd1
Further wip dynamic min/max
gerth2 Jun 27, 2024
8b4a2de
renamed things for better reflection of what it actually is
gerth2 Jun 28, 2024
71177ba
Spotless, reset index.html
gerth2 Jun 28, 2024
f52b381
Formatting cleanup, unit test cleanup (mocks for usb camera)
gerth2 Jun 28, 2024
bd5371e
More wpi format
gerth2 Jun 28, 2024
5182ff4
npm format
gerth2 Jun 28, 2024
a696e89
Cherry-Pick splitting out settables
gerth2 Jul 12, 2024
8d3d321
wip lifecam experiments, not running yet
gerth2 Jul 18, 2024
05314d4
more WIP with usb cam sources. Not yet working with lifecam after ref…
gerth2 Jul 18, 2024
909cef7
Attempting reorder, no difference
gerth2 Jul 18, 2024
4a15f27
Bugfixes. I think we're finally working acceptably with lifecams on w…
gerth2 Jul 19, 2024
e5c9cdf
Renames, improved camera-specific settables
gerth2 Jul 19, 2024
99942fd
Formatting
gerth2 Jul 19, 2024
a454295
review notes cleanup
gerth2 Jul 19, 2024
cac1646
actually use the new settables
gerth2 Jul 19, 2024
5cc620f
formatting
gerth2 Jul 19, 2024
27705ff
it ain't mmal anymore
gerth2 Jul 19, 2024
7fbb93d
Merge remote-tracking branch 'origin/master' Includes fixups to quirk…
gerth2 Jul 19, 2024
dfcc5bf
fixups for supporting unit tests
gerth2 Jul 19, 2024
6578bef
Merge branch 'master' into HEAD
gerth2 Jul 19, 2024
dfb7a2e
spotless/format
gerth2 Jul 19, 2024
4f127e5
reset index.html
gerth2 Jul 19, 2024
94324ed
aligned ts/vue
gerth2 Jul 21, 2024
3d1181b
formatting
gerth2 Jul 21, 2024
353b6d2
Even more formatting
gerth2 Jul 21, 2024
dbdd691
Adding settings remake implementation, innomaker camera support.
gerth2 Jul 26, 2024
cfddf23
reset libcamera jni loader
gerth2 Jul 26, 2024
1ae9358
Merge remote-tracking branch 'origin/master'
gerth2 Jul 26, 2024
c209420
fix failing unit test
gerth2 Jul 26, 2024
8d4afca
actually fix test
gerth2 Jul 26, 2024
f6a9f7f
spotless
gerth2 Jul 26, 2024
7978309
Run lint
mcm001 Jul 29, 2024
61d87ab
Merge remote-tracking branch 'origin/run-lint'
gerth2 Jul 31, 2024
72d5bad
whuppyfermant
gerth2 Jul 31, 2024
b6379ee
Merge branch 'master' into master
gerth2 Aug 2, 2024
db42646
Merge branch 'master' into master
gerth2 Aug 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions photon-client/src/components/cameras/CameraCalibrationCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -389,15 +389,17 @@ const setSelectedVideoFormat = (format: VideoFormat) => {
<v-row v-if="isCalibrating">
<v-col cols="12" class="pt-0">
<pv-slider
v-model="useCameraSettingsStore().currentPipelineSettings.cameraExposure"
v-model="useCameraSettingsStore().currentPipelineSettings.cameraExposureRaw"
:disabled="useCameraSettingsStore().currentCameraSettings.pipelineSettings.cameraAutoExposure"
label="Exposure"
tooltip="Directly controls how much light is allowed to fall onto the sensor, which affects apparent brightness"
:min="0"
:max="100"
tooltip="Directly controls how long the camera shutter remains open. Units are dependant on the underlying driver."
:min="useCameraSettingsStore().minExposureRaw"
:max="useCameraSettingsStore().maxExposureRaw"
:slider-cols="8"
:step="0.1"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraExposure: args }, false)"
:step="1"
@input="
(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraExposureRaw: args }, false)
"
/>
<pv-slider
v-model="useCameraSettingsStore().currentPipelineSettings.cameraBrightness"
Expand Down
12 changes: 6 additions & 6 deletions photon-client/src/components/dashboard/tabs/InputTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ const interactiveCols = computed(() =>
<template>
<div>
<pv-slider
v-model="useCameraSettingsStore().currentPipelineSettings.cameraExposure"
v-model="useCameraSettingsStore().currentPipelineSettings.cameraExposureRaw"
:disabled="useCameraSettingsStore().currentCameraSettings.pipelineSettings.cameraAutoExposure"
label="Exposure"
tooltip="Directly controls how much light is allowed to fall onto the sensor, which affects apparent brightness"
:min="0"
:max="100"
tooltip="Directly controls how long the camera shutter remains open. Units are dependant on the underlying driver."
:min="useCameraSettingsStore().minExposureRaw"
:max="useCameraSettingsStore().maxExposureRaw"
:slider-cols="interactiveCols"
:step="0.1"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraExposure: args }, false)"
:step="1"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraExposureRaw: args }, false)"
/>
<pv-slider
v-model="useCameraSettingsStore().currentPipelineSettings.cameraBrightness"
Expand Down
8 changes: 8 additions & 0 deletions photon-client/src/stores/settings/CameraSettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ export const useCameraSettingsStore = defineStore("cameraSettings", {
},
isCSICamera(): boolean {
return this.currentCameraSettings.isCSICamera;
},
minExposureRaw(): number {
return this.currentCameraSettings.minExposureRaw;
},
maxExposureRaw(): number {
return this.currentCameraSettings.maxExposureRaw;
}
},
actions: {
Expand Down Expand Up @@ -102,6 +108,8 @@ export const useCameraSettingsStore = defineStore("cameraSettings", {
})),
completeCalibrations: d.calibrations,
isCSICamera: d.isCSICamera,
minExposureRaw: d.minExposureRaw,
maxExposureRaw: d.maxExposureRaw,
pipelineNicknames: d.pipelineNicknames,
currentPipelineIndex: d.currentPipelineIndex,
pipelineSettings: d.currentPipelineSettings,
Expand Down
16 changes: 9 additions & 7 deletions photon-client/src/types/PipelineTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ export interface PipelineSettings {
hueInverted: boolean;
outputShowMultipleTargets: boolean;
contourSortMode: number;
cameraExposure: number;
cameraExposureRaw: number;
cameraMinExposureRaw: number;
cameraMaxExposureRaw: number;
offsetSinglePoint: { x: number; y: number };
cameraBrightness: number;
offsetDualPointAArea: number;
Expand Down Expand Up @@ -97,7 +99,7 @@ export type ConfigurablePipelineSettings = Partial<
// Omitted settings are changed for all pipeline types
export const DefaultPipelineSettings: Omit<
PipelineSettings,
"cameraGain" | "targetModel" | "ledMode" | "outputShowMultipleTargets" | "cameraExposure" | "pipelineType"
"cameraGain" | "targetModel" | "ledMode" | "outputShowMultipleTargets" | "cameraExposureRaw" | "pipelineType"
> = {
offsetRobotOffsetMode: RobotOffsetPointMode.None,
streamingFrameDivisor: 0,
Expand Down Expand Up @@ -151,7 +153,7 @@ export const DefaultReflectivePipelineSettings: ReflectivePipelineSettings = {
targetModel: TargetModel.InfiniteRechargeHighGoalOuter,
ledMode: true,
outputShowMultipleTargets: false,
cameraExposure: 6,
cameraExposureRaw: 6,
pipelineType: PipelineType.Reflective,

contourFilterRangeY: 2,
Expand Down Expand Up @@ -182,7 +184,7 @@ export const DefaultColoredShapePipelineSettings: ColoredShapePipelineSettings =
targetModel: TargetModel.InfiniteRechargeHighGoalOuter,
ledMode: true,
outputShowMultipleTargets: false,
cameraExposure: 20,
cameraExposureRaw: 20,
pipelineType: PipelineType.ColoredShape,

erode: false,
Expand Down Expand Up @@ -222,7 +224,7 @@ export const DefaultAprilTagPipelineSettings: AprilTagPipelineSettings = {
targetModel: TargetModel.AprilTag6p5in_36h11,
ledMode: false,
outputShowMultipleTargets: true,
cameraExposure: 20,
cameraExposureRaw: 20,
pipelineType: PipelineType.AprilTag,

hammingDist: 0,
Expand Down Expand Up @@ -264,7 +266,7 @@ export const DefaultArucoPipelineSettings: ArucoPipelineSettings = {
cameraGain: 75,
outputShowMultipleTargets: true,
targetModel: TargetModel.AprilTag6p5in_36h11,
cameraExposure: -1,
cameraExposureRaw: -1,
cameraAutoExposure: true,
ledMode: false,
pipelineType: PipelineType.Aruco,
Expand Down Expand Up @@ -299,7 +301,7 @@ export const DefaultObjectDetectionPipelineSettings: ObjectDetectionPipelineSett
targetModel: TargetModel.InfiniteRechargeHighGoalOuter,
ledMode: true,
outputShowMultipleTargets: false,
cameraExposure: 6,
cameraExposureRaw: 6,
confidence: 0.9,
nms: 0.45,
box_thresh: 0.25
Expand Down
7 changes: 6 additions & 1 deletion photon-client/src/types/SettingTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ export interface CameraSettings {

cameraQuirks: QuirkyCamera;
isCSICamera: boolean;

minExposureRaw: number;
maxExposureRaw: number;
}

export interface CameraSettingsChangeRequest {
Expand Down Expand Up @@ -287,7 +290,9 @@ export const PlaceholderCameraSettings: CameraSettings = {
StickyFPS: false
}
},
isCSICamera: false
isCSICamera: false,
minExposureRaw: 1,
maxExposureRaw: 100
};

export enum CalibrationBoardTypes {
Expand Down
2 changes: 2 additions & 0 deletions photon-client/src/types/WebsocketDataTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export interface WebsocketCameraSettingsUpdate {
pipelineNicknames: string[];
videoFormatList: WebsocketVideoFormat;
cameraQuirks: QuirkyCamera;
minExposureRaw: number;
maxExposureRaw: number;
}
export interface WebsocketNTUpdate {
connected: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,5 +178,7 @@ public static class UICameraConfiguration {
public boolean isFovConfigurable = true;
public QuirkyCamera cameraQuirks;
public boolean isCSICamera;
public double minExposureRaw;
public double maxExposureRaw;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,33 @@ public static long nanosToMicros(long nanos) {
return nanos / 1000;
}

/**
* Constrain a value to only take on certain values. Pick the next-highest allowed value in the
* array if in-between.
*
* @param value value to quantize
* @param allowableSteps sorted array of the allowed values
* @return quantized value
*/
public static int quantize(int value, int[] allowableSteps) {
for (int step : allowableSteps) {
if (value <= step) {
return step;
}
}
return allowableSteps[allowableSteps.length - 1];
}

public static double limit(double value, double out_min, double out_max) {
gerth2 marked this conversation as resolved.
Show resolved Hide resolved
double retVal = value;
if (value > out_max) {
retVal = out_max;
} else if (value < out_min) {
retVal = out_min;
}
return retVal;
}

public static double map(
double value, double in_min, double in_max, double out_min, double out_max) {
return (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
package org.photonvision.raspi;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
Expand All @@ -37,29 +36,8 @@ public static synchronized void forceLoad() throws IOException {
var libraryName = "photonlibcamera";

try {
// We always extract the shared object (we could hash each so, but that's a lot of work)
var arch_name = "linuxarm64";
var nativeLibName = System.mapLibraryName(libraryName);
var resourcePath = "/nativelibraries/" + arch_name + "/" + nativeLibName;
var in = LibCameraJNILoader.class.getResourceAsStream(resourcePath);

if (in == null) {
logger.error("Failed to find internal native library at path " + resourcePath);
libraryLoaded = false;
return;
}

// It's important that we don't mangle the names of these files on Windows at least
File temp = new File(System.getProperty("java.io.tmpdir"), nativeLibName);
FileOutputStream fos = new FileOutputStream(temp);

int read = -1;
byte[] buffer = new byte[1024];
while ((read = in.read(buffer)) != -1) {
fos.write(buffer, 0, read);
}
fos.close();
in.close();
// Temp - use the one we built here
gerth2 marked this conversation as resolved.
Show resolved Hide resolved
gerth2 marked this conversation as resolved.
Show resolved Hide resolved
File temp = new File("/home/pi/photon-libcamera-gl-driver/cmake_build/libphotonlibcamera.so");
gerth2 marked this conversation as resolved.
Show resolved Hide resolved

System.load(temp.getAbsolutePath());

Expand All @@ -68,7 +46,6 @@ public static synchronized void forceLoad() throws IOException {
} catch (UnsatisfiedLinkError e) {
logger.error("Couldn't load shared object " + libraryName, e);
e.printStackTrace();
// logger.error(System.getProperty("java.library.path"));
}
libraryLoaded = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
public enum CameraQuirk {
/** Camera settable for controllable image gain */
Gain,
/** For the Raspberry Pi Camera */
PiCam,
/** Only certain discrete exposure settings work */
LifeCamExposure,
/** Auto-Exposure property uses 1/0, rather than 3/1 */
OneZeroAutoExposure,
/** Cap at 100FPS for high-bandwidth cameras */
FPSCap100,
/** Separate red/blue gain controls available */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) Photon Vision.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.photonvision.vision.camera;

/** Mr. Photonvision's Home for Peculiar Camera Constants */
public class CameraQuirkConstants {
public static int[] LifecamAllowableExposures = {
5, 10, 20, 39, 78, 156, 312, 625, 1250, 2500, 5000, 10000, 20000
gerth2 marked this conversation as resolved.
Show resolved Hide resolved
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public boolean isVendorCamera() {
return false;
}

@Override
public boolean hasLEDs() {
return false; // Assume USB cameras do not have photonvision-controlled LEDs
}

private static class FileSourceSettables extends VisionSourceSettables {
private final VideoMode videoMode;

Expand All @@ -93,7 +98,7 @@ private static class FileSourceSettables extends VisionSourceSettables {
}

@Override
public void setExposure(double exposure) {}
public void setExposureRaw(double exposureRaw) {}

public void setAutoExposure(boolean cameraAutoExposure) {}

Expand All @@ -117,5 +122,15 @@ protected void setVideoModeInternal(VideoMode videoMode) {
public HashMap<Integer, VideoMode> getAllVideoModes() {
return videoModes;
}

@Override
public double getMinExposureRaw() {
return 1f;
}

@Override
public double getMaxExposureRaw() {
return 100f;
}
}
}
Loading
Loading