Skip to content

Commit 87dbb2e

Browse files
committed
feat(hesai): publish on cloud_max_angle
1 parent 6a65d2c commit 87dbb2e

File tree

4 files changed

+89
-54
lines changed

4 files changed

+89
-54
lines changed

nebula_decoders/include/nebula_decoders/nebula_decoders_hesai/decoders/angle_corrector.hpp

+4-9
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,10 @@ class AngleCorrector
4949
/// @return The corrected angles (azimuth, elevation) in radians and their sin/cos values
5050
virtual CorrectedAngleData getCorrectedAngleData(uint32_t block_azimuth, uint32_t channel_id) = 0;
5151

52-
/// @brief Returns true if the current azimuth lies in a different (new) scan compared to the last
53-
/// azimuth
54-
/// @param current_azimuth The current azimuth value in the sensor's angle resolution
55-
/// @param last_azimuth The last azimuth in the sensor's angle resolution
56-
/// @param sync_azimuth The azimuth set in the sensor configuration, for which the
57-
/// timestamp is aligned to the full second
58-
/// @return true if the current azimuth is in a different scan than the last one, false otherwise
59-
virtual bool hasScanned(
60-
uint32_t current_azimuth, uint32_t last_azimuth, uint32_t sync_azimuth) = 0;
52+
/// @brief Returns whether the given block (azimuth) is the last in the current scan
53+
/// @param block_azimuth The current azimuth value in the sensor's angle resolution
54+
/// @return true if the current azimuth is the last in the current scan, false otherwise
55+
virtual bool blockCompletesScan(uint32_t block_azimuth) = 0;
6156
};
6257

6358
} // namespace drivers

nebula_decoders/include/nebula_decoders/nebula_decoders_hesai/decoders/angle_corrector_calibration_based.hpp

+24-9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "nebula_common/hesai/hesai_common.hpp"
1818
#include "nebula_decoders/nebula_decoders_hesai/decoders/angle_corrector.hpp"
1919

20+
#include <nebula_common/nebula_common.hpp>
21+
22+
#include <cmath>
2023
#include <cstdint>
2124
#include <memory>
2225

@@ -40,9 +43,12 @@ class AngleCorrectorCalibrationBased : public AngleCorrector<HesaiCalibrationCon
4043
std::array<std::array<float, ChannelN>, MAX_AZIMUTH_LEN> azimuth_cos_{};
4144
std::array<std::array<float, ChannelN>, MAX_AZIMUTH_LEN> azimuth_sin_{};
4245

46+
uint32_t scan_cut_block_azimuth_{};
47+
4348
public:
4449
AngleCorrectorCalibrationBased(
45-
const std::shared_ptr<const HesaiCalibrationConfiguration> & sensor_calibration)
50+
const std::shared_ptr<const HesaiCalibrationConfiguration> & sensor_calibration,
51+
float scan_cut_azimuth_rad)
4652
{
4753
if (sensor_calibration == nullptr) {
4854
throw std::runtime_error(
@@ -71,6 +77,21 @@ class AngleCorrectorCalibrationBased : public AngleCorrector<HesaiCalibrationCon
7177
azimuth_sin_[block_azimuth][channel_id] = sinf(precision_azimuth);
7278
}
7379
}
80+
81+
auto scan_cut_block_azimuth = static_cast<uint32_t>(rad2deg(scan_cut_azimuth_rad) * 10.0);
82+
while (true) {
83+
auto block_azimuth_rad = block_azimuth_rad_[scan_cut_block_azimuth];
84+
for (auto correction : azimuth_offset_rad_) {
85+
if (block_azimuth_rad + correction < scan_cut_azimuth_rad) {
86+
scan_cut_block_azimuth_++;
87+
break;
88+
}
89+
}
90+
91+
break;
92+
}
93+
94+
scan_cut_block_azimuth_ = scan_cut_block_azimuth;
7495
}
7596

7697
CorrectedAngleData getCorrectedAngleData(uint32_t block_azimuth, uint32_t channel_id) override
@@ -87,15 +108,9 @@ class AngleCorrectorCalibrationBased : public AngleCorrector<HesaiCalibrationCon
87108
elevation_cos_[channel_id]};
88109
}
89110

90-
bool hasScanned(uint32_t current_azimuth, uint32_t last_azimuth, uint32_t sync_azimuth) override
111+
bool blockCompletesScan(uint32_t current_azimuth) override
91112
{
92-
// Cut the scan when the azimuth passes over the sync_azimuth
93-
uint32_t current_diff_from_sync =
94-
(MAX_AZIMUTH_LEN + current_azimuth - sync_azimuth) % MAX_AZIMUTH_LEN;
95-
uint32_t last_diff_from_sync =
96-
(MAX_AZIMUTH_LEN + last_azimuth - sync_azimuth) % MAX_AZIMUTH_LEN;
97-
98-
return current_diff_from_sync < last_diff_from_sync;
113+
return current_azimuth == scan_cut_block_azimuth_;
99114
}
100115
};
101116

