Compare commits

...

14 Commits

Author SHA1 Message Date
Xuwznln
9feeb0c430 Fix Build 9 2026-01-27 15:51:40 +08:00
Xuwznln
b2f26ffb28 Fix Build 8 2026-01-27 15:39:15 +08:00
dependabot[bot]
4b0d1553e9 ci(deps): bump actions/checkout from 4 to 6 (#223)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-27 15:30:47 +08:00
dependabot[bot]
67ddee2ab2 ci(deps): bump actions/upload-pages-artifact from 3 to 4 (#225)
Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-pages-artifact
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-27 15:30:38 +08:00
dependabot[bot]
1bcdad9448 ci(deps): bump actions/upload-artifact from 4 to 6 (#224)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-27 15:30:31 +08:00
dependabot[bot]
039c96fe01 ci(deps): bump actions/configure-pages from 4 to 5 (#222)
Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 4 to 5.
- [Release notes](https://github.com/actions/configure-pages/releases)
- [Commits](https://github.com/actions/configure-pages/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/configure-pages
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-27 15:30:22 +08:00
Xuwznln
e1555d10a0 Fix Build 7 2026-01-27 15:14:31 +08:00
Xuwznln
f2a96b2041 Fix Build 6 2026-01-27 14:36:35 +08:00
Xuwznln
329349639e Fix Build 5 2026-01-27 14:25:34 +08:00
Xuwznln
e4cc111523 Fix Build 4 2026-01-27 14:19:56 +08:00
Xuwznln
d245ceef1b Fix Build 3 2026-01-27 14:15:16 +08:00
Xuwznln
6db7fbd721 Fix Build 2 2026-01-27 13:45:32 +08:00
Xuwznln
ab05b858e1 Fix Build 1 2026-01-27 13:35:35 +08:00
Xuwznln
43e4c71a8e Update to ROS2 Humble 0.7 2026-01-27 13:31:24 +08:00
21 changed files with 904 additions and 456 deletions

61
.conda/base/recipe.yaml Normal file
View File

@@ -0,0 +1,61 @@
# unilabos: Production package (depends on unilabos-env + pip unilabos)
# For production deployment
package:
name: unilabos
version: 0.10.16
source:
path: ../../unilabos
target_directory: unilabos
build:
python:
entry_points:
- unilab = unilabos.app.main:main
script:
- set PIP_NO_INDEX=
- if: win
then:
- copy %RECIPE_DIR%\..\..\MANIFEST.in %SRC_DIR%
- copy %RECIPE_DIR%\..\..\setup.cfg %SRC_DIR%
- copy %RECIPE_DIR%\..\..\setup.py %SRC_DIR%
- pip install %SRC_DIR%
- if: unix
then:
- cp $RECIPE_DIR/../../MANIFEST.in $SRC_DIR
- cp $RECIPE_DIR/../../setup.cfg $SRC_DIR
- cp $RECIPE_DIR/../../setup.py $SRC_DIR
- uv pip install $SRC_DIR
requirements:
host:
- python ==3.11.14
- pip
- setuptools
- zstd
- zstandard
run:
- zstd
- zstandard
- networkx
- typing_extensions
- websockets
- opentrons_shared_data
- pint
- fastapi
- jinja2
- requests
- uvicorn
- opcua
- pyserial
- pandas
- pymodbus
- matplotlib
- pylibftdi
- uni-lab::unilabos-env ==0.10.16
about:
repository: https://github.com/deepmodeling/Uni-Lab-OS
license: GPL-3.0-only
description: "UniLabOS - Production package with minimal ROS2 dependencies"

View File

@@ -0,0 +1,39 @@
# unilabos-env: conda environment dependencies (ROS2 + conda packages)
package:
name: unilabos-env
version: 0.10.16
build:
noarch: generic
requirements:
run:
# Python
- zstd
- zstandard
- conda-forge::python ==3.11.14
- conda-forge::opencv
# ROS2 dependencies (from ci-check.yml)
- robostack-staging::ros-humble-ros-core
- robostack-staging::ros-humble-action-msgs
- robostack-staging::ros-humble-std-msgs
- robostack-staging::ros-humble-geometry-msgs
- robostack-staging::ros-humble-control-msgs
- robostack-staging::ros-humble-nav2-msgs
- robostack-staging::ros-humble-cv-bridge
- robostack-staging::ros-humble-vision-opencv
- robostack-staging::ros-humble-tf-transformations
- robostack-staging::ros-humble-moveit-msgs
- robostack-staging::ros-humble-tf2-ros
- robostack-staging::ros-humble-tf2-ros-py
- conda-forge::transforms3d
- conda-forge::uv
# UniLabOS custom messages
- uni-lab::ros-humble-unilabos-msgs
about:
repository: https://github.com/deepmodeling/Uni-Lab-OS
license: GPL-3.0-only
description: "UniLabOS Environment - ROS2 and conda dependencies (for developers: pip install -e .)"

42
.conda/full/recipe.yaml Normal file
View File

@@ -0,0 +1,42 @@
# unilabos-full: Full package with all features
# Depends on unilabos + complete ROS2 desktop + dev tools
package:
name: unilabos-full
version: 0.10.16
build:
noarch: generic
requirements:
run:
# Base unilabos package (includes unilabos-env)
- uni-lab::unilabos ==0.10.16
# Documentation tools
- sphinx
- sphinx_rtd_theme
# Web UI
- gradio
- flask
# Interactive development
- ipython
- jupyter
- jupyros
- colcon-common-extensions
# ROS2 full desktop (includes rviz2, gazebo, etc.)
- robostack-staging::ros-humble-desktop-full
# Navigation and motion control
- ros-humble-navigation2
- ros-humble-ros2-control
- ros-humble-robot-state-publisher
- ros-humble-joint-state-publisher
# MoveIt motion planning
- ros-humble-moveit
- ros-humble-moveit-servo
# Simulation
- ros-humble-simulation
about:
repository: https://github.com/deepmodeling/Uni-Lab-OS
license: GPL-3.0-only
description: "UniLabOS Full - Complete package with ROS2 Desktop, MoveIt, Navigation2, Gazebo, Jupyter"

View File

@@ -1,91 +0,0 @@
package:
name: unilabos
version: 0.10.15
source:
path: ../unilabos
target_directory: unilabos
build:
python:
entry_points:
- unilab = unilabos.app.main:main
script:
- set PIP_NO_INDEX=
- if: win
then:
- copy %RECIPE_DIR%\..\MANIFEST.in %SRC_DIR%
- copy %RECIPE_DIR%\..\setup.cfg %SRC_DIR%
- copy %RECIPE_DIR%\..\setup.py %SRC_DIR%
- call %PYTHON% -m pip install %SRC_DIR%
- if: unix
then:
- cp $RECIPE_DIR/../MANIFEST.in $SRC_DIR
- cp $RECIPE_DIR/../setup.cfg $SRC_DIR
- cp $RECIPE_DIR/../setup.py $SRC_DIR
- $PYTHON -m pip install $SRC_DIR
requirements:
host:
- python ==3.11.11
- pip
- setuptools
- zstd
- zstandard
run:
- conda-forge::python ==3.11.11
- compilers
- cmake
- zstd
- zstandard
- ninja
- if: unix
then:
- make
- sphinx
- sphinx_rtd_theme
- numpy
- scipy
- pandas
- networkx
- matplotlib
- pint
- pyserial
- pyusb
- pylibftdi
- pymodbus
- python-can
- pyvisa
- opencv
- pydantic
- fastapi
- uvicorn
- gradio
- flask
- websockets
- ipython
- jupyter
- jupyros
- colcon-common-extensions
- robostack-staging::ros-humble-desktop-full
- robostack-staging::ros-humble-control-msgs
- robostack-staging::ros-humble-sensor-msgs
- robostack-staging::ros-humble-trajectory-msgs
- ros-humble-navigation2
- ros-humble-ros2-control
- ros-humble-robot-state-publisher
- ros-humble-joint-state-publisher
- ros-humble-rosbridge-server
- ros-humble-cv-bridge
- ros-humble-tf2
- ros-humble-moveit
- ros-humble-moveit-servo
- ros-humble-simulation
- ros-humble-tf-transformations
- transforms3d
- uni-lab::ros-humble-unilabos-msgs
about:
repository: https://github.com/deepmodeling/Uni-Lab-OS
license: GPL-3.0-only
description: "Uni-Lab-OS"

View File

@@ -8,14 +8,19 @@ on:
jobs: jobs:
registry-check: registry-check:
runs-on: ubuntu-latest runs-on: windows-latest
env:
# Fix Unicode encoding issue on Windows runner (cp1252 -> utf-8)
PYTHONIOENCODING: utf-8
PYTHONUTF8: 1
defaults: defaults:
run: run:
shell: bash -l {0} shell: cmd
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -27,73 +32,31 @@ jobs:
channels: robostack-staging,conda-forge,uni-lab channels: robostack-staging,conda-forge,uni-lab
channel-priority: flexible channel-priority: flexible
activate-environment: check-env activate-environment: check-env
auto-activate-base: false
auto-update-conda: false auto-update-conda: false
show-channel-urls: true show-channel-urls: true
- name: Install ROS dependencies and unilabos-msgs - name: Install ROS dependencies, uv and unilabos-msgs
run: | run: |
# Install all packages together for proper dependency resolution echo Installing ROS dependencies...
# Use mamba for faster and more reliable solving mamba install -n check-env conda-forge::uv conda-forge::opencv robostack-staging::ros-humble-ros-core robostack-staging::ros-humble-action-msgs robostack-staging::ros-humble-std-msgs robostack-staging::ros-humble-geometry-msgs robostack-staging::ros-humble-control-msgs robostack-staging::ros-humble-nav2-msgs uni-lab::ros-humble-unilabos-msgs robostack-staging::ros-humble-cv-bridge robostack-staging::ros-humble-vision-opencv robostack-staging::ros-humble-tf-transformations robostack-staging::ros-humble-moveit-msgs robostack-staging::ros-humble-tf2-ros robostack-staging::ros-humble-tf2-ros-py conda-forge::transforms3d -c robostack-staging -c conda-forge -c uni-lab -y
mamba install -n check-env \
python=3.11.14 \
robostack-staging::ros-humble-ros-core \
robostack-staging::ros-humble-action-msgs \
robostack-staging::ros-humble-std-msgs \
robostack-staging::ros-humble-geometry-msgs \
robostack-staging::ros-humble-control-msgs \
robostack-staging::ros-humble-nav2-msgs \
uni-lab::ros-humble-unilabos-msgs \
robostack-staging::ros-humble-cv-bridge \
robostack-staging::ros-humble-vision-opencv \
robostack-staging::ros-humble-tf-transformations \
robostack-staging::ros-humble-moveit-msgs \
robostack-staging::ros-humble-tf2-ros \
robostack-staging::ros-humble-tf2-ros-py \
conda-forge::transforms3d \
-c robostack-staging -c conda-forge -c uni-lab -y
- name: Install pip dependencies and unilabos - name: Install pip dependencies and unilabos
run: | run: |
# Activate the environment call conda activate check-env
conda activate check-env echo Installing pip dependencies...
uv pip install -r unilabos/utils/requirements.txt
# Core dependencies for devices uv pip install pywinauto git+https://github.com/Xuwznln/pylabrobot.git
pip install uv uv pip uninstall enum34 || echo enum34 not installed, skipping
uv pip install networkx \ uv pip install -e .
typing_extensions \
websockets \
msgcenterpy \
opentrons_shared_data \
pint \
fastapi \
jinja2 \
requests \
uvicorn \
git+https://github.com/Xuwznln/pylabrobot.git \
opencv-python \
pyautogui \
opcua \
pyserial \
pandas \
crcmod-plus \
pymodbus \
pywinauto_recorder \
matplotlib \
# PyLabRobot (custom fork)
pip install
# Install unilabos in editable mode
pip install -e .
- name: Run check mode (complete_registry) - name: Run check mode (complete_registry)
run: | run: |
conda activate check-env call conda activate check-env
echo Running check mode...
python -m unilabos --check_mode --skip_env_check python -m unilabos --check_mode --skip_env_check
- name: Check for uncommitted changes - name: Check for uncommitted changes
shell: bash
run: | run: |
if ! git diff --exit-code; then if ! git diff --exit-code; then
echo "::error::检测到文件变化!请先在本地运行 'python -m unilabos --complete_registry' 并提交变更" echo "::error::检测到文件变化!请先在本地运行 'python -m unilabos --complete_registry' 并提交变更"

View File

@@ -13,6 +13,11 @@ on:
required: false required: false
default: 'win-64' default: 'win-64'
type: string type: string
build_full:
description: '是否构建完整版 unilabos-full (默认构建轻量版 unilabos)'
required: false
default: false
type: boolean
jobs: jobs:
build-conda-pack: build-conda-pack:
@@ -57,7 +62,7 @@ jobs:
echo "should_build=false" >> $GITHUB_OUTPUT echo "should_build=false" >> $GITHUB_OUTPUT
fi fi
- uses: actions/checkout@v4 - uses: actions/checkout@v6
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
with: with:
ref: ${{ github.event.inputs.branch }} ref: ${{ github.event.inputs.branch }}
@@ -69,7 +74,7 @@ jobs:
with: with:
miniforge-version: latest miniforge-version: latest
use-mamba: true use-mamba: true
python-version: '3.11.11' python-version: '3.11.14'
channels: conda-forge,robostack-staging,uni-lab,defaults channels: conda-forge,robostack-staging,uni-lab,defaults
channel-priority: flexible channel-priority: flexible
activate-environment: unilab activate-environment: unilab
@@ -81,7 +86,14 @@ jobs:
run: | run: |
echo Installing unilabos and dependencies to unilab environment... echo Installing unilabos and dependencies to unilab environment...
echo Using mamba for faster and more reliable dependency resolution... echo Using mamba for faster and more reliable dependency resolution...
echo Build full: ${{ github.event.inputs.build_full }}
if "${{ github.event.inputs.build_full }}"=="true" (
echo Installing unilabos-full ^(complete package^)...
mamba install -n unilab uni-lab::unilabos-full conda-pack -c uni-lab -c robostack-staging -c conda-forge -y
) else (
echo Installing unilabos ^(minimal package^)...
mamba install -n unilab uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y mamba install -n unilab uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y
)
- name: Install conda-pack, unilabos and dependencies (Unix) - name: Install conda-pack, unilabos and dependencies (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
@@ -89,7 +101,14 @@ jobs:
run: | run: |
echo "Installing unilabos and dependencies to unilab environment..." echo "Installing unilabos and dependencies to unilab environment..."
echo "Using mamba for faster and more reliable dependency resolution..." echo "Using mamba for faster and more reliable dependency resolution..."
echo "Build full: ${{ github.event.inputs.build_full }}"
if [[ "${{ github.event.inputs.build_full }}" == "true" ]]; then
echo "Installing unilabos-full (complete package)..."
mamba install -n unilab uni-lab::unilabos-full conda-pack -c uni-lab -c robostack-staging -c conda-forge -y
else
echo "Installing unilabos (minimal package)..."
mamba install -n unilab uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y mamba install -n unilab uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y
fi
- name: Get latest ros-humble-unilabos-msgs version (Windows) - name: Get latest ros-humble-unilabos-msgs version (Windows)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
@@ -293,7 +312,7 @@ jobs:
- name: Upload distribution package - name: Upload distribution package
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v6
with: with:
name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }} name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }}
path: dist-package/ path: dist-package/
@@ -308,7 +327,12 @@ jobs:
echo ========================================== echo ==========================================
echo Platform: ${{ matrix.platform }} echo Platform: ${{ matrix.platform }}
echo Branch: ${{ github.event.inputs.branch }} echo Branch: ${{ github.event.inputs.branch }}
echo Python version: 3.11.11 echo Python version: 3.11.14
if "${{ github.event.inputs.build_full }}"=="true" (
echo Package: unilabos-full ^(complete^)
) else (
echo Package: unilabos ^(minimal^)
)
echo. echo.
echo Distribution package contents: echo Distribution package contents:
dir dist-package dir dist-package
@@ -328,7 +352,12 @@ jobs:
echo "==========================================" echo "=========================================="
echo "Platform: ${{ matrix.platform }}" echo "Platform: ${{ matrix.platform }}"
echo "Branch: ${{ github.event.inputs.branch }}" echo "Branch: ${{ github.event.inputs.branch }}"
echo "Python version: 3.11.11" echo "Python version: 3.11.14"
if [[ "${{ github.event.inputs.build_full }}" == "true" ]]; then
echo "Package: unilabos-full (complete)"
else
echo "Package: unilabos (minimal)"
fi
echo "" echo ""
echo "Distribution package contents:" echo "Distribution package contents:"
ls -lh dist-package/ ls -lh dist-package/

View File

@@ -1,10 +1,12 @@
name: Deploy Docs name: Deploy Docs
on: on:
push: # 在 CI Check 成功后自动触发(仅 main 分支)
branches: [main] workflow_run:
pull_request: workflows: ["CI Check"]
types: [completed]
branches: [main] branches: [main]
# 手动触发
workflow_dispatch: workflow_dispatch:
inputs: inputs:
branch: branch:
@@ -33,12 +35,19 @@ concurrency:
jobs: jobs:
# Build documentation # Build documentation
build: build:
# 只在以下情况运行:
# 1. workflow_run 触发且 CI Check 成功
# 2. 手动触发
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v6
with: with:
ref: ${{ github.event.inputs.branch || github.ref }} # workflow_run 时使用触发工作流的分支,手动触发时使用输入的分支
ref: ${{ github.event.workflow_run.head_branch || github.event.inputs.branch || github.ref }}
fetch-depth: 0 fetch-depth: 0
- name: Setup Miniforge (with mamba) - name: Setup Miniforge (with mamba)
@@ -46,7 +55,7 @@ jobs:
with: with:
miniforge-version: latest miniforge-version: latest
use-mamba: true use-mamba: true
python-version: '3.11.11' python-version: '3.11.14'
channels: conda-forge,robostack-staging,uni-lab,defaults channels: conda-forge,robostack-staging,uni-lab,defaults
channel-priority: flexible channel-priority: flexible
activate-environment: unilab activate-environment: unilab
@@ -75,8 +84,10 @@ jobs:
- name: Setup Pages - name: Setup Pages
id: pages id: pages
uses: actions/configure-pages@v4 uses: actions/configure-pages@v5
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true') if: |
github.event.workflow_run.head_branch == 'main' ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
- name: Build Sphinx documentation - name: Build Sphinx documentation
run: | run: |
@@ -94,14 +105,18 @@ jobs:
test -f docs/_build/html/index.html && echo "✓ index.html exists" || echo "✗ index.html missing" test -f docs/_build/html/index.html && echo "✓ index.html exists" || echo "✗ index.html missing"
- name: Upload build artifacts - name: Upload build artifacts
uses: actions/upload-pages-artifact@v3 uses: actions/upload-pages-artifact@v4
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true') if: |
github.event.workflow_run.head_branch == 'main' ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
with: with:
path: docs/_build/html path: docs/_build/html
# Deploy to GitHub Pages # Deploy to GitHub Pages
deploy: deploy:
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true') if: |
github.event.workflow_run.head_branch == 'main' ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
environment: environment:
name: github-pages name: github-pages
url: ${{ steps.deployment.outputs.page_url }} url: ${{ steps.deployment.outputs.page_url }}

View File

@@ -1,11 +1,16 @@
name: Multi-Platform Conda Build name: Multi-Platform Conda Build
on: on:
# 在 CI Check 工作流完成后触发(仅限 main/dev 分支)
workflow_run:
workflows: ["CI Check"]
types:
- completed
branches: [main, dev]
# 支持 tag 推送(不依赖 CI Check
push: push:
branches: [main, dev]
tags: ['v*'] tags: ['v*']
pull_request: # 手动触发
branches: [main, dev]
workflow_dispatch: workflow_dispatch:
inputs: inputs:
platforms: platforms:
@@ -17,9 +22,37 @@ on:
required: false required: false
default: false default: false
type: boolean type: boolean
skip_ci_check:
description: '跳过等待 CI Check (手动触发时可选)'
required: false
default: false
type: boolean
jobs: jobs:
# 等待 CI Check 完成的 job (仅用于 workflow_run 触发)
wait-for-ci:
runs-on: ubuntu-latest
if: github.event_name == 'workflow_run'
outputs:
should_continue: ${{ steps.check.outputs.should_continue }}
steps:
- name: Check CI status
id: check
run: |
if [[ "${{ github.event.workflow_run.conclusion }}" == "success" ]]; then
echo "should_continue=true" >> $GITHUB_OUTPUT
echo "CI Check passed, proceeding with build"
else
echo "should_continue=false" >> $GITHUB_OUTPUT
echo "CI Check did not succeed (status: ${{ github.event.workflow_run.conclusion }}), skipping build"
fi
build: build:
needs: [wait-for-ci]
# 运行条件workflow_run 触发且 CI 成功,或者其他触发方式
if: |
always() &&
(needs.wait-for-ci.result == 'skipped' || needs.wait-for-ci.outputs.should_continue == 'true')
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -44,8 +77,10 @@ jobs:
shell: bash -l {0} shell: bash -l {0}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
# 如果是 workflow_run 触发,使用触发 CI Check 的 commit
ref: ${{ github.event.workflow_run.head_sha || github.ref }}
fetch-depth: 0 fetch-depth: 0
- name: Check if platform should be built - name: Check if platform should be built
@@ -69,7 +104,6 @@ jobs:
channels: conda-forge,robostack-staging,defaults channels: conda-forge,robostack-staging,defaults
channel-priority: strict channel-priority: strict
activate-environment: build-env activate-environment: build-env
auto-activate-base: false
auto-update-conda: false auto-update-conda: false
show-channel-urls: true show-channel-urls: true
@@ -115,7 +149,7 @@ jobs:
- name: Upload conda package artifacts - name: Upload conda package artifacts
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v6
with: with:
name: conda-package-${{ matrix.platform }} name: conda-package-${{ matrix.platform }}
path: conda-packages-temp path: conda-packages-temp

View File

@@ -1,25 +1,62 @@
name: UniLabOS Conda Build name: UniLabOS Conda Build
on: on:
# 在 CI Check 成功后自动触发
workflow_run:
workflows: ["CI Check"]
types: [completed]
branches: [main, dev]
# 标签推送时直接触发(发布版本)
push: push:
branches: [main, dev]
tags: ['v*'] tags: ['v*']
pull_request: # 手动触发
branches: [main, dev]
workflow_dispatch: workflow_dispatch:
inputs: inputs:
platforms: platforms:
description: '选择构建平台 (逗号分隔): linux-64, osx-64, osx-arm64, win-64' description: '选择构建平台 (逗号分隔): linux-64, osx-64, osx-arm64, win-64'
required: false required: false
default: 'linux-64' default: 'linux-64'
build_full:
description: '是否构建 unilabos-full 完整包 (默认只构建 unilabos 基础包)'
required: false
default: false
type: boolean
upload_to_anaconda: upload_to_anaconda:
description: '是否上传到Anaconda.org' description: '是否上传到Anaconda.org'
required: false required: false
default: false default: false
type: boolean type: boolean
skip_ci_check:
description: '跳过等待 CI Check (手动触发时可选)'
required: false
default: false
type: boolean
jobs: jobs:
# 等待 CI Check 完成的 job (仅用于 workflow_run 触发)
wait-for-ci:
runs-on: ubuntu-latest
if: github.event_name == 'workflow_run'
outputs:
should_continue: ${{ steps.check.outputs.should_continue }}
steps:
- name: Check CI status
id: check
run: |
if [[ "${{ github.event.workflow_run.conclusion }}" == "success" ]]; then
echo "should_continue=true" >> $GITHUB_OUTPUT
echo "CI Check passed, proceeding with build"
else
echo "should_continue=false" >> $GITHUB_OUTPUT
echo "CI Check did not succeed (status: ${{ github.event.workflow_run.conclusion }}), skipping build"
fi
build: build:
needs: [wait-for-ci]
# 运行条件workflow_run 触发且 CI 成功,或者其他触发方式
if: |
always() &&
(needs.wait-for-ci.result == 'skipped' || needs.wait-for-ci.outputs.should_continue == 'true')
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -40,8 +77,10 @@ jobs:
shell: bash -l {0} shell: bash -l {0}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
# 如果是 workflow_run 触发,使用触发 CI Check 的 commit
ref: ${{ github.event.workflow_run.head_sha || github.ref }}
fetch-depth: 0 fetch-depth: 0
- name: Check if platform should be built - name: Check if platform should be built
@@ -65,7 +104,6 @@ jobs:
channels: conda-forge,robostack-staging,uni-lab,defaults channels: conda-forge,robostack-staging,uni-lab,defaults
channel-priority: strict channel-priority: strict
activate-environment: build-env activate-environment: build-env
auto-activate-base: false
auto-update-conda: false auto-update-conda: false
show-channel-urls: true show-channel-urls: true
@@ -81,12 +119,33 @@ jobs:
conda list | grep -E "(rattler-build|anaconda-client)" conda list | grep -E "(rattler-build|anaconda-client)"
echo "Platform: ${{ matrix.platform }}" echo "Platform: ${{ matrix.platform }}"
echo "OS: ${{ matrix.os }}" echo "OS: ${{ matrix.os }}"
echo "Building UniLabOS package" echo "Build full package: ${{ github.event.inputs.build_full || 'false' }}"
echo "Building packages:"
echo " - unilabos-env (environment dependencies)"
echo " - unilabos (with pip package)"
if [[ "${{ github.event.inputs.build_full }}" == "true" ]]; then
echo " - unilabos-full (complete package)"
fi
- name: Build conda package - name: Build unilabos-env (conda environment only, noarch)
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
run: | run: |
rattler-build build -r .conda/recipe.yaml -c uni-lab -c robostack-staging -c conda-forge echo "Building unilabos-env (conda environment dependencies)..."
rattler-build build -r .conda/environment/recipe.yaml -c uni-lab -c robostack-staging -c conda-forge
- name: Build unilabos (with pip package)
if: steps.should_build.outputs.should_build == 'true'
run: |
echo "Building unilabos package..."
rattler-build build -r .conda/base/recipe.yaml -c uni-lab -c robostack-staging -c conda-forge --channel ./output
- name: Build unilabos-full - Only when explicitly requested
if: |
steps.should_build.outputs.should_build == 'true' &&
github.event.inputs.build_full == 'true'
run: |
echo "Building unilabos-full package on ${{ matrix.platform }}..."
rattler-build build -r .conda/full/recipe.yaml -c uni-lab -c robostack-staging -c conda-forge --channel ./output
- name: List built packages - name: List built packages
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
@@ -108,7 +167,7 @@ jobs:
- name: Upload conda package artifacts - name: Upload conda package artifacts
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v6
with: with:
name: conda-package-unilabos-${{ matrix.platform }} name: conda-package-unilabos-${{ matrix.platform }}
path: conda-packages-temp path: conda-packages-temp

View File

@@ -1,4 +1,5 @@
recursive-include unilabos/test * recursive-include unilabos/test *
recursive-include unilabos/utils *
recursive-include unilabos/registry *.yaml recursive-include unilabos/registry *.yaml
recursive-include unilabos/app/web/static * recursive-include unilabos/app/web/static *
recursive-include unilabos/app/web/templates * recursive-include unilabos/app/web/templates *

View File

@@ -31,26 +31,46 @@ Detailed documentation can be found at:
## Quick Start ## Quick Start
1. Setup Conda Environment ### 1. Setup Conda Environment
Uni-Lab-OS recommends using `mamba` for environment management: Uni-Lab-OS recommends using `mamba` for environment management. Choose the package that fits your needs:
| Package | Use Case | Contents |
|---------|----------|----------|
| `unilabos` | **Recommended for most users** | Complete package, ready to use |
| `unilabos-env` | Developers (editable install) | Environment only, install unilabos via pip |
| `unilabos-full` | Simulation/Visualization | unilabos + ROS2 Desktop + Gazebo + MoveIt |
```bash ```bash
# Create new environment # Create new environment
mamba create -n unilab python=3.11.11 mamba create -n unilab python=3.11.14
mamba activate unilab mamba activate unilab
mamba install -n unilab uni-lab::unilabos -c robostack-staging -c conda-forge
# Option A: Standard installation (recommended for most users)
mamba install uni-lab::unilabos -c robostack-staging -c conda-forge
# Option B: For developers (editable mode development)
mamba install uni-lab::unilabos-env -c robostack-staging -c conda-forge
# Then install unilabos and dependencies:
git clone https://github.com/deepmodeling/Uni-Lab-OS.git && cd Uni-Lab-OS
pip install -e .
uv pip install -r unilabos/utils/requirements.txt
# Option C: Full installation (simulation/visualization)
mamba install uni-lab::unilabos-full -c robostack-staging -c conda-forge
``` ```
2. Install Dev Uni-Lab-OS **When to use which?**
- **unilabos**: Standard installation for production deployment and general usage (recommended)
- **unilabos-env**: For developers who need `pip install -e .` editable mode, modify source code
- **unilabos-full**: For simulation (Gazebo), visualization (rviz2), and Jupyter notebooks
### 2. Clone Repository (Optional, for developers)
```bash ```bash
# Clone the repository # Clone the repository (only needed for development or examples)
git clone https://github.com/deepmodeling/Uni-Lab-OS.git git clone https://github.com/deepmodeling/Uni-Lab-OS.git
cd Uni-Lab-OS cd Uni-Lab-OS
# Install Uni-Lab-OS
pip install .
``` ```
3. Start Uni-Lab System 3. Start Uni-Lab System

View File

@@ -31,26 +31,46 @@ Uni-Lab-OS 是一个用于实验室自动化的综合平台,旨在连接和控
## 快速开始 ## 快速开始
1. 配置 Conda 环境 ### 1. 配置 Conda 环境
Uni-Lab-OS 建议使用 `mamba` 管理环境。根据您的操作系统选择适当的环境文件: Uni-Lab-OS 建议使用 `mamba` 管理环境。根据您的需求选择合适的安装包:
| 安装包 | 适用场景 | 包含内容 |
|--------|----------|----------|
| `unilabos` | **推荐大多数用户** | 完整安装包,开箱即用 |
| `unilabos-env` | 开发者(可编辑安装) | 仅环境依赖,通过 pip 安装 unilabos |
| `unilabos-full` | 仿真/可视化 | unilabos + ROS2 桌面版 + Gazebo + MoveIt |
```bash ```bash
# 创建新环境 # 创建新环境
mamba create -n unilab python=3.11.11 mamba create -n unilab python=3.11.14
mamba activate unilab mamba activate unilab
mamba install -n unilab uni-lab::unilabos -c robostack-staging -c conda-forge
# 方案 A标准安装推荐大多数用户
mamba install uni-lab::unilabos -c robostack-staging -c conda-forge
# 方案 B开发者环境可编辑模式开发
mamba install uni-lab::unilabos-env -c robostack-staging -c conda-forge
# 然后安装 unilabos 和依赖:
git clone https://github.com/deepmodeling/Uni-Lab-OS.git && cd Uni-Lab-OS
pip install -e .
uv pip install -r unilabos/utils/requirements.txt
# 方案 C完整安装仿真/可视化)
mamba install uni-lab::unilabos-full -c robostack-staging -c conda-forge
``` ```
2. 安装开发版 Uni-Lab-OS: **如何选择?**
- **unilabos**:标准安装,适用于生产部署和日常使用(推荐)
- **unilabos-env**:开发者使用,支持 `pip install -e .` 可编辑模式,可修改源代码
- **unilabos-full**需要仿真Gazebo、可视化rviz2或 Jupyter Notebook
### 2. 克隆仓库(可选,供开发者使用)
```bash ```bash
# 克隆仓库 # 克隆仓库(仅开发或查看示例时需要)
git clone https://github.com/deepmodeling/Uni-Lab-OS.git git clone https://github.com/deepmodeling/Uni-Lab-OS.git
cd Uni-Lab-OS cd Uni-Lab-OS
# 安装 Uni-Lab-OS
pip install .
``` ```
3. 启动 Uni-Lab 系统 3. 启动 Uni-Lab 系统

View File

@@ -31,6 +31,14 @@
详细的安装步骤请参考 [安装指南](installation.md)。 详细的安装步骤请参考 [安装指南](installation.md)。
**选择合适的安装包:**
| 安装包 | 适用场景 | 包含组件 |
|--------|----------|----------|
| `unilabos` | **推荐大多数用户**,生产部署 | 完整安装包,开箱即用 |
| `unilabos-env` | 开发者(可编辑安装) | 仅环境依赖,通过 pip 安装 unilabos |
| `unilabos-full` | 仿真/可视化 | unilabos + 完整 ROS2 桌面版 + Gazebo + MoveIt |
**关键步骤:** **关键步骤:**
```bash ```bash
@@ -38,15 +46,30 @@
# 下载 Miniforge: https://github.com/conda-forge/miniforge/releases # 下载 Miniforge: https://github.com/conda-forge/miniforge/releases
# 2. 创建 Conda 环境 # 2. 创建 Conda 环境
mamba create -n unilab python=3.11.11 mamba create -n unilab python=3.11.14
# 3. 激活环境 # 3. 激活环境
mamba activate unilab mamba activate unilab
# 4. 安装 Uni-Lab-OS # 4. 安装 Uni-Lab-OS(选择其一)
# 方案 A标准安装推荐大多数用户
mamba install uni-lab::unilabos -c robostack-staging -c conda-forge mamba install uni-lab::unilabos -c robostack-staging -c conda-forge
# 方案 B开发者环境可编辑模式开发
mamba install uni-lab::unilabos-env -c robostack-staging -c conda-forge
pip install -e /path/to/Uni-Lab-OS # 可编辑安装
uv pip install -r unilabos/utils/requirements.txt # 安装 pip 依赖
# 方案 C完整版仿真/可视化)
mamba install uni-lab::unilabos-full -c robostack-staging -c conda-forge
``` ```
**选择建议:**
- **日常使用/生产部署**:使用 `unilabos`(推荐),完整功能,开箱即用
- **开发者**:使用 `unilabos-env` + `pip install -e .` + `uv pip install -r unilabos/utils/requirements.txt`,代码修改立即生效
- **仿真/可视化**:使用 `unilabos-full`,含 Gazebo、rviz2、MoveIt
#### 1.2 验证安装 #### 1.2 验证安装
```bash ```bash
@@ -768,7 +791,43 @@ Waiting for host service...
详细的设备驱动编写指南请参考 [添加设备驱动](../developer_guide/add_device.md)。 详细的设备驱动编写指南请参考 [添加设备驱动](../developer_guide/add_device.md)。
#### 9.1 为什么需要自定义设备? #### 9.1 开发环境准备
**推荐使用 `unilabos-env` + `pip install -e .` + `uv pip install`** 进行设备开发:
```bash
# 1. 创建环境并安装 unilabos-envROS2 + conda 依赖 + uv
mamba create -n unilab python=3.11.14
conda activate unilab
mamba install uni-lab::unilabos-env -c robostack-staging -c conda-forge
# 2. 克隆代码
git clone https://github.com/deepmodeling/Uni-Lab-OS.git
cd Uni-Lab-OS
# 3. 以可编辑模式安装(推荐使用脚本,自动检测中文环境)
python scripts/dev_install.py
# 或手动安装:
pip install -e .
uv pip install -r unilabos/utils/requirements.txt
```
**为什么使用这种方式?**
- `unilabos-env` 提供 ROS2 核心组件和 uv通过 conda 安装,避免编译)
- `unilabos/utils/requirements.txt` 包含所有运行时需要的 pip 依赖
- `dev_install.py` 自动检测中文环境,中文系统自动使用清华镜像
- 使用 `uv` 替代 `pip`,安装速度更快
- 可编辑模式:代码修改**立即生效**,无需重新安装
**如果安装失败或速度太慢**,可以手动执行(使用清华镜像):
```bash
pip install -e . -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
uv pip install -r unilabos/utils/requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
```
#### 9.2 为什么需要自定义设备?
Uni-Lab-OS 内置了常见设备,但您的实验室可能有特殊设备需要集成: Uni-Lab-OS 内置了常见设备,但您的实验室可能有特殊设备需要集成:
@@ -777,7 +836,7 @@ Uni-Lab-OS 内置了常见设备,但您的实验室可能有特殊设备需要
- 特殊的实验流程 - 特殊的实验流程
- 第三方设备集成 - 第三方设备集成
#### 9.2 创建 Python 包 #### 9.3 创建 Python 包
为了方便开发和管理,建议为您的实验室创建独立的 Python 包。 为了方便开发和管理,建议为您的实验室创建独立的 Python 包。
@@ -814,7 +873,7 @@ touch my_lab_devices/my_lab_devices/__init__.py
touch my_lab_devices/my_lab_devices/devices/__init__.py touch my_lab_devices/my_lab_devices/devices/__init__.py
``` ```
#### 9.3 创建 setup.py #### 9.4 创建 setup.py
```python ```python
# my_lab_devices/setup.py # my_lab_devices/setup.py
@@ -845,7 +904,7 @@ setup(
) )
``` ```
#### 9.4 开发安装 #### 9.5 开发安装
使用 `-e` 参数进行可编辑安装,这样代码修改后立即生效: 使用 `-e` 参数进行可编辑安装,这样代码修改后立即生效:
@@ -860,7 +919,7 @@ pip install -e . -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
- 方便调试和测试 - 方便调试和测试
- 支持版本控制git - 支持版本控制git
#### 9.5 编写设备驱动 #### 9.6 编写设备驱动
创建设备驱动文件: 创建设备驱动文件:
@@ -1001,7 +1060,7 @@ class MyPump:
- **返回 Dict**:所有动作方法返回字典类型 - **返回 Dict**:所有动作方法返回字典类型
- **文档字符串**:详细说明参数和功能 - **文档字符串**:详细说明参数和功能
#### 9.6 测试设备驱动 #### 9.7 测试设备驱动
创建简单的测试脚本: 创建简单的测试脚本:

View File

@@ -13,15 +13,26 @@
- 开发者需要 Git 和基本的 Python 开发知识 - 开发者需要 Git 和基本的 Python 开发知识
- 自定义 msgs 需要 GitHub 账号 - 自定义 msgs 需要 GitHub 账号
## 安装包选择
Uni-Lab-OS 提供三个安装包版本,根据您的需求选择:
| 安装包 | 适用场景 | 包含组件 | 磁盘占用 |
|--------|----------|----------|----------|
| **unilabos** | **推荐大多数用户**,生产部署 | 完整安装包,开箱即用 | ~2-3 GB |
| **unilabos-env** | 开发者环境(可编辑安装) | 仅环境依赖,通过 pip 安装 unilabos | ~2 GB |
| **unilabos-full** | 仿真可视化、完整功能体验 | unilabos + 完整 ROS2 桌面版 + Gazebo + MoveIt | ~8-10 GB |
## 安装方式选择 ## 安装方式选择
根据您的使用场景,选择合适的安装方式: 根据您的使用场景,选择合适的安装方式:
| 安装方式 | 适用人群 | 特点 | 安装时间 | | 安装方式 | 适用人群 | 推荐安装包 | 特点 | 安装时间 |
| ---------------------- | -------------------- | ------------------------------ | ---------------------------- | | ---------------------- | -------------------- | ----------------- | ------------------------------ | ---------------------------- |
| **方式一:一键安装** | 实验室用户、快速体验 | 预打包环境,离线可用,无需配置 | 5-10 分钟 (网络良好的情况下) | | **方式一:一键安装** | 快速体验、演示 | 预打包环境 | 离线可用,无需配置 | 5-10 分钟 (网络良好的情况下) |
| **方式二:手动安装** | 标准用户、生产环境 | 灵活配置,版本可控 | 10-20 分钟 | | **方式二:手动安装** | **大多数用户** | `unilabos` | 完整功能,开箱即用 | 10-20 分钟 |
| **方式三:开发者安装** | 开发者、需要修改源码 | 可编辑模式,支持自定义 msgs | 20-30 分钟 | | **方式三:开发者安装** | 开发者、需要修改源码 | `unilabos-env` | 可编辑模式,支持自定义开发 | 20-30 分钟 |
| **仿真/可视化** | 仿真测试、可视化调试 | `unilabos-full` | 含 Gazebo、rviz2、MoveIt | 30-60 分钟 |
--- ---
@@ -144,17 +155,38 @@ bash Miniforge3-$(uname)-$(uname -m).sh
使用以下命令创建 Uni-Lab 专用环境: 使用以下命令创建 Uni-Lab 专用环境:
```bash ```bash
mamba create -n unilab python=3.11.11 # 目前ros2组件依赖版本大多为3.11.11 mamba create -n unilab python=3.11.14 # 目前ros2组件依赖版本大多为3.11.14
mamba activate unilab mamba activate unilab
mamba install -n unilab uni-lab::unilabos -c robostack-staging -c conda-forge
# 选择安装包(三选一):
# 方案 A标准安装推荐大多数用户
mamba install uni-lab::unilabos -c robostack-staging -c conda-forge
# 方案 B开发者环境可编辑模式开发
mamba install uni-lab::unilabos-env -c robostack-staging -c conda-forge
# 然后安装 unilabos 和 pip 依赖:
git clone https://github.com/deepmodeling/Uni-Lab-OS.git && cd Uni-Lab-OS
pip install -e .
uv pip install -r unilabos/utils/requirements.txt
# 方案 C完整版含仿真和可视化工具
mamba install uni-lab::unilabos-full -c robostack-staging -c conda-forge
``` ```
**参数说明**: **参数说明**:
- `-n unilab`: 创建名为 "unilab" 的环境 - `-n unilab`: 创建名为 "unilab" 的环境
- `uni-lab::unilabos`: 从 uni-lab channel 安装 unilabos 包 - `uni-lab::unilabos`: 安装 unilabos 完整包,开箱即用(推荐)
- `uni-lab::unilabos-env`: 仅安装环境依赖,适合开发者使用 `pip install -e .`
- `uni-lab::unilabos-full`: 安装完整包(含 ROS2 Desktop、Gazebo、MoveIt 等)
- `-c robostack-staging -c conda-forge`: 添加额外的软件源 - `-c robostack-staging -c conda-forge`: 添加额外的软件源
**包选择建议**
- **日常使用/生产部署**:安装 `unilabos`(推荐,完整功能,开箱即用)
- **开发者**:安装 `unilabos-env`,然后使用 `uv pip install -r unilabos/utils/requirements.txt` 安装依赖,再 `pip install -e .` 进行可编辑安装
- **仿真/可视化**:安装 `unilabos-full`Gazebo、rviz2、MoveIt
**如果遇到网络问题**,可以使用清华镜像源加速下载: **如果遇到网络问题**,可以使用清华镜像源加速下载:
```bash ```bash
@@ -163,8 +195,14 @@ mamba config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/m
mamba config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ mamba config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
mamba config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/ mamba config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
# 然后重新执行安装命令 # 然后重新执行安装命令(推荐标准安装)
mamba create -n unilab uni-lab::unilabos -c robostack-staging mamba create -n unilab uni-lab::unilabos -c robostack-staging
# 或完整版(仿真/可视化)
mamba create -n unilab uni-lab::unilabos-full -c robostack-staging
# pip 安装时使用清华镜像(开发者安装时使用)
uv pip install -r unilabos/utils/requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
``` ```
### 第三步:激活环境 ### 第三步:激活环境
@@ -203,58 +241,87 @@ cd Uni-Lab-OS
cd Uni-Lab-OS cd Uni-Lab-OS
``` ```
### 第二步:安装基础环境 ### 第二步:安装开发环境unilabos-env
**推荐方式**:先通过**方式一(一键安装)**或**方式二(手动安装)**完成基础环境的安装这将包含所有必需的依赖项ROS2、msgs 等)。 **重要**:开发者请使用 `unilabos-env` 包,它专为开发者设计:
- 包含 ROS2 核心组件和消息包ros-humble-ros-core、std-msgs、geometry-msgs 等)
#### 选项 A通过一键安装推荐 - 包含 transforms3d、cv-bridge、tf2 等 conda 依赖
- 包含 `uv` 工具,用于快速安装 pip 依赖
参考上文"方式一:一键安装",完成基础环境的安装后,激活环境: - **不包含** pip 依赖和 unilabos 包(由 `pip install -e .` 和 `uv pip install` 安装)
```bash ```bash
# 创建并激活环境
mamba create -n unilab python=3.11.14
conda activate unilab conda activate unilab
# 安装开发者环境包ROS2 + conda 依赖 + uv
mamba install uni-lab::unilabos-env -c robostack-staging -c conda-forge
``` ```
#### 选项 B通过手动安装 ### 第三步:安装 pip 依赖和可编辑模式安装
参考上文"方式二:手动安装",创建并安装环境 克隆代码并安装依赖
```bash
mamba create -n unilab python=3.11.11
conda activate unilab
mamba install -n unilab uni-lab::unilabos -c robostack-staging -c conda-forge
```
**说明**:这会安装包括 Python 3.11.11、ROS2 Humble、ros-humble-unilabos-msgs 和所有必需依赖
### 第三步:切换到开发版本
现在你已经有了一个完整可用的 Uni-Lab 环境,接下来将 unilabos 包切换为开发版本:
```bash ```bash
# 确保环境已激活 # 确保环境已激活
conda activate unilab conda activate unilab
# 卸载 pip 安装的 unilabos保留所有 conda 依赖 # 克隆仓库(如果还未克隆
pip uninstall unilabos -y git clone https://github.com/deepmodeling/Uni-Lab-OS.git
# 克隆 dev 分支(如果还未克隆)
cd /path/to/your/workspace
git clone -b dev https://github.com/deepmodeling/Uni-Lab-OS.git
# 或者如果已经克隆,切换到 dev 分支
cd Uni-Lab-OS cd Uni-Lab-OS
# 切换到 dev 分支(可选)
git checkout dev git checkout dev
git pull git pull
# 以可编辑模式安装开发版 unilabos
pip install -e . -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
``` ```
**参数说明** **推荐:使用安装脚本**(自动检测中文环境,使用 uv 加速)
- `-e`: editable mode可编辑模式代码修改立即生效无需重新安装 ```bash
- `-i`: 使用清华镜像源加速下载 # 自动检测中文环境,如果是中文系统则使用清华镜像
- `pip uninstall unilabos`: 只卸载 pip 安装的 unilabos 包,不影响 conda 安装的其他依赖(如 ROS2、msgs 等) python scripts/dev_install.py
# 或者手动指定:
python scripts/dev_install.py --china # 强制使用清华镜像
python scripts/dev_install.py --no-mirror # 强制使用 PyPI
python scripts/dev_install.py --skip-deps # 跳过 pip 依赖安装
python scripts/dev_install.py --use-pip # 使用 pip 而非 uv
```
**手动安装**(如果脚本安装失败或速度太慢):
```bash
# 1. 安装 unilabos可编辑模式
pip install -e .
# 2. 使用 uv 安装 pip 依赖(推荐,速度更快)
uv pip install -r unilabos/utils/requirements.txt
# 国内用户使用清华镜像:
pip install -e . -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
uv pip install -r unilabos/utils/requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
```
**注意**
- `uv` 已包含在 `unilabos-env` 中,无需单独安装
- `unilabos/utils/requirements.txt` 包含运行 unilabos 所需的所有 pip 依赖
- 部分特殊包(如 pylabrobot会在运行时由 unilabos 自动检测并安装
**为什么使用可编辑模式?**
- `-e` (editable mode):代码修改**立即生效**,无需重新安装
- 适合开发调试:修改代码后直接运行测试
- 与 `unilabos-env` 配合:环境依赖由 conda 管理unilabos 代码由 pip 管理
**验证安装**
```bash
# 检查 unilabos 版本
python -c "import unilabos; print(unilabos.__version__)"
# 检查安装位置(应该指向你的代码目录)
pip show unilabos | grep Location
```
### 第四步:安装或自定义 ros-humble-unilabos-msgs可选 ### 第四步:安装或自定义 ros-humble-unilabos-msgs可选
@@ -464,7 +531,45 @@ cd $CONDA_PREFIX/envs/unilab
### 问题 8: 环境很大,有办法减小吗? ### 问题 8: 环境很大,有办法减小吗?
**解决方案**: 预打包的环境包含所有依赖,通常较大(压缩后 2-5GB。这是为了确保离线安装和完整功能。如果空间有限考虑使用方式二手动安装只安装需要的组件。 **解决方案**:
1. **使用 `unilabos` 标准版**(推荐大多数用户):
```bash
mamba install uni-lab::unilabos -c robostack-staging -c conda-forge
```
标准版包含完整功能,环境大小约 2-3GB相比完整版的 8-10GB
2. **使用 `unilabos-env` 开发者版**(最小化):
```bash
mamba install uni-lab::unilabos-env -c robostack-staging -c conda-forge
# 然后手动安装依赖
pip install -e .
uv pip install -r unilabos/utils/requirements.txt
```
开发者版只包含环境依赖,体积最小约 2GB。
3. **按需安装额外组件**
如果后续需要特定功能,可以单独安装:
```bash
# 需要 Jupyter
mamba install jupyter jupyros
# 需要可视化
mamba install matplotlib opencv
# 需要仿真(注意:这会安装大量依赖)
mamba install ros-humble-gazebo-ros
```
4. **预打包环境问题**
预打包环境(方式一)包含所有依赖,通常较大(压缩后 2-5GB。这是为了确保离线安装和完整功能。
**包选择建议**
| 需求 | 推荐包 | 预估大小 |
|------|--------|----------|
| 日常使用/生产部署 | `unilabos` | ~2-3 GB |
| 开发调试(可编辑模式) | `unilabos-env` | ~2 GB |
| 仿真/可视化 | `unilabos-full` | ~8-10 GB |
### 问题 9: 如何更新到最新版本? ### 问题 9: 如何更新到最新版本?
@@ -511,6 +616,7 @@ mamba update ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-f
**提示**: **提示**:
- 生产环境推荐使用方式二(手动安装)的稳定版本 - **大多数用户**推荐使用方式二(手动安装)的 `unilabos` 标准版
- 开发和测试推荐使用方式三(开发者安装) - **开发者**推荐使用方式三(开发者安装),安装 `unilabos-env` 后使用 `uv pip install -r unilabos/utils/requirements.txt` 安装依赖
- 快速体验和演示推荐使用方式一(一键安装) - **仿真/可视化**推荐安装 `unilabos-full` 完整版
- **快速体验和演示**推荐使用方式一(一键安装)

View File

@@ -85,7 +85,7 @@ Verification:
------------- -------------
The verify_installation.py script will check: The verify_installation.py script will check:
- Python version (3.11.11) - Python version (3.11.14)
- ROS2 rclpy installation - ROS2 rclpy installation
- UniLabOS installation and dependencies - UniLabOS installation and dependencies
@@ -104,7 +104,7 @@ Build Information:
Branch: {branch} Branch: {branch}
Platform: {platform} Platform: {platform}
Python: 3.11.11 Python: 3.11.14
Date: {build_date} Date: {build_date}
Troubleshooting: Troubleshooting:

214
scripts/dev_install.py Normal file
View File

@@ -0,0 +1,214 @@
#!/usr/bin/env python3
"""
Development installation script for UniLabOS.
Auto-detects Chinese locale and uses appropriate mirror.
Usage:
python scripts/dev_install.py
python scripts/dev_install.py --no-mirror # Force no mirror
python scripts/dev_install.py --china # Force China mirror
python scripts/dev_install.py --skip-deps # Skip pip dependencies installation
Flow:
1. pip install -e . (install unilabos in editable mode)
2. Detect Chinese locale
3. Use uv to install pip dependencies from requirements.txt
4. Special packages (like pylabrobot) are handled by environment_check.py at runtime
"""
import locale
import subprocess
import sys
import argparse
from pathlib import Path
# Tsinghua mirror URL
TSINGHUA_MIRROR = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
def is_chinese_locale() -> bool:
"""
Detect if system is in Chinese locale.
Same logic as EnvironmentChecker._is_chinese_locale()
"""
try:
lang = locale.getdefaultlocale()[0]
if lang and ("zh" in lang.lower() or "chinese" in lang.lower()):
return True
except Exception:
pass
return False
def run_command(cmd: list, description: str, retry: int = 2) -> bool:
"""Run command with retry support."""
print(f"[INFO] {description}")
print(f"[CMD] {' '.join(cmd)}")
for attempt in range(retry + 1):
try:
result = subprocess.run(cmd, check=True, timeout=600)
print(f"[OK] {description}")
return True
except subprocess.CalledProcessError as e:
if attempt < retry:
print(f"[WARN] Attempt {attempt + 1} failed, retrying...")
else:
print(f"[ERROR] {description} failed: {e}")
return False
except subprocess.TimeoutExpired:
print(f"[ERROR] {description} timed out")
return False
return False
def install_editable(project_root: Path, use_mirror: bool) -> bool:
"""Install unilabos in editable mode using pip."""
cmd = [sys.executable, "-m", "pip", "install", "-e", str(project_root)]
if use_mirror:
cmd.extend(["-i", TSINGHUA_MIRROR])
return run_command(cmd, "Installing unilabos in editable mode")
def install_requirements_uv(requirements_file: Path, use_mirror: bool) -> bool:
"""Install pip dependencies using uv (installed via conda-forge::uv)."""
cmd = ["uv", "pip", "install", "-r", str(requirements_file)]
if use_mirror:
cmd.extend(["-i", TSINGHUA_MIRROR])
return run_command(cmd, "Installing pip dependencies with uv", retry=2)
def install_requirements_pip(requirements_file: Path, use_mirror: bool) -> bool:
"""Fallback: Install pip dependencies using pip."""
cmd = [sys.executable, "-m", "pip", "install", "-r", str(requirements_file)]
if use_mirror:
cmd.extend(["-i", TSINGHUA_MIRROR])
return run_command(cmd, "Installing pip dependencies with pip", retry=2)
def check_uv_available() -> bool:
"""Check if uv is available (installed via conda-forge::uv)."""
try:
subprocess.run(["uv", "--version"], capture_output=True, check=True)
return True
except (subprocess.CalledProcessError, FileNotFoundError):
return False
def main():
parser = argparse.ArgumentParser(description="Development installation script for UniLabOS")
parser.add_argument("--china", action="store_true", help="Force use China mirror (Tsinghua)")
parser.add_argument("--no-mirror", action="store_true", help="Force use default PyPI (no mirror)")
parser.add_argument(
"--skip-deps", action="store_true", help="Skip pip dependencies installation (only install unilabos)"
)
parser.add_argument("--use-pip", action="store_true", help="Use pip instead of uv for dependencies")
args = parser.parse_args()
# Determine project root
script_dir = Path(__file__).parent
project_root = script_dir.parent
requirements_file = project_root / "unilabos" / "utils" / "requirements.txt"
if not (project_root / "setup.py").exists():
print(f"[ERROR] setup.py not found in {project_root}")
sys.exit(1)
print("=" * 60)
print("UniLabOS Development Installation")
print("=" * 60)
print(f"Project root: {project_root}")
print()
# Determine mirror usage based on locale
if args.no_mirror:
use_mirror = False
print("[INFO] Mirror disabled by --no-mirror flag")
elif args.china:
use_mirror = True
print("[INFO] China mirror enabled by --china flag")
else:
use_mirror = is_chinese_locale()
if use_mirror:
print("[INFO] Chinese locale detected, using Tsinghua mirror")
else:
print("[INFO] Non-Chinese locale detected, using default PyPI")
print()
# Step 1: Install unilabos in editable mode
print("[STEP 1] Installing unilabos in editable mode...")
if not install_editable(project_root, use_mirror):
print("[ERROR] Failed to install unilabos")
print()
print("Manual fallback:")
if use_mirror:
print(f" pip install -e {project_root} -i {TSINGHUA_MIRROR}")
else:
print(f" pip install -e {project_root}")
sys.exit(1)
print()
# Step 2: Install pip dependencies
if args.skip_deps:
print("[INFO] Skipping pip dependencies installation (--skip-deps)")
else:
print("[STEP 2] Installing pip dependencies...")
if not requirements_file.exists():
print(f"[WARN] Requirements file not found: {requirements_file}")
print("[INFO] Skipping dependencies installation")
else:
# Try uv first (faster), fallback to pip
if args.use_pip:
print("[INFO] Using pip (--use-pip flag)")
success = install_requirements_pip(requirements_file, use_mirror)
elif check_uv_available():
print("[INFO] Using uv (installed via conda-forge::uv)")
success = install_requirements_uv(requirements_file, use_mirror)
if not success:
print("[WARN] uv failed, falling back to pip...")
success = install_requirements_pip(requirements_file, use_mirror)
else:
print("[WARN] uv not available (should be installed via: mamba install conda-forge::uv)")
print("[INFO] Falling back to pip...")
success = install_requirements_pip(requirements_file, use_mirror)
if not success:
print()
print("[WARN] Failed to install some dependencies automatically.")
print("You can manually install them:")
if use_mirror:
print(f" uv pip install -r {requirements_file} -i {TSINGHUA_MIRROR}")
print(" or:")
print(f" pip install -r {requirements_file} -i {TSINGHUA_MIRROR}")
else:
print(f" uv pip install -r {requirements_file}")
print(" or:")
print(f" pip install -r {requirements_file}")
print()
print("=" * 60)
print("Installation complete!")
print("=" * 60)
print()
print("Note: Some special packages (like pylabrobot) are installed")
print("automatically at runtime by unilabos if needed.")
print()
print("Verify installation:")
print(' python -c "import unilabos; print(unilabos.__version__)"')
print()
print("If you encounter issues, you can manually install dependencies:")
if use_mirror:
print(f" uv pip install -r unilabos/utils/requirements.txt -i {TSINGHUA_MIRROR}")
else:
print(" uv pip install -r unilabos/utils/requirements.txt")
print()
if __name__ == "__main__":
main()

View File

@@ -7,7 +7,6 @@ import sys
import threading import threading
import time import time
from typing import Dict, Any, List from typing import Dict, Any, List
import networkx as nx import networkx as nx
import yaml import yaml
@@ -17,9 +16,9 @@ unilabos_dir = os.path.dirname(os.path.dirname(current_dir))
if unilabos_dir not in sys.path: if unilabos_dir not in sys.path:
sys.path.append(unilabos_dir) sys.path.append(unilabos_dir)
from unilabos.app.utils import cleanup_for_restart
from unilabos.utils.banner_print import print_status, print_unilab_banner from unilabos.utils.banner_print import print_status, print_unilab_banner
from unilabos.config.config import load_config, BasicConfig, HTTPConfig from unilabos.config.config import load_config, BasicConfig, HTTPConfig
from unilabos.app.utils import cleanup_for_restart
# Global restart flags (used by ws_client and web/server) # Global restart flags (used by ws_client and web/server)
_restart_requested: bool = False _restart_requested: bool = False
@@ -217,7 +216,10 @@ def main():
args_dict = vars(args) args_dict = vars(args)
# 环境检查 - 检查并自动安装必需的包 (可选) # 环境检查 - 检查并自动安装必需的包 (可选)
if not args_dict.get("skip_env_check", False): skip_env_check = args_dict.get("skip_env_check", False)
check_mode = args_dict.get("check_mode", False)
if not skip_env_check:
from unilabos.utils.environment_check import check_environment from unilabos.utils.environment_check import check_environment
if not check_environment(auto_install=True): if not check_environment(auto_install=True):
@@ -228,7 +230,21 @@ def main():
# 加载配置文件优先加载config然后从env读取 # 加载配置文件优先加载config然后从env读取
config_path = args_dict.get("config") config_path = args_dict.get("config")
if os.getcwd().endswith("unilabos_data"):
if check_mode:
args_dict["working_dir"] = os.path.abspath(os.getcwd())
# 当 skip_env_check 时,默认使用当前目录作为 working_dir
if skip_env_check and not args_dict.get("working_dir") and not config_path:
working_dir = os.path.abspath(os.getcwd())
print_status(f"跳过环境检查模式:使用当前目录作为工作目录 {working_dir}", "info")
# 检查当前目录是否有 local_config.py
local_config_in_cwd = os.path.join(working_dir, "local_config.py")
if os.path.exists(local_config_in_cwd):
config_path = local_config_in_cwd
print_status(f"发现本地配置文件: {config_path}", "info")
else:
print_status(f"未指定config路径可通过 --config 传入 local_config.py 文件路径", "info")
elif os.getcwd().endswith("unilabos_data"):
working_dir = os.path.abspath(os.getcwd()) working_dir = os.path.abspath(os.getcwd())
else: else:
working_dir = os.path.abspath(os.path.join(os.getcwd(), "unilabos_data")) working_dir = os.path.abspath(os.path.join(os.getcwd(), "unilabos_data"))
@@ -247,7 +263,7 @@ def main():
working_dir = os.path.dirname(config_path) working_dir = os.path.dirname(config_path)
elif os.path.exists(working_dir) and os.path.exists(os.path.join(working_dir, "local_config.py")): elif os.path.exists(working_dir) and os.path.exists(os.path.join(working_dir, "local_config.py")):
config_path = os.path.join(working_dir, "local_config.py") config_path = os.path.join(working_dir, "local_config.py")
elif not config_path and ( elif not skip_env_check and not config_path and (
not os.path.exists(working_dir) or not os.path.exists(os.path.join(working_dir, "local_config.py")) not os.path.exists(working_dir) or not os.path.exists(os.path.join(working_dir, "local_config.py"))
): ):
print_status(f"未指定config路径可通过 --config 传入 local_config.py 文件路径", "info") print_status(f"未指定config路径可通过 --config 传入 local_config.py 文件路径", "info")
@@ -261,8 +277,10 @@ def main():
print_status(f"已创建 local_config.py 路径: {config_path}", "info") print_status(f"已创建 local_config.py 路径: {config_path}", "info")
else: else:
os._exit(1) os._exit(1)
# 加载配置文件
# 加载配置文件 (check_mode 跳过)
print_status(f"当前工作目录为 {working_dir}", "info") print_status(f"当前工作目录为 {working_dir}", "info")
if not check_mode:
load_config_from_file(config_path) load_config_from_file(config_path)
# 根据配置重新设置日志级别 # 根据配置重新设置日志级别
@@ -319,12 +337,7 @@ def main():
machine_name = "".join([c if c.isalnum() or c == "_" else "_" for c in machine_name]) machine_name = "".join([c if c.isalnum() or c == "_" else "_" for c in machine_name])
BasicConfig.machine_name = machine_name BasicConfig.machine_name = machine_name
BasicConfig.vis_2d_enable = args_dict["2d_vis"] BasicConfig.vis_2d_enable = args_dict["2d_vis"]
# Check mode 处理
check_mode = args_dict.get("check_mode", False)
BasicConfig.check_mode = check_mode BasicConfig.check_mode = check_mode
if check_mode:
print_status("Check mode 启用,将进行 complete_registry 检查", "info")
from unilabos.resources.graphio import ( from unilabos.resources.graphio import (
read_node_link_json, read_node_link_json,

View File

@@ -4,8 +4,40 @@ UniLabOS 应用工具函数
提供清理、重启等工具函数 提供清理、重启等工具函数
""" """
import gc import glob
import os import os
import shutil
import sys
def patch_rclpy_dll_windows():
"""在 Windows + conda 环境下为 rclpy 打 DLL 加载补丁"""
if sys.platform != "win32" or not os.environ.get("CONDA_PREFIX"):
return
try:
import rclpy
return
except ImportError as e:
if not str(e).startswith("DLL load failed"):
return
cp = os.environ["CONDA_PREFIX"]
impl = os.path.join(cp, "Lib", "site-packages", "rclpy", "impl", "implementation_singleton.py")
pyd = glob.glob(os.path.join(cp, "Lib", "site-packages", "rclpy", "_rclpy_pybind11*.pyd"))
if not os.path.exists(impl) or not pyd:
return
with open(impl, "r", encoding="utf-8") as f:
content = f.read()
lib_bin = os.path.join(cp, "Library", "bin").replace("\\", "/")
patch = f'# UniLabOS DLL Patch\nimport os,ctypes\nos.add_dll_directory("{lib_bin}") if hasattr(os,"add_dll_directory") else None\ntry: ctypes.CDLL("{pyd[0].replace(chr(92),"/")}")\nexcept: pass\n# End Patch\n'
shutil.copy2(impl, impl + ".bak")
with open(impl, "w", encoding="utf-8") as f:
f.write(patch + content)
patch_rclpy_dll_windows()
import gc
import threading import threading
import time import time

View File

@@ -1,187 +0,0 @@
# UniLabOS 日志配置说明
> **文件位置**: `unilabos/utils/log.py`
> **最后更新**: 2026-01-11
> **维护者**: Uni-Lab-OS 开发团队
本文档说明 UniLabOS 日志系统中对第三方库和内部模块的日志级别配置,避免控制台被过多的 DEBUG 日志淹没。
---
## 📋 已屏蔽的日志
以下库/模块的日志已被设置为 **WARNING****INFO** 级别,不再显示 DEBUG 日志:
### 1. pymodbusModbus 通信库)
**配置位置**: `log.py` 第196-200行
```python
# pymodbus 库的日志太详细,设置为 WARNING
logging.getLogger('pymodbus').setLevel(logging.WARNING)
logging.getLogger('pymodbus.logging').setLevel(logging.WARNING)
logging.getLogger('pymodbus.logging.base').setLevel(logging.WARNING)
logging.getLogger('pymodbus.logging.decoders').setLevel(logging.WARNING)
```
**屏蔽原因**:
- pymodbus 在 DEBUG 级别会输出每一次 Modbus 通信的详细信息
- 包括 `Processing: 0x5 0x1e 0x0 0x0...` 等原始数据
- 包括 `decoded PDU function_code(3 sub -1) -> ReadHoldingRegistersResponse(...)` 等解码信息
- 这些信息对日常使用价值不大,但会快速刷屏
**典型被屏蔽的日志**:
```
[DEBUG] Processing: 0x5 0x1e 0x0 0x0 0x0 0x7 0x1 0x3 0x4 0x0 0x0 0x0 0x0 [handleFrame:72] [pymodbus.logging.base]
[DEBUG] decoded PDU function_code(3 sub -1) -> ReadHoldingRegistersResponse(...) [decode:79] [pymodbus.logging.decoders]
```
---
### 2. websocketsWebSocket 库)
**配置位置**: `log.py` 第202-205行
```python
# websockets 库的日志输出较多,设置为 WARNING
logging.getLogger('websockets').setLevel(logging.WARNING)
logging.getLogger('websockets.client').setLevel(logging.WARNING)
logging.getLogger('websockets.server').setLevel(logging.WARNING)
```
**屏蔽原因**:
- WebSocket 连接、断开、心跳等信息在 DEBUG 级别会频繁输出
- 对于长时间运行的服务,这些日志意义不大
---
### 3. ROS Host Node设备状态更新
**配置位置**: `log.py` 第207-208行
```python
# ROS 节点的状态更新日志过于频繁,设置为 INFO
logging.getLogger('unilabos.ros.nodes.presets.host_node').setLevel(logging.INFO)
```
**屏蔽原因**:
- 设备状态更新(如手套箱压力)每隔几秒就会更新一次
- DEBUG 日志会记录每一次状态变化,导致日志刷屏
- 这些频繁的状态更新对调试价值不大
**典型被屏蔽的日志**:
```
[DEBUG] [/devices/host_node] Status updated: BatteryStation.data_glove_box_pressure = 4.229457855224609 [property_callback:666] [unilabos.ros.nodes.presets.host_node]
```
---
### 4. asyncio 和 urllib3
**配置位置**: `log.py` 第224-225行
```python
logging.getLogger("asyncio").setLevel(logging.INFO)
logging.getLogger("urllib3").setLevel(logging.INFO)
```
**屏蔽原因**:
- asyncio: 异步 IO 的内部调试信息
- urllib3: HTTP 请求库的连接池、重试等详细信息
---
## 🔧 如何临时启用这些日志(调试用)
### 方法1: 修改 log.py永久启用
`log.py``configure_logger()` 函数中,将对应库的日志级别改为 `logging.DEBUG`:
```python
# 临时启用 pymodbus 的 DEBUG 日志
logging.getLogger('pymodbus').setLevel(logging.DEBUG)
logging.getLogger('pymodbus.logging').setLevel(logging.DEBUG)
logging.getLogger('pymodbus.logging.base').setLevel(logging.DEBUG)
logging.getLogger('pymodbus.logging.decoders').setLevel(logging.DEBUG)
```
### 方法2: 在代码中临时启用(单次调试)
在需要调试的代码文件中添加:
```python
import logging
# 临时启用 pymodbus DEBUG 日志
logging.getLogger('pymodbus').setLevel(logging.DEBUG)
# 你的 Modbus 调试代码
...
# 调试完成后恢复
logging.getLogger('pymodbus').setLevel(logging.WARNING)
```
### 方法3: 使用环境变量或配置文件(推荐)
未来可以考虑在启动参数中添加 `--debug-modbus` 等选项来动态控制。
---
## 📊 日志级别说明
| 级别 | 数值 | 用途 | 是否显示 |
|------|------|------|---------|
| TRACE | 5 | 最详细的跟踪信息 | ✅ |
| DEBUG | 10 | 调试信息 | ✅ |
| INFO | 20 | 一般信息 | ✅ |
| WARNING | 30 | 警告信息 | ✅ |
| ERROR | 40 | 错误信息 | ✅ |
| CRITICAL | 50 | 严重错误 | ✅ |
**当前配置**:
- UniLabOS 自身代码: DEBUG 及以上全部显示
- pymodbus/websockets: **WARNING** 及以上显示(屏蔽 DEBUG/INFO
- ROS host_node: **INFO** 及以上显示(屏蔽 DEBUG
---
## ⚠️ 重要提示
### 修改生效时间
- 修改 `log.py` 后需要 **重启 unilab 服务** 才能生效
- 不需要重新安装或重新编译
### 调试 Modbus 通信问题
如果需要调试 Modbus 通信故障,应该:
1. 临时启用 pymodbus DEBUG 日志方法2
2. 复现问题
3. 查看详细的通信日志
4. 调试完成后记得恢复 WARNING 级别
### 调试设备状态问题
如果需要调试设备状态更新问题:
```python
logging.getLogger('unilabos.ros.nodes.presets.host_node').setLevel(logging.DEBUG)
```
---
## 📝 维护记录
| 日期 | 修改内容 | 操作人 |
|------|---------|--------|
| 2026-01-11 | 初始创建,添加 pymodbus、websockets、ROS host_node 屏蔽 | - |
| 2026-01-07 | 添加 pymodbus 和 websockets 屏蔽log-0107.py | - |
---
## 🔗 相关文件
- `log.py` - 日志配置主文件
- `unilabos/devices/workstation/coin_cell_assembly/` - 使用 Modbus 的扣电工作站代码
- `unilabos/ros/nodes/presets/host_node.py` - ROS 主机节点代码
---
**维护提示**: 如果添加了新的第三方库或发现新的日志刷屏问题,请在此文档中记录并更新 `log.py` 配置。

View File

@@ -24,6 +24,7 @@ class EnvironmentChecker:
"msgcenterpy": "msgcenterpy", "msgcenterpy": "msgcenterpy",
"opentrons_shared_data": "opentrons_shared_data", "opentrons_shared_data": "opentrons_shared_data",
"typing_extensions": "typing_extensions", "typing_extensions": "typing_extensions",
"crcmod": "crcmod-plus",
} }
# 特殊安装包(需要特殊处理的包) # 特殊安装包(需要特殊处理的包)

View File

@@ -0,0 +1,18 @@
networkx
typing_extensions
websockets
msgcenterpy>=0.1.5
opentrons_shared_data
pint
fastapi
jinja2
requests
uvicorn
pyautogui
opcua
pyserial
pandas
crcmod-plus
pymodbus
matplotlib
pylibftdi