refactor: restructure lidarlib into xlidar-driver plugin SDK
- LidarManager facade (liblidar_manager.so): dlopen plugin discovery, available_drivers map<driver_id, PluginRegistry>, create_lidar_device, config.json load/save with legacy lidarlib migration - Common LidarDriverInterface + DriverInfo/DeviceConfig plugin ABI (extern C get_driver_info / create_driver_instance) - Plugins: driver_rplidar (ported from xlocd, Slamtec SDK), driver_olei, driver_sick_code (TiM CoLa-A), driver_sick_safety (nanoScan3), driver_espe - Diagnostics extended with rplidar health + firmware; FOV filter window, range override and legacy remap window unified in DeviceConfig - Rewritten README, diagnostics doc and examples (list_drivers, example, lidar_app) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
110
include/lidar_manager.hpp
Normal file
110
include/lidar_manager.hpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
// xlidar-driver — LidarManager: the host-facing facade of the SDK.
|
||||
//
|
||||
// The manager scans a plugin directory for driver .so files, registers their
|
||||
// DriverInfo, and creates driver instances by driver_id:
|
||||
//
|
||||
// xlidar::LidarManager manager("/opt/xlidar/plugins");
|
||||
// manager.load_all_plugins();
|
||||
// for (const auto& [id, plugin] : manager.available_drivers())
|
||||
// printf("%s — %s\n", id.c_str(), plugin.info.description.c_str());
|
||||
//
|
||||
// xlidar::DeviceConfig cfg;
|
||||
// cfg.driver_id = "rplidar_c1_driver";
|
||||
// cfg.serial_port = "/dev/ttyUSB0";
|
||||
// auto lidar = manager.create_lidar_device(cfg);
|
||||
//
|
||||
// Plugins stay loaded until the manager is destroyed; the manager must
|
||||
// outlive every device instance it created (instances execute code that
|
||||
// lives inside the plugin .so).
|
||||
|
||||
#include "lidar_interface.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace xlidar {
|
||||
|
||||
// One discovered plugin: its registered identity plus where it came from.
|
||||
struct PluginRegistry {
|
||||
DriverInfo info;
|
||||
std::string file_path; // absolute path of the plugin .so
|
||||
};
|
||||
|
||||
// Configuration document (config.json): a named list of lidar devices.
|
||||
struct ManagerConfig {
|
||||
std::vector<DeviceConfig> lidars;
|
||||
};
|
||||
|
||||
// Returns defaults if the file doesn't exist (without creating it).
|
||||
// Legacy lidarlib entries ({"brand": "OLEI"|"SICK"|"ESPE", ...}) are
|
||||
// migrated on the fly: brand+model resolve to the matching driver_id and the
|
||||
// old angle window keys map to the remap fields.
|
||||
ManagerConfig load_config(const std::string& path);
|
||||
|
||||
void save_config(const std::string& path, const ManagerConfig& cfg);
|
||||
|
||||
class LidarManager {
|
||||
public:
|
||||
// plugins_dir: directory holding the driver .so files. Nothing is
|
||||
// touched until load_all_plugins() runs.
|
||||
explicit LidarManager(std::string plugins_dir);
|
||||
~LidarManager();
|
||||
|
||||
LidarManager(const LidarManager&) = delete;
|
||||
LidarManager& operator=(const LidarManager&) = delete;
|
||||
|
||||
// Scan plugins_dir for *.so, dlopen each, resolve get_driver_info /
|
||||
// create_driver_instance, and register the driver. Files that are not
|
||||
// valid plugins (missing symbols, dlopen failure) are skipped with a
|
||||
// message on stderr. Safe to call again to pick up newly added files
|
||||
// (already-loaded driver_ids are kept, not reloaded). Returns the number
|
||||
// of drivers registered in total.
|
||||
size_t load_all_plugins();
|
||||
|
||||
// Registered drivers keyed by driver_id. Stable while the manager lives;
|
||||
// load_all_plugins() may add entries.
|
||||
const std::map<std::string, PluginRegistry>& available_drivers() const {
|
||||
return available_;
|
||||
}
|
||||
|
||||
bool has_driver(const std::string& driver_id) const {
|
||||
return available_.count(driver_id) != 0;
|
||||
}
|
||||
|
||||
// Create a device instance from the plugin registered for driver_id.
|
||||
// nullptr if driver_id is unknown. The instance is independent and
|
||||
// thread-safe to pump from its own thread; it must be destroyed before
|
||||
// the manager.
|
||||
std::unique_ptr<LidarDriverInterface>
|
||||
create_lidar_device(const std::string& driver_id, const DeviceConfig& cfg);
|
||||
|
||||
// Convenience: driver_id taken from cfg.driver_id.
|
||||
std::unique_ptr<LidarDriverInterface> create_lidar_device(const DeviceConfig& cfg) {
|
||||
return create_lidar_device(cfg.driver_id, cfg);
|
||||
}
|
||||
|
||||
// Convenience: one instance per entry of a config.json document (see
|
||||
// load_config). Entries whose driver_id is not available are skipped
|
||||
// with a message on stderr.
|
||||
std::vector<std::unique_ptr<LidarDriverInterface>>
|
||||
create_from_config_file(const std::string& path);
|
||||
|
||||
const std::string& plugins_dir() const { return plugins_dir_; }
|
||||
|
||||
private:
|
||||
struct LoadedPlugin {
|
||||
void* handle = nullptr; // dlopen handle
|
||||
xlidar_create_driver_instance_fn create = nullptr;
|
||||
};
|
||||
|
||||
std::string plugins_dir_;
|
||||
std::map<std::string, PluginRegistry> available_;
|
||||
std::map<std::string, LoadedPlugin> loaded_;
|
||||
mutable std::mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace xlidar
|
||||
Reference in New Issue
Block a user