nebula_decoders/include/nebula_decoders/nebula_decoders_hesai/decoders/angle_corrector_correction_based.hpp

+36-11
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717
#include "nebula_common/hesai/hesai_common.hpp"
1818
#include "nebula_decoders/nebula_decoders_hesai/decoders/angle_corrector.hpp"
1919

20+
#include <algorithm>
2021
#include <cstdint>
2122
#include <memory>
23+
#include <stdexcept>
24+
#include <string>
25+
#include <vector>
2226

2327
namespace nebula
2428
{
@@ -36,6 +40,8 @@ class AngleCorrectorCorrectionBased : public AngleCorrector<HesaiCorrection>
3640
std::array<float, MAX_AZIMUTH_LENGTH> cos_{};
3741
std::array<float, MAX_AZIMUTH_LENGTH> sin_{};
3842

43+
std::vector<uint32_t> cut_azimuths_;
44+
3945
/// @brief For a given azimuth value, find its corresponding output field
4046
/// @param azimuth The azimuth to get the field for
4147
/// @return The correct output field, as specified in @ref HesaiCorrection
@@ -57,7 +63,7 @@ class AngleCorrectorCorrectionBased : public AngleCorrector<HesaiCorrection>
5763

5864
public:
5965
explicit AngleCorrectorCorrectionBased(
60-
const std::shared_ptr<const HesaiCorrection> & sensor_correction)
66+
const std::shared_ptr<const HesaiCorrection> & sensor_correction, float scan_cut_azimuth_rad)
6167
: correction_(sensor_correction), logger_(rclcpp::get_logger("AngleCorrectorCorrectionBased"))
6268
{
6369
if (sensor_correction == nullptr) {
@@ -72,6 +78,31 @@ class AngleCorrectorCorrectionBased : public AngleCorrector<HesaiCorrection>
7278
cos_[i] = cosf(rad);
7379
sin_[i] = sinf(rad);
7480
}
81+
82+
for (size_t field_id = 0; field_id < correction_->frameNumber; ++field_id) {
83+
auto start = correction_->startFrame[field_id];
84+
auto end = correction_->endFrame[field_id];
85+
auto raw_azimuth = start;
86+
for (; raw_azimuth != end; raw_azimuth = (raw_azimuth + 1) % MAX_AZIMUTH_LENGTH) {
87+
for (size_t channel_id = 0; channel_id < ChannelN; ++channel_id) {
88+
auto corrected_azimuth = getCorrectedAngleData(raw_azimuth, channel_id).azimuth_rad;
89+
if (corrected_azimuth < scan_cut_azimuth_rad) {
90+
break; // Not all channels are past the cut azimuth, search at next raw azimuth
91+
}
92+
}
93+
94+
// All channels are past the cut azimuth, add this raw_azimuths to the cut azimuths
95+
break;
96+
}
97+
98+
cut_azimuths_.push_back(raw_azimuth);
99+
}
100+
101+
if (cut_azimuths_.size() != correction_->frameNumber) {
102+
throw std::runtime_error(
103+
"Sensor has " + std::to_string(correction_->frameNumber) +
104+
" fields but calculation resulted in " + std::to_string(cut_azimuths_.size()));
105+
}
75106
}
76107

77108
CorrectedAngleData getCorrectedAngleData(uint32_t block_azimuth, uint32_t channel_id) override
@@ -95,17 +126,11 @@ class AngleCorrectorCorrectionBased : public AngleCorrector<HesaiCorrection>
95126
cos_[azimuth], sin_[elevation], cos_[elevation]};
96127
}
97128

98-
bool hasScanned(
99-
uint32_t current_azimuth, uint32_t last_azimuth, uint32_t /*sync_azimuth*/) override
129+
bool blockCompletesScan(uint32_t block_azimuth) override
100130
{
101-
// For AT128, the scan is always cut at the beginning of the field:
102-
// If we would cut at `sync_azimuth`, the points left of it would be
103-
// from the previous field and therefore significantly older than the
104-
// points right of it.
105-
// This also means that the pointcloud timestamp is only at top of second
106-
// if the `sync_azimuth` aligns with the beginning of the field (e.g. 30deg for AT128).
107-
// The absolute point time for points at `sync_azimuth` is still at top of second.
108-
return findField(current_azimuth) != findField(last_azimuth);
131+
auto begin = cut_azimuths_.cbegin();
132+
auto end = cut_azimuths_.cend();
133+
return std::find(begin, end, block_azimuth) != end;
109134
}
110135
};
111136

