Plugin configs (PLUGIN_REGISTRY) + ROS2 clock/gantry/odometry plugins#160
Open
juan-g-bonilla wants to merge 4 commits into
Open
Plugin configs (PLUGIN_REGISTRY) + ROS2 clock/gantry/odometry plugins#160juan-g-bonilla wants to merge 4 commits into
juan-g-bonilla wants to merge 4 commits into
Conversation
samuelgundry
left a comment
Contributor
There was a problem hiding this comment.
It's great to have examples that demonstrate the power of the hook-plugin system. Per comments below, I'll sync first with you and brain storm whether we want refinements now or deferred.
Comment on lines
+60
to
+62
| @dataclass(frozen=True) | ||
| class LogRobotStateHookConfig(HookConfig): | ||
| """Reference hook config: periodically log the robot base pose. |
Contributor
There was a problem hiding this comment.
I really dislike single config_types/hook.py for everything. It's mixes framework (HookConfig) with and forces coupling of otherwise unrelated user-facing code but anyways, it is what it is with our current config system.
f45769d to
76b63ed
Compare
2457087 to
1c4d0c5
Compare
76b63ed to
77c2d97
Compare
77c2d97 to
a85eeb4
Compare
Add a plugin family on top of the lifecycle hook registry (simulator.hooks, Phase). A plugin is any class constructed as cls(cfg, simulator) that registers hooks on simulator.hooks in __init__ (duck-typed — no base class). Each pairs with a PluginConfig (CLI-visible knobs, get_cls() returns the runtime class), registered in PLUGIN_REGISTRY and selectable as the dynamic-dict field plugin.<key>:<preset>. Plugin configs flow through FullSimConfig.plugin and are instantiated in BaseSimulator.__init__. Ships the reference plugins: the none no-op (builtin_plugins.py) and the ROS2 examples clock_publish / gantry_control (ros2_plugins.py; rclpy imported lazily so core stays ROS-free). Documents the pattern (write-your-own plugin, phases, cadence) in docs/writing-extensions.md.
A plain (non-camera) plugin that reads robot_root_states each control step and publishes nav_msgs/Odometry on FRAME_END, mirroring ClockPublishPlugin. World->body twist via quat_rotate_inverse. Registered as the 'odometry' preset. rclpy/nav_msgs imported lazily so the config layer stays ROS-free. Ported from dev/gabmerri/sim-cam-service-update, re-homed from the old SensorEgressDriver onto the plugin/hook system.
ExperimentConfig gains a plugin dict field (resolved from PLUGIN_REGISTRY); EnvConfig carries it through get_tyro_env_config; base_task passes plugin=tyro_config.plugin into FullSimConfig. Previously plugin was wired only on RunSimConfig->FullSimConfig, so plugins (clock/gantry/ odometry and, on the camera branch, egress) did not run during training. Now they do.
a85eeb4 to
8998403
Compare
…e objects scene_spawn_assert.py spawns a full but UN-ACTUATED robot alongside the scene; it collapses under gravity and its falling limbs strike any free object spawned near the origin (e.g. physics-box's pbox at [0,0,0.6], multibody's bodies at [0.4,0,0.6]). That produced chaotic per-env/per-run displacement that failed the fall check non-deterministically on the isaacgym lane (physics-box / multibody-override): a free body would barely move or get nudged upward in one of the 4 envs, so fell_all_envs went False. Park the robot at y=-20 (clear of every scene object and off the +x per-env spread axis) so no scene preset can be contaminated. Verified on gjuaga-test1: physics-box/multibody/multibody-override + the full isaacgym scene-spawn file now pass deterministically (13 passed, repeated runs). Test-harness only; no product code changes.
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.
Builds on the lifecycle hook registry (base branch #158): the step loop emits phase events, and behavior attaches as callbacks. Core features (video recording, simulator bridge, virtual gantry) already run this way. This PR lets config/CLI attach the same kind of behavior without subclassing a backend, and ships the ROS2 example plugins.
What this adds
PluginConfigfamily (PLUGIN_REGISTRY, groupholosoma.config.plugin) selectable as the dynamic-dict CLI fieldplugin.<key>:<preset>.cls(cfg, simulator)that registers hooks onsimulator.hooksin__init__— duck-typed, no base class. It pairs with aPluginConfigwhoseget_cls()returns the runtime class. Same registry the core features use.BaseSimulator.__init__(fromFullSimConfig.plugin), so their hooks are registered before the loop emits any phase.RunSimConfig.plugin(sim2sim) andExperimentConfig.plugin→base_task→FullSimConfig(training).none(no-op),clock_publish+gantry_control(ROS2), andodometry— a self-sourced (non-camera) egress plugin that readsrobot_root_stateseach control step and publishesnav_msgs/Odometry.Why: one mechanism for step-loop side effects, core and custom alike — added logging, ROS2 bridges, teleop, egress, etc. become config presets (packaged entry point or
--import-file) instead of loop forks.API changes
FullSimConfig.plugin: dict[str, PluginConfig](default{}), plus registry-boundRunSimConfig.pluginandExperimentConfig.plugin(andEnvConfig.plugin, threaded throughget_tyro_env_config). Additive — existing configs unaffected.PluginConfigABC (holosoma.config_types.plugin): subclass with your knobs as dataclass fields + implementget_cls(). AlsoNoOpPluginConfig,ClockPublishPluginConfig,GantryControlPluginConfig,ROS2OdometryPluginConfig.holosoma.config.pluginfor packaged plugin presets.holosoma[ros2]— opt-in marker for the ROS2 plugins (installrclpyfrom your ROS2 distro / RoboStack; the impls import it lazily so core stays importable without ROS).Behavior changes
pluginfield is empty unless you select plugins, so no existing run changes.FRAME_BEGIN,PRE_STEP,POST_STEP,FRAME_END(periodic),EPISODE_START/EPISODE_END,CLOSE(once, reverse order)."100Hz",">100Hz","<100Hz"), resolved against the phase's base rate; the registry sub-samples natively.Usage
Write-your-own (config + duck-typed class), phases, and cadence are documented in
docs/writing-extensions.md(Plugins section).Stacked on #158 (lifecycle hook system). Review after / alongside it; the diff here is the plugin family only.