VisionaryData.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2023 SICK AG, Waldkirch
3 //
4 // SPDX-License-Identifier: Unlicense
5 
6 #include "VisionaryData.h"
7 
8 #include <algorithm>
9 #include <cassert>
10 #include <cctype> // for tolower
11 #include <chrono>
12 #include <cmath>
13 #include <cstddef> // for size_t
14 #include <ctime>
15 #include <iostream>
16 #include <limits>
17 #include <sstream>
18 
19 namespace visionary {
20 
21 const float bad_point = std::numeric_limits<float>::quiet_NaN();
22 
24  : m_scaleZ(0.0f)
25  , m_changeCounter(0u)
26  , m_frameNum(0u)
27  , m_blobTimestamp(0u)
28  , m_preCalcCamInfoType(VisionaryData::UNKNOWN)
29 {
32 }
33 
35 
36 std::size_t VisionaryData::getItemLength(const std::string& dataType) const
37 {
38  std::string lcstr(dataType);
39  // Transform String to lower case String
40  std::transform(
41  lcstr.begin(), lcstr.end(), lcstr.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
42 
43  if (lcstr == "uint8")
44  {
45  return sizeof(std::uint8_t);
46  }
47  else if (lcstr == "uint16")
48  {
49  return sizeof(std::uint16_t);
50  }
51  else if (lcstr == "uint32")
52  {
53  return sizeof(std::uint32_t);
54  }
55  else if (lcstr == "uint64")
56  {
57  return sizeof(std::uint64_t);
58  }
59  return 0;
60 }
61 
63 {
64  assert(imgType != UNKNOWN); // Unknown image type for the point cloud transformation
66  {
67  std::cout << __FUNCTION__ << ": Invalid Image size" << std::endl;
68  }
71 
72  m_preCalcCamInfo.clear();
73  m_preCalcCamInfo.reserve(static_cast<size_t>(m_cameraParams.height * m_cameraParams.width));
74 
75  //-----------------------------------------------
76  // transform each pixel into Cartesian coordinates
77  for (int row = 0; row < m_cameraParams.height; row++)
78  {
79  double yp = (m_cameraParams.cy - row) / m_cameraParams.fy;
80  double yp2 = yp * yp;
81 
82  for (int col = 0; col < m_cameraParams.width; col++)
83  {
84  // we map from image coordinates with origin top left and x
85  // horizontal (right) and y vertical
86  // (downwards) to camera coordinates with origin in center and x
87  // to the left and y upwards (seen
88  // from the sensor position)
89  const double xp = (m_cameraParams.cx - col) / m_cameraParams.fx;
90 
91  // correct the camera distortion
92  const double r2 = xp * xp + yp2;
93  const double r4 = r2 * r2;
94  const double k = 1 + m_cameraParams.k1 * r2 + m_cameraParams.k2 * r4;
95 
96  // Undistorted direction vector of the point
97  const auto x = static_cast<float>(xp * k);
98  const auto y = static_cast<float>(yp * k);
99  const float z = 1.0f;
100  double s0 = 0;
101  if (RADIAL == imgType)
102  {
103  s0 = std::sqrt(x * x + y * y + z * z) * 1000;
104  }
105  else if (PLANAR == imgType)
106  {
107  s0 = 1000;
108  }
109  else
110  {
111  std::cout << "Unknown image type for the point cloud transformation" << std::endl;
112  assert(false);
113  }
114  PointXYZ point{};
115  point.x = static_cast<float>(x / s0);
116  point.y = static_cast<float>(y / s0);
117  point.z = static_cast<float>(z / s0);
118 
119  m_preCalcCamInfo.push_back(point);
120  }
121  }
122  m_preCalcCamInfoType = imgType;
123 }
124 
125 void VisionaryData::generatePointCloud(const std::vector<uint16_t>& map,
126  const ImageType& imgType,
127  std::vector<PointXYZ>& pointCloud)
128 {
129  // Calculate disortion data from XML metadata once.
130  if (m_preCalcCamInfoType != imgType)
131  {
132  preCalcCamInfo(imgType);
133  }
134  size_t cloudSize = map.size();
135  pointCloud.resize(cloudSize);
136 
137  const auto f2rc = static_cast<float>(m_cameraParams.f2rc / 1000.f); // PointCloud should be in [m] and not in [mm]
138 
139  const float pixelSizeZ = m_scaleZ;
140 
141  //-----------------------------------------------
142  // transform each pixel into Cartesian coordinates
143  auto itMap = map.begin();
144  auto itUndistorted = m_preCalcCamInfo.begin();
145  auto itPC = pointCloud.begin();
146  for (uint32_t i = 0; i < cloudSize; ++i, ++itPC, ++itMap, ++itUndistorted)
147  // for (std::vector<PointXYZ>::iterator itPC = pointCloud.begin(), itEnd = pointCloud.end(); itPC != itEnd; ++itPC,
148  // ++itMap, ++itUndistorted)
149  {
150  PointXYZ point{};
151  // If point is valid put it to point cloud
152  if (*itMap == 0 || *itMap == uint16_t(0xFFFF))
153  {
154  point.x = bad_point;
155  point.y = bad_point;
156  point.z = bad_point;
157  }
158  else
159  {
160  // calculate coordinates & store in point cloud vector
161  float distance = static_cast<float>((*itMap)) * pixelSizeZ;
162  point.x = itUndistorted->x * distance;
163  point.y = itUndistorted->y * distance;
164  point.z = itUndistorted->z * distance - f2rc;
165  }
166  *itPC = point;
167  }
168  return;
169 }
170 
171 void VisionaryData::transformPointCloud(std::vector<PointXYZ>& pointCloud) const
172 {
173  // turn cam 2 world translations from [m] to [mm]
174  const double tx = m_cameraParams.cam2worldMatrix[3] / 1000.;
175  const double ty = m_cameraParams.cam2worldMatrix[7] / 1000.;
176  const double tz = m_cameraParams.cam2worldMatrix[11] / 1000.;
177 
178  for (auto& it : pointCloud)
179  {
180  const double x = it.x;
181  const double y = it.y;
182  const double z = it.z;
183 
184  it.x = static_cast<float>(x * m_cameraParams.cam2worldMatrix[0] + y * m_cameraParams.cam2worldMatrix[1]
185  + z * m_cameraParams.cam2worldMatrix[2] + tx);
186  it.y = static_cast<float>(x * m_cameraParams.cam2worldMatrix[4] + y * m_cameraParams.cam2worldMatrix[5]
187  + z * m_cameraParams.cam2worldMatrix[6] + ty);
188  it.z = static_cast<float>(x * m_cameraParams.cam2worldMatrix[8] + y * m_cameraParams.cam2worldMatrix[9]
189  + z * m_cameraParams.cam2worldMatrix[10] + tz);
190  }
191 }
192 
194 {
195  return m_cameraParams.height;
196 }
197 
199 {
200  return m_cameraParams.width;
201 }
202 
204 {
205  return m_frameNum;
206 }
207 
209 {
210  return m_blobTimestamp;
211 }
212 
214 {
215  std::tm tm{};
216  tm.tm_sec = static_cast<int>((m_blobTimestamp & BITMASK_SECOND) >> 10);
217  tm.tm_min = static_cast<int>((m_blobTimestamp & BITMASK_MINUTE) >> 16);
218  tm.tm_hour = static_cast<int>((m_blobTimestamp & BITMASK_HOUR) >> 22);
219  tm.tm_mday = static_cast<int>((m_blobTimestamp & BITMASK_DAY) >> 38);
220  tm.tm_mon = static_cast<int>(((m_blobTimestamp & BITMASK_MONTH) >> 43) - 1u);
221  tm.tm_year = static_cast<int>(((m_blobTimestamp & BITMASK_YEAR) >> 47u) - 1900);
222  tm.tm_isdst = -1; // Use DST value from local time zone
223 #ifdef _WIN32
224  auto seconds{std::chrono::seconds{::_mkgmtime(&tm)}};
225 #else
226  auto seconds{std::chrono::seconds{::timegm(&tm)}};
227 #endif
228  const uint64_t timestamp =
229  static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(seconds).count())
231 
232  return timestamp;
233 }
234 
236 {
237  return m_cameraParams;
238 }
239 
240 } // namespace visionary
assert
Definition: mpl/assert.hpp:79
visionary::CameraParameters::fy
double fy
Definition: VisionaryData.h:27
visionary::PointXYZ::x
float x
Definition: PointXYZ.h:12
visionary::VisionaryData::UNKNOWN
@ UNKNOWN
Definition: VisionaryData.h:98
visionary::CameraParameters::cy
double cy
Definition: VisionaryData.h:27
visionary::VisionaryData::generatePointCloud
virtual void generatePointCloud(std::vector< PointXYZ > &pointCloud)=0
visionary
Definition: MD5.cpp:44
visionary::VisionaryData::getTimestamp
std::uint64_t getTimestamp() const
Definition: VisionaryData.cpp:208
visionary::VisionaryData::BITMASK_MILLISECOND
static constexpr std::uint64_t BITMASK_MILLISECOND
Definition: VisionaryData.h:160
visionary::VisionaryData::getTimestampMS
std::uint64_t getTimestampMS() const
Definition: VisionaryData.cpp:213
visionary::CameraParameters::fx
double fx
Camera Matrix.
Definition: VisionaryData.h:27
visionary::VisionaryData::getWidth
int getWidth() const
Definition: VisionaryData.cpp:198
visionary::VisionaryData::m_frameNum
std::uint_fast32_t m_frameNum
Definition: VisionaryData.h:131
visionary::bad_point
const float bad_point
Definition: VisionaryData.cpp:21
visionary::VisionaryData::getFrameNum
std::uint32_t getFrameNum() const
Definition: VisionaryData.cpp:203
visionary::VisionaryData::preCalcCamInfo
void preCalcCamInfo(const ImageType &type)
Definition: VisionaryData.cpp:62
f
f
visionary::VisionaryData::BITMASK_HOUR
static constexpr std::uint64_t BITMASK_HOUR
Definition: VisionaryData.h:154
visionary::VisionaryData::m_preCalcCamInfoType
ImageType m_preCalcCamInfoType
Definition: VisionaryData.h:139
visionary::PointXYZ
Definition: PointXYZ.h:10
visionary::VisionaryData::BITMASK_YEAR
static constexpr std::uint64_t BITMASK_YEAR
Definition: VisionaryData.h:148
VisionaryData.h
visionary::VisionaryData::getCameraParameters
const CameraParameters & getCameraParameters() const
Definition: VisionaryData.cpp:235
visionary::VisionaryData::~VisionaryData
virtual ~VisionaryData()
visionary::VisionaryData::getItemLength
std::size_t getItemLength(const std::string &dataType) const
Definition: VisionaryData.cpp:36
visionary::VisionaryData::PLANAR
@ PLANAR
Definition: VisionaryData.h:99
visionary::VisionaryData::VisionaryData
VisionaryData()
Definition: VisionaryData.cpp:23
visionary::CameraParameters::cx
double cx
Definition: VisionaryData.h:27
visionary::CameraParameters::height
int height
The height of the frame in pixels.
Definition: VisionaryData.h:21
visionary::VisionaryData
Definition: VisionaryData.h:49
visionary::VisionaryData::m_scaleZ
float m_scaleZ
Factor to convert unit of distance image to mm.
Definition: VisionaryData.h:123
boost::iterators::i
D const & i
Definition: iterator_facade.hpp:956
visionary::CameraParameters::k2
double k2
Definition: VisionaryData.h:29
visionary::CameraParameters::width
int width
The width of the frame in pixels.
Definition: VisionaryData.h:23
visionary::VisionaryData::m_preCalcCamInfo
std::vector< PointXYZ > m_preCalcCamInfo
Definition: VisionaryData.h:141
visionary::VisionaryData::transformPointCloud
void transformPointCloud(std::vector< PointXYZ > &pointCloud) const
Definition: VisionaryData.cpp:171
visionary::VisionaryData::BITMASK_SECOND
static constexpr std::uint64_t BITMASK_SECOND
Definition: VisionaryData.h:158
visionary::CameraParameters::f2rc
double f2rc
FocalToRayCross - Correction Offset for depth info.
Definition: VisionaryData.h:31
visionary::VisionaryData::getHeight
int getHeight() const
Definition: VisionaryData.cpp:193
visionary::VisionaryData::m_cameraParams
CameraParameters m_cameraParams
Definition: VisionaryData.h:120
visionary::VisionaryData::BITMASK_MONTH
static constexpr std::uint64_t BITMASK_MONTH
Definition: VisionaryData.h:150
visionary::CameraParameters
Definition: VisionaryData.h:18
visionary::CameraParameters::cam2worldMatrix
double cam2worldMatrix[4 *4]
Camera to world transformation matrix.
Definition: VisionaryData.h:25
visionary::UNKNOWN
@ UNKNOWN
Definition: AuthenticationSecure.h:15
visionary::VisionaryData::BITMASK_DAY
static constexpr std::uint64_t BITMASK_DAY
Definition: VisionaryData.h:152
visionary::VisionaryData::BITMASK_MINUTE
static constexpr std::uint64_t BITMASK_MINUTE
Definition: VisionaryData.h:156
visionary::VisionaryData::RADIAL
@ RADIAL
Definition: VisionaryData.h:100
visionary::VisionaryData::m_blobTimestamp
std::uint64_t m_blobTimestamp
Definition: VisionaryData.h:135
visionary::CameraParameters::k1
double k1
Camera Distortion Parameters.
Definition: VisionaryData.h:29
visionary::VisionaryData::ImageType
ImageType
Definition: VisionaryData.h:96


sick_visionary_ros
Author(s): SICK AG TechSupport 3D Snapshot
autogenerated on Thu Feb 8 2024 03:56:19