001/*
002 * Copyright (C) Photon Vision.
003 *
004 * This program is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package org.photonvision.vision.pipeline.result;
019
020import java.util.Collections;
021import java.util.List;
022import java.util.Optional;
023import org.photonvision.common.util.math.MathUtils;
024import org.photonvision.targeting.MultiTargetPNPResult;
025import org.photonvision.vision.frame.Frame;
026import org.photonvision.vision.opencv.Releasable;
027import org.photonvision.vision.target.TrackedTarget;
028
029public class CVPipelineResult implements Releasable {
030    public final long sequenceID;
031    private long imageCaptureTimestampNanos;
032    public final double processingNanos;
033    public final double fps;
034    public final List<TrackedTarget> targets;
035    public final Frame inputAndOutputFrame;
036    public Optional<MultiTargetPNPResult> multiTagResult;
037    public final List<String> objectDetectionClassNames;
038
039    public CVPipelineResult(
040            long sequenceID,
041            double processingNanos,
042            double fps,
043            List<TrackedTarget> targets,
044            Frame inputFrame) {
045        this(sequenceID, processingNanos, fps, targets, Optional.empty(), inputFrame, List.of());
046    }
047
048    public CVPipelineResult(
049            long sequenceID,
050            double processingNanos,
051            double fps,
052            List<TrackedTarget> targets,
053            Frame inputFrame,
054            List<String> classNames) {
055        this(sequenceID, processingNanos, fps, targets, Optional.empty(), inputFrame, classNames);
056    }
057
058    public CVPipelineResult(
059            long sequenceID,
060            double processingNanos,
061            double fps,
062            List<TrackedTarget> targets,
063            Optional<MultiTargetPNPResult> multiTagResult,
064            Frame inputFrame) {
065        this(sequenceID, processingNanos, fps, targets, multiTagResult, inputFrame, List.of());
066    }
067
068    public CVPipelineResult(
069            long sequenceID,
070            double processingNanos,
071            double fps,
072            List<TrackedTarget> targets,
073            Optional<MultiTargetPNPResult> multiTagResult,
074            Frame inputFrame,
075            List<String> classNames) {
076        this.sequenceID = sequenceID;
077        this.processingNanos = processingNanos;
078        this.fps = fps;
079        this.targets = targets != null ? targets : Collections.emptyList();
080        this.multiTagResult = multiTagResult;
081        this.objectDetectionClassNames = classNames;
082
083        this.inputAndOutputFrame = inputFrame;
084    }
085
086    public CVPipelineResult(
087            long sequenceID,
088            double processingNanos,
089            double fps,
090            List<TrackedTarget> targets,
091            Optional<MultiTargetPNPResult> multiTagResult) {
092        this(sequenceID, processingNanos, fps, targets, multiTagResult, null, List.of());
093    }
094
095    public boolean hasTargets() {
096        return !targets.isEmpty();
097    }
098
099    public void release() {
100        for (TrackedTarget tt : targets) {
101            tt.release();
102        }
103        if (inputAndOutputFrame != null) inputAndOutputFrame.release();
104    }
105
106    /**
107     * Get the latency between now (wpi::Now) and the time at which the image was captured. FOOTGUN:
108     * the latency is relative to the time at which this method is called. Waiting to call this method
109     * will change the latency this method returns.
110     */
111    @Deprecated
112    public double getLatencyMillis() {
113        var now = MathUtils.wpiNanoTime();
114        return MathUtils.nanosToMillis(now - imageCaptureTimestampNanos);
115    }
116
117    public double getProcessingMillis() {
118        return MathUtils.nanosToMillis(processingNanos);
119    }
120
121    public long getImageCaptureTimestampNanos() {
122        return imageCaptureTimestampNanos;
123    }
124
125    public void setImageCaptureTimestampNanos(long imageCaptureTimestampNanos) {
126        this.imageCaptureTimestampNanos = imageCaptureTimestampNanos;
127    }
128}