00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <cv_bridge/CvBridge.h>
00028 #include <GL/glew.h>
00029 #include <GL/gl.h>
00030 #include <GL/glut.h>
00031 #include <image_transport/image_transport.h>
00032 #include <math.h>
00033 #include <opencv2/core/core.hpp>
00034 #include <opencv2/highgui/highgui.hpp>
00035 #include <ros/ros.h>
00036 #include <sys/param.h>
00037 #include <sys/times.h>
00038
00039 #include "Camera.h"
00040 #include "CameraContext.h"
00041 #include "CameraException.h"
00042 #include "LadybugCamera.h"
00043 #include "LadybugVirtualCamera.h"
00044
00045 #include "omnicamera_msgs/GetLadybugCameraConfig.h"
00046 #include "omnicamera_msgs/GetVirtualCameraConfig.h"
00047 #include "omnicamera_msgs/VirtualCameraConfig.h"
00048 #include "omnicamera_msgs/LadybugCameraConfig.h"
00049
00050 using std::string;
00051
00052 using nifti::dc1394::Camera;
00053 using nifti::dc1394::CameraContext;
00054 using nifti::dc1394::CameraException;
00055 using nifti::dc1394::LadybugCamera;
00056 using nifti::ladybug::LadybugVirtualCamera;
00057
00058 using omnicamera_msgs::GetVirtualCameraConfig;
00059 using omnicamera_msgs::GetLadybugCameraConfig;
00060 using omnicamera_msgs::LadybugCameraConfig;
00061 using omnicamera_msgs::VirtualCameraConfig;
00062
00063 namespace {
00064 LadybugVirtualCamera virtualCamera;
00065 bool virtualCameraEnabled = false;
00066 LadybugCamera camera;
00067 LadybugCameraConfig ladybugCameraConfig;
00068 VirtualCameraConfig virtualCameraConfig;
00069 sensor_msgs::CvBridge bridge;
00070
00071 double imageUpdateInterval = 5.0;
00072
00076 pthread_mutex_t virtualCameraMutex;
00077 void lockVirtualCamera();
00078 void unlockVirtualCamera();
00079
00080 bool
00081 getLadybugCameraConfigService(GetLadybugCameraConfig::Request& request, GetLadybugCameraConfig::Response& response);
00082 void ladybugCameraConfigCallback(const LadybugCameraConfig::ConstPtr& msg);
00083
00084 bool
00085 getVirtualCameraConfigService(GetVirtualCameraConfig::Request& request, GetVirtualCameraConfig::Response& response);
00086 void virtualCameraConfigCallback(const VirtualCameraConfig::ConstPtr& msg);
00087
00088 void logDuration(string message, tms t1, long r1);
00089 }
00090
00091 int main(int argc, char** argv) {
00092
00093 ros::init(argc, argv, "omnicamera");
00094 ros::NodeHandle nodeHandle;
00095
00096 for (int i = 0; i < argc; i++) {
00097 printf("%d: %s\n", i, argv[i]);
00098 }
00099
00100
00101 string meshFile;
00102 string alphamaskPrefix;
00103 if (argc < 3) {
00104 printf("Not enough arguments. Virtual camera is not used.\n");
00105 printf("Usage: omnicamera_node <mesh file path> <alphamask file prefix>\n");
00106 printf("Example: omnicamera_node mesh.txt alphamask\n");
00107 } else {
00108 virtualCameraEnabled = true;
00109 meshFile = string(argv[1]);
00110 alphamaskPrefix = string(argv[2]);
00111 glutInit(&argc, argv);
00112 }
00113
00114 pthread_mutex_init(&virtualCameraMutex, NULL);
00115
00116 ros::Subscriber virtualCameraConfigSubscriber;
00117 ros::ServiceServer getVirtualCameraConfigServer;
00118 if (virtualCameraEnabled) {
00119 virtualCameraConfigSubscriber = nodeHandle.subscribe("virtual_camera/config", 1,
00120 virtualCameraConfigCallback);
00121 getVirtualCameraConfigServer = nodeHandle.advertiseService("virtual_camera/get_config",
00122 getVirtualCameraConfigService);
00123 }
00124
00125 ros::Subscriber ladybugCameraConfigSubscriber = nodeHandle.subscribe("ladybug_camera/config", 1,
00126 ladybugCameraConfigCallback);
00127 ros::ServiceServer getLadybugCameraConfigServer = nodeHandle.advertiseService("ladybug_camera/get_config",
00128 getLadybugCameraConfigService);
00129
00130 image_transport::ImageTransport it(nodeHandle);
00131 image_transport::Publisher virtualCameraPub = it.advertise("virtual_camera/image", 1);
00132
00133 image_transport::Publisher cameraPub = it.advertise("camera/image", 1);
00134
00135 image_transport::Publisher sensorPubs[LadybugCamera::NUM_CAMERAS] = { it.advertise("camera0/image", 1), it.advertise(
00136 "camera1/image", 1), it.advertise("camera2/image", 1), it.advertise("camera3/image", 1), it.advertise(
00137 "camera4/image", 1), it.advertise("camera5/image", 1) };
00138
00139 ros::Publisher cameraInfoPubs[LadybugCamera::NUM_CAMERAS] = {
00140 nodeHandle.advertise<sensor_msgs::CameraInfo>("camera0/camera_info", 1),
00141 nodeHandle.advertise<sensor_msgs::CameraInfo>("camera1/camera_info", 1),
00142 nodeHandle.advertise<sensor_msgs::CameraInfo>("camera2/camera_info", 1),
00143 nodeHandle.advertise<sensor_msgs::CameraInfo>("camera3/camera_info", 1),
00144 nodeHandle.advertise<sensor_msgs::CameraInfo>("camera4/camera_info", 1),
00145 nodeHandle.advertise<sensor_msgs::CameraInfo>("camera5/camera_info", 1) };
00146
00147 string cameraFrameIds[LadybugCamera::NUM_CAMERAS] = { "tflbcamera0", "tflbcamera1", "tflbcamera2", "tflbcamera3", "tflbcamera4", "tflbcamera5" };
00148
00149 try {
00150
00151 if (virtualCameraEnabled) {
00152 virtualCamera.initialize(true);
00153 virtualCamera.loadMesh(meshFile);
00154 virtualCamera.loadAlphamask(alphamaskPrefix);
00155 }
00156
00157 CameraContext context;
00158
00159
00160
00161 camera = context.getLadybugCamera(0);
00162 camera.resetBus();
00163 sleep(3);
00164 camera.reset();
00165
00166
00167 camera.setOperationMode(DC1394_OPERATION_MODE_LEGACY);
00168 camera.setIsoSpeed(DC1394_ISO_SPEED_400);
00169
00170
00171
00172 dc1394video_mode_t videoMode = DC1394_VIDEO_MODE_FORMAT7_2;
00173 camera.setVideoMode(videoMode);
00174 camera.setSelectedImages(LadybugCamera::ALL_CAMERAS);
00175
00176
00177
00178
00179 camera.setFormat7Roi(videoMode, 4096);
00180 camera.setBayerMethod(DC1394_BAYER_METHOD_SIMPLE);
00181
00182
00183 camera.setupCapture();
00184 camera.startVideoTransmission();
00185
00186 struct tms t2;
00187 long r1 = 0l;
00188 long r2 = 0l;
00189
00190 uint32_t seq = 0;
00191 ros::Rate r(5);
00192 while (nodeHandle.ok()) {
00193 ros::spinOnce();
00194
00195 cv::Mat compositeImage;
00196 uint64_t timestamp;
00197 camera.captureColorMat(compositeImage, timestamp, true);
00198
00199
00200 if (videoMode == DC1394_VIDEO_MODE_FORMAT7_2 || videoMode == DC1394_VIDEO_MODE_FORMAT7_3) {
00201 cv::Mat dst;
00202 cv::resize(compositeImage, dst, cv::Size(compositeImage.cols / 2, compositeImage.rows), 0, 0, CV_INTER_NN);
00203 compositeImage = dst;
00204 }
00205
00206 ros::Time imageTime = ros::Time(static_cast<double>(timestamp) / 1000000.0);
00207
00208 if (cameraPub.getNumSubscribers() > 0) {
00209 IplImage iplImage = compositeImage;
00210 sensor_msgs::ImagePtr msg = bridge.cvToImgMsg(&iplImage, "bgr8");
00211
00212 msg->header.frame_id = "/omni_frame";
00213 msg->header.seq = seq;
00214 msg->header.stamp = imageTime;
00215 cameraPub.publish(msg);
00216 }
00217
00218 int iImage = -1;
00219 for (int i = 0; i < LadybugCamera::NUM_CAMERAS; i++) {
00220 if (!camera.areImagesSelected(LadybugCamera::CAMERAS[i])) {
00221 continue;
00222 }
00223 iImage++;
00224 if (sensorPubs[i].getNumSubscribers() > 0) {
00225 int imageHeight = compositeImage.rows / camera.getNumSelectedImages();
00226
00227
00228 cv::Mat image = compositeImage(cv::Rect(0, iImage * imageHeight, compositeImage.cols, imageHeight)).t();
00229
00230 cv::flip(image, image, 1);
00231
00232 IplImage iplSensorImage = image;
00233 sensor_msgs::ImagePtr msg = bridge.cvToImgMsg(&iplSensorImage, "bgr8");
00234 msg->header.frame_id = cameraFrameIds[i];
00235 msg->header.seq = seq;
00236 msg->header.stamp = imageTime;
00237
00238 sensorPubs[i].publish(msg);
00239
00240 sensor_msgs::CameraInfo cameraInfoMsg;
00241 cameraInfoMsg.header.frame_id = cameraFrameIds[i];
00242 cameraInfoMsg.height = image.rows;
00243 cameraInfoMsg.width = image.cols;
00244 cameraInfoPubs[i].publish(cameraInfoMsg);
00245 }
00246 }
00247
00248 if (virtualCameraEnabled && virtualCameraPub.getNumSubscribers() > 0) {
00249 r2 = times(&t2);
00250 if ((double) (r2 - r1) / HZ >= imageUpdateInterval) {
00251 r1 = r2;
00252 virtualCamera.setImages(compositeImage);
00253 logDuration("Updating virtual camera images", t2, r2);
00254 }
00255
00256 r2 = times(&t2);
00257 cv::Mat virtualView;
00258 virtualCamera.renderView(virtualView);
00259 logDuration("Rendering view", t2, r2);
00260
00261 r2 = times(&t2);
00262 IplImage iplImage = virtualView.operator _IplImage();
00263
00264 sensor_msgs::ImagePtr msg = bridge.cvToImgMsg(&iplImage, "bgr8");
00265
00266
00267 msg->header.frame_id = "/omni_frame";
00268 msg->header.seq = seq;
00269 msg->header.stamp = ros::Time::now();
00270 virtualCameraPub.publish(msg);
00271 logDuration("Publishing images", t2, r2);
00272 }
00273
00274 seq++;
00275 r.sleep();
00276 }
00277
00278
00279 camera.stopVideoTransmission();
00280 camera.stopCapture();
00281 camera.releaseAll();
00282
00283 } catch (CameraException& e) {
00284 ROS_ERROR("Camera exception: %s %s", e.what(), e.getErrorString().data());
00285 unlockVirtualCamera();
00286 return -1;
00287 } catch (std::runtime_error& e) {
00288 ROS_ERROR("Runtime error: %s", e.what());
00289 unlockVirtualCamera();
00290 return -2;
00291 } catch (...) {
00292 ROS_ERROR("Unexpected exception occurred.");
00293 unlockVirtualCamera();
00294 return -3;
00295 }
00296
00297 return 0;
00298 }
00299
00300 namespace {
00301 void lockVirtualCamera() {
00302 pthread_mutex_lock(&virtualCameraMutex);
00303 }
00304 void unlockVirtualCamera() {
00305 pthread_mutex_unlock(&virtualCameraMutex);
00306 }
00307
00308 bool getVirtualCameraConfigService(GetVirtualCameraConfig::Request& request, GetVirtualCameraConfig::Response& response) {
00309 ROS_DEBUG("getVirtualCameraConfigService called");
00310
00311
00312 lockVirtualCamera();
00313
00314 int viewportWidth, viewportHeight;
00315 virtualCamera.getViewport(&viewportWidth, &viewportHeight);
00316 response.config.viewportWidth = viewportWidth;
00317 response.config.viewportHeight = viewportHeight;
00318 response.config.pan = virtualCamera.getPan();
00319 response.config.tilt = virtualCamera.getTilt();
00320 response.config.horizontalFov = virtualCamera.getHorizontalFov();
00321 response.config.verticalFov = virtualCamera.getVerticalFov();
00322
00323 response.config.imageUpdateInterval = imageUpdateInterval;
00324
00325 unlockVirtualCamera();
00326
00327 return true;
00328 }
00329
00330 void virtualCameraConfigCallback(const VirtualCameraConfig::ConstPtr& msg) {
00331 ROS_DEBUG("virtualCameraConfigCallback called");
00332
00333 lockVirtualCamera();
00334
00335 virtualCamera.setViewport(msg->viewportWidth, msg->viewportHeight);
00336 virtualCamera.setPan(msg->pan);
00337 virtualCamera.setTilt(msg->tilt);
00338 virtualCamera.setHorizontalFov(msg->horizontalFov);
00339 virtualCamera.setVerticalFov(msg->verticalFov);
00340
00341 imageUpdateInterval = msg->imageUpdateInterval;
00342
00343 unlockVirtualCamera();
00344 }
00345
00346 void ladybugCameraConfigCallback(const LadybugCameraConfig::ConstPtr& msg) {
00347 ROS_DEBUG("ladybugCameraConfigCallback called");
00348
00349
00350
00351 camera.stopCapture();
00352 camera.stopVideoTransmission();
00353
00354 ladybugCameraConfig = *msg;
00355 camera.setSelectedImages(msg->imagesSelected);
00356
00357 camera.setupCapture();
00358 camera.startVideoTransmission();
00359
00360 }
00361
00362 bool getLadybugCameraConfigService(GetLadybugCameraConfig::Request& request, GetLadybugCameraConfig::Response& response) {
00363 ROS_DEBUG("getLadybugCameraConfigService called");
00364
00365
00366
00367
00368 ladybugCameraConfig.imagesSelected = camera.getSelectedImages();
00369 response.config = ladybugCameraConfig;
00370 return true;
00371 }
00372
00373 void logDuration(string message, tms t1, long r1) {
00374 struct tms t2;
00375 long r2;
00376 r2 = times(&t2);
00377
00378 float userTime = ((float) (t2.tms_utime - t1.tms_utime)) / HZ;
00379 float systemTime = ((float) (t2.tms_stime - t1.tms_stime)) / HZ;
00380 float realTime = ((float) (r2 - r1)) / HZ;
00381
00382 std::string format = "%s: real time: %1.2f, user time: %1.2f, system time: %1.2f";
00383 ROS_DEBUG(format.data(), message.data(), realTime, userTime, systemTime);
00384
00385 }
00386
00387 }