40 float computeAzimuth(
const float a, 
const float b)
    42     return a >= 0 ? 
static_cast<float>(M_PI) - 
atan(b / (a + std::numeric_limits<float>::epsilon()))
    43                   : 
atan(b / -(a + std::numeric_limits<float>::epsilon()));
    46 float computeRange(
const float a, 
const float b)
    51 template <
typename T> T computeQuadraticSurface(T x, T z, 
const T* params)
    57     return params[0] * 
pow(x, 2) + params[1] * 
pow(z, 2) + params[2] * x * z +
    58            params[3] * x + params[4] * z + params[5];
    61 Eigen::Matrix<Eigen::Matrix<float, Eigen::Dynamic, 1>, Eigen::Dynamic, 1> generateBasisArray()
    63     Eigen::Matrix<Eigen::Matrix<float, Eigen::Dynamic, 1>, Eigen::Dynamic, 1> ret(4);
    66     Eigen::Matrix<float, Eigen::Dynamic, 1> basisCoefficients(4);
    76     basisCoefficients(0) = 1.0 / 6.0;
    77     basisCoefficients(1) = -0.5;
    78     basisCoefficients(2) = 0.5;
    79     basisCoefficients(3) = -1.0 / 6.0;
    80     ret(0) = basisCoefficients;
    84     basisCoefficients(0) = 2.0 / 3.0;
    85     basisCoefficients(1) = 0.0;
    86     basisCoefficients(2) = -1.0;
    87     basisCoefficients(3) = 0.5;
    88     ret(1) = basisCoefficients;
    92     basisCoefficients(0) = 1.0 / 6.0;
    93     basisCoefficients(1) = 0.5;
    94     basisCoefficients(2) = 0.5;
    95     basisCoefficients(3) = -0.5;
    96     ret(2) = basisCoefficients;
   100     basisCoefficients(0) = 0.0;
   101     basisCoefficients(1) = 0.0;
   102     basisCoefficients(2) = 0.0;
   103     basisCoefficients(3) = 1.0 / 6.0;
   104     ret(3) = basisCoefficients;
   109 template <
class FloatT>
   110 FloatT getSplineValue(
   111     const FloatT* xzCellOrigin,
   112     const FloatT* xzCellSize,
   115     const Eigen::Matrix<FloatT, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> &controlGrid,
   116     const Eigen::Matrix<Eigen::Matrix<FloatT, Eigen::Dynamic, 1>, Eigen::Dynamic, 1> &basisArray)
   119     FloatT iTmp = (sValue - xzCellOrigin[0]) / xzCellSize[0];
   120     FloatT jTmp = (tValue - xzCellOrigin[1]) / xzCellSize[1];
   122     int iCoord = 
static_cast<int>(floor(iTmp));
   123     int jCoord = 
static_cast<int>(floor(jTmp));
   128     powersOfS[0] = FloatT(1.0);
   129     powersOfS[1] = iTmp - FloatT(iCoord);
   130     powersOfS[2] = powersOfS[1] * powersOfS[1];
   131     powersOfS[3] = powersOfS[2] * powersOfS[1];
   133     powersOfT[0] = FloatT(1.0);
   134     powersOfT[1] = jTmp - FloatT(jCoord);
   135     powersOfT[2] = powersOfT[1] * powersOfT[1];
   136     powersOfT[3] = powersOfT[2] * powersOfT[1];
   138     size_t iIndex = 
static_cast<size_t>(iCoord);
   139     size_t jIndex = 
static_cast<size_t>(jCoord);
   142     int index0 = iIndex - 1;
   143     int index1 = jIndex - 1;
   144     FloatT functionValue = 0.0;
   145     for (
size_t kIndex = 0; kIndex < 4; ++kIndex)
   147         size_t i0PlusK = index0 + kIndex;
   149         FloatT B_k = std::inner_product(
   150             powersOfS, powersOfS + 4, (basisArray)[kIndex].
data(), static_cast<FloatT>(0));
   152         for (
size_t lIndex = 0; lIndex < 4; ++lIndex)
   154             size_t i1PlusL = index1 + lIndex;
   156             FloatT B_l = std::inner_product(
   157                 powersOfT, powersOfT + 4, (basisArray)[lIndex].
data(), static_cast<FloatT>(0));
   159             functionValue += (B_k * B_l * controlGrid(i1PlusL, i0PlusK));
   162     return functionValue;
   170         return Eigen::Matrix<uint8_t, 3, 1>{ 114, 159, 207 };
   172         return Eigen::Matrix<uint8_t, 3, 1>{ 255, 0, 0 };
   174         return Eigen::Matrix<uint8_t, 3, 1>{ 0, 255, 0 };
   177     return Eigen::Matrix<uint8_t, 3, 1>{ 0, 0, 0 };
   181     const std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>> &input,
   182     const std::string &frame_id)
   184     sensor_msgs::PointCloud2 ret =
   185         multisense_ros::initialize_pointcloud<float>(
true, frame_id, 
"intensity");
   187     const double num_points = input.size();
   188     ret.data.resize(num_points * ret.point_step);
   190     for (
size_t i = 0; i < num_points; ++i)
   192         float* cloudP = 
