Skip to content

Commit

Permalink
Merge pull request #115 from deltacv/dev
Browse files Browse the repository at this point in the history
Release 3.6.0
  • Loading branch information
serivesmejia authored Sep 22, 2024
2 parents bf37fa2 + 9ea596d commit a2c4207
Show file tree
Hide file tree
Showing 56 changed files with 2,503 additions and 395 deletions.
37 changes: 37 additions & 0 deletions Common/src/main/java/androidx/annotation/ColorInt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.annotation;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.CLASS;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Denotes that the annotated element represents a packed color
* int, {@code AARRGGBB}. If applied to an int array, every element
* in the array represents a color integer.
* <p>
* Example:
* <pre>{@code
* public abstract void setTextColor(@ColorInt int color);
* }</pre>
*/
@Retention(CLASS)
@Target({PARAMETER,METHOD,LOCAL_VARIABLE,FIELD})
public @interface ColorInt {
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class EventHandler(val name: String) : Runnable {
throw ex
} else {
logger.error("Error while running \"once\" ${listener.javaClass.name}", ex)
removeOnceListener(listener)
}
}

Expand Down
28 changes: 28 additions & 0 deletions Common/src/main/java/com/qualcomm/robotcore/util/SortOrder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2024 FIRST
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package com.qualcomm.robotcore.util;

public enum SortOrder
{
ASCENDING,
DESCENDING
}
15 changes: 13 additions & 2 deletions EOCV-Sim/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ plugins {
id 'org.jetbrains.kotlin.jvm'
id 'com.github.johnrengelman.shadow'
id 'maven-publish'

id 'edu.sc.seis.launch4j' version '3.0.6'
}