nebula_decoders/include/nebula_decoders/nebula_decoders_hesai/decoders/hesai_decoder.hpp

+25-25
Original file line numberDiff line numberDiff line change
@@ -202,20 +202,6 @@ class HesaiDecoder : public HesaiScanDecoder
202202
}
203203
}
204204

205-
/// @brief Checks whether the last processed block was the last block of a scan
206-
/// @param current_phase The azimuth of the last processed block
207-
/// @param sync_phase The azimuth set in the sensor configuration, for which the
208-
/// timestamp is aligned to the full second
209-
/// @return Whether the scan has completed
210-
bool checkScanCompleted(uint32_t current_phase, uint32_t sync_phase)
211-
{
212-
if (last_phase_ == -1) {
213-
return false;
214-
}
215-
216-
return angle_corrector_.hasScanned(current_phase, last_phase_, sync_phase);
217-
}
218-
219205
/// @brief Get the distance of the given unit in meters
220206
float getDistance(const typename SensorT::packet_t::body_t::block_t::unit_t & unit)
221207
{
@@ -236,6 +222,24 @@ class HesaiDecoder : public HesaiScanDecoder
236222
return packet_to_scan_offset_ns + point_to_packet_offset_ns;
237223
}
238224

225+
/**
226+
* @brief Return the appropriate scan cut azimuth based on whether the configured FoV is 360
227+
* degrees (use scan phase for cutting) or less (use max angle for cutting).
228+
*
229+
* @param config The sensor configuration to use
230+
* @return uint32_t The scan cut azimuth in 10ths of degrees
231+
*/
232+
[[nodiscard]] uint32_t getCutAngle() const
233+
{
234+
if (
235+
sensor_configuration_->cloud_min_angle == 0 &&
236+
sensor_configuration_->cloud_max_angle == 3600) {
237+
return static_cast<uint32_t>(sensor_configuration_->scan_phase * 10);
238+
}
239+
240+
return sensor_configuration_->cloud_max_angle;
241+
}
242+
239243
public:
240244
/// @brief Constructor
241245
/// @param sensor_configuration SensorConfiguration for this decoder
@@ -245,14 +249,14 @@ class HesaiDecoder : public HesaiScanDecoder
245249
const std::shared_ptr<const typename SensorT::angle_corrector_t::correction_data_t> &
246250
correction_data)
247251
: sensor_configuration_(sensor_configuration),
248-
angle_corrector_(correction_data),
252+
angle_corrector_(correction_data, deg2rad(getCutAngle() / 10.0)),
249253
logger_(rclcpp::get_logger("HesaiDecoder"))
250254
{
251255
logger_.set_level(rclcpp::Logger::Level::Debug);
252256
RCLCPP_INFO_STREAM(logger_, *sensor_configuration_);
253257

254-
decode_pc_.reset(new NebulaPointCloud);
255-
output_pc_.reset(new NebulaPointCloud);
258+
decode_pc_ = std::make_shared<NebulaPointCloud>();
259+
output_pc_ = std::make_shared<NebulaPointCloud>();
256260

257261
decode_pc_->reserve(SensorT::MAX_SCAN_BUFFER_POINTS);
258262
output_pc_->reserve(SensorT::MAX_SCAN_BUFFER_POINTS);
@@ -273,14 +277,11 @@ class HesaiDecoder : public HesaiScanDecoder
273277
}
274278

275279
const size_t n_returns = hesai_packet::get_n_returns(packet_.tail.return_mode);
276-
uint32_t current_azimuth;
277-
278280
for (size_t block_id = 0; block_id < SensorT::packet_t::N_BLOCKS; block_id += n_returns) {
279-
current_azimuth = packet_.body.blocks[block_id].get_azimuth();
281+
convertReturns(block_id, n_returns);
280282

281-
bool scan_completed = checkScanCompleted(
282-
current_azimuth,
283-
sensor_configuration_->scan_phase * SensorT::packet_t::DEGREE_SUBDIVISIONS);
283+
auto block_azimuth = packet_.body.blocks[block_id].get_azimuth();
284+
bool scan_completed = angle_corrector_.blockCompletesScan(block_azimuth);
284285

285286
if (scan_completed) {
286287
std::swap(decode_pc_, output_pc_);
@@ -295,8 +296,7 @@ class HesaiDecoder : public HesaiScanDecoder
295296
sensor_.getEarliestPointTimeOffsetForBlock(block_id, packet_);
296297
}
297298

298-
convertReturns(block_id, n_returns);
299-
last_phase_ = current_azimuth;
299+
last_phase_ = block_azimuth;
300300
}
301301

302302
return last_phase_;

0 commit comments

Comments
 (0)