diff --git a/README.md b/README.md
index 3507e6d..ffac5d3 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
- 宿主只保留 ASP.NET Core HTTP 控制器层,以及其后端 `Flyshot.ControllerClientCompat` 兼容服务。
- `ExecuteTrajectory` 与 `ExecuteFlyShotTraj` 已经接入 `Planning + Triggering + Runtime` 链路;Web 状态页已通过 `/status` 和 `/api/status/snapshot` 暴露当前兼容层与运行时状态。
- `Flyshot.Core.Planning` 的 ICSP / self-adapt-icsp 轨迹已经完成旧系统导出轨迹对齐;`doubles` 仍未实现。
-- `Flyshot.Native.Planning` 已提供显式 Rust ICSP 规划入口,通过 C ABI 调用 `flyshot_native_planning`;普通轨迹和飞拍轨迹可使用准确参数 `method="icsp_rust"` 选择该后端,默认 `icsp` 仍使用 C# `ICspPlanner`。
+- `Flyshot.Native.Planning` 已提供显式 Rust ICSP 规划入口,通过 C ABI 调用 `flyshot_planning`;普通轨迹和飞拍轨迹可使用准确参数 `method="icsp_rust"` 选择该后端,默认 `icsp` 仍使用 C# `ICspPlanner`。
- `Flyshot.Runtime.Fanuc` 已固化 `10010 / 10012 / 60015` 基础协议帧编解码。`10010` 状态通道以 `j519 协议.pcap` 和 `Rvbust/uttc-20260428/20260428.pcap` 真机抓包确认为 90B 固定帧。
- 2026-04-28 UTTC 抓包确认:UDP 60015 命令 `target[0..5]` 为关节角度制 `deg`,`JointDetialTraj.txt` 为弧度制 `rad`,`speed_ratio=0.7` 体现为 UDP 下发时间轴约 `1.427730x` 拉伸;2026-04-30 实体机确认 `speed_ratio` 不影响生成的 `JointTraj.txt` 规划时长,当前实际生成约 `7.4s` 轨迹。
- 2026-04-30 本机 `50001/TCP+JSON` 抓包确认:`ExecuteFlyShotTraj(save_traj=true,use_cache=false)` 请求只显式携带规划方法、保存、缓存和等待参数,不携带 `JointLimits / acc_limit / jerk_limit / velocity / acceleration / jerk`。因此旧系统不可见的有效规划限制不再继续假设来自公开链路,新系统按 replacement-only 内部参数限制规划加速度。
@@ -96,13 +96,15 @@ Windows x64 需要安装:
.\build\Copy-NativePlanningArtifacts.ps1 -Configuration Release
```
-脚本会通过 `vcvars64.bat` 初始化 MSVC 环境,构建
-`native/flyshot-native-planning/target/release/flyshot_native_planning.dll`,
-并默认复制到 `tests/Flyshot.Core.Tests/bin/Release/net8.0/`。发布服务时可通过
+脚本会执行 `cargo build --release`,构建
+`native/flyshot-native-planning/target/release/flyshot_planning.dll`,
+并默认复制到 `src/Libs/flyshot_planning.dll` 与
+`tests/Flyshot.Core.Tests/bin/Release/net8.0/`。发布服务时可通过
`-DestinationDirectories` 把原生库复制到实际发布目录。
Linux x64 在已安装 `stable-x86_64-unknown-linux-gnu` 工具链的 Linux 环境执行同一脚本,
-产物为 `libflyshot_native_planning.so`。Windows 第一阶段不要求交叉编译 Linux 原生库。
+产物为 `libflyshot_planning.so`,默认写入 `src/Libs/libflyshot_planning.so`。
+Windows 第一阶段不要求交叉编译 Linux 原生库。
剩余 Todo:
diff --git a/build/Copy-NativePlanningArtifacts.ps1 b/build/Copy-NativePlanningArtifacts.ps1
index 91e9e5b..768825d 100644
--- a/build/Copy-NativePlanningArtifacts.ps1
+++ b/build/Copy-NativePlanningArtifacts.ps1
@@ -1,94 +1,76 @@
+<#
+.SYNOPSIS
+构建 Rust ICSP 原生规划库并复制到 src/Libs 与可选目标目录。
+
+.DESCRIPTION
+在 Windows x64 上通过 cargo release 构建 flyshot_planning,默认写入
+src/Libs/flyshot_planning.dll;Linux x64 写入 src/Libs/libflyshot_planning.so。
+可通过 -DestinationDirectories 额外复制到测试或发布输出目录。
+
+.PARAMETER Configuration
+传递给 dotnet 相关路径的构建配置名,默认 Release。
+
+.PARAMETER DestinationDirectories
+除 src/Libs 外需要覆盖复制的额外目标目录列表。
+#>
+
+[CmdletBinding()]
param(
- [ValidateSet("Debug", "Release")]
- [string]$Configuration = "Release",
+ [ValidateSet('Debug', 'Release')]
+ [string]$Configuration = 'Release',
[string[]]$DestinationDirectories = @()
)
-$ErrorActionPreference = "Stop"
+$ErrorActionPreference = 'Stop'
+Set-StrictMode -Version Latest
-# 从脚本位置定位仓库根目录,确保从任意工作目录调用都得到一致结果。
-$repositoryRoot = Split-Path -Parent $PSScriptRoot
-$manifestPath = Join-Path $repositoryRoot "native/flyshot-native-planning/Cargo.toml"
-$cargoExecutable = if ($IsWindows) { "cargo.exe" } else { "cargo" }
-$cargoPath = Join-Path $HOME ".cargo/bin/$cargoExecutable"
-if (-not (Test-Path -LiteralPath $cargoPath)) {
- throw "未找到 Rust Cargo:$cargoPath。请先通过 rustup 安装 stable-x86_64-pc-windows-msvc。"
+$repositoryRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
+$cargoManifest = Join-Path $repositoryRoot 'native\flyshot-native-planning\Cargo.toml'
+$libsDirectory = Join-Path $repositoryRoot 'src\Libs'
+$cargoProfile = if ($Configuration -eq 'Debug') { 'debug' } else { 'release' }
+$targetDirectory = Join-Path $repositoryRoot "native\flyshot-native-planning\target\$cargoProfile"
+
+if ($IsLinux -or (-not $IsWindows -and -not $IsMacOS))
+{
+ $artifactFileName = 'libflyshot_planning.so'
+}
+else
+{
+ $artifactFileName = 'flyshot_planning.dll'
}
-$cargoArguments = @("build", "--manifest-path", $manifestPath)
-if ($Configuration -eq "Release") {
- $cargoArguments += "--release"
+$builtArtifactPath = Join-Path $targetDirectory $artifactFileName
+$libsArtifactPath = Join-Path $libsDirectory $artifactFileName
+
+Write-Host "正在构建 Rust 原生规划库 ($Configuration) ..."
+& cargo build --manifest-path $cargoManifest --$Configuration
+if ($LASTEXITCODE -ne 0)
+{
+ throw "cargo build 失败,退出码:$LASTEXITCODE"
}
-if ($IsWindows) {
- # Windows MSVC 目标必须在 VS C++ 开发者环境中运行,避免 PATH 中其他 link.exe 抢占。
- $vswherePath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
- if (-not (Test-Path -LiteralPath $vswherePath)) {
- throw "未找到 vswhere.exe,无法定位 Visual Studio C++ Build Tools。"
+if (-not (Test-Path -LiteralPath $builtArtifactPath -PathType Leaf))
+{
+ throw "未找到构建产物:$builtArtifactPath"
+}
+
+New-Item -ItemType Directory -Path $libsDirectory -Force | Out-Null
+Copy-Item -LiteralPath $builtArtifactPath -Destination $libsArtifactPath -Force
+Write-Host "已复制到:$libsArtifactPath"
+
+$defaultTestOutput = Join-Path $repositoryRoot "tests\Flyshot.Core.Tests\bin\$Configuration\net8.0"
+$allDestinations = @($DestinationDirectories) + @($defaultTestOutput)
+
+foreach ($destination in $allDestinations | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique)
+{
+ $absoluteDestination = [System.IO.Path]::GetFullPath($destination)
+ if (-not (Test-Path -LiteralPath $absoluteDestination -PathType Container))
+ {
+ Write-Host "跳过不存在的目标目录:$absoluteDestination"
+ continue
}
- $installationPath = & $vswherePath -latest -products * `
- -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
- -property installationPath
- if ([string]::IsNullOrWhiteSpace($installationPath)) {
- throw "未找到已安装的 Visual Studio C++ x64 编译工具。"
- }
-
- $vcvarsPath = Join-Path $installationPath "VC/Auxiliary/Build/vcvars64.bat"
- if (-not (Test-Path -LiteralPath $vcvarsPath)) {
- throw "未找到 VS x64 开发者环境脚本:$vcvarsPath"
- }
-
- $quotedArguments = $cargoArguments | ForEach-Object { '"' + $_.Replace('"', '\"') + '"' }
- $command = 'call "{0}" >nul && "{1}" {2}' -f `
- $vcvarsPath, $cargoPath, ($quotedArguments -join " ")
- & cmd.exe /d /c $command
- if ($LASTEXITCODE -ne 0) {
- throw "Rust 原生规划库构建失败,退出码:$LASTEXITCODE"
- }
-}
-else {
- & $cargoPath @cargoArguments
- if ($LASTEXITCODE -ne 0) {
- throw "Rust 原生规划库构建失败,退出码:$LASTEXITCODE"
- }
-}
-
-$profileDirectory = if ($Configuration -eq "Release") { "release" } else { "debug" }
-$libraryName = if ($IsWindows) {
- "flyshot_native_planning.dll"
-}
-elseif ($IsLinux) {
- "libflyshot_native_planning.so"
-}
-else {
- throw "当前脚本仅支持 Windows x64 和 Linux x64。"
-}
-$sourcePath = Join-Path $repositoryRoot "native/flyshot-native-planning/target/$profileDirectory/$libraryName"
-if (-not (Test-Path -LiteralPath $sourcePath)) {
- throw "Rust 构建已结束,但未找到原生库:$sourcePath"
-}
-
-# 未显式指定目标时,默认复制到对应配置的 Core 测试输出目录。
-if ($DestinationDirectories.Count -eq 0) {
- $DestinationDirectories = @(
- (Join-Path $repositoryRoot "tests/Flyshot.Core.Tests/bin/$Configuration/net8.0")
- )
-}
-
-foreach ($destinationDirectory in $DestinationDirectories) {
- $destinationPath = if ([System.IO.Path]::IsPathRooted($destinationDirectory)) {
- $destinationDirectory
- }
- else {
- Join-Path $repositoryRoot $destinationDirectory
- }
- $resolvedDestination = [System.IO.Path]::GetFullPath(
- $destinationPath)
- New-Item -ItemType Directory -Force -Path $resolvedDestination | Out-Null
- Copy-Item -LiteralPath $sourcePath `
- -Destination (Join-Path $resolvedDestination $libraryName) `
- -Force
- Write-Host "已复制原生规划库到:$resolvedDestination"
+ Copy-Item -LiteralPath $builtArtifactPath -Destination (Join-Path $absoluteDestination $artifactFileName) -Force
+ Write-Host "已复制到:$absoluteDestination\$artifactFileName"
}
diff --git a/native/flyshot-native-planning/Cargo.lock b/native/flyshot-native-planning/Cargo.lock
index 01366c1..483863d 100644
--- a/native/flyshot-native-planning/Cargo.lock
+++ b/native/flyshot-native-planning/Cargo.lock
@@ -3,5 +3,5 @@
version = 4
[[package]]
-name = "flyshot-native-planning"
+name = "flyshot_planning"
version = "0.1.0"
diff --git a/native/flyshot-native-planning/Cargo.toml b/native/flyshot-native-planning/Cargo.toml
index df0b305..027d6b5 100644
--- a/native/flyshot-native-planning/Cargo.toml
+++ b/native/flyshot-native-planning/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "flyshot-native-planning"
+name = "flyshot_planning"
version = "0.1.0"
edition = "2021"
diff --git a/scripts/Publish-Obfuscated.ps1 b/scripts/Publish-Obfuscated.ps1
index 99ef877..9d4f9b2 100644
--- a/scripts/Publish-Obfuscated.ps1
+++ b/scripts/Publish-Obfuscated.ps1
@@ -427,6 +427,13 @@ function Install-ObfuscatedAssemblies
$_.Name -like 'Flyshot*.pdb'
} |
Remove-Item -Force
+
+ # Rust ICSP 原生库必须随框架依赖包一起交付,否则 method=icsp_rust 会在运行时加载失败。
+ $nativePlanningLibraryPath = Join-Path $PublishedDirectory 'flyshot_planning.dll'
+ if (-not (Test-Path -LiteralPath $nativePlanningLibraryPath -PathType Leaf))
+ {
+ throw "发布目录缺少 Rust 原生规划库 flyshot_planning.dll:$nativePlanningLibraryPath"
+ }
}
<#
diff --git a/src/Flyshot.Native.Planning/NativePlanningLibraryResolver.cs b/src/Flyshot.Native.Planning/NativePlanningLibraryResolver.cs
index f03ec96..8197a11 100644
--- a/src/Flyshot.Native.Planning/NativePlanningLibraryResolver.cs
+++ b/src/Flyshot.Native.Planning/NativePlanningLibraryResolver.cs
@@ -17,7 +17,7 @@ public sealed class NativePlanningLibraryResolver
///
/// 原生规划库的逻辑名称。
///
- public const string LogicalLibraryName = "flyshot_native_planning";
+ public const string LogicalLibraryName = "flyshot_planning";
private readonly Func _resolveLibraryPath;
@@ -92,8 +92,8 @@ public sealed class NativePlanningLibraryResolver
string fileName = platform.OperatingSystem switch
{
- "Windows" => "flyshot_native_planning.dll",
- "Linux" => "libflyshot_native_planning.so",
+ "Windows" => "flyshot_planning.dll",
+ "Linux" => "libflyshot_planning.so",
_ => throw new NativePlanningException(
$"Rust 原生规划库不支持当前操作系统:{platform.OperatingSystem}。",
errorCode: -1003)
diff --git a/src/Flyshot.Server.Host/Flyshot.Server.Host.csproj b/src/Flyshot.Server.Host/Flyshot.Server.Host.csproj
index 2065feb..2867803 100644
--- a/src/Flyshot.Server.Host/Flyshot.Server.Host.csproj
+++ b/src/Flyshot.Server.Host/Flyshot.Server.Host.csproj
@@ -16,6 +16,9 @@
+
+
+
diff --git a/src/Libs/flyshot_planning.dll b/src/Libs/flyshot_planning.dll
new file mode 100644
index 0000000..6454182
Binary files /dev/null and b/src/Libs/flyshot_planning.dll differ
diff --git a/src/Libs/libflyshot_planning.so b/src/Libs/libflyshot_planning.so
new file mode 100644
index 0000000..5b3f408
Binary files /dev/null and b/src/Libs/libflyshot_planning.so differ
diff --git a/tests/Flyshot.Core.Tests/Flyshot.Core.Tests.csproj b/tests/Flyshot.Core.Tests/Flyshot.Core.Tests.csproj
index 99129ec..c0c4b40 100644
--- a/tests/Flyshot.Core.Tests/Flyshot.Core.Tests.csproj
+++ b/tests/Flyshot.Core.Tests/Flyshot.Core.Tests.csproj
@@ -32,4 +32,10 @@
+
+
+
+
+
+