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

refactor(hesai)!: combine Hesai ROS wrappers into a single node #127

Merged
merged 57 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
7fae72d
fix(hesai_decoder): print config instead of config address
mojomex Mar 21, 2024
694f28d
refactor(nebula_ros): combine Hesai wrapper nodes into one
mojomex Mar 21, 2024
c10c6ab
refactor: remove pandarScan pub/sub, decode one packet at a time
mojomex Mar 21, 2024
4f014c3
reword later
mojomex Mar 26, 2024
be47714
temporary progress
mojomex Mar 26, 2024
17c8163
fix(hesai_ros_wrapper): remove changes wrongly merged during rebase
mojomex Apr 4, 2024
c7dcab9
fix(hesai_ros_wrapper): increase packet buffering to stop internal pa…
mojomex Apr 4, 2024
991100d
feat(nebula_common): add instrumentation tools
mojomex Apr 4, 2024
cbaccee
feat(hesai_ros_wrapper): instrument code on critical path
mojomex Apr 4, 2024
5db3474
disable instrumentation
mojomex Apr 5, 2024
a723c29
feat(hesai): move received buffer into ros message instead of copy
mojomex Apr 5, 2024
a7dc57b
feat(hesai_ros_wrapper: add thread-safe queue between udp receiver an…
mojomex Apr 5, 2024
d297b15
feat(nebula_common): more instrumentation tools
mojomex Apr 5, 2024
185d584
fix: update link to transport_drivers fork
mojomex Apr 5, 2024
79de4b6
update GitHub PR view
mojomex Apr 8, 2024
5d64e9b
refactor(mt_queue): make variables more readable
mojomex Apr 8, 2024
5571d84
perf(hesai_ros_wrapper): update queue capacity to alleviate packet dr…
mojomex Apr 8, 2024
3e2b120
chore(hesai_ros_wrapper): remove unused pub/sub
mojomex Apr 8, 2024
8b59a58
refactor(hesai_ros_wrapper): clean up control flow, member variables
mojomex Apr 8, 2024
2cebae9
fix(hesai_hw_interface): add error handling
mojomex Mar 28, 2024
d039f12
fix(hesai_hw_monitor_ros_wrapper): fixed wrong range given for S/N copy
mojomex Apr 8, 2024
5a5a6a9
fix(hesai): print uint8, uint16 as numbers
mojomex Apr 8, 2024
5a11cf9
feat(hesai_ros_wrapper): publish/subscribe to legacy pandar_packets o…
mojomex Apr 9, 2024
dc50d12
change launch file back to single-threaded container
mojomex Apr 9, 2024
9aaedbc
attempt to make queue contention less bad
mojomex Apr 10, 2024
a0d24b9
chore(hesai_ros_wrapper): reduce logging output
mojomex Apr 11, 2024
dab6795
feat(hesai_ros_wrapper): print warning when connected to HW and recei…
mojomex Apr 11, 2024
d26473c
feat(nebula_launch.py): throw error when trying to launch Hesai senso…
mojomex Apr 12, 2024
91359d9
refactor(nebula_ros): split single wrapper file into 3 sub-wrappers
mojomex Apr 18, 2024
9145a6d
chore: update cspell ignore
mojomex Apr 16, 2024
de21908
chore(velodyne_calibration_decoder): fix spelling
mojomex Apr 18, 2024
21cdffc
chore(nebula_common): remove debug code
mojomex Apr 18, 2024
5dddb17
chore(velodyne_calibration_decoder): fix spelling
mojomex Apr 18, 2024
d8ab51a
fix(hesai_decoder): initialize last_phase to prevent empty pointclou…
mojomex Apr 18, 2024
efa730a
fix(nebula_tests): make Hesai tests compile again
mojomex Apr 18, 2024
784db44
fix(nebula_examples): make Hesai examples compile again
mojomex Apr 18, 2024
01f5839
chore(velodyne_calibration_decoder): fix spelling once and for all
mojomex Apr 18, 2024
ae28a71
fix(nebula_examples): fix test failure (remove ament_lint_common)
mojomex Apr 18, 2024
f2494ff
fix(hesai_hw_interface): add missing check for PTC error, make error …
mojomex Apr 22, 2024
36931bc
refactor(hesai): re-introduce parameter update mechanism
mojomex Apr 23, 2024
7c91ce7
feat(hesai_ros): add watchdog timer for pointcloud output
mojomex Apr 23, 2024
76fbd38
fix(hesai): change to possibly more accurate high_resolution_clock
mojomex Apr 25, 2024
2e9ca91
fix(hesai): fix crash on QT128
mojomex Apr 25, 2024
5c527fa
refactor(hesai_hw_interface): refactor repeated error handling code
mojomex Apr 30, 2024
b9f446a
fix(hesai_launch_all_hw.xml): set valid RPM when AT128 is selected
mojomex Apr 30, 2024
10487e6
refactor(hesai_decoder): remove redundant arguments for correction/ca…
mojomex Apr 30, 2024
9fadf8a
refactor(nebula_ros): move mt_queue to common
mojomex May 11, 2024
bf581c8
chore(nebula_examples): change output rosbag format to NebulaPackets,…
mojomex May 22, 2024
c32de1e
chore(hesai/decoder_wrapper): clarify watchdog behavior in decoder
mojomex May 22, 2024
906904f
chore(hesai/hw_monitor_wrapper): fix typo in diagnostics name
mojomex May 22, 2024
539d5af
chore(hesai_ros_decoder_test): fix unclear naming in console output
mojomex May 22, 2024
d8d52c6
chore: run pre-commit and implement suggested fixes (not including co…
mojomex May 22, 2024
dc1a59c
fix(expected.hpp): revert explicit constructors
mojomex May 22, 2024
5f36804
chore: remove erroneously added node_modules folder
mojomex May 22, 2024
18f193a
chore(gitconfig): exclude node_modules from git
mojomex May 22, 2024
b2552dc
fix(hesai/decoder_wrapper): store downloaded sensor calibration witho…
mojomex May 22, 2024
11bdda1
chore(nebula_examples,nebula_tests): remove more dangling comments an…
mojomex May 22, 2024
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
34 changes: 18 additions & 16 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,49 @@
"adctp",
"Adctp",
"AT",
"autosar",
"block_id",
"Bpearl",
"calib",
"DHAVE",
"Difop",
"extrinsics",
"fout",
"gprmc",
"gptp",
"Helios",
"Hesai",
"Idat",
"ipaddr",
"manc",
"memcpy",
"mkdoxy",
"Msop",
"nohup",
"nproc",
"ntoa",
"pandar",
"PANDAR",
"PANDARAT",
"PANDARQT",
"PANDARXT",
"Pdelay",
"Piyush",
"piyushk",
"QT",
"rclcpp",
"schedutil",
"srvs",
"STD_COUT",
"stds",
"struct",
"structs",
"UDP_SEQ",
"vccint",
"Vccint",
"Vdat",
"XT",
"XTM",
"DHAVE",
"Bpearl",
"Helios",
"Msop",
"Difop",
"gptp",
"Idat",
"Vdat",
"autosar",
"srvs",
"manc",
"ipaddr",
"ntoa",
"piyushk",
"Piyush",
"fout"
"yukkysaito"
mojomex marked this conversation as resolved.
Show resolved Hide resolved
]
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ site/

# qcreator stuff
CMakeLists.txt.user

# pre-commit
node_modules/
4 changes: 2 additions & 2 deletions build_depends.repos
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ repositories:
# TCP version of transport drivers
transport_drivers:
type: git
url: https://github.com/MapIV/transport_drivers
version: boost
url: https://github.com/mojomex/transport_drivers
version: mutable-buffer-in-udp-callback
2 changes: 2 additions & 0 deletions nebula_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ ament_auto_add_library(nebula_common SHARED
src/velodyne/velodyne_calibration_decoder.cpp
)

target_link_libraries(nebula_common yaml-cpp)

ament_auto_package()

# Set ROS_DISTRO macros
Expand Down
75 changes: 48 additions & 27 deletions nebula_common/include/nebula_common/hesai/hesai_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
namespace nebula
{
namespace drivers
{
/// @brief struct for Hesai sensor configuration
struct HesaiSensorConfiguration : LidarConfigurationBase
struct HesaiSensorConfiguration : public LidarConfigurationBase
{
uint16_t gnss_port{};
double scan_phase{};
Expand Down Expand Up @@ -43,24 +46,38 @@ inline std::ostream & operator<<(std::ostream & os, HesaiSensorConfiguration con
return os;
}

struct HesaiCalibrationConfigurationBase : public CalibrationConfigurationBase
{
virtual nebula::Status LoadFromBytes(const std::vector<uint8_t> & buf) = 0;
virtual nebula::Status LoadFromFile(const std::string & calibration_file) = 0;
virtual nebula::Status SaveToFileFromBytes(
const std::string & calibration_file, const std::vector<uint8_t> & buf) = 0;
};

/// @brief struct for Hesai calibration configuration
struct HesaiCalibrationConfiguration : CalibrationConfigurationBase
struct HesaiCalibrationConfiguration : public HesaiCalibrationConfigurationBase
{
std::map<size_t, float> elev_angle_map;
std::map<size_t, float> azimuth_offset_map;

inline nebula::Status LoadFromFile(const std::string & calibration_file)
inline nebula::Status LoadFromFile(const std::string & calibration_file) override
{
std::ifstream ifs(calibration_file);
if (!ifs) {
return Status::INVALID_CALIBRATION_FILE;
}
std::ostringstream ss;
ss << ifs.rdbuf(); // reading data
ss << ifs.rdbuf(); // reading data
ifs.close();
return LoadFromString(ss.str());
}

nebula::Status LoadFromBytes(const std::vector<uint8_t> & buf)
{
std::string calibration_string = std::string(buf.begin(), buf.end());
return LoadFromString(calibration_string);
}

/// @brief Loading calibration data
/// @param calibration_content
/// @return Resulting status
Expand All @@ -70,14 +87,12 @@ struct HesaiCalibrationConfiguration : CalibrationConfigurationBase
ss << calibration_content;
std::string line;
constexpr size_t expected_cols = 3;
while(std::getline(ss, line)) {
while (std::getline(ss, line)) {
boost::char_separator<char> sep(",");
boost::tokenizer<boost::char_separator<char>> tok(line, sep);

std::vector<std::string> actual_tokens(tok.begin(), tok.end());
if (actual_tokens.size() < expected_cols
|| actual_tokens.size() > expected_cols
) {
if (actual_tokens.size() < expected_cols || actual_tokens.size() > expected_cols) {
std::cerr << "Ignoring line with unexpected data:" << line << std::endl;
continue;
}
Expand All @@ -88,18 +103,17 @@ struct HesaiCalibrationConfiguration : CalibrationConfigurationBase
float azimuth = std::stof(actual_tokens[2]);
elev_angle_map[laser_id - 1] = elevation;
azimuth_offset_map[laser_id - 1] = azimuth;
} catch (const std::invalid_argument& ia) {
} catch (const std::invalid_argument & ia) {
continue;
}

}
return Status::OK;
}

/// @brief Saving calibration data (not used)
/// @param calibration_file
/// @return Resulting status
inline nebula::Status SaveFile(const std::string & calibration_file)
inline nebula::Status SaveToFile(const std::string & calibration_file)
{
std::ofstream ofs(calibration_file);
if (!ofs) {
Expand All @@ -117,11 +131,19 @@ struct HesaiCalibrationConfiguration : CalibrationConfigurationBase
return Status::OK;
}

nebula::Status SaveToFileFromBytes(
const std::string & calibration_file, const std::vector<uint8_t> & buf) override
{
std::string calibration_string = std::string(buf.begin(), buf.end());
return SaveFileFromString(calibration_file, calibration_string);
}

/// @brief Saving calibration data from string
/// @param calibration_file path
/// @param calibration_string calibration string
/// @return Resulting status
inline nebula::Status SaveFileFromString(const std::string & calibration_file, const std::string & calibration_string)
inline nebula::Status SaveFileFromString(
const std::string & calibration_file, const std::string & calibration_string)
{
std::ofstream ofs(calibration_file);
if (!ofs) {
Expand All @@ -134,7 +156,7 @@ struct HesaiCalibrationConfiguration : CalibrationConfigurationBase
};

/// @brief struct for Hesai correction configuration (for AT)
struct HesaiCorrection
struct HesaiCorrection : public HesaiCalibrationConfigurationBase
{
uint16_t delimiter;
uint8_t versionMajor;
Expand All @@ -156,12 +178,11 @@ struct HesaiCorrection
/// @brief Load correction data from file
/// @param buf Binary buffer
/// @return Resulting status
inline nebula::Status LoadFromBinary(const std::vector<uint8_t> & buf)
inline nebula::Status LoadFromBytes(const std::vector<uint8_t> & buf) override
{
size_t index;
for (index = 0; index < buf.size()-1; index++) {
if(buf[index]==0xee && buf[index+1]==0xff)
break;
for (index = 0; index < buf.size() - 1; index++) {
if (buf[index] == 0xee && buf[index + 1] == 0xff) break;
}
delimiter = (buf[index] & 0xff) << 8 | ((buf[index + 1] & 0xff));
versionMajor = buf[index + 2] & 0xff;
Expand Down Expand Up @@ -258,7 +279,7 @@ struct HesaiCorrection
/// @brief Load correction data from file
/// @param correction_file path
/// @return Resulting status
inline nebula::Status LoadFromFile(const std::string & correction_file)
inline nebula::Status LoadFromFile(const std::string & correction_file) override
{
std::ifstream ifs(correction_file, std::ios::in | std::ios::binary);
if (!ifs) {
Expand All @@ -268,10 +289,10 @@ struct HesaiCorrection
// int cnt = 0;
while (!ifs.eof()) {
unsigned char c;
ifs.read((char *)&c, sizeof(unsigned char));
ifs.read(reinterpret_cast<char *>(&c), sizeof(unsigned char));
buf.emplace_back(c);
}
LoadFromBinary(buf);
LoadFromBytes(buf);

ifs.close();
return Status::OK;
Expand All @@ -281,7 +302,8 @@ struct HesaiCorrection
/// @param correction_file path
/// @param buf correction binary
/// @return Resulting status
inline nebula::Status SaveFileFromBinary(const std::string & correction_file, const std::vector<uint8_t> & buf)
inline nebula::Status SaveToFileFromBytes(
const std::string & correction_file, const std::vector<uint8_t> & buf) override
{
std::cerr << "Saving in:" << correction_file << "\n";
std::ofstream ofs(correction_file, std::ios::trunc | std::ios::binary);
Expand All @@ -291,21 +313,20 @@ struct HesaiCorrection
}
std::cerr << "Writing start...." << buf.size() << "\n";
bool sop_received = false;
for (const auto &byte : buf) {
for (const auto & byte : buf) {
if (!sop_received) {
if (byte == 0xEE) {
std::cerr << "SOP received....\n";
sop_received = true;
}
}
if(sop_received) {
if (sop_received) {
ofs << byte;
}
}
std::cerr << "Closing file\n";
ofs.close();
if(sop_received)
return Status::OK;
if (sop_received) return Status::OK;
return Status::INVALID_CALIBRATION_FILE;
}

Expand Down Expand Up @@ -435,8 +456,8 @@ inline int IntFromReturnModeHesai(const ReturnMode return_mode, const SensorMode
case SensorModel::HESAI_PANDARQT128:
if (return_mode == ReturnMode::LAST) return 0;
if (return_mode == ReturnMode::STRONGEST) return 1;
if (return_mode == ReturnMode::DUAL_LAST_STRONGEST
|| return_mode == ReturnMode::DUAL) return 2;
if (return_mode == ReturnMode::DUAL_LAST_STRONGEST || return_mode == ReturnMode::DUAL)
return 2;
if (return_mode == ReturnMode::FIRST) return 3;
if (return_mode == ReturnMode::DUAL_LAST_FIRST) return 4;
if (return_mode == ReturnMode::DUAL_FIRST_STRONGEST) return 5;
Expand Down
41 changes: 17 additions & 24 deletions nebula_common/include/nebula_common/nebula_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
#define NEBULA_COMMON_H

#include <nebula_common/point_types.hpp>

#include <boost/tokenizer.hpp>

#include <algorithm>
#include <map>
#include <ostream>
#include <string>
Expand Down Expand Up @@ -342,24 +345,11 @@ enum class datatype {
FLOAT64 = 8
};

enum class PtpProfile {
IEEE_1588v2 = 0,
IEEE_802_1AS,
IEEE_802_1AS_AUTO,
PROFILE_UNKNOWN
};
enum class PtpProfile { IEEE_1588v2 = 0, IEEE_802_1AS, IEEE_802_1AS_AUTO, UNKNOWN_PROFILE };

enum class PtpTransportType {
UDP_IP = 0,
L2,
UNKNOWN_TRANSPORT
};
enum class PtpTransportType { UDP_IP = 0, L2, UNKNOWN_TRANSPORT };

enum class PtpSwitchType {
NON_TSN = 0,
TSN,
UNKNOWN_SWITCH
};
enum class PtpSwitchType { NON_TSN = 0, TSN, UNKNOWN_SWITCH };

/// @brief not used?
struct PointField
Expand Down Expand Up @@ -618,13 +608,14 @@ inline PtpProfile PtpProfileFromString(const std::string & ptp_profile)
{
// Hesai
auto tmp_str = ptp_profile;
std::transform(tmp_str.begin(), tmp_str.end(), tmp_str.begin(),
[](unsigned char c){ return std::tolower(c); });
std::transform(tmp_str.begin(), tmp_str.end(), tmp_str.begin(), [](unsigned char c) {
return std::tolower(c);
});
if (tmp_str == "1588v2") return PtpProfile::IEEE_1588v2;
if (tmp_str == "802.1as") return PtpProfile::IEEE_802_1AS;
if (tmp_str == "automotive") return PtpProfile::IEEE_802_1AS_AUTO;

return PtpProfile::PROFILE_UNKNOWN;
return PtpProfile::UNKNOWN_PROFILE;
}

/// @brief Convert PtpProfile enum to string (Overloading the << operator)
Expand All @@ -643,7 +634,7 @@ inline std::ostream & operator<<(std::ostream & os, nebula::drivers::PtpProfile
case PtpProfile::IEEE_802_1AS_AUTO:
os << "IEEE_802.1AS Automotive";
break;
case PtpProfile::PROFILE_UNKNOWN:
case PtpProfile::UNKNOWN_PROFILE:
os << "UNKNOWN";
break;
}
Expand All @@ -657,8 +648,9 @@ inline PtpTransportType PtpTransportTypeFromString(const std::string & transport
{
// Hesai
auto tmp_str = transport_type;
std::transform(tmp_str.begin(), tmp_str.end(), tmp_str.begin(),
[](unsigned char c){ return std::tolower(c); });
std::transform(tmp_str.begin(), tmp_str.end(), tmp_str.begin(), [](unsigned char c) {
return std::tolower(c);
});
if (tmp_str == "udp") return PtpTransportType::UDP_IP;
if (tmp_str == "l2") return PtpTransportType::L2;

Expand Down Expand Up @@ -692,8 +684,9 @@ inline PtpSwitchType PtpSwitchTypeFromString(const std::string & switch_type)
{
// Hesai
auto tmp_str = switch_type;
std::transform(tmp_str.begin(), tmp_str.end(), tmp_str.begin(),
[](unsigned char c){ return std::tolower(c); });
std::transform(tmp_str.begin(), tmp_str.end(), tmp_str.begin(), [](unsigned char c) {
return std::tolower(c);
});
if (tmp_str == "tsn") return PtpSwitchType::TSN;
if (tmp_str == "non_tsn") return PtpSwitchType::NON_TSN;

Expand Down
Loading
Loading