41 float computeAzimuth(
const float a,
const float b)
43 return a >= 0 ?
static_cast<float>(M_PI) - atan(b / (a + std::numeric_limits<float>::epsilon()))
44 : atan(b / -(a + std::numeric_limits<float>::epsilon()));
47 float computeRange(
const float a,
const float b)
49 return sqrt(pow(a, 2) + pow(b, 2));
52 template <
typename T> T computeQuadraticSurface(T x, T z,
const T* params)
58 return params[0] * pow(x, 2) + params[1] * pow(z, 2) + params[2] * x * z +
59 params[3] * x + params[4] * z + params[5];
62 Eigen::Matrix<Eigen::Matrix<float, Eigen::Dynamic, 1>, Eigen::Dynamic, 1> generateBasisArray()
64 Eigen::Matrix<Eigen::Matrix<float, Eigen::Dynamic, 1>, Eigen::Dynamic, 1> ret(4);
67 Eigen::Matrix<float, Eigen::Dynamic, 1> basisCoefficients(4);
77 basisCoefficients(0) = 1.0 / 6.0;
78 basisCoefficients(1) = -0.5;
79 basisCoefficients(2) = 0.5;
80 basisCoefficients(3) = -1.0 / 6.0;
81 ret(0) = basisCoefficients;
85 basisCoefficients(0) = 2.0 / 3.0;
86 basisCoefficients(1) = 0.0;
87 basisCoefficients(2) = -1.0;
88 basisCoefficients(3) = 0.5;
89 ret(1) = basisCoefficients;
93 basisCoefficients(0) = 1.0 / 6.0;
94 basisCoefficients(1) = 0.5;
95 basisCoefficients(2) = 0.5;
96 basisCoefficients(3) = -0.5;
97 ret(2) = basisCoefficients;
101 basisCoefficients(0) = 0.0;
102 basisCoefficients(1) = 0.0;
103 basisCoefficients(2) = 0.0;
104 basisCoefficients(3) = 1.0 / 6.0;
105 ret(3) = basisCoefficients;
110 template <
class FloatT>
111 FloatT getSplineValue(
112 const FloatT* xzCellOrigin,
113 const FloatT* xzCellSize,
116 const Eigen::Matrix<FloatT, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> &controlGrid,
117 const Eigen::Matrix<Eigen::Matrix<FloatT, Eigen::Dynamic, 1>, Eigen::Dynamic, 1> &basisArray)
120 FloatT iTmp = (sValue - xzCellOrigin[0]) / xzCellSize[0];
121 FloatT jTmp = (tValue - xzCellOrigin[1]) / xzCellSize[1];
123 int iCoord =
static_cast<int>(floor(iTmp));
124 int jCoord =
static_cast<int>(floor(jTmp));
129 powersOfS[0] = FloatT(1.0);
130 powersOfS[1] = iTmp - FloatT(iCoord);
131 powersOfS[2] = powersOfS[1] * powersOfS[1];
132 powersOfS[3] = powersOfS[2] * powersOfS[1];
134 powersOfT[0] = FloatT(1.0);
135 powersOfT[1] = jTmp - FloatT(jCoord);
136 powersOfT[2] = powersOfT[1] * powersOfT[1];
137 powersOfT[3] = powersOfT[2] * powersOfT[1];
139 size_t iIndex =
static_cast<size_t>(iCoord);
140 size_t jIndex =
static_cast<size_t>(jCoord);
143 int index0 = iIndex - 1;
144 int index1 = jIndex - 1;
145 FloatT functionValue = 0.0;
146 for (
size_t kIndex = 0; kIndex < 4; ++kIndex)
148 size_t i0PlusK = index0 + kIndex;
150 FloatT B_k = std::inner_product(
151 powersOfS, powersOfS + 4, (basisArray)[kIndex].
data(),
static_cast<FloatT
>(0));
153 for (
size_t lIndex = 0; lIndex < 4; ++lIndex)
155 size_t i1PlusL = index1 + lIndex;
157 FloatT B_l = std::inner_product(
158 powersOfT, powersOfT + 4, (basisArray)[lIndex].
data(),
static_cast<FloatT
>(0));
160 functionValue += (B_k * B_l * controlGrid(i1PlusL, i0PlusK));
163 return functionValue;
171 return Eigen::Matrix<uint8_t, 3, 1>{ 114, 159, 207 };
173 return Eigen::Matrix<uint8_t, 3, 1>{ 255, 0, 0 };
175 return Eigen::Matrix<uint8_t, 3, 1>{ 0, 255, 0 };
178 return Eigen::Matrix<uint8_t, 3, 1>{ 0, 0, 0 };
182 const std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>> &input,
183 const std::string &frame_id)
185 auto ret = multisense_ros::initializePointcloud<float, void>({},
192 for (
size_t i = 0; i < input.size(); ++i)
201 const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> &controlGrid,
203 const double pointcloudMaxRange,
204 const float* xzCellOrigin,
205 const float* xzCellSize,
206 const float* minMaxAzimuthAngle,
207 const float* extrinsics,
208 const float* quadraticParams,
209 const float baseline)
211 static const auto basisArray = generateBasisArray();
214 Eigen::Matrix<float, 4, 4> extrinsicsMat;
216 extrinsicsMat.setZero();
217 extrinsicsMat(0, 3) = extrinsics[0];
218 extrinsicsMat(1, 3) = extrinsics[1];
219 extrinsicsMat(2, 3) = extrinsics[2];
220 extrinsicsMat(3, 3) =
static_cast<float>(1.0);
221 Eigen::Matrix<float, 3, 3> rot =
222 (Eigen::AngleAxis<float>(extrinsics[5], Eigen::Matrix<float, 3, 1>(0, 0, 1))
223 * Eigen::AngleAxis<float>(extrinsics[4], Eigen::Matrix<float, 3, 1>(0, 1, 0))
224 * Eigen::AngleAxis<float>(extrinsics[3], Eigen::Matrix<float, 3, 1>(1, 0, 0))).matrix();
225 extrinsicsMat.block(0, 0, 3, 3) = rot;
229 const auto extrinsicsInverse = extrinsicsMat.inverse();
232 const size_t numPoints =
236 std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>> points;
237 points.reserve(numPoints);
244 const auto y = getSplineValue(xzCellOrigin, xzCellSize, x, z, controlGrid, basisArray)
245 + computeQuadraticSurface(x, z, quadraticParams);
247 const Eigen::Vector3f splinePoint = Eigen::Vector3f(x, y, z);
248 const Eigen::Vector3f transformedSplinePoint = (extrinsicsInverse * splinePoint.homogeneous()).hnormalized();
251 const auto distance = computeRange(transformedSplinePoint(0), transformedSplinePoint(2));
252 if (distance > pointcloudMaxRange)
255 const auto leftCamAzimuthAngle = computeAzimuth(transformedSplinePoint(0), transformedSplinePoint(2));
256 if (leftCamAzimuthAngle < minMaxAzimuthAngle[0])
260 const auto rightCamAzimuthAngle = computeAzimuth(transformedSplinePoint(0) + baseline, transformedSplinePoint(2));
261 if (rightCamAzimuthAngle > minMaxAzimuthAngle[1])
264 points.emplace_back(splinePoint);
268 points.shrink_to_fit();