Skip to content

Commit

Permalink
handle camera disconnection/reconnection
Browse files Browse the repository at this point in the history
  • Loading branch information
S1ink committed Apr 23, 2022
1 parent 73ee8ff commit 77bae3b
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 18 deletions.
Binary file modified out/vision_program
Binary file not shown.
2 changes: 1 addition & 1 deletion src/core/defines.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define REMOVE_DISCONNECTED_CAMERAS // remove this to always use all cameras defined in the json, whether or not they actually exist
//#define REMOVE_DISCONNECTED_CAMERAS // remove this to always use all cameras defined in the json, whether or not they actually exist
2 changes: 2 additions & 0 deletions src/core/visioncamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,6 @@ class VisionCamera : public cs::VideoCamera {

int8_t brightness{50}, exposure{-1};
int16_t whitebalance{-1};


};
7 changes: 7 additions & 0 deletions src/core/visionserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,13 @@ const cv::Mat_<float>& VisionServer::getCameraMatrix() const {
const cv::Mat_<float>& VisionServer::getDistortion() const {
return this->distortion;
}
void VisionServer::getFrame(cv::Mat& framebuff) {
if(this->getCurrentCamera().IsConnected()) {
this->source.GrabFrame(framebuff);
} else {
framebuff = cv::Mat::zeros(cv::Size(320, 240), CV_8UC3);
}
}

void VisionServer::updateTarget(const std::string& target) {
this->active_target.setTarget(target);
Expand Down
14 changes: 10 additions & 4 deletions src/core/visionserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,15 @@ class VisionServer { // make singleton?
*/
const cv::Mat_<float>& getDistortion() const;

/**
* Get a frame from the current camera. Returns an blank array if the current camera is disconnected.
* @param framebuff the image matrix buffer
*/
void getFrame(cv::Mat& framebuff);

/**
* Joins any processing threads that are currently running
* @return Returns if there was a thread running that was joined
* @return Returns true if there was a thread running that was joined
*/
bool stopVision();

Expand All @@ -214,7 +220,7 @@ class VisionServer { // make singleton?
* @param quality The default streaming quality
*/
template<class pipeline_t>
inline void runVision_S(int8_t quality = 50) { VisionServer::visionWorker<pipeline_t>(*this, quality); }
inline void runVision_S(int8_t quality = 50) { VisionServer::visionWorker_S<pipeline_t>(*this, quality); }
/**
* Runs a processing instance with 2 pipelines (switchable via networktables). Pipeline instances are
* stack allocated rather than heap allocated like with runVision<pipelines...>().
Expand All @@ -223,7 +229,7 @@ class VisionServer { // make singleton?
* @param quality The default streaming quality
*/
template<class pipeline_t1, class pipeline_t2>
inline void runVision_S(int8_t quality = 50) { VisionServer::visionWorker<pipeline_t1, pipeline_t2>(*this, quality); }
inline void runVision_S(int8_t quality = 50) { VisionServer::visionWorker_S<pipeline_t1, pipeline_t2>(*this, quality); }
/**
* Runs a processing instance with 3 pipelines (switchable via networktables). Pipeline instances are
* stack allocated rather than heap allocated like with runVision<pipelines...>().
Expand All @@ -233,7 +239,7 @@ class VisionServer { // make singleton?
* @param quality The default streaming quality
*/
template<class pipeline_t1, class pipeline_t2, class pipeline_t3>
inline void runVision_S(int8_t quality = 50) { VisionServer::visionWorker<pipeline_t1, pipeline_t2, pipeline_t3>(*this, quality); }
inline void runVision_S(int8_t quality = 50) { VisionServer::visionWorker_S<pipeline_t1, pipeline_t2, pipeline_t3>(*this, quality); }
/**
* Runs a processing instace with however many pipelines are supplied (although heap-allocation is used). Pipelines are switchable via networktables.
* @param pipelines The pipeline typenames, separated by commas
Expand Down
31 changes: 19 additions & 12 deletions src/core/visionserver.inc
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@
template<class pipeline_t>
bool VisionServer::runVisionThread_S(int8_t quality) {
if(!this->launched.joinable()) {
this->launched = std::move(std::thread(VisionServer::visionWorker<pipeline_t>, std::ref(*this), quality));
this->launched = std::move(std::thread(VisionServer::visionWorker_S<pipeline_t>, std::ref(*this), quality));
return true;
}
return false;
}
template<class pipeline_t1, class pipeline_t2>
bool VisionServer::runVisionThread_S(int8_t quality) {
if(!this->launched.joinable()) {
this->launched = std::move(std::thread(VisionServer::visionWorker<pipeline_t1, pipeline_t2>, std::ref(*this), quality));
this->launched = std::move(std::thread(VisionServer::visionWorker_S<pipeline_t1, pipeline_t2>, std::ref(*this), quality));
return true;
}
return false;
}
template<class pipeline_t1, class pipeline_t2, class pipeline_t3>
bool VisionServer::runVisionThread_S(int8_t quality) {
if(!this->launched.joinable()) {
this->launched = std::move(std::thread(VisionServer::visionWorker<pipeline_t1, pipeline_t2, pipeline_t3>, std::ref(*this), quality));
this->launched = std::move(std::thread(VisionServer::visionWorker_S<pipeline_t1, pipeline_t2, pipeline_t3>, std::ref(*this), quality));
return true;
}
return false;
Expand Down Expand Up @@ -50,10 +50,10 @@ void VisionServer::visionWorker_S(VisionServer& server, int8_t quality) {

server.start = CHRONO::high_resolution_clock::now();
while(server.runloop) {
server.source.GrabFrame(frame);
server.getFrame(frame);

server.beg = CHRONO::high_resolution_clock::now();
if(server.vision->GetBoolean("Enable Processing", true)) {
if(server.vision->GetBoolean("Enable Processing", true) && !frame.empty()) {
pipeline.process(frame);
}
server.end = CHRONO::high_resolution_clock::now();
Expand All @@ -73,7 +73,7 @@ void VisionServer::visionWorker_S(VisionServer& server, int8_t quality) {
server.sec1_frames = server.total_frames;
}

if(server.vision->GetEntry("Show Statistics").GetBoolean(false)) {
if(server.vision->GetEntry("Show Statistics").GetBoolean(false) && !frame.empty()) {
server.putStats(frame);
}
server.updateStats();
Expand Down Expand Up @@ -103,8 +103,11 @@ void VisionServer::visionWorker_S(VisionServer& server, int8_t quality) {

server.start = CHRONO::high_resolution_clock::now();
while(server.runloop) {
server.source.GrabFrame(frame);
switch(server.vision->GetBoolean("Enable Processing", true) * ((int8_t)server.vision->GetEntry("Pipeline Index").GetDouble(-1) + 1)) {
server.getFrame(frame);
switch(
(server.vision->GetBoolean("Enable Processing", true) && !frame.empty()) *
((int8_t)server.vision->GetEntry("Pipeline Index").GetDouble(-1) + 1)
) {
case 1 : {
server.beg = CHRONO::high_resolution_clock::now();
p1.process(frame);
Expand Down Expand Up @@ -138,7 +141,7 @@ void VisionServer::visionWorker_S(VisionServer& server, int8_t quality) {
server.sec1_frames = server.total_frames;
}

if(server.vision->GetEntry("Show Statistics").GetBoolean(false)) {
if(server.vision->GetEntry("Show Statistics").GetBoolean(false) && !frame.empty()) {
server.putStats(frame);
}
server.updateStats();
Expand Down Expand Up @@ -172,8 +175,11 @@ void VisionServer::visionWorker_S(VisionServer& server, int8_t quality) {

server.start = CHRONO::high_resolution_clock::now();
while(server.runloop) {
server.source.GrabFrame(frame);
switch(server.vision->GetBoolean("Enable Processing", true) * ((int8_t)server.vision->GetEntry("Pipeline Index").GetDouble(-1) + 1)) {
server.getFrame(frame);
switch(
(server.vision->GetBoolean("Enable Processing", true) && !frame.empty()) *
((int8_t)server.vision->GetEntry("Pipeline Index").GetDouble(-1) + 1)
) {
case 1 : {
server.beg = CHRONO::high_resolution_clock::now();
p1.process(frame);
Expand Down Expand Up @@ -246,7 +252,8 @@ void VisionServer::visionWorker(VisionServer& server, int8_t quality) {

server.start = CHRONO::high_resolution_clock::now();
while(server.runloop) {
server.source.GrabFrame(frame);
server.getFrame(frame);

int idx = server.vision->GetBoolean("Enable Processing", true) * ((int)server.vision->GetEntry("Pipeline Index").GetDouble(-1) + 1);
if(idx > 0 && idx <= pipes.size()) {
server.beg = CHRONO::high_resolution_clock::now();
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ int main(int argc, char* argv[]) {
// Version::HTTP_1_1,
// "81" // the main WPILibPi page uses port 80
// );
//vserver.runVision_S<CargoFinder, StripFinder<VThreshold::LED::BLUE> >(25);
//vserver.runVision_S<CargoFinder, StripFinder<VThreshold::LED::GREEN> >(25); // this currently does not call the right worker
vserver.runVision<
CargoFinder,
StripFinder<VThreshold::LED::BLUE>,
Expand Down

0 comments on commit 77bae3b

Please sign in to comment.