diff --git a/README.md b/README.md index a200f6a..f0c0a17 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,30 @@ # Humanoid-Control-Website -Documentation site for [`Humanoid Control`](https://github.com/Berkeley-Humanoids/humanoid_control) — the -Berkeley Humanoids (Humanoid Control) humanoid low-level control stack. - -Built with [Docusaurus 3](https://docusaurus.io/) + `@docusaurus/theme-mermaid` -for source-controlled diagrams of the control flow, FSM, and package -architecture. +Documentation site for [Humanoid Control](https://github.com/Berkeley-Humanoids/humanoid_control), +the Berkeley Humanoids low-level control stack. Built with [Docusaurus 3](https://docusaurus.io/). ## Develop ```sh npm install -npm start # http://localhost:3000, hot reload +npm start # http://localhost:3000, hot reload ``` ## Build ```sh -npm run build # output: build/ -npm run serve # serve the built dist locally +npm run build # static site -> build/ +npm run serve # preview the build locally ``` ## Deploy -The `build/` directory is a fully static site — drop it on Netlify, -Cloudflare Pages, or GitHub Pages. For GitHub Pages, configure the workflow -to publish `build/`; the bundled `docusaurus.config.ts` already sets -`organizationName` and `projectName` for a `Berkeley-Humanoids/Humanoid-Control-Website` repo. - -## Layout - -``` -. -├── docusaurus.config.ts (nav, footer, mermaid, deploy config) -├── sidebars.ts (single sidebar, three categories) -├── tsconfig.json (extends @docusaurus/tsconfig) -├── src/ -│ ├── pages/index.tsx (React homepage) -│ ├── components/HomepageFeatures/ (feature cards on the homepage) -│ └── css/custom.css (Berkeley blue + gold palette) -├── static/img/ (logo, favicon, social card) -└── docs/ - ├── overview/ - │ ├── intro.md - │ ├── hardware_specifications.md - │ └── software_framework.md - ├── quick_start/ - │ ├── installation.md - │ └── lite_101.md - └── reference/ - ├── packages.md - ├── messages.md - ├── controllers.md - └── launch_args.md -``` +Pushing to `main` builds and publishes to GitHub Pages via +[`.github/workflows/deploy.yml`](.github/workflows/deploy.yml) — no manual step. -## Authoring conventions +## Authoring -- **Diagrams**: prefer Mermaid in fenced code blocks (\`\`\`mermaid). Avoid binary - images for anything expressible as a graph, sequence, or state diagram — - they version-control cleanly. -- **Admonitions (Docusaurus 3 syntax)**: `:::tip[Optional title]` (title in - brackets attached to the fence — not space-separated). -- **Cross-links**: use relative paths. Docusaurus strips the `.md` - extension at build time. +- Docs live in `docs/`; the sidebar order is set in `sidebars.ts`. +- Cross-link with relative paths — Docusaurus drops the `.md` at build. +- Admonitions use Docusaurus 3 syntax: `:::tip[Title]`. +- Diagrams are static SVGs in `static/img/diagrams/`, referenced as `/img/diagrams/…`. diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 244d098..417aca9 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -34,6 +34,8 @@ const config: Config = { editUrl: 'https://github.com/Berkeley-Humanoids/Humanoid-Control-Website/tree/main/', routeBasePath: '/', + showLastUpdateTime: true, + showLastUpdateAuthor: true, }, blog: false, theme: { @@ -69,7 +71,7 @@ const config: Config = { ], }, footer: { - style: 'dark', + style: 'light', links: [ { title: 'Getting started', diff --git a/src/components/HomepageFeatures/index.tsx b/src/components/HomepageFeatures/index.tsx deleted file mode 100644 index 05a23c3..0000000 --- a/src/components/HomepageFeatures/index.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import type {ReactNode} from 'react'; -import clsx from 'clsx'; -import Heading from '@theme/Heading'; -import styles from './styles.module.css'; - -type FeatureItem = { - title: string; - description: ReactNode; -}; - -const FeatureList: FeatureItem[] = [ - { - title: 'Two robots, one codebase', - description: ( - <> - Lite (bimanual, Robstride on SocketCAN) and{' '} - Prime (eRob over EtherCAT + Sito on SocketCAN) share - every controller, policy, and message. Robot differences live entirely - in URDF and hardware-plugin selection. - - ), - }, - { - title: 'Real-time-safe by construction', - description: ( - <> - C++20 on ros2_control + realtime_tools.{' '} - read() / update() / write() are - allocation-free; PREEMPT_RT scheduling and CPU pinning are first-class. - - ), - }, - { - title: 'MIT-mode hybrid commands', - description: ( - <> - Five command interfaces per joint (position,{' '} - velocity, effort, stiffness,{' '} - damping) — the same convention silicon, MuJoCo, and mock - hardware all honor, so policies port across tiers without re-mapping. - - ), - }, - { - title: 'Five-mode FSM', - description: ( - <> - ZERO_TORQUEDAMPINGSTANDBY →{' '} - LOCOMOTION | REMOTE. The gamepad picks the - policy at the button — there's no launch-time arg. Safety status - auto-falls to DAMPING; every transition is one{' '} - switch_controller call. - - ), - }, - { - title: 'MuJoCo sim2real', - description: ( - <> - MuJoCo applies the same MIT-mode torque formula via{' '} - qfrc_applied that our Robstride firmware computes — - controllers and trained policies run unchanged against silicon and sim. - - ), - }, - { - title: 'Out-of-process VLA tier', - description: ( - <> - Heavy transformer / diffusion policies live in a Python rclpy{' '} - node and publish MITAction over DDS.{' '} - ObservationManager mirrors the C++ side structurally so - policies promote between tiers without index drift. - - ), - }, -]; - -function Feature({title, description, index}: FeatureItem & {index: number}) { - return ( -
-
- - {title} -

