Galaxis Codebase  1.0.0
Team Galaxis software stack for the Carolo Cup 2023 - ROS2 based software
AsyncCamera.cpp
Go to the documentation of this file.
1 #include "AsyncCamera.hpp"
2 
3 #include "utils/logger.hpp"
4 
5 #include <chrono>
6 
7 #include "utils/clock.hpp"
8 
9 #include <cv_bridge/cv_bridge.h>
10 
11 // OPENCV includes
12 #include <opencv2/highgui/highgui.hpp>
13 #include <opencv2/imgproc/imgproc.hpp>
14 #include <opencv2/core/core.hpp>
15 
16 using namespace std;
17 using namespace galaxis::utils;
18 
19 using namespace AVT::VmbAPI;
20 using namespace cv;
21 
22 CameraFrameObserver::CameraFrameObserver( AVT::VmbAPI::CameraPtr camera ) : AVT::VmbAPI::IFrameObserver( camera ) {
23  m_currentImageSPtr = nullptr;
24 
25  m_cameraPtr = camera;
26  m_cameraPtr->FlushQueue();
27 }
28 
30  m_cameraPtr->FlushQueue();
31 }
32 
33 
34 void CameraFrameObserver::FrameReceived( const AVT::VmbAPI::FramePtr imgFrame ) {
35  auto timestampCameraImage = m_rosClock.now();
36  log("[CAMERA] [ALVIUM] Frame received!");
37 
38  VmbUint32_t nImageSize = 0;
39  if(VmbErrorSuccess != imgFrame->GetImageSize( nImageSize )) {
40  log_warning("[CAMERA] [ALVIUM] GetImageSize");
41  m_cameraPtr->QueueFrame(imgFrame);
42  return;
43  }
44  VmbUint32_t nWidth = 0;
45  if(VmbErrorSuccess != imgFrame->GetWidth( nWidth )) {
46  log_warning("[CAMERA] [ALVIUM] GetImageSize");
47  m_cameraPtr->QueueFrame(imgFrame);
48  return;
49  }
50  VmbUint32_t nHeight = 0;
51  if(VmbErrorSuccess != imgFrame->GetHeight( nHeight )) {
52  log_warning("[CAMERA] [ALVIUM] GetImageSize");
53  m_cameraPtr->QueueFrame(imgFrame);
54  return;
55  }
56 
57  // Get Image
58  unsigned char* imagePtr;
59  if(VmbErrorSuccess != imgFrame->GetImage( imagePtr )) {
60  log_warning("[CAMERA] [ALVIUM] GetImage");
61  m_cameraPtr->QueueFrame(imgFrame);
62  return;
63  }
64 
65  // COPY TO OPENCV (for resizing)
66  // Resize Parameters cv::Size(Width, Height)
67  auto outImgSize = cv::Size(512, 256);
68 
69  if(static_cast<float>(nHeight)/static_cast<float>(nWidth) != static_cast<float>(outImgSize.height)/static_cast<float>(outImgSize.width)) {
70  log_warning("[CAMERA] [ALVIUM] Camera Image Ratio NOT equal to desired Image Ration");
71  }
72 
73  cv::Mat img(nHeight, nWidth, CV_8UC3, imagePtr);
74  cv::Mat imgResize(outImgSize, CV_8UC3);
75  cv::resize(img, imgResize, outImgSize);
76 
77 
78  // release camera img frame => not used afterwards
79  m_cameraPtr->QueueFrame(imgFrame);
80 
81 
82  // create image msg and bridge to sensor image msg
83  std::shared_ptr<sensor_msgs::msg::Image> msgImgSPtr = std::make_shared<sensor_msgs::msg::Image>();
84  std_msgs::msg::Header header;
85  header.frame_id = "cam";
86  header.stamp = timestampCameraImage;
87 
88  m_bridgeImg = cv_bridge::CvImage(header, sensor_msgs::image_encodings::RGB8, imgResize);
89  m_bridgeImg.toImageMsg(*msgImgSPtr); // cv_bridge to sensor_msgs::Image
90 
91 
93  m_currentImageSPtr = msgImgSPtr;
94  m_newImageConditionVar.notify_one();
95  m_currentImageSPtrMutex.unlock();
96 
97 }
98 
99 std::shared_ptr<sensor_msgs::msg::Image> CameraFrameObserver::PopLastImage(bool blocking) {
100  std::unique_lock<std::mutex> lock(m_currentImageSPtrMutex);
101  std::shared_ptr<sensor_msgs::msg::Image> ret = m_currentImageSPtr;
102  m_currentImageSPtr = nullptr;
103 
104  // if return image is nullptr and blocking is enabled then wait for new image
105  if(ret == nullptr && blocking) {
106  m_newImageConditionVar.wait(lock); // release lock and wait until notify_one called
107  ret = m_currentImageSPtr;
108  m_currentImageSPtr = nullptr;
109  }
110 
111  return ret;
112 }
113 
114 
115 
116 AlviumAsyncCamera::AlviumAsyncCamera() : m_vimbaSystem(VimbaSystem::GetInstance()) {
117  m_runGrabbing = false;
118 
119  if(VmbErrorSuccess != m_vimbaSystem.Startup()) {
120  log_warning("[CAMERA] [ALVIUM] Vimba System failed to startup!");
121  }
122 }
123 
126  m_vimbaSystem.Shutdown();
127 }
128 
130  if(this->m_runGrabbing) {
131  m_camera->StopContinuousImageAcquisition();
132  delete m_frameObserver;
133  this->m_runGrabbing = false;
134  }
135 }
136 
137 std::shared_ptr<sensor_msgs::msg::Image> AlviumAsyncCamera::pop_image(bool blocking) {
138  if(m_frameObserver != nullptr) {
139  return m_frameObserver->PopLastImage(blocking);
140  }
141  else {
142  log_warning("[CAMERA] [ALVIUM] Frame Observer not initialized!");
143  return nullptr;
144  }
145 }
146 
148 
149  AVT::VmbAPI::CameraPtrVector cameraPtrVec;
150  // Get all known cameras
151  if ( VmbErrorSuccess != m_vimbaSystem.GetCameras( cameraPtrVec )){
152  log_warning("[CAMERA] [ALVIUM] Failed to get cameras!");
153  return false;
154  }
155 
156  if(cameraPtrVec.size() < 1) {
157  log_warning("[CAMERA] [ALVIUM] No camera found!");
158  return false;
159  }
160 
161  std::string cameraIdString;
162  if(VmbErrorSuccess != cameraPtrVec[0]->GetID(cameraIdString)) {
163  log_warning("[CAMERA] [ALVIUM] Failed to get the camera ID string.");
164  return false;
165  }
166 
167  // open camera
168  if(VmbErrorSuccess != m_vimbaSystem.OpenCameraByID(cameraIdString.c_str(), VmbAccessModeFull, m_camera)) {
169  log_warning("[CAMERA] [ALVIUM] Failed to open the camera.");
170  return false;
171  }
172 
173  // load settings
174  if(VmbErrorSuccess != m_camera->LoadCameraSettings("AlviumCameraVimbaSettings.xml")) {
175  log_warning("[CAMERA] [ALVIUM] Failed to load camera settings.");
176  return false;
177  }
178 
179  // // set to rgb8
180  // AVT::VmbAPI::FeaturePtr formatFeature;
181  // if(VmbErrorSuccess != m_camera->GetFeatureByName( "PixelFormat", formatFeature )) {
182  // log_warning("[CAMERA] [ALVIUM] Failed to get the pixel format feature.");
183  // }
184 
185  // if(VmbErrorSuccess != formatFeature->SetValue(VmbPixelFormatRgb8)) {
186  // log_warning("[CAMERA] [ALVIUM] Failed to get the pixel format feature.");
187  // }
188 
189  // // prepare for image transformation
190  // if( VmbErrorSuccess != SetIntFeatureValueModulo2( m_camera, "Width" ) ){
191  // log_warning("[CAMERA] [ALVIUM] Failed to set int feature.");
192  // }
193  // if( VmbErrorSuccess != SetIntFeatureValueModulo2( m_camera, "Height" ) ){
194  // log_warning("[CAMERA] [ALVIUM] Failed to set int feature.");
195  // }
196 
197  // create frame observer (This will be wrapped in a shared_ptr so we don't delete it)
199 
200  // start streaming
201  if(VmbErrorSuccess != m_camera->StartContinuousImageAcquisition( 100/*number_of_frames*/, IFrameObserverPtr( m_frameObserver ))) {
202  log_warning("[CAMERA] [ALVIUM] Failed to set start continuous image acquision.");
203  return false;
204  }
205 
206  this->m_runGrabbing = true;
207  return true;
208 }
AlviumAsyncCamera::stop_grabbing_detached
void stop_grabbing_detached()
Definition: AsyncCamera.cpp:129
CameraFrameObserver::PopLastImage
std::shared_ptr< sensor_msgs::msg::Image > PopLastImage(bool blocking)
Definition: AsyncCamera.cpp:99
CameraFrameObserver::m_currentImageSPtrMutex
std::mutex m_currentImageSPtrMutex
Definition: AsyncCamera.hpp:28
AlviumAsyncCamera::AlviumAsyncCamera
AlviumAsyncCamera()
Definition: AsyncCamera.cpp:116
AsyncCamera.hpp
galaxis::utils::log_warning
void log_warning(const Args &... args)
Definition: logger.hpp:41
clock.hpp
AlviumAsyncCamera::~AlviumAsyncCamera
~AlviumAsyncCamera()
Definition: AsyncCamera.cpp:124
CameraFrameObserver::CameraFrameObserver
CameraFrameObserver(AVT::VmbAPI::CameraPtr camera)
Definition: AsyncCamera.cpp:22
CameraFrameObserver::FrameReceived
virtual void FrameReceived(const AVT::VmbAPI::FramePtr pFrame)
Definition: AsyncCamera.cpp:34
CameraFrameObserver
Definition: AsyncCamera.hpp:24
CameraFrameObserver::~CameraFrameObserver
~CameraFrameObserver()
Definition: AsyncCamera.cpp:29
AlviumAsyncCamera::pop_image
std::shared_ptr< sensor_msgs::msg::Image > pop_image(bool blocking)
Definition: AsyncCamera.cpp:137
AlviumAsyncCamera::m_runGrabbing
std::atomic< bool > m_runGrabbing
Definition: AsyncCamera.hpp:47
CameraFrameObserver::m_rosClock
rclcpp::Clock m_rosClock
Definition: AsyncCamera.hpp:31
CameraFrameObserver::m_newImageConditionVar
std::condition_variable m_newImageConditionVar
Definition: AsyncCamera.hpp:29
AlviumAsyncCamera::m_frameObserver
CameraFrameObserver * m_frameObserver
Definition: AsyncCamera.hpp:45
AlviumAsyncCamera::m_vimbaSystem
VimbaSystem & m_vimbaSystem
Definition: AsyncCamera.hpp:49
CameraFrameObserver::m_bridgeImg
cv_bridge::CvImage m_bridgeImg
Definition: AsyncCamera.hpp:26
CameraFrameObserver::m_currentImageSPtr
std::shared_ptr< sensor_msgs::msg::Image > m_currentImageSPtr
Definition: AsyncCamera.hpp:27
logger.hpp
galaxis::utils
Definition: clock.hpp:5
galaxis::utils::log
void log(const Args &... args)
Definition: logger.hpp:33
AlviumAsyncCamera::m_camera
AVT::VmbAPI::CameraPtr m_camera
Definition: AsyncCamera.hpp:50
CameraFrameObserver::m_cameraPtr
AVT::VmbAPI::CameraPtr m_cameraPtr
Definition: AsyncCamera.hpp:33
AlviumAsyncCamera::start_grabbing_detached
bool start_grabbing_detached()
Definition: AsyncCamera.cpp:147