@@ -54,7 +54,7 @@ MeasurementBuffer::MeasurementBuffer(
5454 const double & observation_keep_time, const double & expected_update_rate,
5555 const double & min_obstacle_height, const double & max_obstacle_height,
5656 const double & obstacle_range, tf2_ros::Buffer & tf, const std::string & global_frame,
57- const std::string & sensor_frame, const double & tf_tolerance,
57+ const std::string & sensor_frame, const std::string & z_reference_frame, const double & tf_tolerance,
5858 const double & min_d, const double & max_d, const double & vFOV,
5959 const double & vFOVPadding, const double & hFOV,
6060 const double & decay_acceleration, const bool & marking,
@@ -67,7 +67,7 @@ MeasurementBuffer::MeasurementBuffer(
6767 _expected_update_rate(rclcpp::Duration::from_seconds(expected_update_rate)),
6868 _last_updated(clock->now ()),
6969 _global_frame(global_frame), _sensor_frame(sensor_frame), _source_name(source_name),
70- _topic_name(topic_name), _min_obstacle_height(min_obstacle_height),
70+ _topic_name(topic_name), _z_reference_frame(z_reference_frame), _min_obstacle_height(min_obstacle_height),
7171 _max_obstacle_height(max_obstacle_height), _obstacle_range(obstacle_range),
7272 _tf_tolerance(tf_tolerance), _min_z(min_d), _max_z(max_d),
7373 _vertical_fov(vFOV), _vertical_fov_padding(vFOVPadding),
@@ -137,44 +137,89 @@ void MeasurementBuffer::BufferROSCloud(
137137 return ;
138138 }
139139
140- // transform the cloud in the global frame
141- point_cloud_ptr cld_global (new sensor_msgs::msg::PointCloud2 ());
142- geometry_msgs::msg::TransformStamped tf_stamped =
140+ // transform the cloud in the global frame, directly or indirectly to apply relative z filter
141+ point_cloud_ptr cld_transformed (new sensor_msgs::msg::PointCloud2 ());
142+
143+ geometry_msgs::msg::TransformStamped tf_direct_global =
143144 _buffer.lookupTransform (
144145 _global_frame, cloud.header .frame_id ,
145146 tf2_ros::fromMsg (cloud.header .stamp ));
146- tf2::doTransform (cloud, *cld_global, tf_stamped);
147+
148+ geometry_msgs::msg::TransformStamped tf_z_reference =
149+ _buffer.lookupTransform (
150+ _z_reference_frame, cloud.header .frame_id ,
151+ tf2_ros::fromMsg (cloud.header .stamp ));
152+
153+ geometry_msgs::msg::TransformStamped tf_global_from_z_reference =
154+ _buffer.lookupTransform (
155+ _global_frame, _z_reference_frame,
156+ tf2_ros::fromMsg (cloud.header .stamp ));
147157
148158 pcl::PCLPointCloud2::Ptr cloud_pcl (new pcl::PCLPointCloud2 ());
149159 pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2 ());
150-
160+ pcl::PassThrough<pcl::PCLPointCloud2> pass_through_filter;
161+ pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
162+ float v_s = static_cast <float >(_voxel_size);
151163 // remove points that are below or above our height restrictions, and
152164 // in the same time, remove NaNs and if user wants to use it, combine with a
153- if (_filter == Filters::VOXEL) {
154- pcl_conversions::toPCL (*cld_global, *cloud_pcl);
155- pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
165+
166+ switch (_filter)
167+ {
168+ case Filters::PASSTHROUGH :
169+ tf2::doTransform (cloud, *cld_transformed, tf_direct_global);
170+ pcl_conversions::toPCL (*cld_transformed, *cloud_pcl);
171+ pass_through_filter.setInputCloud (cloud_pcl);
172+ pass_through_filter.setKeepOrganized (false );
173+ pass_through_filter.setFilterFieldName (" z" );
174+ pass_through_filter.setFilterLimits (
175+ _min_obstacle_height, _max_obstacle_height);
176+ pass_through_filter.filter (*cloud_filtered);
177+ pcl_conversions::fromPCL (*cloud_filtered, *cld_transformed);
178+ break ;
179+ case Filters::VOXEL :
180+ tf2::doTransform (cloud, *cld_transformed, tf_direct_global);
181+ pcl_conversions::toPCL (*cld_transformed, *cloud_pcl);
156182 sor.setInputCloud (cloud_pcl);
157183 sor.setFilterFieldName (" z" );
158184 sor.setFilterLimits (_min_obstacle_height, _max_obstacle_height);
159185 sor.setDownsampleAllData (false );
160- float v_s = static_cast <float >(_voxel_size);
161186 sor.setLeafSize (v_s, v_s, v_s);
162187 sor.setMinimumPointsNumberPerVoxel (static_cast <unsigned int >(_voxel_min_points));
163188 sor.filter (*cloud_filtered);
164- pcl_conversions::fromPCL (*cloud_filtered, *cld_global);
165- } else if (_filter == Filters::PASSTHROUGH) {
166- pcl_conversions::toPCL (*cld_global, *cloud_pcl);
167- pcl::PassThrough<pcl::PCLPointCloud2> pass_through_filter;
189+ pcl_conversions::fromPCL (*cloud_filtered, *cld_transformed);
190+ break ;
191+ case Filters::PASSTHROUGH_RELATIVE :
192+ tf2::doTransform (cloud, *cld_transformed, tf_z_reference);
193+ pcl_conversions::toPCL (*cld_transformed, *cloud_pcl);
168194 pass_through_filter.setInputCloud (cloud_pcl);
169195 pass_through_filter.setKeepOrganized (false );
170196 pass_through_filter.setFilterFieldName (" z" );
171197 pass_through_filter.setFilterLimits (
172198 _min_obstacle_height, _max_obstacle_height);
173199 pass_through_filter.filter (*cloud_filtered);
174- pcl_conversions::fromPCL (*cloud_filtered, *cld_global);
200+ pcl_conversions::fromPCL (*cloud_filtered, *cld_transformed);
201+ tf2::doTransform (*cld_transformed, *cld_transformed, tf_global_from_z_reference);
202+ break ;
203+ case Filters::VOXEL_RELATIVE :
204+ tf2::doTransform (cloud, *cld_transformed, tf_z_reference);
205+ pcl_conversions::toPCL (*cld_transformed, *cloud_pcl);
206+ sor.setInputCloud (cloud_pcl);
207+ sor.setFilterFieldName (" z" );
208+ sor.setFilterLimits (_min_obstacle_height, _max_obstacle_height);
209+ sor.setDownsampleAllData (false );
210+ sor.setLeafSize (v_s, v_s, v_s);
211+ sor.setMinimumPointsNumberPerVoxel (static_cast <unsigned int >(_voxel_min_points));
212+ sor.filter (*cloud_filtered);
213+ pcl_conversions::fromPCL (*cloud_filtered, *cld_transformed);
214+ tf2::doTransform (*cld_transformed, *cld_transformed, tf_global_from_z_reference);
215+ break ;
216+ default :
217+ tf2::doTransform (cloud, *cld_transformed, tf_direct_global);
218+ break ;
219+
175220 }
176221
177- _observation_list.front ()._cloud .reset (cld_global .release ());
222+ _observation_list.front ()._cloud .reset (cld_transformed .release ());
178223 } catch (tf2::TransformException & ex) {
179224 // if fails, remove the empty observation
180225 _observation_list.pop_front ();
0 commit comments