reinterpret_cast<float*
>(&(ret.data[i * ret.point_step]));
   193         cloudP[0] = input[i][0];
   194         cloudP[1] = input[i][1];
   195         cloudP[2] = input[i][2];
   199     ret.row_step = num_points * ret.point_step;
   200     ret.width = num_points;
   201     ret.data.resize(num_points * ret.point_step);
   207     const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> &controlGrid,
   209     const double pointcloudMaxRange,
   210     const float* xzCellOrigin,
   211     const float* xzCellSize,
   212     const float* minMaxAzimuthAngle,
   213     const float* extrinsics,
   214     const float* quadraticParams,
   215     const float baseline)
   217     static const auto basisArray = generateBasisArray();
   220     Eigen::Matrix<float, 4, 4> extrinsicsMat;
   222         extrinsicsMat.setZero();
   223         extrinsicsMat(0, 3) = extrinsics[0];
   224         extrinsicsMat(1, 3) = extrinsics[1];
   225         extrinsicsMat(2, 3) = extrinsics[2];
   226         extrinsicsMat(3, 3) = 
static_cast<float>(1.0);
   227         Eigen::Matrix<float, 3, 3> rot =
   228             (Eigen::AngleAxis<float>(extrinsics[5], Eigen::Matrix<float, 3, 1>(0, 0, 1))
   229             * Eigen::AngleAxis<float>(extrinsics[4], Eigen::Matrix<float, 3, 1>(0, 1, 0))
   230             * Eigen::AngleAxis<float>(extrinsics[3], Eigen::Matrix<float, 3, 1>(1, 0, 0))).matrix();
   231         extrinsicsMat.block(0, 0, 3, 3) = rot;
   235     const auto extrinsicsInverse = extrinsicsMat.inverse();
   238     const size_t numPoints =
   242     std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>> points;
   243     points.reserve(numPoints);
   250             const auto y = getSplineValue(xzCellOrigin, xzCellSize, x, z, controlGrid, basisArray)
   251                            + computeQuadraticSurface(x, z, quadraticParams);
   253             const Eigen::Vector3f splinePoint = Eigen::Vector3f(x, y, z);
   254             const Eigen::Vector3f transformedSplinePoint = (extrinsicsInverse * splinePoint.homogeneous()).hnormalized();
   257             const auto distance = computeRange(transformedSplinePoint(0), transformedSplinePoint(2));
   258             if (distance > pointcloudMaxRange)
   261             const auto leftCamAzimuthAngle = computeAzimuth(transformedSplinePoint(0), transformedSplinePoint(2));
   262             if (leftCamAzimuthAngle < minMaxAzimuthAngle[0])
   266             const auto rightCamAzimuthAngle = computeAzimuth(transformedSplinePoint(0) + baseline, transformedSplinePoint(2));
   267             if (rightCamAzimuthAngle > minMaxAzimuthAngle[1])
   270             points.emplace_back(splinePoint);
   274     points.shrink_to_fit();
 
double max_z_m
The max range (along the z dimension / optical axis) to draw the B-spline model. 
INLINE Rall1d< T, V, S > atan(const Rall1d< T, V, S > &x)
double max_x_m
The max width (along the x dimension) to draw the B-spline model. 
Struct containing parameters for drawing a pointcloud representation of a B-Spline model...
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
sensor_msgs::PointCloud2 eigenToPointcloud(const std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f >> &input, const std::string &frame_id)
Convert an eigen representation of a pointcloud to a ROS sensor_msgs::PointCloud2 format...
Eigen::Matrix< uint8_t, 3, 1 > groundSurfaceClassToPixelColor(const uint8_t value)
Look up table to convert a ground surface class value into into a color for visualization (out-of-bou...
double min_x_m
The min width (along the x dimension) to draw the B-spline model. 
double resolution
The resolution to sample the B-Spline model for drawing. 
double min_z_m
The min range (along the z dimension / optical axis) to draw the B-spline model. 
std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f > > convertSplineToPointcloud(const Eigen::Matrix< float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > &controlGrid, const SplineDrawParameters &splineDrawParams, const double pointcloudMaxRange, const float *xzCellOrigin, const float *xzCellSize, const float *minMaxAzimuthAngle, const float *extrinsics, const float *quadraticParams, const float baseline)
Generate a pointcloud representation of a b-spline ground surface model for visualization.