virtual_camera.cpp
Go to the documentation of this file.
00001 
00009 #include <GL/glew.h>
00010 #include <GL/gl.h>
00011 #include <GL/glut.h>
00012 
00013 #include <opencv2/core/core.hpp>
00014 #include <opencv2/highgui/highgui.hpp>
00015 #include <sys/param.h>
00016 #include <sys/times.h>
00017 
00018 #include <cv_bridge/CvBridge.h>
00019 #include <image_transport/image_transport.h>
00020 #include <ros/ros.h>
00021 
00022 #include "LadybugVirtualCamera.h"
00023 
00024 #define TEXTURE_UPDATE_INTERVAL 5.0
00025 
00026 using nifti::ladybug::LadybugVirtualCamera;
00027 
00028 namespace {
00029 std::string nodeName = "virtual_camera";
00030 LadybugVirtualCamera virtualCamera;
00031 
00032 // Time vars for tracking image update frequency.
00033 struct tms t1, t2;
00034 long r1 = 0l;
00035 long r2 = 0l;
00036 
00037 // Mouse button state and coords where button was pressed.
00038 int mouseState = GLUT_UP;
00039 int mouseX, mouseY;
00040 
00041 // ROS context.
00042 ros::NodeHandle* nodeHandlePtr;
00043 image_transport::Subscriber sub;
00044 sensor_msgs::CvBridge bridge;
00045 
00046 // Images to show.
00047 pthread_mutex_t imageMutex = PTHREAD_MUTEX_INITIALIZER;
00048 void lockImage() {
00049   pthread_mutex_lock(&imageMutex);
00050 }
00051 void unlockImage() {
00052   pthread_mutex_unlock(&imageMutex);
00053 }
00054 
00055 void idle(void) {
00056   glutPostRedisplay();
00057 }
00058 
00059 void resizeCallback(int w, int h) {
00060   ROS_DEBUG("resizeCallback: Resizing to %dx%d.", w, h);
00061 
00062   virtualCamera.setViewport(w, h);
00063   virtualCamera.setHorizontalFov(60.0);
00064   virtualCamera.setVerticalFov(60.0 * w / h);
00065 
00066   virtualCamera.updateViewport();
00067   virtualCamera.updateProjection();
00068 }
00069 
00070 void mouseCallback(int button, int state, int x, int y) {
00071   ROS_DEBUG("mouseCallback: x: %d, y: %d.", x, y);
00072 
00073   mouseState = state;
00074   if (mouseState == GLUT_DOWN) {
00075     mouseX = x;
00076     mouseY = y;
00077   }
00078 }
00079 
00080 void motionCallback(int x, int y) {
00081   ROS_DEBUG("motionCallback: x: %d, y: %d.", x, y);
00082 
00083   if (mouseState == GLUT_DOWN) {
00084     virtualCamera.setPan(virtualCamera.getPan() + (double) (x - mouseX));
00085     virtualCamera.setTilt(virtualCamera.getTilt() + (double) (y - mouseY));
00086     mouseX = x;
00087     mouseY = y;
00088   }
00089 }
00090 
00091 void displayCallback(void) {
00092   ROS_DEBUG("displayCallback: Rendering virtual camera view.");
00093 
00094   virtualCamera.clearBuffers();
00095   virtualCamera.updateModelView();
00096 
00097   //  lockImage();
00098   virtualCamera.render();
00099   //  unlockImage();
00100 
00101   glutSwapBuffers();
00102 }
00103 
00104 void imageSubscriberCallback(const sensor_msgs::ImageConstPtr &msg) {
00105   ROS_DEBUG("imageSubscriberCallback: Updating virtual camera images.");
00106 
00107   // Return if too soon from previous texture update.
00108   r2 = times(&t2);
00109   if ((float) (r2 - r1) / HZ < TEXTURE_UPDATE_INTERVAL) {
00110     ROS_DEBUG("imageSubscriberCallback: Skipping image message.");
00111     return;
00112   }
00113   t1 = t2;
00114   r1 = r2;
00115 
00116   // TODO: Lock image?
00117   //  lockImage();
00118 
00119   try {
00120     IplImage* iplImg = bridge.imgMsgToCv(msg, "bgr8");
00121     cv::Mat composite(iplImg);
00122 
00123     ROS_DEBUG("imageSubscriberCallback: Setting images.");
00124     printf("imageSubscriberCallback: Setting images.\n");
00125     virtualCamera.setImages(composite);
00126 
00127     // TODO: Free the image?
00128 
00129   } catch (sensor_msgs::CvBridgeException& e) {
00130     ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
00131     //    unlockImage();
00132   }
00133 
00134   //  unlockImage();
00135 }
00136 
00137 void* subscriberThreadMain(void* ptr) {
00138   ROS_DEBUG("Starting ROS spin thread...");
00139   ros::spin();
00140   ROS_DEBUG("Stopping ROS spin thread...");
00141   return NULL;
00142 }
00143 
00144 }
00145 
00146 int main(int argc, char* argv[]) {
00147 
00148   ros::init(argc, argv, nodeName);
00149 
00150   if (argc < 3) {
00151     printf("Usage: virtual_camera <mesh file> <alphamask prefix>");
00152     printf("Example: virtual_camera mesh.txt alphamask");
00153     return -1;
00154   }
00155 
00156   glutInit(&argc, argv);
00157 
00158   int viewportWidth, viewportHeight;
00159   virtualCamera.getViewport(&viewportWidth, &viewportHeight);
00160   glutInitWindowSize(viewportWidth, viewportHeight);
00161   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
00162   //  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
00163   int glutWin = glutCreateWindow(nodeName.data());
00164 
00165   // On some systems a graphics context has to be initialized prior to
00166   // calling glewInit, e.g. in form of a GLUT window.
00167   //  GLenum glew = glewInit();
00168   //  if (GLEW_OK != glew) {
00169   //    ROS_ERROR("GLEW could not be initialized.");
00170   //    glutDestroyWindow(glutWin);
00171   //    return -1;
00172   //  }
00173 
00174   virtualCamera.initialize(false);
00175   virtualCamera.loadMesh(argv[1]);
00176   virtualCamera.loadAlphamask(argv[2]);
00177 
00178   glutReshapeFunc(resizeCallback);
00179   glutDisplayFunc(displayCallback);
00180   glutMouseFunc(mouseCallback);
00181   glutMotionFunc(motionCallback);
00182   glutIdleFunc(idle);
00183 
00184   ros::NodeHandle nodeHandle;
00185   nodeHandlePtr = &nodeHandle;
00186 
00187   image_transport::ImageTransport it(nodeHandle);
00188   sub = it.subscribe("image", 1, imageSubscriberCallback);
00189 
00190   // Start a thread for reading off published images.
00191   pthread_t subscriberThread;
00192   int subscriberThreadRet = pthread_create(&subscriberThread, NULL, subscriberThreadMain, (void*) NULL);
00193 
00194   glutMainLoop();
00195   glutDestroyWindow(glutWin);
00196 
00197   ros::shutdown();
00198   pthread_join(subscriberThread, NULL);
00199 
00200   return subscriberThreadRet;
00201 }
00202 
 All Classes Namespaces Files Functions Variables Typedefs Defines


omnicamera
Author(s): Tomas Petricek / petrito1@cmp.felk.cvut.cz
autogenerated on Tue Dec 10 2013 14:26:53