Skip to content

feat: support AT128P and FTX140 - #520

Closed
Autumn60 wants to merge 3 commits into
tier4:mainfrom
Autumn60:feat/hesai-at128p-ftx140
Closed

Autumn60 wants to merge 3 commits into
tier4:mainfrom
Autumn60:feat/hesai-at128p-ftx140

Conversation

@Autumn60

@Autumn60 Autumn60 commented Oct 28, 2026 •

Copy link
Copy Markdown

PR Type

  • New Feature

Related Links

Description

This PR adds support for two Hesai sensors, the AT128P and the FTX140, and makes the generic Hesai decoder ignore fault message packets.

AT128P

The AT128P uses the same point cloud packet format (protocol 4.3) as the AT128E2X, so it is implemented as PandarAT128P, a subclass of PandarAT128.

  • Range: 0.5 m to 260 m.
  • Return modes: in addition to the AT128 modes, First and FirstStrongest are supported.
    • In Strongest+First mode, the AT128P stores the strongest return in the first block and the first return in the second block (AT128P user manual, section 3.1.2.3). get_return_type() swaps them before classifying.
  • Calibration: the correction file (.dat) and the PTC handling of the AT128 are reused. Like the AT128, the lidar range is not set over PTC.
  • Inventory: a new HesaiInventory_AT128P_FTX handles the 216-byte inventory, which has a part number after the serial number.
    • The sensor reports 0 as its product model, which would be mistaken for a Pandar40P. The AT128 model number is reported instead, so the sensor is handled like the AT128 (PTC only).

FTX140

The FTX140 is a solid-state lidar using point cloud UDP protocol 7.3. It gets its own decoder, HesaiFtx140Decoder.

  • Packet layout: each packet contains one subzone of 6 rows × 16 columns of the sensor's 192 × 256 channel array.
  • Frames: frames are cut when the frame ID changes, not by azimuth.
  • Calibration (HesaiFtxCalibration): the sensor provides a fisheye camera model instead of per-pixel angles. The model consists of focal length, principal point, four radial distortion coefficients and a tilt of the image plane. The ray direction of each pixel is computed from this model on load.
    • The model and its constants follow FT::CorrectionV3::generate_pixel_vectors() of the Hesai LiDAR SDK 2.0, so points match the ones produced by Hesai's tools.
  • Supported packet variants:
    • Zoom mode: only the central 16 × 10 subzones are output.
    • Bottom-up row order.
  • Ignored packets: IMU and fault message packets arrive on the same port and are ignored.
  • Status: HesaiLidarStatusFTX reads the lidar status. It has the AT128 layout, but the temperature fields are not reported because the sensor does not fill them.
  • Limitation: sensor setup (setup_sensor) is not supported, because the FTX140 does not support most setting commands (e.g. PTP config, lidar range). The node keeps the sensor's settings and logs a warning. This is noted in docs/supported_sensors.md.

Fault message packets

Sensors such as the AT128P send fault messages (SOP 0xCDDC, 99 bytes) to the data port alongside point cloud packets.

  • Before: HesaiDecoder treated them as truncated point cloud packets and logged Packet size mismatch for each one, about 200 times per second per sensor.
  • After: they now return the new DecodeError::PACKET_IGNORED. Other truncated packets are still reported as PACKET_PARSE_FAILED.

Other changes

  • Parameter files, JSON schemas and launch entries for both sensors.
  • Calibration samples (AT128P.dat, FTX140.dat).
  • Documentation pages for both sensors.
  • Support for both sensors in the offline extraction examples.

Review Procedure

  1. Build and run the unit tests:

    colcon build --packages-up-to nebula_hesai --cmake-args -DBUILD_TESTING=ON
    colcon test --packages-select nebula_hesai nebula_hesai_decoders nebula_hesai_hw_interfaces
    colcon test-result --verbose

    New tests:

    • test_hesai_at128p: return type handling of the AT128P, and the fault message handling of HesaiDecoder.
    • test_hesai_ftx140: calibration against reference directions from the Hesai SDK, rejection of invalid calibration data, full frame decoding, zoom mode, bottom-up rows, FoV cropping, and ignoring IMU and fault message packets.
    • test_hesai_hw_interface: PTC commands of the AT128P and FTX140, and the inventory layout with the part number.
  2. (Optional) With a sensor, launch the driver:

    ros2 launch nebula_hesai hesai_launch_all_hw.xml sensor_model:=AT128P
    ros2 launch nebula_hesai hesai_launch_all_hw.xml sensor_model:=FTX140

Test results

  • Unit tests: 173 tests in nebula_hesai, nebula_hesai_decoders and nebula_hesai_hw_interfaces pass (ROS 2 Jazzy, Agnocast disabled).
  • pre-commit: passes on all changed files.

Remarks

  • Hesai SDK derivation: the FTX140 calibration model is derived from the Hesai LiDAR SDK 2.0 (Modified BSD License). Attribution is in the comment of HesaiFtxCalibration. Please check whether this is acceptable for the license of this repository.

Pre-Review Checklist for the PR Author

PR Author should check the checkboxes below when creating the PR.

  • Assign PR to reviewer

Checklist for the PR Reviewer

Reviewers should check the checkboxes below before approval.

  • Commits are properly organized and messages are according to the guideline
  • (Optional) Unit tests have been written for new behavior
  • PR title describes the changes

Post-Review Checklist for the PR Author

PR Author should check the checkboxes below before merging.

  • All open points are addressed and tracked via issues or tickets

CI Checks

  • Build and test for PR: Required to pass before the merge.

Signed-off-by: Autum60 <akiro.harada@tier4.jp>
Signed-off-by: Autum60 <akiro.harada@tier4.jp>
@codecov

codecov Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.16667% with 57 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.80%. Comparing base (bdf127c) to head (a860d59).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #520      +/-   ##
==========================================
+ Coverage   45.71%   46.80%   +1.09%     
==========================================
  Files         136      145       +9     
  Lines       10363    11057     +694     
  Branches     1282     1347      +65     
==========================================
+ Hits         4737     5175     +438     
- Misses       5624     5858     +234     
- Partials        2       24      +22     
Flag Coverage Δ
nebula 45.96% <84.16%> (?)
nebula_core_common 45.96% <84.16%> (?)
nebula_hesai 45.96% <84.16%> (?)
nebula_hesai_common 45.96% <84.16%> (?)
nebula_hesai_decoders 45.96% <84.16%> (?)
nebula_hesai_hw_interfaces 45.96% <84.16%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mojomex

mojomex commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Hi @Autumn60, thanks for the contribution!
Could you please split the PR into 3:

  • ignore fault message packets
  • add at128p
  • add ftx140
    ?

That way review will be much easier on our side.
Cheers!

Signed-off-by: Autum60 <akiro.harada@tier4.jp>
@Autumn60

Copy link
Copy Markdown
Author

@Autumn60 Autumn60 closed this Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants