# Unity-MoveIt2 系统快速部署脚本 (Windows PowerShell) # 此脚本自动化部署Unity-MoveIt2系统的所有组件 param( [string]$Mode = "full", # full, ros2-only, unity-only [string]$RobotName = "niryo_one", [switch]$SkipDocker = $false, [switch]$Development = $false, [switch]$Verbose = $false ) # 设置错误处理 $ErrorActionPreference = "Stop" # 颜色输出函数 function Write-ColorOutput { param( [string]$Message, [string]$Color = "White" ) $colors = @{ "Red" = [ConsoleColor]::Red "Green" = [ConsoleColor]::Green "Yellow" = [ConsoleColor]::Yellow "Blue" = [ConsoleColor]::Blue "Cyan" = [ConsoleColor]::Cyan "White" = [ConsoleColor]::White } Write-Host $Message -ForegroundColor $colors[$Color] } function Write-Step { param([string]$Message) Write-ColorOutput "🔄 $Message" "Cyan" } function Write-Success { param([string]$Message) Write-ColorOutput "✅ $Message" "Green" } function Write-Warning { param([string]$Message) Write-ColorOutput "⚠️ $Message" "Yellow" } function Write-Error { param([string]$Message) Write-ColorOutput "❌ $Message" "Red" } # 检查系统要求 function Test-SystemRequirements { Write-Step "检查系统要求..." # 检查PowerShell版本 if ($PSVersionTable.PSVersion.Major -lt 5) { throw "需要PowerShell 5.0或更高版本" } # 检查操作系统 if (-not $IsWindows -and $PSVersionTable.PSVersion.Major -ge 6) { Write-Warning "此脚本主要为Windows设计" } # 检查Docker(如果需要) if (-not $SkipDocker) { try { $dockerVersion = docker --version Write-Success "Docker已安装: $dockerVersion" } catch { Write-Warning "Docker未安装或不可用,将跳过Docker部署" $script:SkipDocker = $true } } # 检查Git try { $gitVersion = git --version Write-Success "Git已安装: $gitVersion" } catch { throw "Git未安装,请先安装Git" } # 检查Python(用于ROS2) try { $pythonVersion = python --version Write-Success "Python已安装: $pythonVersion" } catch { Write-Warning "Python未安装,ROS2功能可能不可用" } Write-Success "系统要求检查完成" } # 创建目录结构 function New-ProjectStructure { Write-Step "创建项目目录结构..." $directories = @( "logs", "cache", "temp", "backup", "models", "unity-project/Assets/Scripts", "unity-project/Assets/Prefabs", "unity-project/Assets/Materials", "ros2-workspace/src", "ros2-workspace/build", "ros2-workspace/install", "analysis-service/src", "analysis-service/config" ) foreach ($dir in $directories) { $fullPath = Join-Path $PWD $dir if (-not (Test-Path $fullPath)) { New-Item -ItemType Directory -Path $fullPath -Force | Out-Null if ($Verbose) { Write-Host " 创建目录: $dir" } } } Write-Success "目录结构创建完成" } # 安装ROS2依赖 function Install-ROS2Dependencies { Write-Step "安装ROS2依赖..." # 检查是否在WSL环境中 if ($env:WSL_DISTRO_NAME) { Write-ColorOutput "检测到WSL环境,使用Linux安装方式" "Blue" # 在WSL中安装ROS2 $wslCommands = @( "sudo apt update", "sudo apt install -y curl gnupg2 lsb-release", "curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg", "echo 'deb [arch=`$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu `$(. /etc/os-release && echo `$UBUNTU_CODENAME) main' | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null", "sudo apt update", "sudo apt install -y ros-humble-desktop", "sudo apt install -y ros-humble-moveit", "sudo apt install -y python3-colcon-common-extensions" ) foreach ($cmd in $wslCommands) { Write-Host "执行: $cmd" wsl bash -c $cmd } } else { Write-ColorOutput "Windows环境,请手动安装ROS2 Humble" "Yellow" Write-Host "下载地址: https://github.com/ros2/ros2/releases" } Write-Success "ROS2依赖安装完成" } # 构建ROS2工作空间 function Build-ROS2Workspace { Write-Step "构建ROS2工作空间..." $workspacePath = Join-Path $PWD "ros2-workspace" # 创建package.xml模板 $packageXml = @" unity_moveit_bridge 1.0.0 Unity-MoveIt2 Bridge Package Unity-MoveIt2 Team MIT ament_cmake rclcpp rclpy sensor_msgs geometry_msgs trajectory_msgs moveit_msgs moveit_core moveit_ros_planning_interface ros_tcp_endpoint ament_lint_auto ament_lint_common ament_cmake "@ $packagePath = Join-Path $workspacePath "src/unity_moveit_bridge/package.xml" New-Item -ItemType Directory -Path (Split-Path $packagePath) -Force | Out-Null Set-Content -Path $packagePath -Value $packageXml -Encoding UTF8 # 创建CMakeLists.txt模板 $cmakeContent = @" cmake_minimum_required(VERSION 3.8) project(unity_moveit_bridge) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(rclpy REQUIRED) find_package(sensor_msgs REQUIRED) find_package(geometry_msgs REQUIRED) find_package(trajectory_msgs REQUIRED) find_package(moveit_msgs REQUIRED) find_package(moveit_core REQUIRED) find_package(moveit_ros_planning_interface REQUIRED) # Install Python modules ament_python_install_package(`${PROJECT_NAME}) # Install Python scripts install(PROGRAMS scripts/bridge_node.py scripts/planning_node.py DESTINATION lib/`${PROJECT_NAME} ) # Install launch files install(DIRECTORY launch DESTINATION share/`${PROJECT_NAME}/ ) # Install config files install(DIRECTORY config DESTINATION share/`${PROJECT_NAME}/ ) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) ament_lint_auto_find_test_dependencies() endif() ament_package() "@ $cmakePath = Join-Path $workspacePath "src/unity_moveit_bridge/CMakeLists.txt" Set-Content -Path $cmakePath -Value $cmakeContent -Encoding UTF8 # 构建工作空间 if ($env:WSL_DISTRO_NAME) { Push-Location $workspacePath try { wsl bash -c "source /opt/ros/humble/setup.bash && colcon build --symlink-install" } finally { Pop-Location } } Write-Success "ROS2工作空间构建完成" } # 配置Unity项目 function Set-UnityProject { Write-Step "配置Unity项目..." $unityProjectPath = Join-Path $PWD "unity-project" # 创建Unity项目配置文件 $projectSettings = @{ "companyName" = "Unity-MoveIt2" "productName" = "RobotSimulation" "version" = "1.0.0" "bundleVersion" = "1.0" } $settingsJson = $projectSettings | ConvertTo-Json -Depth 3 $settingsPath = Join-Path $unityProjectPath "ProjectSettings/ProjectSettings.json" New-Item -ItemType Directory -Path (Split-Path $settingsPath) -Force | Out-Null Set-Content -Path $settingsPath -Value $settingsJson -Encoding UTF8 # 创建基本的C#脚本模板 $robotControllerScript = @" using UnityEngine; using Unity.Robotics.ROSTCPConnector; using RosMessageTypes.Sensor; using RosMessageTypes.Geometry; namespace UnityMoveIt2 { public class RobotController : MonoBehaviour { [Header("ROS Configuration")] public string rosIPAddress = "127.0.0.1"; public int rosPort = 10000; [Header("Robot Configuration")] public string robotName = "niryo_one"; public Transform[] jointTransforms; private ROSConnection ros; void Start() { // 初始化ROS连接 ROSConnection.GetOrCreateInstance().Connect(rosIPAddress, rosPort); ros = ROSConnection.GetOrCreateInstance(); // 订阅关节状态 ros.Subscribe("/joint_states", OnJointStateReceived); Debug.Log("Unity机器人控制器初始化完成"); } void OnJointStateReceived(JointStateMsg jointState) { // 更新关节位置 UpdateJointPositions(jointState.position); } void UpdateJointPositions(double[] positions) { for (int i = 0; i < Mathf.Min(positions.Length, jointTransforms.Length); i++) { if (jointTransforms[i] != null) { // 根据关节类型更新旋转 jointTransforms[i].localRotation = Quaternion.Euler(0, 0, (float)(positions[i] * Mathf.Rad2Deg)); } } } public void SendJointCommand(float[] targetPositions) { // 发送关节命令到ROS2 // 实现细节... } } } "@ $scriptPath = Join-Path $unityProjectPath "Assets/Scripts/RobotController.cs" New-Item -ItemType Directory -Path (Split-Path $scriptPath) -Force | Out-Null Set-Content -Path $scriptPath -Value $robotControllerScript -Encoding UTF8 Write-Success "Unity项目配置完成" } # 部署Docker服务 function Deploy-DockerServices { if ($SkipDocker) { Write-Warning "跳过Docker部署" return } Write-Step "部署Docker服务..." $dockerComposePath = Join-Path $PWD "configs/docker/docker-compose.yml" if (-not (Test-Path $dockerComposePath)) { Write-Error "Docker Compose文件不存在: $dockerComposePath" return } try { # 构建镜像 Write-Host "构建Docker镜像..." docker-compose -f $dockerComposePath build # 启动服务 Write-Host "启动Docker服务..." docker-compose -f $dockerComposePath up -d # 等待服务启动 Start-Sleep -Seconds 10 # 检查服务状态 $services = docker-compose -f $dockerComposePath ps --format json | ConvertFrom-Json foreach ($service in $services) { if ($service.State -eq "running") { Write-Success "服务 $($service.Service) 运行正常" } else { Write-Warning "服务 $($service.Service) 状态: $($service.State)" } } } catch { Write-Error "Docker部署失败: $_" } Write-Success "Docker服务部署完成" } # 验证部署 function Test-Deployment { Write-Step "验证部署..." $tests = @() # 测试ROS2服务 if (-not $SkipDocker) { try { $rosServices = docker exec unity-ros2-bridge ros2 service list 2>$null if ($rosServices -match "plan_kinematic_path") { $tests += @{ Name = "ROS2规划服务"; Status = "✅" } } else { $tests += @{ Name = "ROS2规划服务"; Status = "❌" } } } catch { $tests += @{ Name = "ROS2规划服务"; Status = "❌" } } } # 测试网络连接 try { $tcpTest = Test-NetConnection -ComputerName "localhost" -Port 10000 -WarningAction SilentlyContinue if ($tcpTest.TcpTestSucceeded) { $tests += @{ Name = "TCP连接(10000)"; Status = "✅" } } else { $tests += @{ Name = "TCP连接(10000)"; Status = "❌" } } } catch { $tests += @{ Name = "TCP连接(10000)"; Status = "❌" } } # 测试文件结构 $requiredFiles = @( "configs/robots/niryo_one.yaml", "configs/unity/unity_settings.json", "configs/ros2/bridge_config.yaml", "README.md" ) foreach ($file in $requiredFiles) { if (Test-Path $file) { $tests += @{ Name = "文件: $file"; Status = "✅" } } else { $tests += @{ Name = "文件: $file"; Status = "❌" } } } # 显示测试结果 Write-Host "`n部署验证结果:" -ForegroundColor Cyan Write-Host "=" * 50 foreach ($test in $tests) { Write-Host "$($test.Status) $($test.Name)" } $successCount = ($tests | Where-Object { $_.Status -eq "✅" }).Count $totalCount = $tests.Count Write-Host "=" * 50 Write-Host "通过: $successCount/$totalCount" -ForegroundColor $(if ($successCount -eq $totalCount) { "Green" } else { "Yellow" }) if ($successCount -eq $totalCount) { Write-Success "所有验证测试通过!" } else { Write-Warning "部分验证测试失败,请检查配置" } } # 生成启动脚本 function New-StartupScripts { Write-Step "生成启动脚本..." # Windows启动脚本 $startScript = @" @echo off echo 启动Unity-MoveIt2系统... REM 检查Docker服务 docker-compose -f configs/docker/docker-compose.yml ps >nul 2>&1 if %errorlevel% neq 0 ( echo 启动Docker服务... docker-compose -f configs/docker/docker-compose.yml up -d timeout /t 10 /nobreak >nul ) REM 检查服务状态 echo 检查服务状态... docker-compose -f configs/docker/docker-compose.yml ps echo. echo Unity-MoveIt2系统已启动 echo 请在Unity中连接到 localhost:10000 echo. pause "@ Set-Content -Path "start-system.bat" -Value $startScript -Encoding UTF8 # PowerShell启动脚本 $psStartScript = @" # Unity-MoveIt2 系统启动脚本 Write-Host "启动Unity-MoveIt2系统..." -ForegroundColor Green # 启动Docker服务 if (Get-Command docker-compose -ErrorAction SilentlyContinue) { Write-Host "启动Docker服务..." docker-compose -f configs/docker/docker-compose.yml up -d Start-Sleep -Seconds 10 Write-Host "服务状态:" docker-compose -f configs/docker/docker-compose.yml ps } else { Write-Warning "Docker Compose未安装,请手动启动ROS2服务" } Write-Host "`nUnity-MoveIt2系统已启动" -ForegroundColor Green Write-Host "请在Unity中连接到 localhost:10000" -ForegroundColor Cyan "@ Set-Content -Path "start-system.ps1" -Value $psStartScript -Encoding UTF8 Write-Success "启动脚本生成完成" } # 主部署函数 function Start-Deployment { Write-ColorOutput "`n🚀 Unity-MoveIt2 系统快速部署" "Blue" Write-ColorOutput "=" * 50 "Blue" Write-Host "部署模式: $Mode" Write-Host "机器人: $RobotName" Write-Host "跳过Docker: $SkipDocker" Write-Host "开发模式: $Development" Write-Host "" try { # 执行部署步骤 Test-SystemRequirements New-ProjectStructure if ($Mode -eq "full" -or $Mode -eq "ros2-only") { Install-ROS2Dependencies Build-ROS2Workspace } if ($Mode -eq "full" -or $Mode -eq "unity-only") { Set-UnityProject } if ($Mode -eq "full" -and -not $SkipDocker) { Deploy-DockerServices } New-StartupScripts Test-Deployment Write-ColorOutput "`n🎉 部署完成!" "Green" Write-ColorOutput "=" * 50 "Green" Write-Host "`n下一步操作:" Write-Host "1. 运行 start-system.ps1 启动系统" Write-Host "2. 在Unity中打开 unity-project 项目" Write-Host "3. 配置ROS连接到 localhost:10000" Write-Host "4. 开始使用Unity-MoveIt2系统!" } catch { Write-Error "部署失败: $_" Write-Host "`n请检查错误信息并重试" exit 1 } } # 显示帮助信息 function Show-Help { Write-Host @" Unity-MoveIt2 快速部署脚本 用法: .\quick-deploy.ps1 [参数] 参数: -Mode 部署模式 (full|ros2-only|unity-only) [默认: full] -RobotName 机器人名称 [默认: niryo_one] -SkipDocker 跳过Docker部署 -Development 开发模式(包含调试工具) -Verbose 详细输出 -Help 显示此帮助信息 示例: .\quick-deploy.ps1 # 完整部署 .\quick-deploy.ps1 -Mode ros2-only # 仅部署ROS2 .\quick-deploy.ps1 -SkipDocker -Verbose # 跳过Docker,详细输出 .\quick-deploy.ps1 -Development # 开发模式部署 "@ } # 脚本入口点 if ($args -contains "-Help" -or $args -contains "--help" -or $args -contains "-h") { Show-Help exit 0 } # 开始部署 Start-Deployment