spinnaker.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright 2015-2019 Autoware Foundation. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <thread>
  17. #include <sstream>
  18. #include <iostream>
  19. #include <ros/ros.h>
  20. #include <cv_bridge/cv_bridge.h>
  21. #include <image_transport/image_transport.h>
  22. #include <std_msgs/Header.h>
  23. #include <sensor_msgs/CameraInfo.h>
  24. #include <sensor_msgs/Image.h>
  25. #include <sensor_msgs/image_encodings.h>
  26. #include <opencv2/core/core.hpp>
  27. #include "SpinGenApi/SpinnakerGenApi.h"
  28. #include "Spinnaker.h"
  29. using namespace Spinnaker;
  30. using namespace Spinnaker::GenApi;
  31. using namespace Spinnaker::GenICam;
  32. using namespace std;
  33. #define __APP_NAME__ "autoware_spinnaker"
  34. class SpinnakerCamera
  35. {
  36. public:
  37. SpinnakerCamera();
  38. ~SpinnakerCamera();
  39. void spin();
  40. void publish_image(int);
  41. private:
  42. ros::NodeHandle nh_, private_nh_;
  43. image_transport::ImageTransport* image_transport_;
  44. std::vector<image_transport::Publisher> image_pubs_;
  45. Spinnaker::SystemPtr system_;
  46. Spinnaker::CameraList camList_;
  47. CameraPtr* pCamList_;
  48. // config
  49. int width_;
  50. int height_;
  51. double fps_;
  52. int dltl_;
  53. std::string format_;
  54. Spinnaker::GenApi::INodeMap* node_map_;
  55. };
  56. SpinnakerCamera::SpinnakerCamera()
  57. : nh_()
  58. , private_nh_("~")
  59. , system_(Spinnaker::System::GetInstance())
  60. , camList_(system_->GetCameras())
  61. , width_(0)
  62. , height_(0)
  63. , fps_(0)
  64. , dltl_(0)
  65. {
  66. private_nh_.param("width", width_, 1440);
  67. private_nh_.param("height", height_, 1080);
  68. private_nh_.param("fps", fps_, 60.0);
  69. private_nh_.param("dltl", dltl_, 100000000);
  70. unsigned int num_cameras = camList_.GetSize();
  71. ROS_INFO_STREAM("[" << __APP_NAME__ << "] Number of cameras detected: " << num_cameras);
  72. if (num_cameras < 1)
  73. {
  74. ROS_ERROR("[%s] Error: This program requires at least 1 camera.", __APP_NAME__);
  75. camList_.Clear();
  76. system_->ReleaseInstance();
  77. std::exit(-1);
  78. }
  79. image_transport_ = new image_transport::ImageTransport(nh_);
  80. pCamList_ = new CameraPtr[num_cameras];
  81. try
  82. {
  83. vector<gcstring> strSerialNumbers(camList_.GetSize());
  84. for (int i = 0; i < camList_.GetSize(); i++)
  85. {
  86. pCamList_[i] = camList_.GetByIndex(i);
  87. pCamList_[i]->Init();
  88. node_map_ = &pCamList_[i]->GetNodeMap();
  89. // config
  90. pCamList_[i]->Width.SetValue(width_);
  91. pCamList_[i]->Height.SetValue(height_);
  92. CEnumerationPtr ptrDeviceType = pCamList_[i]->GetTLDeviceNodeMap().GetNode("DeviceType");
  93. if (IsAvailable(ptrDeviceType) && ptrDeviceType->GetCurrentEntry()->GetSymbolic() == "GEV")
  94. {
  95. /////////////////////// DeviceLinkThroughputLimit /////////////////////////////
  96. CIntegerPtr ptrDeviceLinkThroughputLimit = node_map_->GetNode("DeviceLinkThroughputLimit");
  97. if (IsAvailable(ptrDeviceLinkThroughputLimit) && IsWritable(ptrDeviceLinkThroughputLimit))
  98. {
  99. ROS_INFO_STREAM("[" << __APP_NAME__
  100. << "] DeviceLinkThroughputLimit: " << ptrDeviceLinkThroughputLimit->GetValue());
  101. ptrDeviceLinkThroughputLimit->SetValue(dltl_);
  102. }
  103. else
  104. {
  105. ROS_WARN("[%s] This camera does not support DeviceLinkThroughputLimit, using default value.", __APP_NAME__);
  106. }
  107. }
  108. /////////////////////// FrameRate /////////////////////////////
  109. CFloatPtr ptrAcquisitionFrameRate = node_map_->GetNode("AcquisitionFrameRate");
  110. CBooleanPtr ptrAcquisitionFrameRateEnable = node_map_->GetNode("AcquisitionFrameRateEnable");
  111. CEnumerationPtr ptrAcquisitionFrameRateAuto = pCamList_[i]->GetNodeMap().GetNode("AcquisitionFrameRateAuto");
  112. if (IsAvailable(ptrAcquisitionFrameRateAuto) && IsWritable(ptrAcquisitionFrameRateAuto))
  113. {
  114. CEnumEntryPtr ptrAcquisitionFrameRateAutoOff = ptrAcquisitionFrameRateAuto->GetEntryByName("Off");
  115. if (IsAvailable(ptrAcquisitionFrameRateAutoOff) && IsReadable(ptrAcquisitionFrameRateAutoOff))
  116. {
  117. int64_t FrameRateAutoOff = ptrAcquisitionFrameRateAutoOff->GetValue();
  118. ptrAcquisitionFrameRateAuto->SetIntValue(FrameRateAutoOff);
  119. ROS_INFO_STREAM("[" << __APP_NAME__ << "] Updated FrameRateAuto to Off");
  120. }
  121. else
  122. {
  123. ROS_INFO_STREAM("[" << __APP_NAME__ << "] Cannot update FrameRateAuto to Off");
  124. }
  125. }
  126. if (IsAvailable(ptrAcquisitionFrameRateEnable) && IsWritable(ptrAcquisitionFrameRateEnable))
  127. {
  128. ptrAcquisitionFrameRateEnable->SetValue(true);
  129. }
  130. if (IsAvailable(ptrAcquisitionFrameRate) && IsWritable(ptrAcquisitionFrameRate))
  131. {
  132. ptrAcquisitionFrameRate->SetValue(fps_);
  133. ROS_INFO_STREAM("[" << __APP_NAME__ << "] Set FrameRate to " << fps_);
  134. }
  135. else
  136. {
  137. ROS_WARN("[%s] This camera does not support AcquisitionFrameRate, using default value.", __APP_NAME__);
  138. }
  139. /////////////////////// PixelFormat /////////////////////////////
  140. CEnumerationPtr ptrPixelFormat = node_map_->GetNode("PixelFormat");
  141. if (IsAvailable(ptrPixelFormat) && IsWritable(ptrPixelFormat))
  142. {
  143. ROS_INFO_STREAM("[" << __APP_NAME__ << "] Current pixel Format"
  144. << ptrPixelFormat->GetCurrentEntry()->GetSymbolic());
  145. /*gcstring pixel_format = format_.c_str();
  146. CEnumEntryPtr ptrPixelFormatSetup = ptrPixelFormat->GetEntryByName(pixel_format);
  147. if (IsAvailable(ptrPixelFormatSetup) && IsReadable(ptrPixelFormatSetup))
  148. {
  149. int64_t pixelFormatSetup = ptrPixelFormatSetup->GetValue();
  150. ptrPixelFormat->SetIntValue(ptrPixelFormatSetup);
  151. ROS_INFO_STREAM("[" << __APP_NAME__ << "] Pixel format set to " <<
  152. ptrPixelFormat->GetCurrentEntry()->GetSymbolic());
  153. }
  154. else
  155. {
  156. ROS_WARN("[%s] %s pixel format not available. Using default.", __APP_NAME__, format_.c_str());
  157. }*/
  158. }
  159. else
  160. {
  161. ROS_WARN("[%s] Pixel format cannot be changed on this camera. Using default.", __APP_NAME__);
  162. }
  163. /////////////////////// AcquisitionMode /////////////////////////////
  164. CEnumerationPtr ptrAcquisitionMode = pCamList_[i]->GetNodeMap().GetNode("AcquisitionMode");
  165. if (!IsAvailable(ptrAcquisitionMode) || !IsWritable(ptrAcquisitionMode))
  166. {
  167. ROS_FATAL("[%s] Unable to set acquisition mode to continuous (node retrieval; "
  168. "camera ",
  169. __APP_NAME__);
  170. }
  171. /////////////////////// ContinuousMode /////////////////////////////
  172. CEnumEntryPtr ptrAcquisitionModeContinuous = ptrAcquisitionMode->GetEntryByName("Continuous");
  173. if (!IsAvailable(ptrAcquisitionModeContinuous) || !IsReadable(ptrAcquisitionModeContinuous))
  174. {
  175. ROS_FATAL("[%s] Unable to set acquisition mode to continuous (entry "
  176. "'continuous' retrieval. Aborting...",
  177. __APP_NAME__);
  178. }
  179. int64_t acquisitionModeContinuous = ptrAcquisitionModeContinuous->GetValue();
  180. ptrAcquisitionMode->SetIntValue(acquisitionModeContinuous);
  181. ROS_INFO("[%s] [camera %d] acquisition mode set to continuous...", __APP_NAME__, i);
  182. strSerialNumbers[i] = "";
  183. CStringPtr ptrStringSerial = pCamList_[i]->GetTLDeviceNodeMap().GetNode("DeviceSerialNumber");
  184. if (IsAvailable(ptrStringSerial) && IsReadable(ptrStringSerial))
  185. {
  186. strSerialNumbers[i] = ptrStringSerial->GetValue();
  187. ROS_INFO("[%s] [camera %d] serial number set to %s", __APP_NAME__, i, strSerialNumbers[i].c_str());
  188. }
  189. std::string topic("image_raw");
  190. if (camList_.GetSize() > 1)
  191. topic = "camera" + std::to_string(i) + "/" + topic;
  192. image_pubs_.push_back(image_transport_->advertise(topic, 100));
  193. }
  194. }
  195. catch (Spinnaker::Exception& e)
  196. {
  197. ROS_ERROR("[%s] Error: %s", __APP_NAME__, e.what());
  198. }
  199. }
  200. SpinnakerCamera::~SpinnakerCamera()
  201. {
  202. for (int i = 0; i < camList_.GetSize(); i++)
  203. {
  204. pCamList_[i]->EndAcquisition();
  205. pCamList_[i]->DeInit();
  206. pCamList_[i] = NULL;
  207. ROS_INFO("[%s] Shutting down camera %d", __APP_NAME__, i);
  208. }
  209. delete[] pCamList_;
  210. node_map_ = NULL;
  211. camList_.Clear();
  212. system_->ReleaseInstance();
  213. }
  214. void SpinnakerCamera::publish_image(int index)
  215. {
  216. while (ros::ok())
  217. {
  218. try
  219. {
  220. ImagePtr pResultImage = pCamList_[index]->GetNextImage();
  221. if (pResultImage->IsIncomplete())
  222. {
  223. ROS_WARN("[%s] [camera %d] Image incomplete with image status %d", __APP_NAME__, index,
  224. pResultImage->GetImageStatus());
  225. }
  226. else
  227. {
  228. ros::Time receive_time = ros::Time::now();
  229. // create opencv mat
  230. int pixel_format = pResultImage->GetPixelFormat();
  231. std::string encoding_pattern;
  232. switch (pixel_format)
  233. {
  234. case PixelFormatEnums::PixelFormat_BayerRG8:
  235. encoding_pattern = "bayer_rggb8";
  236. break;
  237. case PixelFormatEnums::PixelFormat_BayerGR8:
  238. encoding_pattern = "bayer_grbg8";
  239. break;
  240. case PixelFormatEnums::PixelFormat_BayerGB8:
  241. encoding_pattern = "bayer_gbrg8";
  242. break;
  243. case PixelFormatEnums::PixelFormat_BayerBG8:
  244. encoding_pattern = "bayer_bggr8";
  245. break;
  246. case PixelFormatEnums::PixelFormat_RGB8:
  247. encoding_pattern = "rgb8";
  248. break;
  249. case PixelFormatEnums::PixelFormat_BGR8:
  250. encoding_pattern = "bgr8";
  251. break;
  252. default:
  253. encoding_pattern = "mono8";
  254. }
  255. unsigned int XPadding = pResultImage->GetXPadding();
  256. unsigned int YPadding = pResultImage->GetYPadding();
  257. unsigned int rowsize = pResultImage->GetWidth();
  258. unsigned int colsize = pResultImage->GetHeight();
  259. // create and publish ros message
  260. std_msgs::Header header;
  261. sensor_msgs::Image msg;
  262. header.stamp = receive_time;
  263. header.frame_id = (camList_.GetSize() > 1) ? "camera" + std::to_string(index) : "camera";
  264. msg.header = header;
  265. msg.height = pResultImage->GetHeight();
  266. msg.width = pResultImage->GetWidth();
  267. msg.encoding = encoding_pattern;
  268. msg.step = pResultImage->GetStride();
  269. size_t image_size = pResultImage->GetImageSize();
  270. msg.data.resize(image_size);
  271. memcpy(msg.data.data(), pResultImage->GetData(), image_size);
  272. image_pubs_[index].publish(msg);
  273. }
  274. pResultImage->Release();
  275. }
  276. catch (Spinnaker::Exception& e)
  277. {
  278. ROS_ERROR("[%s] Error: %s", __APP_NAME__, e.what());
  279. }
  280. }
  281. }
  282. void SpinnakerCamera::spin()
  283. {
  284. for (int i = 0; i < camList_.GetSize(); i++)
  285. {
  286. pCamList_[i]->BeginAcquisition();
  287. ROS_INFO("[%s] [camera %d] started acquisition", __APP_NAME__, i);
  288. }
  289. vector<std::shared_ptr<std::thread>> threads(camList_.GetSize());
  290. for (int i = 0; i < camList_.GetSize(); i++)
  291. {
  292. threads[i] = make_shared<thread>(&SpinnakerCamera::publish_image, this, i);
  293. }
  294. for (auto& thread : threads)
  295. {
  296. thread->join();
  297. }
  298. }
  299. int main(int argc, char** argv)
  300. {
  301. ros::init(argc, argv, "spinnaker");
  302. SpinnakerCamera node;
  303. node.spin();
  304. return 0;
  305. }