[Real-world active learning] PR 4: in-process RealRobot + babyrobot submodule - #93
Merged
Merged
Conversation
…ng helpers Plan PR 4 of BRIDGE_INTERFACE_PLAN.md. Replaces the two-process JSON socket bridge with an in-process library call. **No behavior change on the arm**: still whole-episode, still open-loop. - Add BabyRobotPredicator as the private submodule third_party/BabyRobotPredicator, pinned at 3565015 (its plan PRs 0-2: pyproject, message dataclasses, RealRobot). - real_robot_bridge.py: delete RealRobotBridgeClient and the whole socket/JSON transport. What remains is a make_real_robot() factory that imports babyrobot lazily, and the action-splitting helpers -- _split_actions (now driven by a GripperJointLayout rather than a SingleArmPyBulletRobot) plus split_actions_by_option, which the real-world wrapper will use to chunk by option boundary. - pybullet_domino_real.py: holds a RealRobot instead of a socket client and calls it directly. Same buffering, same whole-episode flush, same homing. - Settings: drop real_robot_bridge_host/port (there is no socket); add real_robot_dry and real_robot_perception. babyrobot stays OPTIONAL: it is not in install_requires, no module under predicators/ imports it at module level, mypy gets a [mypy-babyrobot.*] stanza, and asking for real-robot execution without it raises one error naming the submodule and the install command. `import predicators.envs` and `pip install -e .` both work on a checkout that cannot clone it -- which is what CI is. Also scopes run_autoformat.sh, conftest.py, .coveragerc and mypy.ini away from third_party/, so this repo's tooling never rewrites a submodule's working tree. Deliberately NOT in this PR (they are plan PRs 5-7): observation conversion, option-boundary observation, twin resynchronization, RealWorldEnv. Tested: tests/pybullet_helpers 64 passed; the new test file collects 15 in both configurations -- 15 pass with the submodule installed, 7 pass / 8 skip without it. mypy clean (661 files); pylint 10.00/10 on the changed files; yapf clean. Dry-robot smoke check: a Pick chunk and a Place chunk shipped separately produce exactly one `close` at the hand, so the release is not dropped.
amburger66
marked this pull request as ready for review
July 27, 2026 18:49
Comment and prose edits only, no code change. Strips a trailing space on settings.py:555 that tripped yapf and pylint's trailing-whitespace check.
Collaborator
|
Thanks for the great work! |
Author
@yichao-liang Thanks for reviewing! Right, I had the same thought so I asked claude -- I think this makes sense, but maybe we want to name the folder something else (like |
Collaborator
|
I see! |
yichao-liang
approved these changes
Jul 27, 2026
The submodule lived at third_party/BabyRobotPredicator, which collided with the pre-existing predicators/third_party/ -- a different thing entirely: vendored source (fast_downward_translator, ikfast) imported through the predicators namespace. submodules/ says what this one is: a pointer to a live external repo, installed as its own distribution and imported as `babyrobot`. - git mv third_party submodules, and rename the .gitmodules section so the submodule's name matches its path. Still pinned at 3565015. - Retarget the exclusions: conftest.py, .coveragerc, mypy.ini, run_autoformat.sh. - Update the paths in the README, the missing-babyrobot error message, and the test that asserts that message names the submodule. Two fixes that fall out of this: - mypy's exclude regex said `third_party`, which also matched the vendored predicators/third_party and silently dropped it from the check. Narrowing it to `submodules` restores master's coverage: mypy now reports 699 files against master's 698, the difference being this branch's one new test file. - scripts/run_checks.sh -- which the README points at as the one-line way to run the checks locally -- had the same submodule-dirtying bug run_autoformat.sh did: `docformatter -i -r .` and `isort .` walk the whole tree. Both now skip submodules/. Verified with the submodule both installed and absent: yapf/isort/docformatter clean, mypy clean, pylint 10.00/10 on changed files, tests/pybullet_helpers 64 passed with babyrobot installed from the new path and 56 passed / 8 skipped without it.
amburger66
enabled auto-merge (squash)
July 27, 2026 20:00
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plan PR 4 of
claude_plans/BRIDGE_INTERFACE_PLAN.md(in BabyRobotPredicator).Cross-link: this is the predicators half of BabyRobotPredicator#49 — PR 2: RealRobot in-process interface, which added the
RealRobotlibrary this PR calls. PerCONTRIBUTING.md, the two are one change split across repos.What
Replaces the two-process JSON socket bridge with an in-process library call. No behavior change on the arm — still whole-episode, still open-loop.
submodules/BabyRobotPredicator, pinned at3565015(its plan PRs 0–2:pyproject.toml, the message dataclasses, andRealRobot).real_robot_bridge.py.RealRobotBridgeClientand the entire socket/JSON transport are deleted — no sockets, no serialization, no length-prefix framing, no remote-code-execution surface, because there is no longer a wire. What remains is:make_real_robot(), a factory that imports babyrobot inside the function body and constructs theRealRobotwithdry/ perception from config;_split_actions(actions, layout), now driven by aGripperJointLayout(four numbers) rather than reaching into aSingleArmPyBulletRobot;split_actions_by_option(actions), which groups a buffered episode into per-option chunks. Unused by this PR — it is what the real-world wrapper (plan PR 6) needs to ask for one observation per option boundary — but it lands and is tested here alongside its sibling.pybullet_domino_real.py. Holds aRealRobotinstead of a socket client and calls it directly. Same buffering, same whole-episode flush, same homing before the first option.real_robot_bridge_host/_portare dropped (there is no socket to address);real_robot_dryandreal_robot_perceptionare added.babyrobot stays optional
It is a private repo, so predicators' CI cannot clone it. That constraint is enforced, not assumed:
install_requires; installed separately from the submodule path;predicators/imports babyrobot at module level — a test asserts this on the parse tree, so it holds whether or not babyrobot happens to be installed;mypy.inigets a[mypy-babyrobot.*]stanza covering both the present and absent cases;README.mddocuments the optional install.Tooling scoped away from
submodules/run_autoformat.shreformatted 40+ files inside the submodule on its first run — dirtying another repo's working tree with this repo's style config.run_autoformat.sh,scripts/run_checks.sh(which the README points at as the one-line local check),conftest.py,.coveragercandmypy.iniare all scoped to skipsubmodules/now.The submodule lives at
submodules/, notthird_party/, to keep it distinct from the pre-existingpredicators/third_party/— that holds vendored source (fast_downward_translator,ikfast) imported through the predicators namespace, whereas this is a pointer to a live external repo installed as its own distribution and imported asbabyrobot.Not in this PR
Per the plan these are PRs 5–7 and are deliberately absent: observation conversion (
state_from_observation/task_from_observation), option-boundary observation, twin resynchronization, andRealWorldEnv.How this was tested
tests/pybullet_helpers— 64 passed.tests/pybullet_helpers/test_real_robot_bridge.pycollects 15 tests in both configurations (so a silent mass-skip cannot pass for green): 15 pass with the submodule installed, 7 pass / 8 skip without it.import predicators.envsworks in both.mypy . --config-file mypy.ini— clean, 661 source files.pytest . --pylint -m pylintgate — the changed files rate 10.00/10;yapf --diffclean.stepcalls produce exactly onecloseat the hand. This is the bug that forced whole-episode shipping — the split still re-emits the leadingcloseon the Place, andRealRobot's session-wide gripper dedup drops it, so the release is not dropped.Not validated on hardware. The Franka was not moved; every check above ran with
RealRobot(dry=True)or against a stub. The arm smoke test is human-run at the rig (plan verification step 9).Note for reviewers
.gitmodulesuses the SSH URL (git@github.com:BasisResearch/BabyRobotPredicator.git), matching how the repo is cloned today. Say the word if an HTTPS URL suits more people.🤖 Generated with Claude Code