OpenFTC / EasyOpenCV

Finally, a straightforward and easy way to use OpenCV on an FTC robot!
219 stars 100 forks source link

RC crashes when memory leak detection warning is generated on SDK 7.0 #35

Closed Splorpy closed 2 years ago

Splorpy commented 2 years ago

RC has begun to crash consistently a few seconds after init an op mode. Code for the op mode and pipeline are below, followed by the error message. We have a competition in a few days, so any help is appreciated.

int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName());
this.webcam = OpenCvCameraFactory.getInstance().createWebcam(hardwareMap.get(WebcamName.class, "Webcam 1"), cameraMonitorViewId);

this.webcam.setPipeline(new Pipeline(telemetry));

this.webcam.setMillisecondsPermissionTimeout(2500); // Timeout for obtaining permission is configurable. Set before opening.
this.webcam.openCameraDeviceAsync(new OpenCvCamera.AsyncCameraOpenListener()
{
    @Override
    public void onOpened()
    {
        webcam.startStreaming(1280, 720, OpenCvCameraRotation.UPRIGHT);
    }

    @Override
    public void onError(int errorCode) {telemetry.addData("ErrorCode", errorCode);}
});
telemetry.update();
public class Pipeline extends OpenCvPipeline {

    Scalar blueLower = new Scalar(100,0,0);
    Scalar blueUpper = new Scalar(255,150,150);

    Mat output = new Mat();
    Mat processed1 = new Mat();
    Mat processed2 = new Mat();

    Telemetry tel;

    Pipeline(Telemetry telemetry) {
        this.tel = telemetry;
    }

    @Override
    public Mat processFrame(Mat input)
    {
        output = input.clone();
        return output;
    }
}
V/Robocol: sending CMD_RECEIVE_FRAME_CHUNK(6743), attempt: 0
V/Robocol: sending CMD_RECEIVE_FRAME_CHUNK(6744), attempt: 0
D/AndroidRuntime: Shutting down VM
V/Robocol: sending CMD_RECEIVE_FRAME_CHUNK(6745), attempt: 0

    --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.qualcomm.ftcrobotcontroller, PID: 1377
    java.lang.AbstractMethodError: abstract method "boolean com.qualcomm.robotcore.util.GlobalWarningSource.shouldTriggerWarningSound()"
        at com.qualcomm.robotcore.util.RobotLog.getGlobalWarningMessage(RobotLog.java:457)
        at com.qualcomm.ftccommon.UpdateUI$Callback.refreshTextErrorMessage(UpdateUI.java:260)
        at com.qualcomm.ftccommon.UpdateUI$Callback$2.run(UpdateUI.java:125)
        at android.os.Handler.handleCallback(Handler.java:755)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6121)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795)
V/RobotCore: thread: ...terminating 'opmode loop()'
E/ThreadPool: exception thrown in thread pool; ignored
E/ThreadPool: exception thrown in thread pool; ignored
E/ThreadPool: java.lang.AbstractMethodError: abstract method "boolean com.qualcomm.robotcore.util.GlobalWarningSource.shouldTriggerWarningSound()"
E/ThreadPool:     at com.qualcomm.robotcore.util.RobotLog.getGlobalWarningMessage(RobotLog.java:457)
E/ThreadPool: java.lang.AbstractMethodError: abstract method "boolean com.qualcomm.robotcore.util.GlobalWarningSource.shouldTriggerWarningSound()"
E/ThreadPool:     at com.qualcomm.robotcore.eventloop.EventLoopManager.refreshSystemTelemetry(EventLoopManager.java:388)
E/ThreadPool:     at com.qualcomm.robotcore.eventloop.EventLoopManager.packetReceived(EventLoopManager.java:236)
E/ThreadPool:     at com.qualcomm.robotcore.util.RobotLog.getGlobalWarningMessage(RobotLog.java:457)
V/RobotCore: thread: ...terminating 'RecvLoopRunnable.run()'
E/ThreadPool: exception thrown in thread pool; ignored
E/ThreadPool:     at org.firstinspires.ftc.robotcore.internal.network.NetworkConnectionHandler$RecvLoopCallbackChainer.packetReceived(NetworkConnectionHandler.java:744)
E/ThreadPool:     at org.firstinspires.ftc.robotcore.internal.network.RecvLoopRunnable$PacketProcessor.run(RecvLoopRunnable.java:106)
E/ThreadPool:     at com.qualcomm.robotcore.eventloop.EventLoopManager.refreshSystemTelemetry(EventLoopManager.java:388)
E/ThreadPool:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
E/ThreadPool: java.lang.AbstractMethodError: abstract method "boolean com.qualcomm.robotcore.util.GlobalWarningSource.shouldTriggerWarningSound()"
E/ThreadPool:     at com.qualcomm.robotcore.eventloop.EventLoopManager$EventLoopRunnable$1.run(EventLoopManager.java:262)
E/ThreadPool:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
E/ThreadPool:     at com.qualcomm.robotcore.util.ThreadPool.logThreadLifeCycle(ThreadPool.java:737)
E/ThreadPool:     at com.qualcomm.robotcore.util.RobotLog.getGlobalWarningMessage(RobotLog.java:457)
E/ThreadPool:     at com.qualcomm.robotcore.util.ThreadPool$ThreadFactoryImpl$1.run(ThreadPool.java:793)
E/ThreadPool:     at com.qualcomm.robotcore.eventloop.EventLoopManager$EventLoopRunnable.run(EventLoopManager.java:246)
E/ThreadPool:     at java.lang.Thread.run(Thread.java:761)
V/ThreadPool: container(0x032f08c2: ReceiveLoopService) added id=109 TID=0 count=4
E/ThreadPool:     at com.qualcomm.robotcore.eventloop.EventLoopManager.refreshSystemTelemetry(EventLoopManager.java:388)
V/ThreadPool: container(0x032f08c2: ReceiveLoopService) removed id=66 TID=1480 count=4
I/Process: Sending signal. PID: 1377 SIG: 9
MDNich commented 2 years ago

I got the same thing. I bypassed it by starting the stream only with the start(); method and as soon as the first frame is processed the pipeline, I shut down the camera and stop the stream. Though yes @Windwoes pls help :)

Windwoes commented 2 years ago

Hehe. So, your pipeline has a memory leak, because you are cloning the input mat on every frame and not calling .release() on the cloned mat. EOCV has a memory leak detector which will trigger global warning message if it thinks there is a reasonable chance that your pipeline is leaking memory.

v1.5.0 of EOCV was compiled against SDK v6.2.1. SDK v7.0 has a minor ABI breaking change because it now requires implementations of the GlobalWarningSource interface to implement the public boolean shouldTriggerWarningSound() function. Which means that when the SDK tries to call shouldTriggerWarningSound() on the EOCV camera object, the JavaVM cries because it's being asked to invoke a function that hasn't been defined in the EOCV bytecode...

This issue escaped my notice because I never tested the memory leak detector when running EOCV on SDK v7.0.

So that being said, you have three options:

Splorpy commented 2 years ago

I'm too used to Python haha. .release() worked perfectly. Thank you both for the help!

Windwoes commented 2 years ago

I'm re-opening this until I release the fixed version officially

Windwoes commented 2 years ago

Fixed in 1.5.1