25namespace compensator {
27bool Compensator::QueryPoseAffineFromTF2(
28 const uint64_t& timestamp,
30 const std::string& child_frame_id) {
32 std::string err_string;
39 AERROR <<
"Can not find transform. " << timestamp
40 <<
" frame_id:" << child_frame_id
41 <<
" Error info: " << err_string;
50 }
catch (tf2::TransformException& ex) {
55 Eigen::Affine3d* tmp_pose = (Eigen::Affine3d*)pose;
56 *tmp_pose = Eigen::Translation3d(
69 const std::shared_ptr<const PointCloud>& msg,
70 std::shared_ptr<PointCloud> msg_compensated) {
71 if (msg->height() == 0 || msg->width() == 0) {
72 AERROR <<
"PointCloud width & height should not be 0";
76 Eigen::Affine3d pose_min_time;
77 Eigen::Affine3d pose_max_time;
79 uint64_t timestamp_min = 0;
80 uint64_t timestamp_max = 0;
81 std::string frame_id = msg->header().frame_id();
82 GetTimestampInterval(msg, ×tamp_min, ×tamp_max);
84 msg_compensated->mutable_header()->set_timestamp_sec(
86 msg_compensated->mutable_header()->set_frame_id(msg->header().frame_id());
87 msg_compensated->mutable_header()->set_lidar_timestamp(
88 msg->header().lidar_timestamp());
89 msg_compensated->set_measurement_time(msg->measurement_time());
90 msg_compensated->set_height(msg->height());
91 msg_compensated->set_is_dense(msg->is_dense());
94 AINFO <<
"compenstator new msg diff:" << new_time - start
95 <<
";meta:" << msg->header().lidar_timestamp();
96 msg_compensated->mutable_point()->Reserve(240000);
99 if (QueryPoseAffineFromTF2(timestamp_min, &pose_min_time, frame_id)
100 && QueryPoseAffineFromTF2(timestamp_max, &pose_max_time, frame_id)) {
102 AINFO <<
"compenstator tf msg diff:" << tf_time - new_time
103 <<
";meta:" << msg->header().lidar_timestamp();
112 msg_compensated->set_width(
113 msg_compensated->point_size() / msg->height());
114 AINFO <<
"compenstator com msg diff:" << com_time - tf_time
115 <<
";meta:" << msg->header().lidar_timestamp();
121inline void Compensator::GetTimestampInterval(
122 const std::shared_ptr<const PointCloud>& msg,
123 uint64_t* timestamp_min,
124 uint64_t* timestamp_max) {
126 *timestamp_min = std::numeric_limits<uint64_t>::max();
128 for (
const auto& point : msg->point()) {
129 uint64_t timestamp = point.timestamp();
130 if (timestamp < *timestamp_min) {
131 *timestamp_min = timestamp;
134 if (timestamp > *timestamp_max) {
135 *timestamp_max = timestamp;
141 const std::shared_ptr<const PointCloud>& msg,
142 std::shared_ptr<PointCloud> msg_compensated,
143 const uint64_t timestamp_min,
144 const uint64_t timestamp_max,
145 const Eigen::Affine3d& pose_min_time,
146 const Eigen::Affine3d& pose_max_time) {
151 Eigen::Vector3d translation
152 = pose_min_time.translation() - pose_max_time.translation();
153 Eigen::Quaterniond q_max(pose_max_time.linear());
154 Eigen::Quaterniond q_min(pose_min_time.linear());
155 Eigen::Quaterniond q1(q_max.conjugate() * q_min);
156 Eigen::Quaterniond q0(Eigen::Quaterniond::Identity());
158 translation = q_max.conjugate() * translation;
162 double d = q0.dot(q1);
163 double abs_d = abs(d);
164 double f = 1.0 /
static_cast<double>(timestamp_max - timestamp_min);
171 if (abs_d < 1.0 - 1.0e-8) {
172 double theta = acos(abs_d);
173 double sin_theta =
sin(theta);
174 double c1_sign = (d > 0) ? 1 : -1;
175 for (
const auto& point : msg->point()) {
176 float x_scalar = point.x();
177 if (std::isnan(x_scalar)) {
179 auto* point_new = msg_compensated->add_point();
180 point_new->CopyFrom(point);
186 float y_scalar = point.y();
187 float z_scalar = point.z();
188 Eigen::Vector3d p(x_scalar, y_scalar, z_scalar);
190 uint64_t tp = point.timestamp();
191 double t =
static_cast<double>(timestamp_max - tp) *
f;
193 Eigen::Translation3d ti(t * translation);
195 double c0 =
sin((1 - t) * theta) / sin_theta;
196 double c1 =
sin(t * theta) / sin_theta * c1_sign;
197 Eigen::Quaterniond qi(c0 * q0.coeffs() + c1 * q1.coeffs());
199 Eigen::Affine3d trans = ti * qi;
202 auto* point_new = msg_compensated->add_point();
203 point_new->set_intensity(point.intensity());
204 point_new->set_timestamp(point.timestamp());
205 point_new->set_x(
static_cast<float>(p.x()));
206 point_new->set_y(
static_cast<float>(p.y()));
207 point_new->set_z(
static_cast<float>(p.z()));
212 for (
auto& point : msg->point()) {
213 float x_scalar = point.x();
214 if (std::isnan(x_scalar)) {
218 float y_scalar = point.y();
219 float z_scalar = point.z();
220 Eigen::Vector3d p(x_scalar, y_scalar, z_scalar);
222 uint64_t tp = point.timestamp();
223 double t =
static_cast<double>(timestamp_max - tp) *
f;
224 Eigen::Translation3d ti(t * translation);
228 auto* point_new = msg_compensated->add_point();
229 point_new->set_intensity(point.intensity());
230 point_new->set_timestamp(point.timestamp());
231 point_new->set_x(
static_cast<float>(p.x()));
232 point_new->set_y(
static_cast<float>(p.y()));
233 point_new->set_z(
static_cast<float>(p.z()));