8 const sensor_msgs::CameraInfoConstPtr& info_msg) {
17 fieldOfView(vert_min, vert_max, cx, 0, cx, cy, cx, depth_msg->height -1);
18 const double vertical_fov = vert_max - vert_min;
24 ROS_DEBUG_STREAM(
"Recalculate parameters because of camera model update. Parameters:\n" 26 <<
"\nvertical FOV: " << vertical_fov );
35 if (rmin >= 0 && rmin < rmax) {
40 ROS_ERROR(
"Incorrect value of range minimal parameter. Set default value: 0.");
42 if (rmax >= 0 && rmin < rmax) {
47 ROS_ERROR(
"Incorrect value of range maximum parameter. Set default value: 10.");
57 ROS_ERROR(
"Incorrect value of sensor mount height parameter. Set default value: 0.");
67 ROS_ERROR(
"Incorrect value of sensor mount height parameter. Set default value: 1m.");
72 if( angle < 90 && angle > -90) {
77 ROS_ERROR(
"Incorrect value of sensor tilt angle parameter. Set default value: 0.");
82 if( angle < 90 && angle > -90) {
87 ROS_ERROR(
"Incorrect value of sensor tilt angle parameter. Set default value: 0.");
97 ROS_ERROR(
"Incorrect value of used depth height parameter. Set default value: 200.");
107 ROS_ERROR(
"Incorrect value depth image row step parameter. Set default value: 1.");
117 ROS_ERROR(
"Incorrect value depth image column step parameter. Set default value: 1.");
126 return sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
130 const cv::Point3d& ray2)
const {
131 double dot = ray1.x*ray2.x + ray1.y*ray2.y + ray1.z*ray2.z;
137 double xc,
double yc,
double x2,
double y2) {
138 cv::Point2d raw_pixel_left(x1, y1);
142 cv::Point2d raw_pixel_right(x2, y2);
146 cv::Point2d raw_pixel_center(xc, yc);
161 for (
unsigned i = 0; i < img_height; i++) {
167 std::vector<double>& distances) {
168 const double alpha = tilt_angle * M_PI / 180.0;
171 ROS_ASSERT(img_height >= 0 && mount_height > 0);
173 distances.resize(img_height);
176 for(
unsigned i = 0; i < img_height; i++) {
190 pcl::PointCloud<pcl::PointXYZ>::Ptr& points,
191 std::list<std::pair<unsigned, unsigned>>& points_indices) {
192 enum Point { Row, Col, Depth };
194 #ifdef DEBUG_CALIBRATION 195 std::vector<double> deltaVec;
197 const unsigned img_height = depth_msg->height;
198 const unsigned img_width = depth_msg->width;
200 const T* data =
reinterpret_cast<const T*
>(&depth_msg->data[0]);
204 if (used_depth_height_ < img_height && used_depth_height_ > 0) {
214 if (
typeid(T) ==
typeid(uint16_t)) {
215 unsigned depth_raw_mm =
static_cast<unsigned>(data[img_width * row + col]);
216 d =
static_cast<float>(depth_raw_mm) / 1000.0;
218 else if (
typeid(T) ==
typeid(float)) {
219 d =
static_cast<float>(data[img_width * row + col]);
222 #ifdef DEBUG_CALIBRATION 223 std::ostringstream
s;
225 s <<
"GroundPoints point: (" << col <<
", " << row <<
") " 240 points->push_back(pcl::PointXYZ(x, y, z));
241 points_indices.push_back({row, col});
248 const sensor_msgs::ImageConstPtr& depth_msg,
249 [[maybe_unused]]
double& tilt_angle, [[maybe_unused]]
double& height) {
251 pcl::PointCloud<pcl::PointXYZ>::Ptr ground_points(
new pcl::PointCloud<pcl::PointXYZ>);
252 std::list<std::pair<unsigned, unsigned>> points_indices;
256 getGroundPoints<uint16_t>(depth_msg, ground_points, points_indices);
259 getGroundPoints<float>(depth_msg, ground_points, points_indices);
262 std::stringstream ss;
263 ss <<
"Depth image has unsupported encoding: " << depth_msg->encoding;
264 throw std::runtime_error(ss.str());
272 if (ground_points->size() >= 3) {
274 pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr
275 model(
new pcl::SampleConsensusModelPlane<pcl::PointXYZ>(ground_points));
277 pcl::RandomSampleConsensus<pcl::PointXYZ> ransac (model);
280 ransac.computeModel();
282 Eigen::VectorXf ground_coeffs(4);
283 ransac.getModelCoefficients(ground_coeffs);
286 float a = ground_coeffs[0], b = ground_coeffs[1];
287 float c = ground_coeffs[2],
d = ground_coeffs[3];
290 tilt_angle = std::acos ((b*b + a*a) / (std::sqrt(b*b + a*a) * std::sqrt(a*a+b*b+c*c))) * 180.0 / M_PI;
291 height = std::abs(d) / std::sqrt(a*a+b*b+c*c);
295 std::ostringstream
s;
296 s <<
" sensorLocationCalibration: ground_points size = " << ground_points->size()
297 <<
"\n a = " << ground_coeffs[0]
298 <<
"\n b = " << ground_coeffs[1]
299 <<
"\n c = " << ground_coeffs[2]
300 <<
"\n d = " << ground_coeffs[3]
301 <<
"\n height = " << height
302 <<
"\n tilt = " << tilt_angle;
306 ROS_ERROR(
"Ground points not detected. Please check parameters");
311 ROS_WARN(
"Estimated height (%.2f) not in range. Lowest value from range used instead of estimated.", height);
316 ROS_WARN(
"Estimated tilt angle (%.2f) not in range. Lowest value from range used instead of estimated.", tilt_angle);
321 const std::list<std::pair<unsigned, unsigned>>& ground_points_indices) {
323 sensor_msgs::ImagePtr img(
new sensor_msgs::Image);
324 img->header = depth_msg->header;
325 img->height = depth_msg->height;
326 img->width = depth_msg->width;
327 img->encoding =
"rgb8";
328 img->is_bigendian = depth_msg->is_bigendian;
329 img->step = img->width * 3;
331 img->data.resize(img->step * img->height);
332 uint8_t(*rgb_data)[3] =
reinterpret_cast<uint8_t(*)[3]
>(&img->data[0]);
336 const uint16_t* depth_data =
reinterpret_cast<const uint16_t*
>(&depth_msg->data[0]);
337 for (
unsigned i = 0; i < (img->width * img->height); ++i) {
340 rgb_data[i][0] = 255 - val;
341 rgb_data[i][1] = 255 - val;
342 rgb_data[i][2] = 255 - val;
346 const float* depth_data =
reinterpret_cast<const float*
>(&depth_msg->data[0]);
347 for (
unsigned i = 0; i < (img->width * img->height); ++i) {
350 rgb_data[i][0] = 255 - val;
351 rgb_data[i][1] = 255 - val;
352 rgb_data[i][2] = 255 - val;
356 throw std::runtime_error(
"Unsupported depth image encoding");
360 for (
const auto pt : ground_points_indices) {
361 const auto row = pt.first;
362 const auto col = pt.second;
363 rgb_data[row * img->width + col][0] = 255;
364 rgb_data[row * img->width + col][1] = 0;
365 rgb_data[row * img->width + col][2] = 0;
369 std::list<std::pair<unsigned, unsigned>> pts;
370 for (
unsigned i = 0; i < img->width; ++i) {
372 if (line_row >= 0 && line_row < img->height) {
373 pts.push_back({line_row, i});
377 for (
const auto pt : pts) {
378 const auto row = pt.first;
379 const auto col = pt.second;
380 rgb_data[row * img->width + col][0] = 0;
381 rgb_data[row * img->width + col][1] = 255;
382 rgb_data[row * img->width + col][2] = 0;
cv::Size fullResolution() const
#define ROS_DEBUG_STREAM_THROTTLE(rate, args)
void getGroundPoints(const sensor_msgs::ImageConstPtr &depth_msg, pcl::PointCloud< pcl::PointXYZ >::Ptr &points, std::list< std::pair< unsigned, unsigned >> &points_indices)
std::vector< double > delta_row_
float ransacDistanceThresh_
void setUsedDepthHeight(const unsigned height)
setUsedDepthHeight
std::vector< double > dist_to_ground_min_
std::vector< double > dist_to_ground_max_
float mount_height_min_
Min height of sensor mount from ground.
#define ROS_DEBUG_THROTTLE(rate,...)
cv::Point3d projectPixelTo3dRay(const cv::Point2d &uv_rect) const
float tilt_angle_min_
Min angle of sensor tilt in degrees.
image_geometry::PinholeCameraModel camera_model_
sensor_msgs::ImagePtr dbg_image_
void calcGroundDistancesForImgRows(double mount_height, double tilt_angle, std::vector< double > &distances)
Calculates distances to ground for every row of depth image.
float tilt_angle_max_
Max angle of sensor tilt in degrees.
bool cam_model_update_
Determines if continuously cam model update is required.
sensor_msgs::ImagePtr prepareDbgImage(const sensor_msgs::ImageConstPtr &depth_msg, const std::list< std::pair< unsigned, unsigned >> &ground_points_indices)
TFSIMD_FORCE_INLINE const tfScalar & y() const
doubleAcc dot(const VectorAcc &lhs, const VectorAcc &rhs)
void setRangeLimits(const float rmin, const float rmax)
void calcDeltaAngleForImgRows(double vertical_fov)
float range_min_
Stores the current minimum range to use.
unsigned depth_image_step_col_
Columns step in depth processing (px).
void fieldOfView(double &min, double &max, double x1, double y1, double xc, double yc, double x2, double y2)
bool fromCameraInfo(const sensor_msgs::CameraInfo &msg)
const std::string TYPE_32FC1
float mount_height_max_
Max height of sensor mount from ground.
sensor_msgs::ImageConstPtr getDbgImage() const
const std::string TYPE_16UC1
bool reconf_serv_params_updated_
double angleBetweenRays(const cv::Point3d &ray1, const cv::Point3d &ray2) const
void estimateParams(const sensor_msgs::ImageConstPtr &depth_msg, const sensor_msgs::CameraInfoConstPtr &info_msg)
TFSIMD_FORCE_INLINE const tfScalar & x() const
double lengthOfVector(const cv::Point3d &vec) const
void setSensorMountHeightMin(const float height)
setSensorMountHeight sets the height of sensor mount (in meters) from ground
cv::Point2d rectifyPoint(const cv::Point2d &uv_raw) const
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
void setDepthImgStepCol(const int step)
setDepthImgStepCol
#define ROS_DEBUG_STREAM(args)
TFSIMD_FORCE_INLINE const tfScalar & z() const
void setDepthImgStepRow(const int step)
setDepthImgStepRow
void sensorPoseCalibration(const sensor_msgs::ImageConstPtr &depth_msg, double &tilt_angle, double &height)
INLINE Rall1d< T, V, S > acos(const Rall1d< T, V, S > &x)
#define ROS_INFO_STREAM(args)
unsigned used_depth_height_
Used depth height from img bottom (px)
void setSensorTiltAngleMax(const float angle)
setSensorTiltAngle sets the sensor tilt angle (in degrees)
unsigned depth_image_step_row_
Rows step in depth processing (px).
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
void setSensorMountHeightMax(const float height)
setSensorMountHeight sets the height of sensor mount (in meters) from ground
float range_max_
Stores the current maximum range to use.
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
bool publish_depth_enable_
Determines if debug image should be published.
unsigned max_ground_points_
void setSensorTiltAngleMin(const float angle)
setSensorTiltAngle sets the sensor tilt angle (in degrees)