00001 #include <ros/ros.h>
00002 #include <rospack/rospack.h>
00003 #include <sensor_msgs/fill_image.h>
00004 #include <sensor_msgs/SetCameraInfo.h>
00005 #include <image_transport/image_transport.h>
00006 #include <camera_calibration_parsers/parse.h>
00007
00008 #include <opencv/cv.h>
00009 #include <cv_bridge/cv_bridge.h>
00010
00011 #include <dynamic_reconfigure/server.h>
00012 #include <opt_camera/OptNM33CameraConfig.h>
00013 #include "opt_nm33_uvc/opt_nm33_camera.h"
00014
00015 class OptCamNode
00016 {
00017 private:
00018
00019 OptNM3xCamera *camera_;
00020 std::string serial_id_;
00021
00022
00023 ros::NodeHandle &node_;
00024 ros::Time next_time_;
00025 int count_;
00026
00027
00028 sensor_msgs::Image img_, img_omni_, img_wide_, img_middle_, img_narrow_, img_panorama_;
00029 image_transport::CameraPublisher img_pub_, img_omni_pub_, img_wide_pub_, img_middle_pub_, img_narrow_pub_,img_panorama_pub_;
00030 sensor_msgs::CameraInfo info_, info_omni_, info_wide_, info_middle_, info_narrow_, info_panorama_;
00031 ros::ServiceServer info_srv_, info_omni_srv_, info_wide_srv_, info_middle_srv_, info_narrow_srv_, info_panorama_srv_;
00032
00033
00034 typedef dynamic_reconfigure::Server<opt_camera::OptNM33CameraConfig> ReconfigureServer;
00035 ReconfigureServer reconfigure_server_;
00036 opt_camera::OptNM33CameraConfig config_;
00037
00038 public:
00039 OptCamNode(ros::NodeHandle &node) : node_(node)
00040 {
00041
00042 ros::NodeHandle nh("~");
00043 int camera_index = 0;
00044
00045 nh.getParam("camera_index", camera_index);
00046 camera_ = new OptNM3xCamera(camera_index);
00047 if ((serial_id_ = camera_->getSerialID()) == "") {
00048 nh.getParam("serial_id", serial_id_);
00049 }
00050 camera_->setSmallHemisphere(1);
00051 camera_->setLocationAbsolute(0, 0, 0, 0, 0);
00052 camera_->setLocationAbsolute(1, 0, 0, 0, 40);
00053 camera_->setLocationAbsolute(2, 0, 0, 0, 120);
00054
00055
00056 img_.header.frame_id = std::string("head_camera");
00057 img_omni_.header.frame_id = std::string("head_camera");
00058 img_wide_.header.frame_id = std::string("head_camera");
00059 img_middle_.header.frame_id = std::string("head_camera");
00060 img_narrow_.header.frame_id = std::string("head_camera");
00061 img_panorama_.header.frame_id = std::string("head_camera");
00062 nh.getParam("frame_id", img_.header.frame_id);
00063 nh.getParam("omni_frame_id", img_omni_.header.frame_id);
00064 nh.getParam("wide_frame_id", img_wide_.header.frame_id);
00065 nh.getParam("middle_frame_id", img_middle_.header.frame_id);
00066 nh.getParam("narrow_frame_id", img_narrow_.header.frame_id);
00067 nh.getParam("panorama_frame_id", img_panorama_.header.frame_id);
00068
00069
00070 info_.header.frame_id = img_.header.frame_id;
00071 info_omni_.header.frame_id = img_omni_.header.frame_id;
00072 info_wide_.header.frame_id = img_wide_.header.frame_id;
00073 info_middle_.header.frame_id = img_middle_.header.frame_id;
00074 info_narrow_.header.frame_id = img_narrow_.header.frame_id;
00075 info_panorama_.header.frame_id = img_panorama_.header.frame_id;
00076
00077
00078 img_pub_ = image_transport::ImageTransport(node).advertiseCamera("image_raw" , 1);
00079 img_omni_pub_ = image_transport::ImageTransport(ros::NodeHandle(node,"omni")).advertiseCamera("image_raw" , 1);
00080 img_wide_pub_ = image_transport::ImageTransport(ros::NodeHandle(node,"wide")).advertiseCamera("image_raw" , 1);
00081 img_middle_pub_ = image_transport::ImageTransport(ros::NodeHandle(node,"middle")).advertiseCamera("image_raw" , 1);
00082 img_narrow_pub_ = image_transport::ImageTransport(ros::NodeHandle(node,"narrow")).advertiseCamera("image_raw" , 1);
00083 img_panorama_pub_ = image_transport::ImageTransport(ros::NodeHandle(node,"panorama")).advertiseCamera("image_raw" , 1);
00084
00085 info_srv_ = node.advertiseService("set_camera_info", &OptCamNode::set_camera_info, this);
00086 info_omni_srv_ = ros::NodeHandle(node,"omni").advertiseService("set_camera_info", &OptCamNode::set_camera_info_omni, this);
00087 info_wide_srv_ = ros::NodeHandle(node,"wide").advertiseService("set_camera_info", &OptCamNode::set_camera_info_wide, this);
00088 info_middle_srv_ = ros::NodeHandle(node,"middle").advertiseService("set_camera_info", &OptCamNode::set_camera_info_middle, this);
00089 info_narrow_srv_ = ros::NodeHandle(node,"narrow").advertiseService("set_camera_info", &OptCamNode::set_camera_info_narrow, this);
00090 info_panorama_srv_ = ros::NodeHandle(node,"panorama").advertiseService("set_camera_info", &OptCamNode::set_camera_info_panorama, this);
00091
00092
00093 get_camera_info_method("",info_);
00094 get_camera_info_method("-omni",info_omni_);
00095 get_camera_info_method("-wide",info_wide_);
00096 get_camera_info_method("-middle",info_middle_);
00097 get_camera_info_method("-narrow",info_narrow_);
00098 get_camera_info_method("-panorama",info_panorama_);
00099
00100
00101 ReconfigureServer::CallbackType f = boost::bind(&OptCamNode::config_cb, this, _1, _2);
00102 reconfigure_server_.setCallback(f);
00103
00104 next_time_ = ros::Time::now();
00105 count_ = 0;
00106 }
00107
00108 ~OptCamNode()
00109 {
00110 }
00111
00112 bool take_and_send_image()
00113 {
00114 IplImage *frame = NULL;
00115 ros::Time now;
00116
00117 if ( ( frame = camera_->queryFrame() ) == NULL ) {
00118 ROS_ERROR_STREAM("[" << serial_id_ << "] cvQueryFrame");
00119 return false;
00120 }
00121 now = ros::Time::now();
00122 img_.header.stamp = now;
00123 img_omni_.header.stamp = now;
00124 img_wide_.header.stamp = now;
00125 img_middle_.header.stamp = now;
00126 img_narrow_.header.stamp = now;
00127 img_panorama_.header.stamp = now;
00128 info_.header.stamp = now;
00129 info_omni_.header.stamp = now;
00130 info_wide_.header.stamp = now;
00131 info_middle_.header.stamp = now;
00132 info_narrow_.header.stamp = now;
00133 info_panorama_.header.stamp = now;
00134
00135 try {
00136 fillImage(img_, "bgr8", frame->height, frame->width, frame->width * frame->nChannels, frame->imageData);
00137 img_pub_.publish(img_, info_);
00138 {
00139 IplImage *tmp_img_ = camera_->queryOmniFrame();
00140 fillImage(img_omni_, "bgr8", tmp_img_->height, tmp_img_->width, tmp_img_->width * tmp_img_->nChannels, tmp_img_->imageData);
00141 img_omni_pub_.publish(img_omni_, info_omni_);
00142 }
00143 {
00144 IplImage *tmp_img_ = camera_->queryWideFrame();
00145 fillImage(img_wide_, "bgr8", tmp_img_->height, tmp_img_->width, tmp_img_->width * tmp_img_->nChannels, tmp_img_->imageData);
00146 img_wide_pub_.publish(img_wide_, info_wide_);
00147 }
00148 {
00149 IplImage *tmp_img_ = camera_->queryMiddleFrame();
00150 fillImage(img_middle_, "bgr8", tmp_img_->height, tmp_img_->width, tmp_img_->width * tmp_img_->nChannels, tmp_img_->imageData);
00151 img_middle_pub_.publish(img_middle_, info_middle_);
00152 }
00153 {
00154 IplImage *tmp_img_ = camera_->queryNarrowFrame();
00155 fillImage(img_narrow_, "bgr8", tmp_img_->height, tmp_img_->width, tmp_img_->width * tmp_img_->nChannels, tmp_img_->imageData);
00156 img_narrow_pub_.publish(img_narrow_, info_narrow_);
00157 }
00158 if(config_.mode == 2) {
00159 IplImage* tmp_img_ = cvCreateImage(cvSize(frame->width*2,frame->height/2),frame->depth,frame->nChannels);
00160
00161 cvSetImageROI(frame,cvRect(0,frame->height/2,frame->width,frame->height/2));
00162 cvSetImageROI(tmp_img_,cvRect(0,0,frame->width,frame->height/2));
00163 cvCopy(frame,tmp_img_);
00164 cvSetImageROI(frame,cvRect(0,0,frame->width,frame->height/2));
00165 cvSetImageROI(tmp_img_,cvRect(frame->width,0,frame->width,frame->height/2));
00166 cvCopy(frame,tmp_img_);
00167 fillImage(img_panorama_, "bgr8", tmp_img_->height, tmp_img_->width, tmp_img_->width * tmp_img_->nChannels, tmp_img_->imageData);
00168 img_panorama_pub_.publish(img_panorama_, info_panorama_);
00169 cvResetImageROI(frame);
00170 cvReleaseImage(&tmp_img_);
00171 }
00172 }
00173 catch (cv_bridge::Exception& e)
00174 {
00175 ROS_ERROR("Could not convert from opencv to message.");
00176 }
00177 return true;
00178 }
00179
00180 void config_cb(opt_camera::OptNM33CameraConfig &config, uint32_t level)
00181 {
00182 #define SET_CAMERA(methodname, paramname) \
00183 if (config_.paramname != config.paramname ) { \
00184 camera_->methodname(config.paramname); \
00185 }
00186
00187 SET_CAMERA(setMode, mode);
00188 if ( config.autoexposure ) {
00189 SET_CAMERA(setAutoExposure, autoexposure);
00190 } else {
00191 SET_CAMERA(setExposure, exposure);
00192 SET_CAMERA(setIris, iris);
00193 }
00194 if ( config.mode != 4 && config.mode != 0 ) {
00195 SET_CAMERA(setPanAbsolute, pan);
00196 SET_CAMERA(setTiltAbsolute, tilt);
00197 SET_CAMERA(setRollAbsolute, roll);
00198 SET_CAMERA(setZoomAbsolute, zoom);
00199 }
00200 if ( config.autoexposure ) {
00201 SET_CAMERA(setBrightness, brightness);
00202 }
00203 SET_CAMERA(setSharpness, sharpness);
00204 if ( ! config.autowhitebalance ) {
00205 SET_CAMERA(setWhitebalance, whitebalance);
00206 } else {
00207 SET_CAMERA(setAutoWhitebalance, autowhitebalance);
00208 }
00209 config.firmwareversion = camera_->getFirmwareVersion();
00210 SET_CAMERA(setFlipScreen, flipscreen);
00211 SET_CAMERA(setSmallHemisphere, smallhemisphere);
00212 SET_CAMERA(setMedianFilter, medianfilter);
00213 SET_CAMERA(setJpegQuality, jpegquality);
00214 config.serialid = serial_id_;
00215 SET_CAMERA(setInfoDisplay, infodisplay);
00216 if ( config.capturefps != config_.capturefps) {
00217 SET_CAMERA(setCaptureFPS, capturefps);
00218 }
00219
00220 if ( config.lenstype != config_.lenstype) {
00221 SET_CAMERA(setLensType, lenstype);
00222 }
00223 if ( config.mode == 4 ) {
00224
00225
00226
00227
00228
00229 if ( ( config.camera1_pan != config_.camera1_pan ) ||
00230 ( config.camera1_tilt != config_.camera1_tilt ) ||
00231 ( config.camera1_roll != config_.camera1_roll ) ||
00232 ( config.camera1_zoom != config_.camera1_zoom ) ) {
00233 camera_->setLocationAbsolute(1,config.camera1_pan, config.camera1_tilt, config.camera1_roll, config.camera1_zoom);
00234 }
00235
00236
00237
00238
00239
00240
00241 if ( ( config.camera2_pan != config_.camera2_pan ) ||
00242 ( config.camera2_tilt != config_.camera2_tilt ) ||
00243 ( config.camera2_roll != config_.camera2_roll ) ||
00244 ( config.camera2_zoom != config_.camera2_zoom ) ) {
00245 camera_->setLocationAbsolute(2,config.camera2_pan, config.camera2_tilt, config.camera2_roll, config.camera2_zoom);
00246 }
00247
00248
00249 if ( ( config.camera3_pan != config_.camera3_pan ) ||
00250 ( config.camera3_tilt != config_.camera3_tilt ) ||
00251 ( config.camera3_roll != config_.camera3_roll ) ||
00252 ( config.camera3_zoom != config_.camera3_zoom ) ) {
00253 camera_->setLocationAbsolute(0,config.camera3_pan, config.camera3_tilt, config.camera3_roll, config.camera3_zoom);
00254 }
00255
00256
00257
00258
00259 #if 0
00260 if ( config.camera3_pan != config_.camera3_pan ) {
00261 camera_->setPanAbsolute (0,config.camera3_pan);
00262 }
00263 if ( config.camera3_tilt != config_.camera3_tilt ) {
00264 camera_->setTiltAbsolute(0,config.camera3_tilt);
00265 }
00266 if ( config.camera3_roll != config_.camera3_roll ) {
00267 camera_->setRollAbsolute(0,config.camera3_roll);
00268 }
00269 if ( config.camera3_zoom != config_.camera3_zoom ) {
00270 camera_->setZoomAbsolute(0,config.camera3_zoom);
00271 }
00272 #endif
00273 }
00274 config_ = config;
00275 }
00276
00277 bool get_camera_info_method(std::string view_name, sensor_msgs::CameraInfo &info) {
00278 std::string cam_name = serial_id_+view_name;
00279 std::string ini_name = cam_name+".ini";
00280 try {
00281 #ifdef ROSPACK_EXPORT
00282 rospack::ROSPack rp;
00283 rospack::Package *p = rp.get_pkg("opt_camera");
00284 if (p!=NULL) ini_name = p->path + "/cfg/" + ini_name;
00285 #else
00286 rospack::Rospack rp;
00287 std::vector<std::string> search_path;
00288 rp.getSearchPathFromEnv(search_path);
00289 rp.crawl(search_path, 1);
00290 std::string path;
00291 if (rp.find("opt_camera",path)==true) ini_name = path + "/cfg" + ini_name;
00292 #endif
00293 } catch (std::runtime_error &e) {
00294 }
00295 if (!camera_calibration_parsers::readCalibration(ini_name, cam_name, info)) {
00296 return false;
00297 }
00298 if ( info.P[0] == 0.0 ) {
00299 ROS_ERROR_STREAM( "Loading wrong camera_info from " << ini_name );
00300 return false;
00301 }
00302 ROS_ERROR_STREAM( "Loading camera_info from " << ini_name << info.P[0] );
00303 return true;
00304 }
00305
00306 #ifdef ROSPACK_EXPORT
00307 #define set_camera_info_method(set_camera_info_method, view_name) \
00308 bool set_camera_info_method(sensor_msgs::SetCameraInfo::Request& req, \
00309 sensor_msgs::SetCameraInfo::Response& rsp) { \
00310 ROS_INFO("New camera info received"); \
00311 sensor_msgs::CameraInfo &info = req.camera_info; \
00312 \
00313 std::string cam_name = serial_id_+view_name; \
00314 std::string ini_name = cam_name+".ini"; \
00315 rospack::ROSPack rp; \
00316 try { \
00317 rospack::Package *p = rp.get_pkg("opt_camera"); \
00318 if (p!=NULL) ini_name = p->path + "/cfg/" + ini_name; \
00319 } catch (std::runtime_error &e) { \
00320 } \
00321 if (!camera_calibration_parsers::writeCalibration(ini_name, cam_name.c_str(), info)) { \
00322 rsp.status_message = "Error writing camera_info to " + cam_name + ".ini"; \
00323 rsp.success = false; \
00324 } \
00325 \
00326 rsp.success = true; \
00327 return true; \
00328 }
00329 #else
00330 #define set_camera_info_method(set_camera_info_method, view_name) \
00331 bool set_camera_info_method(sensor_msgs::SetCameraInfo::Request& req, \
00332 sensor_msgs::SetCameraInfo::Response& rsp) { \
00333 ROS_INFO("New camera info received"); \
00334 sensor_msgs::CameraInfo &info = req.camera_info; \
00335 \
00336 std::string cam_name = serial_id_+view_name; \
00337 std::string ini_name = cam_name+".ini"; \
00338 rospack::Rospack rp; \
00339 try { \
00340 std::vector<std::string> search_path; \
00341 rp.getSearchPathFromEnv(search_path); \
00342 rp.crawl(search_path, 1); \
00343 std::string path; \
00344 if(rp.find("opt_camera", path)==true) ini_name = path + "/cfg/" + ini_name; \
00345 } catch (std::runtime_error &e) { \
00346 } \
00347 if (!camera_calibration_parsers::writeCalibration(ini_name, cam_name.c_str(), info)) { \
00348 rsp.status_message = "Error writing camera_info to " + cam_name + ".ini"; \
00349 rsp.success = false; \
00350 } \
00351 \
00352 rsp.success = true; \
00353 return true; \
00354 }
00355 #endif
00356
00357 set_camera_info_method(set_camera_info,"")
00358 set_camera_info_method(set_camera_info_omni,"-omni")
00359 set_camera_info_method(set_camera_info_wide,"-wide")
00360 set_camera_info_method(set_camera_info_middle,"-middle")
00361 set_camera_info_method(set_camera_info_narrow,"-narrow")
00362 set_camera_info_method(set_camera_info_panorama,"-panorama")
00363
00364 bool spin()
00365 {
00366 while (node_.ok())
00367 {
00368 if (take_and_send_image())
00369 {
00370 count_++;
00371 ros::Time now_time = ros::Time::now();
00372 if (now_time > next_time_) {
00373 std::cout << count_ << " frames/sec at " << now_time << std::endl;
00374 count_ = 0;
00375 next_time_ = next_time_ + ros::Duration(1,0);
00376 }
00377 } else {
00378 ROS_ERROR_STREAM("[" << node_.getNamespace() << "] couldn't take image.");
00379 usleep(1000000);
00380 }
00381 ros::spinOnce();
00382 }
00383 return true;
00384 }
00385
00386 };
00387
00388
00389 int main (int argc, char **argv)
00390 {
00391 ros::init(argc, argv, "nm33_cam");
00392 ros::NodeHandle nh("camera");
00393
00394 OptCamNode camera(nh);
00395
00396 camera.spin();
00397
00398 return 0;
00399 }