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

Release 3.6.0 #115

Merged
merged 7 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading