diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..c8f28369 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,56 @@ +name: Build and Deploy Sphinx Docs + +on: + push: + branches: + - main + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r docs/requirements.txt + + - name: Build Sphinx HTML + run: sphinx-build -b html docs docs/_build/html + + - name: Setup GitHub Pages + uses: actions/configure-pages@v3 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/_build/html + + deploy: + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 3df36620..cd09f47c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ settings.json *.egg-info video* GEMINI.md +docs/_build diff --git a/docs/_static/.keep b/docs/_static/.keep new file mode 100644 index 00000000..e69de29b diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 00000000..825c32f0 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1 @@ +# Changelog diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..d4395e70 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,48 @@ +import os +import sys +sys.path.insert(0, os.path.abspath('..')) + +project = 'Robot Control Stack' +author = 'Tobias Jülg' +release = '0.4' + +extensions = [ + 'myst_parser', + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'sphinx.ext.viewcode', +] + +templates_path = ['_templates'] +exclude_patterns = [] + +html_theme = 'pydata_sphinx_theme' +html_static_path = ['_static'] +html_logo = "images/rcs_logo_multiline.svg" +html_favicon = "images/favicon.ico" + +html_theme_options = { + "github_url": "https://github.com/RobotControlStack/robot-control-stack", + "use_edit_page_button": True, + "show_prev_next": False, + "navbar_start": ["navbar-logo"], # ensures the logo is shown + "logo": { + "image_light": "images/rcs_logo_multiline.svg", # your PNG + "image_dark": "images/rcs_logo_multiline.svg", # can be same or a dark-mode version + }, + +} + +html_context = { + "github_user": "RobotControlStack", + "github_repo": "robot-control-stack", + "github_version": "main", # branch name + "doc_path": "docs", # relative path in the repo where your docs live +} + + +myst_enable_extensions = [ + "colon_fence", + "deflist", + "linkify", +] diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 00000000..854139a3 --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1 @@ +# Contributing diff --git a/docs/documentation.md b/docs/documentation.md new file mode 100644 index 00000000..4eb41a7f --- /dev/null +++ b/docs/documentation.md @@ -0,0 +1,9 @@ +# Documentation + +```{toctree} +:maxdepth: 1 +documentation/getting_started.md +documentation/usage.md +documentation/hardware_extentions.md +documentation/development.md +``` \ No newline at end of file diff --git a/docs/documentation/development.md b/docs/documentation/development.md new file mode 100644 index 00000000..84468879 --- /dev/null +++ b/docs/documentation/development.md @@ -0,0 +1,24 @@ +# Development +```shell +# check for c++ formatting errors +make cppcheckformat +# fix them +make cppformat +# Linting with clang tidy +make cpplint +# check for python formatting errors +make pycheckformat +# fix them +make pyformat +# Linting with ruff and mypy +make pylint +# Testing +make pytest +``` + +## Stub Files for Python Bindings +We use autogenerated python stub files (`.pyi`) in the [`_core`](python/rcs/_core/) folder to show our linters the expected types of the C++ Python bindings. +If the python bindings in the C++ code have changed you might need to regenerate them by using: +```shell +make stubgen +``` \ No newline at end of file diff --git a/docs/documentation/getting_started.md b/docs/documentation/getting_started.md new file mode 100644 index 00000000..ec0d5049 --- /dev/null +++ b/docs/documentation/getting_started.md @@ -0,0 +1,10 @@ +# Getting Started + +```{toctree} +:maxdepth: 1 + +getting_started/installation.md +getting_started/docker_installation.md +getting_started/concepts.md + +``` \ No newline at end of file diff --git a/docs/documentation/getting_started/build_system.md b/docs/documentation/getting_started/build_system.md new file mode 100644 index 00000000..58415107 --- /dev/null +++ b/docs/documentation/getting_started/build_system.md @@ -0,0 +1,158 @@ +# Build System + +## 1. You Run + + pip install -e . + +This tells `pip` to: + +- Perform an **editable install** of the current project. +- Use the `pyproject.toml` as the **single source of truth** for building and packaging. + +--- + +## 2. `pip` Reads `pyproject.toml` + +It sees: + + [build-system] + build-backend = "scikit_build_core.build" + +So `pip` uses **`scikit-build-core`** as the **build backend** (instead of legacy `setuptools`). + +--- + +## 3. `scikit-build-core` Invokes CMake + +It starts a CMake build, just like if you had run: + + cmake -S . -B build + cmake --build build + +It uses the `CMakeLists.txt` at the project root, which: + +- Declares the project: + + project(rcs LANGUAGES C CXX VERSION 0.4.0) + +- Sets modern C++20 and compiler policies. +- Locates external dependencies: + - `Eigen3`, `Python3`, `MuJoCo`, `pinocchio` +- Downloads with `FetchContent`: `rl`, `pybind11` +- Includes: + + add_subdirectory(src) + +--- + +## 4. CMake Enters `src/CMakeLists.txt` + + add_subdirectory(rcs) + target_include_directories(rcs INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) + add_subdirectory(sim) + add_subdirectory(pybind) + +This loads and builds 3 subcomponents. + +--- + +## 5. Subcomponent Builds + +### `src/rcs/CMakeLists.txt` + + add_library(rcs SHARED) + target_sources(rcs PRIVATE Pose.cpp Robot.cpp IK.cpp utils.cpp) + target_link_libraries(rcs PUBLIC Eigen3::Eigen mdl pinocchio::all) + +- Builds a **shared C++ library**: `rcs` +- Contains your **robot control logic** +- Exposes `include/` headers +- Linked against external libraries + +### `src/sim/CMakeLists.txt` + + add_library(sim) + target_sources(sim PRIVATE sim.cpp SimRobot.cpp ...) + target_link_libraries(sim PUBLIC rcs MuJoCo::MuJoCo) + +- Builds a **C++ simulation library** +- Depends on: + - Your own `rcs` library + - MuJoCo physics engine + +### `src/pybind/CMakeLists.txt` + + pybind11_add_module(_core MODULE rcs.cpp) + target_link_libraries(_core PRIVATE sim rcs) + +- Compiles a Python extension module: `_core.so` +- Uses `pybind11` to bind C++ classes/functions +- Links to both `sim` and `rcs` native libraries +- Adds install instructions: + + install(TARGETS _core rcs DESTINATION rcs COMPONENT python_package) + +--- + +## 6. Packaging into Python + +From `pyproject.toml`: + + [tool.scikit-build] + build.targets = ["_core", "scenes", "rcs"] + wheel.packages = ["python/rcs"] + install.components = ["python_package"] + +- `scikit-build-core` installs `_core.so` into: + + python/rcs/_core.so + +- That directory becomes a valid **Python package** + +--- + +## 7. Result: Python Import Works + +After install: + + from rcs import _core + +- You now access the C++ functionality exposed in `rcs.cpp` through Python. +- `_core` contains Python-wrapped C++ objects/functions via `pybind11`. + +--- + +## Summary Diagram + + pip install -e . + │ + ▼ + Reads pyproject.toml (scikit_build_core used) + │ + ▼ + CMakeLists.txt (root) → add_subdirectory(src) + │ + ▼ + src/rcs → builds C++ library `rcs` + src/sim → builds C++ library `sim` + src/pybind → builds Python extension `_core` + │ + ▼ + All .so libraries installed in `python/rcs/` + `_core` accessible from Python as import + +--- + +## Recap of Build Layers + +| Layer | Role | Tool | +| --- | --- | --- | +| `pyproject.toml` | Project metadata, build backend | `pip`, `scikit-build-core` | +| `CMakeLists.txt` (root) | Configure the full C++ build | `CMake` | +| `src/rcs` | Core robot logic in C++ | `C++`, `Eigen`, `pinocchio` | +| `src/sim` | Simulation logic, MuJoCo | `C++`, `MuJoCo` | +| `src/pybind` | Bindings to Python | `pybind11` | +| `python/rcs/` | Python package with compiled `.so` | `scikit-build`, `pip` | + + + diff --git a/docs/documentation/getting_started/concepts.md b/docs/documentation/getting_started/concepts.md new file mode 100644 index 00000000..39053f95 --- /dev/null +++ b/docs/documentation/getting_started/concepts.md @@ -0,0 +1,7 @@ +# Concepts +```{toctree} +:maxdepth: 1 +:caption: Contents: +docs_action_observation_flow/action_obersvation_flow.md +build_system.md +``` diff --git a/docs/documentation/getting_started/docker_installation.md b/docs/documentation/getting_started/docker_installation.md new file mode 100644 index 00000000..687a074f --- /dev/null +++ b/docs/documentation/getting_started/docker_installation.md @@ -0,0 +1,122 @@ +# Docker +This setup lets you **build once** and then add capabilities as overrides — GUI, GPU, and Hardware (HW) — onto a single runtime service **without touching your main repo files**. + +--- + +## Prerequisites + +- **Docker** + **docker-compose** (either v1 or v2 plugin) +- **NVIDIA drivers** on host (`nvidia-smi` works on host) +- **NVIDIA Container Toolkit** installed on host (legacy runtime: `nvidia`) +- **X11** on host (Linux) +--- + +## Layout + + docker/ + Dockerfile # Your build definition + compose/ + base.yml # dev (build + source mount) and run (no mount) + gui.yml # adds DISPLAY, XAUTHORITY, X11 socket + gpu.yml # NVIDIA runtime + envs, mounts nvidia-smi + hw.yml # /dev, caps, ulimits (heavy hardware access) + +--- + +## What Each File Does + +- **base.yml** + - `dev`: builds the image from `docker/Dockerfile` and mounts your source + - `run`: clean runtime service (no source mount) +- **gui.yml** — Adds X11 env/socket so GUI apps can display on host +- **gpu.yml** — Enables GPU via legacy runtime: `nvidia` (for older compose) and ensures `nvidia-smi` is available in the container +- **hw.yml** — Grants broad hardware access + +--- + +## How to Use + +From the repo root: + +### 1) Build the image +Uses `docker/Dockerfile`. Only `dev` mounts your source. + + docker-compose -f docker/compose/base.yml build dev + +### 2) (For GUI) Allow root to use your X server + + xhost +local:docker + +### 3) Run with different capability combinations + +**GUI + GPU** + + docker-compose \ + -f docker/compose/base.yml \ + -f docker/compose/gui.yml \ + -f docker/compose/gpu.yml \ + run --rm run bash + +**GUI + GPU + HW** + + docker-compose \ + -f docker/compose/base.yml \ + -f docker/compose/gui.yml \ + -f docker/compose/gpu.yml \ + -f docker/compose/hw.yml \ + run --rm run bash + +--- + +## Quick Checks Inside the Container + +Verify GPU: + + nvidia-smi + +Test GUI apps: + + apt-get update && apt-get install -y x11-apps && xclock & + +--- + +## Sanity Check Before Running + +See the fully merged service to confirm all env/volumes are present: + + docker-compose \ + -f docker/compose/base.yml \ + -f docker/compose/gui.yml \ + -f docker/compose/gpu.yml \ + -f docker/compose/hw.yml \ + config | sed -n '/run:/,/^[^ ]/p' + +--- + +## Example: FR3 Environment in Docker + +1) Build the image: + + docker-compose -f docker/compose/base.yml build dev + +2) Run with full capabilities: + + docker-compose \ + -f docker/compose/base.yml \ + -f docker/compose/gui.yml \ + -f docker/compose/gpu.yml \ + -f docker/compose/hw.yml \ + run --rm run bash + +3) Install FR3 extension: + + pip install -ve extensions/rcs_fr3 + +4) Run example: + + cd examples + python fr3_env_cartesian_control.py + + + + diff --git a/docs/documentation/getting_started/docs_action_observation_flow/action_obersvation_flow.md b/docs/documentation/getting_started/docs_action_observation_flow/action_obersvation_flow.md new file mode 100644 index 00000000..613dbbb1 --- /dev/null +++ b/docs/documentation/getting_started/docs_action_observation_flow/action_obersvation_flow.md @@ -0,0 +1,135 @@ +# Action-Observation Flow + +## wrapper Hierarchy + + +Vertical Order: + +- Top: Highest-level wrapper (first applied) + +- Bottom: Base environment + +Inheritance Notation: + +- Use (ParentClass) next to wrapper names + +Wrapping Notation + +- Show ← wraps arrows between layers +Here is a class hierarchy diagram: + +```{image} images/class_hierarchy.png +:width: 350px +:align: center +``` +## Flow +1. **`RelativeActionSpace(ActionWrapper).step(act)`** + + - 2- Calls step function of ActionWrapper (→2) + +2. **`ActionWrapper.step(act)`** + - 3. Calls `RelativeActionSpace.action(act)` + - 4. Calls `GripperWrapper.step(act)` + +3. **`RelativeActionSpace.action(act)`** + - Processes action: `{"tquart": [0.01, 0, 0, 0, 0, 0, 1], "gripper": 0}` + - Operations: + - Clips action within min/max limits + - Makes action relative (current_pose + action) + - Updates `action["tquart"]` + +4. **`GripperWrapper(ActObsInfoWrapper).step(act)`** + - →5. Calls `GripperWrapper.action(act)` + - →6. Calls `CameraSetWrapper.step(act)` + - →15. Calls `GripperWrapper.observation(obs)` + +5. **`GripperWrapper.action(act)`** + - Uses `act["gripper"]` to open/close gripper + - Only executes if state change needed + - Deletes `"gripper"` key from action dict + +6. **`CameraSetWrapper(ActObsInfoWrapper).step(act)`** + - →7. Calls `CameraSetWrapper.action(act)` + - →8. Calls `CameraSetWrapper(ActObsInfoWrapper).step(act)` + - →14. Calls `CameraSetWrapper.observation(obs)` + +7. **`CameraSetWrapper.action(act)`** + - (Pass-through) Returns original action + +8. **`CameraSetWrapper(ActObsInfoWrapper).step(act)`** + - →9. Calls `CameraSetWrapper.action(act)` + - →10. Calls `FR3Sim.step(act)` + +9. **`CameraSetWrapper.action(act)`** + - (Pass-through) Returns original action + +10. **`FR3Sim.step(act)`** + - →11. Calls `FR3Env.step(act)` + - 13. Executes: + ```python + self.sim.step_until_convergence() + state = self.sim_robot.get_state() + ``` + - Returns observation + +11. **`FR3Env.step(act)`** + - Sets new pose: + ```python + self.robot.set_cartesian_position( + common.Pose( + translation=action_dict[self.tquart_key][:3], + quaternion=action_dict[self.tquart_key][3:] + ) + ) + ``` + - →12. Calls `FR3Env.get_obs()` + +12. **`FR3Env.get_obs()`** + - Returns: + ```python + ( + tquart=np.concatenate([ + self.robot.get_cartesian_position().translation(), + self.robot.get_cartesian_position().rotation_q() + ]), + joints=self.robot.get_joint_position(), + xyzrpy=self.robot.get_cartesian_position().xyzrpy() + ) + ``` + - Shapes: + - `joints`: (7,) + - `tquart`: (7,) [x,y,z, qx,qy,qz,qw] + - `xyzrpy`: (6,) [x,y,z, roll,pitch,yaw] + +14. **`CameraSetWrapper.observation(obs)`** + - Adds camera data: + ```python + { + ...original_obs..., + "frames": { + "wrist": { + "rgb": (256,256,3), + "depth": (256,256,3) + }, + "default_free": { + "wrist": { + "rgb": (256,256,3), + "depth": (256,256,3) + } + } + } + } + ``` + +15. **`GripperWrapper.observation(obs)`** + - Adds gripper state: + ```python + { + ...previous_data..., + "gripper": float + } + ``` +## Sequence Diagram +![image](images/sequence_diagram.png) + + diff --git a/docs/documentation/getting_started/docs_action_observation_flow/images/class_hierarchy.png b/docs/documentation/getting_started/docs_action_observation_flow/images/class_hierarchy.png new file mode 100644 index 00000000..eb7be6d1 Binary files /dev/null and b/docs/documentation/getting_started/docs_action_observation_flow/images/class_hierarchy.png differ diff --git a/docs/documentation/getting_started/docs_action_observation_flow/images/sequence_diagram.png b/docs/documentation/getting_started/docs_action_observation_flow/images/sequence_diagram.png new file mode 100644 index 00000000..0ea1df9e Binary files /dev/null and b/docs/documentation/getting_started/docs_action_observation_flow/images/sequence_diagram.png differ diff --git a/docs/documentation/getting_started/installation.md b/docs/documentation/getting_started/installation.md new file mode 100644 index 00000000..8557a54a --- /dev/null +++ b/docs/documentation/getting_started/installation.md @@ -0,0 +1,40 @@ +# Installation Guide + +## Requirements +RCS is developed and tested on the latest Debian and Ubuntu LTS versions. + +### Step 1: Install System Dependencies +First, update your package list and install dependencies listed in `debian_deps.txt`: + +- `sudo apt update` + +- `sudo apt install -y $(cat debian_deps.txt)` + + +### Step 2: Set Up Python Virtual Environment +Create and activate a virtual environment to isolate Python dependencies: + +- `python3 -m venv .venv` +- `source .venv/bin/activate` + +Upgrade packaging tools and install Python dependencies: + +- `pip install --upgrade pip setuptools wheel` +- `pip install -r requirements_dev.txt` + +Configure pip to allow build isolation: + +- `pip config --site set global.no-build-isolation false` + +### Step 3: Build and Install RCS +Install the package in editable mode for active development: + +- `pip install -ve .` + +--- + + +```{toctree} +:maxdepth: 1 + +``` \ No newline at end of file diff --git a/docs/documentation/hardware_extentions.md b/docs/documentation/hardware_extentions.md new file mode 100644 index 00000000..d7fe32bc --- /dev/null +++ b/docs/documentation/hardware_extentions.md @@ -0,0 +1,121 @@ +# Hardware Extensions + +RCS supports integration with various hardware platforms via dedicated **hardware extensions**. +These allow you to run the same RCS APIs on **real robots and sensors** without modifying your main codebase. + +For example, the **Franka Emika Research 3 (FR3)** robot is supported via the [`rcs_fr3`](extensions/rcs_fr3) extension. + +All natively supported extensions are located in the [`extensions`](extensions) directory. + +--- + +## 1. Installing Hardware Extensions + +To enable hardware usage in RCS, install the desired hardware extension via `pip`: + + pip install -ve extensions/ + +For example, to install the FR3 extension: + + pip install -ve extensions/rcs_fr3 + +> **Tip:** Each extension may have its own setup requirements. See the specific extension's section below for additional configuration steps. + +--- + +## 2. Switching Between Simulation and Hardware + +After installing the required extension, you can switch your RCS instance from simulation to hardware by setting: + + from rcs.common import RobotPlatform + + ROBOT_INSTANCE = RobotPlatform.SIMULATION # Default: Simulation + # ROBOT_INSTANCE = RobotPlatform.HARDWARE # Uncomment to use real hardware + +--- + +## 3. Command-Line Interfaces (CLI) + +Some extensions provide CLI commands to interact with hardware without writing Python code. + +For example: + + python -m rcs_fr3 --help + python -m rcs_realsense --help + +These commands allow you to perform basic operations directly from your terminal. + +--- + +## 4. FR3 Hardware Extension + +The **RCS FR3** extension enables control of the **Franka Emika Research 3** robot via RCS. + +### 4.1 Additional Configuration + +1. Create a `.env` file in your working directory with your FR3 Desk credentials: + + DESK_USERNAME=your_username + DESK_PASSWORD=your_password + +2. Set your FR3’s IP address in your script: + + ROBOT_IP = "192.168.0.1" # Replace with your robot's IP + +--- + +### 4.2 Usage Example + + import numpy as np + import rcs + import rcs_fr3 + from rcs_fr3._core import hw + from rcs_fr3.desk import FCI, Desk, load_creds_fr3_desk + from rcs_fr3.config import FR3Config, IKSolver + from rcs.common import Pose, FrankaHandTCPOffset, RobotPlatform + + ROBOT_IP = "192.168.0.1" + ROBOT_INSTANCE = RobotPlatform.HARDWARE + + # Load credentials + user, pw = load_creds_fr3_desk() + + # Connect to the robot + with FCI(Desk(ROBOT_IP, user, pw), unlock=False, lock_when_done=False): + urdf_path = rcs.scenes["fr3_empty_world"]["urdf"] + ik = rcs.common.RL(str(urdf_path)) + + # Initialize robot + robot = hw.FR3(ROBOT_IP, ik) + robot_cfg = FR3Config() + robot_cfg.tcp_offset = Pose(FrankaHandTCPOffset()) + robot_cfg.ik_solver = IKSolver.rcs_ik + robot.set_parameters(robot_cfg) + + # Configure gripper + gripper_cfg = hw.FHConfig() + gripper_cfg.epsilon_inner = gripper_cfg.epsilon_outer = 0.1 + gripper_cfg.speed = 0.1 + gripper_cfg.force = 30 + gripper = hw.FrankaHand(ROBOT_IP, gripper_cfg) + + # Move and grasp + robot.set_cartesian_position( + robot.get_cartesian_position() * Pose(translation=np.array([0.05, 0, 0])) + ) + gripper.grasp() + +--- + +### 4.3 CLI for FR3 + +The FR3 extension also defines useful CLI commands for controlling the robot without the Desk website: + + python -m rcs_fr3 --help + +--- + +## 5. Additional Resources + +- **Examples:** See the [`examples`](../../examples/) folder for more usage samples. +- **Franka Desk Documentation:** Refer to the FR3 manufacturer’s manual for setup and safety. diff --git a/docs/documentation/usage.md b/docs/documentation/usage.md new file mode 100644 index 00000000..301e9f22 --- /dev/null +++ b/docs/documentation/usage.md @@ -0,0 +1,83 @@ +# Library Usage / API +The python package is called `rcs`. + +## Direct Robot Control +Simple direct robot control: +```python +import rcs +from rcs import sim +from rcs._core.sim import CameraType +from rcs.camera.sim import SimCameraConfig, SimCameraSet +simulation = sim.Sim(rcs.scenes["fr3_empty_world"]["mjb"]) +urdf_path = rcs.scenes["fr3_empty_world"]["urdf"] +ik = rcs.common.RL(str(urdf_path)) +cfg = sim.SimRobotConfig() +cfg.add_id("0") +cfg.tcp_offset = rcs.common.Pose(rcs.common.FrankaHandTCPOffset()) +robot = rcs.sim.SimRobot(simulation, ik, cfg) + +gripper_cfg_sim = sim.SimGripperConfig() +gripper_cfg_sim.add_id("0") +gripper = sim.SimGripper(simulation, gripper_cfg_sim) + +# add camera to have a rendering gui +cameras = { + "wrist": SimCameraConfig( + identifier="wrist_0", + type=CameraType.fixed, + resolution_width=640, + resolution_height=480, + frame_rate=30, + ), +} +camera_set = SimCameraSet(simulation, cameras) +simulation.open_gui() +robot.set_cartesian_position( + robot.get_cartesian_position() * rcs.common.Pose(translation=np.array([0.05, 0, 0])) +) +gripper.grasp() +simulation.step_until_convergence() +``` +## Gym Env Interface +```python +from rcs.envs.creators import SimEnvCreator +from rcs.envs.utils import ( + default_mujoco_cameraset_cfg, + default_sim_gripper_cfg, + default_sim_robot_cfg, +) +from rcs.envs.base import ControlMode, RelativeTo +env_rel = SimEnvCreator()( + control_mode=ControlMode.JOINTS, + collision_guard=False, + robot_cfg=default_sim_robot_cfg(), + gripper_cfg=default_sim_gripper_cfg(), + cameras=default_mujoco_cameraset_cfg(), + max_relative_movement=np.deg2rad(5), + relative_to=RelativeTo.LAST_STEP, +) +env_rel.get_wrapper_attr("sim").open_gui() + +for _ in range(10): + obs, info = env_rel.reset() + for _ in range(10): + # sample random relative action and execute it + act = env_rel.action_space.sample() + print(act) + obs, reward, terminated, truncated, info = env_rel.step(act) + print(obs) + if truncated or terminated: + logger.info("Truncated or terminated!") + return +``` +## Examples +Checkout the python examples in the [examples](examples) folder: +- [fr3_direct_control.py](examples/fr3.py) shows direct robot control with RCS's python bindings +- [fr3_env_joint_control.py](examples/env_joint_control.py) and [fr3_env_cartesian_control.py](examples/env_cartesian_control.py) demonstrates RCS's high level [gymnasium](https://gymnasium.farama.org/) interface both for joint- and end effector space control +All of these examples work both in the MuJoCo simulation as well as on your hardware FR3. + + +```{toctree} +:maxdepth: 1 + +``` \ No newline at end of file diff --git a/docs/images/favicon.ico b/docs/images/favicon.ico new file mode 100644 index 00000000..909ae7af Binary files /dev/null and b/docs/images/favicon.ico differ diff --git a/docs/images/rcs_architecture_small.svg b/docs/images/rcs_architecture_small.svg new file mode 100644 index 00000000..7558b038 --- /dev/null +++ b/docs/images/rcs_architecture_small.svg @@ -0,0 +1,1072 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/rcs_logo.png b/docs/images/rcs_logo.png new file mode 100644 index 00000000..16f3efab Binary files /dev/null and b/docs/images/rcs_logo.png differ diff --git a/docs/images/rcs_logo_multiline.svg b/docs/images/rcs_logo_multiline.svg new file mode 100644 index 00000000..97449565 --- /dev/null +++ b/docs/images/rcs_logo_multiline.svg @@ -0,0 +1,153 @@ + + + + diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..ab71c596 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,38 @@ +# Robotic Control Stack (RCS) + + +![image](images/rcs_architecture_small.svg) + +**RCS** is a modular toolset designed to streamline the process of setting up and running robotics experiments and simulations. Rather than being a rigid framework, RCS acts as a minimalist, scalable architecture that brings together existing tools into an integrated system with simple, unified interfaces. + +## Key Characteristics + +- **Unified Simulation and Hardware Interface** + Seamless transitions between simulation and physical robot execution, reducing potential obstacles in development and testing cycles. + +- **Minimal Dependencies** + Lightweight and easy to set up, ensuring high portability across environments. + +- **Robot-Agnostic Design** + Initially developed for the Franka Research 3 robot, but equipped with abstraction layers to easily support other robot types. + +- **Gymnasium-Style API** + Offers a familiar and standardized interface for reinforcement learning, promoting ease of integration. + +--- + +## Use Cases of RCS + +- **Teleoperation for Data Collection** + RCS supports teleoperation to manually control robots and collect expert task demonstrations, which are essential for training robotics foundation models (RFMs). + +- **Policy-Based Control** + RCS allows robots to be controlled using trained imitation and reinforcement learning policies by providing a modular interface for easy policy switching and remote inference execution. + +```{toctree} +:maxdepth: 1 +documentation.md +contributing.md +changelog.md +roadmap.md +``` \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..236ac6bb --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,5 @@ +sphinx +pydata-sphinx-theme +myst-parser +linkify-it-py +sphinx-autobuild \ No newline at end of file diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 00000000..7feee685 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,2 @@ +# Roadmap +TODO