123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- #include <iostream>
- #include <string>
- #include <sstream>
- #include <stdexcept>
- #include <unistd.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <ros/ros.h>
- #include <sensor_msgs/image_encodings.h>
- #include <sensor_msgs/Image.h>
- #include <sensor_msgs/CameraInfo.h>
- #include <tf/transform_broadcaster.h>
- #include <tf/transform_datatypes.h>
- #include "opencv2/core/core.hpp"
- #include "opencv2/highgui/highgui.hpp"
- #include <opencv2/imgproc/imgproc.hpp>
- #include "ladybug.h"
- #include "ladybugstream.h"
- using namespace std;
- static volatile int running_ = 1;
- LadybugContext m_context;
- LadybugDataFormat m_dataFormat;
- //camera config settings
- float m_frameRate;
- bool m_isFrameRateAuto;
- unsigned int m_jpegQualityPercentage;
- ros::Publisher pub[LADYBUG_NUM_CAMERAS + 1];
- static void signalHandler(int)
- {
- running_ = 0;
- ros::shutdown();
- }
- void parseCameraInfo(const cv::Mat &camMat,
- const cv::Mat &disCoeff,
- const cv::Size &imgSize,
- sensor_msgs::CameraInfo &msg)
- {
- msg.header.frame_id = "camera";
- msg.height = imgSize.height;
- msg.width = imgSize.width;
- for (int row=0; row<3; row++)
- {
- for (int col=0; col<3; col++)
- {
- msg.K[row * 3 + col] = camMat.at<double>(row, col);
- }
- }
- for (int row=0; row<3; row++)
- {
- for (int col=0; col<4; col++)
- {
- if (col == 3)
- {
- msg.P[row * 4 + col] = 0.0f;
- } else
- {
- msg.P[row * 4 + col] = camMat.at<double>(row, col);
- }
- }
- }
- for (int row=0; row<disCoeff.rows; row++)
- {
- for (int col=0; col<disCoeff.cols; col++)
- {
- msg.D.push_back(disCoeff.at<double>(row, col));
- }
- }
- }
- void GetMatricesFromFile(ros::NodeHandle nh, sensor_msgs::CameraInfo &camerainfo_msg)
- {
- //////////////////CAMERA INFO/////////////////////////////////////////
- cv::Mat cameraExtrinsicMat;
- cv::Mat cameraMat;
- cv::Mat distCoeff;
- cv::Size imageSize;
- std::string filename;
- if (nh.getParam("calibrationfile", filename) && filename!="")
- {
- ROS_INFO("Trying to parse calibrationfile :");
- ROS_INFO("> %s", filename.c_str());
- }
- else
- {
- ROS_INFO("No calibrationfile param was received");
- return;
- }
- cv::FileStorage fs(filename, cv::FileStorage::READ);
- if (!fs.isOpened())
- {
- ROS_INFO("Cannot open %s", filename.c_str());;
- return;
- }
- else
- {
- fs["CameraMat"] >> cameraMat;
- fs["DistCoeff"] >> distCoeff;
- fs["ImageSize"] >> imageSize;
- }
- parseCameraInfo(cameraMat, distCoeff, imageSize, camerainfo_msg);
- }
- void publishImage(cv::Mat& image, ros::Publisher& image_pub, long int& count, size_t camera_id)
- {
- sensor_msgs::Image msg;
- //publish*******************
- msg.header.seq = count;
- std::string frame = "camera" + std::to_string(camera_id);
- msg.header.frame_id = frame;
- msg.header.stamp.sec = ros::Time::now().sec; msg.header.stamp.nsec = ros::Time::now().nsec;
- msg.height = image.size().height; msg.width = image.size().width;
- msg.encoding = "rgb8";
- msg.step = image.cols * image.elemSize();
- size_t image_size = image.rows * image.cols * image.elemSize();
- msg.data.resize(image_size);
- memcpy(msg.data.data(), image.data, image_size);
- image_pub.publish(msg);
- }
- LadybugError init_camera()
- {
- LadybugError error;
- error = ladybugCreateContext(&m_context);
- if (error != LADYBUG_OK)
- {
- throw std::runtime_error("Unable to create Ladybug context.");
- }
- LadybugCameraInfo enumeratedCameras[16];
- unsigned int numCameras = 16;
- error = ladybugBusEnumerateCameras(m_context, enumeratedCameras, &numCameras);
- if (error != LADYBUG_OK)
- {
- return error;
- }
- cout << "Cameras detected: " << numCameras << endl << endl;
- if (numCameras == 0)
- {
- ROS_INFO("Insufficient number of cameras detected. ");
- return LADYBUG_FAILED;
- }
- error = ladybugInitializeFromIndex(m_context, 0);
- if (error != LADYBUG_OK)
- {
- return error;
- }
- LadybugCameraInfo camInfo;
- error = ladybugGetCameraInfo(m_context, &camInfo);
- if (error != LADYBUG_OK)
- {
- return error;
- }
- ROS_INFO("Camera information: ");
- ROS_INFO("Base s/n: %d", camInfo.serialBase );
- ROS_INFO("Head s/n: %d", camInfo.serialHead );
- ROS_INFO("Model: %s", camInfo.pszModelName );
- ROS_INFO("Sensor: %s", camInfo.pszSensorInfo);
- ROS_INFO("Vendor: %s", camInfo.pszVendorName);
- ROS_INFO("Bus / Node: %d ,%d" , camInfo.iBusNum , camInfo.iNodeNum );
- switch (camInfo.deviceType)
- {
- case LADYBUG_DEVICE_LADYBUG3:
- {
- m_dataFormat = LADYBUG_DATAFORMAT_RAW8;
- m_frameRate = 16.0f;
- m_isFrameRateAuto = true;
- m_jpegQualityPercentage = 80;
- }
- break;
- case LADYBUG_DEVICE_LADYBUG5:
- {
- m_dataFormat = LADYBUG_DATAFORMAT_RAW8;
- m_frameRate = 10.0f;
- m_isFrameRateAuto = true;
- m_jpegQualityPercentage = 80;
- }
- break;
- default: assert(false); break;
- }
- return error;
- }
- LadybugError start_camera()
- {
- LadybugError error;
- error = ladybugStartLockNext(m_context, m_dataFormat);
- if (error != LADYBUG_OK)
- {
- return error;
- }
- error = ladybugSetAbsPropertyEx(m_context, LADYBUG_FRAME_RATE, false, true, m_isFrameRateAuto, m_frameRate);
- if (error != LADYBUG_OK)
- {
- return error;
- }
- error = ladybugSetJPEGQuality(m_context, m_jpegQualityPercentage);
- if (error != LADYBUG_OK)
- {
- return error;
- }
- // Perform a quick test to make sure images can be successfully acquired
- for (int i=0; i < 10; i++)
- {
- LadybugImage tempImage;
- error = ladybugLockNext(m_context, &tempImage);
- }
- error = ladybugUnlockAll(m_context);
- if (error != LADYBUG_OK)
- {
- return error;
- }
- return error;
- }
- LadybugError stop_camera()
- {
- const LadybugError cameraError = ladybugStop(m_context);
- if (cameraError != LADYBUG_OK)
- {
- ROS_INFO("Error: Unable to stop camera (%s)", ladybugErrorToString(cameraError) );
- }
- return cameraError;
- }
- LadybugError acquire_image( LadybugImage& image )
- {
- return ladybugLockNext(m_context, &image);
- }
- LadybugError unlock_image( unsigned int bufferIndex )
- {
- return ladybugUnlock(m_context, bufferIndex);
- }
- int main (int argc, char **argv)
- {
- ////ROS STUFF
- ros::init(argc, argv, "ladybug_camera");
- ros::NodeHandle n;
- ros::NodeHandle private_nh("~");
- signal(SIGTERM, signalHandler);//detect closing
- /////////////////////////////
- //Config camera
- m_dataFormat = LADYBUG_DATAFORMAT_RAW8;
- m_frameRate = 10;
- m_isFrameRateAuto = true;
- m_jpegQualityPercentage = 80;
- // Initialize ladybug camera
- const LadybugError grabberInitError = init_camera();
- if (LADYBUG_OK != init_camera())
- {
- ROS_INFO("Error: Failed to initialize camera (%s). Terminating...", ladybugErrorToString(grabberInitError) );
- return -1;
- }
- LadybugCameraInfo camInfo;
- if (LADYBUG_OK != ladybugGetCameraInfo(m_context, &camInfo))
- {
- ROS_INFO("Error: Failed to get camera information. Terminating...");
- return -1;
- }
- const LadybugError startError = start_camera();
- if (startError != LADYBUG_OK)
- {
- ROS_INFO("Error: Failed to start camera (%s). Terminating...", ladybugErrorToString(startError) );
- return -1;
- }
- /////////////////////
- //ROS
- // Get the camera information
- ///////calibration data
- sensor_msgs::CameraInfo camerainfo_msg;
- GetMatricesFromFile(private_nh, camerainfo_msg);
- int image_scale = 100;
- if (private_nh.getParam("scale", image_scale) && image_scale>0 && image_scale<100)
- {
- ROS_INFO("Ladybug ImageScale > %i%%", image_scale);
- }
- else
- {
- ROS_INFO("Ladybug ImageScale scale must be (0,100]. Defaulting to 20 ");
- image_scale=20;
- }
- ros::Publisher camera_info_pub;
- camera_info_pub = n.advertise<sensor_msgs::CameraInfo>("/camera/camera_info", 1, true);
- ROS_INFO("Successfully started ladybug camera and stream");
- for (int i = 0; i < LADYBUG_NUM_CAMERAS + 1; i++) {
- std::string topic(std::string("image_raw"));
- topic = "camera" + std::to_string(i) + "/" + topic;
- pub[i] = n.advertise<sensor_msgs::Image>(topic, 100);
- ROS_INFO("Publishing.. %s", topic.c_str());
- }
- //////////////////
- //start camera
- ros::Rate loop_rate(10); // Hz Ladybug works at 10fps
- long int count = 0;
- while (running_ && ros::ok())
- {
- LadybugImage currentImage;
- const LadybugError acquisitionError = acquire_image(currentImage);
- if (acquisitionError != LADYBUG_OK)
- {
- ROS_INFO("Failed to acquire image. Error (%s). Trying to continue..", ladybugErrorToString(acquisitionError) );
- continue;
- }
- // convert to OpenCV Mat
- //receive Bayer Image, convert to Color 3 channels
- cv::Size size(currentImage.uiFullCols, currentImage.uiFullRows);
- cv::Mat full_size;
- for(size_t i =0;i<LADYBUG_NUM_CAMERAS; i++)
- {
- std::ostringstream out;
- out << "image" << i;
- cv::Mat rawImage(size, CV_8UC1, currentImage.pData + (i * size.width*size.height));
- cv::Mat image(size, CV_8UC3);
- cv::cvtColor(rawImage, image, cv::COLOR_BayerBG2RGB);
- cv::resize(image,image,cv::Size(size.width*image_scale/100, size.height*image_scale/100));
- //
- cv::transpose(image, image);
- cv::flip(image, image, 1);
- if (i==0)
- image.copyTo(full_size);
- else
- cv::hconcat(image, full_size, full_size);
- unlock_image(currentImage.uiBufferIndex);
- publishImage(image, pub[LADYBUG_NUM_CAMERAS - i], count, LADYBUG_NUM_CAMERAS - i);
- }
- //publish stitched one
- publishImage(full_size, pub[0], count, LADYBUG_NUM_CAMERAS);
- ros::spinOnce();
- loop_rate.sleep();
- count++;
- }
- cout << "Stopping ladybug_camera..." << endl;
- // Shutdown
- stop_camera();
- ROS_INFO("ladybug_camera stopped");
- return 0;
- }
|