Go to the documentation of this file.00001
00019 #include <cv_bridge/CvBridge.h>
00020 #include <GL/glew.h>
00021 #include <GL/gl.h>
00022 #include <GL/glut.h>
00023 #include <image_transport/image_transport.h>
00024 #include <math.h>
00025 #include <opencv2/core/core.hpp>
00026 #include <opencv2/highgui/highgui.hpp>
00027 #include <ros/ros.h>
00028 #include <sys/param.h>
00029 #include <sys/times.h>
00030
00031 #include "LadybugCamera.h"
00032 #include "LadybugVirtualCamera.h"
00033 #include "omnicamera_msgs/GetVirtualCameraConfig.h"
00034 #include "omnicamera_msgs/VirtualCameraConfig.h"
00035
00036 using std::string;
00037
00038 using nifti::ladybug::LadybugVirtualCamera;
00039 using omnicamera_msgs::GetVirtualCameraConfig;
00040 using omnicamera_msgs::VirtualCameraConfig;
00041
00042 namespace {
00046 LadybugVirtualCamera virtualCamera;
00050 VirtualCameraConfig virtualCameraConfig;
00055 double imageUpdateInterval = 5.0;
00056 long lastImageUpdate = 0l;
00057 sensor_msgs::CvBridge bridge;
00062 bool viewChanged = false;
00063
00064
00065 struct tms t1, t2;
00066 long r1 = 0l, r2 = 0l;
00067
00071 bool
00072 getVirtualCameraConfigService(GetVirtualCameraConfig::Request& request, GetVirtualCameraConfig::Response& response);
00076 void virtualCameraConfigCallback(const VirtualCameraConfig::ConstPtr& msg);
00080 void imageCallback(const sensor_msgs::ImageConstPtr &msg);
00081 void startDuration();
00086 void logDuration(char* message);
00087 }
00088
00089 int main(int argc, char** argv) {
00090
00091 ros::init(argc, argv, "virtual_camera2");
00092 ros::NodeHandle nodeHandle;
00093
00094 for (int i = 0; i < argc; i++) {
00095 printf("%d: %s\n", i, argv[i]);
00096 }
00097
00098
00099 string meshFile;
00100 string alphamaskPrefix;
00101 if (argc < 3) {
00102 printf("Not enough arguments.\n");
00103 printf("Usage: virtual_camera_filter <mesh file path> <alphamask file prefix>\n");
00104 printf("Example: virtual_camera_filter mesh.txt alphamask\n");
00105 return -1;
00106 } else {
00107 meshFile = string(argv[1]);
00108 alphamaskPrefix = string(argv[2]);
00109 glutInit(&argc, argv);
00110 }
00111
00112
00113 ros::Subscriber virtualCameraConfigSubscriber;
00114 ros::ServiceServer getVirtualCameraConfigServer;
00115 virtualCameraConfigSubscriber = nodeHandle.subscribe("virtual_camera/config", 1, virtualCameraConfigCallback);
00116 getVirtualCameraConfigServer
00117 = nodeHandle.advertiseService("virtual_camera/get_config", getVirtualCameraConfigService);
00118
00119 image_transport::ImageTransport it(nodeHandle);
00120
00121 image_transport::Publisher virtualCameraPub = it.advertise("virtual_camera/image", 1);
00122
00123 image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback);
00124
00125 try {
00126 uint32_t seq = 0;
00127 virtualCamera.initialize(true);
00128 virtualCamera.loadMesh(meshFile);
00129 virtualCamera.loadAlphamask(alphamaskPrefix);
00130
00131 while (nodeHandle.ok()) {
00132
00133
00134
00135 ros::spinOnce();
00136
00137 if (viewChanged && virtualCameraPub.getNumSubscribers() > 0) {
00138 ROS_INFO("Rendering virtual camera view...");
00139 cv::Mat virtualCameraView;
00140 startDuration();
00141 virtualCamera.renderView(virtualCameraView);
00142 logDuration("Rendering view");
00143
00144
00145 IplImage iplImage = virtualCameraView.operator _IplImage();
00146
00147 sensor_msgs::ImagePtr msg = bridge.cvToImgMsg(&iplImage);
00148 msg->header.frame_id = "tfladylink";
00149 msg->header.seq = seq++;
00150 msg->header.stamp = ros::Time::now();
00151
00152 startDuration();
00153 virtualCameraPub.publish(msg);
00154 logDuration("Publishing images");
00155
00156 viewChanged = false;
00157 }
00158 }
00159 } catch (std::runtime_error& e) {
00160 ROS_ERROR("Runtime error: %s", e.what());
00161 return -1;
00162 } catch (...) {
00163 ROS_ERROR("Unexpected exception occurred.");
00164 return -1;
00165 }
00166
00167 return 0;
00168 }
00169
00170 namespace {
00171
00172 void imageCallback(const sensor_msgs::ImageConstPtr &msg) {
00173 struct tms t;
00174 long r;
00175 r = times(&t);
00176 double sinceLastUpdate = (double) (r - lastImageUpdate) / HZ;
00177 if (sinceLastUpdate >= imageUpdateInterval) {
00178 try {
00179 IplImage* iplImg = bridge.imgMsgToCv(msg, "bgr8");
00180
00181
00182
00183 cv::Mat composite(iplImg);
00184
00185 startDuration();
00186 virtualCamera.setImages(composite);
00187 logDuration("Updating virtual camera images");
00188 } catch (sensor_msgs::CvBridgeException& e) {
00189 ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
00190 }
00191 lastImageUpdate = r;
00192 viewChanged = true;
00193 }
00194 }
00195
00196 bool getVirtualCameraConfigService(GetVirtualCameraConfig::Request& request, GetVirtualCameraConfig::Response& response) {
00197 ROS_DEBUG("getVirtualCameraConfigService called");
00198
00199
00200
00201 int viewportWidth, viewportHeight;
00202 virtualCamera.getViewport(&viewportWidth, &viewportHeight);
00203 response.config.viewportWidth = viewportWidth;
00204 response.config.viewportHeight = viewportHeight;
00205 response.config.pan = virtualCamera.getPan();
00206 response.config.tilt = virtualCamera.getTilt();
00207 response.config.horizontalFov = virtualCamera.getHorizontalFov();
00208 response.config.verticalFov = virtualCamera.getVerticalFov();
00209
00210 response.config.imageUpdateInterval = imageUpdateInterval;
00211
00212 return true;
00213 }
00214
00215 void virtualCameraConfigCallback(const VirtualCameraConfig::ConstPtr& msg) {
00216 ROS_DEBUG("virtualCameraConfigCallback called");
00217
00218 virtualCamera.setViewport(msg->viewportWidth, msg->viewportHeight);
00219 virtualCamera.setPan(msg->pan);
00220 virtualCamera.setTilt(msg->tilt);
00221 virtualCamera.setHorizontalFov(msg->horizontalFov);
00222 virtualCamera.setVerticalFov(msg->verticalFov);
00223
00224 imageUpdateInterval = msg->imageUpdateInterval;
00225
00226 viewChanged = true;
00227 }
00228
00229 void startDuration() {
00230 r1 = times(&t1);
00231 }
00232
00233 void logDuration(char* message) {
00234 r2 = times(&t2);
00235
00236 float userTime = ((float) (t2.tms_utime - t1.tms_utime)) / HZ;
00237 float systemTime = ((float) (t2.tms_stime - t1.tms_stime)) / HZ;
00238 float realTime = ((float) (r2 - r1)) / HZ;
00239
00240 std::string format = "%s: real time: %1.2f, user time: %1.2f, system time: %1.2f";
00241 ROS_DEBUG(format.data(), message, realTime, userTime, systemTime);
00242 }
00243
00244 }