2016-12-21 21:58:42 -08:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2018-01-02 09:20:21 -08:00
|
|
|
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
2016-12-21 21:58:42 -08:00
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "vision/VisionRunner.h"
|
|
|
|
|
|
2017-08-27 00:11:52 -07:00
|
|
|
#include <opencv2/core/mat.hpp>
|
|
|
|
|
|
2016-12-21 21:58:42 -08:00
|
|
|
#include "DriverStation.h"
|
|
|
|
|
#include "RobotBase.h"
|
|
|
|
|
|
|
|
|
|
using namespace frc;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new vision runner. It will take images from the {@code
|
|
|
|
|
* videoSource}, and call the virtual DoProcess() method.
|
|
|
|
|
*
|
|
|
|
|
* @param videoSource the video source to use to supply images for the pipeline
|
|
|
|
|
*/
|
|
|
|
|
VisionRunnerBase::VisionRunnerBase(cs::VideoSource videoSource)
|
2017-12-10 20:58:14 -08:00
|
|
|
: m_image(std::make_unique<cv::Mat>()),
|
|
|
|
|
m_cvSink("VisionRunner CvSink"),
|
|
|
|
|
m_enabled(true) {
|
2016-12-21 21:58:42 -08:00
|
|
|
m_cvSink.SetSource(videoSource);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Located here and not in header due to cv::Mat forward declaration.
|
|
|
|
|
VisionRunnerBase::~VisionRunnerBase() {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Runs the pipeline one time, giving it the next image from the video source
|
|
|
|
|
* specified in the constructor. This will block until the source either has an
|
|
|
|
|
* image or throws an error. If the source successfully supplied a frame, the
|
|
|
|
|
* pipeline's image input will be set, the pipeline will run, and the listener
|
|
|
|
|
* specified in the constructor will be called to notify it that the pipeline
|
|
|
|
|
* ran. This must be run in a dedicated thread, and cannot be used in the main
|
|
|
|
|
* robot thread because it will freeze the robot program.
|
|
|
|
|
*
|
|
|
|
|
* <p>This method is exposed to allow teams to add additional functionality or
|
|
|
|
|
* have their own ways to run the pipeline. Most teams, however, should just
|
|
|
|
|
* use {@link #runForever} in its own thread using a std::thread.</p>
|
|
|
|
|
*/
|
|
|
|
|
void VisionRunnerBase::RunOnce() {
|
|
|
|
|
if (std::this_thread::get_id() == RobotBase::GetThreadId()) {
|
|
|
|
|
wpi_setErrnoErrorWithContext(
|
|
|
|
|
"VisionRunner::RunOnce() cannot be called from the main robot thread");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
auto frameTime = m_cvSink.GrabFrame(*m_image);
|
|
|
|
|
if (frameTime == 0) {
|
|
|
|
|
auto error = m_cvSink.GetError();
|
|
|
|
|
DriverStation::ReportError(error);
|
|
|
|
|
} else {
|
|
|
|
|
DoProcess(*m_image);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A convenience method that calls {@link #runOnce()} in an infinite loop. This
|
|
|
|
|
* must be run in a dedicated thread, and cannot be used in the main robot
|
|
|
|
|
* thread because it will freeze the robot program.
|
|
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* <strong>Do not call this method directly from the main thread.</strong>
|
2016-12-21 21:58:42 -08:00
|
|
|
*/
|
|
|
|
|
void VisionRunnerBase::RunForever() {
|
|
|
|
|
if (std::this_thread::get_id() == RobotBase::GetThreadId()) {
|
|
|
|
|
wpi_setErrnoErrorWithContext(
|
|
|
|
|
"VisionRunner::RunForever() cannot be called from the main robot "
|
|
|
|
|
"thread");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-12-10 20:58:14 -08:00
|
|
|
while (m_enabled) {
|
2016-12-21 21:58:42 -08:00
|
|
|
RunOnce();
|
|
|
|
|
}
|
2017-08-19 22:14:34 -07:00
|
|
|
}
|
2017-12-10 20:58:14 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stop a RunForever() loop.
|
|
|
|
|
*/
|
|
|
|
|
void VisionRunnerBase::Stop() { m_enabled = false; }
|