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
00033 struct tms t1, t2;
00034 long r1 = 0l;
00035 long r2 = 0l;
00036
00037
00038 int mouseState = GLUT_UP;
00039 int mouseX, mouseY;
00040
00041
00042 ros::NodeHandle* nodeHandlePtr;
00043 image_transport::Subscriber sub;
00044 sensor_msgs::CvBridge bridge;
00045
00046
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
00098 virtualCamera.render();
00099
00100
00101 glutSwapBuffers();
00102 }
00103
00104 void imageSubscriberCallback(const sensor_msgs::ImageConstPtr &msg) {
00105 ROS_DEBUG("imageSubscriberCallback: Updating virtual camera images.");
00106
00107
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
00117
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
00128
00129 } catch (sensor_msgs::CvBridgeException& e) {
00130 ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
00131
00132 }
00133
00134
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
00163 int glutWin = glutCreateWindow(nodeName.data());
00164
00165
00166
00167
00168
00169
00170
00171
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
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