Changelog¶
All notable changes to GraspPanda are recorded here. The format follows Keep a Changelog and the project follows Semantic Versioning.
[Unreleased]¶
GraspPanda was rebuilt from scratch in October 2026. The releases up to v0.56 are an earlier
code base with a different design; they stay under their tags and on the legacy branch, and
none of their code is part of this history. Each line below has its full account in
In detail.
Added¶
- Methods. GraspNet-baseline, GSNet, Scale-Balanced-Grasp, EconomicGrasp and FineGrasp on one seed-based skeleton, and HGGD as a family of its own; each equal to its reference stage by stage with converted weights.
- Datasets and evaluation. Readers, label assets and evaluators for GraspNet-1Billion and GraspClutter6D, equal to the official tools; one command scores a GraspNet-1Billion model on GraspClutter6D.
- Options for every slot, from published code and model libraries: image and scene encoders, seed proposal, view, grouper, heads, losses, post-processing and the training recipe.
- Compose and probe.
grasppanda composebuilds a checked combination from a method config and presets;grasppanda probetrains it briefly on real frames and ends with one verdict. - Measured records. Every option was composed under each method it fits; those accepted were probed; the few without a record say why. Each probe is decided at four levels (composes, runs, learns, predicts), and swaps that train were trained longer beside the component the method ships, to see whether they train like shipped (level 2).
- Refusals that say why. Each refusal names its kind;
composelifts the ones an adapter or a setting fixes. - The combination explorer on the documentation site, and
grasppanda exploreon your machine, with a tab that runs a method. - Model zoo. Released weights scored on whole test splits, GSNet trained here, each number backed by a committed result record.
- Run a method in five minutes: a page per method, from the released file to grasps and a first number.
- Inference and analysis.
GraspInferencer,grasppanda demoandgrasppanda analyze.
Changed¶
- Documentation rebuilt around tasks: install, run a method, swap a component, read the evidence; short pages with the detail folded.
- The README is short: one picture, a quick start, what is inside and the targets; the rest is folded or in the documentation.
- Method order is by family, then year, on every page, table and list.
- Where an option works is shown as a fraction of the methods it applies to, with the reason for each method left out, instead of a class word.
- The pipeline figure shows both detector families and the parts they share.
- The toy example inherits a method-neutral recipe,
_base_/schedules/adam_10e.yaml. - The config hash leaves out the defaults of library classes, so one config hashes the same on every machine.
compose --helpandprobe --helpname the slots, examples, verdicts and exit statuses.
Fixed¶
train --resumeinto another run directory no longer writes into the checkpoint's run.- A
_base_that names a shipped config loads from any directory and from a wheel. - The CPU-only spconv wheel computes correctly: its sparse convolutions run on one thread.
infer --input DIRon a plain folder stops with what the reader looked for.- Data loaders below a
TMPDIRtoo deep for their sockets stop with the fix instead of hanging. - Combinations that used to fail in the first iteration are refused by the config check with the fix.
ASSANetno longer returns zeros for constant input features.- Image-encoder bridges say when their library downloads weights, and under which licence.
Known limits¶
- No method has passed the admission rule of the zoo yet, so the zoo has no weights to download.
- No option beside the ported methods has been trained and evaluated: a probe says a combination trains, not how good it is.
- Mixed precision is refused for the shipped detectors;
optimizer=soapunder HGGD is not verified (one CUDA illegal memory access on a shared GPU). - No shipped augmentation moves image and cloud together, so HGGD has no geometric augmentation.
- Point painting is not written by
composeand has no probe record. - Most combinations of two or more swapped options have no record.
In detail¶
Initial public version of the rebuild
- Core. YAML configs with inheritance and three layers of validation; registries with
lazy imports; typed data contracts between pipeline stages; run snapshots. Commands:
train,test,infer,demo,analyze,components,compose,probe,explore,sweep,prepare,print-config,env. - Benchmarks. Readers, derived label assets and evaluators for GraspNet-1Billion and
GraspClutter6D. Both evaluators agree with the official tools on recorded frames (1,592
and 254;
tests/integration/test_eval_parity.py,test_eval_clutter_parity.py). One command scores a GraspNet-1Billion model on GraspClutter6D. - Methods as interchangeable components, each equal to its reference implementation
stage by stage with converted weights: GraspNet-baseline, GSNet, Scale-Balanced-Grasp,
EconomicGrasp and FineGrasp on one seed-based skeleton, and HGGD as a family of its own.
tools/convert_checkpoint.pyconverts the authors' checkpoints strictly. - Scene encoders. Sparse U-Net, SpUNet, OA-CNNs, PointNet++ (two layouts), PointNeXt,
Point Transformer V3 (also with Sonata, Concerto and Utonia weights), LitePT, the
transformer encoder of Scale-Balanced-Grasp, and adapters between dense and sub-sampled
encoders. Five are weights-verified (
PointNet2,PTv3,PTv3Sonata,PTv3Utonia,LitePT): released weights load strictly and reproduce the official outputs. SpUNet, OA-CNNs and PointNeXt were compared with the official code on synthetic weights only. - Interchange.
grasppanda componentslists every component with its contract, status and source. A swap-matrix test shows, on synthetic scenes, that every combination of registered stages either trains and predicts or is refused at config time with the conflict and the fix. On real frames the probes record some accepted swaps that fail or train unstably.configs/experimental/holds ready-made encoder swaps. - Combinations.
grasppanda compose <method config> --set <slot>=<preset or component>writes a checked config, inserting the one encoder adapter the stage contracts ask for; a refused combination prints the conflict and the fix. Presets (grasppanda/presets/<slot>/) hold the settings of every encoder and stage variant for table-top depth clouds.grasppanda probe <config>runs the real trainer for a few iterations on thesamplesplit and predicts, ending with one verdict. The generated pagedocs/advanced_guides/measured_combinations.mdrecords the combinations probed on real frames and, for every option, the fraction of the methods it runs under, with the reason for each method left out; see "Measured records" below for the numbers. No AP. - Inference and analysis.
GraspInferencerandgrasppanda demo(depth image, point cloud, dataset frame or the built-in synthetic scene);grasppanda analyzesplits an AP by scene, object and cause. - Speed. Optional compiled kernels for furthest point sampling, ball query, cylinder query and nearest neighbours with bit-identical results; dense label grids are read where they are matched instead of being copied into every batch.
Added: options for every slot
Options taken from published code and model libraries, by three routes (a bridge to an
optional library, source adapted from a repository under the MIT, BSD or Apache-2.0
licence and listed in THIRD_PARTY_NOTICES.md, released weights for a class that exists).
Each has a preset, a unit test of its contract, a row and a command on its slot page
(docs/slots/, starting at docs/slots/index.md) and a measured verdict per method.
No accuracy is claimed for any of them.
- Image encoders (
model.image_encoder, registryIMAGE_ENCODERS). HGGD's image encoder is a slot:TimmImageEncoder,HFImageEncoderandTorchvisionImageEncoder(extrastimm,transformers,torchvision) with 38 presets, depth as an explicit option, and a pyramid decoder that takes any strides and widths. Left out, the model is the reference network.ImagePaintedandImagePaintedSubsampledgive the points of a seed-based method the image features at their pixel. - Scene encoders. Point-based:
PointNet2MSG,PointNet2MSGDense,PointMetaBase,PointVector,ASSANet,PointMLP,DeLA,DGCNN,RandLANet, the bridgePyGPointEncoder(extratorch_geometric) and three more PointNeXt sizes. Sparse:MinkUNet(14 to 101). Transformers and tokens:PointTransformerV1,PointTransformerV2,Volt,OctFormer(extraocnn),PointViT,PointMamba(extramamba-ssm),Uni3D(extratimm). - Released encoder weights.
pretrained: <name or path>onSpUNet,MinkUNet,PTv3,PTv3Sonata,PTv3UtoniaandLitePT, with fifteen published checkpoints registered by name;tools/convert_backbone_weights.py(PointNeXt, VoteNet, Contrastive Scene Contexts) andtools/convert_encoder_checkpoint.py(Point-MAE, MaskPoint, PointMamba, Uni3D, Volt). Weights are never shipped; several are non-commercial. - Seed proposal.
ScoredSeeds(the selecting score, the candidate rule, the sampler and the padding as options) andSampledSeeds; a registrySAMPLERSwith eleven samplers (FPS, feature and fusion FPS, score-weighted FPS, top-k, random, voxel grid, FPS then top-k, score NMS, bridges tofpsampleandtorch_cluster); 22 presets. - View.
LatticeViewStage(a lattice of any size, classification, angular class loss, soft arg-max, top-k),IcosphereViewStage(extratrimesh),HealpixViewStage(extrahealpix),DirectionViewStage,TwoVectorViewStage,RomaRotationViewStage(extraroma); 18 presets. - Grouper.
LocalGroupandDepthLocalGroup(shape, encoder and pooling as options),RoIGridGroup,RoIAwareGroup,VoxelSetAbstractionGroup,PyGConvGroup(extratorch_geometric),MultiRadiusGroup, the axis adaptersDepthEmbedGroupandDepthPoolGroup, andDepthCylinderProjectionGroup; 25 presets. - Heads and losses. Losses are a typed slot: every loss term names its kind (
class,unit,value,bins), every loss the kinds it fits, and the config check refuses another pairing with the losses that fit. Twenty loss presets, set per term (--set head.score_loss=quality-focal; extrastorchvision,kornia), three of them wrappers (hard example mining, class balance, uncertainty weighting).DecoupledGridHeadwith four presets, andswad-focal,economic-focal. - Post-processing. Twelve steps beside the collision filter and the NMS (
TopK,ScoreThreshold,FurthestGraspSampling,WorkspaceFilter,ApproachAngleFilter,TablePlaneFilter,MaskFilter,GripperLimits,GripperCentering,WidthFromCloud,ToFrame,GripperMeshCollisionFilterwith the extratrimesh);--post STEP...fortest,inferanddemo,post=forGraspInferencer, and--set post=a+bforcompose; 15 presets. - Training recipe.
composetakes--set optimizer=,schedule=,hooks=a+b,augment=a+bandrecipe=for every detector; 37 presets undergrasppanda/recipes/.TimmOptimizer,PytorchOptimizer,ScheduleFree,TimmSchedule(extraoptim),ParamGroups(rates per module, layer-wise decay),EMAHook,SWAHook,FreezeHook,ScheduleFreeHook,AdaptiveGradClipHook, and the augmentationsRandomJitter,RandomDropout,RandomShift. - Slot documentation.
docs/slots/index.md(the pipeline, the task of every slot, the number of its options, one table that classifies every option from the measured records, how to try one), an overview of the scene encoders and one page per slot.
Added: the combination explorer
- A documentation page (
docs/explorer/) that answers a selection of method and slot options from the measured records: the verdict, the reason of a refusal or failure, the compose and probe commands, the preset; a grid of option by method per slot. Data generated bytools/make_explorer.py. tools/make_explorer_contracts.pystores whatgrasppanda composeanswers for every option alone and every two options of two slots; the page shows them as a contract check, apart from measured verdicts.grasppanda exploreserves the explorer on 127.0.0.1 from the installed package and checks every selection with the realcompose; an accepted combination can be saved as a config. Nothing is trained.- The explorer's tab Run a method:
grasppanda explore --weights-dir DIR(or--weights NAME=PATH) runs a ported method, or the composed selection, on the example scene or on an uploaded depth image with its intrinsics, and shows the picture, the best grasps, the counts through the post-processing and the(G, 17)array as a download, asgrasppanda demodoes. Weights only from the files the command line named, uploads up to 20 MB in a temporary directory, one run at a time. Greyed on the documentation site, with the command that enables it. - An animated README picture (
resources/showcase-{light,dark}.svg) generated bytools/make_showcase.pyfrom a captured transcript of the three commands it shows. - The README opens with a recording of the explorer in use, light and dark
(
resources/explorer-{light,dark}.webp), made bytools/record_explorer_demo.pyfrom the built documentation site. - The explorer redesigned as a product interface: a header with the verdict mix of the
records and its caveats behind an information button; Build as a configuration column
(method tiles, the pipeline as slot rows, a searchable picker per slot, a bottom sheet on
a phone) beside a result card (status, changes, the four levels, numbers, the fall of
every loss term, alerts, the commands in a terminal, folded details); Compare as a slot
sidebar and a matrix of tiles at the chosen level with tooltips and a cell menu; Run with
numbered steps, drop zones and a result card. One SVG icon set, colour tokens with dark
variants, keyboard support throughout;
grasppanda exploregets an app bar and a dark mode. The answer of the contract check stays an outline, apart from measured verdicts.
Measured records
- 1262 cells (1014
runs, 174runs-empty, 29runs-unstable, each of those probed a second time, 41refused, 4fails), every one probed on real frames with judge 2 and the constant schedule. Beside one slot replaced at a time under every method the grid has groups for the image encoders of HGGD, every post-processing preset under all six methods, every loss preset in one term of every kind it fits, every recipe preset under every method it applies to, andcross: eighteen requests that replace an encoder together with options of other slots, at least two per method (all eighteen run). - The contract rules accept 9104 sets of stage options, counted per kind of encoder output; 95 were probed, picked so that every stage variant appears in a probed set under each kind of encoder, and the others are counted as not probed. The 3014 sets on the Swap rules page count the same rules over registered classes.
- Every record names the run that measured it; a probe that runs out of GPU memory is retried alone and, if memory stays short, not recorded.
grasppanda probetells a stage that learns from one that is only wired in (judge 2): it keeps the loss of every iteration, gives every loss term its fall over the iterations in which it was active with the flagsflat,rising,zero_at_endandconstant, names the sub-modules (depth 2) that no gradient reached and the parts whose weights did not change, and reports the scores of the predicted grasps and how far the schedule lowered the learning rate within the probe. A run that predicts no grasp on any frame is the verdictruns-empty(exit status 0); the rest is reported, not judged.tools/probe_grid.pyexports all of it, with the per-iteration losses in a side file; the records on the measured page were made by the first judge and say so until the grid is probed again.grasppanda probe --schedule constanttrains every step at the recipe's peak learning rate instead of running the recipe's schedule over the few epochs of a probe, which decays GSNet to 0.63 and EconomicGrasp to 2.4 % of its rate within 20 iterations and keeps FineGrasp in its warm-up. The optimizer, its weight decay, clipping and hooks stay the recipe's and the config hash is unchanged; the report states the schedule and the rate.--schedule recipe(the default) runs the recipe as shipped.- The measured grid covers post-processing, recipe and loss presets under every method
they apply to: every post-processing preset under all six methods (84 cells), every recipe
preset under all six (the five seed-based ones for a preset that names the scene encoder;
217 cells), every loss preset in one term of every kind it accepts under every seed-based
method with such a term (the last term of the kind in the pipeline), beside the
hand-picked loss cells (134 cells). The 302 new cells are listed as not probed yet until
their records are exported. Grid probes run with
--schedule constant, except a cell whose request sets the schedule. The four groupers that need an option only a preset supplies no longer have cells under their type names (20 refusals that were not combinations); their presets keep theirs.python -m tools.probe_grid refreshrewrites the measured file for a changed grid without probing. python -m tools.probe_grid runtakes--predict-frames(the frames every probe predicts on) and--seed(runtime.seedof every probe). A seeded run records the hash of the config with that seed, so probes of two seeds never stand for each other; without either option the commands and records are those of before.- Level 2 of the measured grid,
python -m tools.learn_check: does an option train like the stage the method ships ("trains like shipped")? A cell whose level-1 verdict isruns,runs-emptyorruns-unstabletrains for 250 iterations on the same 8 frames (seed 0,--schedule constant, prediction on 4 frames), and the mean of every loss term over the last 25 iterations is put beside that of the method as shipped under the same settings. Outcome per cell:on a par,worse,diverging,not comparable(every term redefined by the cell),failsorno reference; a term the cell redefines (a loss preset, a head bundle, an assigner, a proposal or view stage that computes its loss with other code) is marked not comparable and the cell is judged on the others. The tolerance of a method is calibrated from its reference trained under two seeds: 1.25, or the first multiple of 0.05 above the largest seed ratio of a term (1.25 for the five seed-based methods, 1.55 for HGGD); the rising threshold likewise. FineGrasp's reference and cells keep its recipe's warm-up: at the constant rate its fusion of crop scales gives every seed one feature in a short run. Post-processing, which trains nothing, is left out. The runs are probe_grid run directories (L2-<kind>), resumable;exportwrites per-cell files under$GRASPPANDA_CACHE/verification/L2/and the committed summarydocs/advanced_guides/learns_like_reference.json,pagethe page "Does it train like the shipped component?" (in the docs nav), checked by the unit suite like the measured page. Every cell is recorded: 983 cells on top of the six references trained twice, 555on a par, 347worse, 77diverging, 4not comparable(groupers 97 of 128 on a par, losses 101 of 130, encoders 108 of 230; one run each, a statement about training dynamics, not accuracy).
Added: classes of levels, and the options that fit each method
A class used to count the methods under which a component worked (built, trained 20 iterations, predicted), so "universal" meant "accepted by the contracts and did not crash". Classes now count levels, and every method lists the options of each of its slots.
grasppanda.combine.levelsdecides every measured cell at four levels from its record alone: composes (the config check accepts it), runs (the probe ran clean;runs-unstablecounts as not running only after a repeat of the probe, read from arepeatfield of the record, and is unstable, not repeated until then), learns (judge 2: every loss term active in at least half of the iterations fell by at least 5 %, none flat, rising or constant, every unit reached by a gradient, every part changed) and predicts (judge 2: grasps on every predicted frame, scores not all the same). A record of the first judge runs at most and says not checked above. The class of an option is counted per level:universalonly when it reached the level under every method it applies to, which include the five seed-based ones;most,some,specific,nonefor a stage decided under all five; else N of M probed, with the undecided methods named. A refusal by policy (trust_remote_code) waits for consent and is nevernone; a refusal shows its kind (structural, not-implemented, policy, not-a-combination) where the record has one.grasppanda.combine.optionslists the options of every slot of a method from the grid and the records.- The measured page and the slot index show the classes per level, one table per level,
each with the sentence "one run, seed 0, 20 iterations, 8 frames of one scene; a class
counts verdicts, not accuracy"; the definitions and thresholds are printed from
grasppanda.combine.levels. Every probed cell shows its grasps per frame and, for judge 2, the fall of its loss terms and the levels it missed; a probe that predicted no grasp is greyed. The numbers below a table give the fall of every term and what kept a run from learns or predicts. grasppanda compose <method config> --list [<slot>]lists only the options of that method's slots, each with its verdict, levels, class, grasps per frame and fall per loss term; the options that do not fit with the reason, kind and lift; the options without a record as not probed, with the reason (--json: everything, every message whole).--listwithout a config still lists the presets. The wheel ships the measured records for it (grasppanda/_measured/).- The explorer offers, in the lanes of a method, exactly the options of that method's list, shows the four levels of every record, the grasps per frame in every cell of the grid (greyed without a grasp), the class of an option per level with a level picker for the filters, the reason an option has no cell, and the kind of a refusal where compose reports one.
- Every shipped method config names
grasppanda compose <config> --list <slot>for each of its slots, in a comment block and above the slot in its bases (config hashes unchanged). - A generated page per method,
docs/methods/<method>.md(tools/make_method_pages.py, with--checkin the unit suite): every slot, what the method ships, the options that fit (verdict, levels, class, grasps, fall per term, the compose command), those that do not (reason, kind, lift) and those not probed. Linked from the method READMEs and from every slot page, whose class columns are now the class at runs, written from the records by the same tool. A test holds the explorer's lanes to the lists ofcompose.
Added: authors' checkpoints on whole test splits
- The model-zoo page (
docs/model_zoo.md) has two tables ofauthor-ckptnumbers, the authors' released weights scored by this toolbox, with and without collision filter and with the reported number beside each. "Authors' checkpoints scored by this toolbox": GraspNet-1Billion, the whole test split (23,040 frames), for GraspNet-baseline, Scale-Balanced-Grasp, EconomicGrasp, FineGrasp and HGGD on RealSense and for EconomicGrasp and HGGD on Kinect. "GraspClutter6D transfers": the whole test split (3,055 frames) for GraspNet-baseline, Scale-Balanced-Grasp, EconomicGrasp and HGGD. They are not reproductions. Each method's README states every difference from the reported number and what is and is not known about it. python -m tools.record_result <run directory> --method <configs directory>puts a whole-split evaluation into the zoo: it checks the run (every frame scored, clean code, hashed weights that are the file the metafile lists), copies its result records toconfigs/<method>/records/without the paths of the machine, and prints the metafile rows with the numbers computed from the per-scene values.- A metafile row names the splits of its protocol (
seen/similar/novel, ortestfor GraspClutter6D) and may stateAP0.8andAP0.4; a measured row whose record file is missing is a validation error. One test holds every measured row of every method to its record: whole split, clean code, and exactly the numbers of the row.
Added: the first model trained here
- GSNet, trained from scratch with the recipe of
gsnet/gsnet_sunet14_g1b-realsense_10e(10 epochs, seed 0), is the firstreproducedentry of the zoo: on the whole GraspNet-1Billion test split 68.83 / 60.35 / 25.20 AP without and 71.23 / 62.29 / 26.42 with the collision filter, against 65.70 / 53.75 / 23.98 and 67.12 / 54.81 / 24.31 in the paper; on the whole GraspClutter6D test split 25.58 / 31.38 / 19.42 and 26.87 / 33.00 / 20.04 (AP / AP0.8 / AP0.4). It is one training run with one seed, above the paper by more than the 1 AP of the admission gate, and the gap is not explained;configs/gsnet/README.mdsays what is known about it. - Its weights are not published yet. A weights entry of
source: grasppandamay haveurl: nullwith anotesaying so, beside its sha256; the zoo,GraspInferencerandgrasppanda demo <config>without--weightsthen say that the weights are not published instead of failing on the missing link.
Added: refusals that say why, and the ones compose lifts
- Every refusal of the stage contracts and of the config check carries a kind:
structural(a genuine incompatibility),not-implemented(the lift is named),fixed-by-compose,not-a-combination(a component without a required option, options that disagree) orpolicy.grasppanda composeprints it before each message and lists it inrefusal_kindsof its--jsonreport; the pair tables of the swapping page start each reason with it. grasppanda composenow inserts the axis adapter between a grouper and a head bundle whose axes differ (DepthEmbedGrouprepeats a crop over the depth bins,DepthPoolGrouppools over them), sets the assigner options a stage reads, lets a scoring proposal predict graspness only next toObjectnessViewStage(ScoredSeedswithselect_by: graspness_only, a new value of that option), sets the decode option of a head whose score no stage predicts, and writes the label set of the head bundle into the assigner and the data recipe (--set labels=dense|compactasks for it).--unset key.pathputs an option back to the default of its component. A data recipe refusal that remains prints the exact--set,--unsetand--optsthat rewrite it.--no-adapterleaves every such pair refused. Of the 198 refused cells of the earlier records, compose accepts 142; the records now hold their probes.SWADHead,EconomicHead,DecoupledGridHeadandTemplateViewStageapply a weight per seed (a weighted mean over their supervised entries, asOperationHead), soScaleBalancedAssignercombines with every shipped stage. A stage that does not apply one is reported as a warning, no longer refused.
Added: the conversion command in the metafile
- A metafile weights entry of
source: authorstates itsconvertcommand, exactly as the method's README prints it (a test holds the two together); a model whose weights were trained here may list the checkpoint the authors released for it asauthor_weights. The zoo's note, whichgrasppanda demo <config>prints without--weights, now gives that command and the file to pass. HGGD's README converts the file under the name the authors publish it (HGGD_realsense_checkpoint), and EconomicGrasp's gives the RealSense command beside the Kinect one.
Added: run a method in five minutes
- Every method page (
docs/methods/<method>.md) starts with Runin five minutes : the released file, its licence and sha256, and that the project publishes no weights converted from it; the conversion command and the file it writes; the demo on the example scene with what it prints and writes, the measured wall time and grasp counts; the same from Python (GraspInferencer, six statements); the browser route (grasppanda explore --weights-dir, tab Run a method); the test on every 64th frame oftest_seenwith its AP beside the whole-split row, its provenance, collision filter and ground-truth-derived inputs. Every measurement names its date, commit and machine. GSNet's section offers the checkpoint released with the reference code, which runs but is far below the paper (19.23 / 39.75 AP on the 120 frames, without and with the collision filter), beside the weights trained here, which are not published. tools/make_method_pages.pywrites the sections from the metafile, the config anddocs/methods/five_minutes.json(the measured runs; nothing measured is in the generator).tests/unit/test_method_quickstart.pytakes the commands from the pages: each parses with the parser of its program and names what exists, the demo, its camera variant and the Python block run on the CPU over each method's real pipeline with a toy detector and give the same grasps, the browser route picks each converted file for its method, and the measured runs agree with the metafiles and the configs.- The README quick start,
docs/get_started/quickstart.md, the inference guide and every method README link the six sections.
Fixed, in full
train --resume <checkpoint>with another--work-dirorruntime.run_id, or withruntime.allow_config_mismatch, wrote into the run directory of the checkpoint; with a config mismatch it replaced that run's later checkpoints andbest.pth. Such a resume now starts a new run directory belowruntime.work_dir, whoserun.jsonrecordsresumed_from, and leaves the original run as it is; a mismatch without the flag is refused before anything is written. Training longer than planned is therefore a new run directory.- A
_base_entry that is not a file next to the config names a shipped config (_base_/default_runtime.yaml,gsnet/gsnet_sunet14_g1b-realsense_10e.yaml), so a child of a shipped config and the example project load from any directory and from an installed wheel; the example project inherits by name. A missing base is reported at the file that names it. - With the CPU-only spconv wheel and more than one thread (the default), every config with
a sparse encoder stopped at the self-check, and 163 unit tests failed. The wheel's
convolutions and their backward now run on one PyTorch thread, the thread count is
restored for the other operators, and the log of a run and the
probereport say so once. The self-check stays and now compares the input gradient too. A synthetic probe of GSNet with PTv3 on the CPU with three threads:wiredin 18 s (it stopped at the self-check before; 23 s withOMP_NUM_THREADS=1). infer --input DIRon a plain folder of frames ended in a raw traceback from the reader. It now checks the directory before anything runs (the reader of the section has arootparameter and reads its first frame) and otherwise stops with anInputErrorthat names what the reader looked for and points todemo --depth FILE --intrinsicsandGraspInferencer;demo --depth DIRsays the same.- A data loader with workers below a
TMPDIRtoo deep for the sockets of its workers (beyond about 75 characters) waited forever for its first batch: every worker dropped its batches withAF_UNIX path too long, which only the worker printed. The loaders oftrainandtestnow refuse such a setting with the reason and the fix (docs/faq.md). - A model on a data recipe that does not serve its labels is refused by the config check
instead of failing at the first loss. Stages declare what they read from the training
supervision (
needs_supervision), dataset readers what a config makes them serve (served_supervision), and a rule compares the two atdata.train.dataset, naming the field, the stage that reads it and the section or transform that would serve it.grasppanda composeanswers with the shipped configs whose recipe serves the labels, or with the preset that brings the missing dataset section. - The width of the seed features is one contract. An encoder declares the width it
returns for its options (
Backbone.output_channels), a grouper the width it needs (Grouper.required_seed_channels) and the variant that takes any width; the config check compares them without building anything. Compose sets a new encoder'sout_channelsto the width the grouper needs and otherwise putsDepthCylinderProjectionGroupin place;--no-adapterleaves the pair refused. Encoders of a fixed width used to pass the check under Scale-Balanced-Grasp and fail when built. - A composed config can be the base of another compose.
compose -ono longer replaces an existing file without--force, and never the base config or a file it inherits. -
grasppanda probe: a count below one and an unknown split are argument errors (exit status 2), not verdicts; a loss that is not finite in the very first iteration isfails, notruns-unstable. -
Combinations that passed the config check and failed in the first iteration are now refused with the conflict and the fix: a head bundle or a view stage on another grid than the labels of the dataset (
num_angle,num_depth,num_views,label_views);SubsampledSeeds.num_seedsagainst the points a sub-sampling encoder returns (output_points);top_kandfriction_rangeout of range (option_problems); a point transform that moves points on a dataset section that serves images (moves_points); a post-processor that needs the cloud before sub-sampling on a section that drops it (reads_full_points;compose --set post=collision...switcheskeep_full_pointson and says so);train.amp: truefor a detector that does not declareamp_ready. ASSANetreturned zeros for the constant input features most methods feed (its stem batch-normalises them) and was recorded asruns. It has the optionuse_xyz(on in the preset) and refuses constant features without it; a unit test runs every encoder preset on constant features.grasppanda probeon real frames records the parts of the model that received no gradient (no_gradient) and reportsruns-unstablefor one; it prints what every step of a post-processing chain left; a CUDA launch failure gets the note that out-of-memory has. The synthetic wiring check labels its scene on the grid of the dataset and reads the image size of a GraspClutter6D camera.- Image-encoder bridges print one line when their library fetches pretrained weights,
with the licence it states. The presets with non-commercial weights (
convnextv2-tiny,convnextv2-atto,hf-hiera-tiny) ship withpretrained: false; a model that runs code from its hub repository (hf-radio-v3-base) is refused until the config saysaccept_remote_code: true. compose --list image_encoderlists the image encoders; a head refused for its label set names the shipped configs that serve it at once;--set image_encoder=under a seed-based method points to point painting.- Install hints name
pip install "grasppanda[<extra>]"when GraspPanda runs from an installed wheel andpip install -e ".[<extra>]"from the repository root of a checkout. For spconv they name the build that matches the installed PyTorch (spconv-cu118, ...,spconv-cpufor a CPU-only PyTorch) and list the others, instead of alwaysspconv-cu118. tools/probe_grid.pyrefuses to record from a working tree with uncommitted changes (--allow-dirtyoverrides) and records the versions of the optional libraries of a run.approach_to_rotationwas rewritten independently (cross products and a turn about the approach axis); the convention and its tests are unchanged.
Changed, in full
compose --helpandprobe --helpname the slots, the base, examples, the verdicts and the exit statuses;grasppanda components <name>names the presets of a component.- The config hash of the HGGD configs changed (one more detector option); the model and its checkpoints did not.
- The config hash no longer includes the defaults of library classes (PyTorch's optimizers
and schedulers, named by class), which differ between PyTorch versions: one config now
hashes the same on every machine. Hashes written before this change differ; a checkpoint
saved before it resumes with
runtime.allow_config_mismatch=true, andpython -m tools.probe_grid rehashrewrites the hashes of measured records.
Known limits, in full
- No method has passed the admission rule of the zoo yet, and the zoo has no weights to
download. GSNet, the one model trained here, is above the paper by more than 1 AP and
its weights are not published; a training with the unmodified reference code was not
run here. The other numbers are
author-ckpt(see above): each is one run with seed 0, and where a number differs from the reported one the cause is not known. - No option added beside the six ported methods has been trained and evaluated: a measured verdict says that a combination builds, trains for 20 iterations and predicts.
- Mixed precision (
train.amp, presethooks=amp) does not work with the shipped detectors and is refused by the config check: GSNet stopped at a half/float mismatch in the label assigner, HGGD's first loss was not finite.optimizer=soapunder HGGD is not verified: its one probe stopped at the second step with a CUDA illegal memory access on a shared GPU, which says nothing about whether it fits (it runs under GSNet). - No shipped augmentation moves image and cloud together, so a detector that reads images (HGGD) has no geometric augmentation; point transforms that move points are refused there.
- The point-painting wrappers (
image-painted,image-painted-subsampled) are not written bycomposeand have no cell in the measured records; the table of their probes indocs/slots/image_encoders.mdwas measured once by hand. grasppanda probe --synthetic(also the fallback when a dataset is missing) can reportfailsfor FineGrasp with the encodersspunetandminkunet34c-pointcontrast, whose record on real frames isruns: after the second optimizer step on the random labels of the synthetic scene the attention of the grouper returns a value that is not finite. The cause is not found.- 51 measured cells (48 sets of stages and 3 others) were probed from a working tree with
uncommitted changes (
runends in+dirty): the commit they name does not identify the probed code exactly. The runner refuses that from now on. - The unit tests of
OctFormer,PointMamba, the HEALPix view stages andhf-radio-v3-baseneedocnn,mamba-ssm,healpixandopen_clip_torch, which the shared test environments do not hold: those tests skip there, and the measured cells of those options were probed with the libraries in a private environment. Runs recorded before this change do not name the versions of the optional libraries. - The strict-loading checks of released third-party weights (integration tests) skip when the files are absent; they were run once with the files and are not repeated by CI.
- The slot pages differ in how they lay out their tables (method names as columns on some, abbreviations or one slash-separated cell on others).
- Most combinations of two or more replaced options have no measured record.
- The CPU-only wheel of spconv 2.3.8 miscomputes with more than one OpenMP thread; sparse layers detect this and stop with an explanation (see the installation guide).