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
00028
00029
00030
00031
00032
00033
00034 #include "vrmstnode.h"
00035
00036 #include "sourceformatlist.h"
00037 #include "formatindicator.h"
00038
00039 #include <iostream>
00040 #include <sstream>
00041
00042 #include <signal.h>
00043
00044 VRMagicStereoNode *vrsnode = NULL;
00045
00046 class VRGrabException : public std::string
00047 {
00048 public:
00049 VRGrabException(const char *err) : std::string(err) {}
00050 };
00051
00052 class VRControlException : public std::string
00053 {
00054 public:
00055 VRControlException(const char *err) : std::string(err) {}
00056 };
00057
00058 class PropertyCache
00059 {
00060 public:
00061 float exposureTime;
00062 int gainLeft, gainRight;
00063 float fps;
00064 VRmBOOL useLEDs;
00065 };
00066
00067 void VRMagicStereoNode::propertyUpdate(vrmagic_multi_driver::CamParamsConfig &config, uint32_t level)
00068 {
00069 if(props->exposureTime != config.exposureTime)
00070 {
00071 boost::lock_guard<boost::mutex> lock(camAccess);
00072
00073 if(!VRmUsbCamStop(device))
00074 throw VRControlException("VRmUsbCamStop failed.");
00075
00076 float newVal = config.exposureTime;
00077 if(!VRmUsbCamSetPropertyValueF(device, VRM_PROPID_MULTICAM_MASTER_EXPOSURE_TIME_F, &newVal))
00078 std::cerr << "VRmUsbCamSetPropertyValueF(MULTICAM_MASTER_EXPOSURE_TIME_F) failed." << std::endl;
00079 else
00080 props->exposureTime = newVal;
00081
00082 if(!VRmUsbCamStart(device))
00083 throw VRControlException("VRmUsbCamStart failed.");
00084
00085 }
00086
00087 if(props->gainLeft != config.gainLeft)
00088 {
00089 boost::lock_guard<boost::mutex> lock(camAccess);
00090
00091 VRmPropId sensor = VRM_PROPID_GRAB_SENSOR_PROPS_SELECT_1;
00092 VRmUsbCamSetPropertyValueE(device, VRM_PROPID_GRAB_SENSOR_PROPS_SELECT_E, &sensor);
00093
00094 int newVal = config.gainLeft;
00095 if(!VRmUsbCamSetPropertyValueI(device, VRM_PROPID_CAM_GAIN_MONOCHROME_I, &newVal))
00096 std::cerr << "VRmUsbCamSetPropertyValueI(VRM_PROPID_CAM_GAIN_MONOCHROME_I) failed." << std::endl;
00097 else
00098 props->gainLeft = newVal;
00099 }
00100
00101 if(props->gainRight != config.gainRight)
00102 {
00103 boost::lock_guard<boost::mutex> lock(camAccess);
00104
00105 VRmPropId sensor = VRM_PROPID_GRAB_SENSOR_PROPS_SELECT_3;
00106 VRmUsbCamSetPropertyValueE(device, VRM_PROPID_GRAB_SENSOR_PROPS_SELECT_E, &sensor);
00107
00108 int newVal = config.gainRight;
00109 if(!VRmUsbCamSetPropertyValueI(device, VRM_PROPID_CAM_GAIN_MONOCHROME_I, &newVal))
00110 std::cerr << "VRmUsbCamSetPropertyValueI(VRM_PROPID_CAM_GAIN_MONOCHROME_I) failed." << std::endl;
00111 else
00112 props->gainRight = newVal;
00113 }
00114
00115 if(props->useLEDs != config.useLEDs)
00116 {
00117 boost::lock_guard<boost::mutex> lock(camAccess);
00118 VRmBOOL newValue = config.useLEDs;
00119 if(!VRmUsbCamSetPropertyValueB(device, VRM_PROPID_DEVICE_STATUS_LED_B, &newValue))
00120 std::cerr << "VRmUsbCamSetPropertyValueB(DEVICE_STATUS_LED_B) failed." << std::endl;
00121 else
00122 props->useLEDs = newValue;
00123 }
00124
00125 if(props->fps != config.fps)
00126 {
00127 boost::lock_guard<boost::mutex> lock(timerAccess);
00128 fpsLimit = ros::Rate(config.fps);
00129 props->fps = config.fps;
00130 }
00131
00132 }
00133
00134 bool VRMagicStereoNode::runUpdateLeft(sensor_msgs::SetCameraInfo::Request &req,
00135 sensor_msgs::SetCameraInfo::Response &res)
00136 {
00137 boost::lock_guard<boost::mutex> lock(calibAccess);
00138 leftCalib = req.camera_info;
00139 storeCalibration();
00140 res.success = true;
00141 res.status_message = "Calibration updated";
00142 return true;
00143 }
00144
00145 bool VRMagicStereoNode::runUpdateRight(sensor_msgs::SetCameraInfo::Request &req,
00146 sensor_msgs::SetCameraInfo::Response &res)
00147 {
00148 boost::lock_guard<boost::mutex> lock(calibAccess);
00149 rightCalib = req.camera_info;
00150 storeCalibration();
00151 res.success = true;
00152 res.status_message = "Calibration updated";
00153 return true;
00154 }
00155
00156 void VRMagicStereoNode::loadCalibration()
00157 {
00158 VRmUserData *uData;
00159 if(!VRmUsbCamLoadUserData(device, &uData))
00160 {
00161 std::cerr << "VRmUsbCamLoadUserData failed." << std::endl;
00162 return;
00163 }
00164
00165 if(uData->m_length == 0)
00166 {
00167 std::cerr << "there is no calibration stored on the camera." << std::endl;
00168 return;
00169 }
00170
00171 ros::serialization::IStream stream(uData->mp_data, uData->m_length);
00172 ros::serialization::deserialize(stream, leftCalib);
00173 ros::serialization::deserialize(stream, rightCalib);
00174
00175 VRmUsbCamFreeUserData(&uData);
00176
00177 calibrated = true;
00178 }
00179
00180 void VRMagicStereoNode::storeCalibration()
00181 {
00182 uint32_t leftLen = ros::serialization::serializationLength(leftCalib);
00183 uint32_t rightLen = ros::serialization::serializationLength(rightCalib);
00184
00185 VRmUserData *uData;
00186 if(!VRmUsbCamNewUserData(&uData, leftLen + rightLen))
00187 {
00188 std::cerr << "VRmUsbCamNewUserData failed." << std::endl;
00189 return;
00190 }
00191 ros::serialization::OStream stream(uData->mp_data, leftLen + rightLen);
00192 ros::serialization::serialize(stream, leftCalib);
00193 ros::serialization::serialize(stream, rightCalib);
00194
00195 camAccess.lock();
00196 if(!VRmUsbCamSaveUserData(device, uData))
00197 {
00198 std::cerr << "VRmUsbCamSaveUserData failed." << std::endl;
00199 }
00200 camAccess.unlock();
00201
00202 std::cout << "calibration written to camera." << std::endl;
00203
00204 VRmUsbCamFreeUserData(&uData);
00205 }
00206
00207
00208 void VRMagicStereoNode::AnnounceTopics()
00209 {
00210 camPubLeft = image_transport::ImageTransport(leftNs).advertiseCamera("image_raw", 2);
00211 camPubRight = image_transport::ImageTransport(rightNs).advertiseCamera("image_raw", 2);
00212 leftCalibUpdate = leftNs.advertiseService("set_camera_info", &VRMagicStereoNode::runUpdateLeft, this);
00213 rightCalibUpdate = rightNs.advertiseService("set_camera_info", &VRMagicStereoNode::runUpdateRight, this);
00214 }
00215
00216 void VRMagicStereoNode::AbandonTopics()
00217 {
00218 camPubLeft.shutdown();
00219 camPubRight.shutdown();
00220 leftCalibUpdate.shutdown();
00221 rightCalibUpdate.shutdown();
00222 }
00223
00224 void VRMagicStereoNode::broadcastFrame()
00225 {
00226 camAccess.lock();
00227 VRmRetVal success = VRmUsbCamSoftTrigger(device);
00228 camAccess.unlock();
00229 if(!success)
00230 throw VRGrabException("VRmUsbCamSoftTrigger failed.");
00231
00232 ros::Time triggerTime = ros::Time::now();
00233
00234 grabFrame(1, imgLeft, triggerTime);
00235 grabFrame(3, imgRight, triggerTime);
00236 leftCalib.header.stamp = triggerTime;
00237 leftCalib.header.frame_id = frame_id;
00238 rightCalib.header.stamp = triggerTime;
00239 rightCalib.header.frame_id = frame_id;
00240
00241 try
00242 {
00243 boost::lock_guard<boost::mutex> lock(calibAccess);
00244 camPubLeft.publish(imgLeft, leftCalib);
00245 }
00246 catch(ros::serialization::StreamOverrunException &crap)
00247 {
00248 std::cerr << "stream overrun in left channel" << std::endl;
00249 }
00250
00251 try
00252 {
00253 boost::lock_guard<boost::mutex> lock(calibAccess);
00254 camPubRight.publish(imgRight, rightCalib);
00255 }
00256 catch(ros::serialization::StreamOverrunException &crap)
00257 {
00258 std::cerr << "stream overrun in right channel" << std::endl;
00259 }
00260 }
00261
00262 void VRMagicStereoNode::grabFrame(VRmDWORD port, sensor_msgs::Image &img, const ros::Time &triggerTime)
00263 {
00264 img.width = width;
00265 img.height = height;
00266 img.step = width * 2;
00267 img.encoding = sensor_msgs::image_encodings::MONO16;
00268 img.data.resize(height * img.step);
00269 img.header.stamp = triggerTime;
00270 img.header.frame_id = frame_id;
00271
00272 VRmImage *VRimg = NULL;
00273 camAccess.lock();
00274 VRmRetVal success = VRmUsbCamLockNextImageEx(device, port, &VRimg, NULL);
00275 camAccess.unlock();
00276 if(!success)
00277 {
00278 std::stringstream err;
00279 err << "VRmUsbCamLockNextImageEx failed for port" << port << ".";
00280 throw VRGrabException(err.str().c_str());
00281 }
00282
00283 for(unsigned int i = 0; i < height * width; i++)
00284 {
00285 img.data[i * 2 + 1] = VRimg->mp_buffer[i * 2] >> 6;
00286 img.data[i * 2] = (VRimg->mp_buffer[i * 2] << 2)
00287 | (VRimg->mp_buffer[i * 2 + 1] & 0x3);
00288 }
00289
00290 if(!VRmUsbCamUnlockNextImage(device, &VRimg))
00291 throw VRGrabException("VRmUsbCamUnlockNextImage failed.");
00292
00293 if(!VRmUsbCamFreeImage(&VRimg))
00294 throw VRGrabException("VRmUsbCamFreeImage failed.");
00295 }
00296
00297 void VRMagicStereoNode::initProperties()
00298 {
00299 props = new PropertyCache();
00300
00301 if(!VRmUsbCamGetPropertyValueF(device, VRM_PROPID_MULTICAM_MASTER_EXPOSURE_TIME_F, &props->exposureTime))
00302 std::cerr << "VRmUsbCamGetPropertyValueF(MULTICAM_MASTER_EXPOSURE_TIME_F) failed." << std::endl;
00303
00304 if(!VRmUsbCamGetPropertyValueB(device, VRM_PROPID_DEVICE_STATUS_LED_B, &props->useLEDs))
00305 std::cerr << "VRmUsbCamGetPropertyValueB(DEVICE_STATUS_LED_B) failed." << std::endl;
00306
00307 VRmPropId sensor = VRM_PROPID_GRAB_SENSOR_PROPS_SELECT_1;
00308 VRmUsbCamSetPropertyValueE(device, VRM_PROPID_GRAB_SENSOR_PROPS_SELECT_E, &sensor);
00309 if(!VRmUsbCamGetPropertyValueI(device, VRM_PROPID_CAM_GAIN_MONOCHROME_I, &props->gainLeft))
00310 std::cerr << "VRmUsbCamGetPropertyValueI(VRM_PROPID_CAM_GAIN_MONOCHROME_I) failed." << std::endl;
00311
00312 sensor = VRM_PROPID_GRAB_SENSOR_PROPS_SELECT_3;
00313 VRmUsbCamSetPropertyValueE(device, VRM_PROPID_GRAB_SENSOR_PROPS_SELECT_E, &sensor);
00314 if(!VRmUsbCamGetPropertyValueI(device, VRM_PROPID_CAM_GAIN_MONOCHROME_I, &props->gainRight))
00315 std::cerr << "VRmUsbCamGetPropertyValueI(VRM_PROPID_CAM_GAIN_MONOCHROME_I) failed." << std::endl;
00316
00317 props->fps = 0.5;
00318 }
00319
00320 void VRMagicStereoNode::initCam(VRmDWORD camDesired)
00321 {
00322 VRmDWORD libversion;
00323 if(!VRmUsbCamGetVersion(&libversion))
00324 throw VRControlException("VRmUsbCamGetVersion failed.");
00325 else
00326 std::cout << "VR Magic lib has version " << libversion << std::endl;
00327
00328 VRmDWORD size;
00329 if(!VRmUsbCamGetDeviceKeyListSize(&size))
00330 throw VRControlException("VRmUsbCamGetDeviceKeyListSize failed.");
00331
00332 if(camDesired >= size)
00333 throw VRControlException("Invalid device index.");
00334
00335 VRmDeviceKey* devKey;
00336 if(!VRmUsbCamGetDeviceKeyListEntry(camDesired, &devKey))
00337 throw VRControlException("VRmUsbCamGetDeviceKeyListEntry failed.");
00338
00339 if(devKey->m_busy)
00340 throw VRControlException("device busy");
00341
00342 if(!VRmUsbCamOpenDevice(devKey, &device))
00343 throw VRControlException("VRmUsbCamOpenDevice failed.");
00344
00345 std::cout << "device " << devKey->mp_product_str << " [" << devKey->mp_manufacturer_str
00346 << "] opened" << std::endl;
00347
00348 if(!VRmUsbCamFreeDeviceKey(&devKey))
00349 std::cerr << "VRmUsbCamFreeDeviceKey failed." << std::endl;
00350
00351 SourceFormatList sFmtList(device);
00352 SourceFormatList::iterator fmt = find_if(sFmtList.begin(), sFmtList.end(), FormatIndicator());
00353 if(fmt == sFmtList.end())
00354 throw VRControlException("no acceptable format found.");
00355
00356 leftCalib.width = rightCalib.width = width = fmt->m_width;
00357 leftCalib.height = rightCalib.height = height = fmt->m_height;
00358
00359 if(!VRmUsbCamSetSourceFormatIndex(device, fmt - sFmtList.begin()))
00360 throw VRControlException("failed to select desired format.");
00361
00362 VRmPropId mode = VRM_PROPID_GRAB_MODE_TRIGGERED_SOFT;
00363 if (!VRmUsbCamSetPropertyValueE(device, VRM_PROPID_GRAB_MODE_E, &mode))
00364 throw VRControlException("failed to set software trigger (VRM_PROPID_GRAB_MODE_TRIGGERED_SOFT).");
00365
00366 if(!VRmUsbCamStart(device))
00367 throw VRControlException("VRmUsbCamStart failed.");
00368 }
00369
00370 void VRMagicStereoNode::retireCam()
00371 {
00372 if(!VRmUsbCamStop(device))
00373 std::cerr << "VRmUsbCamStop failed." << std::endl;
00374
00375 if(!VRmUsbCamCloseDevice(device))
00376 std::cerr << "VRmUsbCamCloseDevice failed." << std::endl;
00377
00378 VRmUsbCamCleanup();
00379 }
00380
00381 VRMagicStereoNode::VRMagicStereoNode(VRmDWORD camDesired) : calibrated(false), framesDelivered(0),
00382 leftNs("left"), rightNs("right"), fpsLimit(0.5), frame_id("camer_optical_frame")
00383 {
00384 leftCalib.K[0] = rightCalib.K[0] = 0.0;
00385 initCam(camDesired);
00386 loadCalibration();
00387 initProperties();
00388 dConfServer.setCallback(boost::bind(&VRMagicStereoNode::propertyUpdate, this, _1, _2));
00389 AnnounceTopics();
00390 }
00391
00392 VRMagicStereoNode::~VRMagicStereoNode()
00393 {
00394 retireCam();
00395 AbandonTopics();
00396 delete props;
00397 }
00398
00399 void VRMagicStereoNode::spin()
00400 {
00401 while(ros::ok())
00402 {
00403 try
00404 {
00405 broadcastFrame();
00406 }
00407 catch(VRGrabException &ex)
00408 {
00409 std::cerr << ex << std::endl;
00410 }
00411 ros::spinOnce();
00412 framesDelivered++;
00413
00414 boost::lock_guard<boost::mutex> lock(timerAccess);
00415 fpsLimit.sleep();
00416 }
00417 }
00418
00419 void forceShutdown(int sig)
00420 {
00421 signal(SIGSEGV, SIG_DFL);
00422 std::cerr << "Segfault, shutting down camera !" << std::endl;
00423
00424 if (vrsnode)
00425 vrsnode->retireCam();
00426 }
00427
00428 int main(int argc, char **argv)
00429 {
00430 ros::init(argc, argv, "vrmagic_stereo_node", ros::init_options::AnonymousName);
00431
00432 signal(SIGSEGV, forceShutdown);
00433
00434 try
00435 {
00436 vrsnode = new VRMagicStereoNode(0);
00437 vrsnode->spin();
00438 }
00439 catch(VRControlException &cex)
00440 {
00441 std::cerr << cex << std::endl;
00442 VRmUsbCamCleanup();
00443 }
00444
00445 delete vrsnode;
00446
00447 return 0;
00448 }