vrmstnode.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2011, TU Darmstadt.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of TU Darmstadt nor the names of the
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
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 }


vrmagic_multi_driver
Author(s): Philipp Schneider, Stefan Kohlbrecher
autogenerated on Mon Oct 6 2014 08:48:01