00001
00005 #include "streamer.hpp"
00006
00007 #include "cxcore.h"
00008 #include "highgui.h"
00009
00010 int main(int argc, char **argv) {
00011
00012 ros::init(argc, argv, "streamer");
00013
00014 ros::NodeHandle private_node_handle("~");
00015
00016 streamerData startupData;
00017
00018 startupData.read_addr = argv[0];
00019 startupData.read_addr = startupData.read_addr.substr(0, startupData.read_addr.size()-12);
00020 bool inputIsValid = startupData.obtainStartingData(private_node_handle);
00021
00022 if (!inputIsValid) {
00023 ROS_ERROR("Configuration invalid!\n");
00024 return -1;
00025 }
00026
00027 ros::NodeHandle nh;
00028
00029 if (startupData.verboseMode) { ROS_INFO("Establishing streamer node..."); }
00030 boost::shared_ptr < streamerNode > streamer_node (new streamerNode (nh, startupData));
00031
00032 globalNodePtr = &streamer_node;
00033
00034 signal(SIGINT, mySigintHandler);
00035
00036
00037
00038 if (wantsToShutdown) {
00039 ros::shutdown();
00040
00041 return 0;
00042 }
00043
00044
00045 if ((startupData.subscribeMode) || (startupData.resampleMode)) {
00046 streamer_node->runBag();
00047 }
00048
00049 if (startupData.readMode) {
00050 streamer_node->runRead();
00051 }
00052
00053 if (startupData.loadMode) {
00054 streamer_node->runLoad();
00055 }
00056
00057 if ((startupData.captureMode) || (startupData.pollMode)) {
00058 streamer_node->runDevice();
00059 }
00060
00061 ros::shutdown();
00062
00063 return 0;
00064
00065 }
00066
00067 void streamerNode::prepareForTermination() {
00068 if (ofs.is_open()) {
00069 ofs.close();
00070 }
00071
00072 if (ofs_call_log.is_open()) {
00073 ofs_call_log.close();
00074 }
00075
00076 if (ofs_retrieve_log.is_open()) {
00077 ofs_retrieve_log.close();
00078 }
00079
00080 if (ofs_internal_log.is_open()) {
00081 ofs_internal_log.close();
00082 }
00083
00084 if (ofs_write_log.is_open()) {
00085 ofs_write_log.close();
00086 }
00087
00088 if (ofs_duplicates_log.is_open()) ofs_duplicates_log.close();
00089
00090 if (ofs_thermistor_log.is_open()) ofs_thermistor_log.close();
00091
00092 if (configData.serialComms) {
00093 close(mainfd);
00094 }
00095
00096 releaseDevice();
00097
00098 }
00099
00100 void mySigintHandler(int sig)
00101 {
00102
00103
00104
00105 ROS_INFO("Requested shutdown... terminating feeds...");
00106 wantsToShutdown = true;
00107
00108
00109 (*globalNodePtr)->prepareForTermination();
00110
00111
00112
00113
00114
00115
00116
00117 }
00118
00119 bool streamerNode::setupDevice() {
00120
00121 if (configData.verboseMode) { ROS_INFO("Entered setupDevice()..."); }
00122
00123 if (deviceCreated) { return false; }
00124
00125
00126
00127 colourMat.release();
00128
00129 if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00130
00131 if (configData.verboseMode) { ROS_INFO("Setting up device in 8-bit/MM mode..."); }
00132 getVideoCapture()->open(configData.device_num);
00133 } else if (configData.inputDatatype == DATATYPE_RAW) {
00134 if (configData.verboseMode) { ROS_INFO("Setting up device in 16-bit mode..."); }
00135
00136 int deviceWidth, deviceHeight;
00137 getMainVideoSource()->setup_video_capture(configData.capture_device.c_str(), deviceWidth, deviceHeight, configData.verboseMode);
00138
00139
00140
00141 if ((!configData.imageDimensionsSpecified) && (!configData.intrinsicsProvided)) {
00142
00143 ROS_INFO("Using image size learned from device initialization (%d, %d)", deviceWidth, deviceHeight);
00144 globalCameraInfo.imageSize.at<unsigned short>(0, 0) = deviceWidth;
00145 globalCameraInfo.imageSize.at<unsigned short>(0, 1) = deviceHeight;
00146 globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
00147
00148 overwriteCameraDims();
00149
00150 } else {
00151
00152
00153 if ((globalCameraInfo.cameraSize.width != deviceWidth) || (globalCameraInfo.cameraSize.height != deviceHeight)) {
00154 ROS_WARN("Device-based image size estimates (%d, %d) conflict with provided image size (%d, %d)", deviceWidth, deviceHeight, globalCameraInfo.cameraSize.width, globalCameraInfo.cameraSize.height);
00155 }
00156
00157 }
00158
00159 }
00160
00161 if (configData.verboseMode) { ROS_INFO("Device set up!"); }
00162
00163 setValidity(true);
00164 deviceCreated = true;
00165 return true;
00166 }
00167
00168 void streamerNode::releaseDevice() {
00169
00170 if (!deviceCreated) { return; }
00171
00172 if ((isVideoValid()) && (configData.verboseMode)) { ROS_INFO("setValidity(false) : releaseDevice()"); }
00173 setValidity(false);
00174
00175 if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00176 getVideoCapture()->release();
00177 } else if (configData.inputDatatype == DATATYPE_RAW) {
00178
00179 getMainVideoSource()->close_video_capture();
00180
00181 }
00182
00183 deviceCreated = false;
00184 }
00185
00186
00187 bool streamerNode::runDevice() {
00188
00189 if (configData.captureMode) {
00190 ROS_INFO("Video stream (device: %d) started...", configData.device_num);
00191 } else if (configData.pollMode) {
00192 ROS_INFO("Video polling (device: %d) started...", configData.device_num);
00193 }
00194
00195 setupDevice();
00196
00197 while (isVideoValid()) {
00198
00199
00200
00201 if (configData.verboseMode){ ROS_INFO("Starting loop.."); }
00202 if (configData.captureMode) {
00203
00204 if (configData.verboseMode){ ROS_INFO("About to spin"); }
00205 ros::spinOnce();
00206 if (configData.verboseMode){ ROS_INFO("Spun"); }
00207
00208
00209 if (streamCallback()) {
00210
00211
00212
00213 if (configData.verboseMode){ ROS_INFO("About to process"); }
00214
00215
00216 if (processImage()) {
00217
00218 if (configData.verboseMode){ ROS_INFO("Processed image."); }
00219
00220 if (readyToPublish && (!configData.serialComms || !updateUSBMode)) {
00221 if (configData.verboseMode){ ROS_INFO("About to publish topics..."); }
00222 publishTopics();
00223 if (configData.verboseMode){ ROS_INFO("Topics published."); }
00224 writeData();
00225 if (configData.verboseMode){ ROS_INFO("Data written."); }
00226 }
00227 }
00228 }
00229
00230
00231
00232 } else if (configData.pollMode) {
00233
00234
00235 streamCallback(false);
00236 ros::spinOnce();
00237
00238 }
00239
00240 if (configData.verboseMode){ ROS_INFO("Ending loop."); }
00241 }
00242
00243 ROS_INFO("About to release device here...");
00244 releaseDevice();
00245
00246 if (configData.captureMode) {
00247 ROS_INFO("Video capture terminating...");
00248 } else if (configData.pollMode) {
00249 ROS_INFO("Video polling terminating...");
00250 }
00251
00252 return true;
00253 }
00254
00255 bool streamerNode::runLoad() {
00256 ROS_INFO("Image load started...");
00257
00258 if (!processFolder()) {
00259 ROS_ERROR("Processing of folder failed...");
00260 return false;
00261 }
00262
00263 do {
00264
00265 frameCounter = 0;
00266 setValidity(true);
00267
00268 while (isVideoValid()) {
00269 ros::spinOnce();
00270 }
00271
00272 } while (configData.loopMode && !wantsToShutdown);
00273
00274 return true;
00275
00276 }
00277
00278 bool streamerNode::runRead() {
00279
00280 ROS_INFO("Video reading started...");
00281
00282 do {
00283
00284 setValidity(true);
00285
00286 if (configData.verboseMode) { ROS_INFO("Opening file (%s)...", configData.filename.c_str()); }
00287 if (configData.inputDatatype == DATATYPE_RAW) {
00288 if (getMainVideoSource()->setup_video_file(configData.filename) < 0) {
00289 ROS_ERROR("Source configuration failed.");
00290 return false;
00291 }
00292 } else if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00293 getVideoCapture()->open(configData.filename.c_str());
00294
00295 if(!cap.isOpened()) {
00296 ROS_ERROR("File open failed (using OpenCV).");
00297 return false;
00298 }
00299
00300 }
00301
00302 if (configData.verboseMode) { ROS_INFO("Source configured."); }
00303
00304 while (isVideoValid()) {
00305 ros::spinOnce();
00306 }
00307
00308 if (configData.verboseMode) { ROS_INFO("Video complete."); }
00309
00310 if (configData.inputDatatype == DATATYPE_RAW) {
00311 getMainVideoSource()->close_video_file(configData.filename);
00312 } else if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00313 getVideoCapture()->release();
00314 }
00315
00316 } while (configData.loopMode && !wantsToShutdown);
00317
00318 if (configData.verboseMode) { ROS_INFO("Video reading terminating..."); }
00319
00320 return true;
00321
00322 }
00323
00324 bool streamerNode::runBag() {
00325
00326 if (configData.subscribeMode) {
00327 ROS_INFO("Subscription started...");
00328 } else if (configData.resampleMode) {
00329 ROS_INFO("Resampling subscription started...");
00330 }
00331
00332 while (isVideoValid()) {
00333
00334 ros::spinOnce();
00335
00336 }
00337
00338 if (configData.subscribeMode) {
00339 ROS_INFO("Subscription terminating...");
00340 } else if (configData.resampleMode) {
00341 ROS_INFO("Resampling subscription terminating...");
00342 }
00343
00344 return true;
00345 }
00346
00347
00348 bool streamerNode::processFolder() {
00349
00350 DIR * dirp;
00351 struct dirent * entry;
00352
00353 dirp = opendir(configData.folder.c_str());
00354
00355 if (dirp == NULL) {
00356 ROS_ERROR("Opening of directory (%s) failed.", configData.folder.c_str());
00357 return false;
00358 }
00359
00360 while ((entry = readdir(dirp)) != NULL) {
00361 if (entry->d_type == DT_REG) {
00362 inputList.push_back(string(entry->d_name));
00363 fileCount++;
00364 }
00365 }
00366
00367 closedir(dirp);
00368
00369 sort(inputList.begin(), inputList.end());
00370
00371 if(fileCount == -1) {
00372 ROS_ERROR("File counting error.\n");
00373 return false;
00374 }
00375
00376 ROS_INFO("No. of images in folder = %d\n", fileCount);
00377
00378 if (fileCount == 0) {
00379 ROS_ERROR("Returning, because no images are in folder.\n");
00380 return false;
00381 }
00382
00383 return true;
00384 }
00385
00386 void streamerNode::markCurrentFrameAsDuplicate() {
00387
00388
00389 camera_info.binning_y = 1;
00390 }
00391
00392 void streamerNode::updateCameraInfo() {
00393
00394
00395
00396
00397 if ((configData.subscribeMode) || (configData.resampleMode)) {
00398
00399
00400
00401 if (configData.syncMode == SYNCMODE_IMAGEONLY) {
00402
00403
00404
00405
00406 if (configData.useCurrentRosTime) {
00407 ros::Time currTime = ros::Time::now();
00408 camera_info.header.stamp = currTime;
00409 } else {
00410 camera_info.header.stamp = original_time;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420 } else {
00421 camera_info = original_camera_info;
00422 }
00423
00424
00425
00426 memcpy(&newThermistorReading, &camera_info.binning_x, sizeof(float));
00427
00428
00429
00430
00431
00432 } else {
00433
00434
00435 ros::Time currTime = ros::Time::now();
00436
00437 camera_info.header.stamp = currTime;
00438
00439 if ((configData.captureMode || configData.pollMode) && configData.readThermistor) {
00440 memcpy(&camera_info.binning_x, &lastThermistorReading, sizeof(float));
00441
00442 }
00443
00444
00445
00446
00447 memcpy(&camera_info.R[0], &firmwareTime, sizeof(float));
00448
00449 }
00450
00451 if (configData.wantsToMarkDuplicates && lastIsDuplicate) {
00452 camera_info.binning_y = 1;
00453 } else if (configData.wantsToMarkDuplicates) {
00454 camera_info.binning_y = 0;
00455 }
00456
00457 if ((globalCameraInfo.cameraMatrix.rows == 3) && (configData.wantsToUndistort)) {
00458 for (unsigned int iii = 0; iii < 3; iii++) {
00459 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00460 camera_info.K[iii*3 + jjj] = globalCameraInfo.newCamMat.at<double>(iii,jjj);
00461 }
00462 }
00463
00464 for (unsigned int iii = 0; iii < camera_info.D.size(); iii++) {
00465 camera_info.D.at(iii) = 0.0;
00466 }
00467 }
00468
00469 msg_color.header = camera_info.header;
00470 msg_16bit.header = camera_info.header;
00471 msg_8bit.header = camera_info.header;
00472
00473
00474 }
00475
00476 void streamerNode::assignCameraInfo() {
00477
00478 if (configData.verboseMode) { ROS_INFO("Entered assignCameraInfo()..."); }
00479
00480 char frame_id[256];
00481 sprintf(frame_id, "%s_%s_%s", "thermalvis", nodeName, "optical_frame");
00482 camera_info.header.frame_id = string(frame_id);
00483 msg_color.header.frame_id = string(frame_id);
00484 msg_16bit.header.frame_id = string(frame_id);
00485 msg_8bit.header.frame_id = string(frame_id);
00486
00487 camera_info.height = globalCameraInfo.imageSize.at<unsigned short>(0, 1);
00488 camera_info.width = globalCameraInfo.imageSize.at<unsigned short>(0, 0);
00489
00490
00491
00492
00493
00494
00495 if (globalCameraInfo.distCoeffs.cols != 5) {
00496
00497 camera_info.distortion_model = "rational_polynomial";
00498 if (configData.verboseMode) { ROS_INFO("Camera model : RATIONAL POLYNOMIAL - (%d) coeffs", globalCameraInfo.distCoeffs.cols); }
00499 } else {
00500 camera_info.distortion_model = "plumb_bob";
00501 if (configData.verboseMode) { ROS_INFO("Camera model : PLUMB BOB - (%d) coeffs", globalCameraInfo.distCoeffs.cols); }
00502 }
00503
00504 camera_info.D.clear();
00505
00506
00507
00508 for (int iii = 0; iii < globalCameraInfo.distCoeffs.cols; iii++) {
00509 camera_info.D.push_back(globalCameraInfo.distCoeffs.at<double>(0, iii));
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 if (globalCameraInfo.cameraMatrix.rows == 3) {
00525 for (unsigned int iii = 0; iii < 3; iii++) {
00526 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00527 if (configData.wantsToUndistort) {
00528 camera_info.K[iii*3 + jjj] = globalCameraInfo.newCamMat.at<double>(iii,jjj);
00529 } else {
00530 camera_info.K[iii*3 + jjj] = globalCameraInfo.cameraMatrix.at<double>(iii,jjj);
00531 }
00532 }
00533 }
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 if (configData.wantsToAddExtrinsics){
00555 if (configData.camera_number == 0){
00556 for (unsigned int iii = 0; iii < 3; iii++) {
00557 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00558 camera_info.R[iii*3 + jjj] = globalExtrinsicsData.R0.at<double>(iii,jjj);
00559 }
00560 }
00561 for (unsigned int iii = 0; iii < 3; iii++) {
00562 for (unsigned int jjj = 0; jjj < 4; jjj++) {
00563 camera_info.P[iii*4 + jjj] = globalExtrinsicsData.P0.at<double>(iii,jjj);
00564 }
00565 }
00566 }else if (configData.camera_number == 1){
00567 for (unsigned int iii = 0; iii < 3; iii++) {
00568 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00569 camera_info.R[iii*3 + jjj] = globalExtrinsicsData.R1.at<double>(iii,jjj);
00570 }
00571 }
00572 for (unsigned int iii = 0; iii < 3; iii++) {
00573 for (unsigned int jjj = 0; jjj < 4; jjj++) {
00574 camera_info.P[iii*4 + jjj] = globalExtrinsicsData.P1.at<double>(iii,jjj);
00575 }
00576 }
00577 }
00578
00579 } else {
00580 if (globalCameraInfo.R.rows == 3) {
00581 for (unsigned int iii = 0; iii < 3; iii++) {
00582 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00583 camera_info.R[iii*3 + jjj] = globalCameraInfo.R.at<double>(iii,jjj);
00584 }
00585 }
00586 }
00587
00588 if (globalCameraInfo.newCamMat.rows == 3) {
00589 for (unsigned int iii = 0; iii < 3; iii++) {
00590 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00591 camera_info.P[iii*4 + jjj] = globalCameraInfo.newCamMat.at<double>(iii,jjj);
00592 }
00593 }
00594 }
00595 }
00596
00597
00598 if (configData.wantsToUndistort) {
00599 if ((globalCameraInfo.cameraMatrix.rows == 3) && (globalCameraInfo.distCoeffs.cols > 0) && (globalCameraInfo.newCamMat.rows == 3)) {
00600
00601
00602 if (configData.wantsToAddExtrinsics){
00603 if (configData.wantsToRectify){
00604 if (configData.camera_number == 0){
00605 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R0, globalExtrinsicsData.P0, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
00606 }else if (configData.camera_number == 1){
00607 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R1, globalExtrinsicsData.P1, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
00608 }
00609 }else{
00610 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
00611 }
00612 }else{
00613 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
00614 }
00615
00616 }
00617 }
00618
00619 if (configData.verboseMode) { ROS_INFO("Camera info assigned."); }
00620
00621 }
00622
00623
00624 void streamerNode::updateCameraInfoExtrinsics() {
00625 if (configData.verboseMode) { ROS_INFO("Updating camera info..."); }
00626 if (configData.camera_number == 0){
00627 for (unsigned int iii = 0; iii < 3; iii++) {
00628 for (unsigned int jjj = 0; jjj < 4; jjj++) {
00629 camera_info.P[iii*4 + jjj] = globalExtrinsicsData.P0.at<double>(iii,jjj);
00630 }
00631 }
00632 }else if (configData.camera_number == 1){
00633 for (unsigned int iii = 0; iii < 3; iii++) {
00634 for (unsigned int jjj = 0; jjj < 4; jjj++) {
00635 camera_info.P[iii*4 + jjj] = globalExtrinsicsData.P1.at<double>(iii,jjj);
00636 }
00637 }
00638 }
00639 if (configData.verboseMode) { ROS_INFO("Camera info updated."); }
00640 }
00641
00642 bool streamerNode::setCameraInfo(sensor_msgs::SetCameraInfo::Request &req, sensor_msgs::SetCameraInfo::Response &rsp) {
00643
00644 camera_info = req.camera_info;
00645
00646 if (configData.verboseMode) { ROS_INFO("calling assignCameraInfo() from setCameraInfo()..."); }
00647 assignCameraInfo();
00648
00649 if (camera_calibration_parsers::writeCalibrationIni("../camera_parameters.txt", "gscam", camera_info)) {
00650 ROS_INFO("Camera information written to camera_parameters.txt");
00651 return true;
00652 }
00653 else {
00654 ROS_ERROR("Could not write camera_parameters.txt");
00655 return false;
00656 }
00657 }
00658
00659 bool streamerNode::streamCallback(bool capture) {
00660
00661 int currAttempts = 0;
00662
00663 if (configData.verboseMode) {
00664 ros::Time callbackTime = ros::Time::now();
00665 ROS_INFO("Entered <streamCallback> at (%f)", callbackTime.toSec());
00666 }
00667
00668 if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00669
00670 if (configData.verboseMode){ ROS_INFO("Updating camera info..."); }
00671 updateCameraInfo();
00672 if (configData.verboseMode){ ROS_INFO("Camera info updated."); }
00673 ofs_call_log << ros::Time::now().toNSec() << endl;
00674 if (configData.verboseMode){ ROS_INFO("Capturing frame (8-bit/MM)..."); }
00675 cap >> frame;
00676
00677 if (configData.fixDudPixels) {
00678 if (configData.verboseMode){ ROS_INFO("Fixing dud pixels..."); }
00679 fix_bottom_right(frame);
00680 if (configData.verboseMode){ ROS_INFO("Dud pixels fixed."); }
00681 }
00682
00683 if (configData.verboseMode){ ROS_INFO("Frame captured."); }
00684 ofs_retrieve_log << ros::Time::now().toNSec() << endl;
00685 } else if (configData.inputDatatype == DATATYPE_RAW) {
00686
00687 ros::Time callTime, retrieveTime;
00688
00689 callTime = ros::Time::now();
00690 if (configData.verboseMode) { ROS_INFO("Capturing frame (16-bit)... (%f)", callTime.toSec()); }
00691
00692
00693 while ((configData.maxReadAttempts == 0) || (currAttempts < configData.maxReadAttempts)) {
00694
00695
00696 if (configData.verboseMode){ ROS_INFO("Attempting to capture frame..."); }
00697
00698 if (av_read_frame(mainVideoSource->pIFormatCtx, &(mainVideoSource->oPacket)) != 0) {
00699 if (configData.verboseMode){ ROS_WARN("av_read_frame() failed."); }
00700 currAttempts++;
00701 continue;
00702 }
00703
00704 if (configData.verboseMode){ ROS_INFO("Frame captured successfully."); }
00705
00706 retrieveTime = ros::Time::now();
00707 firmwareTime = mainVideoSource->oPacket.pts;
00708
00709 if (configData.verboseMode){ ROS_INFO("Updating camera info..."); }
00710 updateCameraInfo();
00711 if (configData.verboseMode){ ROS_INFO("Camera info updated."); }
00712
00713 if (mainVideoSource->bRet < 0) {
00714 if (configData.verboseMode) { ROS_WARN("(mainVideoSource->bRet < 0) failed."); }
00715 currAttempts++;
00716 continue;
00717 }
00718
00719 if (mainVideoSource->oPacket.stream_index != mainVideoSource->ixInputStream) {
00720 if (configData.verboseMode) { ROS_WARN("(mainVideoSource->oPacket.stream_index != mainVideoSource->ixInputStream) failed."); }
00721 currAttempts++;
00722 continue;
00723 }
00724
00725 if (configData.verboseMode){ ROS_INFO("Decoding frame..."); }
00726 avcodec_decode_video2(mainVideoSource->pICodecCtx, mainVideoSource->pFrame, &(mainVideoSource->fFrame),&(mainVideoSource->oPacket));
00727 if (configData.verboseMode){ ROS_INFO("Frame decoded."); }
00728
00729 av_free_packet(&(mainVideoSource->oPacket));
00730 if (configData.verboseMode){ ROS_INFO("Frame freed."); }
00731
00732 if (!(mainVideoSource->fFrame)) {
00733 if (configData.verboseMode) { ROS_WARN("(!(mainVideoSource->fFrame)) failed."); }
00734 currAttempts++;
00735 continue;
00736 }
00737
00738 if (capture) {
00739 if (configData.verboseMode){ ROS_INFO("Accepting image..."); }
00740 acceptImage((void*) *(mainVideoSource->pFrame->data));
00741 if (configData.verboseMode){ ROS_INFO("Image accepted."); }
00742
00743 char outbuff[256];
00744
00745 uint32_t internal_sec, internal_nsec;
00746
00747 internal_sec = firmwareTime / 1000000;
00748 internal_nsec = (firmwareTime % 1000000) * 1000;
00749
00750
00751 sprintf(outbuff, "%010d.%09d", internal_sec, internal_nsec);
00752
00753 if (configData.wantsToDumpTimestamps) {
00754 ofs_internal_log << outbuff << endl;
00755
00756
00757 char output_time[256];
00758 sprintf(output_time,"%010d.%09d", retrieveTime.sec, retrieveTime.nsec);
00759 ofs_retrieve_log << output_time << endl;
00760 ofs_call_log << callTime.toNSec() << endl;
00761 }
00762
00763 }
00764
00765
00766 if (configData.verboseMode){ ROS_INFO("Frame read."); }
00767 break;
00768
00769 }
00770
00771 if ((currAttempts >= configData.maxReadAttempts) && (configData.maxReadAttempts != 0)) {
00772 ROS_ERROR("Frame reading failed after (%d) attempts.", currAttempts);
00773 setValidity(false);
00774 return false;
00775 }
00776
00777
00778 if (currAttempts >= 1) {
00779 ROS_WARN("Frame reading required (%d) attempts.", currAttempts+1);
00780 }
00781 }
00782
00783
00784
00785
00786 if (configData.verboseMode){ ROS_INFO("Exiting callback..."); }
00787
00788 return true;
00789 }
00790
00791 void streamerNode::acceptImage(void *ptr) {
00792
00793 if (temperatureMat.rows == 0) {
00794 if (canRadiometricallyCorrect) {
00795
00796 temperatureMat = cv::Mat::zeros(camera_info.height, camera_info.width, CV_32FC1);
00797
00798 }
00799 }
00800
00801 if (configData.inputDatatype == DATATYPE_RAW) {
00802 if ((frame.rows == 0) || (frame.type() != CV_16UC1)) {
00803 frame = cv::Mat::zeros(camera_info.height, camera_info.width, CV_16UC1);
00804 }
00805
00806 if (configData.verboseMode){ ROS_INFO("Copying image data to internal matrix... (%d, %d)", camera_info.width, camera_info.height); }
00807 memcpy(&(frame.at<unsigned char>(0,0)), ptr, camera_info.width*camera_info.height*2);
00808 if (configData.verboseMode){ ROS_INFO("Data copied."); }
00809
00810
00811
00812 } else if (configData.inputDatatype == DATATYPE_8BIT) {
00813 if ((frame.rows == 0) || (frame.type() != CV_8UC1)) {
00814 frame = cv::Mat::zeros(camera_info.height, camera_info.width, CV_8UC1);
00815 }
00816
00817 if (configData.verboseMode){ ROS_INFO("Copying image data to internal matrix.... (%d, %d)", camera_info.width, camera_info.height); }
00818 memcpy(&(frame.at<unsigned char>(0,0)), ptr, camera_info.width*camera_info.height);
00819 if (configData.verboseMode){ ROS_INFO("Data copied."); }
00820
00821 } else if (configData.inputDatatype == DATATYPE_MM){
00822 if ((frame.rows == 0) || (frame.type() != CV_8UC3)) {
00823 frame = cv::Mat::zeros(camera_info.height, camera_info.width, CV_8UC3);
00824 }
00825
00826 if (configData.verboseMode){ ROS_INFO("Copying image data to internal matrix... (%d, %d)", camera_info.width, camera_info.height); }
00827 memcpy(&(frame.at<unsigned char>(0,0)), ptr, camera_info.width*camera_info.height*3);
00828 if (configData.verboseMode){ ROS_INFO("Data copied."); }
00829 }
00830
00831 if (configData.fixDudPixels) {
00832 if (configData.verboseMode){ ROS_INFO("Fixing dud pixels..."); }
00833 fix_bottom_right(frame);
00834 if (configData.verboseMode){ ROS_INFO("Dud pixels fixed."); }
00835 }
00836
00837 }
00838
00839 bool streamerNode::processImage() {
00840
00841 if (frame.rows == 0) {
00842 return false;
00843 }
00844
00845
00846
00847
00848 if (configData.wantsToResize) {
00849 resize(frame, rzMat, cv::Size(configData.desiredCols, configData.desiredRows));
00850 frame = cv::Mat(rzMat);
00851 }
00852
00853
00854 if (configData.wantsToRemoveDuplicates || configData.wantsToMarkDuplicates || configData.wantsToOutputDuplicates) {
00855
00856 if (matricesAreEqual(frame, lastFrame)) {
00857
00858 lastNucPerformed_at_the_earliest = ros::Time::now();
00859
00860 if (configData.wantsToMarkDuplicates) {
00861
00862
00863 lastIsDuplicate = true;
00864 }
00865
00866
00867 if (configData.wantsToOutputDuplicates) {
00868
00869 ofs_duplicates_log << "1" << endl;
00870 } else {
00871
00872 }
00873
00874
00875 if (configData.wantsToRemoveDuplicates) {
00876 if (configData.loadMode) {
00877 frameCounter++;
00878 }
00879 return false;
00880 }
00881
00882 } else {
00883
00884
00885 if (configData.wantsToMarkDuplicates) {
00886
00887 lastIsDuplicate = false;
00888 }
00889
00890
00891 if (configData.wantsToOutputDuplicates) {
00892
00893 ofs_duplicates_log << "0" << endl;
00894 } else {
00895
00896 }
00897
00898 }
00899
00900 frame.copyTo(lastFrame);
00901
00902 }
00903
00904
00905
00906
00907 if (configData.readThermistor) {
00908
00909
00910 }
00911
00912
00913
00914
00915 if (configData.verboseMode){ROS_INFO("Processing image (%d)...", frameCounter);}
00916
00917
00918 if (pastMeanIndex >= (configData.temporalMemory-1)) {
00919 pastMeanIndex = 0;
00920 } else {
00921 pastMeanIndex++;
00922 }
00923
00924 if (configData.inputDatatype == DATATYPE_RAW) {
00925
00926 _16bitMat = cv::Mat(frame);
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 if (configData.normFactor > 0.0) {
00940
00941
00942 double percentile_levels[2];
00943 percentile_levels[0] = (configData.normFactor / 2.0);
00944 percentile_levels[1] = 1.0 - (configData.normFactor / 2.0);
00945 double percentile_values[2];
00946
00947 findPercentiles(_16bitMat, percentile_values, percentile_levels, 2);
00948
00949 thresholdRawImage(_16bitMat, percentile_values);
00950
00951 }
00952
00953
00954
00955
00956 if (canRadiometricallyCorrect && configData.radiometricCorrection) {
00957
00958
00959
00960 if (configData.radiometricBias != 0) {
00961 _16bitMat += configData.radiometricBias;
00962 }
00963
00964 radMapper.apply(_16bitMat, temperatureMat, lastThermistorReading, configData.radiometricInterpolation);
00965
00966 }
00967
00968
00969
00970
00971 if ((configData.outputColorFlag) || (configData.output8bitFlag) || ((configData.wantsToWrite) && ((configData.outputType == "CV_8UC3") || (configData.outputType == "CV_8UC1")) )) {
00972
00973
00974 if (configData.verboseMode) { ROS_INFO("Entering here x123..."); }
00975
00976 if ((canRadiometricallyCorrect && configData.radiometricCorrection) || configData.alreadyCorrected) {
00977
00978 if (configData.verboseMode) { ROS_INFO("Entering here x124..."); }
00979
00980 if (configData.alreadyCorrected) {
00981 convertToTemperatureMat(_16bitMat, temperatureMat);
00982 }
00983
00984
00985 if (configData.autoTemperature) {
00986
00987 if (configData.verboseMode) { ROS_INFO("Entering here x125..."); }
00988
00989 if (configData.verboseMode) {
00990 double currMin, currMax;
00991 minMaxLoc(temperatureMat, &currMin, &currMax);
00992 ROS_WARN("Current temp image limits = (%f) : (%f, %f)", abs(currMax-currMin), currMin, currMax);
00993 }
00994
00995 double currMin, currMax, currRange, newMin, newMax;
00996
00997
00998
00999
01000
01001 minMaxLoc(temperatureMat, &currMin, &currMax);
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 if (configData.stepChangeTempScale) {
01014
01015 currRange = currMax - currMin;
01016
01017 if (currRange < 20.0) {
01018 newMin = floor(currMin);
01019 newMax = ceil(currMax);
01020 } else if (currRange < 50.0) {
01021 newMin = 2*floor(currMin/2);
01022 newMax = 2*ceil(currMax/2);
01023 } else if (currRange < 100.0) {
01024 newMin = 5*floor(currMin/5);
01025 newMax = 5*ceil(currMax/5);
01026 } else if (currRange < 200.0) {
01027 newMin = 10*floor(currMin/5);
01028 newMax = 10*ceil(currMax/5);
01029 } else if (currRange < 500.0) {
01030 newMin = 20*floor(currMin/5);
01031 newMax = 20*ceil(currMax/5);
01032 } else if (currRange < 1000.0) {
01033 newMin = 50*floor(currMin/5);
01034 newMax = 50*ceil(currMax/5);
01035 } else {
01036 newMin = 100*floor(currMin/5);
01037 newMax = 100*ceil(currMax/5);
01038 }
01039
01040
01041
01042
01043
01044
01045 if ( (abs(newMin - lastMinDisplayTemp) > 0.1*currRange) || (abs(newMax - lastMaxDisplayTemp) > 0.1*currRange) ) {
01046
01047
01048 ROS_WARN("MIN/MAX for display changed to = (%f, %f)", newMin, newMax);
01049
01050 lastMinDisplayTemp = newMin;
01051 lastMaxDisplayTemp = newMax;
01052
01053 }
01054
01055 } else {
01056 lastMinDisplayTemp = currMin;
01057 lastMaxDisplayTemp = currMax;
01058 }
01059
01060
01061
01062
01063
01064
01065
01066 temperatureDownsample(temperatureMat, preFilteredMat, lastMinDisplayTemp, lastMaxDisplayTemp);
01067
01068
01069
01070
01071 } else {
01072 if (configData.verboseMode) { ROS_INFO("Downsampling with (%f, %f)", configData.minTemperature, configData.maxTemperature); }
01073 temperatureDownsample(temperatureMat, preFilteredMat, configData.minTemperature, configData.maxTemperature);
01074 }
01075
01076
01077
01078
01079 } else {
01080 if (configData.verboseMode) { ROS_INFO("Entering here x126..."); }
01081 adaptiveDownsample(_16bitMat, preFilteredMat, configData.normMode, configData.normFactor);
01082 }
01083
01084
01085 }
01086
01087
01088
01089
01090 if (configData.output16bitFlag || (configData.wantsToWrite && (configData.outputType == "CV_16UC1"))) {
01091
01092 if (canRadiometricallyCorrect && configData.radiometricCorrection && configData.radiometricRaw) {
01093
01094 temperatureDownsample16(temperatureMat, scaled16Mat);
01095
01096
01097 } else {
01098
01099 scaled16Mat = _16bitMat;
01100
01101 }
01102
01103 }
01104
01105
01106
01107
01108 } else if (configData.inputDatatype == DATATYPE_8BIT) {
01109
01110
01111
01112
01113 if (frame.channels() == 3) {
01114
01115
01116
01117 if (firstFrame) {
01118 isActuallyGray = checkIfActuallyGray(frame);
01119
01120 firstFrame = false;
01121
01122 if (configData.forceInputGray) {
01123 isActuallyGray = true;
01124 if (configData.verboseMode) { ROS_INFO("Forcing input images to be considered gray."); }
01125 }
01126 }
01127
01128 }
01129
01130 if ((frame.channels() == 1) || (isActuallyGray)) {
01131
01132 if (frame.channels() == 1) {
01133 workingFrame = cv::Mat(frame);
01134 } else if (isActuallyGray) {
01135 if (((configData.outputColorFlag) || (configData.outputType == "CV_8UC3")) || ((configData.output8bitFlag) || (configData.outputType == "CV_8UC1"))) {
01136 cvtColor(frame, workingFrame, CV_RGB2GRAY);
01137 }
01138 }
01139
01140
01141
01142
01143 process8bitImage(workingFrame, preFilteredMat, configData.normMode, configData.normFactor);
01144
01145 } else if (frame.channels() == 3) {
01146
01147 colourMat = cv::Mat(frame);
01148
01149
01150
01151 if ((configData.output8bitFlag) || (configData.outputType == "CV_8UC1")) {
01152 cvtColor(colourMat, preFilteredMat, CV_RGB2GRAY);
01153 }
01154
01155 }
01156
01157 } else if (configData.inputDatatype == DATATYPE_MM) {
01158
01159
01160
01161 if (frame.channels() != 3) {
01162
01163 ROS_ERROR("Frames must have 3 channels to be used for multi-modal fusion.");
01164
01165 if (firstFrame) {
01166 isActuallyGray = false;
01167 firstFrame = false;
01168 }
01169
01170 } else {
01171
01172
01173
01174
01175
01176 cv::Mat thermal, visible;
01177
01178 splitMultimodalImage(frame, thermal, visible);
01179
01180 double fusion_params[2];
01181 fusion_params[0] = max(min(0.5, 0.5 - (fusionFactor/2.0)), 0.0);
01182 fusion_params[1] = max(min(0.5, 1.0 - (fusionFactor/2.0)), 1.0);
01183
01184 colourMap.fuse_image(thermal, visible, colourMat, fusion_params);
01185
01186
01187 if ((configData.output8bitFlag) || (configData.outputType == "CV_8UC1")) {
01188 cvtColor(colourMat, preFilteredMat, CV_RGB2GRAY);
01189 }
01190
01191 }
01192
01193 }
01194
01195
01196
01197
01198
01199 if (configData.filterMode > 0) {
01200 applyFilter(preFilteredMat, smoothedMat, configData.filterMode, configData.filterParam);
01201 } else {
01202 smoothedMat = preFilteredMat;
01203 }
01204
01205 if (configData.temporalSmoothing) {
01206 if (((configData.outputColorFlag) || ((configData.wantsToWrite) && (configData.outputType == "CV_8UC3"))) || ((configData.output8bitFlag) || ((configData.wantsToWrite) && (configData.outputType == "CV_8UC1")))) {
01207
01208
01209 cv::Scalar means = mean(smoothedMat);
01210
01211 pastMeans[pastMeanIndex] = means[0];
01212
01213
01214
01215 double temporalMean = 0.0;
01216
01217 for (int iii = 0; iii < min(frameCounter+1, configData.temporalMemory); iii++) {
01218
01219 temporalMean += pastMeans[iii];
01220
01221 }
01222
01223 temporalMean /= min(frameCounter+1, configData.temporalMemory);
01224
01225
01226
01227
01228
01229 shiftDiff = (((temporalMean - pastMeans[pastMeanIndex]) > 0.0) ? 1.0 : (((temporalMean - pastMeans[pastMeanIndex]) < 0.0) ? -1.0 : 0.0)) * min(abs((pastMeans[pastMeanIndex] - temporalMean)), configData.maxIntensityChange);
01230
01231 _8bitMat = smoothedMat + shiftDiff;
01232
01233
01234
01235
01236 }
01237
01238 } else {
01239 _8bitMat = smoothedMat;
01240 }
01241
01242 if ((configData.inputDatatype != DATATYPE_MM) && ((configData.inputDatatype != DATATYPE_8BIT) || (frame.channels() != 3) || isActuallyGray)) {
01243
01244
01245
01246
01247
01248
01249 if ((configData.outputColorFlag) || ((configData.wantsToWrite) && (configData.outputType == "CV_8UC3"))) {
01250
01251
01252
01253
01254 colourMap.falsify_image(_8bitMat, colourMat, configData.mapParam);
01255
01256 }
01257 }
01258
01259
01260
01261
01262
01263 if (configData.displayThermistor) {
01264
01265
01266
01267 double displayVal;
01268
01269
01270 if (newThermistorReading > lastDisplayed) {
01271
01272 displayVal = newThermistorReading-0.015;
01273
01274 } else {
01275
01276 displayVal = newThermistorReading+0.015;
01277
01278
01279 }
01280
01281 displayVal = round(20.0*displayVal)/20.0;
01282
01283 ROS_INFO("Temperature = (%.2f)", displayVal);
01284
01285 lastDisplayed = displayVal;
01286 }
01287
01288 frameCounter++;
01289
01290 if (!readyToPublish) {
01291 readyToPublish = true;
01292 }
01293
01294 return true;
01295
01296 }
01297
01298 void streamerNode::initializeMessages() {
01299
01300
01301 if (configData.output16bitFlag) {
01302 if (msg_16bit.width == 0) {
01303 if (_16bitMat.rows != 0) {
01304 msg_16bit.width = _16bitMat.cols;
01305 msg_16bit.height = _16bitMat.rows;
01306 msg_16bit.encoding = "mono16";
01307 msg_16bit.is_bigendian = false;
01308 msg_16bit.step = _16bitMat.cols*2;
01309 msg_16bit.data.resize(_16bitMat.cols*_16bitMat.rows*2);
01310 }
01311 }
01312
01313 }
01314
01315 if (configData.output8bitFlag) {
01316 if (msg_8bit.width == 0) {
01317 if (_8bitMat.rows != 0) {
01318 msg_8bit.width = _8bitMat.cols;
01319 msg_8bit.height = _8bitMat.rows;
01320 msg_8bit.encoding = "mono8";
01321 msg_8bit.is_bigendian = false;
01322 msg_8bit.step = _8bitMat.cols*1;
01323 msg_8bit.data.resize(_8bitMat.cols*_8bitMat.rows*1);
01324 }
01325 }
01326 }
01327
01328 if (configData.outputColorFlag) {
01329 if (msg_color.width == 0) {
01330 if (colourMat.rows != 0) {
01331 msg_color.width = colourMat.cols;
01332 msg_color.height = colourMat.rows;
01333 msg_color.encoding = "bgr8";
01334 msg_color.is_bigendian = false;
01335 msg_color.step = colourMat.cols*3;
01336 msg_color.data.resize(colourMat.cols*colourMat.rows*3);
01337 }
01338 }
01339
01340 }
01341 }
01342
01343 void streamerNode::publishTopics() {
01344
01345
01346 initializeMessages();
01347
01348
01349
01350
01351
01352
01353
01354
01355 bool cameraPublished = false;
01356
01357 if (configData.wantsToDumpTimestamps) {
01358
01359 ofs << camera_info.header.stamp.toNSec() << endl;
01360 }
01361
01362
01363
01364 if ((configData.output16bitFlag) || (configData.wantsToWrite && (configData.outputType == "CV_16UC1"))) {
01365
01366
01367
01368 if (configData.wantsToUndistort) {
01369 if (scaled16Mat.data == _16bitMat_pub.data) {
01370 _16bitMat_pub = cv::Mat(scaled16Mat.size(), scaled16Mat.type());
01371 }
01372
01373 remap(scaled16Mat, _16bitMat_pub, map1, map2, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
01374 } else {
01375 _16bitMat_pub = cv::Mat(scaled16Mat);
01376 }
01377
01378
01379
01380
01381
01382
01383
01384 if (configData.output16bitFlag) {
01385
01386 std::copy(&(_16bitMat_pub.at<char>(0,0)), &(_16bitMat_pub.at<char>(0,0))+(_16bitMat_pub.cols*_16bitMat_pub.rows*2), msg_16bit.data.begin());
01387
01388
01389
01390 if (!cameraPublished) {
01391
01392 pub_16bit.publish(msg_16bit, camera_info);
01393 cameraPublished = true;
01394 } else {
01395
01396 pub_16bit_im.publish(msg_16bit);
01397 }
01398
01399
01400
01401 if (configData.republishSource==REPUBLISH_CODE_16BIT){
01402
01403 if (configData.republishNewTimeStamp){
01404
01405 pub_republish.publish(msg_16bit, camera_info, ros::Time::now());
01406 } else {
01407 pub_republish.publish(msg_16bit, camera_info);
01408 }
01409 }
01410
01411 }
01412
01413 }
01414
01415 if ((configData.output8bitFlag) || (configData.wantsToWrite && (configData.outputType == "CV_8UC1"))) {
01416
01417 if (configData.wantsToUndistort) {
01418 if (_8bitMat.data == _8bitMat_pub.data) {
01419 _8bitMat_pub = cv::Mat(_8bitMat.size(), _8bitMat.type());
01420 }
01421
01422 remap(_8bitMat, _8bitMat_pub, map1, map2, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
01423 } else {
01424 _8bitMat_pub = cv::Mat(_8bitMat);
01425 }
01426
01427 if (configData.output8bitFlag) {
01428
01429
01430 if (configData.drawReticle){
01431 line(_8bitMat_pub, cv::Point(0,_8bitMat_pub.rows/2), cv::Point(_8bitMat_pub.cols, _8bitMat_pub.rows/2), cv::Scalar(0),1,8);
01432 line(_8bitMat_pub, cv::Point(_8bitMat_pub.cols/2,0), cv::Point(_8bitMat_pub.cols/2, _8bitMat_pub.rows), cv::Scalar(0),1,8);
01433 }
01434
01435 std::copy(&(_8bitMat_pub.at<unsigned char>(0,0)), &(_8bitMat_pub.at<unsigned char>(0,0))+(_8bitMat_pub.cols*_8bitMat_pub.rows), msg_8bit.data.begin());
01436
01437
01438 if (!cameraPublished) {
01439 pub_8bit.publish(msg_8bit, camera_info);
01440
01441 cameraPublished = true;
01442 } else {
01443 pub_8bit_im.publish(msg_8bit);
01444
01445 }
01446
01447
01448 if (configData.republishSource==REPUBLISH_CODE_8BIT_MONO){
01449
01450 if (configData.republishNewTimeStamp){
01451
01452 pub_republish.publish(msg_8bit, camera_info, ros::Time::now());
01453 } else{
01454 pub_republish.publish(msg_8bit, camera_info);
01455 }
01456 }
01457
01458 }
01459
01460 }
01461
01462 if ((configData.outputColorFlag) || (configData.wantsToWrite && (configData.outputType == "CV_8UC3"))) {
01463
01464
01465 if (colourMat.rows > 0) {
01466
01467
01468 if (configData.wantsToUndistort) {
01469 if (colourMat.data == colourMat_pub.data) {
01470 colourMat_pub = cv::Mat(colourMat.size(), colourMat.type());
01471 }
01472
01473 remap(colourMat, colourMat_pub, map1, map2, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
01474 } else {
01475 colourMat_pub = cv::Mat(colourMat);
01476 }
01477
01478 if (configData.outputColorFlag) {
01479
01480
01481 if (configData.drawReticle){
01482 line(colourMat_pub, cv::Point(0,colourMat_pub.rows/2), cv::Point(colourMat_pub.cols, colourMat_pub.rows/2), cv::Scalar(0,255,0),1,8);
01483 line(colourMat_pub, cv::Point(colourMat_pub.cols/2,0), cv::Point(colourMat_pub.cols/2, colourMat_pub.rows), cv::Scalar(0,255,0),1,8);
01484
01485
01486
01487
01488 }
01489
01490 std::copy(&(colourMat_pub.at<cv::Vec3b>(0,0)[0]), &(colourMat_pub.at<cv::Vec3b>(0,0)[0])+(colourMat_pub.cols*colourMat_pub.rows*3), msg_color.data.begin());
01491
01492
01493
01494 if (!cameraPublished) {
01495 if (configData.verboseMode) { ROS_INFO("%s << Publishing the whole camera...", __FUNCTION__); }
01496 pub_color.publish(msg_color, camera_info);
01497 cameraPublished = true;
01498 } else {
01499
01500 pub_color_im.publish(msg_color);
01501 }
01502
01503
01504 if (configData.republishSource==REPUBLISH_CODE_8BIT_COL){
01505
01506 if (configData.republishNewTimeStamp){
01507
01508 pub_republish.publish(msg_color, camera_info, ros::Time::now());
01509 }else{
01510 pub_republish.publish(msg_color, camera_info);
01511 }
01512
01513 }
01514 }
01515
01516
01517
01518
01519
01520
01521 }
01522 }
01523
01524
01525
01526 readyToPublish = false;
01527
01528 }
01529
01530 void streamerNode::writeData() {
01531
01532 if (configData.wantsToWrite) {
01533
01534
01535
01536 if ((frameCounter-1) != lastWritten) {
01537
01538
01539
01540 char *outputFilename;
01541 outputFilename = (char*) malloc(256);
01542
01543 if (configData.loadMode && configData.wantsToKeepNames) {
01544
01545 size_t findDot = inputList.at(frameCounter-1).rfind(".");
01546
01547 string partialName;
01548 partialName = inputList.at(frameCounter-1).substr(0, findDot);
01549
01550 sprintf(outputFilename, "%s/%s.%s", configData.outputFolder.c_str(), partialName.c_str(), configData.outputFormatString.c_str());
01551
01552 } else {
01553 sprintf(outputFilename, "%s/frame%06d.%s", configData.outputFolder.c_str(), frameCounter-1, configData.outputFormatString.c_str());
01554 }
01555
01556 if (configData.verboseMode) { ROS_INFO("Output name = (%s), outputType = (%s)", outputFilename, configData.outputType.c_str()); }
01557
01558 if (configData.outputType == "CV_16UC1") {
01559 if (scaled16Mat.rows > 0) {
01560
01561 if (configData.outputFormatString == "png") {
01562 imwrite(outputFilename, _16bitMat_pub, configData.outputFileParams);
01563 } else if ((configData.outputFormatString == "pgm") || (configData.outputFormatString == "ppm")) {
01564 imwrite(outputFilename, _16bitMat_pub);
01565 }
01566 }
01567 } else if (configData.outputType == "CV_8UC3") {
01568 if (colourMat.rows > 0) {
01569
01570
01571
01572 if ((configData.outputFormatString == "png") || (configData.outputFormatString == "jpg")) {
01573 imwrite(outputFilename, colourMat_pub, configData.outputFileParams);
01574 } else if ((configData.outputFormatString == "bmp") || (configData.outputFormatString == "ppm")) {
01575 imwrite(outputFilename, colourMat_pub);
01576 }
01577 }
01578 } else if (configData.outputType == "CV_8UC1") {
01579 if (_8bitMat.rows > 0) {
01580 if ((configData.outputFormatString == "png") || (configData.outputFormatString == "jpg")) {
01581 imwrite(outputFilename, _8bitMat_pub, configData.outputFileParams);
01582 } else if ((configData.outputFormatString == "bmp") || (configData.outputFormatString == "pgm") || (configData.outputFormatString == "ppm")) {
01583 imwrite(outputFilename, _8bitMat_pub);
01584 }
01585 }
01586 }
01587 lastWritten = frameCounter - 1;
01588 }
01589 }
01590
01591 if (configData.wantsToEncode) {
01592 if (!videoInitialized) {
01593 if (configData.videoType == "CV_16UC1") {
01594
01595 vid_writer.open(configData.outputVideo, CV_FOURCC('P','I','M','1'), ((int) configData.framerate), scaled16Mat.size(), true);
01596 } else if (configData.videoType == "CV_8UC3") {
01597 vid_writer.open(configData.outputVideo, CV_FOURCC('P','I','M','1'), ((int) configData.framerate), colourMat.size());
01598 } else if (configData.videoType == "CV_8UC1") {
01599 vid_writer.open(configData.outputVideo, CV_FOURCC('X', 'V', 'I', 'D'), ((int) configData.framerate), _8bitMat.size(), false);
01600 }
01601
01602 videoInitialized = true;
01603 }
01604
01605 if (configData.videoType == "CV_16UC1") {
01606 vid_writer << scaled16Mat;
01607 } else if (configData.videoType == "CV_8UC3") {
01608 vid_writer << colourMat;
01609 } else if (configData.videoType == "CV_8UC1") {
01610 vid_writer << _8bitMat;
01611 }
01612
01613 }
01614 }
01615
01616 bool streamerNode::performNuc() {
01617
01618 if (configData.verboseMode) { ROS_INFO("Sending NUC command..."); }
01619
01620 char localCommand[256];
01621 sprintf(localCommand, "nuc");
01622 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01623
01624 return true;
01625 }
01626
01627 void streamerNode::serialCallback(const ros::TimerEvent&) {
01628
01629 if (!configData.serialComms) {
01630 return;
01631 }
01632
01633 if (configData.serialPollingRate == 0.0) {
01634 if (configData.verboseMode) { ROS_INFO("Skipping serial callback because desired frequency is zero (0)."); }
01635 return;
01636 } else {
01637
01638
01639
01640
01641
01642
01643 if (configData.readThermistor) {
01644
01645 newThermistorReading = getThermistorReading();
01646
01647
01648 if ((newThermistorReading < MAX_VALID_THERMISTOR) && (newThermistorReading > MIN_VALID_THERMISTOR)) {
01649
01650
01651
01652 if ((lastThermistorReading == -99.0) || ( (lastThermistorReading != -99.0) && (abs(lastThermistorReading - newThermistorReading) < configData.maxThermistorDiff) ) ) {
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662 if (newThermistorReading == 0.0) {
01663
01664 }
01665
01666
01667 thermistorBuffer[recordedThermistorReadings % MAX_THERMISTOR_READINGS_TO_STORE][0] = ros::Time::now().toSec();
01668 thermistorBuffer[recordedThermistorReadings % MAX_THERMISTOR_READINGS_TO_STORE][1] = newThermistorReading;
01669 recordedThermistorReadings++;
01670
01671
01672
01673 if (configData.smoothThermistor) {
01674 double smoothReading = smoothThermistorReading();
01675
01676 if ((smoothReading < MAX_VALID_THERMISTOR) && (smoothReading > MIN_VALID_THERMISTOR)) {
01677
01678
01679
01680 if ((abs(smoothReading - newThermistorReading) < configData.maxThermistorDiff)) {
01681 newThermistorReading = smoothReading;
01682
01683
01684
01685 } else {
01686
01687 }
01688
01689 } else {
01690
01691 }
01692
01693
01694 }
01695
01696
01697
01698
01699 lastThermistorReading = newThermistorReading;
01700
01701
01702
01703 }
01704
01705
01706
01707 }
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730 }
01731
01732 if (configData.calibrationMode > 0) {
01733 if (alternateCounter >= configData.alternatePeriod) {
01734
01735 char localCommand[256];
01736
01737 if (configData.calibrationMode == CALIBMODE_ALT_OUTPUT) {
01738 if (altStatus) {
01739 sprintf(localCommand, "vidout raw");
01740 } else {
01741 sprintf(localCommand, "vidout ins");
01742 }
01743 altStatus = !altStatus;
01744 } else if (configData.calibrationMode == CALIBMODE_ALT_SHUTTER) {
01745 if (performingNuc) {
01746
01747 if (configData.verboseMode) { ROS_INFO("About to switch shutter"); }
01748
01749 if (altStatus) {
01750 sprintf(localCommand, "close");
01751 } else {
01752 sprintf(localCommand, "open");
01753 }
01754 altStatus = !altStatus;
01755
01756 } else {
01757 if (configData.verboseMode) { ROS_INFO("About to perform a NUC"); }
01758 sprintf(localCommand, "nuc");
01759 }
01760
01761 performingNuc = !performingNuc;
01762 } else if (configData.calibrationMode == CALIBMODE_LONG_SHUTTER) {
01763
01764 if (configData.verboseMode) { ROS_INFO("About to switch shutter"); }
01765
01766 if (altStatus) {
01767 sprintf(localCommand, "close");
01768 } else {
01769 sprintf(localCommand, "open");
01770 }
01771
01772 altStatus = !altStatus;
01773 }
01774
01775 if (configData.verboseMode) { ROS_INFO("Sending SPECIAL command: (%s)", localCommand); }
01776 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01777
01778 alternateCounter = 0;
01779 }
01780 alternateCounter++;
01781 }
01782
01783 }
01784
01785 bool wantsToPerformNuc = false;
01786
01787 if (currentNucProtectionMode && currentDesiredNucProtectionMode && (abs(ros::Time::now().toSec() - lastFlagReceived.toSec()) > MAX_TIME_WITHOUT_FLAGS) ) {
01788
01789 if (configData.verboseMode) { ROS_INFO("Timer exceeded for disabled NUC mode, preparing to restore NUC settings..."); }
01790
01791 currentDesiredNucProtectionMode = false;
01792 updateNucInterval = true;
01793 wantsToPerformNuc = true;
01794
01795 }
01796
01797 if (currentNucProtectionMode && !currentDesiredNucProtectionMode) {
01798
01799 if (abs(ros::Time::now().toSec() - lastNucPerformed_at_the_earliest.toSec()) > MAX_TIME_WITHOUT_NUC_conservative) {
01800 wantsToPerformNuc = true;
01801 }
01802
01803 }
01804
01805 if (wantsToPerformNuc) {
01806 lastNucPerformed_at_the_earliest = ros::Time::now();
01807 performNuc();
01808
01809 }
01810
01811 if (updateDetectorMode) {
01812
01813 string detectorCode;
01814
01815 if (configData.detectorMode == DETECTOR_MODE_RAW) {
01816 detectorCode = "raw";
01817 } else if (configData.detectorMode == DETECTOR_MODE_LUM) {
01818 detectorCode = "lum";
01819 } else if (configData.detectorMode == DETECTOR_MODE_INS) {
01820 detectorCode = "ins";
01821 } else if (configData.detectorMode == DETECTOR_MODE_RAD) {
01822 detectorCode = "rad";
01823 } else if (configData.detectorMode == DETECTOR_MODE_TMP) {
01824 detectorCode = "t";
01825 }
01826
01827 if (configData.verboseMode) { ROS_INFO("Changing detector output..."); }
01828 char localCommand[256];
01829 sprintf(localCommand, "vidout %s", detectorCode.substr(0,3).c_str());
01830 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01831
01832 char buff[SERIAL_BUFF_SIZE];
01833 int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
01834
01835
01836
01837 updateDetectorMode = false;
01838 }
01839
01840 if (updateUSBMode) {
01841
01842 string usbCode;
01843
01844
01845
01846 if (configData.usbMode == USB_MODE_16) {
01847 usbCode = "1";
01848 } else if (configData.usbMode == USB_MODE_8) {
01849 usbCode = "2";
01850 }
01851
01852
01853 if (configData.verboseMode) { ROS_INFO("Changing usb output with command..."); }
01854 char localCommand[256];
01855 sprintf(localCommand, "usb %s", usbCode.substr(0,usbCode.size()).c_str());
01856 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01857
01858 char buff[SERIAL_BUFF_SIZE];
01859 int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
01860
01861
01862
01863 updateUSBMode = false;
01864 }
01865
01866 if (updateNucInterval) {
01867
01868
01869
01870
01871
01872 double valid_thermLimit;
01873 int maxInterval;
01874
01875 if (configData.verboseMode) { ROS_INFO("Currently in protection mode (%d), want to be in mode (%d)", currentNucProtectionMode, currentDesiredNucProtectionMode); }
01876
01877 if (currentDesiredNucProtectionMode && !currentNucProtectionMode) {
01878 valid_thermLimit = 0.0;
01879 maxInterval = 0;
01880 if (configData.verboseMode) { ROS_WARN("Disabling NUC settings..."); }
01881
01882 } else if (currentDesiredNucProtectionMode && currentNucProtectionMode) {
01883 ROS_ERROR("Shouldn't be in here! (%d, %d)", currentNucProtectionMode, currentDesiredNucProtectionMode);
01884 } else {
01885 valid_thermLimit = float(int(round(100*configData.maxNucThreshold)))/100.0;
01886 maxInterval = configData.maxNucInterval;
01887 if (configData.verboseMode) { ROS_INFO("Updating NUC settings... (%d, %f)", maxInterval, valid_thermLimit); }
01888 settingsDisabled = false;
01889 }
01890
01891 if (configData.verboseMode) { ROS_INFO("Sending NUCSET command..."); }
01892 char localCommand[256];
01893 sprintf(localCommand, "nucset %d %d %d %.2f", maxInterval, 0, 0, valid_thermLimit);
01894 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01895
01896 char buff[SERIAL_BUFF_SIZE];
01897 int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908 currentNucProtectionMode = currentDesiredNucProtectionMode;
01909
01910 updateNucInterval = false;
01911
01912 }
01913
01914 }
01915
01916 bool streamerNode::sendSerialCommand(char *command, int max_attempts) {
01917
01918 int bytesToWrite = 0;
01919
01920
01921
01922 while (command[bytesToWrite] != '\0') {
01923
01924 bytesToWrite++;
01925 }
01926 bytesToWrite++;
01927
01928 char *ext_command;
01929 ext_command = new char[bytesToWrite+1];
01930
01931 for (int iii = 0; iii < bytesToWrite-1; iii++) {
01932 ext_command[iii] = command[iii];
01933 }
01934
01935 ext_command[bytesToWrite-1] = '\r';
01936 ext_command[bytesToWrite] = '\0';
01937
01938
01939
01940 int attempts = 0, n = 0;
01941 while ((max_attempts == 0) || (attempts < max_attempts)) {
01942
01943 n = write(mainfd, ext_command, bytesToWrite);
01944
01945 if (n == bytesToWrite) {
01946 if (configData.serialFeedback) { ROS_INFO("Serial write of (%s) was successful.", command); }
01947 return true;
01948 }
01949 attempts++;
01950 }
01951
01952 if ((n < 0) && (errno == EINTR)) {
01953 ROS_WARN("write() failed 1");
01954 } else if ( n < 0 ) {
01955 ROS_WARN("write() failed 2");
01956 } else {
01957 ROS_WARN("write() failed 3");
01958 }
01959
01960 return false;
01961 }
01962
01963 void streamerNode::timerCallback(const ros::TimerEvent&) {
01964
01965 if (configData.pauseMode) {
01966 return;
01967 }
01968
01969 if (configData.captureMode || configData.subscribeMode) {
01970 return;
01971 }
01972
01973 if (configData.pollMode || configData.resampleMode) {
01974
01975 if (configData.pollMode) {
01976
01977
01978
01979 streamCallback();
01980
01981
01982 }
01983
01984 if (processImage()) {
01985
01986
01987
01988 if (readyToPublish) {
01989 if (configData.resampleMode) {
01990
01991 }
01992 publishTopics();
01993
01994
01995
01996 writeData();
01997
01998
01999
02000 }
02001
02002 }
02003
02004
02005
02006
02007 return;
02008 }
02009
02010 if (configData.loadMode) {
02011
02012 string filename;
02013
02014 if (configData.folder.at(configData.folder.length()-1) == '/') {
02015 filename = configData.folder + inputList.at(frameCounter);
02016 } else {
02017 filename = configData.folder + "/" + inputList.at(frameCounter);
02018 }
02019
02020 frame = cv::imread(filename, -1);
02021
02022
02023
02024 if (processImage()) {
02025
02026 if (readyToPublish) {
02027
02028 updateCameraInfo();
02029 publishTopics();
02030 writeData();
02031 }
02032
02033 }
02034
02035 if (frameCounter >= fileCount) {
02036 if (configData.verboseMode) { ROS_INFO("setValidity(false) : (frameCounter >= fileCount)"); }
02037 setValidity(false);
02038 }
02039
02040 return;
02041 }
02042
02043 bool validFrameRead = true;
02044
02045
02046 if (configData.inputDatatype == DATATYPE_RAW) {
02047
02048 do {
02049
02050 if (av_read_frame(mainVideoSource->pIFormatCtx, &(mainVideoSource->packet)) != 0) {
02051 ROS_WARN("Frame invalid...");
02052 validFrameRead = false;
02053 break;
02054 }
02055
02056 } while (mainVideoSource->packet.stream_index != mainVideoSource->videoStream);
02057
02058
02059 if (validFrameRead) {
02060
02061
02062 avcodec_decode_video2(mainVideoSource->pCodecCtx, mainVideoSource->pFrame, &(mainVideoSource->frameFinished), &(mainVideoSource->packet));
02063
02064 acceptImage((void*) *(mainVideoSource->pFrame->data));
02065
02066 if (processImage()) {
02067 if (readyToPublish) {
02068 updateCameraInfo();
02069 publishTopics();
02070 writeData();
02071 }
02072 }
02073
02074
02075
02076 av_free_packet(&(mainVideoSource->packet));
02077
02078 } else {
02079 if (configData.verboseMode) { ROS_INFO("setValidity(false) : (validFrameRead)"); }
02080 setValidity(false);
02081 }
02082
02083 } else if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
02084
02085 if (configData.verboseMode) { ROS_INFO("About to read in frame..."); }
02086
02087 if(!cap.isOpened()) {
02088 ROS_ERROR("Actually, device isn't open...");
02089 return;
02090 } else {
02091 if (configData.verboseMode) { ROS_INFO("Device is open..."); }
02092 }
02093
02094 if (configData.verboseMode) { ROS_INFO("framecount = (%f)", cap.get(CV_CAP_PROP_FRAME_COUNT)); }
02095
02096 if (configData.verboseMode) { ROS_INFO("dim = (%f, %f)", cap.get(CV_CAP_PROP_FRAME_WIDTH), cap.get(CV_CAP_PROP_FRAME_HEIGHT)); }
02097
02098 cap >> frame;
02099
02100
02101
02102 if (configData.verboseMode) { ROS_INFO("Frame read"); }
02103
02104
02105
02106
02107 if (&frame == NULL) {
02108 if (configData.verboseMode) { ROS_INFO("setValidity(false) : (&frame == NULL)"); }
02109 setValidity(false);
02110
02111 } else {
02112 if (processImage()) {
02113 if (readyToPublish) {
02114 updateCameraInfo();
02115 publishTopics();
02116 writeData();
02117 }
02118 }
02119
02120
02121 }
02122
02123 }
02124 }
02125
02126 void streamerNode::assignDefaultCameraInfo() {
02127
02128 globalCameraInfo.imageSize = cv::Mat(1, 2, CV_16UC1);
02129 globalCameraInfo.imageSize.at<unsigned short>(0, 1) = DEFAULT_IMAGE_HEIGHT;
02130 globalCameraInfo.imageSize.at<unsigned short>(0, 0) = DEFAULT_IMAGE_WIDTH;
02131
02132 globalCameraInfo.cameraMatrix = cv::Mat::eye(3, 3, CV_64FC1);
02133 globalCameraInfo.distCoeffs = cv::Mat::zeros(1, 8, CV_64FC1);
02134 globalCameraInfo.newCamMat = cv::Mat::eye(3, 3, CV_64FC1);
02135 globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
02136
02137 }
02138
02139 void streamerNode::overwriteCameraDims() {
02140
02141 camera_info.height = globalCameraInfo.imageSize.at<unsigned short>(0, 1);
02142 camera_info.width = globalCameraInfo.imageSize.at<unsigned short>(0, 0);
02143
02144 }
02145
02146 streamerNode::streamerNode(ros::NodeHandle& nh, streamerData startupData) {
02147
02148 configData = startupData;
02149
02150 if (configData.wantsToAddExtrinsics) {
02151 getRectification();
02152 updateCameraInfoExtrinsics();
02153 }
02154
02155 sprintf(nodeName, "%s", ros::this_node::getName().substr(1).c_str());
02156
02157 if (configData.verboseMode) { ROS_INFO("Initializing node (%s)", nodeName); }
02158
02159 canRadiometricallyCorrect = false;
02160
02161 deviceCreated = false;
02162
02163 recordedThermistorReadings = 0;
02164
02165 settingsDisabled = false;
02166
02167 currentNucProtectionMode = false;
02168 wantsToDisableNuc = false;
02169
02170 lastIsDuplicate = true;
02171 firstCall = true;
02172 updateNucInterval = true;
02173 updateDetectorMode = true;
02174 updateUSBMode = true;
02175 altStatus = true;
02176 performingNuc = false;
02177 alphaChanged = true;
02178 readyToPublish = false;
02179 isActuallyGray = false;
02180 videoInitialized = false;
02181 setValidity(true);
02182 firstFrame = true;
02183 centerPrincipalPoint = true;
02184 firstServerCallbackProcessed = false;
02185 pastMeanIndex = -1;
02186 medianPercentile = 0.50;
02187 alternateCounter = 0;
02188 dodgeTime.sec = 0;
02189 dodgeTime.nsec = 0;
02190 fusionFactor = 0.8;
02191 fileCount = 0;
02192 writeIndex = 0;
02193 frameCounter = 0;
02194 lastWritten = -1;
02195 lastThermistorReading = -99.0;
02196 lastMedian = -1.0;
02197 lastLowerLimit = -1.0;
02198 lastUpperLimit = -1.0;
02199 oldMaxDiff = -1.0;
02200 minVal = 65535.0;
02201 maxVal = 0.0;
02202
02203
02204 if (configData.radiometryFile != "radiometryFile") {
02205
02206
02207 cv::Mat sensorLimits, graylevelLimits, mappingMatrix;
02208
02209 if (configData.verboseMode) { ROS_INFO("About to read from (%s)", configData.radiometryFile.c_str()); }
02210
02211 cv::FileStorage fs(configData.radiometryFile, cv::FileStorage::READ);
02212 fs["sensorLimits"] >> sensorLimits;
02213 fs["graylevelLimits"] >> graylevelLimits;
02214 fs["mappingMatrix"] >> mappingMatrix;
02215 fs.release();
02216
02217 if ((sensorLimits.rows == 0) || (graylevelLimits.rows == 0) || (mappingMatrix.rows == 0)) {
02218 ROS_ERROR("Provided radiometry file is invalid. Please check.");
02219 wantsToShutdown = true;
02220 prepareForTermination();
02221 return;
02222 }
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249 radMapper.update(mappingMatrix, sensorLimits.at<double>(0,0), sensorLimits.at<double>(0,1), graylevelLimits.at<double>(0,0), graylevelLimits.at<double>(0,1));
02250
02251 canRadiometricallyCorrect = true;
02252
02253
02254
02255
02256
02257
02258 }
02259
02260 if (configData.serialComms) {
02261 if (configData.verboseMode) { ROS_INFO("Configuring serial comms..."); }
02262 if (!configureSerialComms()) {
02263 ROS_ERROR("Serial comms configuration failed. Shutting down.");
02264 wantsToShutdown = true;
02265 prepareForTermination();
02266 return;
02267 }
02268 }
02269
02270 if (configData.verboseMode) { ROS_INFO("configData.serialPollingRate = (%f)", configData.serialPollingRate); }
02271
02272 if (configData.serialPollingRate > 0.1) {
02273 if (configData.verboseMode) { ROS_INFO("Initializing serial timer at (%f)", 1.0 / ((double) configData.serialPollingRate)); }
02274 serial_timer = nh.createTimer(ros::Duration(1.0 / ((double) configData.serialPollingRate)), &streamerNode::serialCallback, this);
02275 } else {
02276 if (configData.verboseMode) { ROS_INFO("Initializing serial timer at (%f)", DEFAULT_SERIAL_POLLING_RATE); }
02277 serial_timer = nh.createTimer(ros::Duration(DEFAULT_SERIAL_POLLING_RATE), &streamerNode::serialCallback, this);
02278 }
02279
02280 it = new image_transport::ImageTransport(nh);
02281
02282 string info_name = configData.topicname.substr(0, configData.topicname.find_last_of("/") + 1) + "camera_info";
02283 if (configData.verboseMode) { ROS_INFO("configData.topicname = (%s)", info_name.c_str()); }
02284
02285 if (configData.calibrationMode) {
02286 ros::Duration(1.0).sleep();
02287 }
02288
02289 if (configData.verboseMode) { ROS_INFO("Initializing camera (%s)", configData.topicname.c_str()); }
02290
02291 mainVideoSource = new streamerSource;
02292
02293 std::string camera_name;
02294
02295 if (configData.outputFolder.size() == 0) {
02296 configData.outputFolder = configData.read_addr + configData.outputFolder;
02297 } else if (configData.outputFolder[0] != '/') {
02298 configData.outputFolder = configData.read_addr + configData.outputFolder;
02299 }
02300
02301 configData.outputTimeFile = configData.outputFolder + "-timestamps.txt";
02302
02303 if (configData.wantsToDumpTimestamps) {
02304 ofs.open(configData.outputTimeFile.c_str());
02305 }
02306
02307 if (configData.intrinsicsProvided) {
02308
02309 if (configData.verboseMode) { ROS_INFO("Reading in calibration data"); }
02310
02311 if (configData.intrinsics[0] != '/') {
02312 configData.intrinsics = configData.read_addr + configData.intrinsics;
02313 }
02314
02315 if (configData.verboseMode) { ROS_INFO("intrinsics = %s", configData.intrinsics.c_str()); }
02316
02317
02318 cv::Mat dummyImage(300, 300, CV_8UC1);
02319 GaussianBlur(dummyImage, dummyImage, cv::Size(5, 5), 1.5);
02320
02321
02322 cv::FileStorage fs(configData.intrinsics, cv::FileStorage::READ);
02323 fs["imageSize"] >> globalCameraInfo.imageSize;
02324 fs["cameraMatrix"] >> globalCameraInfo.cameraMatrix;
02325 fs["distCoeffs"] >> globalCameraInfo.distCoeffs;
02326 fs["newCamMat"] >> globalCameraInfo.newCamMat;
02327 fs.release();
02328
02329 if (configData.verboseMode) { ROS_INFO("Calibration data read."); }
02330
02331
02332 if (globalCameraInfo.cameraMatrix.empty()){
02333 ROS_ERROR("Intrinsics file %s invalid! Please check path and filecontent...\n", configData.intrinsics.c_str());
02334 }
02335
02336 if (configData.verboseMode) { ROS_INFO("Establishing size (%d, %d).", globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1)); }
02337
02338 globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
02339
02340
02341
02342
02343 if (configData.verboseMode) { ROS_INFO("Global params determined."); }
02344
02345
02346 } else if (configData.imageDimensionsSpecified) {
02347
02348 if (configData.verboseMode) { ROS_INFO("Assigning default intrinsics but with specified image size"); }
02349
02350 assignDefaultCameraInfo();
02351
02352 globalCameraInfo.imageSize.at<unsigned short>(0, 1) = configData.inputHeight;
02353 globalCameraInfo.imageSize.at<unsigned short>(0, 0) = configData.inputWidth;
02354 globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
02355
02356
02357
02358 } else {
02359 if (configData.verboseMode) { ROS_INFO("Assigning default intrinsics..."); }
02360
02361 assignDefaultCameraInfo();
02362
02363 if (configData.verboseMode) { ROS_INFO("Default intrinsics assigned."); }
02364 }
02365
02366
02367
02368 if (configData.autoAlpha) {
02369
02370 if (configData.intrinsicsProvided) {
02371 if (configData.verboseMode) { ROS_INFO("Finding auto alpha..."); }
02372 configData.alpha = findBestAlpha(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.cameraSize);
02373
02374 if (configData.verboseMode) { ROS_INFO("Optimal alpha: (%f)", configData.alpha); }
02375 } else {
02376 ROS_WARN("Cannot estimate an appropriate alpha coefficient because no intrinsics were provided.");
02377 }
02378
02379 }
02380
02381
02382 if (configData.wantsToAddExtrinsics) {
02383 if (configData.verboseMode) { ROS_INFO("Reading in extrinsics..."); }
02384
02385 char rotation_name[256], translation_name[256];
02386
02387 sprintf(rotation_name, "R_%d", configData.camera_number);
02388 sprintf(translation_name, "T%d", configData.camera_number);
02389
02390
02391 cv::Mat dummyImage(300, 300, CV_8UC1);
02392 GaussianBlur(dummyImage, dummyImage, cv::Size(5, 5), 1.5);
02393
02394 cv::FileStorage fs(configData.extrinsics, cv::FileStorage::READ);
02395
02396
02397 fs[rotation_name] >> globalCameraInfo.R;
02398 fs[translation_name] >> globalCameraInfo.T;
02399
02400
02401 fs["R"] >> globalExtrinsicsData.R;
02402 fs["T"] >> globalExtrinsicsData.T;
02403
02404
02405 fs["cameraMatrix0"] >> globalExtrinsicsData.cameraMatrix0;
02406 fs["cameraMatrix1"] >> globalExtrinsicsData.cameraMatrix1;
02407 fs["distCoeffs0"] >> globalExtrinsicsData.distCoeffs0;
02408 fs["distCoeffs1"] >> globalExtrinsicsData.distCoeffs1;
02409
02410 fs.release();
02411
02412 if (globalExtrinsicsData.R.empty()){
02413 ROS_ERROR("Extrinsics file %s invalid! Please check path and filecontent...\n", configData.extrinsics.c_str());
02414 }
02415
02416 globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
02417
02418 getRectification();
02419
02420 } else {
02421
02422 globalCameraInfo.R = cv::Mat::eye(3, 3, CV_64FC1);
02423 globalCameraInfo.T = cv::Mat::zeros(3, 1, CV_64FC1);
02424 }
02425
02426 if (configData.verboseMode) { ROS_INFO("calling assignCameraInfo() from streamerNode()..."); }
02427 assignCameraInfo();
02428
02429 if (configData.verboseMode) { ROS_INFO("Initializing video source..."); }
02430 mainVideoSource->initialize_video_source();
02431
02432 colourMap.load_standard(configData.mapCode, configData.mapParam);
02433
02434 refreshCameraAdvertisements();
02435
02436 char cameraInfoName[256];
02437 sprintf(cameraInfoName, "thermalvis/%s/set_camera_info", nodeName);
02438 ros::ServiceServer set_camera_info = nh.advertiseService(cameraInfoName, &streamerNode::setCameraInfo, this);
02439
02440
02441 if (configData.framerate > 0.0) {
02442 configData.pauseMode = false;
02443 timer = nh.createTimer(ros::Duration(1.0 / ((double) configData.framerate)), &streamerNode::timerCallback, this);
02444 } else {
02445 configData.pauseMode = true;
02446 timer = nh.createTimer(ros::Duration(1.0 / 1.0), &streamerNode::timerCallback, this);
02447 }
02448
02449
02450 callLogFile = configData.read_addr + "/nodes/streamer/log/call_log.txt";
02451 retrieveLogFile = configData.read_addr + "/nodes/streamer/log/retrieve_log.txt";
02452 internalLogFile = configData.read_addr + "/nodes/streamer/log/internal_log.txt";
02453 writeLogFile = configData.read_addr + "/nodes/streamer/log/write_log.txt";
02454 duplicatesLogFile = configData.outputFolder + "-duplicates.txt";
02455 thermistorLogFile = configData.outputFolder + "-thermistor.txt";
02456
02457
02458
02459
02460
02461
02462 if (configData.verboseMode) { ROS_INFO("Establishing server callback..."); }
02463 f = boost::bind (&streamerNode::serverCallback, this, _1, _2);
02464 server.setCallback (f);
02465
02466 if (configData.subscribeMode || configData.resampleMode) {
02467 if (configData.verboseMode) { ROS_INFO("syncMode: (%d)", configData.syncMode); }
02468 if (configData.syncMode == SYNCMODE_HARD) {
02469 camera_sub = it->subscribeCamera(configData.topicname, 1, &streamerNode::handle_camera, this);
02470 } else if (configData.syncMode == SYNCMODE_SOFT) {
02471 info_sub = nh.subscribe<sensor_msgs::CameraInfo>(info_name, 1, &streamerNode::handle_info, this);
02472 image_sub = it->subscribe(configData.topicname, 1, &streamerNode::handle_image, this);
02473 } else if (configData.syncMode == SYNCMODE_IMAGEONLY) {
02474 image_sub = it->subscribe(configData.topicname, 1, &streamerNode::handle_image, this);
02475 }
02476 }
02477
02478 if (configData.externalNucManagement != "") {
02479
02480 lastFlagReceived = ros::Time::now();
02481
02482 ROS_INFO("Subscribing to external nuc management flag (%s)", configData.externalNucManagement.c_str());
02483 nuc_management_sub = nh.subscribe<std_msgs::Float32>(configData.externalNucManagement, 1, &streamerNode::handle_nuc_instruction, this);
02484
02485 }
02486
02487
02488 while (!firstServerCallbackProcessed) { };
02489
02490 if (configData.wantsToDumpTimestamps) {
02491 ofs_call_log.open(callLogFile.c_str());
02492 ofs_retrieve_log.open(retrieveLogFile.c_str());
02493 ofs_internal_log.open(internalLogFile.c_str());
02494 ofs_write_log.open(writeLogFile.c_str());
02495 }
02496
02497 if (configData.wantsToOutputDuplicates) {
02498 if (configData.verboseMode) { ROS_INFO("Outputting duplicates to (%s)", duplicatesLogFile.c_str()); }
02499 ofs_duplicates_log.open(duplicatesLogFile.c_str());
02500 }
02501 }
02502
02503
02504 void streamerNode::getRectification(){
02505
02506 cv::Mat Q;
02507
02508 cv::stereoRectify(globalExtrinsicsData.cameraMatrix0, globalExtrinsicsData.distCoeffs0, globalExtrinsicsData.cameraMatrix1, globalExtrinsicsData.distCoeffs1,
02509 globalCameraInfo.cameraSize,
02510 globalExtrinsicsData.R, globalExtrinsicsData.T,
02511 globalExtrinsicsData.R0, globalExtrinsicsData.R1, globalExtrinsicsData.P0, globalExtrinsicsData.P1,
02512 Q,
02513 cv::CALIB_ZERO_DISPARITY, configData.alpha, globalCameraInfo.cameraSize, &globalExtrinsicsData.roi0, &globalExtrinsicsData.roi1);
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525 }
02526
02527 void streamerNode::handle_nuc_instruction(const std_msgs::Float32::ConstPtr& nuc_msg) {
02528
02529
02530 if (configData.verboseMode) { ROS_INFO("Handling NUC instruction: (%f)", nuc_msg->data); }
02531
02532 lastFlagReceived = ros::Time::now();
02533
02534 currentDesiredNucProtectionMode = (nuc_msg->data < 0.5);
02535
02536 if (currentDesiredNucProtectionMode != currentNucProtectionMode) {
02537 updateNucInterval = true;
02538 }
02539
02540
02541 }
02542
02543 void streamerNode::handle_info(const sensor_msgs::CameraInfoConstPtr& info_msg) {
02544
02545
02546
02547 if (configData.syncMode != SYNCMODE_SOFT) {
02548 return;
02549 }
02550
02551
02552 if ((!configData.subscribeMode) && (!configData.resampleMode)) {
02553 return;
02554 }
02555
02556 if (configData.verboseMode) { ROS_INFO("Copying camera info over..."); }
02557
02558
02559 original_camera_info = *info_msg;
02560
02561
02562
02563 info_time = ros::Time::now();
02564 original_time = info_msg->header.stamp;
02565 originalInternalTime = info_msg->R[0];
02566
02567 original_bx = info_msg->binning_x;
02568 original_by = info_msg->binning_y;
02569
02570
02571
02572 if (std::abs(image_time.toNSec() - info_time.toNSec()) < configData.soft_diff_limit) {
02573
02574 image_time = dodgeTime;
02575
02576 act_on_image();
02577 }
02578
02579
02580 }
02581
02582 void streamerNode::refreshCameraAdvertisements() {
02583
02584
02585 char colorPubName[256], _16bitPubName[256], _8bitPubName[256];
02586
02587 sprintf(colorPubName, "thermalvis/%s/image_col", nodeName);
02588 sprintf(_16bitPubName, "thermalvis/%s/image_raw", nodeName);
02589 sprintf(_8bitPubName, "thermalvis/%s/image_mono", nodeName);
02590
02591 bool cameraAdvertised = false;
02592
02593
02594
02595
02596 pub_color.shutdown();
02597 pub_color_im.shutdown();
02598 pub_16bit.shutdown();
02599 pub_16bit_im.shutdown();
02600 pub_8bit.shutdown();
02601 pub_8bit_im.shutdown();
02602
02603
02604 pub_republish.shutdown();
02605 pub_republish_im.shutdown();
02606
02607 char _republishPubName[256];
02608 sprintf(_republishPubName, "%s", configData.republishTopic.c_str());
02609
02610
02611
02612 if (configData.output16bitFlag) {
02613
02614
02615 if (configData.republishSource==REPUBLISH_CODE_16BIT){
02616 pub_republish = it->advertiseCamera(_republishPubName, 1);
02617 }
02618
02619 if (!cameraAdvertised) {
02620 pub_16bit = it->advertiseCamera(_16bitPubName, 1);
02621
02622 cameraAdvertised = true;
02623 } else {
02624 pub_16bit_im = it->advertise(_16bitPubName, 1);
02625
02626 }
02627
02628 }
02629
02630 if (configData.output8bitFlag) {
02631
02632
02633 if (configData.republishSource==REPUBLISH_CODE_8BIT_MONO){
02634 pub_republish = it->advertiseCamera(_republishPubName, 1);
02635 }
02636
02637 if (!cameraAdvertised) {
02638 pub_8bit = it->advertiseCamera(_8bitPubName, 1);
02639
02640 cameraAdvertised = true;
02641 } else {
02642 pub_8bit_im = it->advertise(_8bitPubName, 1);
02643
02644 }
02645
02646 }
02647
02648
02649 if (configData.outputColorFlag) {
02650
02651 if (configData.republishSource==REPUBLISH_CODE_8BIT_COL){
02652 pub_republish = it->advertiseCamera(_republishPubName, 1);
02653 }
02654 if (!cameraAdvertised) {
02655 pub_color = it->advertiseCamera(colorPubName, 1);
02656
02657 cameraAdvertised = true;
02658 } else {
02659 pub_color_im = it->advertise(colorPubName, 1);
02660
02661 }
02662 }
02663
02664 }
02665
02666
02667 void streamerNode::handle_camera(const sensor_msgs::ImageConstPtr& msg_ptr, const sensor_msgs::CameraInfoConstPtr& info_msg) {
02668
02669
02670
02671 if (configData.syncMode != SYNCMODE_HARD) {
02672 return;
02673 }
02674
02675 if ((!configData.subscribeMode) && (!configData.resampleMode)) {
02676 return;
02677 }
02678
02679
02680
02681
02682
02683
02684
02685
02686 if (configData.verboseMode) { ROS_INFO("Copying camera info over..."); }
02687
02688 original_camera_info = *info_msg;
02689
02690 if (configData.verboseMode) { ROS_INFO("original_camera_info.header.seq = (%d)", original_camera_info.header.seq); }
02691
02692 original_time = info_msg->header.stamp;
02693
02694
02695
02696 memcpy(&lastThermistorReading, &info_msg->binning_x, sizeof(float));
02697
02698
02699
02700
02701
02702
02703 if (configData.inputDatatype == DATATYPE_DEPTH) {
02704 cv_ptr = cv_bridge::toCvCopy(msg_ptr, "16UC1");
02705 } else {
02706 cv_ptr = cv_bridge::toCvCopy(msg_ptr, enc::BGR8);
02707 }
02708
02709
02710 act_on_image();
02711
02712 }
02713
02714 void streamerNode::act_on_image() {
02715
02716
02717
02718 updateCameraInfo();
02719
02720 newImage = cv::Mat(cv_ptr->image);
02721
02722 cv::Mat grayImage;
02723
02724 if (newImage.type() == CV_16UC3) {
02725 cv::cvtColor(newImage, frame, CV_RGB2GRAY);
02726 } else {
02727 frame = cv::Mat(newImage);
02728 }
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739 if (readyToPublish) {
02740
02741
02742 } else {
02743 readyToPublish = true;
02744 }
02745
02746
02747 if (!configData.resampleMode) {
02748
02749 if (processImage()) {
02750 if (readyToPublish) {
02751 updateCameraInfo();
02752 publishTopics();
02753 writeData();
02754 }
02755 }
02756
02757 }
02758
02759 return;
02760
02761 }
02762
02763 void streamerNode::handle_image(const sensor_msgs::ImageConstPtr& msg_ptr) {
02764
02765
02766
02767 if (configData.syncMode == SYNCMODE_HARD) {
02768 return;
02769 }
02770
02771 if ((!configData.subscribeMode) && (!configData.resampleMode)) {
02772 return;
02773 }
02774
02775
02776
02777 original_time = msg_ptr->header.stamp;
02778
02779
02780
02781 image_time = ros::Time::now();
02782 cv_ptr = cv_bridge::toCvCopy(msg_ptr, enc::BGR8);
02783
02784 if (configData.syncMode == SYNCMODE_SOFT) {
02785 if (std::abs(image_time.toNSec() - info_time.toNSec()) < configData.soft_diff_limit) {
02786
02787
02788 image_time = dodgeTime;
02789 act_on_image();
02790 }
02791 } else {
02792 act_on_image();
02793 }
02794
02795
02796
02797
02798
02799
02800
02801 }
02802
02803 streamerData::streamerData() {
02804
02805 intrinsicsProvided = false;
02806
02807
02808 wantsToAddExtrinsics = false;
02809 wantsToWrite = false;
02810 wantsToEncode = false;
02811 wantsToKeepNames = false;
02812 wantsToUndistort = false;
02813 wantsToResize = false;
02814 loopMode = false;
02815 imageDimensionsSpecified = false;
02816
02817
02818
02819 mapCode = CIECOMP;
02820 mapParam = 0;
02821
02822 framerate = -1.0;
02823
02824 soft_diff_limit = 5000000;
02825
02826 }
02827
02828 bool streamerData::obtainStartingData(ros::NodeHandle& nh) {
02829
02830 nh.param<std::string>("source", source, "dev");
02831
02832 nh.param<std::string>("file", filename, "file");
02833 nh.param<std::string>("dev", capture_device, "/dev/video0");
02834 device_num = atoi(&(capture_device.c_str(), capture_device.at(capture_device.length()-1)));
02835
02836 nh.param<std::string>("topic", topicname, "/thermalvis/streamer/image_raw");
02837 nh.param<std::string>("externalNucManagement", externalNucManagement, "");
02838
02839
02840 nh.param<bool>("serialFeedback", serialFeedback, false);
02841
02842 nh.param<double>("maxThermistorDiff", maxThermistorDiff, 0.5);
02843
02844 nh.param<int>("outputFormat", outputFormat, 4);
02845
02846 nh.param<int>("temporalMemory", temporalMemory, 5);
02847
02848 nh.param<int>("serialWriteAttempts", serialWriteAttempts, 1);
02849
02850
02851 nh.param<int>("alternatePeriod", alternatePeriod, 5);
02852
02853 if (outputFormat == 0) {
02854 outputFormatString = "jpg";
02855 } else if (outputFormat == 1) {
02856 outputFormatString = "pgm";
02857 } else if (outputFormat == 2) {
02858 outputFormatString = "bmp";
02859 } else if (outputFormat == 3) {
02860 outputFormatString = "ppm";
02861 } else if (outputFormat == 4) {
02862 outputFormatString = "png";
02863 }
02864
02865 nh.param<std::string>("outputType", outputType, "CV_8UC3");
02866
02867 if (outputType == "CV_8UC3") {
02868 if (outputFormatString == "pgm") {
02869 ROS_WARN("PGM cannot write as CV_8UC3...");
02870 }
02871 } else if (outputType == "CV_8UC1") {
02872
02873 } else if (outputType == "CV_16UC1") {
02874 if ((outputFormatString == "jpg") || (outputFormatString == "bmp")) {
02875 ROS_WARN("JPG/BMP cannot write as CV_16UC1...");
02876 }
02877 } else {
02878 ROS_WARN("Unrecognized output format (%s)", outputType.c_str());
02879 }
02880
02881 nh.param<double>("maxIntensityChange", maxIntensityChange, 2.0);
02882
02883
02884 nh.param<bool>("drawReticle", drawReticle, false);
02885 nh.param<bool>("displayThermistor", displayThermistor, false);
02886 nh.param<bool>("dumpDuplicates", wantsToOutputDuplicates, false);
02887 nh.param<bool>("fixDudPixels", fixDudPixels, true);
02888 nh.param<bool>("forceInputGray", forceInputGray, false);
02889 nh.param<bool>("stepChangeTempScale", stepChangeTempScale, false);
02890 nh.param<bool>("extremes", extremes, true);
02891 nh.param<bool>("temporalSmoothing", temporalSmoothing, false);
02892 nh.param<bool>("markDuplicates", wantsToMarkDuplicates, false);
02893 nh.param<bool>("smoothThermistor", smoothThermistor, false);
02894 nh.param<double>("thermistorWindow", thermistorWindow, 5.0);
02895
02896 nh.param<bool>("readThermistor", readThermistor, true);
02897
02898 nh.param<int>("maxReadAttempts", maxReadAttempts, 0);
02899
02900 nh.param<int>("filterMode", filterMode, 0);
02901 nh.param<double>("filterParam", filterParam, 2.0);
02902
02903
02904 nh.param<std::string>("radiometryFile", radiometryFile, "radiometryFile");
02905
02906 nh.param<double>("syncDiff", syncDiff, 0.005);
02907
02908 soft_diff_limit = (unsigned long) (syncDiff * 1000000000.0);
02909
02910 nh.param<std::string>("portAddress", portAddress, "/dev/ttyUSB0");
02911
02912 nh.param<bool>("autoAlpha", autoAlpha, true);
02913 nh.param<double>("alpha", alpha, 0.00);
02914
02915
02916 nh.param<int>("serialCommsConfigurationCode", serialCommsConfigurationCode, SERIAL_COMMS_CONFIG_DEFAULT);
02917
02918 nh.param<bool>("useCurrentRosTime", useCurrentRosTime, false);
02919
02920
02921
02922 nh.param<std::string>("intrinsics", intrinsics, "intrinsics");
02923
02924 nh.param<int>("inputWidth", inputWidth, 0);
02925 nh.param<int>("inputHeight", inputHeight, 0);
02926
02927
02928 nh.param<std::string>("extrinsics", extrinsics, "extrinsics");
02929
02930
02931
02932 nh.param<int>("camera_number", camera_number, 0);
02933 nh.param<double>("framerate", framerate, -1.0);
02934
02935 nh.param<double>("writeQuality", writeQuality, 1.0);
02936
02937 nh.param<bool>("output16bit", output16bitFlag, true);
02938 nh.param<bool>("output8bit", output8bitFlag, false);
02939 nh.param<bool>("outputColor", outputColorFlag, true);
02940
02941 nh.param<bool>("loopMode", loopMode, false);
02942
02943
02944 nh.param<bool>("disableSkimming", disableSkimming, true);
02945
02946 nh.param<bool>("writeImages", wantsToWrite, false);
02947 nh.param<std::string>("outputFolder", outputFolder, "outputFolder");
02948
02949 nh.param<bool>("serialComms", serialComms, false);
02950 nh.param<bool>("radiometricCorrection", radiometricCorrection, true);
02951 nh.param<bool>("alreadyCorrected", alreadyCorrected, false);
02952 nh.param<bool>("radiometricRaw", radiometricRaw, false);
02953 nh.param<bool>("radiometricInterpolation", radiometricInterpolation, true);
02954
02955 nh.param<int>("radiometricBias", radiometricBias, 0);
02956
02957 nh.param<int>("calibrationMode", calibrationMode, CALIBMODE_OFF);
02958
02959 ROS_INFO("calibrationMode = (%d)", calibrationMode);
02960
02961 if (outputFolder.size() > 0) {
02962 if (outputFolder.at(outputFolder.size()-1) == '/') {
02963 outputFolder = outputFolder.substr(0, outputFolder.size()-1);
02964 }
02965 } else {
02966 ROS_WARN("Specified output folder is 0 characters long - ignoring.");
02967 outputFolder = "outputFolder";
02968 }
02969
02970
02971 if ((wantsToWrite) && (outputFolder.size() > 0)) {
02972
02973 char folderCommand[256];
02974 sprintf(folderCommand, "mkdir -p %s", outputFolder.c_str());
02975
02976 int res = system(folderCommand);
02977
02978 if (res == 0) {
02979 ROS_WARN("system() call returned 0...");
02980 }
02981 }
02982
02983
02984 if (verboseMode) { ROS_INFO("outputFolder = (%s)", outputFolder.c_str()); }
02985
02986
02987
02988 nh.param<std::string>("outputType", outputType, "CV_16UC1");
02989
02990 outputFileParams.clear();
02991 int val;
02992 if (outputFormatString == "png") {
02993 outputFileParams.push_back(CV_IMWRITE_PNG_COMPRESSION);
02994 val = int((1.0-writeQuality) * 9.0);
02995 outputFileParams.push_back(val);
02996 } else if (outputFormatString == "jpg") {
02997 outputFileParams.push_back(CV_IMWRITE_JPEG_QUALITY);
02998 val = int(writeQuality * 100.0);
02999 outputFileParams.push_back(val);
03000 }
03001
03002 nh.param<bool>("keepOriginalNames", wantsToKeepNames, false);
03003 nh.param<bool>("loopMode", loopMode, false);
03004
03005 nh.param<bool>("writeVideo", wantsToEncode, false);
03006 nh.param<std::string>("outputVideo", outputVideo, "outputVideo");
03007 nh.param<std::string>("videoType", videoType, "videoType");
03008
03009 nh.param<bool>("undistortImages", wantsToUndistort, false);
03010
03011 nh.param<bool>("rectifyImages", wantsToRectify, false);
03012
03013 nh.param<bool>("removeDuplicates", wantsToRemoveDuplicates, false);
03014
03015 if (outputFolder != "outputFolder") {
03016 nh.param<bool>("dumpTimestamps", wantsToDumpTimestamps, false);
03017 } else {
03018 wantsToDumpTimestamps = false;
03019 }
03020
03021 nh.param<bool>("resizeMode", wantsToResize, false);
03022
03023 nh.param<int>("syncMode", syncMode, SYNCMODE_HARD);
03024
03025
03026
03027
03028
03029
03030
03031 nh.param<int>("rows", desiredRows, -1);
03032 nh.param<int>("cols", desiredCols, -1);
03033
03034 if (wantsToResize) {
03035 if ((desiredRows < 1) || (desiredRows > MAX_ROWS) || (desiredCols < 1) || (desiredCols > MAX_COLS)) {
03036 ROS_ERROR("Resizing values (%d, %d) invalid.",desiredCols, desiredRows);
03037 return false;
03038
03039 } else {
03040 ROS_INFO("Resizing to (%d x %d)", desiredCols, desiredRows);
03041 }
03042 }
03043
03044 if (wantsToUndistort) { ROS_INFO("Undistorting images..."); }
03045
03046 nh.param<int>("normMode", normMode, 0);
03047 nh.param<std::string>("normalizationMode", normalizationMode, "normalizationMode");
03048
03049 nh.param<double>("normFactor", normFactor, 0.0);
03050
03051 if (normalizationMode == "standard") {
03052 normMode = 0;
03053 } else if (normalizationMode == "low_contrast") {
03054 normMode = 1;
03055 }
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076
03077
03078
03079
03080 if (wantsToEncode) {
03081 if (verboseMode) { ROS_INFO("Has chosen to encode."); }
03082
03083 if (outputVideo == "outputVideo") {
03084 ROS_ERROR("outputVideo incorrectly specified...");
03085 return false;
03086 } else {
03087 ROS_INFO("outputVideo = (%s)", outputVideo.c_str());
03088
03089 }
03090
03091 if (verboseMode) { ROS_INFO("Image format = (%s); image type = (%s)", "avi", videoType.c_str()); }
03092
03093 }
03094
03095 if (inputDatatype == DATATYPE_8BIT) {
03096 if (verboseMode) { ROS_INFO("Streaming mode: 8-bit"); }
03097 } else if (inputDatatype == DATATYPE_RAW) {
03098 if (verboseMode) { ROS_INFO("Streaming mode: 16-bit"); }
03099 } else if (inputDatatype == DATATYPE_MM) {
03100 if (verboseMode) { ROS_INFO("Streaming mode: multimodal"); }
03101 }
03102
03103
03104
03105 readMode = false;
03106 loadMode = false;
03107 captureMode = false;
03108 pollMode = false;
03109 subscribeMode = false;
03110 resampleMode = false;
03111
03112
03113 if (source == "dev") {
03114
03115 if ((framerate < 0) || (framerate > MAX_READ_RATE)) {
03116 if (verboseMode) { ROS_INFO("Framerate set to (%f) so therefore defaulting to capture mode.", framerate); }
03117 framerate = MAX_READ_RATE;
03118 captureMode = true;
03119 } else {
03120 if (verboseMode) { ROS_INFO("Requested framerate (%f) - polling mode", framerate); }
03121 pollMode = true;
03122 }
03123
03124 ROS_INFO("Reading from device (%s)", capture_device.c_str());
03125
03126 } else if (source == "file") {
03127 readMode = true;
03128
03129 if ((framerate < 0.0) || (framerate > MAX_READ_RATE)) {
03130 ROS_INFO("Invalid framerate (%f) so defaulting to (%f).", framerate, DEFAULT_READ_RATE);
03131 framerate = DEFAULT_READ_RATE;
03132 } else {
03133 ROS_INFO("Requested framerate = %f", framerate);
03134 }
03135
03136 ROS_INFO("Reading from a file (%s)", filename.c_str());
03137 } else if (source == "folder") {
03138
03139 loadMode = true;
03140
03141 if ((framerate < 0.0) || (framerate > MAX_READ_RATE)) {
03142 ROS_WARN("Invalid framerate (%f) so defaulting to (%f).", framerate, DEFAULT_READ_RATE);
03143 framerate = DEFAULT_READ_RATE;
03144 } else {
03145 ROS_INFO("Requested framerate = %f", framerate);
03146 }
03147
03148 ROS_INFO("Loading images from a folder (%s)", folder.c_str());
03149
03150
03151 } else if (source == "topic") {
03152
03153 ROS_INFO("Subscribing to topic (%s) ", topicname.c_str());
03154
03155 if ((framerate < 0.0) || (framerate > MAX_READ_RATE)) {
03156 ROS_WARN("Invalid framerate (%f) so defaulting to subscribe mode.", framerate);
03157 framerate = DEFAULT_READ_RATE;
03158 subscribeMode = true;
03159 } else {
03160 ROS_INFO("Requested framerate = %f (resample mode)", framerate);
03161 resampleMode = true;
03162 }
03163
03164 }
03165
03166
03167
03168
03169 if (loopMode == true) {
03170 ROS_INFO("Option to loop has been selected.");
03171 }
03172
03173 if (intrinsics != "intrinsics") {
03174 intrinsicsProvided = true;
03175 if (verboseMode) { ROS_INFO("Intrinsics at (%s) selected.", intrinsics.c_str()); }
03176
03177 if ((inputWidth != 0) && (inputHeight != 0)) {
03178 ROS_WARN("Provided image dimensions will be ignored because of provided intrinsics file.");
03179 }
03180 } else {
03181
03182 if ((inputWidth != 0) && (inputHeight != 0)) {
03183 ROS_INFO("Provided image dimensions (%d, %d) will be used.", inputWidth, inputHeight);
03184 imageDimensionsSpecified = true;
03185 } else {
03186 ROS_WARN("No intrinsics or image dimensions provided. Will attempt to estimate camera size...");
03187 }
03188
03189
03190
03191
03192 }
03193
03194
03195
03196 if (extrinsics != "extrinsics") {
03197 ROS_INFO("Extrinsics at %s selected.", extrinsics.c_str());
03198
03199
03200
03201
03202
03203 wantsToAddExtrinsics = true;
03204 if (camera_number < 0) {
03205 ROS_WARN("Invalid camera number selected (%d) so defaulting to (0).", camera_number);
03206 camera_number = 0;
03207
03208 } else {
03209 ROS_INFO("Camera number (%d).", camera_number);
03210 }
03211
03212 }
03213
03214 getMapping(map, extremes, mapCode, mapParam);
03215
03216 int modeCount = 0;
03217
03218 if (captureMode) modeCount++;
03219 if (pollMode) modeCount++;
03220 if (readMode) modeCount++;
03221 if (loadMode) modeCount++;
03222 if (subscribeMode) modeCount++;
03223 if (resampleMode) modeCount++;
03224
03225 if (modeCount == 0) {
03226 ROS_ERROR("Either a device, file or topic should be specified for streaming.");
03227 return false;
03228 } else if (modeCount > 1) {
03229 ROS_ERROR("Either a device, file or topic should be specified - not more than one.");
03230 return false;
03231 }
03232
03233 if ((framerate < -1.0) || (framerate > MAX_READ_RATE)) {
03234 framerate = DEFAULT_READ_RATE;
03235 }
03236
03237
03238
03239
03240 nh.param<int>("republishSource", republishSource, NO_REPUBLISH_CODE);
03241 nh.param<std::string>("republishTopic", republishTopic, "specifyTopic/image_raw");
03242
03243 switch(republishSource){
03244 case REPUBLISH_CODE_8BIT_MONO:
03245 ROS_INFO("Republishing mono image as %s", republishTopic.c_str() );
03246 break;
03247 case REPUBLISH_CODE_8BIT_COL:
03248 ROS_INFO("Republishing color image as %s", republishTopic.c_str() );
03249 break;
03250 case REPUBLISH_CODE_16BIT:
03251 ROS_INFO("Republishing 16bit image as %s", republishTopic.c_str() );
03252 break;
03253 default:
03254 republishSource = NO_REPUBLISH_CODE;
03255 break;
03256 }
03257 if (republishSource != NO_REPUBLISH_CODE){
03258 ROS_INFO("Republish Code: %d", republishSource);
03259 }
03260
03261 nh.param<bool>("republishNewTimeStamp",republishNewTimeStamp,false);
03262
03263 nh.param<std::string>("frameID", frameID, "");
03264
03265 nh.param<bool>("drawReticle",drawReticle, false);
03266
03267
03268 return true;
03269 }
03270
03271 void getMapping(int mapIndex, bool extremes, int& mapCode, int& mapParam) {
03272
03273 if (mapIndex == 0) {
03274 mapCode = GRAYSCALE;
03275 } else if (mapIndex == 1) {
03276 mapCode = CIECOMP;
03277 } else if (mapIndex == 2) {
03278 mapCode = BLACKBODY;
03279 } else if (mapIndex == 3) {
03280 mapCode = RAINBOW;
03281 } else if (mapIndex == 4) {
03282 mapCode = IRON;
03283 } else if (mapIndex == 5) {
03284 mapCode = BLUERED;
03285 } else if (mapIndex == 6) {
03286 mapCode = JET;
03287 } else if (mapIndex == 7) {
03288 mapCode = CIELUV;
03289 } else if (mapIndex == 8) {
03290 mapCode = ICEIRON;
03291 } else if (mapIndex == 9) {
03292 mapCode = ICEFIRE;
03293 } else if (mapIndex == 10) {
03294 mapCode = REPEATED;
03295 } else if (mapIndex == 11) {
03296 mapCode = HIGHLIGHTED;
03297 } else {
03298 mapCode = GRAYSCALE;
03299 }
03300
03301 if (extremes) {
03302 mapParam = 0;
03303 } else {
03304 mapParam = 1;
03305 }
03306
03307 }
03308
03309 bool streamerNode::isVideoValid() {
03310
03311 if (::wantsToShutdown) {
03312 if (configData.verboseMode){ ROS_INFO("Wants to shut down.."); }
03313 setValidity(false);
03314 }
03315
03316 return videoValid;
03317
03318 }
03319
03320 void streamerNode::setValidity(bool val) {
03321 if ((val == false) && (configData.verboseMode)) { ROS_INFO("Validity being set to false.."); }
03322 videoValid = val;
03323 }
03324
03325 streamerSource * streamerNode::getMainVideoSource() {
03326 return mainVideoSource;
03327 }
03328
03329 cv::VideoCapture * streamerNode::getVideoCapture() {
03330 return ∩
03331 }
03332
03333 void streamerNode::updateMap() {
03334
03335 if (configData.verboseMode) { ROS_INFO("Updating map..."); }
03336
03337 if (configData.autoAlpha) {
03338 configData.alpha = findBestAlpha(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.cameraSize);
03339
03340 if (configData.verboseMode) { ROS_INFO("Optimal alpha: (%f)", configData.alpha); }
03341
03342 }
03343
03344 cv::Rect* validPixROI = 0;
03345 globalCameraInfo.newCamMat = getOptimalNewCameraMatrix(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.cameraSize, configData.alpha, globalCameraInfo.cameraSize, validPixROI, centerPrincipalPoint);
03346
03347
03348
03349 if (configData.wantsToAddExtrinsics){
03350
03351
03352 getRectification();
03353 updateCameraInfoExtrinsics();
03354
03355 if (configData.wantsToRectify){
03356 if (configData.camera_number == 0){
03357 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R0, globalExtrinsicsData.P0, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03358 }else if (configData.camera_number == 1){
03359 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R1, globalExtrinsicsData.P1, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03360 }
03361 }else{
03362 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03363 }
03364
03365 }else{
03366 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, cv::Mat() , globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03367 }
03368
03369 alphaChanged = false;
03370
03371 if (configData.verboseMode) { ROS_INFO("Map updated."); }
03372 }
03373
03374 void streamerNode::serverCallback(thermalvis::streamerConfig &config, uint32_t level) {
03375
03376 if (configData.verboseMode){ ROS_INFO("Processing reconfigure request..."); }
03377
03378
03379
03380 configData.minTemperature = config.minTemperature;
03381 configData.maxTemperature = config.maxTemperature;
03382
03383
03384
03385
03386
03387
03388 if (configData.autoTemperature != config.autoTemperature) {
03389 lastMinDisplayTemp = -9e99, lastMaxDisplayTemp = 9e99;
03390 configData.autoTemperature = config.autoTemperature;
03391 }
03392
03393
03394
03395
03396
03397
03398
03399
03400 if (configData.detectorMode != config.detectorMode) {
03401
03402 configData.detectorMode = config.detectorMode;
03403
03404 if (!configData.serialComms) {
03405 ROS_WARN("Selecting a detector mode has no effect unless serial comms are enabled.");
03406 } else {
03407 updateDetectorMode = true;
03408 }
03409
03410
03411 }
03412
03413
03414 configData.usbMode = config.usbMode;
03415 if (!configData.serialComms) {
03416 if (configData.usbMode != config.usbMode) {
03417 ROS_WARN("Selecting a USB mode has no effect unless serial comms are enabled.");
03418 }
03419 } else {
03420
03421 updateUSBMode = true;
03422
03423 if (configData.usbMode == USB_MODE_16) {
03424 if (configData.verboseMode) { ROS_INFO("changing <configData.inputDatatype> to DATATYPE_RAW"); }
03425 config.inputDatatype = DATATYPE_RAW;
03426 if (configData.outputType != "CV_8UC3") { configData.outputType = "CV_16UC1"; }
03427 } else if (configData.usbMode == USB_MODE_8) {
03428 config.inputDatatype = DATATYPE_8BIT;
03429 if (configData.outputType != "CV_8UC3") { configData.outputType = "CV_8UC1"; }
03430 }
03431
03432
03433 }
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464 if (configData.serialPollingRate != config.serialPollingRate) {
03465 configData.serialPollingRate = config.serialPollingRate;
03466 if (configData.verboseMode) { ROS_INFO("Updating period with rate (%f)", configData.serialPollingRate); }
03467
03468 if (configData.serialPollingRate > 0.1) {
03469 serial_timer.setPeriod(ros::Duration(1.0 / configData.serialPollingRate));
03470 } else {
03471 serial_timer.setPeriod(ros::Duration(1.0 / 1.0));
03472 }
03473 }
03474
03475 if (configData.maxNucInterval != config.maxNucInterval) {
03476
03477 configData.maxNucInterval = config.maxNucInterval;
03478 ROS_WARN("NUC interval changed by config...");
03479 updateNucInterval = true;
03480 }
03481
03482 if (configData.maxNucThreshold != config.maxNucThreshold) {
03483
03484 configData.maxNucThreshold = config.maxNucThreshold;
03485 updateNucInterval = true;
03486 }
03487
03488
03489 if (!configData.temporalSmoothing) {
03490 lastMedian = -1.0;
03491 }
03492
03493 configData.verboseMode = config.verboseMode;
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505 configData.normFactor = config.normFactor;
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526 if (config.framerate != 0.0) {
03527 configData.pauseMode = false;
03528 }
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554 if (alphaChanged) {
03555 if (configData.verboseMode) { ROS_INFO("Updating map..."); }
03556 updateMap();
03557 }
03558
03559 fusionFactor = config.fusionFactor;
03560
03561
03562
03563 if (config.framerate < 0.0) {
03564
03565 if (configData.pollMode) {
03566
03567 ROS_WARN("Invalid framerate (%f) so switching to capture mode.", config.framerate);
03568 configData.framerate = DEFAULT_READ_RATE;
03569 configData.pollMode = false;
03570 configData.captureMode = true;
03571
03572 } else if (configData.readMode) {
03573
03574 ROS_WARN("Invalid framerate (%f) so defaulting to (%f).", config.framerate, DEFAULT_READ_RATE);
03575 configData.framerate = DEFAULT_READ_RATE;
03576
03577 } else if (configData.loadMode) {
03578
03579 ROS_WARN("Invalid framerate (%f) so defaulting to (%f).", config.framerate, DEFAULT_READ_RATE);
03580 configData.framerate = DEFAULT_READ_RATE;
03581
03582 } else if (configData.resampleMode) {
03583
03584 ROS_WARN("Invalid framerate (%f) so switching to subscribe mode.", config.framerate);
03585 configData.framerate = DEFAULT_READ_RATE;
03586 configData.resampleMode = false;
03587 configData.subscribeMode = true;
03588
03589 }
03590
03591 timer.setPeriod(ros::Duration(1.0 / DEFAULT_READ_RATE));
03592
03593 } else {
03594
03595 if (configData.captureMode) {
03596
03597 ROS_INFO("Specified framerate (%f) so switching to poll mode.", config.framerate);
03598 configData.framerate = config.framerate;
03599 configData.captureMode = false;
03600 configData.pollMode = true;
03601
03602 } else if (configData.subscribeMode) {
03603
03604 ROS_INFO("Specified framerate (%f) so switching to resample mode.", config.framerate);
03605 configData.framerate = config.framerate;
03606 configData.subscribeMode = false;
03607 configData.resampleMode = true;
03608
03609 }
03610
03611 if (config.framerate > 0.0) {
03612 timer.setPeriod(ros::Duration(1.0 / config.framerate));
03613 } else {
03614 configData.pauseMode = true;
03615 timer.setPeriod(ros::Duration(1.0 / 1.0));
03616 }
03617
03618
03619 }
03620
03621 if (config.inputDatatype != configData.inputDatatype) {
03622 if (configData.readMode) {
03623 ROS_WARN("You cannot change the bit-reading mode mid-stream. Consider restarting.");
03624 } else if ((configData.captureMode) || (configData.pollMode)) {
03625 if (configData.verboseMode) { ROS_INFO("Resetting device in order to change streaming mode to (%d)...", config.inputDatatype); }
03626 releaseDevice();
03627 if (configData.verboseMode) { ROS_INFO("device released..."); }
03628 configData.inputDatatype = config.inputDatatype;
03629 if (configData.verboseMode) { ROS_INFO("Changing to (%d)", configData.inputDatatype); }
03630 setupDevice();
03631 if (configData.verboseMode) { ROS_INFO("Set up done."); }
03632 } else {
03633 configData.inputDatatype = config.inputDatatype;
03634 }
03635
03636 }
03637
03638
03639
03640
03641
03642
03643 configData.normMode = config.normMode;
03644
03645 bool wantsToRefreshCameras = false;
03646
03647 if (config.output16bit && !configData.output16bitFlag) {
03648 configData.output16bitFlag = true;
03649 wantsToRefreshCameras = true;
03650 } else if (!config.output16bit && configData.output16bitFlag) {
03651 configData.output16bitFlag = false;
03652 wantsToRefreshCameras = true;
03653 }
03654
03655 if (config.output8bit && !configData.output8bitFlag) {
03656 configData.output8bitFlag = true;
03657 wantsToRefreshCameras = true;
03658 } else if (!config.output8bit && configData.output8bitFlag){
03659 configData.output8bitFlag = false;
03660 wantsToRefreshCameras = true;
03661 }
03662
03663 if (config.outputColor && !configData.outputColorFlag) {
03664 configData.outputColorFlag = true;
03665 wantsToRefreshCameras = true;
03666 } else if (!config.outputColor && configData.outputColorFlag) {
03667 configData.outputColorFlag = false;
03668 wantsToRefreshCameras = true;
03669 }
03670
03671 if (wantsToRefreshCameras) {
03672 refreshCameraAdvertisements();
03673 }
03674
03675 getMapping(config.map, configData.extremes, configData.mapCode, configData.mapParam);
03676 colourMap.load_standard(configData.mapCode, configData.mapParam);
03677
03678 if (configData.outputFolder != "outputFolder") {
03679
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718 } else {
03719 ROS_WARN("No valid output folder specified...");
03720 configData.wantsToWrite = false;
03721 configData.wantsToDumpTimestamps = false;
03722 }
03723
03724
03725
03726
03727 if (config.undistortImages) {
03728
03729
03730
03731 if (configData.wantsToAddExtrinsics){
03732 if (configData.wantsToRectify){
03733 if (configData.camera_number == 0){
03734 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R0, globalExtrinsicsData.P0, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03735 }else if (configData.camera_number == 1){
03736 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R1, globalExtrinsicsData.P1, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03737 }
03738
03739 }else{
03740 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03741 }
03742 }else{
03743 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03744 }
03745
03746 }
03747
03748 configData.wantsToUndistort = config.undistortImages;
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788 if (!firstServerCallbackProcessed) {
03789 firstServerCallbackProcessed = true;
03790 }
03791
03792 if (configData.verboseMode) { ROS_INFO("Reconfigure request complete..."); }
03793 }
03794
03795 int getMapIndex(string mapping) {
03796
03797 int map;
03798
03799 if (mapping == "GRAYSCALE") {
03800 map = 0;
03801 } else if (mapping == "CIECOMP") {
03802 map = 1;
03803 } else if (mapping == "BLACKBODY") {
03804 map = 2;
03805 } else if (mapping == "RAINBOW") {
03806 map = 3;
03807 } else if (mapping == "IRON") {
03808 map = 4;
03809 } else if (mapping == "BLUERED") {
03810 map = 5;
03811 } else if (mapping == "JET") {
03812 map = 6;
03813 } else if (mapping == "CIELUV") {
03814 map = 7;
03815 } else if (mapping == "ICEIRON") {
03816 map = 8;
03817 } else if (mapping == "ICEFIRE") {
03818 map = 9;
03819 } else if (mapping == "REPEATED") {
03820 map = 10;
03821 } else if (mapping == "HIGHLIGHTED") {
03822 map = 11;
03823 } else {
03824 map = 0;
03825 }
03826
03827 return map;
03828 }
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844 void set_blocking (int fd, int should_block)
03845 {
03846 struct termios tty;
03847 memset (&tty, 0, sizeof tty);
03848 if (tcgetattr (fd, &tty) != 0)
03849 {
03850 ROS_ERROR("error %d getting term settings set_blocking", errno);
03851
03852 }
03853
03854 tty.c_cc[VMIN] = should_block ? 1 : 0;
03855 tty.c_cc[VTIME] = should_block ? 5 : 0;
03856
03857 if (tcsetattr (fd, TCSANOW, &tty) != 0)
03858 ROS_ERROR("error setting term %sblocking", should_block ? "" : "no");
03859 }
03860
03861 int streamerNode::open_port() {
03862 int fd;
03863
03864
03865
03866
03867
03868 fd = open(configData.portAddress.c_str(), O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK | O_SYNC);
03869
03870 set_blocking (fd, 0);
03871
03872 char buf [10000];
03873 int n;
03874 do {
03875 n = read (fd, buf, sizeof buf);
03876 } while (n > 0);
03877
03878
03879
03880 usleep(200000);
03881 tcflush(fd, TCIOFLUSH);
03882
03883 if (fd == -1) {
03884 ROS_ERROR("open_port(): Unable to open (%s) (%s)", configData.portAddress.c_str(), strerror(errno));
03885 } else {
03886
03887
03888
03889 }
03890 return (fd);
03891 }
03892
03893 void displayTermiosData(termios options) {
03894
03895 ROS_INFO(" Termios Summary:");
03896
03897 ROS_INFO("c_iflag = (%d)", options.c_iflag);
03898 ROS_INFO("c_oflag = (%d)", options.c_oflag);
03899 ROS_INFO("c_cflag = (%d)", options.c_cflag);
03900 ROS_INFO("c_lflag = (%d)", options.c_lflag);
03901 ROS_INFO("c_ispeed = (%d)", options.c_ispeed);
03902 ROS_INFO("c_ospeed = (%d)", options.c_ospeed);
03903
03904 for (unsigned int iii = 0; iii < NCCS; iii++) {
03905 ROS_INFO("c_cc[%d] = (%d)", iii, options.c_cc[iii]);
03906 }
03907
03908 ROS_WARN("Termios Summary Complete.");
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920 }
03921
03922 bool streamerNode::configureSerialComms() {
03923
03924
03925 struct termios options;
03926
03927 mainfd = open_port();
03928
03929
03930
03931
03932 int fcntl_ret = fcntl(mainfd, F_SETFL, FNDELAY);
03933
03934
03935 if (fcntl_ret != 0) { ROS_ERROR("fcntl_ret = (%d)", fcntl_ret); }
03936
03937
03938
03939
03940 if (configData.verboseMode) { displayTermiosData(options); }
03941
03942
03943
03944
03945 if (0) {
03946
03947 bzero(&options, sizeof(options));
03948 options.c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD;
03949 options.c_iflag = IGNPAR;
03950 options.c_oflag = 0;
03951
03952
03953 options.c_lflag = 0;
03954
03955 options.c_cc[VTIME] = 0;
03956 options.c_cc[VMIN] = 11;
03957
03958 tcflush(mainfd, TCIFLUSH);
03959 tcsetattr(mainfd,TCSANOW,&options);
03960 tcflush(mainfd, TCIFLUSH);
03961 } else {
03962
03963
03964
03965
03966
03967
03968 int cfsetispeed_ret = cfsetispeed(&options, B115200);
03969 if (cfsetispeed_ret != 0) { ROS_ERROR("cfsetispeed_ret = (%d)", cfsetispeed_ret); }
03970 int cfsetospeed_ret = cfsetospeed(&options, B115200);
03971 if (cfsetospeed_ret != 0) { ROS_ERROR("cfsetospeed_ret = (%d)", cfsetospeed_ret); }
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984 if (configData.serialCommsConfigurationCode == SERIAL_COMMS_CONFIG_DEFAULT) {
03985
03986
03987
03988 if (1) {
03989
03990 bzero(&options, sizeof(options));
03991
03992 options.c_iflag = 0;
03993 options.c_oflag = 0;
03994 options.c_cflag = 0;
03995 options.c_lflag = 0;
03996
03997
03998
03999
04000
04001 cfsetispeed(&options, B115200);
04002 cfsetospeed(&options, B115200);
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012 options.c_iflag &= ~INPCK;
04013 options.c_iflag |= IGNPAR;
04014 options.c_iflag &= ~PARMRK;
04015 options.c_iflag &= ~ISTRIP;
04016 options.c_iflag |= IGNBRK;
04017 options.c_iflag &= ~BRKINT;
04018 options.c_iflag &= ~IGNCR;
04019 options.c_iflag &= ~ICRNL;
04020 options.c_iflag &= ~INLCR;
04021 options.c_iflag &= ~IXOFF;
04022 options.c_iflag &= ~IXON;
04023 options.c_iflag &= ~IXANY;
04024 options.c_iflag &= ~IMAXBEL;
04025
04026 options.c_iflag &= ~IUCLC;
04027 options.c_iflag &= ~IUTF8;
04028
04029
04030
04031 options.c_oflag &= ~OPOST;
04032 options.c_oflag &= ~ONLCR;
04033
04034 options.c_oflag &= ~OLCUC;
04035 options.c_oflag &= ~OCRNL;
04036 options.c_oflag &= ~ONOCR;
04037 options.c_oflag &= ~ONLRET;
04038 options.c_oflag &= ~OFILL;
04039 options.c_oflag &= ~OFDEL;
04040
04041 options.c_oflag |= NL0;
04042 options.c_oflag |= CR0;
04043 options.c_oflag |= TAB0;
04044 options.c_oflag |= BS0;
04045 options.c_oflag |= VT0;
04046 options.c_oflag |= FF0;
04047
04048
04049
04050 options.c_cflag |= CLOCAL;
04051 options.c_cflag &= ~HUPCL;
04052 options.c_cflag |= CREAD;
04053 options.c_cflag &= ~CSTOPB;
04054 options.c_cflag &= ~PARENB;
04055 options.c_cflag &= ~PARODD;
04056 options.c_cflag &= ~CSIZE;
04057 options.c_cflag |= CS8;
04058
04059
04060 options.c_cflag &= ~CRTSCTS;
04061
04062
04063
04064 options.c_lflag &= ~ICANON;
04065 options.c_lflag &= ~ECHO;
04066 options.c_lflag &= ~ECHOE;
04067 options.c_lflag &= ~ECHOPRT;
04068 options.c_lflag &= ~ECHOK;
04069 options.c_lflag &= ~ECHOKE;
04070 options.c_lflag &= ~ECHONL;
04071 options.c_lflag &= ~ECHOCTL;
04072 options.c_lflag &= ~ISIG;
04073 options.c_lflag &= ~IEXTEN;
04074 options.c_lflag &= ~NOFLSH;
04075 options.c_lflag &= ~TOSTOP;
04076
04077 options.c_lflag &= ~XCASE;
04078
04079 options.c_ispeed = B115200;
04080 options.c_ospeed = B115200;
04081
04082
04083 options.c_cc[0] = 79;
04084 options.c_cc[1] = 215;
04085 options.c_cc[2] = 212;
04086 options.c_cc[3] = 255;
04087 options.c_cc[4] = 127;
04088
04089 options.c_cc[5] = 0;
04090 options.c_cc[6] = 0;
04091 options.c_cc[7] = 88;
04092 options.c_cc[8] = 42;
04093 options.c_cc[9] = 121;
04094
04095 options.c_cc[10] = 106;
04096 options.c_cc[11] = 96;
04097 options.c_cc[12] = 127;
04098 options.c_cc[13] = 0;
04099 options.c_cc[14] = 0;
04100
04101 options.c_cc[15] = 104;
04102 options.c_cc[16] = 41;
04103 options.c_cc[17] = 121;
04104 options.c_cc[18] = 106;
04105 options.c_cc[19] = 96;
04106
04107 options.c_cc[20] = 127;
04108 options.c_cc[21] = 0;
04109 options.c_cc[22] = 0;
04110 options.c_cc[23] = 16;
04111 options.c_cc[24] = 16;
04112
04113 options.c_cc[25] = 121;
04114 options.c_cc[26] = 106;
04115 options.c_cc[27] = 96;
04116 options.c_cc[28] = 127;
04117 options.c_cc[29] = 0;
04118
04119 options.c_cc[30] = 0;
04120 options.c_cc[31] = 144;
04121
04122
04123
04124
04125
04126 tcflush(mainfd, TCOFLUSH );
04127 tcflush(mainfd, TCIFLUSH);
04128
04129 int yes = 1;
04130
04131 ioctl(mainfd, TIOCCONS, &yes);
04132
04133
04134
04135 } else {
04136
04137
04138
04139 options.c_cflag |= (CLOCAL | CREAD);
04140 options.c_cflag &= ~PARENB;
04141 options.c_cflag |= CSTOPB;
04142 options.c_cflag &= ~CSIZE;
04143 options.c_cflag |= CS8;
04144 options.c_cflag &= ~CRTSCTS;
04145
04146
04147 options.c_oflag = 0;
04148
04149
04150 options.c_lflag &= ~(ICANON | ECHO | ISIG);
04151
04152
04153 options.c_cflag &= ~CSTOPB;
04154 options.c_cflag &= ~HUPCL;
04155
04156
04157 options.c_cflag &= IGNBRK;
04158 options.c_cflag &= IGNPAR;
04159
04160
04161
04162 options.c_cflag &= ~ICRNL;
04163 options.c_cflag &= ~IXON;
04164 options.c_cflag &= ~IEXTEN;
04165 options.c_cflag &= ~ECHOE;
04166 options.c_cflag &= ~ECHOK;
04167 options.c_cflag &= ~ECHOCTL;
04168 options.c_cflag &= ~ECHOKE;
04169
04170
04171 }
04172
04173
04174
04175
04176 } else {
04177 if (configData.verboseMode) { ROS_INFO("Using modified serial comms configuration settings..."); }
04178 }
04179
04180 if (configData.verboseMode) { displayTermiosData(options); }
04181
04182
04183
04184 int tcsetattr_ret = tcsetattr(mainfd, TCSANOW, &options);
04185
04186
04187 if (tcsetattr_ret != 0) { ROS_ERROR("tcsetattr_ret = (%d)", tcsetattr_ret); }
04188
04189
04190
04191 tcflush(mainfd,TCIOFLUSH);
04192
04193 }
04194
04195
04196
04197
04198
04199 {
04200 if (configData.verboseMode) { ROS_INFO("SerialComms: Opening shutter..."); }
04201 char localCommand[256];
04202 sprintf(localCommand, "open");
04203 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
04204 }
04205
04206 {
04207
04208 int n;
04209 char buff[SERIAL_BUFF_SIZE];
04210 n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04211
04212 if (configData.verboseMode) { ROS_INFO("Cleared (%d) characters from buffer: (%s)", n, buff); }
04213
04214 }
04215
04216 int statusNum = 0;
04217
04218
04219
04220 if (configData.disableSkimming) {
04221
04222 char localCommand[256];
04223 sprintf(localCommand, "SKIMACTIVE");
04224
04225 if (1) { ROS_INFO("SerialComms: Disabling mean-shifting..."); }
04226 if (!sendSerialCommand(localCommand, 1)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, 1);
04227
04228 ros::Duration(1.0).sleep();
04229
04230 char buff[SERIAL_BUFF_SIZE];
04231 read(mainfd, buff, SERIAL_BUFF_SIZE);
04232
04233
04234
04235
04236
04237 statusNum = atof(&buff[17]);
04238 if (configData.verboseMode) { ROS_INFO("SKIMACTIVE status = (%d)", statusNum); }
04239
04240 }
04241
04242 ros::Duration(1.0).sleep();
04243
04244 if (configData.disableSkimming) {
04245 char localCommand[256];
04246 sprintf(localCommand, "SKIMACTIVE 0");
04247
04248 if (configData.verboseMode) { ROS_INFO("SerialComms: Verifying disabling of mean-shifting..."); }
04249 if (!sendSerialCommand(localCommand, 1)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, 1);
04250
04251 }
04252
04253 {
04254 char localCommand[256];
04255 sprintf(localCommand, "SAVE");
04256
04257 if (configData.verboseMode) { ROS_INFO("SerialComms: Saving current settings..."); }
04258 if (!sendSerialCommand(localCommand, 1)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, 1);
04259
04260
04261 }
04262
04263 int n;
04264 char buff[SERIAL_BUFF_SIZE];
04265
04266 n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04267
04268
04269 if ((configData.verboseMode) && (n != 0)) { ROS_WARN("read(): n = (%d)", n); }
04270
04271 sleep(2);
04272 tcflush(mainfd,TCIOFLUSH);
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299 if (configData.disableSkimming) {
04300 if (statusNum == 1) {
04301 ROS_ERROR("Camera must now be powercycled: SKIMACTIVE was not originally off.");
04302 return false;
04303 } else {
04304 ROS_WARN("Assuming camera has been powercycled since SKIMACTIVE was saved as off.");
04305 return true;
04306 }
04307 } else {
04308 return true;
04309 }
04310
04311 }
04312
04313 double streamerNode::smoothThermistorReading() {
04314
04315 int history = min((int)recordedThermistorReadings, MAX_THERMISTOR_READINGS_TO_STORE);
04316
04317 double smoothedTemperature = 0.0;
04318
04319 double x[MAX_THERMISTOR_READINGS_TO_STORE], y[MAX_THERMISTOR_READINGS_TO_STORE];
04320
04321 unsigned int termsToConsider = 0;
04322
04323 for (int iii = 0; iii < history; iii++) {
04324
04325 if ( ( ros::Time::now().toSec() - thermistorBuffer[(recordedThermistorReadings-iii-1) % MAX_THERMISTOR_READINGS_TO_STORE][0] ) < configData.thermistorWindow) {
04326 x[termsToConsider] = thermistorBuffer[(recordedThermistorReadings-iii-1) % MAX_THERMISTOR_READINGS_TO_STORE][0];
04327 y[termsToConsider] = thermistorBuffer[(recordedThermistorReadings-iii-1) % MAX_THERMISTOR_READINGS_TO_STORE][1];
04328 termsToConsider++;
04329 }
04330 }
04331
04332
04333 if (0) {
04334 for (unsigned int iii = 0; iii < termsToConsider; iii++) {
04335
04336 smoothedTemperature += y[iii];
04337 }
04338
04339 smoothedTemperature /= double(termsToConsider);
04340 }
04341
04342
04343
04344
04345 if (1) {
04346 double m, c;
04347
04348 findLinearModel(x, y, termsToConsider, m, c);
04349
04350
04351 smoothedTemperature = m * thermistorBuffer[(recordedThermistorReadings-1) % MAX_THERMISTOR_READINGS_TO_STORE][0] + c;
04352
04353 }
04354
04355
04356
04357 return smoothedTemperature;
04358 }
04359
04360 bool streamerNode::getNucSettingsReading(int& delay, double& diff) {
04361
04362 bool writeSucceeded = false;
04363
04364 char localCommand[256];
04365 sprintf(localCommand, "NUCSET");
04366 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
04367
04368 char buff[SERIAL_BUFF_SIZE];
04369
04370 memset(&buff[0], 0, sizeof(buff));
04371
04372 int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04373
04374
04375 bool readSucceeded = false;
04376
04377
04378
04379 if (n < 0) {
04380 ROS_WARN("NUC settings were unable to be read!");
04381 } else if (n == 0) {
04382 ROS_WARN("0 characters from NUC settings...");
04383 } else {
04384 readSucceeded = true;
04385
04386 }
04387
04388 ROS_INFO("Read: (%s)", buff);
04389
04390 return (writeSucceeded && readSucceeded);
04391
04392 }
04393
04394 float streamerNode::getThermistorReading() {
04395
04396 double retVal;
04397
04398 bool writeSucceeded = false;
04399
04400 char localCommand[256];
04401 sprintf(localCommand, "THERM");
04402 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) {
04403 if (configData.verboseMode) { ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts); }
04404 return -9e99;
04405 }
04406
04407 char buff[SERIAL_BUFF_SIZE];
04408 memset(&buff[0], 0, sizeof(buff));
04409
04410 int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04411
04412
04413
04414 bool readSucceeded = false;
04415
04416
04417
04418 if (n < 0) {
04419 ROS_WARN("Thermistor value was unable to be read!");
04420 } else if (n == 0) {
04421 ROS_WARN("Zero characters returned from attempted thermistor reading.");
04422 } else {
04423 readSucceeded = true;
04424 }
04425
04426 if (!readSucceeded) {
04427 return -9e99;
04428 }
04429
04430 for (unsigned int iii = 0; iii < 512; iii++) {
04431 if (buff[iii] == '\r') {
04432 buff[iii] = '-';
04433 }
04434 }
04435
04436
04437
04438
04439
04440 retVal = atof(&buff[103]);
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451
04452
04453
04454 return retVal;
04455
04456 }