52 const size_t N = in_correspondences.size();
54 if (N < 2)
return false;
56 const float N_inv = 1.0f / N;
81 __m128 sum_a_xyz = _mm_setzero_ps();
82 __m128 sum_b_xyz = _mm_setzero_ps();
86 __m128 sum_ab_xyz = _mm_setzero_ps();
88 for (
const auto& in_correspondence : in_correspondences)
98 _mm_loadu_ps(&in_correspondence.this_x);
100 _mm_loadu_ps(&in_correspondence.other_x);
103 _mm_shuffle_ps(a_xyz, a_xyz, _MM_SHUFFLE(1, 0, 1, 0));
105 _mm_shuffle_ps(b_xyz, b_xyz, _MM_SHUFFLE(0, 1, 1, 0));
108 sum_a_xyz = _mm_add_ps(sum_a_xyz, a_xyz);
109 sum_b_xyz = _mm_add_ps(sum_b_xyz, b_xyz);
113 sum_ab_xyz = _mm_add_ps(sum_ab_xyz, _mm_mul_ps(a_xyxy, b_xyyx));
116 alignas(MRPT_MAX_STATIC_ALIGN_BYTES)
float sums_a[4], sums_b[4];
117 _mm_store_ps(sums_a, sum_a_xyz);
118 _mm_store_ps(sums_b, sum_b_xyz);
120 float SumXa = sums_a[0];
121 float SumYa = sums_a[1];
122 float SumXb = sums_b[0];
123 float SumYb = sums_b[1];
126 const __m128 Ninv_4val =
128 sum_a_xyz = _mm_mul_ps(sum_a_xyz, Ninv_4val);
129 sum_b_xyz = _mm_mul_ps(sum_b_xyz, Ninv_4val);
135 alignas(MRPT_MAX_STATIC_ALIGN_BYTES)
float means_a[4], means_b[4];
136 _mm_store_ps(means_a, sum_a_xyz);
137 _mm_store_ps(means_b, sum_b_xyz);
139 float mean_x_a = means_a[0];
140 float mean_y_a = means_a[1];
141 float mean_x_b = means_b[0];
142 float mean_y_b = means_b[1];
146 alignas(MRPT_MAX_STATIC_ALIGN_BYTES)
float cross_sums[4];
147 _mm_store_ps(cross_sums, sum_ab_xyz);
149 float Sxx = cross_sums[0];
150 float Syy = cross_sums[1];
151 float Sxy = cross_sums[2];
152 float Syx = cross_sums[3];
155 const float Ax = N * (Sxx + Syy) - SumXa * SumXb - SumYa * SumYb;
156 const float Ay = SumXa * SumYb + N * (Syx - Sxy) - SumXb * SumYa;
160 float SumXa = 0, SumXb = 0, SumYa = 0, SumYb = 0;
161 float Sxx = 0, Sxy = 0, Syx = 0, Syy = 0;
163 for (TMatchingPairList::const_iterator corrIt = in_correspondences.begin();
164 corrIt != in_correspondences.end(); corrIt++)
167 const float xa = corrIt->this_x;
168 const float ya = corrIt->this_y;
169 const float xb = corrIt->other_x;
170 const float yb = corrIt->other_y;
185 const float mean_x_a = SumXa * N_inv;
186 const float mean_y_a = SumYa * N_inv;
187 const float mean_x_b = SumXb * N_inv;
188 const float mean_y_b = SumYb * N_inv;
191 const float Ax = N * (Sxx + Syy) - SumXa * SumXb - SumYa * SumYb;
192 const float Ay = SumXa * SumYb + N * (Syx - Sxy) - SumXb * SumYa;
196 out_transformation.
phi =
198 ? atan2(static_cast<double>(Ay),
static_cast<double>(Ax))
201 const double ccos = cos(out_transformation.
phi);
202 const double csin = sin(out_transformation.
phi);
204 out_transformation.
x = mean_x_a - mean_x_b * ccos + mean_y_b * csin;
205 out_transformation.
y = mean_y_a - mean_x_b * csin - mean_y_b * ccos;
207 if (out_estimateCovariance)
213 double var_x_a = 0, var_y_a = 0, var_x_b = 0, var_y_b = 0;
214 const double N_1_inv = 1.0 / (N - 1);
218 for (
const auto& in_correspondence : in_correspondences)
220 var_x_a +=
square(in_correspondence.this_x - mean_x_a);
221 var_y_a +=
square(in_correspondence.this_y - mean_y_a);
222 var_x_b +=
square(in_correspondence.other_x - mean_x_b);
223 var_y_b +=
square(in_correspondence.other_y - mean_y_b);
232 const double BETA = (var_x_a + var_y_a + var_x_b + var_y_b) *
233 pow(static_cast<double>(N), 2.0) *
234 static_cast<double>(N - 1);
243 2.0 * N_inv + BETA *
square((mean_x_b * Ay + mean_y_b * Ax) / D);
245 2.0 * N_inv + BETA *
square((mean_x_b * Ax - mean_y_b * Ay) / D);
246 (*C)(2, 2) = BETA / D;
248 (*C)(0, 1) = (*C)(1, 0) = -BETA * (mean_x_b * Ay + mean_y_b * Ax) *
249 (mean_x_b * Ax - mean_y_b * Ay) /
square(D);
251 (*C)(0, 2) = (*C)(2, 0) =
252 BETA * (mean_x_b * Ay + mean_y_b * Ax) / pow(D, 1.5);
254 (*C)(1, 2) = (*C)(2, 1) =
255 BETA * (mean_y_b * Ay - mean_x_b * Ax) / pow(D, 1.5);
CPose2D mean
The mean value.
bool se2_l2(const mrpt::tfest::TMatchingPairList &in_correspondences, mrpt::math::TPose2D &out_transformation, mrpt::math::CMatrixDouble33 *out_estimateCovariance=nullptr)
Least-squares (L2 norm) solution to finding the optimal SE(2) (x,y,yaw) between two reference frames...
mrpt::math::CMatrixDouble33 cov
The 3x3 covariance matrix.
This base provides a set of functions for maths stuff.
Declares a class that represents a Probability Density function (PDF) of a 2D pose ...
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
return_t square(const num_t x)
Inline function for the square of a number.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
Functions for estimating the optimal transformation between two frames of references given measuremen...
double phi
Orientation (rads)