查看“Detour”的源代码
←
Detour
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
管理员
您可以查看和复制此页面的源代码。
= DetourLite独立插件开发 = == 1. 前言 == Detour仓库里的 `Standalone` 目录给出了一个可直接复用的扩展方式:把扩展代码单独编译成 `*Plugin.dll`,部署到 DetourLite 的 `plugins` 目录,在不改动 `DetourCore` / `DetourDance` 主工程的前提下扩展算法核。 这种 Standalone Plugin 适合以下场景: * 增加自定义 HTTP API。 * 对接 ROS2、原生 C/C++ 动态库、UDP/TCP 传感器。 * 新增自定义 2D / 3D 传感器组件类型。 * 在启动时执行一次性初始化逻辑。 仓库中的参考工程: * `Standalone/DemoPlugin` * `Standalone/StandaloneSensors` * `Standalone/DllImportSensor` == 2. 加载机制 == DetourLite 的插件加载逻辑在 `DetourLite/DetourLiteMain.cs` 中,规则很直接: * 启动时扫描当前目录下 `plugins` 文件夹以及所有子目录。 * 所有文件名匹配 `*Plugin.dll` 的程序集都会被 `Assembly.LoadFrom(...)` 加载。 * 如果程序集里导出了一个名为 `Plugin` 的类,并且该类里存在 `static void Main()`,则该方法会在 `DetourLib.Init()` 之后被调用。 因此有两个层次的能力: * 只要 DLL 名称以 `Plugin.dll` 结尾,程序集就会被加载。 * 如果还提供 `Plugin.Main()`,就可以执行启动初始化逻辑。 这意味着: * '''纯组件型插件''' 可以只提供导出的组件类,不一定非要写 `Plugin.Main()`。 * '''启动型插件''' 则应提供 `Plugin.Main()`,在里面注册 HTTP 路由、启动线程、初始化第三方库等。 == 3. 组件是如何注册进 Detour 的 == DetourCore 使用 `DetourCore/Misc/JSONLoader.cs` 从当前 AppDomain 中所有已加载程序集的导出类型里查找组件类型。 所以自定义组件要满足下面几个条件: * 类型必须是 `public`。 * 类型必须继承 `LayoutDefinition.Component`,通常继承 `Lidar.Lidar2D` 或 `DetourDance.Lidar3D`。 * 类型必须有无参构造函数。 * 类型所在程序集必须在 Detour 读取 `detour.json` 之前已经被加载。 组件类型通常用属性声明: <syntaxhighlight lang="csharp"> [LayoutDefinition.ComponentType(Name = "ROS2d lidar")] public class ROS2Lidar2D : Lidar.Lidar2D { } </syntaxhighlight> 公开字段可配合以下属性暴露到参数界面和状态输出: * `FieldMember` * `StatusMember` * `MethodMember` == 4. 你可以做的两类插件 == === 4.1 启动型插件 === 这类插件只关心 DetourLite 启动后执行逻辑,不一定要新增配置里的组件类型。最常见用途是挂额外 API。 `Standalone/DemoPlugin/loader.cs` 就是这种模式。它在 `Plugin.Main()` 里注册了: * `/eraseCloud` * `/get2dlm` * `/mycall` * `/getPCD` 最小示例: <syntaxhighlight lang="csharp"> using DetourCore; namespace MyStandalonePlugin { public class Plugin { public static void Main() { PicoHttpServer.AddGetHandler("/helloPlugin", () => { return "hello from standalone plugin"; }); } } } </syntaxhighlight> === 4.2 组件型插件 === 这类插件把新传感器或新部件编译进独立 DLL,让 DetourLite 在读取 `detour.json` 时识别出来。 仓库里的对应示例: * `Standalone/DemoPlugin/ros2lidar2d.cs` * `Standalone/StandaloneSensors/Mid360Lidar.cs` * `Standalone/StandaloneSensors/LeishenC16Lidar.cs` * `Standalone/DllImportSensor/CppLidar.cs` == 5. 2D 传感器插件写法 == 2D 传感器通常继承 `DetourCore.CartDefinition.Lidar.Lidar2D`,重点是重写两个方法: * `InitReadLidar()` * `ReadLidar()` 最小骨架: <syntaxhighlight lang="csharp"> using System.Threading; using DetourCore.CartDefinition; [LayoutDefinition.ComponentType(Name = "My UDP Lidar")] public class MyUdpLidar : Lidar.Lidar2D { private readonly object sync = new(); private Lidar.LidarFrame latest = new(); private int scanC = 0; public override void InitReadLidar() { new Thread(() => { while (true) { latest = new Lidar.LidarFrame() { counter = ++scanC, raw = new[] { new Lidar.Lidar2D.RawLidar { th = 0, d = 1000, intensity = 1 } } }; lock (sync) Monitor.PulseAll(sync); } }).Start(); } public override Lidar.LidarFrame ReadLidar() { lock (sync) Monitor.Wait(sync); return latest; } } </syntaxhighlight> 2D 输出约定: * `th`:角度,单位是 '''度'''。 * `d`:距离,单位是 '''毫米'''。 * `intensity`:反射强度,`float`。 * `counter`:单调递增帧号。 Detour 的 2D 预处理、去拖尾、车体滤波、反光板提取、激光里程计等逻辑都在基类中完成,所以插件作者只需要稳定地产生原始帧。 == 6. 3D 传感器插件写法 == 3D 传感器通常继承 `DetourDance.Lidar3D`,同样重写: * `InitReadLidar()` * `ReadLidar()` 3D 返回值是 `LidarOutput3D`,关键字段如下: * `azimuth`:水平角,单位度。 * `altitude`:俯仰角,单位度。 * `d`:距离,单位毫米。 * `intensity`:反射强度。 * `progression`:该点在当前扫描周期里的进度,推荐归一化到 `0..1`。 * `tick`:单调递增扫描序号。 如果你的数据源来自原生库,可以参考 `Standalone/DllImportSensor/CppLidar.cs`;如果来自 ROS2,可以参考 `Standalone/DemoPlugin/ros2lidar2d.cs`;如果来自 UDP 包流,可以参考 `Standalone/StandaloneSensors/*`。 == 7. 开发环境与引用 DLL == Detour 独立插件不是通过 NuGet 分发 SDK,而是直接引用发布到 MDCS 站点的参考 DLL。 运行包下载入口: * [https://dl.lessokaji.com MDCS 下载站] * [https://dl.lessokaji.com/prebaked 预配置下载集合] 插件开发常用引用: * [https://mdcs.lessokaji.com/dependencies/Detour/RefDetourCore.dll RefDetourCore.dll] * [https://mdcs.lessokaji.com/dependencies/Detour/RefDetourDance.dll RefDetourDance.dll] * [https://mdcs.lessokaji.com/dependencies/RefFundamentalLib.dll RefFundamentalLib.dll] * [https://mdcs.lessokaji.com/dependencies/LessokajiWeaverUtilities.dll LessokajiWeaverUtilities.dll] 可选辅助引用: * [https://mdcs.lessokaji.com/dependencies/RefLessokajiProtect.dll RefLessokajiProtect.dll] * [https://mdcs.lessokaji.com/dependencies/LessokajiWeaver.Fody.dll LessokajiWeaver.Fody.dll] 为方便拉取这些 DLL,提供一个下载脚本: * [https://mdcs.lessokaji.com/res/get-detour-plugin-sdk.ps1 get-detour-plugin-sdk.ps1] 典型用法: <syntaxhighlight lang="powershell"> Invoke-WebRequest ` -Uri "https://mdcs.lessokaji.com/res/get-detour-plugin-sdk.ps1" ` -OutFile ".\get-detour-plugin-sdk.ps1" powershell -ExecutionPolicy Bypass ` -File .\get-detour-plugin-sdk.ps1 ` -Destination .\tools </syntaxhighlight> 执行后会得到: * `tools\RefDetourCore.dll` * `tools\RefDetourDance.dll` * `tools\deps\RefFundamentalLib.dll` * `tools\deps\LessokajiWeaverUtilities.dll` == 8. csproj 参考写法 == `Standalone/DemoPlugin/DemoPlugin.csproj` 给出了一个可直接工作的最小模式。 一个简化版示例如下: <syntaxhighlight lang="xml"> <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Library</OutputType> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <Reference Include="FundamentalLib"> <HintPath>..\tools\deps\RefFundamentalLib.dll</HintPath> </Reference> <Reference Include="DetourCore"> <HintPath>..\tools\RefDetourCore.dll</HintPath> </Reference> <Reference Include="DetourDance"> <HintPath>..\tools\RefDetourDance.dll</HintPath> </Reference> <Reference Include="LessokajiWeaverUtilities"> <HintPath>..\tools\deps\LessokajiWeaverUtilities.dll</HintPath> </Reference> </ItemGroup> </Project> </syntaxhighlight> 如果希望本地构建后直接落到运行目录,可以像 `Standalone/DemoPlugin` 那样把 `OutputPath` 设到 DetourLite 的 `plugins` 目录,这对调试最方便。 == 9. 构建与部署 == 建议流程: # 在独立工程中编译插件 DLL。 # 确认文件名以 `Plugin.dll` 结尾,例如 `StandaloneSensorsPlugin.dll`。 # 把 DLL 复制到 DetourLite 运行目录下的 `plugins` 子目录。 # 如果插件依赖额外原生库,也一起放到 DetourLite 可搜索到的位置。 # 启动 DetourLite,检查控制台是否打印: #* 找到并加载了 `*Plugin.dll` #* 找到了 `Plugin.Main()` #* 或至少程序集被成功加载 本仓库当前已验证可编译的示例: * `Standalone/DemoPlugin` * `Standalone/StandaloneSensors` * `Standalone/DllImportSensor` == 10. 当前限制 == 这一点非常重要: * '''DetourLite''' 当前会自动扫描 `plugins\*Plugin.dll`。 * '''Windows 版 Detour.exe''' 当前仓库里 '''没有''' 对等的自动插件加载器。 这会带来两个直接影响: * 如果插件只是给 DetourLite 增加 HTTP API,这没有问题。 * 如果插件新增了自定义组件类型,而你又想在 Windows `Detour.exe` 里直接通过 UI 新建、编辑、加载这种组件,那么客户端进程也必须先把同一个程序集加载进来,否则 UI 的类型列表和 JSON 反序列化都看不到该类型。 换句话说,'''当前代码最稳妥的使用方式''' 是: * 纯扩展 API:只部署到 DetourLite。 * 自定义组件:优先用于 Lite 端独立运行场景;如果还要配合 Windows UI 使用,则需要让客户端也加载同一个插件程序集。 == 11. 推荐开发方法 == 结合仓库里的 `Standalone` 示例,推荐按下面的顺序开发: # 先做一个只包含 `Plugin.Main()` 的最小插件,确认 DLL 能被 DetourLite 发现并执行。 # 再加一个最小 HTTP 路由,确认运行时初始化逻辑没问题。 # 如果要接传感器,再新建一个继承 `Lidar2D` 或 `Lidar3D` 的类型,先返回最小假数据。 # 假数据跑通后,再接入 ROS2 / UDP / 原生 DLL 等真实数据源。 # 最后再补 `FieldMember` / `StatusMember`,把参数和状态整理到可维护的程度。 这样排查最简单,能快速区分是: * 加载失败, * 初始化失败, * 组件识别失败, * 还是数据源本身有问题。 == 12. 结语 == Standalone Plugin 的核心价值是:'''把项目级扩展放在独立 DLL 里维护,而不是不断改 Detour 主工程'''。对于项目交付、客户定制、特定传感器桥接、快速试验都更合适。 如果只是想扩 API,写启动型插件即可;如果要接自定义雷达,就按 `Lidar2D` / `Lidar3D` 的约定返回原始帧,让 Detour 继续负责后面的预处理和 SLAM 计算。
返回
Detour
。
导航菜单
个人工具
中文(中国大陆)
创建账号
登录
命名空间
页面
讨论
大陆简体
查看
阅读
查看源代码
查看历史
更多
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息