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
00035 #include "prosilica/prosilica.h"
00036 #include <prosilica_gige_sdk/PvRegIo.h>
00037 #include <cassert>
00038 #include <cstdio>
00039 #include <ctime>
00040 #include <cstring>
00041 #include <arpa/inet.h>
00042
00043 #include <ros/console.h>
00044
00045 #define CHECK_ERR(fnc, amsg) \
00046 do { \
00047 tPvErr err = fnc; \
00048 if (err != ePvErrSuccess) { \
00049 char msg[256]; \
00050 snprintf(msg, 256, "%s: %s", amsg, errorStrings[err]); \
00051 throw ProsilicaException(err, msg); \
00052 } \
00053 } while (false)
00054
00055 namespace prosilica {
00056
00057 static const unsigned int MAX_CAMERA_LIST = 10;
00058 static const char* autoValues[] = {"Manual", "Auto", "AutoOnce"};
00059 static const char* triggerModes[] = {"Freerun", "SyncIn1", "SyncIn2", "FixedRate", "Software"};
00060 static const char* acquisitionModes[] = {"Continuous","SingleFrame","MultiFrame","Recorder"};
00061 static const char* errorStrings[] = {"No error",
00062 "Unexpected camera fault",
00063 "Unexpected fault in PvApi or driver",
00064 "Camera handle is invalid",
00065 "Bad parameter to API call",
00066 "Sequence of API calls is incorrect",
00067 "Camera or attribute not found",
00068 "Camera cannot be opened in the specified mode",
00069 "Camera was unplugged",
00070 "Setup is invalid (an attribute is invalid)",
00071 "System/network resources or memory not available",
00072 "1394 bandwidth not available",
00073 "Too many frames on queue",
00074 "Frame buffer is too small",
00075 "Frame cancelled by user",
00076 "The data for the frame was lost",
00077 "Some data in the frame is missing",
00078 "Timeout during wait",
00079 "Attribute value is out of the expected range",
00080 "Attribute is not this type (wrong access function)",
00081 "Attribute write forbidden at this time",
00082 "Attribute is not available at this time",
00083 "A firewall is blocking the traffic"};
00084
00085 static tPvCameraInfo cameraList[MAX_CAMERA_LIST];
00086 static unsigned long cameraNum = 0;
00087
00088 void init()
00089 {
00090 CHECK_ERR( PvInitialize(), "Failed to initialize Prosilica API" );
00091 }
00092
00093 void fini()
00094 {
00095 PvUnInitialize();
00096 }
00097
00098 size_t numCameras()
00099 {
00100 cameraNum = PvCameraList(cameraList, MAX_CAMERA_LIST, NULL);
00101 return cameraNum;
00102 }
00103
00104 uint64_t getGuid(size_t i)
00105 {
00106 assert(i < MAX_CAMERA_LIST);
00107 if (i >= cameraNum)
00108 throw ProsilicaException(ePvErrBadParameter, "No camera at index i");
00109 return cameraList[i].UniqueId;
00110 }
00111
00112 std::vector<CameraInfo> listCameras()
00113 {
00114 std::vector<CameraInfo> cameras;
00115 tPvCameraInfo cameraList[MAX_CAMERA_LIST];
00116 unsigned long cameraNum = 0;
00118 cameraNum = PvCameraList(cameraList, MAX_CAMERA_LIST, NULL);
00120 if (cameraNum < MAX_CAMERA_LIST)
00121 {
00122 cameraNum += PvCameraListUnreachable(&cameraList[cameraNum], MAX_CAMERA_LIST-cameraNum, NULL);
00123 }
00124 if(cameraNum)
00125 {
00126 struct in_addr addr;
00127 tPvIpSettings Conf;
00128
00130 for(unsigned long i=0; i < cameraNum; i++)
00131 {
00132
00133 CameraInfo camInfo;
00134 camInfo.serial = to_string(cameraList[i].SerialString);
00135 camInfo.name = to_string(cameraList[i].DisplayName);
00136 camInfo.guid = to_string(cameraList[i].UniqueId);
00137 PvCameraIpSettingsGet(cameraList[i].UniqueId,&Conf);
00138 addr.s_addr = Conf.CurrentIpAddress;
00139 camInfo.ip_address = to_string(inet_ntoa(addr));
00140 camInfo.access = cameraList[i].PermittedAccess & ePvAccessMaster ? true : false;
00141
00142 cameras.push_back(camInfo);
00143 }
00144 }
00145 return cameras;
00146 }
00147
00148 std::string getIPAddress(uint64_t guid)
00149 {
00150 struct in_addr addr;
00151 tPvIpSettings Conf;
00152 CHECK_ERR(PvCameraIpSettingsGet(guid, &Conf), "Unable to retrieve IP address");
00153 addr.s_addr = Conf.CurrentIpAddress;
00154 std::stringstream ip;
00155 ip<<inet_ntoa(addr);
00156 return ip.str();
00157 }
00158
00160 static void openCamera(boost::function<tPvErr (tPvCameraInfo*)> info_fn,
00161 boost::function<tPvErr (tPvAccessFlags)> open_fn)
00162 {
00163 cameraNum = PvCameraList(cameraList, MAX_CAMERA_LIST, NULL);
00164 tPvCameraInfo info;
00165 CHECK_ERR( info_fn(&info), "Unable to find requested camera" );
00166
00167 if (!(info.PermittedAccess & ePvAccessMaster))
00168 throw ProsilicaException(ePvErrAccessDenied,
00169 "Unable to open camera as master. "
00170 "Another process is already using it.");
00171
00172 CHECK_ERR( open_fn(ePvAccessMaster), "Unable to open requested camera" );
00173 }
00174
00175 Camera::Camera(unsigned long guid, size_t bufferSize)
00176 : bufferSize_(bufferSize), FSTmode_(None)
00177 {
00178 openCamera(boost::bind(PvCameraInfo, guid, _1),
00179 boost::bind(PvCameraOpen, guid, _1, &handle_));
00180
00181 setup();
00182 }
00183
00184 Camera::Camera(const char* ip_address, size_t bufferSize)
00185 : bufferSize_(bufferSize), FSTmode_(None)
00186 {
00187 unsigned long addr = inet_addr(ip_address);
00188 tPvIpSettings settings;
00189 openCamera(boost::bind(PvCameraInfoByAddr, addr, _1, &settings),
00190 boost::bind(PvCameraOpenByAddr, addr, _1, &handle_));
00191
00192 setup();
00193 }
00194
00195 void Camera::setup()
00196 {
00197
00198 tPvUint32 maxPacketSize = 9000;
00199 PvCaptureAdjustPacketSize(handle_, maxPacketSize);
00200
00201
00202 unsigned long max_data_rate = getMaxDataRate();
00203 if (max_data_rate < GIGE_MAX_DATA_RATE) {
00204 ROS_WARN("Detected max data rate is %lu bytes/s, typical maximum data rate for a "
00205 "GigE port is %lu bytes/s. Are you using a GigE network card and cable?\n",
00206 max_data_rate, GIGE_MAX_DATA_RATE);
00207 }
00208 setAttribute("StreamBytesPerSecond", max_data_rate);
00209
00210
00211 setBinning();
00212 setRoiToWholeFrame();
00213
00214
00215 CHECK_ERR( PvAttrUint32Get(handle_, "TotalBytesPerFrame", &frameSize_),
00216 "Unable to retrieve frame size" );
00217
00218
00219 frames_ = new tPvFrame[bufferSize_];
00220 memset(frames_, 0, sizeof(tPvFrame) * bufferSize_);
00221 for (unsigned int i = 0; i < bufferSize_; ++i)
00222 {
00223 frames_[i].ImageBuffer = new char[frameSize_];
00224 frames_[i].ImageBufferSize = frameSize_;
00225 frames_[i].Context[0] = (void*)this;
00226 }
00227
00228 PvLinkCallbackRegister(Camera::kill, ePvLinkRemove, this);
00229 }
00230
00231 Camera::~Camera()
00232 {
00233 PvLinkCallbackUnRegister(Camera::kill, ePvLinkRemove);
00234 stop();
00235
00236 PvCameraClose(handle_);
00237
00238 if (frames_)
00239 {
00240 for (unsigned int i = 0; i < bufferSize_; ++i)
00241 delete[] (char*)frames_[i].ImageBuffer;
00242 delete[] frames_;
00243 }
00244 }
00245
00246 void Camera::setFrameCallback(boost::function<void (tPvFrame*)> callback)
00247 {
00248 userCallback_ = callback;
00249 }
00250 void Camera::setFrameRate(tPvFloat32 frame_rate){
00251 CHECK_ERR( PvAttrFloat32Set(handle_, "FrameRate", frame_rate),
00252 "Could not set frame rate");
00253 }
00254
00255 void Camera::setKillCallback(boost::function<void (unsigned long UniqueId)> callback)
00256 {
00257 killCallback_ = callback;
00258 }
00259
00260 void Camera::start(FrameStartTriggerMode fmode, tPvFloat32 frame_rate, AcquisitionMode amode)
00261 {
00262 assert( FSTmode_ == None && fmode != None );
00264 assert( fmode == SyncIn1 || fmode == SyncIn2 || fmode == Software || fmode == FixedRate || !userCallback_.empty() );
00265
00266
00267 CHECK_ERR( PvCaptureStart(handle_), "Could not start capture");
00268
00269 if (fmode == Freerun || fmode == FixedRate || fmode == SyncIn1 || fmode == SyncIn2)
00270 {
00271 for (unsigned int i = 0; i < bufferSize_; ++i)
00272 PvCaptureQueueFrame(handle_, frames_ + i, Camera::frameDone);
00273
00274 }
00275 else
00276 {
00277 bufferIndex_ = 0;
00278 CHECK_ERR( PvCaptureQueueFrame(handle_, &frames_[bufferIndex_], NULL), "Could not queue frame");
00279 }
00280
00281
00282 try {
00284 CHECK_ERR( PvAttrEnumSet(handle_, "AcquisitionMode", acquisitionModes[amode]),
00285 "Could not set acquisition mode" );
00286 CHECK_ERR( PvAttrEnumSet(handle_, "FrameStartTriggerMode", triggerModes[fmode]),
00287 "Could not set trigger mode" );
00288 CHECK_ERR( PvCommandRun(handle_, "AcquisitionStart"),
00289 "Could not start acquisition" );
00290 }
00291 catch (ProsilicaException& e) {
00292 stop();
00293 throw;
00294 }
00295 FSTmode_ = fmode;
00296 Amode_ = amode;
00297
00298 CHECK_ERR( PvAttrFloat32Set(handle_, "FrameRate", frame_rate),
00299 "Could not set frame rate");
00300 }
00301
00302 void Camera::stop()
00303 {
00304 if (FSTmode_ == None)
00305 return;
00306
00307 PvCommandRun(handle_, "AcquisitionStop");
00308 PvCaptureQueueClear(handle_);
00309 PvCaptureEnd(handle_);
00310 FSTmode_ = None;
00311 }
00312
00313 void Camera::removeEvents()
00314 {
00315
00316 PvAttrUint32Set(handle_, "EventsEnable1", 0);
00317 }
00318
00319 tPvFrame* Camera::grab(unsigned long timeout_ms)
00320 {
00321 assert( FSTmode_ == Software );
00322 tPvFrame* frame = &frames_[0];
00323
00324 CHECK_ERR( PvCommandRun(handle_, "FrameStartTriggerSoftware"), "Couldn't trigger capture" );
00325 CHECK_ERR( PvCaptureWaitForFrameDone(handle_, frame, timeout_ms), "couldn't capture frame");
00326
00327 if (frame->Status == ePvErrUnplugged || frame->Status == ePvErrCancelled )
00328 {
00329 return NULL;
00330 }
00331 CHECK_ERR( PvCaptureQueueFrame(handle_, frame, NULL), "Couldn't queue frame");
00332
00333 if (frame->Status == ePvErrSuccess)
00334 return frame;
00335 if (frame->Status == ePvErrDataMissing || frame->Status == ePvErrTimeout)
00336 {
00338 boost::this_thread::sleep(boost::posix_time::millisec(50));
00339 return NULL;
00340 }
00341 else
00342 throw std::runtime_error("Unknown error grabbing frame");
00343
00344 return frame;
00345 }
00346
00347 void Camera::setExposure(unsigned int val, AutoSetting isauto)
00348 {
00349 CHECK_ERR( PvAttrEnumSet(handle_, "ExposureMode", autoValues[isauto]),
00350 "Couldn't set exposure mode" );
00351
00352 if (isauto == Manual)
00353 CHECK_ERR( PvAttrUint32Set(handle_, "ExposureValue", val),
00354 "Couldn't set exposure value" );
00355 }
00356
00357 void Camera::setGain(unsigned int val, AutoSetting isauto)
00358 {
00361 if (PvAttrIsAvailable(handle_, "GainMode") == ePvErrSuccess)
00362 {
00363 CHECK_ERR( PvAttrEnumSet(handle_, "GainMode", autoValues[isauto]),
00364 "Couldn't set gain mode" );
00365 }
00366
00367 if (isauto == Manual)
00368 CHECK_ERR( PvAttrUint32Set(handle_, "GainValue", val),
00369 "Couldn't set gain value" );
00370 }
00371
00372 void Camera::setWhiteBalance(unsigned int blue, unsigned int red, AutoSetting isauto)
00373 {
00374 if (PvAttrIsAvailable(handle_, "WhitebalMode") == ePvErrSuccess)
00375 {
00376 CHECK_ERR( PvAttrEnumSet(handle_, "WhitebalMode", autoValues[isauto]),
00377 "Couldn't set white balance mode" );
00378 }
00379
00380 if (isauto == Manual)
00381 {
00382 if(hasAttribute("WhitebalValueBlue"))
00383 {
00384 CHECK_ERR( PvAttrUint32Set(handle_, "WhitebalValueBlue", blue),
00385 "Couldn't set white balance blue value" );
00386 }
00387 if(hasAttribute("WhitebalValueRed"))
00388 {
00389 CHECK_ERR( PvAttrUint32Set(handle_, "WhitebalValueRed", red),
00390 "Couldn't set white balance red value" );
00391 }
00392 }
00393 }
00394
00395 void Camera::setRoi(unsigned int x, unsigned int y,
00396 unsigned int width, unsigned int height)
00397 {
00398 CHECK_ERR( PvAttrUint32Set(handle_, "RegionX", x),
00399 "Couldn't set region x (left edge)" );
00400 CHECK_ERR( PvAttrUint32Set(handle_, "RegionY", y),
00401 "Couldn't set region y (top edge)" );
00402 CHECK_ERR( PvAttrUint32Set(handle_, "Width", width),
00403 "Couldn't set region width" );
00404 CHECK_ERR( PvAttrUint32Set(handle_, "Height", height),
00405 "Couldn't set region height" );
00406 }
00407
00408 void Camera::setRoiToWholeFrame()
00409 {
00410 tPvUint32 min_val, max_val;
00411 CHECK_ERR( PvAttrUint32Set(handle_, "RegionX", 0),
00412 "Couldn't set region x (left edge)" );
00413 CHECK_ERR( PvAttrUint32Set(handle_, "RegionY", 0),
00414 "Couldn't set region y (top edge)" );
00415 CHECK_ERR( PvAttrRangeUint32(handle_, "Width", &min_val, &max_val),
00416 "Couldn't get range of Width attribute" );
00417 CHECK_ERR( PvAttrUint32Set(handle_, "Width", max_val),
00418 "Couldn't set region width" );
00419 CHECK_ERR( PvAttrRangeUint32(handle_, "Height", &min_val, &max_val),
00420 "Couldn't get range of Height attribute" );
00421 CHECK_ERR( PvAttrUint32Set(handle_, "Height", max_val),
00422 "Couldn't set region height" );
00423 }
00424
00425 void Camera::setBinning(unsigned int binning_x, unsigned int binning_y)
00426 {
00427
00428 if (!hasAttribute("BinningX") && binning_x == 1 && binning_y == 1)
00429 return;
00430
00431 CHECK_ERR( PvAttrUint32Set(handle_, "BinningX", binning_x),
00432 "Couldn't set horizontal binning" );
00433 CHECK_ERR( PvAttrUint32Set(handle_, "BinningY", binning_y),
00434 "Couldn't set vertical binning" );
00435 }
00436
00437 bool Camera::hasAttribute(const std::string &name)
00438 {
00439 return (PvAttrIsAvailable(handle_, name.c_str()) == ePvErrSuccess);
00440 }
00441
00442 static void getStringValuedAttribute(std::string &value,
00443 boost::function<tPvErr (char*, unsigned long, unsigned long*)> get_fn)
00444 {
00445 if (value.size() == 0)
00446 value.resize(32);
00447
00448 unsigned long actual_size;
00449 CHECK_ERR( get_fn(&value[0], value.size(), &actual_size),
00450 "Couldn't get attribute" );
00451
00452 if (actual_size >= value.size()) {
00453 value.resize(actual_size + 1);
00454 CHECK_ERR( get_fn(&value[0], value.size(), &actual_size),
00455 "Couldn't get attribute" );
00456 }
00457 }
00458
00459 void Camera::getAttributeEnum(const std::string &name, std::string &value)
00460 {
00461 getStringValuedAttribute(value,
00462 boost::bind(PvAttrEnumGet, handle_, name.c_str(), _1, _2, _3));
00463 }
00464
00465 void Camera::getAttribute(const std::string &name, tPvUint32 &value)
00466 {
00467 std::string err_msg = "Couldn't get attribute " + name;
00468 CHECK_ERR( PvAttrUint32Get(handle_, name.c_str(), &value),
00469 err_msg.c_str());
00470
00471 }
00472
00473 void Camera::getAttribute(const std::string &name, tPvFloat32 &value)
00474 {
00475 std::string err_msg = "Couldn't get attribute " + name;
00476 CHECK_ERR( PvAttrFloat32Get(handle_, name.c_str(), &value),
00477 err_msg.c_str());
00478 }
00479
00480 void Camera::getAttribute(const std::string &name, std::string &value)
00481 {
00482 getStringValuedAttribute(value,
00483 boost::bind(PvAttrStringGet, handle_, name.c_str(), _1, _2, _3));
00484 }
00485
00486 void Camera::setAttributeEnum(const std::string &name, const std::string &value)
00487 {
00488 std::string err_msg = "Couldn't get attribute " + name;
00489 CHECK_ERR( PvAttrEnumSet(handle_, name.c_str(), value.c_str()),
00490 err_msg.c_str());
00491 }
00492
00493 void Camera::setAttribute(const std::string &name, tPvUint32 value)
00494 {
00495 std::string err_msg = "Couldn't set attribute " + name;
00496 CHECK_ERR( PvAttrUint32Set(handle_, name.c_str(), value),
00497 err_msg.c_str());
00498 }
00499
00500 void Camera::setAttribute(const std::string &name, tPvFloat32 value)
00501 {
00502 std::string err_msg = "Couldn't set attribute " + name;
00503 CHECK_ERR( PvAttrFloat32Set(handle_, name.c_str(), value),
00504 err_msg.c_str());
00505 }
00506
00507 void Camera::setAttribute(const std::string &name, const std::string &value)
00508 {
00509 std::string err_msg = "Couldn't set attribute " + name;
00510 CHECK_ERR( PvAttrStringSet(handle_, name.c_str(), value.c_str()),
00511 err_msg.c_str());
00512 }
00513
00514 void Camera::runCommand(const std::string& name)
00515 {
00516 std::string err_msg = "Couldn't run command " + name;
00517 CHECK_ERR( PvCommandRun(handle_, name.c_str()), err_msg.c_str());
00518 }
00519
00520 unsigned long Camera::guid()
00521 {
00522 unsigned long id;
00523 CHECK_ERR( PvAttrUint32Get(handle_, "UniqueId", &id),
00524 "Couldn't retrieve unique id" );
00525 return id;
00526 }
00527
00528 unsigned long Camera::getMaxDataRate()
00529 {
00530 tPvUint32 min_data_rate, max_data_rate;
00531 CHECK_ERR( PvAttrRangeUint32(handle_, "StreamBytesPerSecond", &min_data_rate, &max_data_rate),
00532 "Couldn't get range of attribute StreamBytesPerSecond" );
00533 return max_data_rate;
00534 }
00535
00536 static const unsigned long USER_ADDRESS = 0x17200;
00537
00538 void Camera::writeUserMemory(const char* data, size_t size)
00539 {
00540 assert(size <= USER_MEMORY_SIZE);
00541
00542 unsigned char buffer[USER_MEMORY_SIZE] = {0};
00543 memcpy(buffer, data, size);
00544
00545 unsigned long written;
00546 CHECK_ERR( PvMemoryWrite(handle_, USER_ADDRESS, USER_MEMORY_SIZE, buffer, &written),
00547 "Couldn't write to user memory" );
00548 }
00549
00550 void Camera::readUserMemory(char* data, size_t size)
00551 {
00552 assert(size <= USER_MEMORY_SIZE);
00553
00554 unsigned char buffer[USER_MEMORY_SIZE];
00555
00556 CHECK_ERR( PvMemoryRead(handle_, USER_ADDRESS, USER_MEMORY_SIZE, buffer),
00557 "Couldn't read from user memory" );
00558
00559 memcpy(data, buffer, size);
00560 }
00561
00562 void Camera::frameDone(tPvFrame* frame)
00563 {
00564
00565 Camera* camPtr = (Camera*) frame->Context[0];
00566 if (camPtr && !camPtr->userCallback_.empty()) {
00567
00568 boost::lock_guard<boost::mutex> guard(camPtr->frameMutex_);
00569 camPtr->userCallback_(frame);
00570 }
00571
00572
00573 if (frame->Status == ePvErrUnplugged || frame->Status == ePvErrCancelled)
00574 {
00575 return;
00576 }
00577 PvCaptureQueueFrame(camPtr->handle_, frame, Camera::frameDone);
00578 }
00579
00580
00581 void Camera::kill(void* Context,
00582 tPvInterface Interface,
00583 tPvLinkEvent Event,
00584 unsigned long UniqueId)
00585 {
00586 Camera* camPtr = (Camera*) Context;
00587 if (camPtr && !camPtr->killCallback_.empty())
00588 {
00589
00590 camPtr->killCallback_(UniqueId);
00591 }
00592 }
00593
00594 tPvHandle Camera::handle()
00595 {
00596 return handle_;
00597 }
00598
00599 }
00600