- 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>
111 lines
4.0 KiB
C++
111 lines
4.0 KiB
C++
#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
|