Skip to content

Releases: personalrobotics/sscbirrt

v3.9.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 18:21
f1ee323

planner.validator(constraint_tsrs=...) returns the validator a
CBiRRT.plan() call applies, so a consumer can validate another motion under
the plan's own rules using only public API (#236).

Added

  • CBiRRT.validator(constraint_tsrs=None, *, backend=None): the validator plan(..., constraint_tsrs=...) applies.
    • It lowers the constraint exactly as plan does, with the same space, checker, policy and backend selection.
    • Its reports equal result.validation and result.trajectory.validation, on either backend (#236).
    • It lets personalrobotics/ssrobot#132 validate a runtime command under the plan's own rules with public API only.

Changed

  • ValidationReport.backend is recorded but no longer part of equality. Two reports for the same subject under the
    same policy compare equal whichever implementation answered.

v3.8.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 16:57
0756749

Motion validation is public, and it is the planner's own check (#230).
sscbirrt.Validator answers for a state, a motion, a path or a timed
trajectory under an explicit policy. The planner returns a path or
trajectory only after that same validator accepts it. Seeded paths differ
from 3.7 because edge subdivision now tolerates rounding.

Added

  • Public motion validation (#230). sscbirrt.Validator validates a state, one motion or a whole path, and
    returns a ValidationReport: valid under the reported ValidationPolicy, or the first invalid state with its
    segment, fraction, failure kind, contacts (native MuJoCo scene) and violated path-constraint member. It is the
    planner's own check: Validator.for_problem(problem, config), in Python and natively (sscbirrt::Validator), with
    the native core used when every component lowers.

    • Motions are raw-linear: the straight line in raw joint values, as runtimes execute it. A continuous joint is never
      wrapped, so a half turn or more is validated as the long raw line.
    • PlanResult.validation is the returned path's report. A planner returns a path only after validating it whole;
      a path that fails is not returned (failure_reason "Returned path failed final validation", native status
      invalid_result). Only checkers that are not invariant to full turns of a continuous joint can fail it.
    • sscbirrt._native.__version__, and a StateValidator::contacts hook that witnesses use.
  • Timed trajectories are validated whole (#230). Validator.validate_trajectory checks a trajectory's whole law:

    • pieces along its source path (Trajectory.path) at the path's own states within their span;
    • other pieces at speed-bounded time steps;
    • position limits exactly, at every ramp's turning point.

    Its witness gives the piece and time_s. A trajectory that breaks its own invariants raises MalformedTrajectory.
    The smoother accepts a shortcut only if every piece the splice leaves passes this rule, and Trajectory.validation
    is the returned trajectory's report. A trajectory that failed would not be returned ("Returned trajectory failed
    final validation").

  • sscbirrt.mujoco.validator(model, data, arm, ...): the validator plan with the same arguments applies.

  • Evidence for #230.

    • tools/validation_artifact.py writes tests/reference/validation_evidence.json, and a test holds a fresh run's
      verdicts to it. On a small native MuJoCo world it records, for both backends:
      • an accepted and a rejected path, with the rejection's witness;
      • a trajectory along its path (an exact reparameterization), and a trace-changing shortcut through the wall;
      • the reports from planning next to the public calls;
      • repeated and reordered queries.
    • tools/geodude_132_evidence.py reruns the reduced Geodude edge of personalrobotics/ssrobot#132 inside ssrobot and
      records the result in tests/reference/geodude_132_evidence.json. Its timed trajectory crosses the left gripper
      for 4 ms inside a shortcut.
      • The 3.7 rule and this validator both accept it under the 0.05 policy, and planning and the public call agree.
      • The miss is the policy's, which #222 owns.
  • Two modes of motion check (#230).

    • Prefix: MotionValidator.validate answers how far from the start a motion is valid. Tree growth keeps that
      prefix, so it checks in order.
    • Whole: the new optional validate_whole (native: a virtual with a default through validate) answers whether
      the whole motion is valid. It returns the same configurations on a yes, and checks the same states in van der
      Corput order, so it stops sooner on a no. Path shortcuts and trajectory shortcut acceptance use it.
    • Reports: Validator answers whole first. On a failure it refines to the earliest invalid state.
    • Verdicts and planner outputs are unchanged; only the order of the checks differs.

Changed

  • Edge subdivision tolerates rounding (#230). An edge of length d is checked at max(1, ceil(d / resolution - 1e-9)) intervals, in the planner and the validator alike. Without the tolerance, a path piece exactly one resolution
    long, recomputed from its stored nodes, could split in two, so the final check sampled a state the planner never
    checked (one door path in 20 failed at such a midpoint). It also drops the redundant third sample that a step of
    exactly step_size took. Search state checks fall 4–14% on the benchmark problems (door about 1%), with every
    problem still succeeding 100%. Seeded paths differ from 3.7; the reference artifact's cases and statuses do not.

v3.7.1

Choose a tag to compare

@github-actions github-actions released this 13 Oct 21:54
628da21

Fixed

  • The ImportError raised by sscbirrt.backends.ssik when ssik is missing named the old range >=7,<8. It now
    names the [ssik] extra, which pins the supported range (>=8.2,<9 since 3.7.0), with no range of its own (#226).

v3.7.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 18:38
fe6316d

Every ssik family runs natively (#220). Pose goals on the JACO2, the Panda and
the iiwa now plan in C++, 14–19x faster than on the Python backend in a
no-obstacle probe. Requires ssik 8.2.

Changed

  • Every SSIK family runs natively (#220). The native backend plans pose regions (TSRs and TSR chains) with SSIK
    for every family ssik solves natively (ssik.cpp.NATIVE_FAMILIES), 6R and 7R alike:

    • UR arms;
    • general 6R arms such as ADA's Kinova JACO2;
    • the 7R SRS and spherical-shoulder arms such as the KUKA iiwa and the Franka Panda.

    Only UR arms ran natively before; the others fell back to Python for every pose goal. The adapter is ssik's own
    ssik::Solver (ssik 8.2, personalrobotics/ssik#707), which ssik verifies against its Python, so sscbirrt drops its
    family allowlist.

  • Requires ssik>=8.2,<9 (was >=7.0,<8). ssik 8.2 also caches the general-6R preparation, so a runtime-built
    JACO2's first query no longer takes about 30 s once the cache is warm (personalrobotics/ssik#708).

v3.6.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 05:07
0d3e797

Paths end on the nearest winding of the start or goal member they reached
(#212). On the pick demo the wrist no longer spins an extra turn on almost
half the seeds. The median path falls from 7.21 to 5.48 rad, and the median
timed trajectory (#214) from 3.61 to 2.91 s. Pick's median solve rises from
0.035 to 0.047 s; transport and door are unchanged (100 seeds each,
benchmarks/endpoint_windings/).

Changed

  • A path ends on the nearest winding of the start or goal member it
    reached (#212).
    When a role is a set (not finite), the member the trees
    reached can be a full turn of a bounded joint away from another member
    with the same pose. On the pick demo that spun the wrist an extra turn on
    most seeds.

    After smoothing, the planner proposes the endpoint's windings that unwind
    a turn (a joint more than π from the path's other end), and the set's
    contains decides membership. A candidate is used if a validated
    route makes the path shorter. The route unwinds the path: it keeps the
    path's route and makes the turn early, so the end of the path is
    physically unchanged. The pass is deterministic and is in both backends.

    CBiRRTConfig.shorten_endpoints (default True; C++
    PlannerConfig::shorten_endpoints) turns it off. goal_index and the
    sources are unchanged.

Migrating from 3.5.0: paths to and from sets can end on a different winding
of the same member, so seeded paths change. shorten_endpoints=False
restores 3.5.0's paths.

v3.5.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 00:42
9c06c08

Timed trajectories for execution (#214). Given joint velocity and
acceleration limits, sscbirrt now also returns a trajectory along the planned
path. It carries velocity through corners and cuts them where the planning
problem allows. On the pick demo the median duration falls from 6.23 s (a
stop at every corner) to 3.61 s. PR #211's blends retimed by TOPP-RA reach
4.47 s, and they fail validation on 8% of seeds.

Added

  • trajectory=TrajectoryOptions(...) on CBiRRT.solve, CBiRRT.plan
    (with return_details=True) and sscbirrt.mujoco.plan sets
    result.trajectory. CBiRRT.smooth_trajectory(problem, path, options)
    times a path you already have. result.path is unchanged.

  • sscbirrt.Trajectory: the exact source law. It provides:

    • evaluate, which gives q, qdot and qddot;
    • the boundary states start and goal;
    • the limits used, joint_names and the validation resolution;
    • seed, backend and why it stopped;
    • a validation record on every piece ("planned" or "shortcut").

    sample(dt_ns) gives a runtime command. It is a discretization, which the
    consumer validates under its own interpolation.

  • sscbirrt.TrajectoryOptions: the limits (required; a scalar or one per
    joint) and named stopping defaults:

    • stop once the last 40 attempts shortened the trajectory by less than 0.5%;
    • at most 400 attempts;
    • no time budget.

    The defaults come from a stopping-rule study
    (tools/trajectory_benchmark.py trace / stopping). Every rule except
    time_budget depends only on the trajectory, so a seed gives the same
    trajectory on any machine. abort_fn also stops smoothing.

  • Native trajectory smoother (sscbirrt::trajectory in the C++ core).
    It mirrors the Python reference operation by operation, and only the
    random stream differs. Parity tests hold the ramps, synchronization and
    corner merging to 1e-12. backend="auto" uses it when the problem lowers.

  • tools/trajectory_benchmark.py: #214's adoption benchmark and gates, and
    offline replay of stopping rules. tools/blend_baseline.py is a frozen copy
    of PR #211's blends, for the TOPP-RA baseline only. Results are in
    benchmarks/trajectory/.

v3.4.0

Choose a tag to compare

@github-actions github-actions released this 08 Oct 00:16
9f1b5a1

Defaults set from measurement. Collision checking is finer by default, and
root collection keeps every IK candidate of a draw, which a 240-setting
parameter study found 1.7–1.9× faster on the median, with shorter or equal
paths (#186). On the pick demo, the median solve is now 0.05 s.

Migrating from 3.3.0:

  • Code that relied on the old defaults plans different, denser paths.
    Collision is checked every 0.05 rad instead of every step_size, and up to
    every IK candidate of a draw becomes a root instead of 3.
  • To get the old behaviour, set edge_resolution=None and max_per_draw=3.
  • max_per_draw now accepts None. C++: PlannerConfig::max_per_draw is
    std::optional<int>, and edge_resolution defaults to 0.05.

Changed

  • max_per_draw defaults to None, keeping every candidate of a draw
    (#186).
    A parameter study chose this. It is in benchmarks/ablation/,
    run with tools/planning_benchmark.py sweep / analyze, with a decision
    rule fixed before the data. Stages:

    • screening: 240 settings of num_tree_roots, the sample probabilities,
      max_per_draw and step_size on pick, 20 seeds each;
    • confirmation: the shortlist on 100 fresh seeds;
    • generalization: transport and the door.

    Only max_per_draw beat today's defaults. On fresh seeds, pick's median
    solve is ×0.54 [0.46, 0.65] and its p90 ×0.58 [0.32, 0.92], with paths 12%
    shorter. Under the library's own defaults, pick is ×0.60 and transport
    ×0.53. Since #200, keeping all of a pose's IK solutions is cheap, and they
    give a tree roots on every branch. The other parameters were not better
    than today's values within the CI, so they stay. A sample probability of
    0 is the one setting that breaks the planner (72% success). The door
    keeps its explicit 400 roots: for a fixed grasp, fewer roots made its p90
    2.3–2.5× worse. max_per_draw takes None or an int (C++:
    std::optional<int>). A draw is now visited in random order whenever it
    offers more candidates than can be kept, including when the cap comes
    from num_tree_roots (#168).

  • The door demo reaches the handle first, then opens the door (#198).
    It used to plan the opening first and then reach its start. That start is
    one IK solution, which can lie on a joint winding HOME cannot reach. The
    demo failed at seed 1 that way, and at seed 0 once candidate order
    changed. Reaching any grasp first, then opening from there, succeeded on
    seeds 0–9.

  • edge_resolution defaults to 0.05 rad, independent of step_size (#204).
    It is the spacing of collision checks along an edge, a joint-space distance.
    It used to default to step_size (0.1 rad). On a UR5e with gripper, a point
    can move up to ~1.2 m per radian, so the old default let it move up to
    12 cm between checks and step over thin obstacles. 0.05 rad bounds that to
    ~6 cm. Every shipped demo and reference case already set 0.05, so they are
    unchanged. A problem that relied on the default gets finer checks, is
    slower, and plans different paths. Its returned paths are also denser: the
    planner stores each checked configuration, so there is a waypoint every
    0.05 rad. edge_resolution=None still means step_size. C++:
    PlannerConfig::edge_resolution defaults to 0.05.

v3.3.0

Choose a tag to compare

@github-actions github-actions released this 05 Oct 05:37
cb2bf7c

Root collection now follows CBiRRT, and it is much cheaper. Over 100 seeds
of the pick demo, every run succeeds (it was 97%), and the median solve drops
from 0.68 to 0.07 s (p90 from 1.69 to 0.18 s). Two changes, each measured
against the one before it with tools/planning_benchmark.py:

  • The start and goal sets keep growing during the search (#196).
  • IK windings of one physical configuration share a collision verdict
    (#200). This gives the same paths, faster.

Migrating from 3.2.0:

  • The same seed gives a different path.
  • goal_bias and start_bias are deprecated, and their meaning changed.
    Prefer goal_sample_probability and start_sample_probability; the old
    names map to them, with a warning, until 4.0.
  • C++ consumers: the PlannerConfig fields are renamed the same way.

The start and goal sets keep growing during the search, as in CBiRRT (#196).
On each tree's turn a weighted coin, the paper's P_sample, either draws new
members of that tree's own start or goal set and adds them as roots, or takes
an ordinary turn toward a random configuration. Until now, roots were
collected once, before the search, and frozen. Measured over 100 seeds per
problem, with both versions interleaved on one machine
(tools/planning_benchmark.py):

  • every run that used to time out now succeeds: pick goes from 97% to 100%
    of seeds, and the TSR-chain crank from 93% to 100%;
  • the slow tail shrinks: pick's p90 goes from 1.69 to 0.84 s (worst case
    from a 30 s timeout to 1.75 s); the crank's p90 from 11.0 to 5.4 s (worst
    case from a 120 s timeout to 12.6 s); transport's p90 from 0.45 to 0.32 s;
  • medians hold or improve, for example pick from 0.68 to 0.54 s, measured
    as root collection plus search;
  • the door, whose up-front roots already connect it in one iteration, is
    unchanged.

Changed

  • Behaviour. The same seed now gives a different path, in both backends.
    Every reference-artifact case keeps its outcome and passes validation;
    native parity holds.

  • Parameters. New start_sample_probability and goal_sample_probability
    (default 0.1) replace start_bias and goal_bias. The meaning changed: the
    old biases steered a turn's extension toward a member of the other tree's
    set. The new probabilities add roots to the tree's own set. A finite set
    never tosses the coin, because its members are all roots already. The old
    names still work until 4.0, mapped to the new ones, with a
    DeprecationWarning that says the meaning changed.

  • Faster root collection, same result (#200). SSIK returns every winding
    of every IK branch: 320 solutions per pick pose, but only about 12
    physically distinct arm poses. Root collection now collision-checks each
    physical configuration once per draw instead of every winding. Pick's root
    collection goes from 0.41 s to 0.03 s, so its median solve drops from 0.53
    to 0.07 s (p90 from 0.80 to 0.18 s). Transport's median drops from 0.14 to
    0.05 s. All 700 benchmark runs give identical paths. This needs two
    declarations, never inferred:

    • the IK solver's revolute_joints (SSIK: every joint);
    • the collision checker's full_turn_invariant (the MuJoCo checkers, when
      every planned joint is a hinge).

    stats["reused_verdicts"] counts the shared verdicts. C++: Sample::key,
    IKSolver::revolute_joints(), StateValidator::full_turn_invariant() and
    SolveStats::reused_verdicts are new.

  • New stat. PlanResult.stats["search_roots"] counts the roots added
    during the search, on both backends.

  • New tool. tools/planning_benchmark.py measures planning time and work
    on realistic problems. benchmarks/ holds the v3.2.0 baseline and this
    change's measurement.

  • C++ consumers. PlannerConfig::goal_bias and start_bias are renamed
    to goal_sample_probability and start_sample_probability, with the new
    meaning. Tree::add_root is new. SolveStats::search_roots is new.

v3.2.0

Choose a tag to compare

@github-actions github-actions released this 03 Oct 00:35
7890dbc

TSR chains plan on the native backend (#184). sscbirrt's TSRs now come from
sstsr's own C++ core (sstsr 3.3), which carries chains, so a chain goal,
start or path constraint no longer falls back to Python. The door demo plans
its chain about 15-20 times faster than on Python.

Migrating from 3.1.0: nothing to change in Python. Install pulls
sstsr>=3.3. C++ consumers of the installed package need sstsr's CMake
package findable (tsr.get_cmake_dir(), from a built wheel; an editable
install has none).

Changed

  • sstsr>=3.3,<4 is required, to build and to run. The native TSR is
    sstsr's C++, and sscbirrt's own C++ port of the TSR rules is removed.
  • The native backend lowers TSRChain regions. Exact paths match the Python
    bit-for-bit. Elsewhere a chain's distance is sstsr's bounded inverse, an
    upper bound in both backends, held to the same properties rather than to
    the same numbers. A chain whose later link has a non-identity T0_w is
    refused by sstsr 3.3 itself (personalrobotics/sstsr#169).
  • The door demo plans only its chain and drops the single-TSR comparison.
    Its README GIF is re-rendered from the native plan.
  • The reference artifact gains ur5e_mujoco_tsr_chain_crank: a UR5e turning
    a crank, with start, goal and path constraint one chain. It runs natively
    under auto.

Removed

  • C++ consumers: the RPY helpers in sscbirrt/transform.hpp
    (rot_to_rpy, xyzrpy_to_trans and their kin), which only the TSR port used,
    and their sscbirrt._native bindings. sscbirrt/sscbirrt.hpp no longer
    includes the TSR headers; include sscbirrt/tsr/tsr_set.hpp, which needs
    sstsr_cpp (found by find_package(sscbirrt)).

v3.1.0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 04:58
d7e248c

sscbirrt becomes effortless to start with. pip install "sscbirrt[demo]"
then sscbirrt-demo renders MuJoCo demos with no Menagerie clone: the robot
models come from the new sscbirrt-assets wheel. sscbirrt.mujoco plans for
an arm in a MuJoCo world in one call:
plan(model, data, Arm(model, joints, site, mjcf=...), goal=...). Errors
name what exists and how to fix it. Names are consistent across the API, and
the README opens with something you can run.

Migrating from 3.0.0: nothing breaks. Renamed names keep working with a
DeprecationWarning until 4.0:

  • ik_solver → ik;
  • tsr_samples / max_ik_per_pose → sample_draws / max_per_draw;
  • angular_joints → continuous_joints;
  • seeds → explicit_samples;
  • plan_native → sscbirrt.mujoco.plan.

Two behaviours tighten:

  • A MuJoCo model with free bodies now needs explicit joint_names.
  • A malformed start or goal raises a ValueError. Seeded TSR plans on
    arms whose IK enumerates many solutions per pose (SSIK on the UR5e) take
    different, equally valid paths, because roots are now a random subset of
    each draw (#168).

Added

  • sscbirrt-demo (pip install "sscbirrt[demo]"): rendered MuJoCo demos on
    sscbirrt.mujoco, with no Menagerie clone and no system ffmpeg (#163-#165).
    • pick: a goal set of every side grasp of three cans among obstacles.
    • transport: a can carried upright over a box by a path constraint.
    • door: a door opened along its handle's arc by a TSR chain.
    • The README shows them as GIFs, regenerated by tools/readme_gifs.py.
  • sscbirrt-assets, a separate data wheel in assets/ that packages the
    MuJoCo Menagerie UR5e and Robotiq 2F-85 models (pinned upstream commit,
    SHA-256 manifest, upstream BSD licenses kept), released by its own
    assets-v* tag pipeline. It is the first step toward
    pip install "sscbirrt[demo]" running the demos without a Menagerie
    clone (#162).
  • sscbirrt.mujoco, the one-call MuJoCo API (#175).
    • Arm(model, joints, ee_site, mjcf=...) describes the arm once and
      builds analytical IK from its MJCF. The frames that relate SSIK to the
      world are computed from the model, so an arm attached anywhere, with a
      name prefix, just works, and they are checked.
    • plan(model, data, arm, goal=..., start=..., constraint=..., holding=...)
      always returns a PlanResult.
    • start defaults to where the arm is now.
    • start, goal and constraint each take a configuration,
      configurations, a TSR, TSRs, or any set.
    • holding="can" takes the grasp from the current poses.

Changed

  • Errors name what exists: a missing site or joint lists the model's sites
    or joints, and the unlimited-joint error names the joint and both fixes.
    MuJoCoRobotModel(joint_limits=(lower, upper)) gives finite planning
    limits. Install hints match pyproject. NativeUnsupported is exported
    from sscbirrt (#174).
  • CBiRRTConfig's set tolerances are documented as applying to the sets
    plan(...) builds (#177).

Deprecated

  • Consistent names; the old ones keep working, with a DeprecationWarning,
    until 4.0 (#176).
    • CBiRRT(ik_solver=) is now ik=. ik is optional: planning between
      configurations never uses it, and TSRs without it raise a clear error.
    • CBiRRTConfig.tsr_samples / max_ik_per_pose are now sample_draws /
      max_per_draw, the names the native core already used. The budgets
      apply to any sampleable set, not only TSRs.
    • CBiRRTConfig.angular_joints and JointSpace(angular_joints=) are now
      continuous_joints. Every revolute joint is angular; the flag means
      unlimited.
    • sscbirrt.seeds is now explicit_samples, because seed means an RNG
      seed everywhere else.
  • sscbirrt.backends.native_mujoco.plan_native: use sscbirrt.mujoco.plan.
    It keeps working, with a DeprecationWarning, until 4.0 (#175).

Removed

  • The UR5e examples (ur5e_mujoco.py, ur5e_transport.py,
    tsr_union_demo.py), superseded by sscbirrt-demo on sscbirrt.mujoco.
    Their scene, which the reference artifact and the UR5e tests plan in, moved
    unchanged to sscbirrt.testing.ur5e; the artifact is bit-for-bit
    identical. multi_config_demo.py is now planar_arm.py -e 4, and
    planar_arm.py uses sscbirrt.testing's arm and IK. The examples extra
    no longer installs mediapy (#166).

Fixed

  • Roots kept from one sampling draw are now a random subset of its
    candidates, as max_ik_per_pose's "for diversity" promised, on both
    backends. Previously the first max_ik_per_pose candidates were kept,
    in the sampler's order. An IK solver that enumerates branches and joint
    windings (SSIK on the UR5e returns 256 solutions per pose) lists them in
    a fixed order, so every draw contributed near-duplicates from one
    corner of the solution set. Draws at or under the cap consume no
    randomness: the planar reference cases are bit-for-bit unchanged, and
    the three UR5e cases have new paths that pass every validation (#168).

  • dataclasses.replace(config, membership_tolerance=x) kept the old value,
    because the deprecated tsr_tolerance was a stored field mirroring it.
    Deprecated names are no longer fields (#176).

  • The native backend's "All N start/goal configuration(s)" count matches
    Python's; it counted each rejected explicit candidate twice (#170).

  • plan(start=[0.1, 0.2]): a flat list is one configuration on every
    backend, and a malformed start/goal raises a ValueError naming the
    argument and the expected shape. It used to crash under the default
    backend with TypeError: iteration over a 0-d array (#171).

  • plan_native checks its arguments before doing any work. Pose regions
    without ik raise a ValueError naming ik, instead of leaking _NoIK
    or claiming there are no pose regions. A wrong site or joint is reported
    before the scene is built. A missing native scene says that fallback
    cannot cover it (#172).

  • MuJoCoRobotModel, MuJoCoCollisionChecker and MuJoCoIKSolver no
    longer take every joint by default when the model has free or ball joints,
    which silently gave the wrong DOF; they ask for the arm's joints and list
    them (#173).

Documentation

  • README images and links use relative paths, so they render on every
    branch, in pull requests and in local previews. The release build pins
    them to the release tag in the PyPI description (tools/pypi_readme.py),
    so PyPI shows each release's own images; before this, relative images
    were broken on PyPI.
  • The README starts with installing and a runnable MuJoCo plan
    (sscbirrt.mujoco with the packaged UR5e), then the concepts. The
    PlanResult table lists backend, backend_reasons, provenance and
    stats. The MuJoCo snippets use real site names, and the tsr hand models
    are introduced for grasp regions. tests/test_readme.py runs the snippets
    (#178).
  • The README starts with installing and a runnable MuJoCo plan
    (sscbirrt.mujoco with the packaged UR5e), then the concepts. The
    PlanResult table lists backend, backend_reasons, provenance and
    stats. The MuJoCo snippets use real site names, and the tsr hand models
    are introduced for grasp regions. tests/test_readme.py runs the snippets
    (#178).