{description}

-
-
- ); -} - -export default function HomepageFeatures(): ReactNode { - return ( -
-
-
- {FeatureList.map((props, idx) => ( - - ))} -
-
-
- ); -} diff --git a/src/components/HomepageFeatures/styles.module.css b/src/components/HomepageFeatures/styles.module.css deleted file mode 100644 index dae9e09..0000000 --- a/src/components/HomepageFeatures/styles.module.css +++ /dev/null @@ -1,51 +0,0 @@ -.features { - display: flex; - align-items: stretch; - padding: 3rem 0; - width: 100%; -} - -.featureCard { - position: relative; - height: 100%; - padding: 1.75rem 1.5rem; - border: 1px solid var(--ifm-color-emphasis-300); - border-radius: 12px; - background: var(--ifm-card-background-color, var(--ifm-background-color)); - transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease; - margin-bottom: 1.5rem; -} - -.featureCard:hover { - transform: translateY(-2px); - box-shadow: 0 8px 20px rgba(0, 50, 98, 0.08); - border-color: var(--ifm-color-primary); -} - -.featureBadge { - position: absolute; - top: 1rem; - right: 1rem; - font-family: ui-monospace, Menlo, Consolas, monospace; - font-size: 0.85rem; - font-weight: 700; - letter-spacing: 0.05em; - color: var(--hc-accent, #FDB515); - padding: 0.15rem 0.5rem; - border: 1px solid var(--hc-accent, #FDB515); - border-radius: 4px; - background: rgba(253, 181, 21, 0.08); -} - -.featureTitle { - font-size: 1.15rem; - margin: 0 0 0.5rem 0; - color: var(--ifm-color-primary); -} - -.featureDescription { - font-size: 0.95rem; - line-height: 1.6; - color: var(--ifm-color-content); - margin: 0; -} diff --git a/src/css/custom.css b/src/css/custom.css index e4dfd63..e91a3ef 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -1,66 +1,98 @@ /** * Site-wide overrides for Docusaurus's default (Infima) theme. * - * Palette is Berkeley blue (#003262) + Berkeley gold (#FDB515). - * The --ifm-color-primary-* ladder is generated by tuning lightness from - * the base — values picked by hand so links remain readable in both modes. + * Plain, content-first treatment: a Helvetica system stack (no webfont, zero + * dependencies), a single orange theme (#FF6633) used only for links and + * buttons, hairline chrome and generous whitespace. + * + * Palette ladder is tuned around #FF6633 (HSL 15°, 100%, 60%) by stepping + * lightness, the way Docusaurus's color generator does. */ :root { - --ifm-color-primary: #003262; /* Berkeley blue */ - --ifm-color-primary-dark: #002b54; - --ifm-color-primary-darker: #00284f; - --ifm-color-primary-darkest: #002041; - --ifm-color-primary-light: #003a72; - --ifm-color-primary-lighter: #003d76; - --ifm-color-primary-lightest: #00457d; + --ifm-color-primary: #ff6633; /* theme orange */ + --ifm-color-primary-dark: #ff5b24; + --ifm-color-primary-darker: #ff561d; + --ifm-color-primary-darkest: #ff4f14; + --ifm-color-primary-light: #ff7242; + --ifm-color-primary-lighter: #ff7649; + --ifm-color-primary-lightest: #ff7d52; + + /* Helvetica-first stack — no webfont, so nothing to self-host or fall back. */ + --ifm-font-family-base: 'Helvetica Neue', Helvetica, Arial, sans-serif; + --ifm-font-family-monospace: ui-monospace, 'SF Mono', SFMono-Regular, + Menlo, 'Cascadia Code', Consolas, monospace; + --ifm-heading-font-weight: 700; + --ifm-line-height-base: 1.65; - --ifm-code-font-size: 92%; - --docusaurus-highlighted-code-line-bg: rgba(0, 50, 98, 0.10); + --ifm-code-font-size: 90%; + --docusaurus-highlighted-code-line-bg: rgba(255, 102, 51, 0.12); - /* Accent color used by tip admonitions, hover states. */ - --hc-accent: #FDB515; + /* Calmer chrome: a hairline navbar, not a shadow. */ + --ifm-navbar-shadow: none; + --ifm-toc-border-color: var(--ifm-color-emphasis-200); } [data-theme='dark'] { - --ifm-color-primary: #6aa3d6; - --ifm-color-primary-dark: #4a8bc4; - --ifm-color-primary-darker: #3a7eba; - --ifm-color-primary-darkest: #2f6da0; - --ifm-color-primary-light: #8ab8df; - --ifm-color-primary-lighter: #99c1e3; - --ifm-color-primary-lightest: #b5d2eb; - --docusaurus-highlighted-code-line-bg: rgba(106, 163, 214, 0.15); + --ifm-color-primary: #ff7d52; + --ifm-color-primary-dark: #ff7242; + --ifm-color-primary-darker: #ff6e3d; + --ifm-color-primary-darkest: #ff6633; + --ifm-color-primary-light: #ff8861; + --ifm-color-primary-lighter: #ff8c66; + --ifm-color-primary-lightest: #ff9470; + --docusaurus-highlighted-code-line-bg: rgba(255, 122, 77, 0.18); } -/* Mermaid diagrams: cap their max width so the wide flowcharts don't - bleed off the content column. Center them under the heading. */ -.docusaurus-mermaid-container { - display: flex; - justify-content: center; - margin: 1.5rem 0; +/* Navbar: a single hairline instead of a drop shadow. */ +.navbar { + border-bottom: 1px solid var(--ifm-color-emphasis-200); } -.docusaurus-mermaid-container svg { - max-width: 100%; - height: auto; + +/* Headings: tighter tracking and balanced wrapping for an editorial feel. */ +.markdown h1, +.markdown h2, +.markdown h3 { + letter-spacing: -0.018em; + text-wrap: balance; } -/* Slightly tighter line-height in tables — the joint-spec table is wide. */ -table { - font-size: 0.95rem; - line-height: 1.5; +/* Sidebar active item: accent text, a soft fill and a left rule. */ +.menu__link--active:not(.menu__link--sublist) { + background: rgba(255, 102, 51, 0.08); + box-shadow: inset 2px 0 0 var(--ifm-color-primary); +} +[data-theme='dark'] .menu__link--active:not(.menu__link--sublist) { + background: rgba(255, 122, 77, 0.16); +} + +/* Table of contents: smaller and calmer; bolder on the active anchor. */ +.table-of-contents { + font-size: 0.8rem; +} +.table-of-contents__link--active { + font-weight: 600; } -/* Code blocks: use the Inter-monospace pairing the navbar already pulls in. */ -code, pre, .token { - font-family: ui-monospace, 'JetBrains Mono', 'Cascadia Code', - 'SF Mono', Menlo, Consolas, monospace; +/* Admonitions: flatter. Keep Infima's semantic left-border color; only drop + the shadow, thin the accent rule and round the corners a little more. */ +.theme-admonition { + border-left-width: 3px; + border-radius: 8px; + box-shadow: none; } -/* Custom container the homepage uses for the hero accent on inline code. */ -.hc-mermaid-caption { - text-align: center; +/* "Last updated" line: small and muted, the way tutorial sites show it. */ +.theme-last-updated { font-size: 0.85rem; color: var(--ifm-color-emphasis-600); - margin-top: -1rem; +} + +/* Tables: tighter line-height (the joint-spec table is wide) + a header tint. */ +table { + font-size: 0.95rem; + line-height: 1.5; +} +table thead tr { + background: var(--ifm-color-emphasis-100); } diff --git a/src/pages/index.module.css b/src/pages/index.module.css index 9af41e5..028bd46 100644 --- a/src/pages/index.module.css +++ b/src/pages/index.module.css @@ -1,61 +1,94 @@ /** - * CSS scoped to the homepage. Following Docusaurus's CSS-modules convention: - * imports as a JS object, classes are uniquified at build time. + * Homepage styles — deliberately plain. A modest, left-aligned intro followed + * by a simple "Documentation" contents list: no cards, no icons, no hover + * motion, the way a classical manual or reference site reads. Colors come from + * Infima variables so light and dark both work. */ -.heroBanner { - padding: 4rem 0; - text-align: center; - position: relative; - overflow: hidden; - background: linear-gradient(135deg, #003262 0%, #1c4f7d 60%, #246da6 100%); - color: #fff; +.hero { + padding: 4rem 0 0.5rem; } -.heroBanner :global(.hero__title) { - font-size: 3rem; - font-weight: 700; +.title { + font-size: clamp(2rem, 4vw, 2.6rem); + line-height: 1.15; letter-spacing: -0.02em; + font-weight: 700; + margin: 0 0 0.75rem; } -.heroBanner :global(.hero__subtitle) { - font-size: 1.4rem; - opacity: 0.95; +.tagline { + font-size: 1.25rem; + line-height: 1.45; + font-weight: 400; + color: var(--ifm-color-emphasis-800); + margin: 0 0 1.5rem; + max-width: 46ch; } -.tagDetail { - max-width: 720px; - margin: 1.5rem auto 0 auto; +.intro { font-size: 1rem; - opacity: 0.85; - line-height: 1.6; + line-height: 1.7; + max-width: 65ch; + margin: 0; + color: var(--ifm-color-content); } -.tagDetail code { - background: rgba(255, 255, 255, 0.15); - color: #FDB515; /* Berkeley gold */ - padding: 0.1em 0.4em; - border-radius: 4px; - font-size: 0.95em; -} - -.buttons { +.actions { display: flex; - align-items: center; - justify-content: center; - gap: 0.75rem; - margin-top: 2rem; flex-wrap: wrap; + align-items: center; + gap: 1.25rem; + margin-top: 1.75rem; } -@media screen and (max-width: 996px) { - .heroBanner { - padding: 2.5rem 1rem; - } - .heroBanner :global(.hero__title) { - font-size: 2.2rem; +.ghostLink { + font-weight: 600; +} + +/* Contents list — a plain reference index, not a card grid. */ +.contents { + margin: 3rem 0 5rem; +} + +.contentsHead { + font-size: 1.4rem; + font-weight: 700; + letter-spacing: -0.01em; + padding-bottom: 0.4rem; + border-bottom: 1px solid var(--ifm-color-emphasis-300); + margin: 0 0 1.5rem; +} + +.list { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1.75rem 3rem; +} + +.entryTitle { + font-size: 1.05rem; + font-weight: 700; + margin: 0 0 0.3rem; +} + +.entryTitle a { + color: var(--ifm-color-primary); +} + +.entryDesc { + font-size: 0.92rem; + line-height: 1.55; + color: var(--ifm-color-emphasis-700); + margin: 0; + max-width: 48ch; +} + +@media screen and (max-width: 768px) { + .hero { + padding: 2.5rem 0 0.5rem; } - .heroBanner :global(.hero__subtitle) { - font-size: 1.1rem; + .list { + grid-template-columns: 1fr; } } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 8092610..bc3f617 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,47 +1,70 @@ import type {ReactNode} from 'react'; -import clsx from 'clsx'; import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; import Heading from '@theme/Heading'; -import HomepageFeatures from '@site/src/components/HomepageFeatures'; import styles from './index.module.css'; -function HomepageHeader() { - const {siteConfig} = useDocusaurusContext(); +const GITHUB_URL = 'https://github.com/Berkeley-Humanoids/humanoid_control'; + +type Entry = { + title: string; + to: string; + desc: string; +}; + +const CONTENTS: Entry[] = [ + { + title: 'Getting started', + to: '/getting_started/intro', + desc: 'Install with pixi, then bring up Lite in MuJoCo in about ten minutes — no system-wide ROS install required.', + }, + { + title: 'Tutorials', + to: '/tutorials/', + desc: 'Learning-oriented walkthroughs: drive a single Robstride, walk an FSM in simulation, run a tracking policy.', + }, + { + title: 'How-to guides', + to: '/how_to/', + desc: 'Task recipes for real work: first real bringup, calibrate the zero pose, recover from a fault, probe the CAN bus.', + }, + { + title: 'Concepts', + to: '/concepts/', + desc: 'The reasoning layer: the architecture, the five-mode FSM, the MIT command surface, the safety pipeline.', + }, + { + title: 'Reference', + to: '/reference/quick_reference', + desc: 'Dense and scannable: hardware specs, packages, controllers, launch args, message schemas, troubleshooting.', + }, +]; + +function Hero() { return ( -
+
- - {siteConfig.title} + + Humanoid Control -

{siteConfig.tagline}

-

- A unified ros2_control stack for the Berkeley Architecture - Research bimanual humanoids — same controllers, same MIT-mode interfaces, - mock / MuJoCo / real CAN selectable from a single xacro arg. +

+ One low-level control stack for two Berkeley bimanual humanoids — Lite and Prime.

-
- - Quick start → - - - What is this? - - - Reference +

+ Built on ROS 2 Jazzy and ros2_control under PREEMPT_RT. The same + controllers, MIT-mode command interfaces, and message schemas run across both + robots; mock, MuJoCo, and real CAN / EtherCAT hardware are selectable from a + single xacro argument. Robot differences live entirely in URDF and + hardware-plugin selection. +

+
+ + Get started → - - GitHub + + View on GitHub ↗
@@ -49,15 +72,37 @@ function HomepageHeader() { ); } +function Contents() { + return ( +
+
+ + Documentation + +
+ {CONTENTS.map((item) => ( +
+ + {item.title} + +

{item.desc}

+
+ ))} +
+
+
+ ); +} + export default function Home(): ReactNode { const {siteConfig} = useDocusaurusContext(); return ( - + description="Docs for Humanoid Control, the unified low-level control stack for the Berkeley bimanual humanoids."> +
- +
); diff --git a/static/img/diagrams/concepts__architecture__01_rt_cycle.svg b/static/img/diagrams/concepts__architecture__01_rt_cycle.svg index 1bc60a8..3431921 100644 --- a/static/img/diagrams/concepts__architecture__01_rt_cycle.svg +++ b/static/img/diagrams/concepts__architecture__01_rt_cycle.svg @@ -13,7 +13,7 @@ ros2_control real-time cycle (50 Hz) -One tick = read -> update -> writecontroller_managerHardware pluginActive controllerBus (CAN / qfrc)read()update()write() +One tick = read -> update -> writecontroller_managerHardware pluginActive controllerBus (CAN / qfrc)read()update()write() read(time, period) poll cached state q, qd, tau diff --git a/static/img/diagrams/concepts__architecture__02_policy_tiers.svg b/static/img/diagrams/concepts__architecture__02_policy_tiers.svg index f51414d..7910bc7 100644 --- a/static/img/diagrams/concepts__architecture__02_policy_tiers.svg +++ b/static/img/diagrams/concepts__architecture__02_policy_tiers.svg @@ -13,30 +13,30 @@ Policy execution: System 0 (in-process, real-time) -Learned policies run in the RT loop; heavy deps confined to a launch-time prepare step -Launch-time prepare (non-RT, Python) +Learned policies run in the RT loop; heavy deps confined to a launch-time prepare step +Launch-time prepare (non-RT, Python) humanoid_control_policy / pianist_policy prepare -resolve ONNX -> .mcap + overlay -System 0 - RLPolicyController (C++, real-time update()) +resolve ONNX -> .mcap + overlay +System 0 - RLPolicyController (C++, real-time update()) ObservationManager -built-in + .mcap ref + extern +built-in + .mcap ref + extern OnnxPolicy -onnxruntime C++ (opt-in) +onnxruntime C++ (opt-in) ReferenceProvider -McapTracking / McapPiano +McapTracking / McapPiano ActionMapper -decode + scatter -> full joints +decode + scatter -> full joints at launch Per-tick inputs state interfaces | /imu/data | /piano/key_state 5 MIT command interfaces / joint -K, D, q_cmd, qd_cmd, tau_ff -> bus -System 1/2 ingress (non-RT, out-of-process) +K, D, q_cmd, qd_cmd, tau_ff -> bus +System 1/2 ingress (non-RT, out-of-process) External source -gravity-comp / VLA +gravity-comp / VLA RemotePolicyController -C++ +C++ -MITCommand / DDSone active at a time (FSM-selected) +MITCommand / DDSone active at a time (FSM-selected) diff --git a/static/img/diagrams/concepts__architecture__03_module_deps.svg b/static/img/diagrams/concepts__architecture__03_module_deps.svg index de9b80e..d4fc9de 100644 --- a/static/img/diagrams/concepts__architecture__03_module_deps.svg +++ b/static/img/diagrams/concepts__architecture__03_module_deps.svg @@ -18,15 +18,15 @@ Controllers + policies Hardware plugins + URDF Foundations (no humanoid_control_* deps) -External +External humanoid_bringup_lite -launch + YAML +launch + YAML humanoid_bringup_prime -(scaffold) +(scaffold) pianist_policy -piano key-state +piano key-state humanoid_controllers -5 modes + mode_manager +5 modes + mode_manager humanoid_control_policy ONNX runner (Python) humanoid_devices_robstride @@ -56,5 +56,5 @@ huggingface_hub nlohmann_json - + pluginlibSolid arrow = build-time dep (CMake find_package + ament)Dashed arrow = runtime dep only (pluginlib)Note: humanoid_controllers does NOT find_package(humanoid_devices_robstride) — the plugin is loaded by controller_manager at launch. diff --git a/static/img/diagrams/concepts__architecture__04_data_pipeline.svg b/static/img/diagrams/concepts__architecture__04_data_pipeline.svg index 517915c..7f3a88a 100644 --- a/static/img/diagrams/concepts__architecture__04_data_pipeline.svg +++ b/static/img/diagrams/concepts__architecture__04_data_pipeline.svg @@ -22,28 +22,28 @@ decode frame encode frame - + RX ring (SPSC, 256) - + TX ring (SPSC, 64) write() -controller_manager (RT, 50 Hz, no allocs) +controller_manager (RT, 50 Hz, no allocs) RobstrideSystem.read - + RobstrideSystem.write state_interfaces q, qd, tau command_interfaces -q_cmd, qd_cmd, tau, K, D +q_cmd, qd_cmd, tau, K, D controller.update() lock-free pop -lock-free pushcalibration applied herecalibration applied hereThe I/O thread is the only place that touches the kernel CAN socket. Lock-free SPSC rings cross the RT boundary in both directions.Calibration (direction, homing_offset) is applied inside read()/write() so controllers see joint frame, never the raw encoder. -TimingI/O thread:syscall-blocked on epoll_wait; drains kernel at line rate.RT thread:20 ms tick. read() = pop ring head, no syscalls.Latency:~1 ms wire-to-controller best case; tail bounded by SPSC depth. +lock-free pushcalibration applied herecalibration applied hereThe I/O thread is the only place that touches the kernel CAN socket. Lock-free SPSC rings cross the RT boundary in both directions.Calibration (direction, homing_offset) is applied inside read()/write() so controllers see joint frame, never the raw encoder. +TimingI/O thread:syscall-blocked on epoll_wait; drains kernel at line rate.RT thread:20 ms tick. read() = pop ring head, no syscalls.Latency:~1 ms wire-to-controller best case; tail bounded by SPSC depth. If a buffer fills upRX ring overflow:oldest frame dropped (latest-wins).TX ring overflow:write_command() returns false; flag TX_QUEUE_OVERRUN.Net effect:stale state propagates -> SafetyStatus -> auto-DAMP. diff --git a/static/img/diagrams/concepts__architecture__05_piano_data_flow.svg b/static/img/diagrams/concepts__architecture__05_piano_data_flow.svg index 0ab540e..7de43b1 100644 --- a/static/img/diagrams/concepts__architecture__05_piano_data_flow.svg +++ b/static/img/diagrams/concepts__architecture__05_piano_data_flow.svg @@ -19,25 +19,25 @@ MusicSequence (numpy bool[F,K]) - + pianist_policy song replay - + /piano/key_command TRANSIENT_LOCAL - + PianoKeyReference Provider - + ObservationManager (rclpy) - + OnnxPolicyRunner (meta-driven) - + PolicyActionDecoder + ActionMapper - + MITCommand load @@ -47,7 +47,7 @@ key_goal_states + lookahead obs vec action -joints +joints Remote PolicyController diff --git a/static/img/diagrams/concepts__calibration_math__01.svg b/static/img/diagrams/concepts__calibration_math__01.svg index 43a5bf3..520fdf1 100644 --- a/static/img/diagrams/concepts__calibration_math__01.svg +++ b/static/img/diagrams/concepts__calibration_math__01.svg @@ -17,9 +17,9 @@ read() — motor frame → joint frame raw_motor_pos (rad, encoder) - + direction * (raw - homing_offset) - + joint_pos (rad, URDF frame) @@ -29,15 +29,15 @@ write() — joint frame → motor frame command_interface /position - + direction * joint + homing_offset raw_motor_cmd CAN frame (MIT-mode) -Constants per joint: +Constants per joint: direction (URDF) -wiring fact, same per robot model +wiring fact, same per robot model homing_offset (calibration.json) per physical robot, regenerated diff --git a/static/img/diagrams/concepts__five_mode_fsm__01.svg b/static/img/diagrams/concepts__five_mode_fsm__01.svg index 8ee3255..eeab9b6 100644 --- a/static/img/diagrams/concepts__five_mode_fsm__01.svg +++ b/static/img/diagrams/concepts__five_mode_fsm__01.svg @@ -17,11 +17,11 @@ ZERO_TORQUE DAMPING - + STANDBY - + LOCOMOTION - + REMOTE DAMP (X / Ctrl+C) @@ -31,4 +31,4 @@ START_LOCOMOTION (R1+A)+is_finished START_REMOTE (R1+B) DAMP / fault -DAMP / faultQUITQUITGreen = safe / fail-safeBlue = transitionalGold = active policy +DAMP / faultQUITQUITGreen = safe / fail-safeOrange = transitionalSlate = active policy diff --git a/static/img/diagrams/concepts__frozen_schemas__01.svg b/static/img/diagrams/concepts__frozen_schemas__01.svg index 13ac346..84dacc6 100644 --- a/static/img/diagrams/concepts__frozen_schemas__01.svg +++ b/static/img/diagrams/concepts__frozen_schemas__01.svg @@ -15,12 +15,12 @@ Frozen schemas Changing these requires retraining every policy that depends on them Schema -Who locks in when you ship +Who locks in when you ship humanoid_control_msgs/MITCommand -fields name + orderRemotePolicyController (subscriber)humanoid_control_policy.ActionMapper (publisher)every trained ONNX (action_joint_names) +fields name + orderRemotePolicyController (subscriber)humanoid_control_policy.ActionMapper (publisher)every trained ONNX (action_joint_names) Joint order in YAML -controllers.yaml `joints:` listRLPolicyController obs indexObservationManager term layoutURDF `` block order +controllers.yaml `joints:` listRLPolicyController obs indexObservationManager term layoutURDF `` block order MITState (POD + dataclass) -field names, types, unitsC++ controllers (read state_interfaces)Python ObservationManager (mirror)trained policy observation_term_names +field names, types, unitsC++ controllers (read state_interfaces)Python ObservationManager (mirror)trained policy observation_term_names ObservationTerm.scale / default per-joint, per-term constantsevery ONNX trained against this scaleregression would require recalibrationEdits to anything in the left column = a new ONNX export + a sim2real re-verification pass. diff --git a/static/img/diagrams/concepts__safety_pipeline__01.svg b/static/img/diagrams/concepts__safety_pipeline__01.svg index e18f929..ebd88c6 100644 --- a/static/img/diagrams/concepts__safety_pipeline__01.svg +++ b/static/img/diagrams/concepts__safety_pipeline__01.svg @@ -36,20 +36,20 @@ flags: uint32 bit mask source: 'humanoid_devices_robstride/can0' - + /safety_status (TRANSIENT_LOCAL) - + mode_manager.on_safety() level == OK? - + request_mode(Mode::Damping) if STRICT switch fails: request_mode(Mode::ZeroTorque) - + controller_manager: switch_controller diff --git a/static/img/diagrams/getting_started__intro__01.svg b/static/img/diagrams/getting_started__intro__01.svg index d4c2d31..a053c6f 100644 --- a/static/img/diagrams/getting_started__intro__01.svg +++ b/static/img/diagrams/getting_started__intro__01.svg @@ -16,18 +16,18 @@ Developer workstation -> onboard PREEMPT_RT PC -> robot Developer workstation Onboard PC (PREEMPT_RT) -Robot (Lite shown) +Robot (Lite shown) IDE / editor - + MuJoCo viewer (humanoid_bringup_lite/mujoco) -Edits, sim runs, debug +Edits, sim runs, debug humanoid_bringup_lite / launch - + controller_manager (50 Hz) - + mode_manager - + humanoid_control_policy humanoid_devices_robstride diff --git a/static/img/diagrams/getting_started__intro__02.svg b/static/img/diagrams/getting_started__intro__02.svg index c6e5405..f6fd922 100644 --- a/static/img/diagrams/getting_started__intro__02.svg +++ b/static/img/diagrams/getting_started__intro__02.svg @@ -16,15 +16,15 @@ Shared core + per-robot leaves Shared (Lite + Prime) Lite-only -Prime-only +Prime-only humanoid_control_common -RT helpers, MITState POD +RT helpers, MITState POD humanoid_control_msgs -MITCommand, ControlMode, ... +MITCommand, ControlMode, ... humanoid_controllers -5 mode-FSM + mode_manager +5 mode-FSM + mode_manager humanoid_control_policy -ONNX runner + LeRobot ref +ONNX runner + LeRobot ref humanoid_drivers_socketcan SocketCAN bus library lite_description diff --git a/static/img/diagrams/getting_started__lite_101__01_mujoco_spawn.svg b/static/img/diagrams/getting_started__lite_101__01_mujoco_spawn.svg index d9412c9..774ab96 100644 --- a/static/img/diagrams/getting_started__lite_101__01_mujoco_spawn.svg +++ b/static/img/diagrams/getting_started__lite_101__01_mujoco_spawn.svg @@ -13,7 +13,7 @@ MuJoCo bringup spawn sequence -What happens when you run `ros2 launch humanoid_bringup_lite mujoco.launch.py`launchxacromujoco_simcontroller_managermode_manager +What happens when you run `ros2 launch humanoid_bringup_lite mujoco.launch.py`launchxacromujoco_simcontroller_managermode_manager expand xacro (use_sim:=true) URDF start mujoco_sim @@ -23,4 +23,4 @@ spawn zero_torque (active) spawn 4 others (inactive) start mode_manager -switch_controller(zero_torque)System is now at ZERO_TORQUE, publishing /joint_states at 50 Hz +switch_controller(zero_torque)System is now at ZERO_TORQUE, publishing /joint_states at 50 Hz diff --git a/static/img/diagrams/getting_started__lite_101__02_mujoco_internals.svg b/static/img/diagrams/getting_started__lite_101__02_mujoco_internals.svg index 0abc1cb..f13ca1d 100644 --- a/static/img/diagrams/getting_started__lite_101__02_mujoco_internals.svg +++ b/static/img/diagrams/getting_started__lite_101__02_mujoco_internals.svg @@ -14,16 +14,16 @@ MuJoCo bringup — single mujoco_sim process Physics + controller_manager + hardware plugin all live in one binary -mujoco_sim process (mujoco_sim_ros2) +mujoco_sim process (mujoco_sim_ros2) MuJoCo viewer (GLFW window) - + Physics step (500 Hz) - + MujocoRos2ControlPlugin (physics plugin) - + controller_manager (50 Hz) diff --git a/static/img/diagrams/how_to__first_real_bringup__01.svg b/static/img/diagrams/how_to__first_real_bringup__01.svg index 69f1ff3..fa0e794 100644 --- a/static/img/diagrams/how_to__first_real_bringup__01.svg +++ b/static/img/diagrams/how_to__first_real_bringup__01.svg @@ -13,7 +13,7 @@ Lite real-hardware bringup -What happens between `pixi run launch-real` and `ZERO_TORQUE active`operatorlaunchros2_control_nodeRobstrideSystemmode_manager +What happens between `pixi run launch-real` and `ZERO_TORQUE active`operatorlaunchros2_control_nodeRobstrideSystemmode_manager pixi run launch-real (can interfaces UP?) ip link set can0/1 up @ 1Mbit @@ -27,4 +27,4 @@ spawn damping/standby/rl/remote (inactive) start mode_manager switch_controller(zero_torque, asap) -subscribe /safety_status, /joyAfter this sequence: motors compliant, /joint_states @ 50 Hz, /control_mode publishes ZERO_TORQUE. +subscribe /safety_status, /joyAfter this sequence: motors compliant, /joint_states @ 50 Hz, /control_mode publishes ZERO_TORQUE. diff --git a/static/img/diagrams/reference__hardware_specs__01.svg b/static/img/diagrams/reference__hardware_specs__01.svg index 9132eb3..ba9bc76 100644 --- a/static/img/diagrams/reference__hardware_specs__01.svg +++ b/static/img/diagrams/reference__hardware_specs__01.svg @@ -17,42 +17,42 @@ base_link chest - + left_shoulder_pitch -17 Nm +17 Nm left_shoulder_roll -14 Nm +14 Nm left_shoulder_yaw -14 Nm +14 Nm left_elbow_pitch -14 Nm +14 Nm left_wrist_yaw -5.5 Nm +5.5 Nm left_wrist_roll -5.5 Nm +5.5 Nm left_wrist_pitch -5.5 Nm +5.5 Nm neck_yaw -10 Nm +10 Nm neck_roll -10 Nm +10 Nm neck_pitch -10 Nm +10 Nm right_shoulder_pitch -17 Nm +17 Nm right_shoulder_roll -14 Nm +14 Nm right_shoulder_yaw -14 Nm +14 Nm right_elbow_pitch -14 Nm +14 Nm right_wrist_yaw -5.5 Nm +5.5 Nm right_wrist_roll -5.5 Nm +5.5 Nm right_wrist_pitch -5.5 Nm +5.5 Nm -arm joint +arm joint neck joint diff --git a/static/img/diagrams/reference__hardware_specs__02.svg b/static/img/diagrams/reference__hardware_specs__02.svg index 2bfb3a4..dbb9002 100644 --- a/static/img/diagrams/reference__hardware_specs__02.svg +++ b/static/img/diagrams/reference__hardware_specs__02.svg @@ -13,7 +13,7 @@ Lite CAN topology -2 CAN-USB adapters, one per arm; neck shares can0 +2 CAN-USB adapters, one per arm; neck shares can0 Onboard PC PREEMPT_RT CAN-USB #0 diff --git a/static/img/diagrams/reference__hardware_specs__03.svg b/static/img/diagrams/reference__hardware_specs__03.svg index b81bf2b..ae57ac3 100644 --- a/static/img/diagrams/reference__hardware_specs__03.svg +++ b/static/img/diagrams/reference__hardware_specs__03.svg @@ -14,17 +14,17 @@ MIT-mode hybrid command Same five interfaces, same torque formula across silicon, sim, mock -5 cmd interfaces / joint +5 cmd interfaces / joint position -q_cmd +q_cmd velocity -qd_cmd +qd_cmd effort -tau_ff +tau_ff stiffness -K_p +K_p damping -K_d +K_d tau = K_p * (q_cmd - q) + K_d * (qd_cmd - qd) + tau_ff diff --git a/static/img/diagrams/reference__messages__01.svg b/static/img/diagrams/reference__messages__01.svg index 1bd233e..04cb280 100644 --- a/static/img/diagrams/reference__messages__01.svg +++ b/static/img/diagrams/reference__messages__01.svg @@ -16,15 +16,15 @@ Who publishes / who subscribes for each of the 4 active topics Publishers Topics -Subscribers +Subscribers StandbyController - + mode_manager Hardware plugins - + Active policy ctrls - + humanoid_control_policy (Python) /standby_controller/state @@ -34,12 +34,12 @@ /safety_status ~/command (MITCommand) - + mode_manager diagnostics / log - + mode_manager - + RemotePolicyController /standby_controller/state uses TRANSIENT_LOCAL QoS so a late mode_manager sees the last is_finished diff --git a/static/img/diagrams/reference__packages__01_xacro_selector.svg b/static/img/diagrams/reference__packages__01_xacro_selector.svg index 67b75c8..9f3c16d 100644 --- a/static/img/diagrams/reference__packages__01_xacro_selector.svg +++ b/static/img/diagrams/reference__packages__01_xacro_selector.svg @@ -13,12 +13,12 @@ lite.urdf.xacro: 3-way hardware selector -One xacro file, three target backends +One xacro file, three target backends lite.urdf.xacro use_sim? -args +args mujoco_ros2_control/ MujocoSystem diff --git a/static/img/logo.svg b/static/img/logo.svg index 27a111e..eadb9b6 100644 --- a/static/img/logo.svg +++ b/static/img/logo.svg @@ -1,14 +1,12 @@ - - + + - + - + - - - - + +