Skip to content

Catalog search (bt.catalog)

Real products to choose from: the catalog's published index, filtered the way a requirement reads. See Selecting parts.

cands = bt.catalog.search("gripper.parallel", stroke_mm=150, payload_kg=2.3)
cands[0].identify(scene, "ur5e/tool")
bt.catalog.search_for(scene.requirements()["eye"], level="V2")

catalog

Search the botrail catalog — real products to choose from.

The catalog (the Hugging Face dataset botrail/botrail-catalog) publishes an index.json with every product's category, maker, numeric specs and validation level. This module reads that index and filters it the way a requirement reads — minimums on spec keys — so a person or an agent picks from products that exist, with the numbers that decide the pick in view. botrail still does not choose: :func:search returns candidates, and :meth:Product.identify writes the one you picked onto the cell.

cands = bt.catalog.search("gripper.parallel", stroke_mm=150, payload_kg=2.3)
cands[0].identify(scene, "ur5e/tool")           # set_part with the catalog id and its specs
bt.catalog.search_for(scene.requirements()["eye"])   # straight from a requirement row

Spec keys are the requirement vocabulary of :mod:botrail.select — the catalog's specs / mechanical / electrical numbers, read through the same aliases. A product that does not state a filtered key does not match (unknown is not a pass). Results are ordered by validation level, then by closeness to the requested minimums, then by id — the same query gives the same list.

The index is fetched with huggingface_hub (pip install botrail[catalog]) and pinned to a dataset commit; a copy already in the Hugging Face cache is used when the hub cannot be reached, and index(path=...) / BOTRAIL_CATALOG_INDEX read a local file (a builder's dist/index.json).

ALIASES module-attribute

ALIASES = {
    "payload_kg": ("payload_kg",),
    "reach_mm": ("reach_mm",),
    "stroke_mm": ("stroke_mm", "opening_mm"),
    "aperture_mm": ("aperture_mm",),
    "grip_force_n": (
        "grip_force_max_n",
        "grip_force_min_n",
    ),
    "sensing_range_mm": (
        "sensing_range_mm",
        "range_mm",
        "max_range_mm",
    ),
    "fov_deg": ("fov_h_deg", "hfov_deg", "fov_deg"),
    "resolution_h_px": ("resolution_h_px",),
    "resolution_v_px": ("resolution_v_px",),
    "max_range_mm": ("max_range_mm",),
    "min_range_mm": ("min_range_mm",),
    "scan_fov_deg": ("scan_fov_deg",),
    "range_mm": (
        "range_mm",
        "max_range_mm",
        "sensing_range_mm",
    ),
    "protective_height_mm": (
        "protective_height_mm",
        "height_mm",
    ),
    "length_mm": ("length_mm",),
    "width_mm": ("width_mm", "belt_width_mm"),
    "speed_mps": (
        "max_speed_mps",
        "speed_max_mps",
        "speed_mps",
    ),
    "max_speed_mps": (
        "max_speed_mps",
        "speed_max_mps",
        "speed_mps",
    ),
    "max_climb_mps": ("max_climb_mps",),
    "max_descent_mps": ("max_descent_mps",),
    "flight_time_min": ("flight_time_min",),
    "load_kg": (
        "load_kg",
        "capacity_kg",
        "max_load_kg",
        "payload_kg",
    ),
    "output_a": ("output_a", "current_a"),
    "di": ("di",),
    "do": ("do",),
    "ai": ("ai",),
    "ao": ("ao",),
    "safe_di": ("safe_di",),
    "safe_do": ("safe_do",),
}

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

LEVELS module-attribute

LEVELS = ('V0', 'V1', 'V2', 'V3', 'V4', 'V5')

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

REPO_ID module-attribute

REPO_ID = 'botrail/botrail-catalog'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

REPO_URL module-attribute

REPO_URL = "https://huggingface.co/datasets/botrail/botrail-catalog"

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

Index

The catalog index: every product, and the search over them.

get

get(query: str) -> Product

A product by exact id, or by a unique id whose path segments contain the query's segments in order (universal_robots/ur5e); several revisions of one product resolve to the newest.

search

search(
    category: Optional[str] = None,
    *,
    kind: Optional[str] = None,
    manufacturer: Optional[str] = None,
    level: Optional[str] = None,
    text: Optional[str] = None,
    limit: Optional[int] = None,
    **specs: Any,
) -> list[Product]

Products matching a category (prefix: gripper matches gripper.parallel), a maker, a minimum validation level, a text fragment of id or name, and spec filters: key=value means the product states key >= value; key__max=value means <= value; a string value must equal the product's string spec. Ordered by validation level (best first), then closeness to the minimums (smallest headroom first), then id.

Product

One catalog entry as the index lists it.

catalog_ref property

catalog_ref

What set_part(catalog=...) records: the id and the revision.

distribution class-attribute

distribution = 'public'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

kind class-attribute

kind = 'model'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

level property

level

Validation level as a number (V0 = 0); unknown counts as -1.

attributes

attributes() -> dict[str, float]

Every numeric spec the product states, flattened — what lands on the part when it is identified, and what :func:search filters on.

identify

identify(
    scene,
    target: str,
    *,
    kind: Optional[str] = None,
    qty: int = 1,
    **overrides: Any,
) -> str

Write this product onto a resident: set_part(target, catalog=(id, revision), manufacturer, model, category, attributes). The numeric specs come along, so the requirement check reads them. overrides add or replace attributes (mass_kg=...). Returns what set_part returns (the kind the target resolved to).

text

text(key: str) -> Optional[str]

A string spec (ip_rating, flange_standard, ...), if stated.

value

value(key: str) -> Optional[float]

The number answering a requirement key, through the same aliases the requirement check uses.

index

index(
    *,
    revision: Optional[str] = None,
    path: Union[str, Path, None] = None,
    offline: Optional[bool] = None,
    refresh: bool = False,
) -> Index

The catalog index. path (or BOTRAIL_CATALOG_INDEX) reads a local index.json; otherwise the hub resolves revision (default: the newest commit) and downloads the index pinned to it. When the hub cannot be reached the newest index already in the Hugging Face cache is used — offline=True goes straight to the cache, offline=False never does. Hub lookups are cached per process (refresh=True asks again).

search

search(
    category: Optional[str] = None,
    *,
    index: Union[Index, str, Path, None] = None,
    revision: Optional[str] = None,
    kind: Optional[str] = None,
    manufacturer: Optional[str] = None,
    level: Optional[str] = None,
    text: Optional[str] = None,
    limit: Optional[int] = None,
    **specs: Any,
) -> list[Product]

Products in the catalog that match — see :meth:Index.search. index takes an :class:Index or a path to one; otherwise the published index is used (pinned to revision when given).

bt.catalog.search("gripper.parallel", stroke_mm=150, payload_kg=2.3)
bt.catalog.search("manipulator", reach_mm=900, payload_kg=6, level="V3")
bt.catalog.search(kind="spec", category="structure.fence")

search_for

search_for(
    row,
    *,
    category: Optional[str] = None,
    index: Union[Index, str, Path, None] = None,
    **extra: Any,
) -> list[Product]

Candidates for one requirement row (scene.requirements()["tool"]): its category and every >= requirement become the filters; extra adds or overrides filters (level="V3", ip_rating="IP54").