Requirements and the check (bt.select)¶
What the cell asks of every bill-of-materials line, compared with what the chosen part says — and every static check in one report. botrail derives and compares; it does not choose. See Selecting parts.
req = scene.requirements() # bt.select.requirements(scene)
print(req.to_markdown())
req["ur5e/tool"].minimum # {"payload_kg": 2.3, "stroke_mm": 150.0}
report = scene.check() # bt.select.check(scene)
assert report.ok, report.to_markdown()
select
¶
Requirements derived from the cell, and the selection check.
botrail does not choose parts. It derives what every bill-of-materials line
must be able to do — from the cell the part sits in — compares that with what
the chosen part says it can do, and reports where the two disagree or where
it does not know. Choosing stays with the person, the agent or the vendor;
:mod:botrail.catalog finds the real candidates to choose from.
req = scene.requirements() # one row per BOM line
print(req.to_markdown())
req["tool"].minimum # {"payload_kg": 2.3, "stroke_mm": 150.0}
report = scene.check() # I/O lint + sequences + parts + requirements
assert report.ok, report.to_markdown()
Vocabulary. A requirement names a spec the catalog names too, so a value
read from a catalog package (Robot.from_catalog, bt.parts.*(catalog=...),
bt.catalog.Product.identify) or typed by hand on set_part(...) lands in the
same column. The keys, and the attribute names that answer them
(:data:ALIASES):
| requirement | derived from | answered by |
|---|---|---|
payload_kg |
tool mass + the heaviest part the robot grasps; parts riding a vehicle's deck at start | payload_kg |
reach_mm |
the farthest taught target from the base, plus a margin; the table of a machining centre (or the spindle of a lathe) in the cell, through its opening | reach_mm |
stroke_mm |
the smallest side of the grasped parts (parallel gripper) | stroke_mm, opening_mm |
sensing_range_mm |
a beam sensor's span | sensing_range_mm, range_mm, max_range_mm |
range_mm |
a light curtain's span / an area sensor's half-diagonal | range_mm, max_range_mm, sensing_range_mm |
protective_height_mm |
a light curtain's post height | protective_height_mm, height_mm |
scan_fov_deg |
a lidar's authored sweep angle | scan_fov_deg |
length_mm, width_mm |
a conveyor's zone along and across its belt | length_mm / width_mm, belt_width_mm |
speed_mps |
a conveyor's belt speed, an axis speed | max_speed_mps, speed_max_mps, speed_mps |
max_speed_mps |
a vehicle's travel speed | the same |
max_climb_mps |
an aerial vehicle's climb rate | the same |
max_descent_mps |
an aerial vehicle's descent rate | the same |
flight_time_min |
an aerial vehicle's airborne time per cycle, from the baked timeline (requirements(timeline=tl)) |
the same |
load_kg |
parts on a conveyor / an axis; robots standing on a pedestal | load_kg, capacity_kg, max_load_kg, payload_kg |
di do ai ao safe_di safe_do |
points assigned to an I/O node | the node's declared channels |
Every requirement is a minimum (>=) unless noted. The derivations are
geometric and deterministic — no sizing, no safety evaluation; a value that
cannot be derived (a grasped part without mass_kg) is reported as a note,
never guessed.
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)
CheckReport
¶
Every static check of a cell in one list — what botrail check prints.
Finding
¶
Finding(severity: 'str', code: 'str', message: 'str', target: 'Optional[str]' = None)
Requirement
¶
One thing a BOM line must be able to do, and whether its part can.
basis
class-attribute
¶
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'.
op
class-attribute
¶
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'.
status
class-attribute
¶
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'.
Requirements
¶
What the cell asks of every BOM line — the result of :func:requirements.
Row
¶
check
¶
check(
scene,
*,
sequences: Optional[list[str]] = None,
timeline=None,
) -> CheckReport
Every static check in one report: the I/O lint, each sequence walked
for dangling references, unidentified equipment lines (with what the
cell asks of them) and the requirement comparison. timeline (a baked
cycle) adds the cycle-fact requirements — an aerial vehicle's flight
time. Errors make ok false; botrail check prints exactly this.
requirements
¶
requirements(
scene,
*,
sequences: Optional[list[str]] = None,
margin: float = 0.1,
timeline=None,
) -> Requirements
Derive what every BOM line must be able to do from the cell it is in,
and compare it with what the chosen part says (its catalog specs or the
attributes typed on set_part).
sequences limits the programs whose grasps and I/O points are counted
(default: all). margin is added to the reach and flight-time
requirements (0.1 = 10 %). timeline is an optional baked
simulate_sequences result: cycle facts only it can supply — an aerial
vehicle's airborne time — are derived from it, and left as a note when
it is absent. Nothing is chosen and nothing is sized: a number the cell
cannot supply (a grasped part with no mass_kg) becomes a note, not a
guess.