Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make AT128 scans align with scan_phase #84

Merged
merged 16 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Supported models, where sensor_model is the ROS param to be used at launch:
| HESAI | Pandar XT32M | PandarXT32M | PandarXT32M.yaml | :warning: |
| HESAI | Pandar QT64 | PandarQT64 | PandarQT64.yaml | :heavy_check_mark: |
| HESAI | Pandar QT128 | PandarQT128 | PandarQT128.yaml | :warning: |
| HESAI | Pandar AT128 | PandarAT128 | PandarAT128.yaml | :heavy_check_mark: |
| HESAI | Pandar AT128 | PandarAT128 | PandarAT128.yaml | :heavy_check_mark:* |
| HESAI | Pandar 128E4X | Pandar128E4X | Pandar128E4X.yaml | :warning: |
| Velodyne | VLP-16 | VLP16 | VLP16.yaml | :warning: |
| Velodyne | VLP-16-HiRes | VLP16 | | :x: |
Expand All @@ -103,7 +103,9 @@ Supported models, where sensor_model is the ROS param to be used at launch:
Test status:\
:heavy_check_mark:: complete\
:warning:: some functionality yet to be tested\
:x: : untested
:x:: untested\
*: AT128 needs software version 3.50.8 or newer for the `scan_angle` setting to work correctly.


## ROS parameters

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ class AngleCorrector
/// azimuth
/// @param current_azimuth The current azimuth value in the sensor's angle resolution
/// @param last_azimuth The last azimuth in the sensor's angle resolution
/// @param sync_azimuth The azimuth set in the sensor configuration, for which the
/// timestamp is aligned to the full second
/// @return true if the current azimuth is in a different scan than the last one, false otherwise
virtual bool hasScanned(int current_azimuth, int last_azimuth) = 0;
virtual bool hasScanned(uint32_t current_azimuth, uint32_t last_azimuth, uint32_t sync_azimuth) = 0;
};

} // namespace drivers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,15 @@ class AngleCorrectorCalibrationBased : public AngleCorrector
elevation_cos_[channel_id]};
}

bool hasScanned(int current_azimuth, int last_azimuth) override
bool hasScanned(uint32_t current_azimuth, uint32_t last_azimuth, uint32_t sync_azimuth) override
{
return current_azimuth < last_azimuth;
// Cut the scan when the azimuth passes over the sync_azimuth
uint32_t current_diff_from_sync =
(MAX_AZIMUTH_LEN + current_azimuth - sync_azimuth) % MAX_AZIMUTH_LEN;
uint32_t last_diff_from_sync =
(MAX_AZIMUTH_LEN + last_azimuth - sync_azimuth) % MAX_AZIMUTH_LEN;

return current_diff_from_sync < last_diff_from_sync;
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,18 @@ class AngleCorrectorCorrectionBased : public AngleCorrector
cos_[azimuth], sin_[elevation], cos_[elevation]};
}

bool hasScanned(int current_azimuth, int last_azimuth) override
bool hasScanned(uint32_t current_azimuth, uint32_t last_azimuth, uint32_t /*sync_azimuth*/) override
{
int field = findField(current_azimuth);
int last_field = findField(last_azimuth);

// RCLCPP_DEBUG_STREAM(
// logger_, '{' << _(field) << _(last_field) << _(current_azimuth) << _(last_azimuth) << '}');
return last_field != field;
// For AT128, the scan is always cut at the beginning of the field:
// If we would cut at `sync_azimuth`, the points left of it would be
// from the previous field and therefore significantly older than the
// points right of it.
// This also means that the pointcloud timestamp is only at top of second
// if the `sync_azimuth` aligns with the beginning of the field (e.g. 30deg for AT128).
// The absolute point time for points at `sync_azimuth` is still at top of second.
return findField(current_azimuth) != findField(last_azimuth);
}
};

} // namespace drivers
} // namespace nebula
} // namespace nebula
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ class HesaiDecoder : public HesaiScanDecoder
NebulaPoint point;
point.distance = distance;
point.intensity = unit.reflectivity;
// TODO(mojomex) add header offset to scan offset correction
point.time_stamp =
getPointTimeRelative(packet_timestamp_ns, block_offset + start_block_id, channel_id);

Expand All @@ -167,10 +166,12 @@ class HesaiDecoder : public HesaiScanDecoder

/// @brief Checks whether the last processed block was the last block of a scan
/// @param current_phase The azimuth of the last processed block
/// @param sync_phase The azimuth set in the sensor configuration, for which the
/// timestamp is aligned to the full second
/// @return Whether the scan has completed
bool checkScanCompleted(int current_phase)
bool checkScanCompleted(uint32_t current_phase, uint32_t sync_phase)
{
return angle_corrector_.hasScanned(current_phase, last_phase_);
return angle_corrector_.hasScanned(current_phase, last_phase_, sync_phase);
}

/// @brief Get the distance of the given unit in meters
Expand Down Expand Up @@ -233,17 +234,15 @@ class HesaiDecoder : public HesaiScanDecoder
}

const size_t n_returns = hesai_packet::get_n_returns(packet_.tail.return_mode);
int current_azimuth;
uint32_t current_azimuth;

for (size_t block_id = 0; block_id < SensorT::packet_t::N_BLOCKS; block_id += n_returns) {
current_azimuth =
(360 * SensorT::packet_t::DEGREE_SUBDIVISIONS +
packet_.body.blocks[block_id].get_azimuth() -
static_cast<int>(
sensor_configuration_->scan_phase * SensorT::packet_t::DEGREE_SUBDIVISIONS)) %
(360 * SensorT::packet_t::DEGREE_SUBDIVISIONS);

bool scan_completed = checkScanCompleted(current_azimuth);
current_azimuth = packet_.body.blocks[block_id].get_azimuth();

bool scan_completed = checkScanCompleted(
current_azimuth,
sensor_configuration_->scan_phase * SensorT::packet_t::DEGREE_SUBDIVISIONS);

if (scan_completed) {
std::swap(decode_pc_, output_pc_);
decode_pc_->clear();
Expand Down
2 changes: 1 addition & 1 deletion nebula_ros/config/hesai/PandarAT128.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
data_port: 2368 # LiDAR Data Port
gnss_port: 10110 # LiDAR GNSS Port
return_mode: "LastStrongest" # See readme for supported return modes
scan_phase: 0.0 # Angle where scans begin (degrees, [0.,360.]
scan_phase: 30.0 # Angle where scans begin (degrees, [30.,150.])
packet_mtu_size: 1500 # Packet MTU size
rotation_speed: 200 # Motor RPM, the sensor's internal spin rate.
cloud_min_angle: 0 # Field of View, start degrees.
Expand Down
Loading