42 #include <sensor_msgs/Image.h> 43 #include <sensor_msgs/CameraInfo.h> 45 #include <sensor_msgs/SetCameraInfo.h> 46 #include <driver_base/SensorLevels.h> 54 #include <linux/sysctl.h> 57 #include <wge100_camera/BoardConfig.h> 58 #include <boost/tokenizer.hpp> 59 #include <boost/format.hpp> 67 #include <wge100_camera/WGE100CameraConfig.h> 73 #define RMEM_MAX_RECOMMENDED 20000000 83 : rows(rows), cols(cols), data(data)
89 for (
int i = 0; i < m.
rows; ++i) {
90 for (
int j = 0; j < m.
cols; ++j) {
99 const sensor_msgs::CameraInfo& cam_info)
104 out <<
"# Camera intrinsics\n\n";
106 out <<
"[image]\n\n";
107 out <<
"width\n" << cam_info.width <<
"\n\n";
108 out <<
"height\n" << cam_info.height <<
"\n\n";
109 out <<
"[" << camera_name <<
"]\n\n";
111 out <<
"camera matrix\n" <<
SimpleMatrix(3, 3, &cam_info.K[0]);
112 out <<
"\ndistortion\n" <<
SimpleMatrix(1, 5, &cam_info.D[0]);
113 out <<
"\n\nrectification\n" <<
SimpleMatrix(3, 3, &cam_info.R[0]);
114 out <<
"\nprojection\n" <<
SimpleMatrix(3, 4, &cam_info.P[0]);
155 FrameTimeFilter(
double frame_rate = 1.,
double late_locked_threshold = 1e-3,
double early_locked_threshold = 3e-3,
int early_recovery_frames = 5,
int max_recovery_frames = 10,
double max_skew = 1.001,
double max_skipped_frames = 100)
157 frame_period_ = max_skew / frame_rate;
158 max_recovery_frames_ = max_recovery_frames;
159 early_recovery_frames_ = early_recovery_frames;
160 late_locked_threshold_ = late_locked_threshold;
161 early_locked_threshold_ = early_locked_threshold;
162 max_skipped_frames_ = max_skipped_frames;
163 last_frame_number_ = 0;
169 relock_time_ = anticipated_time_ = std::numeric_limits<double>::infinity();
170 unlocked_count_ = late_locked_threshold_;
173 double run(
double in_time,
int frame_number)
175 double out_time = in_time;
176 int delta = (frame_number - last_frame_number_) & 0xFFFF;
178 if (delta > max_skipped_frames_)
180 ROS_WARN_NAMED(
"frame_time_filter",
"FrameTimeFilter missed too many frames from #%u to #%u. Resetting.", last_frame_number_, frame_number);
184 anticipated_time_ += frame_period_ * delta;
185 relock_time_ += frame_period_ * delta;
187 if (out_time < relock_time_)
188 relock_time_ = out_time;
192 bool early_trigger =
false;
193 if (out_time < anticipated_time_ - early_locked_threshold_ && finite(anticipated_time_))
195 ROS_WARN_NAMED(
"frame_time_filter",
"FrameTimeFilter saw frame #%u was early by %f.", frame_number, anticipated_time_ - out_time);
196 early_trigger =
true;
198 if (out_time < anticipated_time_)
200 anticipated_time_ = out_time;
201 relock_time_ = std::numeric_limits<double>::infinity();
204 else if (out_time > anticipated_time_ + late_locked_threshold_)
207 if (unlocked_count_ > max_recovery_frames_)
209 ROS_DEBUG_NAMED(
"frame_time_filter",
"FrameTimeFilter lost lock at frame #%u, shifting by %f.", frame_number, relock_time_ - anticipated_time_);
210 anticipated_time_ = relock_time_;
211 relock_time_ = std::numeric_limits<double>::infinity();
215 out_time = anticipated_time_;
218 last_frame_number_ = frame_number;
220 return early_trigger ? -out_time : out_time;
251 before_clear_ = before_clear;
252 before_warn_ = before_warn;
253 countdown_ = before_warn_;
263 countdown_ = before_warn_;
268 countdown_ = before_clear_;
280 countdown_ = before_clear_;
284 countdown_ = before_warn_;
293 typedef wge100_camera::WGE100CameraConfig
Config;
371 int bintable[5] = { -1, 0, 1, -1, 2 };
375 setStatusMessage(
"Error setting video mode.");
381 setStatusMessage(
"Error setting companding mode.");
387 setStatusMessage(
"Error setting AGC/AEC mode. Exposure and gain may be incorrect.");
393 setStatusMessage(
"Error setting analog gain.");
399 setStatusMessage(
"Error setting mirroring properties.");
405 setStatusMessage(
"Error setting exposure.");
412 setStatusMessage(
"Error setting black level.");
418 setStatusMessage(
"Error setting brightness.");
424 setStatusMessage(
"Error setting maximum exposure.");
434 trigger_matcher_(5, 60),
435 no_timestamp_warning_filter_(10, 10)
441 last_camera_ok_time_ = 0;
442 last_image_time_ = 0;
444 missed_line_count_ = 0;
445 trigger_matcher_drop_count_ = 0;
446 missed_eof_count_ = 0;
447 dropped_packets_ = 0;
448 lost_image_thread_count_ = 0;
449 massive_frame_losses_ = 0;
450 dropped_packet_event_ =
false;
457 if (config_.horizontal_binning == 3)
459 config_.horizontal_binning = 2;
460 ROS_WARN(
"horizontal_binning = 3 is invalid. Setting to 2.");
463 if (config_.vertical_binning == 3)
465 config_.vertical_binning = 2;
466 ROS_WARN(
"horizontal_binning = 3 is invalid. Setting to 2.");
469 desired_freq_ = config_.ext_trig ? config_.trig_rate : config_.imager_rate;
473 if (!config_.auto_exposure && config_.exposure > 0.99 / desired_freq_)
475 ROS_WARN(
"Exposure (%f s) is greater than 99%% of frame period (%f s). Setting to 99%% of frame period.",
476 config_.exposure, 0.99 / desired_freq_);
477 config_.exposure = 0.99 * 1 / desired_freq_;
484 if (config_.auto_exposure && config_.max_exposure && config_.max_exposure > 0.99 / desired_freq_)
486 ROS_WARN(
"Maximum exposure (%f s) is greater than 99%% of frame period (%f s). Setting to 99%% of frame period.",
487 config_.max_exposure, 0.99 / desired_freq_);
488 config_.max_exposure = 0.99 * 1 / desired_freq_;
496 enable_primary_ = (config_.register_set != wge100_camera::WGE100Camera_AlternateRegisterSet);
497 enable_alternate_ = (config_.register_set != wge100_camera::WGE100Camera_PrimaryRegisterSet);
510 std::ifstream
f(
"/proc/sys/net/core/rmem_max");
518 if (state_ != CLOSED)
520 ROS_ERROR(
"Assertion failing. state_ = %i", state_);
529 rmem_max_ = get_rmem_max();
532 ROS_WARN_NAMED(
"rmem_max",
"rmem_max is %i. Buffer overflows and packet loss may occur. Minimum recommended value is 20000000. Updates may not take effect until the driver is restarted. See http://www.ros.org/wiki/wge100_camera/Troubleshooting", rmem_max_);
541 setStatusMessagef(
"Matching URL %s : %s", config_.camera_url.c_str(), errmsg);
549 setStatusMessage(
"IP address configuration failed");
553 ROS_INFO(
"Configured camera. Complete URLs: serial://%u@%s#%s name://%s@%s#%s",
561 setStatusMessagef(
"Unable to get local MAC address for interface %s", camera_.
ifName);
567 setStatusMessagef(
"Unable to get local IP address for interface %s", camera_.
ifName);
571 if (config_.ext_trig && config_.trig_timestamp_topic.empty())
573 setStatusMessage(
"External triggering is selected, but no \"trig_timestamp_topic\" was specified.");
579 setStatusMessage(
"Error selecting image resolution.");
585 primary_settings.
height = config_.height;
586 primary_settings.
width = config_.width;
587 primary_settings.
x_offset = config_.x_offset;
588 primary_settings.
y_offset = config_.y_offset;
591 primary_settings.
imager_rate = config_.imager_rate;
592 primary_settings.
companding = config_.companding;
593 primary_settings.
auto_gain = config_.auto_gain;
594 primary_settings.
gain = config_.gain;
596 primary_settings.
exposure = config_.exposure;
597 primary_settings.
mirror_x = config_.mirror_x;
598 primary_settings.
mirror_y = config_.mirror_y;
599 primary_settings.
rotate_180 = config_.rotate_180;
603 primary_settings.
black_level = config_.black_level;
604 primary_settings.
brightness = config_.brightness;
607 alternate_settings.
height = config_.height;
608 alternate_settings.
width = config_.width;
609 alternate_settings.
x_offset = config_.x_offset;
610 alternate_settings.
y_offset = config_.y_offset;
613 alternate_settings.
imager_rate = config_.imager_rate;
614 alternate_settings.
companding = config_.companding_alternate;
615 alternate_settings.
auto_gain = config_.auto_gain_alternate;
616 alternate_settings.
gain = config_.gain_alternate;
617 alternate_settings.
auto_exposure = config_.auto_exposure_alternate;
618 alternate_settings.
exposure = config_.exposure_alternate;
619 alternate_settings.
mirror_x = config_.mirror_x;
620 alternate_settings.
mirror_y = config_.mirror_y;
621 alternate_settings.
rotate_180 = config_.rotate_180;
623 alternate_settings.
black_level = config_.black_level;
626 alternate_settings.
brightness = config_.brightness;
632 setStatusMessage(
"Unknown imager model.");
635 alternate_imager_ = imager_->getAlternateContext();
637 if (enable_primary_ && enable_alternate_)
639 if (!alternate_imager_)
641 setStatusMessage(
"Unable to find alternate imager context, but enable_alternate is true.");
646 primary_settings.
auto_exposure = config_.auto_exposure_alternate;
647 primary_settings.
gain = config_.gain_alternate;
648 primary_settings.
companding = config_.companding_alternate;
650 alternate_settings.
gain = config_.gain;
651 alternate_settings.
companding = config_.companding;
653 if (setImagerSettings(*imager_, primary_settings) ||
654 setImagerSettings(*alternate_imager_, alternate_settings))
657 else if (enable_primary_)
659 if (setImagerSettings(*imager_, primary_settings))
664 if (setImagerSettings(*imager_, alternate_settings))
670 setStatusMessage(
"Error configuring camera to report alternate frames.");
674 next_is_alternate_ = !enable_primary_;
677 frame_time_filter_ =
FrameTimeFilter(desired_freq_, 0.001, 0.5 / config_.imager_rate);
678 trigger_matcher_.
setTrigDelay(1. / config_.imager_rate);
682 bool is_027 = ((camera_.
serial / 100000) % 100) == 27;
683 bool is_MT9V032 = imager_->getModel() ==
"MT9V032";
684 if (camera_.
serial != 0 && is_027 == is_MT9V032)
686 boost::recursive_mutex::scoped_lock lock(mutex_);
687 setStatusMessagef(
"Camera has %s serial number, but has %s imager. This is a serious problem with the hardware.",
688 is_027 ?
"027" :
"non-027", imager_->getModel().c_str());
692 if (config_.test_pattern && (
695 setStatusMessage(
"Error turning on test pattern.");
699 setStatusMessage(
"Camera is opened.");
709 setStatusMessage(
"Camera is closed.");
714 last_frame_number_ = 0xFFFF;
715 last_partial_frame_number_ = 0xFFFF;
719 if (enable_alternate_ && enable_primary_)
721 if (config_.rising_edge_trig)
724 setStatusMessagef(
"Trigger mode set error. Is %s accessible from interface %s? (Try running route to check.)", camera_.
ip_str, camera_.
ifName);
729 trigger_matcher_.
reset();
745 setStatusMessage(
"Waiting for first frame...");
753 if (state_ != RUNNING)
757 setStatusMessage(
"Stopped");
761 if (image_thread_ && !image_thread_->timed_join((boost::posix_time::milliseconds) 2000))
763 ROS_ERROR(
"image_thread_ did not die after two seconds. Pretending that it did. This is probably a bad sign.");
764 lost_image_thread_count_++;
766 image_thread_.reset();
772 status.
summary(2,
"Could not set imager into test mode.");
773 status.
add(
"Writing imager test mode",
"Fail");
778 status.
add(
"Writing imager test mode",
"Pass");
784 status.
summary(2,
"Could not read imager mode back.");
785 status.
add(
"Reading imager test mode",
"Fail");
790 status.
add(
"Reading imager test mode",
"Pass");
793 if (inmode != mode) {
794 status.
summary(2,
"Imager test mode read back did not match.");
795 status.
addf(
"Comparing read back value",
"Fail (%04x != %04x)", inmode, mode);
800 status.
add(
"Comparing read back value",
"Pass");
811 return (boost::format(
"WGE100_%05u") % camera_.
serial).str();
824 setStatusMessage(
"Camera terminated streaming with an overflow error.");
826 setStatusMessage(
"Camera terminated streaming with an error.");
828 setStatusMessage(
"wge100VidReceiveAuto exited with an error code.");
834 if (state_ == RUNNING)
841 double since_last_frame_ =
ros::Time::now().
toSec() - (last_image_time_ ? last_image_time_ : driver_start_time_);
842 if (since_last_frame_ > 10)
844 stat.
summary(2,
"Next frame is way past due.");
846 else if (since_last_frame_ > 5 / desired_freq_)
848 stat.
summary(1,
"Next frame is past due.");
852 stat.
summaryf(1,
"Frames are streaming, but the receive buffer is small (rmem_max=%u). Please increase rmem_max to %u to avoid dropped frames. For details: http://www.ros.org/wiki/wge100_camera/Troubleshooting", rmem_max_,
RMEM_MAX_RECOMMENDED);
854 else if (dropped_packet_event_ && config_.packet_debug)
857 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
"There have been dropped packets.");
858 dropped_packet_event_ = 0;
862 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Frames are streaming.");
863 dropped_packet_event_ = 0;
866 stat.
addf(
"Missing image line frames",
"%d", missed_line_count_);
867 stat.
addf(
"Missing EOF frames",
"%d", missed_eof_count_);
868 stat.
addf(
"Dropped packet estimate",
"%d", dropped_packets_);
869 stat.
addf(
"Frames dropped by trigger filter",
"%d", trigger_matcher_drop_count_);
870 stat.
addf(
"Massive frame losses",
"%d", massive_frame_losses_);
871 stat.
addf(
"Losses of image thread",
"%d", lost_image_thread_count_);
872 stat.
addf(
"First packet offset",
"%d", config_.first_packet_offset);
875 static const std::string not_opened =
"not_opened";
876 stat.
add(
"Camera Serial #", not_opened);
877 stat.
add(
"Camera Name", not_opened);
878 stat.
add(
"Camera Hardware", not_opened);
879 stat.
add(
"Camera MAC", not_opened);
880 stat.
add(
"Interface", not_opened);
881 stat.
add(
"Camera IP", not_opened);
882 stat.
add(
"Image encoding", not_opened);
886 stat.
add(
"Camera Serial #", camera_.
serial);
888 stat.
add(
"Camera Hardware", hwinfo_);
889 stat.
addf(
"Camera MAC",
"%02X:%02X:%02X:%02X:%02X:%02X", camera_.
mac[0], camera_.
mac[1], camera_.
mac[2], camera_.
mac[3], camera_.
mac[4], camera_.
mac[5]);
892 stat.
add(
"Image encoding", image_encoding_);
894 stat.
add(
"Image width", config_.width);
895 stat.
add(
"Image height", config_.height);
896 stat.
add(
"Image horizontal binning", config_.horizontal_binning);
897 stat.
add(
"Image vertical binning", config_.vertical_binning);
898 stat.
add(
"Requested imager rate", config_.imager_rate);
899 stat.
add(
"Latest frame time", last_image_time_);
900 stat.
add(
"Latest frame #", last_frame_number_);
901 stat.
add(
"External trigger controller", config_.trig_timestamp_topic);
902 stat.
add(
"Trigger mode", config_.ext_trig ?
"external" :
"internal");
906 stat.
add(
"Imager model", imager->getModel());
907 stat.
addf(
"Imager version",
"0x%04x", imager->getVersion());
937 double exposeEndTime = firstPacketTime - config_.first_packet_offset +
938 1 / config_.imager_rate -
939 1 / config_.trig_rate;
941 return exposeEndTime;
948 return firstPacketTime - config_.first_packet_offset;
970 boost::recursive_mutex::scoped_lock(diagnostics_lock_);
972 if (state_ != RUNNING)
975 if (frame_info == NULL)
977 boost::recursive_mutex::scoped_lock lock(mutex_);
980 if (config_.ext_trig && !trigger_matcher_.
hasTimestamp())
982 const char *
msg =
"More than one second elapsed without receiving any trigger. Is this normal?";
983 if (no_timestamp_warning_filter_.
badFrame())
994 setStatusMessagef(
"No data have arrived for more than one second. Assuming that camera is no longer streaming.");
998 no_timestamp_warning_filter_.
goodFrame();
1003 setStatusMessage(
"Camera streaming.");
1005 first_frame_ =
false;
1007 double firstPacketTime = frame_info->
startTime.tv_sec + frame_info->
startTime.tv_usec / 1e6;
1011 double firstPacketTimeFiltered = fabs(frame_time_filter_.
run(firstPacketTime, frame_info->
frame_number));
1018 if (!config_.ext_trig || config_.trig_timestamp_topic.empty())
1023 double triggerTimeGuess = firstPacketTimeFiltered - config_.first_packet_offset;
1044 int16_t frame_delta = (frame_info->
frame_number - last_partial_frame_number_) & 0xFFFF;
1046 if (frame_delta > 1)
1048 dropped_packet_event_ =
true;
1049 ROS_DEBUG_NAMED(
"dropped_frame",
"Some frames were never seen. The dropped packet count will be incorrect.");
1050 massive_frame_losses_++;
1054 if (frame_info->
eofInfo == NULL) {
1055 missed_eof_count_++;
1057 dropped_packet_event_ =
true;
1064 missed_line_count_++;
1066 dropped_packet_event_ =
true;
1074 trigger_matcher_drop_count_++;
1081 trigger_matcher_drop_count_++;
1086 last_image_time_ = imageTime.toSec();
1091 bool alternate = next_is_alternate_;
1092 next_is_alternate_ = enable_alternate_ && (!enable_primary_ || (frame_info->
eofInfo->
i2c[0] & 0x8000));
1094 return useFrame_(frame_info->
width, frame_info->
height, frame_info->
frameData, imageTime, alternate);
1099 return imager_->getModel() ==
"MT9V032";
1115 for (
int i = 0; i < words; i++)
1116 sum += htons(data[i]);
1117 return htons(0xFFFF - sum);
1128 ROS_WARN(
"Error reading camera intrinsics from flash.\n");
1132 uint16_t chk = intrinsicsChecksum((uint16_t *) &calbuff[0], calbuff.length() / 2);
1135 ROS_WARN_NAMED(
"no_intrinsics",
"Camera intrinsics have a bad checksum. They have probably never been set.");
1142 if (success && (cam_info.width != (
unsigned int) config_.width || cam_info.height != (
unsigned int) config_.height)) {
1143 ROS_ERROR(
"Image resolution from intrinsics file does not match current video setting, " 1144 "intrinsics expect %ix%i but running at %ix%i", cam_info.width, cam_info.height, config_.width, config_.height);
1148 ROS_ERROR(
"Could not parse camera intrinsics downloaded from camera.");
1157 std::stringstream inifile;
1163 *chk = intrinsicsChecksum((uint16_t *) calbuff,
sizeof(calbuff) / 2);
1165 ROS_INFO(
"Writing camera info:\n%s", calbuff);
1167 boost::recursive_mutex::scoped_lock lock_(mutex_);
1173 if (state_ != OPENED)
1174 ROS_ERROR(
"Error putting camera into OPENED state to write to flash.\n");
1177 ROS_ERROR(
"Error writing camera intrinsics to flash.\n");
1180 ROS_INFO(
"Camera_info successfully written to camera.");
1189 bool boardConfig(wge100_camera::BoardConfig::Request &
req, wge100_camera::BoardConfig::Response &rsp)
1191 if (state_ != RUNNING)
1193 ROS_ERROR(
"board_config sevice called while camera was not running. To avoid programming the wrong camera, board_config can only be called while viewing the camera stream.");
1199 if (req.mac.size() != 6)
1201 ROS_ERROR(
"board_config service called with %zu bytes in MAC. Should be 6.", req.mac.size());
1205 for (
int i = 0; i < 6; i++)
1206 mac[i] = req.mac[i];
1207 ROS_INFO(
"board_config called s/n #%i, and MAC %02x:%02x:%02x:%02x:%02x:%02x.", req.serial, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
1212 ROS_INFO(
"board_config succeeded.");
1226 camera_node_handle_(nh.resolveName(
"camera")),
1227 camera_node_handle_alt_(nh.resolveName(
"camera_alternate")),
1228 cam_pub_diag_(cam_pub_.getTopic(),
1230 diagnostic_updater::FrequencyStatusParam(&driver_.desired_freq_, &driver_.desired_freq_, 0.05),
1232 config_bord_service_(private_node_handle_.advertiseService(
"board_config", &
WGE100CameraDriver::boardConfig, &driver_)),
1233 set_camera_info_service_(camera_node_handle_.advertiseService(
"set_camera_info", &
WGE100CameraNode::setCameraInfo, this)),
1240 std::string topic = camera_node_handle_.resolveName(
"image_raw");
1241 std::string alt_topic = camera_node_handle_alt_.resolveName(
"image_raw");
1244 if (topic == alt_topic)
1245 cam_pub_alt_ = cam_pub_;
1275 fillImage(image_, driver_.image_encoding_, height, width, width, frameData);
1278 (alternate ? cam_pub_alt_ : cam_pub_).publish(image_, camera_info_, t);
1279 cam_pub_diag_.
tick(t);
1286 ROS_DEBUG(
"WGE100CameraNode::reconfigureHook called at level %x", level);
1288 image_.header.frame_id = driver_.config_.frame_id;
1289 camera_info_.header.frame_id = driver_.config_.frame_id;
1295 calibrated_ = driver_.loadIntrinsics(camera_info_);
1297 ROS_INFO(
"Loaded intrinsics from camera.");
1300 ROS_WARN_NAMED(
"no_intrinsics",
"Failed to load intrinsics from camera");
1301 camera_info_ = sensor_msgs::CameraInfo();
1302 camera_info_.width = driver_.config_.width;
1303 camera_info_.height = driver_.config_.height;
1306 if (driver_.config_.ext_trig && !driver_.config_.trig_timestamp_topic.empty())
1309 trigger_sub_ = node_handle_.subscribe(driver_.config_.trig_timestamp_topic, 100, cb, &driver_.trigger_matcher_);
1314 diagnostic_.setHardwareID(driver_.getID());
1320 driver_status_diagnostic_.addTask(&wge100_diagnostic_task_);
1328 bool setCameraInfo(sensor_msgs::SetCameraInfo::Request &
req, sensor_msgs::SetCameraInfo::Response &rsp)
1330 sensor_msgs::CameraInfo &cam_info = req.camera_info;
1334 ROS_ERROR(
"set_camera_info service called while camera was not running. To avoid programming the wrong camera, set_camera_info can only be called while viewing the camera stream.");
1335 rsp.status_message =
"Camera not running. Camera must be running to avoid setting the intrinsics of the wrong camera.";
1336 rsp.success =
false;
1340 if ((cam_info.width != (
unsigned int) driver_.config_.width || cam_info.height != (
unsigned int) driver_.config_.height)) {
1341 ROS_ERROR(
"Image resolution of camera_info passed to set_camera_info service does not match current video setting, " 1342 "camera_info contains %ix%i but camera running at %ix%i", cam_info.width, cam_info.height, driver_.config_.width, driver_.config_.height);
1343 rsp.status_message = (boost::format(
"Camera_info resolution %ix%i does not match camera resolution %ix%i.")%cam_info.width%cam_info.height%driver_.config_.width%driver_.config_.height).str();
1344 rsp.success =
false;
1347 rsp.success = driver_.saveIntrinsics(cam_info);
1349 rsp.status_message =
"Error writing camera_info to flash.";
1360 ROS_DEBUG(
"Adding wge100 camera video mode tests.");
1366 self_test_.add( str(boost::format(
"Test Pattern in mode %s")%
MT9VModes[i].name), f );
1373 for (
int i = 0; i < 10; i++)
1378 cam_pub_diag_.
run(status);
1396 status_.add(
"Got a frame",
"Pass");
1398 bool final = frame_count_++ > 10;
1410 ROS_WARN(
"Unexpected imager_id, autodetecting test pattern for this camera.");
1415 for (
size_t y = 0; y <
height; y++)
1416 for (
size_t x = 0; x <
width; x++, data++)
1422 msg = check_expected(x, y, *data,
final, mode);
1436 ROS_WARN(
"Pattern mismatch, retrying...");
1440 status_.summary(2, msg);
1441 status_.add(
"Frame content", msg);
1447 status_.addf(
"Frame content",
"Pass");
1455 #define NUM_TEST_PATTERNS 3 1459 col[0] = (x + 2 * y + 25) / 4;
1460 if ((x + 1) / 2 + y < 500)
1461 col[1] = 14 + x / 4;
1464 col[2] = (x + 2 * y + 43) / 4;
1470 if (col[mode] == actual_col)
1473 msg = (boost::format(
"Unexpected value %u instead of %u at (x=%u, y=%u)")%(int)actual_col%(
int)col[mode]%x%y).str();
1478 if (col[i] == actual_col)
1484 msg = (boost::format(
"Unexpected value in first pixel %u, expected: %u, %u or %u")%(int)actual_col%(
int)col[0]%(int)col[1]%(
int)col[2]).str();
1499 ROS_ERROR(
"Tried to call videoModeTest with out of range mode %u.", mode);
1503 const Config old_config = driver_.config_;
1506 Config new_config = driver_.config_;
1509 new_config.x_offset = 0;
1510 new_config.y_offset = 0;
1512 new_config.ext_trig = 0;
1513 new_config.register_set = wge100_camera::WGE100Camera_PrimaryRegisterSet;
1514 new_config.test_pattern =
true;
1515 driver_.config_update(new_config);
1518 driver_.useFrame_ = boost::bind(&VideoModeTestFrameHandler::run, boost::ref(callback), _1, _2, _3, _4, _5);
1520 status.name = (boost::format(
"Pattern Test: %ix%i at %.1f fps.")%new_config.width%new_config.height%new_config.imager_rate).str();
1523 int oldcount = driver_.lost_image_thread_count_;
1524 for (
int i = 0; i < 50 && !callback.got_frame_; i++)
1530 if (!callback.got_frame_)
1532 ROS_ERROR(
"Got no frame during pattern test.");
1533 status.
summary(2,
"Got no frame during pattern test.");
1535 if (oldcount < driver_.lost_image_thread_count_)
1537 ROS_ERROR(
"Lost the image_thread. This should never happen.");
1538 status.
summary(2,
"Lost the image_thread. This should never happen.");
1541 driver_.useFrame_ = oldUseFrame;
1542 driver_.config_update(old_config);
1544 ROS_INFO(
"Exiting test %s with status %i: %s", status.name.c_str(), status.level, status.message.c_str());
1550 return driver_base::main<WGE100CameraNode>(argc, argv,
"wge100_camera");
virtual void addStoppedTests()
image_transport::CameraPublisher cam_pub_alt_
int wge100IpGetLocalAddr(const char *ifName, struct in_addr *addr)
bool boardConfig(wge100_camera::BoardConfig::Request &req, wge100_camera::BoardConfig::Response &rsp)
virtual bool setBlackLevel(bool manual_override, int calibration_value, int step_size, int filter_length)=0
double run(double in_time, int frame_number)
MT9VImagerPtr alternate_imager_
boost::function< int(size_t, size_t, uint8_t *, ros::Time, bool)> UseFrameFunction
char hwinfo[WGE100_CAMINFO_LEN]
virtual bool setBrightness(int brightness)=0
virtual bool setGain(int gain)=0
int massive_frame_losses_
ros::NodeHandle camera_node_handle_
static const state_t RUNNING
int publishImage(size_t width, size_t height, uint8_t *frameData, ros::Time t, bool alternate)
const struct MT9VMode MT9VModes[MT9V_NUM_MODES]
#define ROS_WARN_NAMED(name,...)
int frameHandler(wge100FrameInfo *frame_info)
virtual void reconfigureHook(int level)
void summary(unsigned char lvl, const std::string s)
diagnostic_updater::TopicDiagnostic cam_pub_diag_
int wge100ReliableFlashRead(const IpCamList *camInfo, uint32_t address, uint8_t *pageDataOut, int *retries)
int wge100ReliableFlashWrite(const IpCamList *camInfo, uint32_t address, const uint8_t *pageDataIn, int *retries)
int black_level_filter_length
double late_locked_threshold_
ros::Subscriber trigger_sub_
void videoModeTest(int mode, diagnostic_updater::DiagnosticStatusWrapper &status)
#define TRIG_STATE_INTERNAL
bool setCameraInfo(sensor_msgs::SetCameraInfo::Request &req, sensor_msgs::SetCameraInfo::Response &rsp)
int wge100Configure(IpCamList *camInfo, const char *ipAddress, unsigned wait_us)
SlowTriggerFilter no_timestamp_warning_filter_
ros::ServiceClient trig_service_
int wge100ReliableSensorRead(const IpCamList *camInfo, uint8_t reg, uint16_t *data, int *retries)
WGE100CameraNode(ros::NodeHandle &nh)
bool writeCalibrationIni(std::ostream &out, const std::string &camera_name, const sensor_msgs::CameraInfo &cam_info)
virtual void addRunningTests()
uint16_t intrinsicsChecksum(uint16_t *data, int words)
bool loadIntrinsics(sensor_msgs::CameraInfo &cam_info)
FrameTimeFilter(double frame_rate=1., double late_locked_threshold=1e-3, double early_locked_threshold=3e-3, int early_recovery_frames=5, int max_recovery_frames=10, double max_skew=1.001, double max_skipped_frames=100)
VideoModeTestFrameHandler(diagnostic_updater::DiagnosticStatusWrapper &status, int imager_id)
ros::ServiceServer config_bord_service_
diagnostic_updater::FunctionDiagnosticTask wge100_diagnostic_task_
int wge100ReliableSensorWrite(const IpCamList *camInfo, uint8_t reg, uint16_t data, int *retries)
bool parseCalibration(const std::string &buffer, const std::string &format, std::string &camera_name, sensor_msgs::CameraInfo &cam_info)
double getFreeRunningFrameTime(double firstPacketTime)
void addf(const std::string &key, const char *format,...)
unsigned int last_frame_number_
void cameraStatus(diagnostic_updater::DiagnosticStatusWrapper &stat)
#define RMEM_MAX_RECOMMENDED
virtual bool setMirror(bool mirrorx, bool mirrory)=0
void summaryf(unsigned char lvl, const char *format,...)
virtual bool setExposure(double exposure)=0
int wge100FindByUrl(const char *url, IpCamList *camera, unsigned wait_us, const char **errmsg)
UseFrameFunction useFrame_
virtual void addOpenedTests()
#define ROS_DEBUG_NAMED(name,...)
int wge100VidReceiveAuto(IpCamList *camera, size_t height, size_t width, FrameHandler frameHandler, void *userData)
#define IMAGER_LINENO_OVF
Flags this video packet as being an Overflow packet.
CameraPublisher advertiseCamera(const std::string &base_topic, uint32_t queue_size, bool latch=false)
#define NUM_TEST_PATTERNS
virtual bool setAgcAec(bool agc_on, bool aec_on)=0
SlowTriggerFilter(int before_warn, int before_clear)
int wge100TriggerControl(const IpCamList *camInfo, uint32_t triggerType)
void config_update(const Config &new_cfg, uint32_t level=0)
static int frameHandler(wge100FrameInfo *frameInfo, void *userData)
ros::ServiceServer set_camera_info_service_
int main(int argc, char **argv)
unsigned int last_partial_frame_number_
double last_camera_ok_time_
ros::NodeHandle camera_node_handle_alt_
int wge100ImagerSetRes(const IpCamList *camInfo, uint16_t horizontal, uint16_t vertical)
int wge100EthGetLocalMac(const char *ifName, struct sockaddr *macAddr)
virtual void addDiagnostics()
sensor_msgs::Image image_
std::ostream & operator<<(std::ostream &out, const SimpleMatrix &m)
sensor_msgs::CameraInfo camera_info_
int setTestMode(uint16_t mode, diagnostic_updater::DiagnosticStatusWrapper &status)
const std::string BAYER_BGGR8
#define TRIG_STATE_EXTERNAL
char cam_name[CAMERA_NAME_LEN]
virtual bool setCompanding(bool activated)=0
int early_recovery_frames_
int black_level_step_size
void streamingTest(diagnostic_updater::DiagnosticStatusWrapper &status)
int setImagerSettings(MT9VImager &imager, ImagerSettings &cfg)
double getTriggeredFrameTime(double firstPacketTime)
#define IMAGER_LINENO_ERR
Flags this video packet as being a General Error packet.
#define TRIG_STATE_RISING
static MT9VImagerPtr getInstance(IpCamList &cam)
boost::function< void(DiagnosticStatusWrapper &)> TaskFunction
diagnostic_updater::DiagnosticStatusWrapper & status_
#define ROS_INFO_COND(cond,...)
int wge100ConfigureBoard(const IpCamList *camInfo, uint32_t serial, MACAddress *mac)
double early_locked_threshold_
int run(size_t width, size_t height, uint8_t *data, ros::Time stamp, bool alternate)
FrameTimeFilter frame_time_filter_
wge100_camera::WGE100CameraConfig Config
image_transport::CameraPublisher cam_pub_
virtual void run(DiagnosticStatusWrapper &stat)
std::string image_encoding_
std::string check_expected(int x, int y, uint8_t actual_col, bool final, int &mode)
void add(const std::string &key, const T &val)
virtual bool setMaxExposure(double exposure)=0
uint16_t i2c[I2C_REGS_PER_FRAME]
Storage for I2C values read during the frame.
bool saveIntrinsics(const sensor_msgs::CameraInfo &cam_info)
double driver_start_time_
int lost_image_thread_count_
double getExternallyTriggeredFrameTime(double firstPacketTime)
SimpleMatrix(int rows, int cols, const double *data)
virtual bool setMode(int x, int y, int binx, int biny, double rate, int xoffset, int yoffset)=0
boost::shared_ptr< boost::thread > image_thread_
bool dropped_packet_event_
#define FLASH_CALIBRATION_PAGENO
int trigger_matcher_drop_count_
#define TRIG_STATE_ALTERNATE
timestamp_tools::TriggerMatcher trigger_matcher_
int wge100SensorSelect(const IpCamList *camInfo, uint8_t index, uint32_t reg)