apply from: '../build.common.gradle'
Expand All @@ -32,6 +34,17 @@ test {

apply from: '../test-logging.gradle'

launch4j {
mainClassName = 'com.github.serivesmejia.eocvsim.Main'
icon = "${projectDir}/src/main/resources/images/icon/ico_eocvsim.ico"

outfile = "${project.name}-${standardVersion}.exe"

copyConfigurable = [] // Prevents copying dependencies
jarTask = shadowJar

}

dependencies {
api project(':Common')
api project(':Vision')
Expand Down Expand Up @@ -66,8 +79,6 @@ dependencies {
testImplementation "io.kotest:kotest-assertions-core:$kotest_version"

implementation 'com.moandjiezana.toml:toml4j:0.7.2'
implementation 'com.google.jimfs:jimfs:1.3.0'

implementation 'org.ow2.asm:asm:9.7'
}

Expand Down
18 changes: 13 additions & 5 deletions EOCV-Sim/src/main/java/com/github/serivesmejia/eocvsim/EOCVSim.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

package com.github.serivesmejia.eocvsim

import com.github.serivesmejia.eocvsim.EOCVSim.Parameters
import com.github.serivesmejia.eocvsim.config.Config
import com.github.serivesmejia.eocvsim.config.ConfigManager
import com.github.serivesmejia.eocvsim.gui.DialogFactory
Expand All @@ -32,7 +33,6 @@ import com.github.serivesmejia.eocvsim.input.InputSourceManager
import com.github.serivesmejia.eocvsim.output.VideoRecordingSession
import com.github.serivesmejia.eocvsim.pipeline.PipelineManager
import com.github.serivesmejia.eocvsim.pipeline.PipelineSource
import io.github.deltacv.common.pipeline.util.PipelineStatisticsCalculator
import com.github.serivesmejia.eocvsim.tuner.TunerManager
import com.github.serivesmejia.eocvsim.util.ClasspathScan
import com.github.serivesmejia.eocvsim.util.FileFilters
Expand All @@ -41,13 +41,13 @@ import com.github.serivesmejia.eocvsim.util.event.EventHandler
import com.github.serivesmejia.eocvsim.util.exception.MaxActiveContextsException
import com.github.serivesmejia.eocvsim.util.exception.handling.CrashReport
import com.github.serivesmejia.eocvsim.util.exception.handling.EOCVSimUncaughtExceptionHandler
import com.github.serivesmejia.eocvsim.util.extension.plus
import com.github.serivesmejia.eocvsim.util.fps.FpsLimiter
import com.github.serivesmejia.eocvsim.util.io.EOCVSimFolder
import com.github.serivesmejia.eocvsim.util.loggerFor
import com.github.serivesmejia.eocvsim.workspace.WorkspaceManager
import com.qualcomm.robotcore.eventloop.opmode.OpMode
import com.qualcomm.robotcore.eventloop.opmode.OpModePipelineHandler
import io.github.deltacv.common.pipeline.util.PipelineStatisticsCalculator
import io.github.deltacv.common.util.ParsedVersion
import io.github.deltacv.eocvsim.plugin.loader.PluginManager
import io.github.deltacv.vision.external.PipelineRenderHook
Expand Down Expand Up @@ -242,7 +242,7 @@ class EOCVSim(val params: Parameters = Parameters()) {
* @see destroy
*/
enum class DestroyReason {
USER_REQUESTED, RESTART, CRASH
USER_REQUESTED, THREAD_EXIT, RESTART, CRASH
}

/**
Expand Down Expand Up @@ -437,9 +437,12 @@ class EOCVSim(val params: Parameters = Parameters()) {

logger.warn("Main thread interrupted ($hexCode)")

if(!destroying) {
destroy(DestroyReason.THREAD_EXIT)
}

if (isRestarting) {
Thread.interrupted() //clear interrupted flag

EOCVSim(params).init()
}
}
Expand All @@ -464,9 +467,14 @@ class EOCVSim(val params: Parameters = Parameters()) {
configManager.saveToFile()
visualizer.close()

eocvSimThread.interrupt()
destroying = true

if(reason == DestroyReason.THREAD_EXIT) {
exitProcess(0)
} else {
eocvSimThread.interrupt()
}

if (reason == DestroyReason.USER_REQUESTED || reason == DestroyReason.CRASH) jvmMainThread.interrupt()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ var currentMainThread: Thread = jvmMainThread
* @see CommandLine
*/
fun main(args: Array<String>) {
System.setProperty("sun.java2d.d3d", "false")

val result = CommandLine(
EOCVSimCommandInterface()
).setCaseInsensitiveEnumValuesAllowed(true).execute(*args)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import javax.swing.border.SoftBevelBorder;
import java.awt.*;

@SuppressWarnings("Unchecked")
public class TunableFieldPanel extends JPanel {

public final TunableField tunableField;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class TunableFieldPanelOptions(val fieldPanel: TunableFieldPanel,
if(i < colorScalar.`val`.size) {
val colorVal = colorScalar.`val`[i]
fieldPanel.setFieldValue(i, colorVal)
fieldPanel.tunableField.setGuiFieldValue(i, colorVal.toString())
fieldPanel.tunableField.setFieldValueFromGui(i, colorVal.toString())
} else { break } //keep looping until we write the entire scalar value
}
colorPickButton.isSelected = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private void init() {

addItemListener(evt -> eocvSim.onMainUpdate.doOnce(() -> {
try {
tunableField.setGuiComboBoxValue(index, Objects.requireNonNull(getSelectedItem()).toString());
tunableField.setComboBoxValueFromGui(index, Objects.requireNonNull(getSelectedItem()).toString());
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class TunableSlider(val index: Int,

private val changeFieldValue = EventListener {
if(inControl) {
tunableField.setGuiFieldValue(index, scaledValue.toString())
tunableField.setFieldValueFromGui(index, scaledValue.toString())

if (eocvSim.pipelineManager.paused)
eocvSim.pipelineManager.setPaused(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public void replace(FilterBypass fb, int offset, int length, String text, Attrib
Runnable changeFieldValue = () -> {
if ((!hasValidText || !tunableField.isOnlyNumbers() || !getText().trim().equals(""))) {
try {
tunableField.setGuiFieldValue(index, getText());
tunableField.setFieldValueFromGui(index, getText());
} catch (Exception e) {
setRedBorder();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ import com.github.serivesmejia.eocvsim.util.fps.FpsCounter
import com.github.serivesmejia.eocvsim.util.loggerForThis
import io.github.deltacv.common.image.MatPoster
import io.github.deltacv.common.pipeline.util.PipelineStatisticsCalculator
import io.github.deltacv.eocvsim.virtualreflect.VirtualField
import io.github.deltacv.eocvsim.virtualreflect.VirtualReflectContext
import io.github.deltacv.eocvsim.virtualreflect.VirtualReflection
import io.github.deltacv.eocvsim.virtualreflect.jvm.JvmVirtualReflection
import kotlinx.coroutines.*
import org.firstinspires.ftc.robotcore.external.Telemetry
import org.firstinspires.ftc.robotcore.internal.opmode.TelemetryImpl
Expand Down Expand Up @@ -89,14 +93,21 @@ class PipelineManager(
private set
@Volatile var currentPipelineData: PipelineData? = null
private set
var currentTunerTarget: Any? = null
private set
var currentPipelineName = ""
private set
var currentPipelineIndex = -1
private set
var previousPipelineIndex = 0

var virtualReflect: VirtualReflection = JvmVirtualReflection
set(value) {
eocvSim.tunerManager.setVirtualReflection(value)
field = value
}

var reflectTarget: Any? = null
private set

@Volatile var previousPipeline: OpenCvPipeline? = null
private set

Expand Down Expand Up @@ -130,7 +141,7 @@ class PipelineManager(

var applyLatestSnapshotOnChange = false

val snapshotFieldFilter: (Field) -> Boolean = {
val snapshotFieldFilter: (VirtualField) -> Boolean = {
// only snapshot fields managed by the variable tuner
// when getTunableFieldOf returns null, it means that
// it wasn't able to find a suitable TunableField for
Expand Down Expand Up @@ -258,6 +269,12 @@ class PipelineManager(
val telemetry = currentTelemetry
onUpdate.run()

for(activeContext in activePipelineContexts.toTypedArray()) {
if(!activeContext.isActive) {
activePipelineContexts.remove(activeContext)
}
}

if(activePipelineContexts.size > MAX_ALLOWED_ACTIVE_PIPELINE_CONTEXTS) {
throw MaxActiveContextsException("Current amount of active pipeline coroutine contexts (${activePipelineContexts.size}) is more than the maximum allowed. This generally means that there are multiple pipelines stuck in processFrame() running in the background, check for any lengthy operations in your pipelines.")
}
Expand Down Expand Up @@ -347,22 +364,18 @@ class PipelineManager(
}
}

if(!isActive) {
activePipelineContexts.remove(this.coroutineContext)
}

updateExceptionTracker()
} catch (ex: Exception) { //handling exceptions from pipelines
if(!hasInitCurrentPipeline) {
pipelineExceptionTracker.addMessage("Error while initializing requested pipeline, \"$currentPipelineName\". Falling back to previous one.")
pipelineExceptionTracker.addMessage("Error while initializing requested pipeline, \"$currentPipelineName\". Falling back to default.")
pipelineExceptionTracker.addMessage(
StrUtil.fromException(ex).trim()
)

eocvSim.visualizer.pipelineSelectorPanel.selectedIndex = previousPipelineIndex
changePipeline(currentPipelineIndex)
eocvSim.visualizer.pipelineSelectorPanel.selectedIndex = 0
changePipeline(0)

logger.error("Error while initializing requested pipeline, $currentPipelineName", ex)
logger.error("Error while initializing requested pipeline, $currentPipelineName. Falling back to default.", ex)
} else {
updateExceptionTracker(ex)
}
Expand All @@ -386,8 +399,6 @@ class PipelineManager(
withTimeout(timeout) {
pipelineJob.join()
}

activePipelineContexts.remove(currentPipelineContext)
} catch (ex: TimeoutCancellationException) {
//oops, pipeline ran out of time! we'll fall back
//to default pipeline to avoid further issues.
Expand Down Expand Up @@ -463,10 +474,14 @@ class PipelineManager(
}

fun addInstantiator(instantiatorFor: Class<*>, instantiator: PipelineInstantiator) {
pipelineInstantiators.put(instantiatorFor, instantiator)
pipelineInstantiators[instantiatorFor] = instantiator
}

fun getInstantiatorFor(clazz: Class<*>): PipelineInstantiator? {
if(pipelineInstantiators.containsKey(clazz)) {
return pipelineInstantiators[clazz]
}

for((instantiatorFor, instantiator) in pipelineInstantiators) {
if(ReflectUtil.hasSuperclass(clazz, instantiatorFor)) {
return instantiator
Expand Down Expand Up @@ -601,16 +616,18 @@ class PipelineManager(
previousPipelineIndex = currentPipelineIndex
previousPipeline = currentPipeline

currentPipeline = nextPipeline
currentPipelineData = pipelines[index]
currentTelemetry = nextTelemetry
currentPipelineIndex = index
currentPipelineName = currentPipeline!!.javaClass.simpleName
currentTunerTarget = instantiator.variableTunerTargetObject(currentPipeline!!)
currentPipeline = nextPipeline
currentPipelineData = pipelines[index]
currentTelemetry = nextTelemetry
currentPipelineIndex = index
currentPipelineName = currentPipeline!!.javaClass.simpleName

virtualReflect = instantiator.virtualReflectOf(currentPipeline!!)
reflectTarget = instantiator.variableTunerTarget(currentPipeline!!)

currentTelemetry?.update() // clear telemetry

val snap = PipelineSnapshot(currentPipeline!!, snapshotFieldFilter)
val snap = PipelineSnapshot(virtualReflect.contextOf(reflectTarget!!)!!, snapshotFieldFilter)

lastInitialSnapshot = if(applyLatestSnapshot) {
applyLatestSnapshot()
Expand Down Expand Up @@ -668,13 +685,13 @@ class PipelineManager(

fun captureSnapshot() {
if(currentPipeline != null) {
latestSnapshot = PipelineSnapshot(currentPipeline!!, snapshotFieldFilter)
latestSnapshot = PipelineSnapshot(virtualReflect.contextOf(reflectTarget!!)!!, snapshotFieldFilter)
}
}

fun captureStaticSnapshot() {
if(currentPipeline != null) {
staticSnapshot = PipelineSnapshot(currentPipeline!!, snapshotFieldFilter)
staticSnapshot = PipelineSnapshot(virtualReflect.contextOf(reflectTarget!!)!!, snapshotFieldFilter)
}
}

Expand All @@ -698,7 +715,7 @@ class PipelineManager(
fun getIndexOf(pipeline: OpenCvPipeline, source: PipelineSource = PipelineSource.CLASSPATH) =
getIndexOf(pipeline::class.java, source)

fun getIndexOf(pipelineClass: Class<out OpenCvPipeline>, source: PipelineSource = PipelineSource.CLASSPATH): Int? {
fun getIndexOf(pipelineClass: Class<*>, source: PipelineSource = PipelineSource.CLASSPATH): Int? {
for((i, pipelineData) in pipelines.withIndex()) {
if(pipelineData.clazz.name == pipelineClass.name && pipelineData.source == source) {
return i
Expand Down
Loading

0 comments on commit a2c4207

Please sign in to comment.