From e74145f9f3af437d6f3440585a67944a50b6ff11 Mon Sep 17 00:00:00 2001 From: Lea Wedmann Date: Fri, 19 Jun 2026 20:55:14 +0200 Subject: [PATCH 01/68] Forward correct image topics --- .../bitbots_bringup/launch/mujoco_simulation.launch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bitbots_misc/bitbots_bringup/launch/mujoco_simulation.launch.py b/src/bitbots_misc/bitbots_bringup/launch/mujoco_simulation.launch.py index a6a6de664..f05c958a3 100644 --- a/src/bitbots_misc/bitbots_bringup/launch/mujoco_simulation.launch.py +++ b/src/bitbots_misc/bitbots_bringup/launch/mujoco_simulation.launch.py @@ -61,8 +61,8 @@ def generate_domain_bridge_config(robot_domain: int, output_dir: Path) -> Path: sensor_topics = [ ("joint_states", "sensor_msgs/msg/JointState"), ("imu/data", "sensor_msgs/msg/Imu"), - ("camera/image_proc", "sensor_msgs/msg/Image"), - ("camera/camera_info", "sensor_msgs/msg/CameraInfo"), + ("zed/zed_node/rgb/image_rect_color", "sensor_msgs/msg/Image"), + ("zed/zed_node/rgb/camera_info", "sensor_msgs/msg/CameraInfo"), ] for topic_suffix, msg_type in sensor_topics: From 5c21291f665ca09142b119b56043b6d67c533721 Mon Sep 17 00:00:00 2001 From: Lea Wedmann Date: Fri, 19 Jun 2026 20:56:59 +0200 Subject: [PATCH 02/68] Make robots black --- .../bitbots_mujoco_sim/xml/pi_plus.xml | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/bitbots_simulation/bitbots_mujoco_sim/xml/pi_plus.xml b/src/bitbots_simulation/bitbots_mujoco_sim/xml/pi_plus.xml index 7989100c3..19146f6dc 100644 --- a/src/bitbots_simulation/bitbots_mujoco_sim/xml/pi_plus.xml +++ b/src/bitbots_simulation/bitbots_mujoco_sim/xml/pi_plus.xml @@ -78,32 +78,32 @@ - + - + - + - + - + - + - + @@ -114,23 +114,23 @@ - + - + - + - + - + @@ -141,16 +141,16 @@ - + - + - + @@ -159,32 +159,32 @@ - + - + - + - + - + - + @@ -199,32 +199,32 @@ - + - + - + - + - + - + From 6cd3000a4e1bea3a094e6a18c0493ab7c34fe629 Mon Sep 17 00:00:00 2001 From: Lea Wedmann Date: Fri, 19 Jun 2026 23:26:13 +0200 Subject: [PATCH 03/68] Add example script for formation calc --- formation_prototype.py | 450 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 450 insertions(+) create mode 100644 formation_prototype.py diff --git a/formation_prototype.py b/formation_prototype.py new file mode 100644 index 000000000..c7cc1e55b --- /dev/null +++ b/formation_prototype.py @@ -0,0 +1,450 @@ +#!/usr/bin/env python3 +""" +Defensive formation prototype. + +A single pure function `compute_formation(ball, field, n_players, params)` maps a +ball position to positions for every non-... well, *every* role (goalie, defenders, +supporter, striker), and a small matplotlib GUI to click a ball and watch the result. + +Core idea +--------- +Everything keys off two vectors derived from the ball B and our goal centre G: + + to_ball = normalize(B - G) # axis pointing from our goal out to the ball + perp = (-to_ball.y, to_ball.x) # perpendicular to that axis + +Defenders sit ON the axis (at a controlled depth from goal) and spread ALONG perp. +As the ball moves the axis rotates, so the same construction continuously morphs +from a horizontal defensive line (ball far/central) into a goal-line wall beside +the goalie (ball close & frontal). No special-casing -> automatically smooth. + +A short pairwise-repulsion pass at the end enforces a minimum separation; it is +also what shoves the defenders sideways into clean flanking slots when they would +otherwise pile onto the goalie -> the "wall next to the goalie" emerges for free. +""" + +from dataclasses import dataclass, field as dc_field +import numpy as np + + +# --------------------------------------------------------------------------- # +# Config + tunables +# --------------------------------------------------------------------------- # +@dataclass +class Field: + length: float = 9.0 # x extent (own goal at -length/2, opp goal at +length/2) + width: float = 6.0 # y extent + goal_width: float = 2.6 # goal mouth + margin: float = 0.3 # keep field players this far inside the touchlines + + +@dataclass +class Params: + # goalie + d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) + # defenders + alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) + depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back + D_min: float = 0.9 # min defender depth from goal (never tuck behind this) + D_max: float = 3.8 # max defender depth from goal (high-line cap) + dz: float = 0.45 # keep defenders at least this far ahead of the goalie + standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball + gap: float = 1.1 # lateral spacing between adjacent defenders + def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) + # supporter + f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits + supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) + supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) + # striker + kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) + post_margin: float = 0.45 # safety margin inside each goal post for a straight shot + back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side + # separation + min_sep: float = 0.8 # no two robots closer than this + sep_iters: int = 8 + # kick lane: keep teammates out of the corridor in front of the ball + kick_clear: float = 0.7 # half-width of the cleared corridor + kick_range: float = 3.0 # how far in front of the ball the corridor extends + + +# --------------------------------------------------------------------------- # +# Helpers +# --------------------------------------------------------------------------- # +def _normalize(v, fallback=np.array([1.0, 0.0])): + n = np.linalg.norm(v) + return v / n if n > 1e-9 else fallback.copy() + + +def _face(frm, to, fallback=0.0): + """Heading (rad) to look from `frm` toward `to`.""" + d = np.asarray(to) - np.asarray(frm) + return np.arctan2(d[1], d[0]) if np.linalg.norm(d) > 1e-9 else fallback + + +def _smoothstep(x, lo, hi): + """C1 ramp from 0 (x<=lo) to 1 (x>=hi).""" + if hi <= lo: + return float(x >= hi) + t = np.clip((x - lo) / (hi - lo), 0.0, 1.0) + return t * t * (3 - 2 * t) + + +def _angle_diff(a, b): + """Smallest absolute angle between two headings (rad), in [0, pi].""" + return abs((a - b + np.pi) % (2 * np.pi) - np.pi) + + +def match_assignment(old_poses, new_items, ball, angle_w=0.3): + """Assign physical robots (at `old_poses`) to the new target poses. + + The robot closest to the ball always takes the striker target; the rest are + matched optimally (Hungarian) to minimise total cost = distance + angle_w * + heading difference. Returns a list of (old_pose, new_pose, new_role). + `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). + """ + from scipy.optimize import linear_sum_assignment + + old_poses = [np.asarray(p) for p in old_poses] + ball = np.asarray(ball) + n = len(old_poses) + + # striker target -> the old robot nearest the ball + s_j = next(j for j, (r, _) in enumerate(new_items) if r == "striker") + s_i = min(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) + pairs = [(old_poses[s_i], new_items[s_j][1], new_items[s_j][0])] + + rem_i = [i for i in range(n) if i != s_i] + rem_j = [j for j in range(len(new_items)) if j != s_j] + if rem_i: + cost = np.empty((len(rem_i), len(rem_j))) + for a, i in enumerate(rem_i): + for b, j in enumerate(rem_j): + op, npose = old_poses[i], new_items[j][1] + cost[a, b] = (np.linalg.norm(op[:2] - npose[:2]) + + angle_w * _angle_diff(op[2], npose[2])) + ri, ci = linear_sum_assignment(cost) + for a, b in zip(ri, ci): + i, j = rem_i[a], rem_j[b] + pairs.append((old_poses[i], new_items[j][1], new_items[j][0])) + return pairs + + +def _clamp_field(p, fld, margin=None): + """Clamp a point to the playable rectangle (continuous / C0).""" + m = fld.margin if margin is None else margin + return np.array([ + np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), + np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), + ]) + + +def _allocate_roles(n, ball=None, field=None): + """Keep-priority as the count drops: striker > goalie > 1st defender > supporter + > 2nd defender (and any further players are extra defenders). + + Equivalently, removing players one at a time drops: a defender, then the + supporter, then the other defender, then the goalie. + + Short-handed (n < 5) with the ball in our own defensive third, the supporter + is reassigned as an extra defender (note: this is a discrete role switch). + """ + n_def = 0 + has_support = False + if n >= 3: + n_def += 1 # first defender + if n >= 4: + has_support = True # supporter + n_def += max(n - 4, 0) # everyone past 4 is another defender + + if has_support and n < 5 and ball is not None and field is not None: + own_third = -field.length / 2 + field.length / 3.0 + if ball[0] < own_third: + has_support, n_def = False, n_def + 1 + + roles = [] + if n >= 1: + roles.append("striker") + if n >= 2: + roles.append("goalie") + roles += [f"defender_{i}" for i in range(n_def)] + if has_support: + roles.append("supporter") + return roles + + +# --------------------------------------------------------------------------- # +# The pure function +# --------------------------------------------------------------------------- # +def compute_formation(ball, field: Field, n_players: int, params: Params): + """Map a ball position -> {role_name: np.array([x, y])}. Pure & deterministic.""" + B = np.asarray(ball, dtype=float) + G = np.array([-field.length / 2.0, 0.0]) + opp = np.array([+field.length / 2.0, 0.0]) + + d = np.linalg.norm(B - G) + to_ball = _normalize(B - G) # our-goal -> ball + perp = np.array([-to_ball[1], to_ball[0]]) + + roles = _allocate_roles(n_players, B, field) + out = {} + head = {} # role -> heading (rad); filled lazily, completed after separation + kick_aim = None # striker's kick direction; used to clear the kick lane + + # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # + if "striker" in roles: + h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth + # aim at the goal, target clamped into the safe mouth: this gives a straight + # (+x) shot whenever the ball is aligned within the posts, angled otherwise + target = np.array([opp[0], np.clip(B[1], -h, h)]) + aim_goal = _normalize(target - B) + # fallback: play back toward our side (field centre) + aim_back = _normalize(np.array([0.0, 0.0]) - B, fallback=np.array([-1.0, 0.0])) + # blend to back-pass only when close to the opp goal AND not aligned + near_goal = _smoothstep(B[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) + not_aligned = _smoothstep(abs(B[1]), h, h + 1.0) + w_back = near_goal * not_aligned + # rotate the aim around the ball at constant angular rate (shortest path) so + # the striker swings smoothly rather than whipping when the two aims oppose + a0 = np.arctan2(aim_goal[1], aim_goal[0]) + a1 = np.arctan2(aim_back[1], aim_back[0]) + da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn + ang = a0 + w_back * da + aim = np.array([np.cos(ang), np.sin(ang)]) + out["striker"] = B - params.kick_offset * aim + head["striker"] = ang # striker faces where it kicks + kick_aim = aim + + # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # + if "goalie" in roles: + g = G + params.d_g * to_ball + g = np.array([ + np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), + np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), + ]) + out["goalie"] = g + + # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # + defender_roles = [r for r in roles if r.startswith("defender_")] + m = len(defender_roles) + if m > 0: + D = np.clip(params.alpha * d + params.depth_bias, # push up + fwd/back bias + params.D_min, params.D_max) + D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball + D = max(D, params.d_g + params.dz) # stay ahead of the goalie + anchor = G + D * to_ball + if m == 1: + # a single defender: shade to the centre side so it doesn't sit on the + # striker<->goalie line (otherwise all three are collinear) + side_dir = -1.0 if B[1] >= 0 else 1.0 + offsets = [params.def_side * side_dir] + else: + offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] + for r, off in zip(defender_roles, offsets): + out[r] = _clamp_field(anchor + off * perp, field) + + # --- supporter: slightly in front of the ball, kept inside the field -------- # + if "supporter" in roles: + # always sit to the centre side of the ball; hard swap so it is never + # directly in front of the striker, even when the ball is on the centre line + side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) + sup = B + np.array([params.f, params.supp_side * side_dir]) + sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner + out["supporter"] = _clamp_field(sup, field) + + # --- min-separation repulsion + kick-lane clearance ----------------------- # + _separate(out, field, params, B, kick_aim) + + # --- orientations (computed from the final positions) --------------------- # + for role, p in out.items(): + if role in head: + continue # striker already set (faces its kick aim) + if role == "supporter": + # face the bisector of (toward ball, toward opp goal): "watch both" + bis = _normalize(B - p) + _normalize(opp - p) + head[role] = _face(np.zeros(2), bis, fallback=_face(p, opp)) + else: + head[role] = _face(p, B) # goalie + defenders face the ball + + return {role: np.array([p[0], p[1], head[role]]) for role, p in out.items()} + + +def _separate(positions: dict, field: Field, params: Params, ball=None, aim=None): + """In-place relaxation: pairwise min-sep + clearing the striker's kick lane. + + Only the striker is a fixed anchor (it must reach the ball); everyone else, + goalie included, gives way around it. In normal play the goalie is far from + all teammates so it never moves; it only shifts off its line in the degenerate + case where the ball sits right in the goal mouth. Continuous in the inputs, + so small ball moves -> small position moves. + + If `ball`/`aim` are given, teammates inside the corridor in front of the ball + (along the kick direction) are pushed sideways out of it so they don't block + the kick; the push tapers in/out along the corridor to stay smooth. + """ + fixed = {"striker"} + names = list(positions.keys()) + sep = params.min_sep + # model the kick corridor as a row of fixed repulsors along the aim, each with + # keep-out radius kick_clear: radial pushes are smooth (no side-flip teleport) + lane_pts, perp = [], None + if aim is not None and ball is not None: + perp = np.array([-aim[1], aim[0]]) + step = max(params.kick_clear * 0.7, 0.3) + lane_pts = [np.asarray(ball) + s * aim + for s in np.arange(step, params.kick_range + 1e-9, step)] + for _ in range(params.sep_iters): + disp = {n: np.zeros(2) for n in names} + for i in range(len(names)): + for j in range(i + 1, len(names)): + a, b = names[i], names[j] + diff = positions[a] - positions[b] + dist = np.linalg.norm(diff) + if dist < sep: + dirv = _normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 \ + else np.array([0.0, 1.0]) + overlap = sep - dist + a_fixed, b_fixed = a in fixed, b in fixed + if a_fixed and b_fixed: + continue + if a_fixed: + disp[b] -= overlap * dirv + elif b_fixed: + disp[a] += overlap * dirv + else: + disp[a] += 0.5 * overlap * dirv + disp[b] -= 0.5 * overlap * dirv + # push teammates out of the kick corridor in front of the ball + for n in names: + if n in fixed: + continue + for lp in lane_pts: + diff = positions[n] - lp + dist = np.linalg.norm(diff) + if dist < params.kick_clear: + dirv = _normalize(diff, perp) # exactly on the line -> step sideways + disp[n] += (params.kick_clear - dist) * dirv + for n in names: + if n in fixed: + continue + positions[n] = _clamp_field(positions[n] + disp[n], field) + + +# --------------------------------------------------------------------------- # +# GUI +# --------------------------------------------------------------------------- # +def run_gui(): + import matplotlib + import matplotlib.pyplot as plt + from matplotlib.widgets import Slider + from matplotlib.patches import Rectangle, Circle + + fld = Field() + params = Params() + state = {"ball": np.array([1.0, 0.5]), "n": 5, "prev": None} + + colors = {"goalie": "#e6b800", "striker": "#d62728", "supporter": "#2ca02c"} + + fig, ax = plt.subplots(figsize=(9, 9)) + plt.subplots_adjust(left=0.08, right=0.97, top=0.98, bottom=0.50) + + # sliders (stacked bottom -> top) + def _ax(b): return plt.axes([0.18, b, 0.72, 0.015]) + s_n = Slider(_ax(0.470), "players", 1, 8, valinit=state["n"], valstep=1) + s_sep = Slider(_ax(0.435), "min_sep", 0.3, 2.0, valinit=params.min_sep) + s_alpha = Slider(_ax(0.400), "push α", 0.1, 0.8, valinit=params.alpha) + s_dbias = Slider(_ax(0.365), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) + s_dside = Slider(_ax(0.330), "def side", 0.0, 2.0, valinit=params.def_side) + s_gap = Slider(_ax(0.295), "def gap", 0.5, 2.0, valinit=params.gap) + s_f = Slider(_ax(0.260), "supp lead", 0.0, 3.0, valinit=params.f) + s_side = Slider(_ax(0.225), "supp side", 0.0, 2.5, valinit=params.supp_side) + s_smax = Slider(_ax(0.190), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) + s_pmarg = Slider(_ax(0.155), "post margin", 0.0, 1.3, valinit=params.post_margin) + s_back = Slider(_ax(0.120), "back dist", 0.0, 3.0, valinit=params.back_dist) + s_kclr = Slider(_ax(0.085), "kick clear", 0.0, 1.5, valinit=params.kick_clear) + s_gout = Slider(_ax(0.050), "goalie out", 0.2, 2.0, valinit=params.d_g) + + def draw(): + ax.clear() + # pitch + ax.add_patch(Rectangle((-fld.length / 2, -fld.width / 2), fld.length, fld.width, + fill=False, color="white", lw=2)) + ax.axvline(0, color="white", lw=1) + ax.add_patch(Circle((0, 0), 0.75, fill=False, color="white", lw=1)) + for sgn in (-1, 1): # goals + ax.plot([sgn * fld.length / 2] * 2, + [-fld.goal_width / 2, fld.goal_width / 2], + color="#4da6ff" if sgn < 0 else "#ff9999", lw=6) + ax.set_facecolor("#2e7d32") + + params.min_sep, params.alpha, params.gap, params.f = \ + s_sep.val, s_alpha.val, s_gap.val, s_f.val + params.depth_bias, params.supp_side, params.d_g = \ + s_dbias.val, s_side.val, s_gout.val + params.supp_max_x, params.def_side = s_smax.val, s_dside.val + params.post_margin, params.back_dist = s_pmarg.val, s_back.val + params.kick_clear = s_kclr.val + n = int(s_n.val) + + form = compute_formation(state["ball"], fld, n, params) + new_items = list(form.items()) + + # match the previous assignment to the new targets and draw the transition + prev = state["prev"] + if prev is not None and len(prev) == len(new_items): + for old_pose, new_pose, role in match_assignment(prev, new_items, state["ball"]): + c = colors.get(role.split("_")[0], "#1f77b4") + ax.plot([old_pose[0], new_pose[0]], [old_pose[1], new_pose[1]], + ls=":", color=c, lw=1.5, zorder=3) + ax.add_patch(Circle(old_pose[:2], 0.10, color=c, alpha=0.55, zorder=4)) + # this assignment becomes the "previous" for the next click + state["prev"] = [pose for _role, pose in new_items] + + # ball + ax.add_patch(Circle(state["ball"], 0.12, color="white", ec="black", zorder=5)) + # striker kick-aim arrow (the striker faces this way) + cleared corridor + if "striker" in form: + th = form["striker"][2] + aim = np.array([np.cos(th), np.sin(th)]) + perp = np.array([-aim[1], aim[0]]) + b = np.asarray(state["ball"]) + far = b + params.kick_range * aim + corner = perp * params.kick_clear + lane = np.array([b + corner, far + corner, far - corner, b - corner]) + ax.add_patch(plt.Polygon(lane, closed=True, color="white", alpha=0.10, zorder=1)) + ax.arrow(*state["ball"], *(1.4 * aim), color="white", width=0.02, + head_width=0.18, length_includes_head=True, zorder=8, alpha=0.9) + # robots (pose = [x, y, heading]) + for role, pose in form.items(): + p, th = pose[:2], pose[2] + base = role.split("_")[0] + c = colors.get(base, "#1f77b4") # defenders blue + ax.add_patch(Circle(p, params.min_sep / 2, color=c, alpha=0.18, zorder=2)) + ax.add_patch(Circle(p, 0.16, color=c, ec="black", zorder=6)) + # heading indicator + ax.plot([p[0], p[0] + 0.45 * np.cos(th)], [p[1], p[1] + 0.45 * np.sin(th)], + color="black", lw=2.5, zorder=7, solid_capstyle="round") + ax.annotate(role.replace("defender_", "D").replace("supporter", "supp"), + p, color="white", fontsize=8, ha="center", va="center", zorder=8) + + ax.set_xlim(-fld.length / 2 - 0.5, fld.length / 2 + 0.5) + ax.set_ylim(-fld.width / 2 - 0.5, fld.width / 2 + 0.5) + ax.set_aspect("equal") + ax.set_title("click to move the ball · dots = previous assignment (dotted = who moves where)", + color="black") + fig.canvas.draw_idle() + + def on_click(event): + if event.inaxes is ax and event.xdata is not None: + state["ball"] = np.array([event.xdata, event.ydata]) + draw() + + for s in (s_n, s_sep, s_alpha, s_dbias, s_dside, s_gap, s_f, s_side, s_smax, + s_pmarg, s_back, s_kclr, s_gout): + s.on_changed(lambda _v: draw()) + fig.canvas.mpl_connect("button_press_event", on_click) + draw() + plt.show() + + +if __name__ == "__main__": + run_gui() From 1ced7f658f61300dd7a2ac6b2fc5d00b1b85d33d Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sun, 21 Jun 2026 16:13:04 +0200 Subject: [PATCH 04/68] basic creation of positioning_capsule --- .../capsules/positioning_capsule.py | 344 ++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py new file mode 100644 index 000000000..08d682f89 --- /dev/null +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -0,0 +1,344 @@ +from dataclasses import dataclass, field as dc_field +from bitbots_utils.utils import get_parameters_from_other_node +import numpy as np + +from bitbots_blackboard.capsules import AbstractBlackboardCapsule + +class AnimationCapsule(AbstractBlackboardCapsule): + """Decides and communicates the optial positions, based on the game situation.""" + def __init__(self, node, blackboard): + super().__init__(node, blackboard) + + """ + A single pure function `compute_formation(ball, field, n_players, params)` maps a + ball position to positions for every non-... well, *every* role (goalie, defenders, + supporter, striker), and a small matplotlib GUI to click a ball and watch the result. + + Core idea + --------- + Everything keys off two vectors derived from the ball B and our goal centre G: + + to_ball = normalize(B - G) # axis pointing from our goal out to the ball + perp = (-to_ball.y, to_ball.x) # perpendicular to that axis + + Defenders sit ON the axis (at a controlled depth from goal) and spread ALONG perp. + As the ball moves the axis rotates, so the same construction continuously morphs + from a horizontal defensive line (ball far/central) into a goal-line wall beside + the goalie (ball close & frontal). No special-casing -> automatically smooth. + + A short pairwise-repulsion pass at the end enforces a minimum separation; it is + also what shoves the defenders sideways into clean flanking slots when they would + otherwise pile onto the goalie -> the "wall next to the goalie" emerges for free. + """ + + + # --------------------------------------------------------------------------- # + # Config + tunables + # --------------------------------------------------------------------------- # + parameters = get_parameters_from_other_node( + self._node, + "/parameter_blackboard", + [ + "field.goal.width", + "field.markings.penalty_area.size.x", + "field.size.x", + "field.size.y", + ], + ) + + @dataclass + class Field: + length: float = parameters["field.size.x"] # x extent (own goal at -length/2, opp goal at +length/2) + width: float = parameters["field.size.y"] # y extent + goal_width: float = parameters["field.goal.width"] # goal mouth + margin: float = 0.3 # keep field players this far inside the touchlines + + + @dataclass + class Params: + # goalie + d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) + # defenders + alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) + depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back + D_min: float = 0.9 # min defender depth from goal (never tuck behind this) + D_max: float = 3.8 # max defender depth from goal (high-line cap) + dz: float = 0.45 # keep defenders at least this far ahead of the goalie + standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball + gap: float = 1.1 # lateral spacing between adjacent defenders + def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) + # supporter + f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits + supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) + supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) + # striker + kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) + post_margin: float = 0.45 # safety margin inside each goal post for a straight shot + back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side + # separation + min_sep: float = 0.8 # no two robots closer than this + sep_iters: int = 8 + # kick lane: keep teammates out of the corridor in front of the ball + kick_clear: float = 0.7 # half-width of the cleared corridor + kick_range: float = 3.0 # how far in front of the ball the corridor extends + + + # --------------------------------------------------------------------------- # + # Helpers + # --------------------------------------------------------------------------- # + def _normalize(v, fallback=np.array([1.0, 0.0])): + n = np.linalg.norm(v) + return v / n if n > 1e-9 else fallback.copy() + + + def _face(frm, to, fallback=0.0): + """Heading (rad) to look from `frm` toward `to`.""" + d = np.asarray(to) - np.asarray(frm) + return np.arctan2(d[1], d[0]) if np.linalg.norm(d) > 1e-9 else fallback + + + def _smoothstep(x, lo, hi): + """C1 ramp from 0 (x<=lo) to 1 (x>=hi).""" + if hi <= lo: + return float(x >= hi) + t = np.clip((x - lo) / (hi - lo), 0.0, 1.0) + return t * t * (3 - 2 * t) + + + def _angle_diff(a, b): + """Smallest absolute angle between two headings (rad), in [0, pi].""" + return abs((a - b + np.pi) % (2 * np.pi) - np.pi) + + def match_assignment(old_poses, new_items, ball, angle_w=0.3): + """Assign physical robots (at `old_poses`) to the new target poses. + + The robot closest to the ball always takes the striker target; the rest are + matched optimally (Hungarian) to minimise total cost = distance + angle_w * + heading difference. Returns a list of (old_pose, new_pose, new_role). + `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). + """ + from scipy.optimize import linear_sum_assignment + + old_poses = [np.asarray(p) for p in old_poses] + ball = np.asarray(ball) + n = len(old_poses) + + # striker target -> the old robot nearest the ball + s_j = next(j for j, (r, _) in enumerate(new_items) if r == "striker") + s_i = min(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) + pairs = [(old_poses[s_i], new_items[s_j][1], new_items[s_j][0])] + + rem_i = [i for i in range(n) if i != s_i] + rem_j = [j for j in range(len(new_items)) if j != s_j] + if rem_i: + cost = np.empty((len(rem_i), len(rem_j))) + for a, i in enumerate(rem_i): + for b, j in enumerate(rem_j): + op, npose = old_poses[i], new_items[j][1] + cost[a, b] = (np.linalg.norm(op[:2] - npose[:2]) + + angle_w * _angle_diff(op[2], npose[2])) + ri, ci = linear_sum_assignment(cost) + for a, b in zip(ri, ci): + i, j = rem_i[a], rem_j[b] + pairs.append((old_poses[i], new_items[j][1], new_items[j][0])) + return pairs + + + def _clamp_field(p, fld, margin=None): + """Clamp a point to the playable rectangle (continuous / C0).""" + m = fld.margin if margin is None else margin + return np.array([ + np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), + np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), + ]) + + + def _allocate_roles(n, ball=None, field=None): + """Keep-priority as the count drops: striker > goalie > 1st defender > supporter + > 2nd defender (and any further players are extra defenders). + + Equivalently, removing players one at a time drops: a defender, then the + supporter, then the other defender, then the goalie. + + Short-handed (n < 5) with the ball in our own defensive third, the supporter + is reassigned as an extra defender (note: this is a discrete role switch). + """ + n_def = 0 + has_support = False + if n >= 3: + n_def += 1 # first defender + if n >= 4: + has_support = True # supporter + n_def += max(n - 4, 0) # everyone past 4 is another defender + + if has_support and n < 5 and ball is not None and field is not None: + own_third = -field.length / 2 + field.length / 3.0 + if ball[0] < own_third: + has_support, n_def = False, n_def + 1 + + roles = [] + if n >= 1: + roles.append("striker") + if n >= 2: + roles.append("goalie") + roles += [f"defender_{i}" for i in range(n_def)] + if has_support: + roles.append("supporter") + return roles + + + # --------------------------------------------------------------------------- # + # The pure function + # --------------------------------------------------------------------------- # + def compute_formation(ball, field: Field, n_players: int, params: Params): + """Map a ball position -> {role_name: np.array([x, y])}. Pure & deterministic.""" + B = np.asarray(ball, dtype=float) + G = np.array([-field.length / 2.0, 0.0]) + opp = np.array([+field.length / 2.0, 0.0]) + + d = np.linalg.norm(B - G) + to_ball = _normalize(B - G) # our-goal -> ball + perp = np.array([-to_ball[1], to_ball[0]]) + + roles = _allocate_roles(n_players, B, field) + out = {} + head = {} # role -> heading (rad); filled lazily, completed after separation + kick_aim = None # striker's kick direction; used to clear the kick lane + + # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # + if "striker" in roles: + h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth + # aim at the goal, target clamped into the safe mouth: this gives a straight + # (+x) shot whenever the ball is aligned within the posts, angled otherwise + target = np.array([opp[0], np.clip(B[1], -h, h)]) + aim_goal = _normalize(target - B) + # fallback: play back toward our side (field centre) + aim_back = _normalize(np.array([0.0, 0.0]) - B, fallback=np.array([-1.0, 0.0])) + # blend to back-pass only when close to the opp goal AND not aligned + near_goal = _smoothstep(B[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) + not_aligned = _smoothstep(abs(B[1]), h, h + 1.0) + w_back = near_goal * not_aligned + # rotate the aim around the ball at constant angular rate (shortest path) so + # the striker swings smoothly rather than whipping when the two aims oppose + a0 = np.arctan2(aim_goal[1], aim_goal[0]) + a1 = np.arctan2(aim_back[1], aim_back[0]) + da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn + ang = a0 + w_back * da + aim = np.array([np.cos(ang), np.sin(ang)]) + out["striker"] = B - params.kick_offset * aim + head["striker"] = ang # striker faces where it kicks + kick_aim = aim + + # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # + if "goalie" in roles: + g = G + params.d_g * to_ball + g = np.array([ + np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), + np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), + ]) + out["goalie"] = g + + # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # + defender_roles = [r for r in roles if r.startswith("defender_")] + m = len(defender_roles) + if m > 0: + D = np.clip(params.alpha * d + params.depth_bias, # push up + fwd/back bias + params.D_min, params.D_max) + D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball + D = max(D, params.d_g + params.dz) # stay ahead of the goalie + anchor = G + D * to_ball + if m == 1: + # a single defender: shade to the centre side so it doesn't sit on the + # striker<->goalie line (otherwise all three are collinear) + side_dir = -1.0 if B[1] >= 0 else 1.0 + offsets = [params.def_side * side_dir] + else: + offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] + for r, off in zip(defender_roles, offsets): + out[r] = _clamp_field(anchor + off * perp, field) + + # --- supporter: slightly in front of the ball, kept inside the field -------- # + if "supporter" in roles: + # always sit to the centre side of the ball; hard swap so it is never + # directly in front of the striker, even when the ball is on the centre line + side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) + sup = B + np.array([params.f, params.supp_side * side_dir]) + sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner + out["supporter"] = _clamp_field(sup, field) + + # --- min-separation repulsion + kick-lane clearance ----------------------- # + _separate(out, field, params, B, kick_aim) + + # --- orientations (computed from the final positions) --------------------- # + for role, p in out.items(): + if role in head: + continue # striker already set (faces its kick aim) + if role == "supporter": + # face the bisector of (toward ball, toward opp goal): "watch both" + bis = _normalize(B - p) + _normalize(opp - p) + head[role] = _face(np.zeros(2), bis, fallback=_face(p, opp)) + else: + head[role] = _face(p, B) # goalie + defenders face the ball + + return {role: np.array([p[0], p[1], head[role]]) for role, p in out.items()} + + + def _separate(positions: dict, field: Field, params: Params, ball=None, aim=None): + """In-place relaxation: pairwise min-sep + clearing the striker's kick lane. + + Only the striker is a fixed anchor (it must reach the ball); everyone else, + goalie included, gives way around it. In normal play the goalie is far from + all teammates so it never moves; it only shifts off its line in the degenerate + case where the ball sits right in the goal mouth. Continuous in the inputs, + so small ball moves -> small position moves. + + If `ball`/`aim` are given, teammates inside the corridor in front of the ball + (along the kick direction) are pushed sideways out of it so they don't block + the kick; the push tapers in/out along the corridor to stay smooth. + """ + fixed = {"striker"} + names = list(positions.keys()) + sep = params.min_sep + # model the kick corridor as a row of fixed repulsors along the aim, each with + # keep-out radius kick_clear: radial pushes are smooth (no side-flip teleport) + lane_pts, perp = [], None + if aim is not None and ball is not None: + perp = np.array([-aim[1], aim[0]]) + step = max(params.kick_clear * 0.7, 0.3) + lane_pts = [np.asarray(ball) + s * aim + for s in np.arange(step, params.kick_range + 1e-9, step)] + for _ in range(params.sep_iters): + disp = {n: np.zeros(2) for n in names} + for i in range(len(names)): + for j in range(i + 1, len(names)): + a, b = names[i], names[j] + diff = positions[a] - positions[b] + dist = np.linalg.norm(diff) + if dist < sep: + dirv = _normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 \ + else np.array([0.0, 1.0]) + overlap = sep - dist + a_fixed, b_fixed = a in fixed, b in fixed + if a_fixed and b_fixed: + continue + if a_fixed: + disp[b] -= overlap * dirv + elif b_fixed: + disp[a] += overlap * dirv + else: + disp[a] += 0.5 * overlap * dirv + disp[b] -= 0.5 * overlap * dirv + # push teammates out of the kick corridor in front of the ball + for n in names: + if n in fixed: + continue + for lp in lane_pts: + diff = positions[n] - lp + dist = np.linalg.norm(diff) + if dist < params.kick_clear: + dirv = _normalize(diff, perp) # exactly on the line -> step sideways + disp[n] += (params.kick_clear - dist) * dirv + for n in names: + if n in fixed: + continue + positions[n] = _clamp_field(positions[n] + disp[n], field) From 61bf6e781c8ee334795ddad83a74378135c0ae7b Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sun, 21 Jun 2026 19:19:14 +0200 Subject: [PATCH 05/68] connect positioning capsule with behaviour (example for defender) --- .../bitbots_blackboard/body_blackboard.py | 3 + .../capsules/game_status_capsule.py | 3 + .../capsules/positioning_capsule.py | 709 +++++++++--------- .../capsules/team_data_capsule.py | 15 + .../actions/go_to_defense_position.py | 9 +- .../behavior_dsd/decisions/closest_to_ball.py | 28 +- .../behavior_dsd/main.dsd | 24 +- 7 files changed, 427 insertions(+), 364 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/body_blackboard.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/body_blackboard.py index d7c636104..85490092d 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/body_blackboard.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/body_blackboard.py @@ -10,6 +10,7 @@ from bitbots_blackboard.capsules.pathfinding_capsule import PathfindingCapsule from bitbots_blackboard.capsules.team_data_capsule import TeamDataCapsule from bitbots_blackboard.capsules.world_model_capsule import WorldModelCapsule +from bitbots_blackboard.capsules.positioning_capsule import PositioningCapsule class BodyBlackboard: @@ -34,6 +35,7 @@ def __init__(self, node: Node, tf_buffer: tf2.BufferInterface): self.costmap = CostmapCapsule(self.node, self) self.pathfinding = PathfindingCapsule(self.node, self) self.team_data = TeamDataCapsule(self.node, self) + self.positioning = PositioningCapsule(self.node, self) self.capsules = [ self.misc, @@ -44,6 +46,7 @@ def __init__(self, node: Node, tf_buffer: tf2.BufferInterface): self.costmap, self.pathfinding, self.team_data, + self.positioning, ] def clear_cache(self): diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py index 6e1abba8d..01a304172 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py @@ -97,6 +97,9 @@ def received_gamestate(self) -> bool: def get_team_id(self) -> int: return self.team_id + + def get_own_id(self) -> int: + return self.own_id def gamestate_callback(self, gamestate_msg: GameState) -> None: if self.gamestate.penalized and not gamestate_msg.penalized: diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 08d682f89..5ee972961 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -1,344 +1,385 @@ -from dataclasses import dataclass, field as dc_field +from dataclasses import dataclass from bitbots_utils.utils import get_parameters_from_other_node import numpy as np -from bitbots_blackboard.capsules import AbstractBlackboardCapsule +from bitbots_blackboard.capsules import AbstractBlackboardCapsule, cached_capsule_function + + +@dataclass +class Field: + """Field geometry. Populated from the parameter blackboard in __init__.""" + length: float = 9.0 # x extent (own goal at -length/2, opp goal at +length/2) + width: float = 6.0 # y extent + goal_width: float = 1.5 # goal mouth + margin: float = 0.3 # keep field players this far inside the touchlines + + +@dataclass +class Params: + """ + A single pure function `compute_formation(ball, field, n_players, params)` maps a + ball position to positions for every non-... well, *every* role (goalie, defenders, + supporter, striker), and a small matplotlib GUI to click a ball and watch the result. + + Core idea + --------- + Everything keys off two vectors derived from the ball B and our goal centre G: + + to_ball = normalize(B - G) # axis pointing from our goal out to the ball + perp = (-to_ball.y, to_ball.x) # perpendicular to that axis + + Defenders sit ON the axis (at a controlled depth from goal) and spread ALONG perp. + As the ball moves the axis rotates, so the same construction continuously morphs + from a horizontal defensive line (ball far/central) into a goal-line wall beside + the goalie (ball close & frontal). No special-casing -> automatically smooth. + + A short pairwise-repulsion pass at the end enforces a minimum separation; it is + also what shoves the defenders sideways into clean flanking slots when they would + otherwise pile onto the goalie -> the "wall next to the goalie" emerges for free. + """ + # goalie + d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) + # defenders + alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) + depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back + D_min: float = 0.9 # min defender depth from goal (never tuck behind this) + D_max: float = 3.8 # max defender depth from goal (high-line cap) + dz: float = 0.45 # keep defenders at least this far ahead of the goalie + standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball + gap: float = 1.1 # lateral spacing between adjacent defenders + def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) + # supporter + f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits + supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) + supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) + # striker + kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) + post_margin: float = 0.45 # safety margin inside each goal post for a straight shot + back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side + # separation + min_sep: float = 0.8 # no two robots closer than this + sep_iters: int = 8 + # kick lane: keep teammates out of the corridor in front of the ball + kick_clear: float = 0.7 # half-width of the cleared corridor + kick_range: float = 3.0 # how far in front of the ball the corridor extends + + +class PositioningCapsule(AbstractBlackboardCapsule): + """Decides and communicates the optimal positions, based on the game situation.""" + + # --------------------------------------------------------------------------- # + # Config + # --------------------------------------------------------------------------- # -class AnimationCapsule(AbstractBlackboardCapsule): - """Decides and communicates the optial positions, based on the game situation.""" def __init__(self, node, blackboard): super().__init__(node, blackboard) + parameters = get_parameters_from_other_node( + self._node, + "/parameter_blackboard", + [ + "field.goal.width", + "field.markings.penalty_area.size.x", + "field.size.x", + "field.size.y", + ], + ) + + self._field = Field( + length=parameters["field.size.x"], + width=parameters["field.size.y"], + goal_width=parameters["field.goal.width"], + ) + self._params = Params() + + # --------------------------------------------------------------------------- # + # Helpers + # --------------------------------------------------------------------------- # + + @staticmethod + def _normalize(v, fallback=np.array([1.0, 0.0])): + n = np.linalg.norm(v) + return v / n if n > 1e-9 else fallback.copy() + + @staticmethod + def _face(frm, to, fallback=0.0): + """Heading (rad) to look from `frm` toward `to`.""" + d = np.asarray(to) - np.asarray(frm) + return np.arctan2(d[1], d[0]) if np.linalg.norm(d) > 1e-9 else fallback + + @staticmethod + def _smoothstep(x, lo, hi): + """C1 ramp from 0 (x<=lo) to 1 (x>=hi).""" + if hi <= lo: + return float(x >= hi) + t = np.clip((x - lo) / (hi - lo), 0.0, 1.0) + return t * t * (3 - 2 * t) + + @staticmethod + def _angle_diff(a, b): + """Smallest absolute angle between two headings (rad), in [0, pi].""" + return abs((a - b + np.pi) % (2 * np.pi) - np.pi) + + @staticmethod + def _clamp_field(p, fld, margin=None): + """Clamp a point to the playable rectangle (continuous / C0).""" + m = fld.margin if margin is None else margin + return np.array([ + np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), + np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), + ]) + + # --------------------------------------------------------------------------- # + # Role allocation + # --------------------------------------------------------------------------- # + + @staticmethod + def _allocate_roles(n, ball=None, field=None): + """Keep-priority as the count drops: striker > goalie > 1st defender > supporter + > 2nd defender (and any further players are extra defenders). + + Equivalently, removing players one at a time drops: a defender, then the + supporter, then the other defender, then the goalie. + + Short-handed (n < 5) with the ball in our own defensive third, the supporter + is reassigned as an extra defender (note: this is a discrete role switch). """ - A single pure function `compute_formation(ball, field, n_players, params)` maps a - ball position to positions for every non-... well, *every* role (goalie, defenders, - supporter, striker), and a small matplotlib GUI to click a ball and watch the result. - - Core idea - --------- - Everything keys off two vectors derived from the ball B and our goal centre G: - - to_ball = normalize(B - G) # axis pointing from our goal out to the ball - perp = (-to_ball.y, to_ball.x) # perpendicular to that axis - - Defenders sit ON the axis (at a controlled depth from goal) and spread ALONG perp. - As the ball moves the axis rotates, so the same construction continuously morphs - from a horizontal defensive line (ball far/central) into a goal-line wall beside - the goalie (ball close & frontal). No special-casing -> automatically smooth. - - A short pairwise-repulsion pass at the end enforces a minimum separation; it is - also what shoves the defenders sideways into clean flanking slots when they would - otherwise pile onto the goalie -> the "wall next to the goalie" emerges for free. + n_def = 0 + has_support = False + if n >= 3: + n_def += 1 # first defender + if n >= 4: + has_support = True # supporter + n_def += max(n - 4, 0) # everyone past 4 is another defender + + if has_support and n < 5 and ball is not None and field is not None: + own_third = -field.length / 2 + field.length / 3.0 + if ball[0] < own_third: + has_support, n_def = False, n_def + 1 + + roles = [] + if n >= 1: + roles.append("striker") + if n >= 2: + roles.append("goalie") + roles += [f"defender_{i}" for i in range(n_def)] + if has_support: + roles.append("supporter") + return roles + + # --------------------------------------------------------------------------- # + # Separation / kick-lane clearance + # --------------------------------------------------------------------------- # + + def _separate(self, positions: dict, field: Field, params: Params, ball=None, aim=None): + """In-place relaxation: pairwise min-sep + clearing the striker's kick lane. + + Only the striker is a fixed anchor (it must reach the ball); everyone else, + goalie included, gives way around it. In normal play the goalie is far from + all teammates so it never moves; it only shifts off its line in the degenerate + case where the ball sits right in the goal mouth. Continuous in the inputs, + so small ball moves -> small position moves. + + If `ball`/`aim` are given, teammates inside the corridor in front of the ball + (along the kick direction) are pushed sideways out of it so they don't block + the kick; the push tapers in/out along the corridor to stay smooth. """ - - - # --------------------------------------------------------------------------- # - # Config + tunables - # --------------------------------------------------------------------------- # - parameters = get_parameters_from_other_node( - self._node, - "/parameter_blackboard", - [ - "field.goal.width", - "field.markings.penalty_area.size.x", - "field.size.x", - "field.size.y", - ], - ) - - @dataclass - class Field: - length: float = parameters["field.size.x"] # x extent (own goal at -length/2, opp goal at +length/2) - width: float = parameters["field.size.y"] # y extent - goal_width: float = parameters["field.goal.width"] # goal mouth - margin: float = 0.3 # keep field players this far inside the touchlines - - - @dataclass - class Params: - # goalie - d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) - # defenders - alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) - depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back - D_min: float = 0.9 # min defender depth from goal (never tuck behind this) - D_max: float = 3.8 # max defender depth from goal (high-line cap) - dz: float = 0.45 # keep defenders at least this far ahead of the goalie - standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball - gap: float = 1.1 # lateral spacing between adjacent defenders - def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) - # supporter - f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits - supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) - supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) - # striker - kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) - post_margin: float = 0.45 # safety margin inside each goal post for a straight shot - back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side - # separation - min_sep: float = 0.8 # no two robots closer than this - sep_iters: int = 8 - # kick lane: keep teammates out of the corridor in front of the ball - kick_clear: float = 0.7 # half-width of the cleared corridor - kick_range: float = 3.0 # how far in front of the ball the corridor extends - - - # --------------------------------------------------------------------------- # - # Helpers - # --------------------------------------------------------------------------- # - def _normalize(v, fallback=np.array([1.0, 0.0])): - n = np.linalg.norm(v) - return v / n if n > 1e-9 else fallback.copy() - - - def _face(frm, to, fallback=0.0): - """Heading (rad) to look from `frm` toward `to`.""" - d = np.asarray(to) - np.asarray(frm) - return np.arctan2(d[1], d[0]) if np.linalg.norm(d) > 1e-9 else fallback - - - def _smoothstep(x, lo, hi): - """C1 ramp from 0 (x<=lo) to 1 (x>=hi).""" - if hi <= lo: - return float(x >= hi) - t = np.clip((x - lo) / (hi - lo), 0.0, 1.0) - return t * t * (3 - 2 * t) - - - def _angle_diff(a, b): - """Smallest absolute angle between two headings (rad), in [0, pi].""" - return abs((a - b + np.pi) % (2 * np.pi) - np.pi) - - def match_assignment(old_poses, new_items, ball, angle_w=0.3): - """Assign physical robots (at `old_poses`) to the new target poses. - - The robot closest to the ball always takes the striker target; the rest are - matched optimally (Hungarian) to minimise total cost = distance + angle_w * - heading difference. Returns a list of (old_pose, new_pose, new_role). - `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). - """ - from scipy.optimize import linear_sum_assignment - - old_poses = [np.asarray(p) for p in old_poses] - ball = np.asarray(ball) - n = len(old_poses) - - # striker target -> the old robot nearest the ball - s_j = next(j for j, (r, _) in enumerate(new_items) if r == "striker") - s_i = min(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) - pairs = [(old_poses[s_i], new_items[s_j][1], new_items[s_j][0])] - - rem_i = [i for i in range(n) if i != s_i] - rem_j = [j for j in range(len(new_items)) if j != s_j] - if rem_i: - cost = np.empty((len(rem_i), len(rem_j))) - for a, i in enumerate(rem_i): - for b, j in enumerate(rem_j): - op, npose = old_poses[i], new_items[j][1] - cost[a, b] = (np.linalg.norm(op[:2] - npose[:2]) - + angle_w * _angle_diff(op[2], npose[2])) - ri, ci = linear_sum_assignment(cost) - for a, b in zip(ri, ci): - i, j = rem_i[a], rem_j[b] - pairs.append((old_poses[i], new_items[j][1], new_items[j][0])) - return pairs - - - def _clamp_field(p, fld, margin=None): - """Clamp a point to the playable rectangle (continuous / C0).""" - m = fld.margin if margin is None else margin - return np.array([ - np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), - np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), + fixed = {"striker"} + names = list(positions.keys()) + sep = params.min_sep + # model the kick corridor as a row of fixed repulsors along the aim, each with + # keep-out radius kick_clear: radial pushes are smooth (no side-flip teleport) + lane_pts, perp = [], None + if aim is not None and ball is not None: + perp = np.array([-aim[1], aim[0]]) + step = max(params.kick_clear * 0.7, 0.3) + lane_pts = [np.asarray(ball) + s * aim + for s in np.arange(step, params.kick_range + 1e-9, step)] + for _ in range(params.sep_iters): + disp = {n: np.zeros(2) for n in names} + for i in range(len(names)): + for j in range(i + 1, len(names)): + a, b = names[i], names[j] + diff = positions[a] - positions[b] + dist = np.linalg.norm(diff) + if dist < sep: + dirv = self._normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 \ + else np.array([0.0, 1.0]) + overlap = sep - dist + a_fixed, b_fixed = a in fixed, b in fixed + if a_fixed and b_fixed: + continue + if a_fixed: + disp[b] -= overlap * dirv + elif b_fixed: + disp[a] += overlap * dirv + else: + disp[a] += 0.5 * overlap * dirv + disp[b] -= 0.5 * overlap * dirv + # push teammates out of the kick corridor in front of the ball + for n in names: + if n in fixed: + continue + for lp in lane_pts: + diff = positions[n] - lp + dist = np.linalg.norm(diff) + if dist < params.kick_clear: + dirv = self._normalize(diff, perp) # exactly on the line -> step sideways + disp[n] += (params.kick_clear - dist) * dirv + for n in names: + if n in fixed: + continue + positions[n] = self._clamp_field(positions[n] + disp[n], field) + + # --------------------------------------------------------------------------- # + # Assignment + # --------------------------------------------------------------------------- # + + def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): + """Assign physical robots (at `old_poses`) to the new target poses. + + The robot closest to the ball always takes the striker target; the rest are + matched optimally (Hungarian) to minimise total cost = distance + angle_w * + heading difference. Returns a list of (old_pose, new_pose, new_role). + `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). + """ + from scipy.optimize import linear_sum_assignment + + old_poses = [np.asarray(p) for p in old_poses] + ball = np.asarray(ball) + n = len(old_poses) + + # striker target -> the old robot nearest the ball + s_j = next(j for j, (r, _) in enumerate(new_items) if r == "striker") + s_i = min(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) + pairs = [(old_poses[s_i], new_items[s_j][1], new_items[s_j][0])] + + rem_i = [i for i in range(n) if i != s_i] + rem_j = [j for j in range(len(new_items)) if j != s_j] + if rem_i: + cost = np.empty((len(rem_i), len(rem_j))) + for a, i in enumerate(rem_i): + for b, j in enumerate(rem_j): + op, npose = old_poses[i], new_items[j][1] + cost[a, b] = (np.linalg.norm(op[:2] - npose[:2]) + + angle_w * self._angle_diff(op[2], npose[2])) + ri, ci = linear_sum_assignment(cost) + for a, b in zip(ri, ci): + i, j = rem_i[a], rem_j[b] + pairs.append((old_poses[i], new_items[j][1], new_items[j][0])) + return pairs + + # --------------------------------------------------------------------------- # + # Formation computation + # --------------------------------------------------------------------------- # + + def _compute_formation(self, ball, field: Field, n_players: int, params: Params): + """Map a ball position -> {role_name: np.array([x, y, theta])}. Pure & deterministic.""" + B = np.asarray(ball, dtype=float) + G = np.array([-field.length / 2.0, 0.0]) + opp = np.array([+field.length / 2.0, 0.0]) + + d = np.linalg.norm(B - G) + to_ball = self._normalize(B - G) # our-goal -> ball + perp = np.array([-to_ball[1], to_ball[0]]) + + roles = self._allocate_roles(n_players, B, field) + out = {} + head = {} # role -> heading (rad); filled lazily, completed after separation + kick_aim = None # striker's kick direction; used to clear the kick lane + + # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # + if "striker" in roles: + h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth + # aim at the goal, target clamped into the safe mouth: this gives a straight + # (+x) shot whenever the ball is aligned within the posts, angled otherwise + target = np.array([opp[0], np.clip(B[1], -h, h)]) + aim_goal = self._normalize(target - B) + # fallback: play back toward our side (field centre) + aim_back = self._normalize(np.array([0.0, 0.0]) - B, fallback=np.array([-1.0, 0.0])) + # blend to back-pass only when close to the opp goal AND not aligned + near_goal = self._smoothstep(B[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) + not_aligned = self._smoothstep(abs(B[1]), h, h + 1.0) + w_back = near_goal * not_aligned + # rotate the aim around the ball at constant angular rate (shortest path) so + # the striker swings smoothly rather than whipping when the two aims oppose + a0 = np.arctan2(aim_goal[1], aim_goal[0]) + a1 = np.arctan2(aim_back[1], aim_back[0]) + da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn + ang = a0 + w_back * da + aim = np.array([np.cos(ang), np.sin(ang)]) + out["striker"] = B - params.kick_offset * aim + head["striker"] = ang # striker faces where it kicks + kick_aim = aim + + # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # + if "goalie" in roles: + g = G + params.d_g * to_ball + g = np.array([ + np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), + np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), ]) - - - def _allocate_roles(n, ball=None, field=None): - """Keep-priority as the count drops: striker > goalie > 1st defender > supporter - > 2nd defender (and any further players are extra defenders). - - Equivalently, removing players one at a time drops: a defender, then the - supporter, then the other defender, then the goalie. - - Short-handed (n < 5) with the ball in our own defensive third, the supporter - is reassigned as an extra defender (note: this is a discrete role switch). - """ - n_def = 0 - has_support = False - if n >= 3: - n_def += 1 # first defender - if n >= 4: - has_support = True # supporter - n_def += max(n - 4, 0) # everyone past 4 is another defender - - if has_support and n < 5 and ball is not None and field is not None: - own_third = -field.length / 2 + field.length / 3.0 - if ball[0] < own_third: - has_support, n_def = False, n_def + 1 - - roles = [] - if n >= 1: - roles.append("striker") - if n >= 2: - roles.append("goalie") - roles += [f"defender_{i}" for i in range(n_def)] - if has_support: - roles.append("supporter") - return roles - - - # --------------------------------------------------------------------------- # - # The pure function - # --------------------------------------------------------------------------- # - def compute_formation(ball, field: Field, n_players: int, params: Params): - """Map a ball position -> {role_name: np.array([x, y])}. Pure & deterministic.""" - B = np.asarray(ball, dtype=float) - G = np.array([-field.length / 2.0, 0.0]) - opp = np.array([+field.length / 2.0, 0.0]) - - d = np.linalg.norm(B - G) - to_ball = _normalize(B - G) # our-goal -> ball - perp = np.array([-to_ball[1], to_ball[0]]) - - roles = _allocate_roles(n_players, B, field) - out = {} - head = {} # role -> heading (rad); filled lazily, completed after separation - kick_aim = None # striker's kick direction; used to clear the kick lane - - # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # - if "striker" in roles: - h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth - # aim at the goal, target clamped into the safe mouth: this gives a straight - # (+x) shot whenever the ball is aligned within the posts, angled otherwise - target = np.array([opp[0], np.clip(B[1], -h, h)]) - aim_goal = _normalize(target - B) - # fallback: play back toward our side (field centre) - aim_back = _normalize(np.array([0.0, 0.0]) - B, fallback=np.array([-1.0, 0.0])) - # blend to back-pass only when close to the opp goal AND not aligned - near_goal = _smoothstep(B[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) - not_aligned = _smoothstep(abs(B[1]), h, h + 1.0) - w_back = near_goal * not_aligned - # rotate the aim around the ball at constant angular rate (shortest path) so - # the striker swings smoothly rather than whipping when the two aims oppose - a0 = np.arctan2(aim_goal[1], aim_goal[0]) - a1 = np.arctan2(aim_back[1], aim_back[0]) - da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn - ang = a0 + w_back * da - aim = np.array([np.cos(ang), np.sin(ang)]) - out["striker"] = B - params.kick_offset * aim - head["striker"] = ang # striker faces where it kicks - kick_aim = aim - - # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # - if "goalie" in roles: - g = G + params.d_g * to_ball - g = np.array([ - np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), - np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), - ]) - out["goalie"] = g - - # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # - defender_roles = [r for r in roles if r.startswith("defender_")] - m = len(defender_roles) - if m > 0: - D = np.clip(params.alpha * d + params.depth_bias, # push up + fwd/back bias - params.D_min, params.D_max) - D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball - D = max(D, params.d_g + params.dz) # stay ahead of the goalie - anchor = G + D * to_ball - if m == 1: - # a single defender: shade to the centre side so it doesn't sit on the - # striker<->goalie line (otherwise all three are collinear) - side_dir = -1.0 if B[1] >= 0 else 1.0 - offsets = [params.def_side * side_dir] - else: - offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] - for r, off in zip(defender_roles, offsets): - out[r] = _clamp_field(anchor + off * perp, field) - - # --- supporter: slightly in front of the ball, kept inside the field -------- # - if "supporter" in roles: - # always sit to the centre side of the ball; hard swap so it is never - # directly in front of the striker, even when the ball is on the centre line - side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) - sup = B + np.array([params.f, params.supp_side * side_dir]) - sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner - out["supporter"] = _clamp_field(sup, field) - - # --- min-separation repulsion + kick-lane clearance ----------------------- # - _separate(out, field, params, B, kick_aim) - - # --- orientations (computed from the final positions) --------------------- # - for role, p in out.items(): - if role in head: - continue # striker already set (faces its kick aim) - if role == "supporter": - # face the bisector of (toward ball, toward opp goal): "watch both" - bis = _normalize(B - p) + _normalize(opp - p) - head[role] = _face(np.zeros(2), bis, fallback=_face(p, opp)) - else: - head[role] = _face(p, B) # goalie + defenders face the ball - - return {role: np.array([p[0], p[1], head[role]]) for role, p in out.items()} - - - def _separate(positions: dict, field: Field, params: Params, ball=None, aim=None): - """In-place relaxation: pairwise min-sep + clearing the striker's kick lane. - - Only the striker is a fixed anchor (it must reach the ball); everyone else, - goalie included, gives way around it. In normal play the goalie is far from - all teammates so it never moves; it only shifts off its line in the degenerate - case where the ball sits right in the goal mouth. Continuous in the inputs, - so small ball moves -> small position moves. - - If `ball`/`aim` are given, teammates inside the corridor in front of the ball - (along the kick direction) are pushed sideways out of it so they don't block - the kick; the push tapers in/out along the corridor to stay smooth. - """ - fixed = {"striker"} - names = list(positions.keys()) - sep = params.min_sep - # model the kick corridor as a row of fixed repulsors along the aim, each with - # keep-out radius kick_clear: radial pushes are smooth (no side-flip teleport) - lane_pts, perp = [], None - if aim is not None and ball is not None: - perp = np.array([-aim[1], aim[0]]) - step = max(params.kick_clear * 0.7, 0.3) - lane_pts = [np.asarray(ball) + s * aim - for s in np.arange(step, params.kick_range + 1e-9, step)] - for _ in range(params.sep_iters): - disp = {n: np.zeros(2) for n in names} - for i in range(len(names)): - for j in range(i + 1, len(names)): - a, b = names[i], names[j] - diff = positions[a] - positions[b] - dist = np.linalg.norm(diff) - if dist < sep: - dirv = _normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 \ - else np.array([0.0, 1.0]) - overlap = sep - dist - a_fixed, b_fixed = a in fixed, b in fixed - if a_fixed and b_fixed: - continue - if a_fixed: - disp[b] -= overlap * dirv - elif b_fixed: - disp[a] += overlap * dirv - else: - disp[a] += 0.5 * overlap * dirv - disp[b] -= 0.5 * overlap * dirv - # push teammates out of the kick corridor in front of the ball - for n in names: - if n in fixed: - continue - for lp in lane_pts: - diff = positions[n] - lp - dist = np.linalg.norm(diff) - if dist < params.kick_clear: - dirv = _normalize(diff, perp) # exactly on the line -> step sideways - disp[n] += (params.kick_clear - dist) * dirv - for n in names: - if n in fixed: - continue - positions[n] = _clamp_field(positions[n] + disp[n], field) + out["goalie"] = g + + # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # + defender_roles = [r for r in roles if r.startswith("defender_")] + m = len(defender_roles) + if m > 0: + D = np.clip(params.alpha * d + params.depth_bias, # push up + fwd/back bias + params.D_min, params.D_max) + D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball + D = max(D, params.d_g + params.dz) # stay ahead of the goalie + anchor = G + D * to_ball + if m == 1: + # a single defender: shade to the centre side so it doesn't sit on the + # striker<->goalie line (otherwise all three are collinear) + side_dir = -1.0 if B[1] >= 0 else 1.0 + offsets = [params.def_side * side_dir] + else: + offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] + for r, off in zip(defender_roles, offsets): + out[r] = self._clamp_field(anchor + off * perp, field) + + # --- supporter: slightly in front of the ball, kept inside the field -------- # + if "supporter" in roles: + # always sit to the centre side of the ball; hard swap so it is never + # directly in front of the striker, even when the ball is on the centre line + side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) + sup = B + np.array([params.f, params.supp_side * side_dir]) + sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner + out["supporter"] = self._clamp_field(sup, field) + + # --- min-separation repulsion + kick-lane clearance ----------------------- # + self._separate(out, field, params, B, kick_aim) + + # --- orientations (computed from the final positions) --------------------- # + for role, p in out.items(): + if role in head: + continue # striker already set (faces its kick aim) + if role == "supporter": + # face the bisector of (toward ball, toward opp goal): "watch both" + bis = self._normalize(B - p) + self._normalize(opp - p) + head[role] = self._face(np.zeros(2), bis, fallback=self._face(p, opp)) + else: + head[role] = self._face(p, B) # goalie + defenders face the ball + + return {role: np.array([p[0], p[1], head[role]]) for role, p in out.items()} + + @cached_capsule_function + def get_formation_assignment(self) -> dict: + ball = self._blackboard.world_model.get_best_ball_point_stamped() + robot_poses = self._blackboard.team_data.get_robot_poses() + + formation = self._compute_formation(ball, self._field, len(robot_poses), self._params) + new_items = list(formation.items()) + ordered_jerseys = sorted(robot_poses.keys()) + old_poses = [robot_poses[j] for j in ordered_jerseys] + pairs = self._match_assignment(old_poses, new_items, ball) + + result = {} + for jersey, old_pose in zip(ordered_jerseys, [robot_poses[j] for j in ordered_jerseys]): + for ap, new_pose, role in pairs: + if np.allclose(np.asarray(ap), np.asarray(old_pose)): + result[jersey] = {"role": role, "goal_pose": np.asarray(new_pose)} + break + return result diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index c44d479f1..876e74511 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -1,6 +1,7 @@ from typing import Literal, Optional import numpy as np +import math from bitbots_utils.utils import get_parameters_from_other_node from geometry_msgs.msg import PointStamped, Pose from rclpy.duration import Duration @@ -182,6 +183,20 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: if self.is_valid(data) and (data.strategy.role != Strategy.ROLE_GOALIE or count_goalies): poses.append(data.robot_position.pose) return poses + + def quaternion_to_yaw(q) -> float: + """Extract yaw (theta) from a quaternion.""" + return math.atan2(2.0 * (q.w * q.z + q.x * q.y), 1.0 - 2.0 * (q.y * q.y + q.z * q.z)) + + def get_robot_poses(self) -> dict[int, list[float]]: + """Returns a mapping of jersey_number -> [x, y, theta] for all active robots.""" + robot_poses = {} + data: TeamData + for data in self.team_data.values(): + if self.is_valid(data): + pose = data.robot_position.pose + robot_poses[data.robot_id] = [pose.point.x, pose.point.y, self.quaternion_to_yaw(pose.orientation)] + return robot_poses def get_number_of_active_field_players(self, count_goalie: bool = False) -> int: def is_not_goalie(team_data: TeamData) -> bool: diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py index a84743a06..28fcc9d2a 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py @@ -83,8 +83,11 @@ def perform(self, reevaluate=False): pose_msg.pose.orientation = Quaternion(x=x, y=y, z=z, w=w) else: # center point between ball and own goal - pose_msg.pose.position.x = (goal_position[0] + ball_position[0]) / 2 - pose_msg.pose.position.y = ball_position[1] / 2 + self.y_offset - pose_msg.pose.orientation.w = 1.0 + optimal_positioning = self.blackboard.positioning.get_formation_assignment() + own_position = optimal_positioning[self.blackboard.game_status.get_own_id()] + pose = own_position["goal_pose"] + pose_msg.pose.position.x = pose[0] + pose_msg.pose.position.y = pose[1] + pose_msg.pose.orientation.w = pose[2] self.blackboard.pathfinding.publish(pose_msg) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index c3b7766b6..8d7010bd4 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -47,20 +47,26 @@ def __init__(self, blackboard, dsd, parameters): super().__init__(blackboard, dsd, parameters) def perform(self, reevaluate=False): - my_time_to_ball = self.blackboard.team_data.get_own_time_to_ball() - rank = self.blackboard.team_data.team_rank_to_ball(my_time_to_ball, count_goalies=False, use_time_to_ball=True) - self.publish_debug_data("time to ball", my_time_to_ball) - self.publish_debug_data("Rank to ball", rank) - if rank == 1: - return "FIRST" - elif rank == 2: - return "SECOND" - elif rank == 3: - return "THIRD" + optimal_positioning = self.blackboard.positioning.get_formation_assignment() + own_position = optimal_positioning[self.blackboard.game_status.get_own_id()] + role = own_position["role"] + self.publish_debug_data("Role from positioning", role) + if role == "striker": + return "STRIKER" + elif role == "defender_0": + return "DEFENDER0" + elif role == "defender_1": + return "DEFENDER1" + elif role == "defender_2": + return "DEFENDER2" + elif role == "defender_3": + return "DEFENDER3" + elif role == "supporter": + return "SUPPORTER" else: # emergency fall back if something goes wrong self.blackboard.node.get_logger().warning("Rank to ball had some issues") - return "FIRST" + return "STRIKER" def get_reevaluate(self): return True diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 41c63c423..b488781ad 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -62,11 +62,6 @@ $GoalieHandlingBall YES --> @ChangeAction + action:positioning, @AvoidBallActive, @LookAtFieldFeatures, @GoToDefensePosition //quick fix for playing with two robots during GO NO --> #KickWithAvoidance -#DefensePositioning -$GoalieActive - YES --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToBlockPosition - #SupporterRole $PassStarted YES --> $BallSeen @@ -95,9 +90,9 @@ $DoOnce OUR --> #SearchBall ELSE --> @AvoidBallActive, @LookAtFieldFeatures, @WalkInPlace + duration:2, @GoToRelativePosition + x:1 + y:0 + t:0, @Stand YES --> $RankToBallNoGoalie - FIRST --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_first - SECOND --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_second - THIRD --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + STRIKER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_first + DEFENDER0 --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_second + SUPPORTER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition #Init @Stand + duration:0.1 + r:false, @ChangeAction + action:waiting, @LookForward, @Stand @@ -112,14 +107,11 @@ $BallSeen NO_FREEKICK --> #Placing YES --> $ConfigRole GOALIE --> #GoalieBehavior - ELSE --> $CountActiveRobotsWithoutGoalie - ONE --> $RankToBallNoGoalie - FIRST --> #StrikerRole - SECOND --> #DefensePositioning - ELSE --> $RankToBallNoGoalie - FIRST --> #StrikerRole - SECOND --> #SupporterRole - THIRD --> #DefensePositioning + ELSE --> $RankToBallNoGoalie + STRIKER --> #StrikerRole + DEFENDER0 --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition + SUPPORTER --> #SupporterRole + ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition //defender 1 bis 4 integrieren? #PlayingBehavior $SecondaryStateDecider From 4fa2aed7c64f59051768c79d568033bcd23e21a0 Mon Sep 17 00:00:00 2001 From: Clemens Date: Mon, 22 Jun 2026 16:02:08 +0200 Subject: [PATCH 06/68] fix some type errors and run format (now works in simulation for a single robot that plays as striker) --- formation_prototype.py | 204 ++++++++++-------- .../bitbots_blackboard/body_blackboard.py | 2 +- .../capsules/game_status_capsule.py | 2 +- .../capsules/positioning_capsule.py | 115 +++++----- .../capsules/team_data_capsule.py | 6 +- .../behavior_dsd/decisions/closest_to_ball.py | 2 +- 6 files changed, 184 insertions(+), 147 deletions(-) diff --git a/formation_prototype.py b/formation_prototype.py index c7cc1e55b..5c443bc5e 100644 --- a/formation_prototype.py +++ b/formation_prototype.py @@ -23,7 +23,8 @@ otherwise pile onto the goalie -> the "wall next to the goalie" emerges for free. """ -from dataclasses import dataclass, field as dc_field +from dataclasses import dataclass + import numpy as np @@ -32,39 +33,39 @@ # --------------------------------------------------------------------------- # @dataclass class Field: - length: float = 9.0 # x extent (own goal at -length/2, opp goal at +length/2) - width: float = 6.0 # y extent - goal_width: float = 2.6 # goal mouth - margin: float = 0.3 # keep field players this far inside the touchlines + length: float = 9.0 # x extent (own goal at -length/2, opp goal at +length/2) + width: float = 6.0 # y extent + goal_width: float = 2.6 # goal mouth + margin: float = 0.3 # keep field players this far inside the touchlines @dataclass class Params: # goalie - d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) + d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) # defenders - alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) - depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back - D_min: float = 0.9 # min defender depth from goal (never tuck behind this) - D_max: float = 3.8 # max defender depth from goal (high-line cap) - dz: float = 0.45 # keep defenders at least this far ahead of the goalie - standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball - gap: float = 1.1 # lateral spacing between adjacent defenders - def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) + alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) + depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back + D_min: float = 0.9 # min defender depth from goal (never tuck behind this) + D_max: float = 3.8 # max defender depth from goal (high-line cap) + dz: float = 0.45 # keep defenders at least this far ahead of the goalie + standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball + gap: float = 1.1 # lateral spacing between adjacent defenders + def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) # supporter - f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits - supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) - supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) + f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits + supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) + supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) # striker - kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) - post_margin: float = 0.45 # safety margin inside each goal post for a straight shot - back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side + kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) + post_margin: float = 0.45 # safety margin inside each goal post for a straight shot + back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side # separation - min_sep: float = 0.8 # no two robots closer than this + min_sep: float = 0.8 # no two robots closer than this sep_iters: int = 8 # kick lane: keep teammates out of the corridor in front of the ball - kick_clear: float = 0.7 # half-width of the cleared corridor - kick_range: float = 3.0 # how far in front of the ball the corridor extends + kick_clear: float = 0.7 # half-width of the cleared corridor + kick_range: float = 3.0 # how far in front of the ball the corridor extends # --------------------------------------------------------------------------- # @@ -120,8 +121,7 @@ def match_assignment(old_poses, new_items, ball, angle_w=0.3): for a, i in enumerate(rem_i): for b, j in enumerate(rem_j): op, npose = old_poses[i], new_items[j][1] - cost[a, b] = (np.linalg.norm(op[:2] - npose[:2]) - + angle_w * _angle_diff(op[2], npose[2])) + cost[a, b] = np.linalg.norm(op[:2] - npose[:2]) + angle_w * _angle_diff(op[2], npose[2]) ri, ci = linear_sum_assignment(cost) for a, b in zip(ri, ci): i, j = rem_i[a], rem_j[b] @@ -132,10 +132,12 @@ def match_assignment(old_poses, new_items, ball, angle_w=0.3): def _clamp_field(p, fld, margin=None): """Clamp a point to the playable rectangle (continuous / C0).""" m = fld.margin if margin is None else margin - return np.array([ - np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), - np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), - ]) + return np.array( + [ + np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), + np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), + ] + ) def _allocate_roles(n, ball=None, field=None): @@ -151,10 +153,10 @@ def _allocate_roles(n, ball=None, field=None): n_def = 0 has_support = False if n >= 3: - n_def += 1 # first defender + n_def += 1 # first defender if n >= 4: - has_support = True # supporter - n_def += max(n - 4, 0) # everyone past 4 is another defender + has_support = True # supporter + n_def += max(n - 4, 0) # everyone past 4 is another defender if has_support and n < 5 and ball is not None and field is not None: own_third = -field.length / 2 + field.length / 3.0 @@ -182,12 +184,12 @@ def compute_formation(ball, field: Field, n_players: int, params: Params): opp = np.array([+field.length / 2.0, 0.0]) d = np.linalg.norm(B - G) - to_ball = _normalize(B - G) # our-goal -> ball + to_ball = _normalize(B - G) # our-goal -> ball perp = np.array([-to_ball[1], to_ball[0]]) roles = _allocate_roles(n_players, B, field) out = {} - head = {} # role -> heading (rad); filled lazily, completed after separation + head = {} # role -> heading (rad); filled lazily, completed after separation kick_aim = None # striker's kick direction; used to clear the kick lane # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # @@ -207,30 +209,35 @@ def compute_formation(ball, field: Field, n_players: int, params: Params): # the striker swings smoothly rather than whipping when the two aims oppose a0 = np.arctan2(aim_goal[1], aim_goal[0]) a1 = np.arctan2(aim_back[1], aim_back[0]) - da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn + da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn ang = a0 + w_back * da aim = np.array([np.cos(ang), np.sin(ang)]) out["striker"] = B - params.kick_offset * aim - head["striker"] = ang # striker faces where it kicks + head["striker"] = ang # striker faces where it kicks kick_aim = aim # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # if "goalie" in roles: g = G + params.d_g * to_ball - g = np.array([ - np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), - np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), - ]) + g = np.array( + [ + np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), + np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), + ] + ) out["goalie"] = g # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # defender_roles = [r for r in roles if r.startswith("defender_")] m = len(defender_roles) if m > 0: - D = np.clip(params.alpha * d + params.depth_bias, # push up + fwd/back bias - params.D_min, params.D_max) - D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball - D = max(D, params.d_g + params.dz) # stay ahead of the goalie + D = np.clip( + params.alpha * d + params.depth_bias, # push up + fwd/back bias + params.D_min, + params.D_max, + ) + D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball + D = max(D, params.d_g + params.dz) # stay ahead of the goalie anchor = G + D * to_ball if m == 1: # a single defender: shade to the centre side so it doesn't sit on the @@ -246,7 +253,7 @@ def compute_formation(ball, field: Field, n_players: int, params: Params): if "supporter" in roles: # always sit to the centre side of the ball; hard swap so it is never # directly in front of the striker, even when the ball is on the centre line - side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) + side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) sup = B + np.array([params.f, params.supp_side * side_dir]) sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner out["supporter"] = _clamp_field(sup, field) @@ -257,13 +264,13 @@ def compute_formation(ball, field: Field, n_players: int, params: Params): # --- orientations (computed from the final positions) --------------------- # for role, p in out.items(): if role in head: - continue # striker already set (faces its kick aim) + continue # striker already set (faces its kick aim) if role == "supporter": # face the bisector of (toward ball, toward opp goal): "watch both" bis = _normalize(B - p) + _normalize(opp - p) head[role] = _face(np.zeros(2), bis, fallback=_face(p, opp)) else: - head[role] = _face(p, B) # goalie + defenders face the ball + head[role] = _face(p, B) # goalie + defenders face the ball return {role: np.array([p[0], p[1], head[role]]) for role, p in out.items()} @@ -290,8 +297,7 @@ def _separate(positions: dict, field: Field, params: Params, ball=None, aim=None if aim is not None and ball is not None: perp = np.array([-aim[1], aim[0]]) step = max(params.kick_clear * 0.7, 0.3) - lane_pts = [np.asarray(ball) + s * aim - for s in np.arange(step, params.kick_range + 1e-9, step)] + lane_pts = [np.asarray(ball) + s * aim for s in np.arange(step, params.kick_range + 1e-9, step)] for _ in range(params.sep_iters): disp = {n: np.zeros(2) for n in names} for i in range(len(names)): @@ -300,8 +306,7 @@ def _separate(positions: dict, field: Field, params: Params, ball=None, aim=None diff = positions[a] - positions[b] dist = np.linalg.norm(diff) if dist < sep: - dirv = _normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 \ - else np.array([0.0, 1.0]) + dirv = _normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 else np.array([0.0, 1.0]) overlap = sep - dist a_fixed, b_fixed = a in fixed, b in fixed if a_fixed and b_fixed: @@ -321,7 +326,7 @@ def _separate(positions: dict, field: Field, params: Params, ball=None, aim=None diff = positions[n] - lp dist = np.linalg.norm(diff) if dist < params.kick_clear: - dirv = _normalize(diff, perp) # exactly on the line -> step sideways + dirv = _normalize(diff, perp) # exactly on the line -> step sideways disp[n] += (params.kick_clear - dist) * dirv for n in names: if n in fixed: @@ -333,10 +338,9 @@ def _separate(positions: dict, field: Field, params: Params, ball=None, aim=None # GUI # --------------------------------------------------------------------------- # def run_gui(): - import matplotlib import matplotlib.pyplot as plt + from matplotlib.patches import Circle, Rectangle from matplotlib.widgets import Slider - from matplotlib.patches import Rectangle, Circle fld = Field() params = Params() @@ -348,38 +352,42 @@ def run_gui(): plt.subplots_adjust(left=0.08, right=0.97, top=0.98, bottom=0.50) # sliders (stacked bottom -> top) - def _ax(b): return plt.axes([0.18, b, 0.72, 0.015]) - s_n = Slider(_ax(0.470), "players", 1, 8, valinit=state["n"], valstep=1) - s_sep = Slider(_ax(0.435), "min_sep", 0.3, 2.0, valinit=params.min_sep) - s_alpha = Slider(_ax(0.400), "push α", 0.1, 0.8, valinit=params.alpha) - s_dbias = Slider(_ax(0.365), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) - s_dside = Slider(_ax(0.330), "def side", 0.0, 2.0, valinit=params.def_side) - s_gap = Slider(_ax(0.295), "def gap", 0.5, 2.0, valinit=params.gap) - s_f = Slider(_ax(0.260), "supp lead", 0.0, 3.0, valinit=params.f) - s_side = Slider(_ax(0.225), "supp side", 0.0, 2.5, valinit=params.supp_side) - s_smax = Slider(_ax(0.190), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) - s_pmarg = Slider(_ax(0.155), "post margin", 0.0, 1.3, valinit=params.post_margin) - s_back = Slider(_ax(0.120), "back dist", 0.0, 3.0, valinit=params.back_dist) - s_kclr = Slider(_ax(0.085), "kick clear", 0.0, 1.5, valinit=params.kick_clear) - s_gout = Slider(_ax(0.050), "goalie out", 0.2, 2.0, valinit=params.d_g) + def _ax(b): + return plt.axes([0.18, b, 0.72, 0.015]) + + s_n = Slider(_ax(0.470), "players", 1, 8, valinit=state["n"], valstep=1) + s_sep = Slider(_ax(0.435), "min_sep", 0.3, 2.0, valinit=params.min_sep) + s_alpha = Slider(_ax(0.400), "push α", 0.1, 0.8, valinit=params.alpha) + s_dbias = Slider(_ax(0.365), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) + s_dside = Slider(_ax(0.330), "def side", 0.0, 2.0, valinit=params.def_side) + s_gap = Slider(_ax(0.295), "def gap", 0.5, 2.0, valinit=params.gap) + s_f = Slider(_ax(0.260), "supp lead", 0.0, 3.0, valinit=params.f) + s_side = Slider(_ax(0.225), "supp side", 0.0, 2.5, valinit=params.supp_side) + s_smax = Slider(_ax(0.190), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) + s_pmarg = Slider(_ax(0.155), "post margin", 0.0, 1.3, valinit=params.post_margin) + s_back = Slider(_ax(0.120), "back dist", 0.0, 3.0, valinit=params.back_dist) + s_kclr = Slider(_ax(0.085), "kick clear", 0.0, 1.5, valinit=params.kick_clear) + s_gout = Slider(_ax(0.050), "goalie out", 0.2, 2.0, valinit=params.d_g) def draw(): ax.clear() # pitch - ax.add_patch(Rectangle((-fld.length / 2, -fld.width / 2), fld.length, fld.width, - fill=False, color="white", lw=2)) + ax.add_patch( + Rectangle((-fld.length / 2, -fld.width / 2), fld.length, fld.width, fill=False, color="white", lw=2) + ) ax.axvline(0, color="white", lw=1) ax.add_patch(Circle((0, 0), 0.75, fill=False, color="white", lw=1)) for sgn in (-1, 1): # goals - ax.plot([sgn * fld.length / 2] * 2, - [-fld.goal_width / 2, fld.goal_width / 2], - color="#4da6ff" if sgn < 0 else "#ff9999", lw=6) + ax.plot( + [sgn * fld.length / 2] * 2, + [-fld.goal_width / 2, fld.goal_width / 2], + color="#4da6ff" if sgn < 0 else "#ff9999", + lw=6, + ) ax.set_facecolor("#2e7d32") - params.min_sep, params.alpha, params.gap, params.f = \ - s_sep.val, s_alpha.val, s_gap.val, s_f.val - params.depth_bias, params.supp_side, params.d_g = \ - s_dbias.val, s_side.val, s_gout.val + params.min_sep, params.alpha, params.gap, params.f = s_sep.val, s_alpha.val, s_gap.val, s_f.val + params.depth_bias, params.supp_side, params.d_g = s_dbias.val, s_side.val, s_gout.val params.supp_max_x, params.def_side = s_smax.val, s_dside.val params.post_margin, params.back_dist = s_pmarg.val, s_back.val params.kick_clear = s_kclr.val @@ -393,8 +401,7 @@ def draw(): if prev is not None and len(prev) == len(new_items): for old_pose, new_pose, role in match_assignment(prev, new_items, state["ball"]): c = colors.get(role.split("_")[0], "#1f77b4") - ax.plot([old_pose[0], new_pose[0]], [old_pose[1], new_pose[1]], - ls=":", color=c, lw=1.5, zorder=3) + ax.plot([old_pose[0], new_pose[0]], [old_pose[1], new_pose[1]], ls=":", color=c, lw=1.5, zorder=3) ax.add_patch(Circle(old_pose[:2], 0.10, color=c, alpha=0.55, zorder=4)) # this assignment becomes the "previous" for the next click state["prev"] = [pose for _role, pose in new_items] @@ -411,8 +418,16 @@ def draw(): corner = perp * params.kick_clear lane = np.array([b + corner, far + corner, far - corner, b - corner]) ax.add_patch(plt.Polygon(lane, closed=True, color="white", alpha=0.10, zorder=1)) - ax.arrow(*state["ball"], *(1.4 * aim), color="white", width=0.02, - head_width=0.18, length_includes_head=True, zorder=8, alpha=0.9) + ax.arrow( + *state["ball"], + *(1.4 * aim), + color="white", + width=0.02, + head_width=0.18, + length_includes_head=True, + zorder=8, + alpha=0.9, + ) # robots (pose = [x, y, heading]) for role, pose in form.items(): p, th = pose[:2], pose[2] @@ -421,16 +436,28 @@ def draw(): ax.add_patch(Circle(p, params.min_sep / 2, color=c, alpha=0.18, zorder=2)) ax.add_patch(Circle(p, 0.16, color=c, ec="black", zorder=6)) # heading indicator - ax.plot([p[0], p[0] + 0.45 * np.cos(th)], [p[1], p[1] + 0.45 * np.sin(th)], - color="black", lw=2.5, zorder=7, solid_capstyle="round") - ax.annotate(role.replace("defender_", "D").replace("supporter", "supp"), - p, color="white", fontsize=8, ha="center", va="center", zorder=8) + ax.plot( + [p[0], p[0] + 0.45 * np.cos(th)], + [p[1], p[1] + 0.45 * np.sin(th)], + color="black", + lw=2.5, + zorder=7, + solid_capstyle="round", + ) + ax.annotate( + role.replace("defender_", "D").replace("supporter", "supp"), + p, + color="white", + fontsize=8, + ha="center", + va="center", + zorder=8, + ) ax.set_xlim(-fld.length / 2 - 0.5, fld.length / 2 + 0.5) ax.set_ylim(-fld.width / 2 - 0.5, fld.width / 2 + 0.5) ax.set_aspect("equal") - ax.set_title("click to move the ball · dots = previous assignment (dotted = who moves where)", - color="black") + ax.set_title("click to move the ball · dots = previous assignment (dotted = who moves where)", color="black") fig.canvas.draw_idle() def on_click(event): @@ -438,8 +465,7 @@ def on_click(event): state["ball"] = np.array([event.xdata, event.ydata]) draw() - for s in (s_n, s_sep, s_alpha, s_dbias, s_dside, s_gap, s_f, s_side, s_smax, - s_pmarg, s_back, s_kclr, s_gout): + for s in (s_n, s_sep, s_alpha, s_dbias, s_dside, s_gap, s_f, s_side, s_smax, s_pmarg, s_back, s_kclr, s_gout): s.on_changed(lambda _v: draw()) fig.canvas.mpl_connect("button_press_event", on_click) draw() diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/body_blackboard.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/body_blackboard.py index 85490092d..695713593 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/body_blackboard.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/body_blackboard.py @@ -8,9 +8,9 @@ from bitbots_blackboard.capsules.kick_capsule import KickCapsule from bitbots_blackboard.capsules.misc_capsule import MiscCapsule from bitbots_blackboard.capsules.pathfinding_capsule import PathfindingCapsule +from bitbots_blackboard.capsules.positioning_capsule import PositioningCapsule from bitbots_blackboard.capsules.team_data_capsule import TeamDataCapsule from bitbots_blackboard.capsules.world_model_capsule import WorldModelCapsule -from bitbots_blackboard.capsules.positioning_capsule import PositioningCapsule class BodyBlackboard: diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py index 01a304172..28805514f 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py @@ -97,7 +97,7 @@ def received_gamestate(self) -> bool: def get_team_id(self) -> int: return self.team_id - + def get_own_id(self) -> int: return self.own_id diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 5ee972961..a3c56661f 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -1,6 +1,7 @@ from dataclasses import dataclass -from bitbots_utils.utils import get_parameters_from_other_node + import numpy as np +from bitbots_utils.utils import get_parameters_from_other_node from bitbots_blackboard.capsules import AbstractBlackboardCapsule, cached_capsule_function @@ -8,10 +9,11 @@ @dataclass class Field: """Field geometry. Populated from the parameter blackboard in __init__.""" - length: float = 9.0 # x extent (own goal at -length/2, opp goal at +length/2) - width: float = 6.0 # y extent - goal_width: float = 1.5 # goal mouth - margin: float = 0.3 # keep field players this far inside the touchlines + + length: float = 9.0 # x extent (own goal at -length/2, opp goal at +length/2) + width: float = 6.0 # y extent + goal_width: float = 1.5 # goal mouth + margin: float = 0.3 # keep field players this far inside the touchlines @dataclass @@ -37,31 +39,32 @@ class Params: also what shoves the defenders sideways into clean flanking slots when they would otherwise pile onto the goalie -> the "wall next to the goalie" emerges for free. """ + # goalie - d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) + d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) # defenders - alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) - depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back - D_min: float = 0.9 # min defender depth from goal (never tuck behind this) - D_max: float = 3.8 # max defender depth from goal (high-line cap) - dz: float = 0.45 # keep defenders at least this far ahead of the goalie - standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball - gap: float = 1.1 # lateral spacing between adjacent defenders - def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) + alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) + depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back + D_min: float = 0.9 # min defender depth from goal (never tuck behind this) + D_max: float = 3.8 # max defender depth from goal (high-line cap) + dz: float = 0.45 # keep defenders at least this far ahead of the goalie + standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball + gap: float = 1.1 # lateral spacing between adjacent defenders + def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) # supporter - f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits - supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) - supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) + f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits + supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) + supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) # striker - kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) - post_margin: float = 0.45 # safety margin inside each goal post for a straight shot - back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side + kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) + post_margin: float = 0.45 # safety margin inside each goal post for a straight shot + back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side # separation - min_sep: float = 0.8 # no two robots closer than this + min_sep: float = 0.8 # no two robots closer than this sep_iters: int = 8 # kick lane: keep teammates out of the corridor in front of the ball - kick_clear: float = 0.7 # half-width of the cleared corridor - kick_range: float = 3.0 # how far in front of the ball the corridor extends + kick_clear: float = 0.7 # half-width of the cleared corridor + kick_range: float = 3.0 # how far in front of the ball the corridor extends class PositioningCapsule(AbstractBlackboardCapsule): @@ -124,10 +127,12 @@ def _angle_diff(a, b): def _clamp_field(p, fld, margin=None): """Clamp a point to the playable rectangle (continuous / C0).""" m = fld.margin if margin is None else margin - return np.array([ - np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), - np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), - ]) + return np.array( + [ + np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), + np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), + ] + ) # --------------------------------------------------------------------------- # # Role allocation @@ -147,10 +152,10 @@ def _allocate_roles(n, ball=None, field=None): n_def = 0 has_support = False if n >= 3: - n_def += 1 # first defender + n_def += 1 # first defender if n >= 4: - has_support = True # supporter - n_def += max(n - 4, 0) # everyone past 4 is another defender + has_support = True # supporter + n_def += max(n - 4, 0) # everyone past 4 is another defender if has_support and n < 5 and ball is not None and field is not None: own_third = -field.length / 2 + field.length / 3.0 @@ -193,8 +198,7 @@ def _separate(self, positions: dict, field: Field, params: Params, ball=None, ai if aim is not None and ball is not None: perp = np.array([-aim[1], aim[0]]) step = max(params.kick_clear * 0.7, 0.3) - lane_pts = [np.asarray(ball) + s * aim - for s in np.arange(step, params.kick_range + 1e-9, step)] + lane_pts = [np.asarray(ball) + s * aim for s in np.arange(step, params.kick_range + 1e-9, step)] for _ in range(params.sep_iters): disp = {n: np.zeros(2) for n in names} for i in range(len(names)): @@ -203,8 +207,7 @@ def _separate(self, positions: dict, field: Field, params: Params, ball=None, ai diff = positions[a] - positions[b] dist = np.linalg.norm(diff) if dist < sep: - dirv = self._normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 \ - else np.array([0.0, 1.0]) + dirv = self._normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 else np.array([0.0, 1.0]) overlap = sep - dist a_fixed, b_fixed = a in fixed, b in fixed if a_fixed and b_fixed: @@ -261,8 +264,7 @@ def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): for a, i in enumerate(rem_i): for b, j in enumerate(rem_j): op, npose = old_poses[i], new_items[j][1] - cost[a, b] = (np.linalg.norm(op[:2] - npose[:2]) - + angle_w * self._angle_diff(op[2], npose[2])) + cost[a, b] = np.linalg.norm(op[:2] - npose[:2]) + angle_w * self._angle_diff(op[2], npose[2]) ri, ci = linear_sum_assignment(cost) for a, b in zip(ri, ci): i, j = rem_i[a], rem_j[b] @@ -275,17 +277,17 @@ def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): def _compute_formation(self, ball, field: Field, n_players: int, params: Params): """Map a ball position -> {role_name: np.array([x, y, theta])}. Pure & deterministic.""" - B = np.asarray(ball, dtype=float) + B = ball G = np.array([-field.length / 2.0, 0.0]) opp = np.array([+field.length / 2.0, 0.0]) d = np.linalg.norm(B - G) - to_ball = self._normalize(B - G) # our-goal -> ball + to_ball = self._normalize(B - G) # our-goal -> ball perp = np.array([-to_ball[1], to_ball[0]]) roles = self._allocate_roles(n_players, B, field) out = {} - head = {} # role -> heading (rad); filled lazily, completed after separation + head = {} # role -> heading (rad); filled lazily, completed after separation kick_aim = None # striker's kick direction; used to clear the kick lane # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # @@ -305,30 +307,35 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) # the striker swings smoothly rather than whipping when the two aims oppose a0 = np.arctan2(aim_goal[1], aim_goal[0]) a1 = np.arctan2(aim_back[1], aim_back[0]) - da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn + da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn ang = a0 + w_back * da aim = np.array([np.cos(ang), np.sin(ang)]) out["striker"] = B - params.kick_offset * aim - head["striker"] = ang # striker faces where it kicks + head["striker"] = ang # striker faces where it kicks kick_aim = aim # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # if "goalie" in roles: g = G + params.d_g * to_ball - g = np.array([ - np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), - np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), - ]) + g = np.array( + [ + np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), + np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), + ] + ) out["goalie"] = g # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # defender_roles = [r for r in roles if r.startswith("defender_")] m = len(defender_roles) if m > 0: - D = np.clip(params.alpha * d + params.depth_bias, # push up + fwd/back bias - params.D_min, params.D_max) - D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball - D = max(D, params.d_g + params.dz) # stay ahead of the goalie + D = np.clip( + params.alpha * d + params.depth_bias, # push up + fwd/back bias + params.D_min, + params.D_max, + ) + D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball + D = max(D, params.d_g + params.dz) # stay ahead of the goalie anchor = G + D * to_ball if m == 1: # a single defender: shade to the centre side so it doesn't sit on the @@ -344,7 +351,7 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) if "supporter" in roles: # always sit to the centre side of the ball; hard swap so it is never # directly in front of the striker, even when the ball is on the centre line - side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) + side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) sup = B + np.array([params.f, params.supp_side * side_dir]) sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner out["supporter"] = self._clamp_field(sup, field) @@ -355,7 +362,7 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) # --- orientations (computed from the final positions) --------------------- # for role, p in out.items(): if role in head: - continue # striker already set (faces its kick aim) + continue # striker already set (faces its kick aim) if role == "supporter": # face the bisector of (toward ball, toward opp goal): "watch both" bis = self._normalize(B - p) + self._normalize(opp - p) @@ -367,9 +374,11 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) @cached_capsule_function def get_formation_assignment(self) -> dict: - ball = self._blackboard.world_model.get_best_ball_point_stamped() + ballPose = self._blackboard.world_model.get_best_ball_point_stamped() + ball = np.array([ballPose.point.x, ballPose.point.y]) robot_poses = self._blackboard.team_data.get_robot_poses() - + self._node.get_logger().info(f"Length of robot_poses: {len(robot_poses)}") + formation = self._compute_formation(ball, self._field, len(robot_poses), self._params) new_items = list(formation.items()) ordered_jerseys = sorted(robot_poses.keys()) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index 876e74511..4e18f2819 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -1,7 +1,7 @@ +import math from typing import Literal, Optional import numpy as np -import math from bitbots_utils.utils import get_parameters_from_other_node from geometry_msgs.msg import PointStamped, Pose from rclpy.duration import Duration @@ -183,7 +183,7 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: if self.is_valid(data) and (data.strategy.role != Strategy.ROLE_GOALIE or count_goalies): poses.append(data.robot_position.pose) return poses - + def quaternion_to_yaw(q) -> float: """Extract yaw (theta) from a quaternion.""" return math.atan2(2.0 * (q.w * q.z + q.x * q.y), 1.0 - 2.0 * (q.y * q.y + q.z * q.z)) @@ -196,6 +196,8 @@ def get_robot_poses(self) -> dict[int, list[float]]: if self.is_valid(data): pose = data.robot_position.pose robot_poses[data.robot_id] = [pose.point.x, pose.point.y, self.quaternion_to_yaw(pose.orientation)] + # include own data + robot_poses[self._blackboard.gamestate.get_own_id()] = list(self._blackboard.world_model.get_current_position()) return robot_poses def get_number_of_active_field_players(self, count_goalie: bool = False) -> int: diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index 8d7010bd4..fce466a7d 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -48,7 +48,7 @@ def __init__(self, blackboard, dsd, parameters): def perform(self, reevaluate=False): optimal_positioning = self.blackboard.positioning.get_formation_assignment() - own_position = optimal_positioning[self.blackboard.game_status.get_own_id()] + own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] role = own_position["role"] self.publish_debug_data("Role from positioning", role) if role == "striker": From eca2b979921a631952bd37abedb87ce1db2a3c7f Mon Sep 17 00:00:00 2001 From: Clemens Date: Mon, 22 Jun 2026 17:46:05 +0200 Subject: [PATCH 07/68] test integration of different roles in simulation (only normal behaviour) --- .../capsules/team_data_capsule.py | 8 ++++++-- .../actions/go_to_block_position.py | 20 +++++++++++++++++++ .../actions/go_to_defense_position.py | 2 +- .../actions/go_to_pass_position.py | 11 +++++++--- .../behavior_dsd/decisions/closest_to_ball.py | 10 ++++++---- .../behavior_dsd/main.dsd | 17 ++++++++-------- 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index 4e18f2819..ed9ff070d 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -184,7 +184,7 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: poses.append(data.robot_position.pose) return poses - def quaternion_to_yaw(q) -> float: + def quaternion_to_yaw(self, q) -> float: """Extract yaw (theta) from a quaternion.""" return math.atan2(2.0 * (q.w * q.z + q.x * q.y), 1.0 - 2.0 * (q.y * q.y + q.z * q.z)) @@ -195,7 +195,11 @@ def get_robot_poses(self) -> dict[int, list[float]]: for data in self.team_data.values(): if self.is_valid(data): pose = data.robot_position.pose - robot_poses[data.robot_id] = [pose.point.x, pose.point.y, self.quaternion_to_yaw(pose.orientation)] + robot_poses[data.robot_id] = [ + pose.position.x, + pose.position.y, + self.quaternion_to_yaw(pose.orientation), + ] # include own data robot_poses[self._blackboard.gamestate.get_own_id()] = list(self._blackboard.world_model.get_current_position()) return robot_poses diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py index c2f91fc90..bf805ce65 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py @@ -6,6 +6,26 @@ from dynamic_stack_decider.abstract_action_element import AbstractActionElement from tf2_geometry_msgs import PoseStamped +class GoToGoaliePosition(AbstractActionElement): + blackboard: BodyBlackboard + + def __init__(self, blackboard, dsd, parameters): + super().__init__(blackboard, dsd, parameters) + + def perform(self, reevaluate=False): + + pose_msg = PoseStamped() + pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() + pose_msg.header.frame_id = self.blackboard.map_frame + + optimal_positioning = self.blackboard.positioning.get_formation_assignment() + own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] + pose = own_position["goal_pose"] + pose_msg.pose.position.x = pose[0] + pose_msg.pose.position.y = pose[1] + pose_msg.pose.orientation.w = pose[2] + + self.blackboard.pathfinding.publish(pose_msg) class GoToBlockPosition(AbstractActionElement): blackboard: BodyBlackboard diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py index 28fcc9d2a..e5b67eafd 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py @@ -84,7 +84,7 @@ def perform(self, reevaluate=False): else: # center point between ball and own goal optimal_positioning = self.blackboard.positioning.get_formation_assignment() - own_position = optimal_positioning[self.blackboard.game_status.get_own_id()] + own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] pose = own_position["goal_pose"] pose_msg.pose.position.x = pose[0] pose_msg.pose.position.y = pose[1] diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py index c05511f99..13f6a4074 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py @@ -40,9 +40,14 @@ def perform(self, reevaluate=False): pose_msg = PoseStamped() pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() pose_msg.header.frame_id = self.blackboard.map_frame - pose_msg.pose.position.x = float(goal_x) - pose_msg.pose.position.y = float(goal_y) - pose_msg.pose.orientation = quat_from_yaw(goal_yaw) + + optimal_positioning = self.blackboard.positioning.get_formation_assignment() + own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] + pose = own_position["goal_pose"] + pose_msg.pose.position.x = pose[0] + pose_msg.pose.position.y = pose[1] + pose_msg.pose.orientation.w = pose[2] + self.blackboard.pathfinding.publish(pose_msg) if not self.blocking: diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index fce466a7d..68b49f099 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -33,14 +33,14 @@ def perform(self, reevaluate=False): self.publish_debug_data("time to ball", my_time_to_ball) self.publish_debug_data("Rank to ball", rank) if rank == 1: - return "YES" + return "NO" # only for testing remeber to REMOVE! return "NO" def get_reevaluate(self): return True -class RankToBallNoGoalie(AbstractDecisionElement): +class RankToBallWithGoalie(AbstractDecisionElement): blackboard: BodyBlackboard def __init__(self, blackboard, dsd, parameters): @@ -53,8 +53,10 @@ def perform(self, reevaluate=False): self.publish_debug_data("Role from positioning", role) if role == "striker": return "STRIKER" + elif role == "goalie": + return "GOALIE" elif role == "defender_0": - return "DEFENDER0" + return "DEFENDER_ZERO" elif role == "defender_1": return "DEFENDER1" elif role == "defender_2": @@ -65,7 +67,7 @@ def perform(self, reevaluate=False): return "SUPPORTER" else: # emergency fall back if something goes wrong - self.blackboard.node.get_logger().warning("Rank to ball had some issues") + self.blackboard.node.get_logger().warning("Rank to ball had some issues. Role" + role) return "STRIKER" def get_reevaluate(self): diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index b488781ad..8d9143358 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -89,10 +89,12 @@ $DoOnce NO --> $SecondaryStateTeamDecider OUR --> #SearchBall ELSE --> @AvoidBallActive, @LookAtFieldFeatures, @WalkInPlace + duration:2, @GoToRelativePosition + x:1 + y:0 + t:0, @Stand - YES --> $RankToBallNoGoalie + YES --> $RankToBallWithGoalie STRIKER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_first DEFENDER0 --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_second SUPPORTER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + GOALIE --> @GoToGoaliePosition + ELSE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_second #Init @Stand + duration:0.1 + r:false, @ChangeAction + action:waiting, @LookForward, @Stand @@ -105,13 +107,12 @@ $BallSeen YES --> $KickOffTimeUp NO_NORMAL --> #StandAndLook NO_FREEKICK --> #Placing - YES --> $ConfigRole - GOALIE --> #GoalieBehavior - ELSE --> $RankToBallNoGoalie - STRIKER --> #StrikerRole - DEFENDER0 --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition - SUPPORTER --> #SupporterRole - ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition //defender 1 bis 4 integrieren? + YES --> $RankToBallWithGoalie + STRIKER --> #StrikerRole + GOALIE --> @GoToGoaliePosition + DEFENDER_ZERO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition + SUPPORTER --> #SupporterRole + ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition //defender 1 bis 4 integrieren? #PlayingBehavior $SecondaryStateDecider From 775da1283f66bd0004951ec56b9382ab9f1fee02 Mon Sep 17 00:00:00 2001 From: Clemens Date: Mon, 22 Jun 2026 18:02:08 +0200 Subject: [PATCH 08/68] add x any pos slider to rqt data sim --- .../bitbots_team_data_sim_rqt/team_data_ui.py | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py b/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py index 80da523f2..9a69b64f4 100755 --- a/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py +++ b/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py @@ -24,6 +24,7 @@ from rqt_gui_py.plugin import Plugin from bitbots_msgs.msg import Strategy, TeamData +from geometry_msgs.msg import PoseWithCovariance class RobotWidget(QGroupBox): @@ -31,7 +32,7 @@ def __init__(self, parent=None): super().__init__(parent) self.setTitle("Robot") # Set maximum width - self.setMaximumWidth(350) + self.setMaximumWidth(450) self.setMinimumWidth(150) # Create layout self.main_layout = QVBoxLayout() @@ -45,6 +46,10 @@ def __init__(self, parent=None): self.main_layout.addWidget(self.state_box) self.time_to_position_box = TimeToPositionBox() self.main_layout.addWidget(self.time_to_position_box) + self.position_sliders_x = PositionCoordsX() + self.main_layout.addWidget(self.position_sliders_x) + self.position_sliders_y = PositionCoordsY() + self.main_layout.addWidget(self.position_sliders_y) self.strategy_box = StrategyBox() self.main_layout.addWidget(self.strategy_box) self.publish_button = PublishButton() @@ -58,6 +63,8 @@ def id_spin_box_update(self): self.time_to_position_box.setEnabled(enabled) self.strategy_box.setEnabled(enabled) self.publish_button.setEnabled(enabled) + self.position_sliders_x.setEnabled(enabled) + self.position_sliders_y.setEnabled(enabled) def get_robot_id(self) -> int: return self.id_spin_box.value() @@ -121,6 +128,56 @@ def get_time(self) -> float: return float(self.time_spin_box.value()) +class PositionCoordsX(QGroupBox): + def __init__(self, parent=None): + super().__init__(parent) + # x position + self.setTitle("X position") + self.setEnabled(False) + # Create layout + self.main_layout = QHBoxLayout() + self.setLayout(self.main_layout) + # Create spin box + self.x_pos_spin_box = QSpinBox() + self.x_pos_spin_box.setRange(-550, 550) + self.main_layout.addWidget(self.x_pos_spin_box) + # Create slider + self.x_pos_slider = QSlider(Qt.Horizontal) # type: ignore[attr-defined] + self.x_pos_slider.setRange(-550, 550) + self.main_layout.addWidget(self.x_pos_slider) + # Connect spin box and slider + self.x_pos_spin_box.valueChanged.connect(self.x_pos_slider.setValue) # type: ignore[attr-defined] + self.x_pos_slider.valueChanged.connect(self.x_pos_spin_box.setValue) # type: ignore[attr-defined] + + def get_x_position(self) -> float: + return float(self.x_pos_spin_box.value() / 100) + + +class PositionCoordsY(QGroupBox): + def __init__(self, parent=None): + super().__init__(parent) + # y position + self.setTitle("Y position") + self.setEnabled(False) + # Create layout + self.main_layout = QHBoxLayout() + self.setLayout(self.main_layout) + # Create spin box + self.y_pos_spin_box = QSpinBox() + self.y_pos_spin_box.setRange(-400, 400) + self.main_layout.addWidget(self.y_pos_spin_box) + # Create slider + self.y_pos_slider = QSlider(Qt.Horizontal) # type: ignore[attr-defined] + self.y_pos_slider.setRange(-400, 400) + self.main_layout.addWidget(self.y_pos_slider) + # Connect spin box and slider + self.y_pos_spin_box.valueChanged.connect(self.y_pos_slider.setValue) # type: ignore[attr-defined] + self.y_pos_slider.valueChanged.connect(self.y_pos_spin_box.setValue) # type: ignore[attr-defined] + + def get_y_position(self) -> float: + return float(self.y_pos_spin_box.value() / 100) + + class StrategyBox(QGroupBox): _roles: dict[str, int] = { "Undefined": Strategy.ROLE_UNDEFINED, @@ -250,6 +307,10 @@ def timer_callback(self): if robot_widget.active(): team_data = TeamData() team_data.robot_id = robot_widget.get_robot_id() + poseWithCov = PoseWithCovariance() + poseWithCov.pose.position.x = robot_widget.position_sliders_x.get_x_position() + poseWithCov.pose.position.y = robot_widget.position_sliders_y.get_y_position() + team_data.robot_position = poseWithCov team_data.state = robot_widget.state_box.get_state() team_data.time_to_position_at_ball = robot_widget.time_to_position_box.get_time() team_data.strategy.role = robot_widget.strategy_box.get_role() From 842adfd4f4a3f2c8e768631e0865ebf31e2c63b1 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Mon, 29 Jun 2026 16:18:33 +0200 Subject: [PATCH 09/68] Use events executor for rviz markers Signed-off-by: Florian Vahl --- .../soccer_vision_3d_rviz_markers/visualizer.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lib/soccer_vision_3d_rviz_markers/soccer_vision_3d_rviz_markers/visualizer.py b/src/lib/soccer_vision_3d_rviz_markers/soccer_vision_3d_rviz_markers/visualizer.py index fd7b5e546..3fcf1ff54 100755 --- a/src/lib/soccer_vision_3d_rviz_markers/soccer_vision_3d_rviz_markers/visualizer.py +++ b/src/lib/soccer_vision_3d_rviz_markers/soccer_vision_3d_rviz_markers/visualizer.py @@ -15,6 +15,7 @@ import rclpy from rclpy.node import Node +from rclpy.experimental.events_executor import EventsExecutor from soccer_vision_3d_msgs.msg import ( BallArray, FieldBoundary, GoalpostArray, MarkingArray, ObstacleArray, RobotArray) @@ -89,14 +90,15 @@ def main(args=None): rclpy.init(args=args) node = SoccerVision3DMarkers() + + executor = EventsExecutor() + executor.add_node(node) + try: - rclpy.spin(node) + executor.spin() except KeyboardInterrupt: pass - - node.destroy_node() - rclpy.shutdown() - + if __name__ == '__main__': main() From 43c6e3125e63b87d752cbef55f7432fc48319ba7 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Mon, 29 Jun 2026 16:49:10 +0200 Subject: [PATCH 10/68] Isolate placement test script Signed-off-by: Florian Vahl --- pixi.lock | 195 ++++++++++-------- .../bitbots_blackboard/CMakeLists.txt | 5 + .../capsules/positioning_capsule.py | 52 ++--- .../scripts/debug_positioning.py | 147 +++++++++++++ 4 files changed, 288 insertions(+), 111 deletions(-) create mode 100755 src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py diff --git a/pixi.lock b/pixi.lock index 02e1b722e..141365d1c 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1,7 +1,17 @@ version: 7 platforms: - name: linux-64 + virtual-packages: + - __unix=0=0 + - __linux=4.18 + - __glibc=2.28 + - __archspec=0=x86_64 - name: linux-aarch64 + virtual-packages: + - __unix=0=0 + - __linux=4.18 + - __glibc=2.28 + - __archspec=0=aarch64 environments: default: channels: @@ -992,7 +1002,7 @@ environments: - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/tts-supertonic-1.0.0-h4616a5c_1.conda - - conda_source: bitbots_rust_nav[218786e9] @ src/bitbots_navigation/bitbots_rust_nav + - conda_source: bitbots_rust_nav[eb738ce2] @ src/bitbots_navigation/bitbots_rust_nav - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/de/0880cf8af64b225bc8fde0924f76ea5e6cd8d8dc50c6dd61232beb54327f/mjviser-0.0.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl @@ -1978,7 +1988,7 @@ environments: - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/tts-supertonic-1.0.0-h4616a5c_1.conda - - conda_source: bitbots_rust_nav[de420e0b] @ src/bitbots_navigation/bitbots_rust_nav + - conda_source: bitbots_rust_nav[77771cb3] @ src/bitbots_navigation/bitbots_rust_nav - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/de/0880cf8af64b225bc8fde0924f76ea5e6cd8d8dc50c6dd61232beb54327f/mjviser-0.0.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl @@ -3110,7 +3120,7 @@ environments: - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/tts-supertonic-1.0.0-h4616a5c_1.conda - - conda_source: bitbots_rust_nav[218786e9] @ src/bitbots_navigation/bitbots_rust_nav + - conda_source: bitbots_rust_nav[eb738ce2] @ src/bitbots_navigation/bitbots_rust_nav - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/de/0880cf8af64b225bc8fde0924f76ea5e6cd8d8dc50c6dd61232beb54327f/mjviser-0.0.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl @@ -4100,7 +4110,7 @@ environments: - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/tts-supertonic-1.0.0-h4616a5c_1.conda - - conda_source: bitbots_rust_nav[de420e0b] @ src/bitbots_navigation/bitbots_rust_nav + - conda_source: bitbots_rust_nav[77771cb3] @ src/bitbots_navigation/bitbots_rust_nav - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/de/0880cf8af64b225bc8fde0924f76ea5e6cd8d8dc50c6dd61232beb54327f/mjviser-0.0.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl @@ -5165,7 +5175,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/frozenlist?source=compressed-mapping + - pkg:pypi/frozenlist?source=hash-mapping size: 55016 timestamp: 1779999817627 - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_19.conda @@ -9362,7 +9372,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/scipy?source=compressed-mapping + - pkg:pypi/scipy?source=hash-mapping size: 16828243 timestamp: 1779874781187 - conda: https://conda.anaconda.org/conda-forge/linux-64/sdformat14-14.8.0-h5bb51b8_2.conda @@ -9610,7 +9620,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=compressed-mapping + - pkg:pypi/tornado?source=hash-mapping size: 860785 timestamp: 1779915943143 - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py312hd9148b4_0.conda @@ -10344,7 +10354,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/yarl?source=compressed-mapping + - pkg:pypi/yarl?source=hash-mapping size: 155061 timestamp: 1779246264888 - conda: https://conda.anaconda.org/conda-forge/linux-64/zenoh-rust-abi-1.7.2.1.85.0-h8619998_0.conda @@ -10974,7 +10984,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/coverage?source=compressed-mapping + - pkg:pypi/coverage?source=hash-mapping size: 390698 timestamp: 1779839029690 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cppcheck-2.18.3-py312h5677ec4_1.conda @@ -15298,7 +15308,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/scipy?source=compressed-mapping + - pkg:pypi/scipy?source=hash-mapping size: 16878451 timestamp: 1779874509446 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdformat14-14.8.0-hb4dca6f_2.conda @@ -15531,7 +15541,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=compressed-mapping + - pkg:pypi/tornado?source=hash-mapping size: 862640 timestamp: 1779916964108 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py312h4f740d2_0.conda @@ -16567,7 +16577,8 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/colcon-core?source=compressed-mapping + - pkg:pypi/colcon-core?source=hash-mapping + - pkg:pypi/colcon-distutils-commands?source=hash-mapping size: 96785 timestamp: 1780438171992 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-defaults-0.2.9-pyhd8ed1ab_1.conda @@ -16837,7 +16848,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/distlib?source=compressed-mapping + - pkg:pypi/distlib?source=hash-mapping size: 302890 timestamp: 1780422960389 - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda @@ -16948,7 +16959,7 @@ packages: - python >=3.10 license: Unlicense purls: - - pkg:pypi/filelock?source=compressed-mapping + - pkg:pypi/filelock?source=hash-mapping size: 34899 timestamp: 1780521975987 - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-7.3.0-pyhd8ed1ab_0.conda @@ -17216,7 +17227,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/idna?source=compressed-mapping + - pkg:pypi/idna?source=hash-mapping size: 56858 timestamp: 1779999227630 - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda @@ -17300,7 +17311,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/ipython?source=compressed-mapping + - pkg:pypi/ipython?source=hash-mapping size: 652893 timestamp: 1780654403616 - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda @@ -17584,7 +17595,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/nvidia-ml-py?source=compressed-mapping + - pkg:pypi/nvidia-ml-py?source=hash-mapping size: 50107 timestamp: 1780355713540 - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda @@ -18014,7 +18025,7 @@ packages: license: MPL-2.0 license_family: OTHER purls: - - pkg:pypi/pytest-rerunfailures?source=compressed-mapping + - pkg:pypi/pytest-rerunfailures?source=hash-mapping size: 21401 timestamp: 1779715182649 - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda @@ -18430,6 +18441,9 @@ packages: license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + strong: + - __glibc >=2.28,<3.0.a0 size: 24008591 timestamp: 1765578833462 - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda @@ -18442,6 +18456,9 @@ packages: license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + strong: + - __glibc >=2.28,<3.0.a0 size: 23644746 timestamp: 1765578629426 - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda @@ -18588,7 +18605,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/wcwidth?source=compressed-mapping + - pkg:pypi/wcwidth?source=hash-mapping size: 136960 timestamp: 1780736911642 - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.8-pyhcf101f3_0.conda @@ -34839,77 +34856,14 @@ packages: license: LicenseRef-openrail size: 244991335 timestamp: 1771976595791 -- conda_source: bitbots_rust_nav[218786e9] @ src/bitbots_navigation/bitbots_rust_nav - variants: - target_platform: linux-64 - depends: - - python >=3.12 - - python_abi 3.12.* *_cp312 - constrains: - - __glibc >=2.17 - - __glibc >=2.17 - build_packages: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.45.1-default_h4852527_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-15.2.0-h7be306e_25.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.95.0-h53717f1_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rust_linux-64-1.95.0-hb4ea61c_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.95.0-h2c6d0dc_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - host_packages: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.2-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.13.3-py310h2b5ca13_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.91.1-h53717f1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.19-h26efc2c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.91.1-h2c6d0dc_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda -- conda_source: bitbots_rust_nav[de420e0b] @ src/bitbots_navigation/bitbots_rust_nav +- conda_source: bitbots_rust_nav[77771cb3] @ src/bitbots_navigation/bitbots_rust_nav variants: + c_stdlib: sysroot + c_stdlib_version: '2.28' target_platform: linux-aarch64 depends: - python >=3.12 + - __glibc >=2.28,<3.0.a0 - python_abi 3.12.* *_cp312 constrains: - __glibc >=2.17 @@ -34972,6 +34926,75 @@ packages: - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda +- conda_source: bitbots_rust_nav[eb738ce2] @ src/bitbots_navigation/bitbots_rust_nav + variants: + c_stdlib: sysroot + c_stdlib_version: '2.28' + target_platform: linux-64 + depends: + - python >=3.12 + - __glibc >=2.28,<3.0.a0 + - python_abi 3.12.* *_cp312 + constrains: + - __glibc >=2.17 + - __glibc >=2.17 + build_packages: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.45.1-default_h4852527_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-15.2.0-h7be306e_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.95.0-h53717f1_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust_linux-64-1.95.0-hb4ea61c_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.95.0-h2c6d0dc_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + host_packages: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.2-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.13.3-py310h2b5ca13_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.91.1-h53717f1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.19-h26efc2c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.91.1-h2c6d0dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl name: trimesh version: 4.12.2 diff --git a/src/bitbots_behavior/bitbots_blackboard/CMakeLists.txt b/src/bitbots_behavior/bitbots_blackboard/CMakeLists.txt index 9ae643437..5d6a26340 100644 --- a/src/bitbots_behavior/bitbots_blackboard/CMakeLists.txt +++ b/src/bitbots_behavior/bitbots_blackboard/CMakeLists.txt @@ -12,6 +12,11 @@ if(BUILD_TESTING) ament_mypy(CONFIG_FILE "${CMAKE_CURRENT_LIST_DIR}/mypy.ini") endif() +install(DIRECTORY + scripts/ USE_SOURCE_PERMISSIONS + DESTINATION lib/${PROJECT_NAME} +) + ament_python_install_package(${PROJECT_NAME}) ament_package() diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index a3c56661f..fe2e2085d 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -70,10 +70,6 @@ class Params: class PositioningCapsule(AbstractBlackboardCapsule): """Decides and communicates the optimal positions, based on the game situation.""" - # --------------------------------------------------------------------------- # - # Config - # --------------------------------------------------------------------------- # - def __init__(self, node, blackboard): super().__init__(node, blackboard) @@ -95,6 +91,33 @@ def __init__(self, node, blackboard): ) self._params = Params() + self._inner = InnerPositioningCapsule(self._field, self._params) + + @cached_capsule_function + def get_formation_assignment(self) -> dict: + ballPose = self._blackboard.world_model.get_best_ball_point_stamped() + ball = np.array([ballPose.point.x, ballPose.point.y]) + robot_poses = self._blackboard.team_data.get_robot_poses() + self._node.get_logger().info(f"Length of robot_poses: {len(robot_poses)}") + + formation = self._inner._compute_formation(ball, self._field, len(robot_poses), self._params) + new_items = list(formation.items()) + ordered_jerseys = sorted(robot_poses.keys()) + old_poses = [robot_poses[j] for j in ordered_jerseys] + pairs = self._inner._match_assignment(old_poses, new_items, ball) + + result = {} + for jersey, old_pose in zip(ordered_jerseys, [robot_poses[j] for j in ordered_jerseys]): + for ap, new_pose, role in pairs: + if np.allclose(np.asarray(ap), np.asarray(old_pose)): + result[jersey] = {"role": role, "goal_pose": np.asarray(new_pose)} + break + return result + + +class InnerPositioningCapsule: + """Pure & deterministic formation computation, independent of ROS and the rest of the system.""" + # --------------------------------------------------------------------------- # # Helpers # --------------------------------------------------------------------------- # @@ -371,24 +394,3 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) head[role] = self._face(p, B) # goalie + defenders face the ball return {role: np.array([p[0], p[1], head[role]]) for role, p in out.items()} - - @cached_capsule_function - def get_formation_assignment(self) -> dict: - ballPose = self._blackboard.world_model.get_best_ball_point_stamped() - ball = np.array([ballPose.point.x, ballPose.point.y]) - robot_poses = self._blackboard.team_data.get_robot_poses() - self._node.get_logger().info(f"Length of robot_poses: {len(robot_poses)}") - - formation = self._compute_formation(ball, self._field, len(robot_poses), self._params) - new_items = list(formation.items()) - ordered_jerseys = sorted(robot_poses.keys()) - old_poses = [robot_poses[j] for j in ordered_jerseys] - pairs = self._match_assignment(old_poses, new_items, ball) - - result = {} - for jersey, old_pose in zip(ordered_jerseys, [robot_poses[j] for j in ordered_jerseys]): - for ap, new_pose, role in pairs: - if np.allclose(np.asarray(ap), np.asarray(old_pose)): - result[jersey] = {"role": role, "goal_pose": np.asarray(new_pose)} - break - return result diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py new file mode 100755 index 000000000..e106c3b8b --- /dev/null +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +"""Debug GUI for InnerPositioningCapsule. + +Exercises the exact capsule code without starting the full stack. +Click the field to move the ball; use the sliders to tweak params. +""" + +import numpy as np + +from bitbots_blackboard.capsules.positioning_capsule import Field, InnerPositioningCapsule, Params + +_inner = InnerPositioningCapsule() + + +def run_gui(): + import matplotlib.pyplot as plt + from matplotlib.patches import Circle, Rectangle + from matplotlib.widgets import Slider + + fld = Field() + params = Params() + state = {"ball": np.array([1.0, 0.5]), "n": 5, "prev": None} + + colors = {"goalie": "#e6b800", "striker": "#d62728", "supporter": "#2ca02c"} + + fig, ax = plt.subplots(figsize=(9, 9)) + plt.subplots_adjust(left=0.08, right=0.97, top=0.98, bottom=0.50) + + def _ax(b): + return plt.axes([0.18, b, 0.72, 0.015]) + + s_n = Slider(_ax(0.470), "players", 1, 8, valinit=state["n"], valstep=1) + s_sep = Slider(_ax(0.435), "min_sep", 0.3, 2.0, valinit=params.min_sep) + s_alpha = Slider(_ax(0.400), "push α", 0.1, 0.8, valinit=params.alpha) + s_dbias = Slider(_ax(0.365), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) + s_dside = Slider(_ax(0.330), "def side", 0.0, 2.0, valinit=params.def_side) + s_gap = Slider(_ax(0.295), "def gap", 0.5, 2.0, valinit=params.gap) + s_f = Slider(_ax(0.260), "supp lead", 0.0, 3.0, valinit=params.f) + s_side = Slider(_ax(0.225), "supp side", 0.0, 2.5, valinit=params.supp_side) + s_smax = Slider(_ax(0.190), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) + s_pmarg = Slider(_ax(0.155), "post margin", 0.0, 1.3, valinit=params.post_margin) + s_back = Slider(_ax(0.120), "back dist", 0.0, 3.0, valinit=params.back_dist) + s_kclr = Slider(_ax(0.085), "kick clear", 0.0, 1.5, valinit=params.kick_clear) + s_gout = Slider(_ax(0.050), "goalie out", 0.2, 2.0, valinit=params.d_g) + + def draw(): + ax.clear() + ax.add_patch( + Rectangle((-fld.length / 2, -fld.width / 2), fld.length, fld.width, fill=False, color="white", lw=2) + ) + ax.axvline(0, color="white", lw=1) + ax.add_patch(Circle((0, 0), 0.75, fill=False, color="white", lw=1)) + for sgn in (-1, 1): + ax.plot( + [sgn * fld.length / 2] * 2, + [-fld.goal_width / 2, fld.goal_width / 2], + color="#4da6ff" if sgn < 0 else "#ff9999", + lw=6, + ) + ax.set_facecolor("#2e7d32") + + params.min_sep, params.alpha, params.gap, params.f = s_sep.val, s_alpha.val, s_gap.val, s_f.val + params.depth_bias, params.supp_side, params.d_g = s_dbias.val, s_side.val, s_gout.val + params.supp_max_x, params.def_side = s_smax.val, s_dside.val + params.post_margin, params.back_dist = s_pmarg.val, s_back.val + params.kick_clear = s_kclr.val + n = int(s_n.val) + + form = _inner._compute_formation(state["ball"], fld, n, params) + new_items = list(form.items()) + + prev = state["prev"] + if prev is not None and len(prev) == len(new_items): + for old_pose, new_pose, role in _inner._match_assignment(prev, new_items, state["ball"]): + c = colors.get(role.split("_")[0], "#1f77b4") + ax.plot([old_pose[0], new_pose[0]], [old_pose[1], new_pose[1]], ls=":", color=c, lw=1.5, zorder=3) + ax.add_patch(Circle(old_pose[:2], 0.10, color=c, alpha=0.55, zorder=4)) + state["prev"] = [pose for _role, pose in new_items] + + ax.add_patch(Circle(state["ball"], 0.12, color="white", ec="black", zorder=5)) + if "striker" in form: + th = form["striker"][2] + aim = np.array([np.cos(th), np.sin(th)]) + perp = np.array([-aim[1], aim[0]]) + b = np.asarray(state["ball"]) + far = b + params.kick_range * aim + corner = perp * params.kick_clear + lane = np.array([b + corner, far + corner, far - corner, b - corner]) + ax.add_patch(plt.Polygon(lane, closed=True, color="white", alpha=0.10, zorder=1)) + ax.arrow( + *state["ball"], + *(1.4 * aim), + color="white", + width=0.02, + head_width=0.18, + length_includes_head=True, + zorder=8, + alpha=0.9, + ) + for role, pose in form.items(): + p, th = pose[:2], pose[2] + base = role.split("_")[0] + c = colors.get(base, "#1f77b4") + ax.add_patch(Circle(p, params.min_sep / 2, color=c, alpha=0.18, zorder=2)) + ax.add_patch(Circle(p, 0.16, color=c, ec="black", zorder=6)) + ax.plot( + [p[0], p[0] + 0.45 * np.cos(th)], + [p[1], p[1] + 0.45 * np.sin(th)], + color="black", + lw=2.5, + zorder=7, + solid_capstyle="round", + ) + ax.annotate( + role.replace("defender_", "D").replace("supporter", "supp"), + p, + color="white", + fontsize=8, + ha="center", + va="center", + zorder=8, + ) + + ax.set_xlim(-fld.length / 2 - 0.5, fld.length / 2 + 0.5) + ax.set_ylim(-fld.width / 2 - 0.5, fld.width / 2 + 0.5) + ax.set_aspect("equal") + ax.set_title("click to move the ball · dots = previous assignment (dotted = who moves where)", color="black") + fig.canvas.draw_idle() + + def on_click(event): + if event.inaxes is ax and event.xdata is not None: + state["ball"] = np.array([event.xdata, event.ydata]) + draw() + + for s in (s_n, s_sep, s_alpha, s_dbias, s_dside, s_gap, s_f, s_side, s_smax, s_pmarg, s_back, s_kclr, s_gout): + s.on_changed(lambda _v: draw()) + fig.canvas.mpl_connect("button_press_event", on_click) + draw() + plt.show() + + +def main(): + run_gui() + + +if __name__ == "__main__": + main() From 49ed7aa7e21d43033d57b56412971704b5a24b6a Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Mon, 29 Jun 2026 16:50:07 +0200 Subject: [PATCH 11/68] Delete redundant file Signed-off-by: Florian Vahl --- formation_prototype.py | 476 ----------------------------------------- 1 file changed, 476 deletions(-) delete mode 100644 formation_prototype.py diff --git a/formation_prototype.py b/formation_prototype.py deleted file mode 100644 index 5c443bc5e..000000000 --- a/formation_prototype.py +++ /dev/null @@ -1,476 +0,0 @@ -#!/usr/bin/env python3 -""" -Defensive formation prototype. - -A single pure function `compute_formation(ball, field, n_players, params)` maps a -ball position to positions for every non-... well, *every* role (goalie, defenders, -supporter, striker), and a small matplotlib GUI to click a ball and watch the result. - -Core idea ---------- -Everything keys off two vectors derived from the ball B and our goal centre G: - - to_ball = normalize(B - G) # axis pointing from our goal out to the ball - perp = (-to_ball.y, to_ball.x) # perpendicular to that axis - -Defenders sit ON the axis (at a controlled depth from goal) and spread ALONG perp. -As the ball moves the axis rotates, so the same construction continuously morphs -from a horizontal defensive line (ball far/central) into a goal-line wall beside -the goalie (ball close & frontal). No special-casing -> automatically smooth. - -A short pairwise-repulsion pass at the end enforces a minimum separation; it is -also what shoves the defenders sideways into clean flanking slots when they would -otherwise pile onto the goalie -> the "wall next to the goalie" emerges for free. -""" - -from dataclasses import dataclass - -import numpy as np - - -# --------------------------------------------------------------------------- # -# Config + tunables -# --------------------------------------------------------------------------- # -@dataclass -class Field: - length: float = 9.0 # x extent (own goal at -length/2, opp goal at +length/2) - width: float = 6.0 # y extent - goal_width: float = 2.6 # goal mouth - margin: float = 0.3 # keep field players this far inside the touchlines - - -@dataclass -class Params: - # goalie - d_g: float = 0.55 # how far the goalie comes out of the goal (dist from goal centre) - # defenders - alpha: float = 0.42 # defender depth as a fraction of |ball-goal| (push-up factor) - depth_bias: float = 0.0 # extra defender depth: + = further forward, - = further back - D_min: float = 0.9 # min defender depth from goal (never tuck behind this) - D_max: float = 3.8 # max defender depth from goal (high-line cap) - dz: float = 0.45 # keep defenders at least this far ahead of the goalie - standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball - gap: float = 1.1 # lateral spacing between adjacent defenders - def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) - # supporter - f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits - supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) - supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) - # striker - kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) - post_margin: float = 0.45 # safety margin inside each goal post for a straight shot - back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side - # separation - min_sep: float = 0.8 # no two robots closer than this - sep_iters: int = 8 - # kick lane: keep teammates out of the corridor in front of the ball - kick_clear: float = 0.7 # half-width of the cleared corridor - kick_range: float = 3.0 # how far in front of the ball the corridor extends - - -# --------------------------------------------------------------------------- # -# Helpers -# --------------------------------------------------------------------------- # -def _normalize(v, fallback=np.array([1.0, 0.0])): - n = np.linalg.norm(v) - return v / n if n > 1e-9 else fallback.copy() - - -def _face(frm, to, fallback=0.0): - """Heading (rad) to look from `frm` toward `to`.""" - d = np.asarray(to) - np.asarray(frm) - return np.arctan2(d[1], d[0]) if np.linalg.norm(d) > 1e-9 else fallback - - -def _smoothstep(x, lo, hi): - """C1 ramp from 0 (x<=lo) to 1 (x>=hi).""" - if hi <= lo: - return float(x >= hi) - t = np.clip((x - lo) / (hi - lo), 0.0, 1.0) - return t * t * (3 - 2 * t) - - -def _angle_diff(a, b): - """Smallest absolute angle between two headings (rad), in [0, pi].""" - return abs((a - b + np.pi) % (2 * np.pi) - np.pi) - - -def match_assignment(old_poses, new_items, ball, angle_w=0.3): - """Assign physical robots (at `old_poses`) to the new target poses. - - The robot closest to the ball always takes the striker target; the rest are - matched optimally (Hungarian) to minimise total cost = distance + angle_w * - heading difference. Returns a list of (old_pose, new_pose, new_role). - `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). - """ - from scipy.optimize import linear_sum_assignment - - old_poses = [np.asarray(p) for p in old_poses] - ball = np.asarray(ball) - n = len(old_poses) - - # striker target -> the old robot nearest the ball - s_j = next(j for j, (r, _) in enumerate(new_items) if r == "striker") - s_i = min(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) - pairs = [(old_poses[s_i], new_items[s_j][1], new_items[s_j][0])] - - rem_i = [i for i in range(n) if i != s_i] - rem_j = [j for j in range(len(new_items)) if j != s_j] - if rem_i: - cost = np.empty((len(rem_i), len(rem_j))) - for a, i in enumerate(rem_i): - for b, j in enumerate(rem_j): - op, npose = old_poses[i], new_items[j][1] - cost[a, b] = np.linalg.norm(op[:2] - npose[:2]) + angle_w * _angle_diff(op[2], npose[2]) - ri, ci = linear_sum_assignment(cost) - for a, b in zip(ri, ci): - i, j = rem_i[a], rem_j[b] - pairs.append((old_poses[i], new_items[j][1], new_items[j][0])) - return pairs - - -def _clamp_field(p, fld, margin=None): - """Clamp a point to the playable rectangle (continuous / C0).""" - m = fld.margin if margin is None else margin - return np.array( - [ - np.clip(p[0], -fld.length / 2 + m, fld.length / 2 - m), - np.clip(p[1], -fld.width / 2 + m, fld.width / 2 - m), - ] - ) - - -def _allocate_roles(n, ball=None, field=None): - """Keep-priority as the count drops: striker > goalie > 1st defender > supporter - > 2nd defender (and any further players are extra defenders). - - Equivalently, removing players one at a time drops: a defender, then the - supporter, then the other defender, then the goalie. - - Short-handed (n < 5) with the ball in our own defensive third, the supporter - is reassigned as an extra defender (note: this is a discrete role switch). - """ - n_def = 0 - has_support = False - if n >= 3: - n_def += 1 # first defender - if n >= 4: - has_support = True # supporter - n_def += max(n - 4, 0) # everyone past 4 is another defender - - if has_support and n < 5 and ball is not None and field is not None: - own_third = -field.length / 2 + field.length / 3.0 - if ball[0] < own_third: - has_support, n_def = False, n_def + 1 - - roles = [] - if n >= 1: - roles.append("striker") - if n >= 2: - roles.append("goalie") - roles += [f"defender_{i}" for i in range(n_def)] - if has_support: - roles.append("supporter") - return roles - - -# --------------------------------------------------------------------------- # -# The pure function -# --------------------------------------------------------------------------- # -def compute_formation(ball, field: Field, n_players: int, params: Params): - """Map a ball position -> {role_name: np.array([x, y])}. Pure & deterministic.""" - B = np.asarray(ball, dtype=float) - G = np.array([-field.length / 2.0, 0.0]) - opp = np.array([+field.length / 2.0, 0.0]) - - d = np.linalg.norm(B - G) - to_ball = _normalize(B - G) # our-goal -> ball - perp = np.array([-to_ball[1], to_ball[0]]) - - roles = _allocate_roles(n_players, B, field) - out = {} - head = {} # role -> heading (rad); filled lazily, completed after separation - kick_aim = None # striker's kick direction; used to clear the kick lane - - # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # - if "striker" in roles: - h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth - # aim at the goal, target clamped into the safe mouth: this gives a straight - # (+x) shot whenever the ball is aligned within the posts, angled otherwise - target = np.array([opp[0], np.clip(B[1], -h, h)]) - aim_goal = _normalize(target - B) - # fallback: play back toward our side (field centre) - aim_back = _normalize(np.array([0.0, 0.0]) - B, fallback=np.array([-1.0, 0.0])) - # blend to back-pass only when close to the opp goal AND not aligned - near_goal = _smoothstep(B[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) - not_aligned = _smoothstep(abs(B[1]), h, h + 1.0) - w_back = near_goal * not_aligned - # rotate the aim around the ball at constant angular rate (shortest path) so - # the striker swings smoothly rather than whipping when the two aims oppose - a0 = np.arctan2(aim_goal[1], aim_goal[0]) - a1 = np.arctan2(aim_back[1], aim_back[0]) - da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn - ang = a0 + w_back * da - aim = np.array([np.cos(ang), np.sin(ang)]) - out["striker"] = B - params.kick_offset * aim - head["striker"] = ang # striker faces where it kicks - kick_aim = aim - - # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # - if "goalie" in roles: - g = G + params.d_g * to_ball - g = np.array( - [ - np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), - np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), - ] - ) - out["goalie"] = g - - # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # - defender_roles = [r for r in roles if r.startswith("defender_")] - m = len(defender_roles) - if m > 0: - D = np.clip( - params.alpha * d + params.depth_bias, # push up + fwd/back bias - params.D_min, - params.D_max, - ) - D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball - D = max(D, params.d_g + params.dz) # stay ahead of the goalie - anchor = G + D * to_ball - if m == 1: - # a single defender: shade to the centre side so it doesn't sit on the - # striker<->goalie line (otherwise all three are collinear) - side_dir = -1.0 if B[1] >= 0 else 1.0 - offsets = [params.def_side * side_dir] - else: - offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] - for r, off in zip(defender_roles, offsets): - out[r] = _clamp_field(anchor + off * perp, field) - - # --- supporter: slightly in front of the ball, kept inside the field -------- # - if "supporter" in roles: - # always sit to the centre side of the ball; hard swap so it is never - # directly in front of the striker, even when the ball is on the centre line - side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) - sup = B + np.array([params.f, params.supp_side * side_dir]) - sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner - out["supporter"] = _clamp_field(sup, field) - - # --- min-separation repulsion + kick-lane clearance ----------------------- # - _separate(out, field, params, B, kick_aim) - - # --- orientations (computed from the final positions) --------------------- # - for role, p in out.items(): - if role in head: - continue # striker already set (faces its kick aim) - if role == "supporter": - # face the bisector of (toward ball, toward opp goal): "watch both" - bis = _normalize(B - p) + _normalize(opp - p) - head[role] = _face(np.zeros(2), bis, fallback=_face(p, opp)) - else: - head[role] = _face(p, B) # goalie + defenders face the ball - - return {role: np.array([p[0], p[1], head[role]]) for role, p in out.items()} - - -def _separate(positions: dict, field: Field, params: Params, ball=None, aim=None): - """In-place relaxation: pairwise min-sep + clearing the striker's kick lane. - - Only the striker is a fixed anchor (it must reach the ball); everyone else, - goalie included, gives way around it. In normal play the goalie is far from - all teammates so it never moves; it only shifts off its line in the degenerate - case where the ball sits right in the goal mouth. Continuous in the inputs, - so small ball moves -> small position moves. - - If `ball`/`aim` are given, teammates inside the corridor in front of the ball - (along the kick direction) are pushed sideways out of it so they don't block - the kick; the push tapers in/out along the corridor to stay smooth. - """ - fixed = {"striker"} - names = list(positions.keys()) - sep = params.min_sep - # model the kick corridor as a row of fixed repulsors along the aim, each with - # keep-out radius kick_clear: radial pushes are smooth (no side-flip teleport) - lane_pts, perp = [], None - if aim is not None and ball is not None: - perp = np.array([-aim[1], aim[0]]) - step = max(params.kick_clear * 0.7, 0.3) - lane_pts = [np.asarray(ball) + s * aim for s in np.arange(step, params.kick_range + 1e-9, step)] - for _ in range(params.sep_iters): - disp = {n: np.zeros(2) for n in names} - for i in range(len(names)): - for j in range(i + 1, len(names)): - a, b = names[i], names[j] - diff = positions[a] - positions[b] - dist = np.linalg.norm(diff) - if dist < sep: - dirv = _normalize(diff, np.array([0.0, 1.0])) if dist > 1e-6 else np.array([0.0, 1.0]) - overlap = sep - dist - a_fixed, b_fixed = a in fixed, b in fixed - if a_fixed and b_fixed: - continue - if a_fixed: - disp[b] -= overlap * dirv - elif b_fixed: - disp[a] += overlap * dirv - else: - disp[a] += 0.5 * overlap * dirv - disp[b] -= 0.5 * overlap * dirv - # push teammates out of the kick corridor in front of the ball - for n in names: - if n in fixed: - continue - for lp in lane_pts: - diff = positions[n] - lp - dist = np.linalg.norm(diff) - if dist < params.kick_clear: - dirv = _normalize(diff, perp) # exactly on the line -> step sideways - disp[n] += (params.kick_clear - dist) * dirv - for n in names: - if n in fixed: - continue - positions[n] = _clamp_field(positions[n] + disp[n], field) - - -# --------------------------------------------------------------------------- # -# GUI -# --------------------------------------------------------------------------- # -def run_gui(): - import matplotlib.pyplot as plt - from matplotlib.patches import Circle, Rectangle - from matplotlib.widgets import Slider - - fld = Field() - params = Params() - state = {"ball": np.array([1.0, 0.5]), "n": 5, "prev": None} - - colors = {"goalie": "#e6b800", "striker": "#d62728", "supporter": "#2ca02c"} - - fig, ax = plt.subplots(figsize=(9, 9)) - plt.subplots_adjust(left=0.08, right=0.97, top=0.98, bottom=0.50) - - # sliders (stacked bottom -> top) - def _ax(b): - return plt.axes([0.18, b, 0.72, 0.015]) - - s_n = Slider(_ax(0.470), "players", 1, 8, valinit=state["n"], valstep=1) - s_sep = Slider(_ax(0.435), "min_sep", 0.3, 2.0, valinit=params.min_sep) - s_alpha = Slider(_ax(0.400), "push α", 0.1, 0.8, valinit=params.alpha) - s_dbias = Slider(_ax(0.365), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) - s_dside = Slider(_ax(0.330), "def side", 0.0, 2.0, valinit=params.def_side) - s_gap = Slider(_ax(0.295), "def gap", 0.5, 2.0, valinit=params.gap) - s_f = Slider(_ax(0.260), "supp lead", 0.0, 3.0, valinit=params.f) - s_side = Slider(_ax(0.225), "supp side", 0.0, 2.5, valinit=params.supp_side) - s_smax = Slider(_ax(0.190), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) - s_pmarg = Slider(_ax(0.155), "post margin", 0.0, 1.3, valinit=params.post_margin) - s_back = Slider(_ax(0.120), "back dist", 0.0, 3.0, valinit=params.back_dist) - s_kclr = Slider(_ax(0.085), "kick clear", 0.0, 1.5, valinit=params.kick_clear) - s_gout = Slider(_ax(0.050), "goalie out", 0.2, 2.0, valinit=params.d_g) - - def draw(): - ax.clear() - # pitch - ax.add_patch( - Rectangle((-fld.length / 2, -fld.width / 2), fld.length, fld.width, fill=False, color="white", lw=2) - ) - ax.axvline(0, color="white", lw=1) - ax.add_patch(Circle((0, 0), 0.75, fill=False, color="white", lw=1)) - for sgn in (-1, 1): # goals - ax.plot( - [sgn * fld.length / 2] * 2, - [-fld.goal_width / 2, fld.goal_width / 2], - color="#4da6ff" if sgn < 0 else "#ff9999", - lw=6, - ) - ax.set_facecolor("#2e7d32") - - params.min_sep, params.alpha, params.gap, params.f = s_sep.val, s_alpha.val, s_gap.val, s_f.val - params.depth_bias, params.supp_side, params.d_g = s_dbias.val, s_side.val, s_gout.val - params.supp_max_x, params.def_side = s_smax.val, s_dside.val - params.post_margin, params.back_dist = s_pmarg.val, s_back.val - params.kick_clear = s_kclr.val - n = int(s_n.val) - - form = compute_formation(state["ball"], fld, n, params) - new_items = list(form.items()) - - # match the previous assignment to the new targets and draw the transition - prev = state["prev"] - if prev is not None and len(prev) == len(new_items): - for old_pose, new_pose, role in match_assignment(prev, new_items, state["ball"]): - c = colors.get(role.split("_")[0], "#1f77b4") - ax.plot([old_pose[0], new_pose[0]], [old_pose[1], new_pose[1]], ls=":", color=c, lw=1.5, zorder=3) - ax.add_patch(Circle(old_pose[:2], 0.10, color=c, alpha=0.55, zorder=4)) - # this assignment becomes the "previous" for the next click - state["prev"] = [pose for _role, pose in new_items] - - # ball - ax.add_patch(Circle(state["ball"], 0.12, color="white", ec="black", zorder=5)) - # striker kick-aim arrow (the striker faces this way) + cleared corridor - if "striker" in form: - th = form["striker"][2] - aim = np.array([np.cos(th), np.sin(th)]) - perp = np.array([-aim[1], aim[0]]) - b = np.asarray(state["ball"]) - far = b + params.kick_range * aim - corner = perp * params.kick_clear - lane = np.array([b + corner, far + corner, far - corner, b - corner]) - ax.add_patch(plt.Polygon(lane, closed=True, color="white", alpha=0.10, zorder=1)) - ax.arrow( - *state["ball"], - *(1.4 * aim), - color="white", - width=0.02, - head_width=0.18, - length_includes_head=True, - zorder=8, - alpha=0.9, - ) - # robots (pose = [x, y, heading]) - for role, pose in form.items(): - p, th = pose[:2], pose[2] - base = role.split("_")[0] - c = colors.get(base, "#1f77b4") # defenders blue - ax.add_patch(Circle(p, params.min_sep / 2, color=c, alpha=0.18, zorder=2)) - ax.add_patch(Circle(p, 0.16, color=c, ec="black", zorder=6)) - # heading indicator - ax.plot( - [p[0], p[0] + 0.45 * np.cos(th)], - [p[1], p[1] + 0.45 * np.sin(th)], - color="black", - lw=2.5, - zorder=7, - solid_capstyle="round", - ) - ax.annotate( - role.replace("defender_", "D").replace("supporter", "supp"), - p, - color="white", - fontsize=8, - ha="center", - va="center", - zorder=8, - ) - - ax.set_xlim(-fld.length / 2 - 0.5, fld.length / 2 + 0.5) - ax.set_ylim(-fld.width / 2 - 0.5, fld.width / 2 + 0.5) - ax.set_aspect("equal") - ax.set_title("click to move the ball · dots = previous assignment (dotted = who moves where)", color="black") - fig.canvas.draw_idle() - - def on_click(event): - if event.inaxes is ax and event.xdata is not None: - state["ball"] = np.array([event.xdata, event.ydata]) - draw() - - for s in (s_n, s_sep, s_alpha, s_dbias, s_dside, s_gap, s_f, s_side, s_smax, s_pmarg, s_back, s_kclr, s_gout): - s.on_changed(lambda _v: draw()) - fig.canvas.mpl_connect("button_press_event", on_click) - draw() - plt.show() - - -if __name__ == "__main__": - run_gui() From 6d616d61aa394b24f78228c990fd87ce29735092 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Mon, 29 Jun 2026 18:26:15 +0200 Subject: [PATCH 12/68] Add freekick mode Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 70 +++++++++++++------ .../scripts/debug_positioning.py | 36 ++++++---- 2 files changed, 70 insertions(+), 36 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index fe2e2085d..9492d3fd6 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -58,13 +58,16 @@ class Params: # striker kick_offset: float = 0.25 # striker stands this far behind the ball (to push it forward) post_margin: float = 0.45 # safety margin inside each goal post for a straight shot - back_dist: float = 1.0 # within this x of the opp goal & not aligned -> play back to our side + back_dist: float = 0.21 # within this x of the opp goal & not aligned -> play back to our side # separation min_sep: float = 0.8 # no two robots closer than this sep_iters: int = 8 # kick lane: keep teammates out of the corridor in front of the ball kick_clear: float = 0.7 # half-width of the cleared corridor kick_range: float = 3.0 # how far in front of the ball the corridor extends + # opponent free kick / goal kick / penalty: keep all robots outside this radius + freekick: bool = False + freekick_clearance: float = 0.75 class PositioningCapsule(AbstractBlackboardCapsule): @@ -257,6 +260,16 @@ def _separate(self, positions: dict, field: Field, params: Params, ball=None, ai continue positions[n] = self._clamp_field(positions[n] + disp[n], field) + def _clear_ball(self, positions: dict, ball, radius: float, field: Field): + """Push all robots to at least `radius` distance from `ball` (in-place).""" + ball = np.asarray(ball) + for name in positions: + diff = positions[name] - ball + dist = np.linalg.norm(diff) + if dist < radius: + dirv = self._normalize(diff, fallback=np.array([-1.0, 0.0])) + positions[name] = self._clamp_field(ball + radius * dirv, field) + # --------------------------------------------------------------------------- # # Assignment # --------------------------------------------------------------------------- # @@ -309,33 +322,42 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) perp = np.array([-to_ball[1], to_ball[0]]) roles = self._allocate_roles(n_players, B, field) + if params.freekick and "supporter" in roles: + n_def = sum(1 for r in roles if r.startswith("defender_")) + roles[roles.index("supporter")] = f"defender_{n_def}" out = {} head = {} # role -> heading (rad); filled lazily, completed after separation kick_aim = None # striker's kick direction; used to clear the kick lane # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # if "striker" in roles: - h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth - # aim at the goal, target clamped into the safe mouth: this gives a straight - # (+x) shot whenever the ball is aligned within the posts, angled otherwise - target = np.array([opp[0], np.clip(B[1], -h, h)]) - aim_goal = self._normalize(target - B) - # fallback: play back toward our side (field centre) - aim_back = self._normalize(np.array([0.0, 0.0]) - B, fallback=np.array([-1.0, 0.0])) - # blend to back-pass only when close to the opp goal AND not aligned - near_goal = self._smoothstep(B[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) - not_aligned = self._smoothstep(abs(B[1]), h, h + 1.0) - w_back = near_goal * not_aligned - # rotate the aim around the ball at constant angular rate (shortest path) so - # the striker swings smoothly rather than whipping when the two aims oppose - a0 = np.arctan2(aim_goal[1], aim_goal[0]) - a1 = np.arctan2(aim_back[1], aim_back[0]) - da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn - ang = a0 + w_back * da - aim = np.array([np.cos(ang), np.sin(ang)]) - out["striker"] = B - params.kick_offset * aim - head["striker"] = ang # striker faces where it kicks - kick_aim = aim + if params.freekick: + # park at the clearance boundary on the goal side, facing the ball + dir_to_goal = self._normalize(G - B, fallback=np.array([-1.0, 0.0])) + out["striker"] = self._clamp_field(B + params.freekick_clearance * dir_to_goal, field) + # heading will be computed in the orientation pass (face ball) + else: + h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth + # aim at the goal, target clamped into the safe mouth: this gives a straight + # (+x) shot whenever the ball is aligned within the posts, angled otherwise + target = np.array([opp[0], np.clip(B[1], -h, h)]) + aim_goal = self._normalize(target - B) + # fallback: play back toward our side (field centre) + aim_back = self._normalize(np.array([0.0, 0.0]) - B, fallback=np.array([-1.0, 0.0])) + # blend to back-pass only when close to the opp goal AND not aligned + near_goal = self._smoothstep(B[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) + not_aligned = self._smoothstep(abs(B[1]), h, h + 1.0) + w_back = near_goal * not_aligned + # rotate the aim around the ball at constant angular rate (shortest path) so + # the striker swings smoothly rather than whipping when the two aims oppose + a0 = np.arctan2(aim_goal[1], aim_goal[0]) + a1 = np.arctan2(aim_back[1], aim_back[0]) + da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn + ang = a0 + w_back * da + aim = np.array([np.cos(ang), np.sin(ang)]) + out["striker"] = B - params.kick_offset * aim + head["striker"] = ang # striker faces where it kicks + kick_aim = aim # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # if "goalie" in roles: @@ -382,6 +404,10 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) # --- min-separation repulsion + kick-lane clearance ----------------------- # self._separate(out, field, params, B, kick_aim) + # --- freekick: push every robot outside the mandatory clearance radius ---- # + if params.freekick: + self._clear_ball(out, B, params.freekick_clearance, field) + # --- orientations (computed from the final positions) --------------------- # for role, p in out.items(): if role in head: diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index e106c3b8b..a48154b21 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -15,7 +15,7 @@ def run_gui(): import matplotlib.pyplot as plt from matplotlib.patches import Circle, Rectangle - from matplotlib.widgets import Slider + from matplotlib.widgets import CheckButtons, Slider fld = Field() params = Params() @@ -30,18 +30,20 @@ def _ax(b): return plt.axes([0.18, b, 0.72, 0.015]) s_n = Slider(_ax(0.470), "players", 1, 8, valinit=state["n"], valstep=1) - s_sep = Slider(_ax(0.435), "min_sep", 0.3, 2.0, valinit=params.min_sep) - s_alpha = Slider(_ax(0.400), "push α", 0.1, 0.8, valinit=params.alpha) - s_dbias = Slider(_ax(0.365), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) - s_dside = Slider(_ax(0.330), "def side", 0.0, 2.0, valinit=params.def_side) - s_gap = Slider(_ax(0.295), "def gap", 0.5, 2.0, valinit=params.gap) - s_f = Slider(_ax(0.260), "supp lead", 0.0, 3.0, valinit=params.f) - s_side = Slider(_ax(0.225), "supp side", 0.0, 2.5, valinit=params.supp_side) - s_smax = Slider(_ax(0.190), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) - s_pmarg = Slider(_ax(0.155), "post margin", 0.0, 1.3, valinit=params.post_margin) - s_back = Slider(_ax(0.120), "back dist", 0.0, 3.0, valinit=params.back_dist) - s_kclr = Slider(_ax(0.085), "kick clear", 0.0, 1.5, valinit=params.kick_clear) - s_gout = Slider(_ax(0.050), "goalie out", 0.2, 2.0, valinit=params.d_g) + s_sep = Slider(_ax(0.440), "min_sep", 0.3, 2.0, valinit=params.min_sep) + s_alpha = Slider(_ax(0.410), "push α", 0.1, 0.8, valinit=params.alpha) + s_dbias = Slider(_ax(0.380), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) + s_dside = Slider(_ax(0.350), "def side", 0.0, 2.0, valinit=params.def_side) + s_gap = Slider(_ax(0.320), "def gap", 0.5, 2.0, valinit=params.gap) + s_f = Slider(_ax(0.290), "supp lead", 0.0, 3.0, valinit=params.f) + s_side = Slider(_ax(0.260), "supp side", 0.0, 2.5, valinit=params.supp_side) + s_smax = Slider(_ax(0.230), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) + s_pmarg = Slider(_ax(0.200), "post margin", 0.0, 1.3, valinit=params.post_margin) + s_back = Slider(_ax(0.170), "back dist", 0.0, 3.0, valinit=params.back_dist) + s_kclr = Slider(_ax(0.140), "kick clear", 0.0, 1.5, valinit=params.kick_clear) + s_gout = Slider(_ax(0.110), "goalie out", 0.2, 2.0, valinit=params.d_g) + check_fk = CheckButtons(plt.axes([0.18, 0.073, 0.20, 0.022]), ["freekick"], [False]) + s_fkcl = Slider(_ax(0.050), "fk clearance", 0.1, 2.0, valinit=params.freekick_clearance) def draw(): ax.clear() @@ -64,8 +66,13 @@ def draw(): params.supp_max_x, params.def_side = s_smax.val, s_dside.val params.post_margin, params.back_dist = s_pmarg.val, s_back.val params.kick_clear = s_kclr.val + params.freekick = check_fk.get_status()[0] + params.freekick_clearance = s_fkcl.val n = int(s_n.val) + if params.freekick: + ax.add_patch(Circle(state["ball"], params.freekick_clearance, fill=False, color="yellow", lw=1.5, ls="--", zorder=2, alpha=0.7)) + form = _inner._compute_formation(state["ball"], fld, n, params) new_items = list(form.items()) @@ -132,8 +139,9 @@ def on_click(event): state["ball"] = np.array([event.xdata, event.ydata]) draw() - for s in (s_n, s_sep, s_alpha, s_dbias, s_dside, s_gap, s_f, s_side, s_smax, s_pmarg, s_back, s_kclr, s_gout): + for s in (s_n, s_sep, s_alpha, s_dbias, s_dside, s_gap, s_f, s_side, s_smax, s_pmarg, s_back, s_kclr, s_gout, s_fkcl): s.on_changed(lambda _v: draw()) + check_fk.on_clicked(lambda _label: draw()) fig.canvas.mpl_connect("button_press_event", on_click) draw() plt.show() From 251a18d872f593050bba6089a58284bb01435918 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Mon, 29 Jun 2026 19:32:11 +0200 Subject: [PATCH 13/68] Apply PR feedback Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 98 +++++++++++++------ .../capsules/team_data_capsule.py | 8 +- .../scripts/debug_positioning.py | 3 +- .../behavior_dsd/decisions/config_role.py | 2 +- .../config/body_behavior.yaml | 10 +- 5 files changed, 84 insertions(+), 37 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 9492d3fd6..32a45b656 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -1,11 +1,22 @@ +import random from dataclasses import dataclass +from enum import StrEnum +from typing import TypedDict import numpy as np from bitbots_utils.utils import get_parameters_from_other_node +from numpy.typing import NDArray from bitbots_blackboard.capsules import AbstractBlackboardCapsule, cached_capsule_function +class Role(StrEnum): + STRIKER = "striker" + GOALIE = "goalie" + DEFENDER = "defender" + SUPPORTER = "supporter" + + @dataclass class Field: """Field geometry. Populated from the parameter blackboard in __init__.""" @@ -93,8 +104,11 @@ def __init__(self, node, blackboard): goal_width=parameters["field.goal.width"], ) self._params = Params() - self._inner = InnerPositioningCapsule(self._field, self._params) + self._own_locked_role: str | None = None + self._own_lock_until: float = 0.0 + self._hysteresis_min: float = self._blackboard.config["role_hysteresis.min"] + self._hysteresis_max: float = self._blackboard.config["role_hysteresis.max"] @cached_capsule_function def get_formation_assignment(self) -> dict: @@ -108,14 +122,28 @@ def get_formation_assignment(self) -> dict: ordered_jerseys = sorted(robot_poses.keys()) old_poses = [robot_poses[j] for j in ordered_jerseys] pairs = self._inner._match_assignment(old_poses, new_items, ball) + return {ordered_jerseys[old_idx]: {"role": role, "goal_pose": new_pose} for old_idx, new_pose, role in pairs} - result = {} - for jersey, old_pose in zip(ordered_jerseys, [robot_poses[j] for j in ordered_jerseys]): - for ap, new_pose, role in pairs: - if np.allclose(np.asarray(ap), np.asarray(old_pose)): - result[jersey] = {"role": role, "goal_pose": np.asarray(new_pose)} - break - return result + @cached_capsule_function + def get_own_role(self) -> str: + """Return our assigned role, locking it in for a random duration on each change. + + Each robot runs this independently with slightly different world state, so + hysteresis is local: once we switch to a new role we commit to it for + Uniform(hysteresis_min, hysteresis_max) seconds before accepting another change. + """ + own_jersey = self._blackboard.gamestate.get_own_id() + assigned_role = self.get_formation_assignment()[own_jersey]["role"] + now = self._node.get_clock().now().nanoseconds / 1e9 + + if now < self._own_lock_until: + return self._own_locked_role # type: ignore[return-value] + + if assigned_role != self._own_locked_role: + self._own_locked_role = assigned_role + self._own_lock_until = now + random.uniform(self._hysteresis_min, self._hysteresis_max) + + return assigned_role class InnerPositioningCapsule: @@ -190,12 +218,12 @@ def _allocate_roles(n, ball=None, field=None): roles = [] if n >= 1: - roles.append("striker") + roles.append(Role.STRIKER) if n >= 2: - roles.append("goalie") - roles += [f"defender_{i}" for i in range(n_def)] + roles.append(Role.GOALIE) + roles += [f"{Role.DEFENDER}_{i}" for i in range(n_def)] if has_support: - roles.append("supporter") + roles.append(Role.SUPPORTER) return roles # --------------------------------------------------------------------------- # @@ -215,7 +243,7 @@ def _separate(self, positions: dict, field: Field, params: Params, ball=None, ai (along the kick direction) are pushed sideways out of it so they don't block the kick; the push tapers in/out along the corridor to stay smooth. """ - fixed = {"striker"} + fixed = {Role.STRIKER} names = list(positions.keys()) sep = params.min_sep # model the kick corridor as a row of fixed repulsors along the aim, each with @@ -279,7 +307,8 @@ def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): The robot closest to the ball always takes the striker target; the rest are matched optimally (Hungarian) to minimise total cost = distance + angle_w * - heading difference. Returns a list of (old_pose, new_pose, new_role). + heading difference. Returns a list of (old_idx, new_pose, new_role) where + old_idx is the index into `old_poses`. `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). """ from scipy.optimize import linear_sum_assignment @@ -289,9 +318,9 @@ def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): n = len(old_poses) # striker target -> the old robot nearest the ball - s_j = next(j for j, (r, _) in enumerate(new_items) if r == "striker") + s_j = next(j for j, (r, _) in enumerate(new_items) if r == Role.STRIKER) s_i = min(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) - pairs = [(old_poses[s_i], new_items[s_j][1], new_items[s_j][0])] + pairs = [(s_i, new_items[s_j][1], new_items[s_j][0])] rem_i = [i for i in range(n) if i != s_i] rem_j = [j for j in range(len(new_items)) if j != s_j] @@ -304,7 +333,7 @@ def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): ri, ci = linear_sum_assignment(cost) for a, b in zip(ri, ci): i, j = rem_i[a], rem_j[b] - pairs.append((old_poses[i], new_items[j][1], new_items[j][0])) + pairs.append((i, new_items[j][1], new_items[j][0])) return pairs # --------------------------------------------------------------------------- # @@ -312,7 +341,14 @@ def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): # --------------------------------------------------------------------------- # def _compute_formation(self, ball, field: Field, n_players: int, params: Params): - """Map a ball position -> {role_name: np.array([x, y, theta])}. Pure & deterministic.""" + """Map a ball position -> {role: np.array([x, y, yaw])}. Pure & deterministic. + + yaw is in radians, z-up ROS convention (counter-clockwise from +x). + To build a ROS PoseStamped use `quat_from_yaw(pose[2])` from + `bitbots_utils.transforms` which returns a geometry_msgs/Quaternion in + xyzw order (ROS/tf convention). Internally, transforms3d uses wxyz order; + `bitbots_utils.transforms` handles the conversion. + """ B = ball G = np.array([-field.length / 2.0, 0.0]) opp = np.array([+field.length / 2.0, 0.0]) @@ -322,19 +358,19 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) perp = np.array([-to_ball[1], to_ball[0]]) roles = self._allocate_roles(n_players, B, field) - if params.freekick and "supporter" in roles: - n_def = sum(1 for r in roles if r.startswith("defender_")) - roles[roles.index("supporter")] = f"defender_{n_def}" + if params.freekick and Role.SUPPORTER in roles: + n_def = sum(1 for r in roles if r.startswith(Role.DEFENDER + "_")) + roles[roles.index(Role.SUPPORTER)] = f"{Role.DEFENDER}_{n_def}" out = {} head = {} # role -> heading (rad); filled lazily, completed after separation kick_aim = None # striker's kick direction; used to clear the kick lane # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # - if "striker" in roles: + if Role.STRIKER in roles: if params.freekick: # park at the clearance boundary on the goal side, facing the ball dir_to_goal = self._normalize(G - B, fallback=np.array([-1.0, 0.0])) - out["striker"] = self._clamp_field(B + params.freekick_clearance * dir_to_goal, field) + out[Role.STRIKER] = self._clamp_field(B + params.freekick_clearance * dir_to_goal, field) # heading will be computed in the orientation pass (face ball) else: h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth @@ -355,12 +391,12 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn ang = a0 + w_back * da aim = np.array([np.cos(ang), np.sin(ang)]) - out["striker"] = B - params.kick_offset * aim - head["striker"] = ang # striker faces where it kicks + out[Role.STRIKER] = B - params.kick_offset * aim + head[Role.STRIKER] = ang # striker faces where it kicks kick_aim = aim # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # - if "goalie" in roles: + if Role.GOALIE in roles: g = G + params.d_g * to_ball g = np.array( [ @@ -368,10 +404,10 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) np.clip(g[1], -field.goal_width / 2, field.goal_width / 2), ] ) - out["goalie"] = g + out[Role.GOALIE] = g # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # - defender_roles = [r for r in roles if r.startswith("defender_")] + defender_roles = [r for r in roles if r.startswith(Role.DEFENDER + "_")] m = len(defender_roles) if m > 0: D = np.clip( @@ -393,13 +429,13 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) out[r] = self._clamp_field(anchor + off * perp, field) # --- supporter: slightly in front of the ball, kept inside the field -------- # - if "supporter" in roles: + if Role.SUPPORTER in roles: # always sit to the centre side of the ball; hard swap so it is never # directly in front of the striker, even when the ball is on the centre line side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) sup = B + np.array([params.f, params.supp_side * side_dir]) sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner - out["supporter"] = self._clamp_field(sup, field) + out[Role.SUPPORTER] = self._clamp_field(sup, field) # --- min-separation repulsion + kick-lane clearance ----------------------- # self._separate(out, field, params, B, kick_aim) @@ -412,7 +448,7 @@ def _compute_formation(self, ball, field: Field, n_players: int, params: Params) for role, p in out.items(): if role in head: continue # striker already set (faces its kick aim) - if role == "supporter": + if role == Role.SUPPORTER: # face the bisector of (toward ball, toward opp goal): "watch both" bis = self._normalize(B - p) + self._normalize(opp - p) head[role] = self._face(np.zeros(2), bis, fallback=self._face(p, opp)) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index ed9ff070d..9b0048c61 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -188,7 +188,7 @@ def quaternion_to_yaw(self, q) -> float: """Extract yaw (theta) from a quaternion.""" return math.atan2(2.0 * (q.w * q.z + q.x * q.y), 1.0 - 2.0 * (q.y * q.y + q.z * q.z)) - def get_robot_poses(self) -> dict[int, list[float]]: + def get_robot_poses(self, include_own: bool = True) -> dict[int, list[float]]: """Returns a mapping of jersey_number -> [x, y, theta] for all active robots.""" robot_poses = {} data: TeamData @@ -200,8 +200,10 @@ def get_robot_poses(self) -> dict[int, list[float]]: pose.position.y, self.quaternion_to_yaw(pose.orientation), ] - # include own data - robot_poses[self._blackboard.gamestate.get_own_id()] = list(self._blackboard.world_model.get_current_position()) + if include_own: + robot_poses[self._blackboard.gamestate.get_own_id()] = list( + self._blackboard.world_model.get_current_position() + ) return robot_poses def get_number_of_active_field_players(self, count_goalie: bool = False) -> int: diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index a48154b21..cf73ccb7b 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -78,7 +78,8 @@ def draw(): prev = state["prev"] if prev is not None and len(prev) == len(new_items): - for old_pose, new_pose, role in _inner._match_assignment(prev, new_items, state["ball"]): + for old_idx, new_pose, role in _inner._match_assignment(prev, new_items, state["ball"]): + old_pose = prev[old_idx] c = colors.get(role.split("_")[0], "#1f77b4") ax.plot([old_pose[0], new_pose[0]], [old_pose[1], new_pose[1]], ls=":", color=c, lw=1.5, zorder=3) ax.add_patch(Circle(old_pose[:2], 0.10, color=c, alpha=0.55, zorder=4)) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/config_role.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/config_role.py index b3b32f6f7..74009dd73 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/config_role.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/config_role.py @@ -4,7 +4,7 @@ class ConfigRole(AbstractDecisionElement): """ - Decides what kind of behaviour the robot performs + Decides what kind of behavior the robot performs """ blackboard: BodyBlackboard diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index 8108faeb1..cf63d1924 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -3,6 +3,14 @@ body_behavior: # Data older than this is seen as non existent team_data_timeout: 2 + # Role hysteresis: when our assigned role changes, lock the new role for a + # random duration in [role_hysteresis_min, role_hysteresis_max] seconds to + # prevent rapid flickering between roles across distributed robot states. + role_hysteresis: + min: 0.0 + max: 2.0 + + # The roles that are used in the initial role configuration. roles: - "goalie" - "offense" @@ -46,7 +54,7 @@ body_behavior: 2: [ -0.085, -0.33 ] # Time to wait in ready state before moving to role position to give the localization time to converge. - ready_wait_time: 4.0 + ready_wait_time: 2.0 # The orientation threshold defining which range (in Degrees) is acceptable as aligned to the goal (in each direction) goal_alignment_orientation_threshold: 5.0 From 9002998f65b28ff3c9d219c718da2543517891ca Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Mon, 29 Jun 2026 19:41:45 +0200 Subject: [PATCH 14/68] Add typing Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 32a45b656..c848c6f8f 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -10,6 +10,11 @@ from bitbots_blackboard.capsules import AbstractBlackboardCapsule, cached_capsule_function +class RobotAssignment(TypedDict): + role: str + goal_pose: NDArray[np.float64] + + class Role(StrEnum): STRIKER = "striker" GOALIE = "goalie" @@ -104,14 +109,14 @@ def __init__(self, node, blackboard): goal_width=parameters["field.goal.width"], ) self._params = Params() - self._inner = InnerPositioningCapsule(self._field, self._params) + self._inner = InnerPositioningCapsule() self._own_locked_role: str | None = None self._own_lock_until: float = 0.0 self._hysteresis_min: float = self._blackboard.config["role_hysteresis.min"] self._hysteresis_max: float = self._blackboard.config["role_hysteresis.max"] @cached_capsule_function - def get_formation_assignment(self) -> dict: + def get_formation_assignment(self) -> dict[int, RobotAssignment]: ballPose = self._blackboard.world_model.get_best_ball_point_stamped() ball = np.array([ballPose.point.x, ballPose.point.y]) robot_poses = self._blackboard.team_data.get_robot_poses() @@ -154,31 +159,31 @@ class InnerPositioningCapsule: # --------------------------------------------------------------------------- # @staticmethod - def _normalize(v, fallback=np.array([1.0, 0.0])): + def _normalize(v: NDArray[np.float64], fallback: NDArray[np.float64] = np.array([1.0, 0.0])) -> NDArray[np.float64]: n = np.linalg.norm(v) return v / n if n > 1e-9 else fallback.copy() @staticmethod - def _face(frm, to, fallback=0.0): + def _face(frm: NDArray[np.float64], to: NDArray[np.float64], fallback: float = 0.0) -> float: """Heading (rad) to look from `frm` toward `to`.""" d = np.asarray(to) - np.asarray(frm) - return np.arctan2(d[1], d[0]) if np.linalg.norm(d) > 1e-9 else fallback + return float(np.arctan2(d[1], d[0])) if np.linalg.norm(d) > 1e-9 else fallback @staticmethod - def _smoothstep(x, lo, hi): + def _smoothstep(x: float, lo: float, hi: float) -> float: """C1 ramp from 0 (x<=lo) to 1 (x>=hi).""" if hi <= lo: return float(x >= hi) t = np.clip((x - lo) / (hi - lo), 0.0, 1.0) - return t * t * (3 - 2 * t) + return float(t * t * (3 - 2 * t)) @staticmethod - def _angle_diff(a, b): + def _angle_diff(a: float, b: float) -> float: """Smallest absolute angle between two headings (rad), in [0, pi].""" - return abs((a - b + np.pi) % (2 * np.pi) - np.pi) + return float(abs((a - b + np.pi) % (2 * np.pi) - np.pi)) @staticmethod - def _clamp_field(p, fld, margin=None): + def _clamp_field(p: NDArray[np.float64], fld: Field, margin: float | None = None) -> NDArray[np.float64]: """Clamp a point to the playable rectangle (continuous / C0).""" m = fld.margin if margin is None else margin return np.array( @@ -193,7 +198,7 @@ def _clamp_field(p, fld, margin=None): # --------------------------------------------------------------------------- # @staticmethod - def _allocate_roles(n, ball=None, field=None): + def _allocate_roles(n: int, ball: NDArray[np.float64] | None = None, field: Field | None = None) -> list[str]: """Keep-priority as the count drops: striker > goalie > 1st defender > supporter > 2nd defender (and any further players are extra defenders). @@ -230,7 +235,14 @@ def _allocate_roles(n, ball=None, field=None): # Separation / kick-lane clearance # --------------------------------------------------------------------------- # - def _separate(self, positions: dict, field: Field, params: Params, ball=None, aim=None): + def _separate( + self, + positions: dict[str, NDArray[np.float64]], + field: Field, + params: Params, + ball: NDArray[np.float64] | None = None, + aim: NDArray[np.float64] | None = None, + ) -> None: """In-place relaxation: pairwise min-sep + clearing the striker's kick lane. Only the striker is a fixed anchor (it must reach the ball); everyone else, @@ -288,7 +300,7 @@ def _separate(self, positions: dict, field: Field, params: Params, ball=None, ai continue positions[n] = self._clamp_field(positions[n] + disp[n], field) - def _clear_ball(self, positions: dict, ball, radius: float, field: Field): + def _clear_ball(self, positions: dict[str, NDArray[np.float64]], ball: NDArray[np.float64], radius: float, field: Field) -> None: """Push all robots to at least `radius` distance from `ball` (in-place).""" ball = np.asarray(ball) for name in positions: @@ -302,7 +314,13 @@ def _clear_ball(self, positions: dict, ball, radius: float, field: Field): # Assignment # --------------------------------------------------------------------------- # - def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): + def _match_assignment( + self, + old_poses: list[list[float] | NDArray[np.float64]], + new_items: list[tuple[str, NDArray[np.float64]]], + ball: NDArray[np.float64], + angle_w: float = 0.3, + ) -> list[tuple[int, NDArray[np.float64], str]]: """Assign physical robots (at `old_poses`) to the new target poses. The robot closest to the ball always takes the striker target; the rest are @@ -340,7 +358,7 @@ def _match_assignment(self, old_poses, new_items, ball, angle_w=0.3): # Formation computation # --------------------------------------------------------------------------- # - def _compute_formation(self, ball, field: Field, n_players: int, params: Params): + def _compute_formation(self, ball: NDArray[np.float64], field: Field, n_players: int, params: Params) -> dict[str, NDArray[np.float64]]: """Map a ball position -> {role: np.array([x, y, yaw])}. Pure & deterministic. yaw is in radians, z-up ROS convention (counter-clockwise from +x). From 49d519a50633fcebdc94d00509277f8cc36d5422 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Mon, 29 Jun 2026 19:59:36 +0200 Subject: [PATCH 15/68] Apply format --- pixi.lock | 14 ++-- .../bitbots_blackboard/CMakeLists.txt | 6 +- .../capsules/positioning_capsule.py | 66 ++++++++++--------- .../scripts/debug_positioning.py | 31 ++++++++- .../actions/go_to_block_position.py | 5 +- .../actions/go_to_pass_position.py | 6 +- .../bitbots_team_data_sim_rqt/team_data_ui.py | 10 +-- 7 files changed, 82 insertions(+), 56 deletions(-) diff --git a/pixi.lock b/pixi.lock index 141365d1c..8edf57975 100644 --- a/pixi.lock +++ b/pixi.lock @@ -997,7 +997,7 @@ environments: - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros-jazzy-zenoh-cpp-vendor-0.2.9-np2py312ha80d210_16.conda - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros-jazzy-zstd-vendor-0.26.9-np2py312h2ed9cc7_16.conda - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros2-distro-mutex-0.14.0-jazzy_16.conda - - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_0.conda + - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2022_10_07_flo_torso21_yoeox-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda @@ -3115,7 +3115,7 @@ environments: - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros-jazzy-zenoh-cpp-vendor-0.2.9-np2py312ha80d210_16.conda - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros-jazzy-zstd-vendor-0.26.9-np2py312h2ed9cc7_16.conda - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros2-distro-mutex-0.14.0-jazzy_16.conda - - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_0.conda + - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2022_10_07_flo_torso21_yoeox-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda @@ -34818,15 +34818,15 @@ packages: license: BSD-3-Clause size: 2334 timestamp: 1771181488082 -- conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_0.conda - sha256: b81b05ded4ec13d8cefc504fc110aa8712f7c467a918a11c4f05445b68b21ebe - md5: dcf15ae037e842d7f38231e062d8dc93 +- conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda + sha256: 8d6ce89805148cd661bb2f4406631c0251b2ded3a9b42b7d1160eff9b5778c9b + md5: a5a82453b80fcb05372b42cab5c43204 depends: - python >=3.12,<3.13 - python_abi 3.12.* *_cp312 license: MIT - size: 738579415 - timestamp: 1775921730373 + size: 10651622 + timestamp: 1782745906333 - conda: https://data.bit-bots.de/conda-misc/output/linux-aarch64/libonnxruntime-webgpu-1.24.3-he8cfe8b_0.conda sha256: 4876857396a9a049cfa8b12e4e450c8f4288f471788817476084945737c1d2ae md5: de18b3bee6102a8ee4212cf6e1d675e9 diff --git a/src/bitbots_behavior/bitbots_blackboard/CMakeLists.txt b/src/bitbots_behavior/bitbots_blackboard/CMakeLists.txt index 5d6a26340..1a94473cb 100644 --- a/src/bitbots_behavior/bitbots_blackboard/CMakeLists.txt +++ b/src/bitbots_behavior/bitbots_blackboard/CMakeLists.txt @@ -12,10 +12,8 @@ if(BUILD_TESTING) ament_mypy(CONFIG_FILE "${CMAKE_CURRENT_LIST_DIR}/mypy.ini") endif() -install(DIRECTORY - scripts/ USE_SOURCE_PERMISSIONS - DESTINATION lib/${PROJECT_NAME} -) +install(DIRECTORY scripts/ USE_SOURCE_PERMISSIONS + DESTINATION lib/${PROJECT_NAME}) ament_python_install_package(${PROJECT_NAME}) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index c848c6f8f..7539d8d6d 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -117,8 +117,8 @@ def __init__(self, node, blackboard): @cached_capsule_function def get_formation_assignment(self) -> dict[int, RobotAssignment]: - ballPose = self._blackboard.world_model.get_best_ball_point_stamped() - ball = np.array([ballPose.point.x, ballPose.point.y]) + ball_pose = self._blackboard.world_model.get_best_ball_point_stamped() + ball = np.array([ball_pose.point.x, ball_pose.point.y]) robot_poses = self._blackboard.team_data.get_robot_poses() self._node.get_logger().info(f"Length of robot_poses: {len(robot_poses)}") @@ -159,7 +159,9 @@ class InnerPositioningCapsule: # --------------------------------------------------------------------------- # @staticmethod - def _normalize(v: NDArray[np.float64], fallback: NDArray[np.float64] = np.array([1.0, 0.0])) -> NDArray[np.float64]: + def _normalize(v: NDArray[np.float64], fallback: NDArray[np.float64] | None = None) -> NDArray[np.float64]: + if fallback is None: + fallback = np.array([1.0, 0.0]) n = np.linalg.norm(v) return v / n if n > 1e-9 else fallback.copy() @@ -300,7 +302,9 @@ def _separate( continue positions[n] = self._clamp_field(positions[n] + disp[n], field) - def _clear_ball(self, positions: dict[str, NDArray[np.float64]], ball: NDArray[np.float64], radius: float, field: Field) -> None: + def _clear_ball( + self, positions: dict[str, NDArray[np.float64]], ball: NDArray[np.float64], radius: float, field: Field + ) -> None: """Push all robots to at least `radius` distance from `ball` (in-place).""" ball = np.asarray(ball) for name in positions: @@ -358,7 +362,9 @@ def _match_assignment( # Formation computation # --------------------------------------------------------------------------- # - def _compute_formation(self, ball: NDArray[np.float64], field: Field, n_players: int, params: Params) -> dict[str, NDArray[np.float64]]: + def _compute_formation( + self, ball: NDArray[np.float64], field: Field, n_players: int, params: Params + ) -> dict[str, NDArray[np.float64]]: """Map a ball position -> {role: np.array([x, y, yaw])}. Pure & deterministic. yaw is in radians, z-up ROS convention (counter-clockwise from +x). @@ -367,15 +373,15 @@ def _compute_formation(self, ball: NDArray[np.float64], field: Field, n_players: xyzw order (ROS/tf convention). Internally, transforms3d uses wxyz order; `bitbots_utils.transforms` handles the conversion. """ - B = ball - G = np.array([-field.length / 2.0, 0.0]) + b = ball + goal = np.array([-field.length / 2.0, 0.0]) opp = np.array([+field.length / 2.0, 0.0]) - d = np.linalg.norm(B - G) - to_ball = self._normalize(B - G) # our-goal -> ball + d = np.linalg.norm(b - goal) + to_ball = self._normalize(b - goal) # our-goal -> ball perp = np.array([-to_ball[1], to_ball[0]]) - roles = self._allocate_roles(n_players, B, field) + roles = self._allocate_roles(n_players, b, field) if params.freekick and Role.SUPPORTER in roles: n_def = sum(1 for r in roles if r.startswith(Role.DEFENDER + "_")) roles[roles.index(Role.SUPPORTER)] = f"{Role.DEFENDER}_{n_def}" @@ -387,20 +393,20 @@ def _compute_formation(self, ball: NDArray[np.float64], field: Field, n_players: if Role.STRIKER in roles: if params.freekick: # park at the clearance boundary on the goal side, facing the ball - dir_to_goal = self._normalize(G - B, fallback=np.array([-1.0, 0.0])) - out[Role.STRIKER] = self._clamp_field(B + params.freekick_clearance * dir_to_goal, field) + dir_to_goal = self._normalize(goal - b, fallback=np.array([-1.0, 0.0])) + out[Role.STRIKER] = self._clamp_field(b + params.freekick_clearance * dir_to_goal, field) # heading will be computed in the orientation pass (face ball) else: h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth # aim at the goal, target clamped into the safe mouth: this gives a straight # (+x) shot whenever the ball is aligned within the posts, angled otherwise - target = np.array([opp[0], np.clip(B[1], -h, h)]) - aim_goal = self._normalize(target - B) + target = np.array([opp[0], np.clip(b[1], -h, h)]) + aim_goal = self._normalize(target - b) # fallback: play back toward our side (field centre) - aim_back = self._normalize(np.array([0.0, 0.0]) - B, fallback=np.array([-1.0, 0.0])) + aim_back = self._normalize(np.array([0.0, 0.0]) - b, fallback=np.array([-1.0, 0.0])) # blend to back-pass only when close to the opp goal AND not aligned - near_goal = self._smoothstep(B[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) - not_aligned = self._smoothstep(abs(B[1]), h, h + 1.0) + near_goal = self._smoothstep(b[0], opp[0] - params.back_dist - 1.0, opp[0] - params.back_dist) + not_aligned = self._smoothstep(abs(b[1]), h, h + 1.0) w_back = near_goal * not_aligned # rotate the aim around the ball at constant angular rate (shortest path) so # the striker swings smoothly rather than whipping when the two aims oppose @@ -409,13 +415,13 @@ def _compute_formation(self, ball: NDArray[np.float64], field: Field, n_players: da = (a1 - a0 + np.pi) % (2 * np.pi) - np.pi # shortest signed turn ang = a0 + w_back * da aim = np.array([np.cos(ang), np.sin(ang)]) - out[Role.STRIKER] = B - params.kick_offset * aim + out[Role.STRIKER] = b - params.kick_offset * aim head[Role.STRIKER] = ang # striker faces where it kicks kick_aim = aim # --- goalie: on the ball->goal axis, hugging the goal, clamped to the mouth -- # if Role.GOALIE in roles: - g = G + params.d_g * to_ball + g = goal + params.d_g * to_ball g = np.array( [ np.clip(g[0], -field.length / 2 + 0.05, -field.length / 2 + params.d_g), @@ -428,18 +434,18 @@ def _compute_formation(self, ball: NDArray[np.float64], field: Field, n_players: defender_roles = [r for r in roles if r.startswith(Role.DEFENDER + "_")] m = len(defender_roles) if m > 0: - D = np.clip( + depth = np.clip( params.alpha * d + params.depth_bias, # push up + fwd/back bias params.D_min, params.D_max, ) - D = min(D, max(d - params.standoff, 0.0)) # stay goal-side of the ball - D = max(D, params.d_g + params.dz) # stay ahead of the goalie - anchor = G + D * to_ball + depth = min(depth, max(d - params.standoff, 0.0)) # stay goal-side of the ball + depth = max(depth, params.d_g + params.dz) # stay ahead of the goalie + anchor = goal + depth * to_ball if m == 1: # a single defender: shade to the centre side so it doesn't sit on the # striker<->goalie line (otherwise all three are collinear) - side_dir = -1.0 if B[1] >= 0 else 1.0 + side_dir = -1.0 if b[1] >= 0 else 1.0 offsets = [params.def_side * side_dir] else: offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] @@ -450,17 +456,17 @@ def _compute_formation(self, ball: NDArray[np.float64], field: Field, n_players: if Role.SUPPORTER in roles: # always sit to the centre side of the ball; hard swap so it is never # directly in front of the striker, even when the ball is on the centre line - side_dir = -1.0 if B[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) - sup = B + np.array([params.f, params.supp_side * side_dir]) + side_dir = -1.0 if b[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) + sup = b + np.array([params.f, params.supp_side * side_dir]) sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner out[Role.SUPPORTER] = self._clamp_field(sup, field) # --- min-separation repulsion + kick-lane clearance ----------------------- # - self._separate(out, field, params, B, kick_aim) + self._separate(out, field, params, b, kick_aim) # --- freekick: push every robot outside the mandatory clearance radius ---- # if params.freekick: - self._clear_ball(out, B, params.freekick_clearance, field) + self._clear_ball(out, b, params.freekick_clearance, field) # --- orientations (computed from the final positions) --------------------- # for role, p in out.items(): @@ -468,9 +474,9 @@ def _compute_formation(self, ball: NDArray[np.float64], field: Field, n_players: continue # striker already set (faces its kick aim) if role == Role.SUPPORTER: # face the bisector of (toward ball, toward opp goal): "watch both" - bis = self._normalize(B - p) + self._normalize(opp - p) + bis = self._normalize(b - p) + self._normalize(opp - p) head[role] = self._face(np.zeros(2), bis, fallback=self._face(p, opp)) else: - head[role] = self._face(p, B) # goalie + defenders face the ball + head[role] = self._face(p, b) # goalie + defenders face the ball return {role: np.array([p[0], p[1], head[role]]) for role, p in out.items()} diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index cf73ccb7b..012a2bc34 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -6,7 +6,6 @@ """ import numpy as np - from bitbots_blackboard.capsules.positioning_capsule import Field, InnerPositioningCapsule, Params _inner = InnerPositioningCapsule() @@ -71,7 +70,18 @@ def draw(): n = int(s_n.val) if params.freekick: - ax.add_patch(Circle(state["ball"], params.freekick_clearance, fill=False, color="yellow", lw=1.5, ls="--", zorder=2, alpha=0.7)) + ax.add_patch( + Circle( + state["ball"], + params.freekick_clearance, + fill=False, + color="yellow", + lw=1.5, + ls="--", + zorder=2, + alpha=0.7, + ) + ) form = _inner._compute_formation(state["ball"], fld, n, params) new_items = list(form.items()) @@ -140,7 +150,22 @@ def on_click(event): state["ball"] = np.array([event.xdata, event.ydata]) draw() - for s in (s_n, s_sep, s_alpha, s_dbias, s_dside, s_gap, s_f, s_side, s_smax, s_pmarg, s_back, s_kclr, s_gout, s_fkcl): + for s in ( + s_n, + s_sep, + s_alpha, + s_dbias, + s_dside, + s_gap, + s_f, + s_side, + s_smax, + s_pmarg, + s_back, + s_kclr, + s_gout, + s_fkcl, + ): s.on_changed(lambda _v: draw()) check_fk.on_clicked(lambda _label: draw()) fig.canvas.mpl_connect("button_press_event", on_click) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py index bf805ce65..6d3d73573 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py @@ -6,14 +6,14 @@ from dynamic_stack_decider.abstract_action_element import AbstractActionElement from tf2_geometry_msgs import PoseStamped + class GoToGoaliePosition(AbstractActionElement): blackboard: BodyBlackboard - + def __init__(self, blackboard, dsd, parameters): super().__init__(blackboard, dsd, parameters) def perform(self, reevaluate=False): - pose_msg = PoseStamped() pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() pose_msg.header.frame_id = self.blackboard.map_frame @@ -27,6 +27,7 @@ def perform(self, reevaluate=False): self.blackboard.pathfinding.publish(pose_msg) + class GoToBlockPosition(AbstractActionElement): blackboard: BodyBlackboard diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py index 13f6a4074..4ba276a33 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py @@ -1,5 +1,4 @@ from bitbots_blackboard.body_blackboard import BodyBlackboard -from bitbots_utils.transforms import quat_from_yaw from dynamic_stack_decider.abstract_action_element import AbstractActionElement from tf2_geometry_msgs import PoseStamped @@ -34,13 +33,10 @@ def perform(self, reevaluate=False): # Limit the x position, so that we are not running into the enemy goal goal_x = min(self.max_x, goal_x) - goal_y = ball_pos[1] + side_sign * self.pass_pos_y - goal_yaw = 0.0 - pose_msg = PoseStamped() pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() pose_msg.header.frame_id = self.blackboard.map_frame - + optimal_positioning = self.blackboard.positioning.get_formation_assignment() own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] pose = own_position["goal_pose"] diff --git a/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py b/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py index 9a69b64f4..82550e874 100755 --- a/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py +++ b/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py @@ -3,6 +3,7 @@ import sys from ament_index_python import get_package_share_directory +from geometry_msgs.msg import PoseWithCovariance from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( QComboBox, @@ -24,7 +25,6 @@ from rqt_gui_py.plugin import Plugin from bitbots_msgs.msg import Strategy, TeamData -from geometry_msgs.msg import PoseWithCovariance class RobotWidget(QGroupBox): @@ -307,10 +307,10 @@ def timer_callback(self): if robot_widget.active(): team_data = TeamData() team_data.robot_id = robot_widget.get_robot_id() - poseWithCov = PoseWithCovariance() - poseWithCov.pose.position.x = robot_widget.position_sliders_x.get_x_position() - poseWithCov.pose.position.y = robot_widget.position_sliders_y.get_y_position() - team_data.robot_position = poseWithCov + pose_with_cov = PoseWithCovariance() + pose_with_cov.pose.position.x = robot_widget.position_sliders_x.get_x_position() + pose_with_cov.pose.position.y = robot_widget.position_sliders_y.get_y_position() + team_data.robot_position = pose_with_cov team_data.state = robot_widget.state_box.get_state() team_data.time_to_position_at_ball = robot_widget.time_to_position_box.get_time() team_data.strategy.role = robot_widget.strategy_box.get_role() From eaaf36d9d4fd83d8338d8cb8c774ce20f90376a3 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Tue, 30 Jun 2026 06:43:37 +0200 Subject: [PATCH 16/68] improved dsd based on comments in PR (not testet for building) --- .../behavior_dsd/actions/go_to_ball.py | 11 +++- .../actions/go_to_formation_position.py | 25 +++++++++ .../behavior_dsd/decisions/closest_to_ball.py | 24 ++++----- .../behavior_dsd/main.dsd | 51 +++++++------------ 4 files changed, 65 insertions(+), 46 deletions(-) create mode 100644 src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py index 83f6f528a..e84516b69 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py @@ -2,6 +2,7 @@ from bitbots_blackboard.capsules.pathfinding_capsule import BallGoalType from dynamic_stack_decider.abstract_action_element import AbstractActionElement from geometry_msgs.msg import Vector3 +from tf2_geometry_msgs import PoseStamped from std_msgs.msg import ColorRGBA from visualization_msgs.msg import Marker @@ -25,7 +26,15 @@ def __init__(self, blackboard, dsd, parameters): self.side_offset = parameters.get("side_offset", 0.00) def perform(self, reevaluate=False): - pose_msg = self.blackboard.pathfinding.get_ball_goal(self.target, self.distance, self.side_offset) + pose_msg = PoseStamped() + pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() + pose_msg.header.frame_id = self.blackboard.map_frame + optimal_positioning = self.blackboard.positioning.get_formation_assignment() + own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] + pose = own_position["goal_pose"] + pose_msg.pose.position.x = pose[0] + pose_msg.pose.position.y = pose[1] + pose_msg.pose.orientation.w = pose[2] self.blackboard.pathfinding.publish(pose_msg) approach_marker = Marker() diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py new file mode 100644 index 000000000..f8dce21d5 --- /dev/null +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py @@ -0,0 +1,25 @@ + +from bitbots_blackboard.body_blackboard import BodyBlackboard +from dynamic_stack_decider.abstract_action_element import AbstractActionElement +from tf2_geometry_msgs import PoseStamped + + +class GoToFormationPosition(AbstractActionElement): + blackboard: BodyBlackboard + + def __init__(self, blackboard, dsd, parameters): + super().__init__(blackboard, dsd, parameters) + + def perform(self, reevaluate=False): + pose_msg = PoseStamped() + pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() + pose_msg.header.frame_id = self.blackboard.map_frame + + optimal_positioning = self.blackboard.positioning.get_formation_assignment() + own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] + pose = own_position["goal_pose"] + pose_msg.pose.position.x = pose[0] + pose_msg.pose.position.y = pose[1] + pose_msg.pose.orientation.w = pose[2] + + self.blackboard.pathfinding.publish(pose_msg) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index 68b49f099..23e1e5116 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -33,7 +33,7 @@ def perform(self, reevaluate=False): self.publish_debug_data("time to ball", my_time_to_ball) self.publish_debug_data("Rank to ball", rank) if rank == 1: - return "NO" # only for testing remeber to REMOVE! + return "YES" return "NO" def get_reevaluate(self): @@ -51,20 +51,20 @@ def perform(self, reevaluate=False): own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] role = own_position["role"] self.publish_debug_data("Role from positioning", role) - if role == "striker": + if role == 1: return "STRIKER" - elif role == "goalie": + elif role == 2: return "GOALIE" - elif role == "defender_0": - return "DEFENDER_ZERO" - elif role == "defender_1": - return "DEFENDER1" - elif role == "defender_2": - return "DEFENDER2" - elif role == "defender_3": - return "DEFENDER3" - elif role == "supporter": + elif role == 3: + return "DEFENDER" + elif role == 4: return "SUPPORTER" + elif role == 5: + return "DEFENDER" + elif role == 6: + return "DEFENDER" + elif role == 7: + return "DEFENDER" else: # emergency fall back if something goes wrong self.blackboard.node.get_logger().warning("Rank to ball had some issues. Role" + role) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 8d9143358..51d82d496 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -46,28 +46,15 @@ $GoalScoreRecently YES --> $ConfigRole GOALIE --> $RobotInOwnPercentOfField + p:40 YES --> @Stand + duration:1.0 + r:false, @PlayAnimationCheering + r:false, @Stand - NO --> @ChangeAction + action:positioning, @PlaySound + file:ole.wav, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToRolePosition - ELSE --> @ChangeAction + action:positioning, @PlaySound + file:ole.wav, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToRolePosition - NO --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToRolePosition - -#GoalieBehavior -$ClosestToBall - NO --> $BallInOwnPercent + p:40 - YES --> @ChangeAction + action:positioning, @AvoidBallActive, @LookAtFieldFeatures, @GoToBlockPosition - NO --> #RolePositionWithPause - YES --> #KickWithAvoidance - -#StrikerRole -$GoalieHandlingBall - YES --> @ChangeAction + action:positioning, @AvoidBallActive, @LookAtFieldFeatures, @GoToDefensePosition //quick fix for playing with two robots during GO - NO --> #KickWithAvoidance + NO --> @ChangeAction + action:positioning, @PlaySound + file:ole.wav, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToFormationPosition + ELSE --> @ChangeAction + action:positioning, @PlaySound + file:ole.wav, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToFormationPosition + NO --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToFormationPosition #SupporterRole -$PassStarted - YES --> $BallSeen - YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToPassAcceptPosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToPassAcceptPosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToPassPreparePosition +$BallSeen + YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + #PenaltyShootoutBehavior $SecondaryStateTeamDecider @@ -84,17 +71,15 @@ $SecondaryStateTeamDecider $DoOnce NOT_DONE --> @ForgetBall, @LookAtFieldFeatures DONE --> $ConfigRole - GOALIE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToBlockPosition + GOALIE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition ELSE --> $BallSeen - NO --> $SecondaryStateTeamDecider - OUR --> #SearchBall - ELSE --> @AvoidBallActive, @LookAtFieldFeatures, @WalkInPlace + duration:2, @GoToRelativePosition + x:1 + y:0 + t:0, @Stand + NO --> #SearchBall YES --> $RankToBallWithGoalie - STRIKER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_first - DEFENDER0 --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_second + STRIKER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition + DEFENDER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition SUPPORTER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition GOALIE --> @GoToGoaliePosition - ELSE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_second + ELSE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition #Init @Stand + duration:0.1 + r:false, @ChangeAction + action:waiting, @LookForward, @Stand @@ -102,17 +87,17 @@ $DoOnce #NormalBehavior $BallSeen NO --> $ConfigRole - GOALIE --> #RolePositionWithPause - ELSE --> #SearchBall + STRIKER --> #SearchBall + ELSE --> #RolePositionWithPause YES --> $KickOffTimeUp NO_NORMAL --> #StandAndLook NO_FREEKICK --> #Placing YES --> $RankToBallWithGoalie - STRIKER --> #StrikerRole - GOALIE --> @GoToGoaliePosition - DEFENDER_ZERO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition + STRIKER --> #KickWithAvoidance + GOALIE --> GoToFormationPosition + DEFENDER --> @LookAtFieldFeatures, @ChangeAction + action:positioning, GoToFormationPosition SUPPORTER --> #SupporterRole - ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToDefensePosition //defender 1 bis 4 integrieren? + ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, GoToFormationPosition #PlayingBehavior $SecondaryStateDecider From bfbf3c703f3072b862674bcce8704daa0ef33c9c Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Tue, 30 Jun 2026 08:00:24 +0200 Subject: [PATCH 17/68] integrate positioning capsule changes in main dsd --- .../behavior_dsd/decisions/closest_to_ball.py | 10 ++++------ .../bitbots_body_behavior/behavior_dsd/main.dsd | 14 +++++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index 23e1e5116..0aa20bfe4 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -47,11 +47,9 @@ def __init__(self, blackboard, dsd, parameters): super().__init__(blackboard, dsd, parameters) def perform(self, reevaluate=False): - optimal_positioning = self.blackboard.positioning.get_formation_assignment() - own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] - role = own_position["role"] - self.publish_debug_data("Role from positioning", role) - if role == 1: + role = self.blackboard.positioning.get_own_role() + return self.publish_debug_data("Role from positioning", role) + """if role == "STRIKER": return "STRIKER" elif role == 2: return "GOALIE" @@ -68,7 +66,7 @@ def perform(self, reevaluate=False): else: # emergency fall back if something goes wrong self.blackboard.node.get_logger().warning("Rank to ball had some issues. Role" + role) - return "STRIKER" + return "STRIKER" """ def get_reevaluate(self): return True diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 51d82d496..6d477142a 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -35,11 +35,11 @@ $AvoidBall NO --> $BallClose + distance:%ball_reapproach_dist + angle:%ball_reapproach_angle YES --> $BallKickArea NEAR --> #Dribble - FAR --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToBall + target:map - NO --> @ChangeAction + action:going_to_ball + r:false, @LookAtFieldFeatures + r:false, @AvoidBallActive + r:false, @GoToBall + target:map + blocking:false + distance:%ball_far_approach_dist + FAR --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToFormationPosition + NO --> @ChangeAction + action:going_to_ball + r:false, @LookAtFieldFeatures + r:false, @AvoidBallActive + r:false, @GoToFormationPosition + target:map + blocking:false + distance:%ball_far_approach_dist YES --> $ReachedPathPlanningGoalPosition + threshold:%ball_far_approach_position_thresh YES --> @AvoidBallInactive - NO --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToBall + target:map + distance:%ball_far_approach_dist + NO --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToFormationPosition #PositioningReady $GoalScoreRecently @@ -75,7 +75,7 @@ $DoOnce ELSE --> $BallSeen NO --> #SearchBall YES --> $RankToBallWithGoalie - STRIKER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition + STRIKER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition //ugly yet DEFENDER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition SUPPORTER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition GOALIE --> @GoToGoaliePosition @@ -118,14 +118,14 @@ $IsPenalized NO --> $GameStateDecider INITIAL --> #Init READY --> $AnyGoalScoreRecently + time:50 - YES --> #PositioningReady + YES --> @GoToFormationPosition NO --> $DoOnce NOT_DONE --> @ChangeAction + action:waiting + r:false, @LookAtFieldFeatures + r:false, @Stand + duration:2 - DONE --> #PositioningReady + DONE --> @GoToFormationPosition SET --> $WhistleDetected DETECTED --> $SecondaryStateTeamDecider OUR --> #PlayingBehavior - OTHER --> #PositioningReady + OTHER --> @GoToFormationPosition ELSE --> #PlayingBehavior NOT_DETECTED --> $SecondaryStateDecider PENALTYSHOOT --> $SecondaryStateTeamDecider From 3fc4e2c105bff7cf21a9b00ad0c6edb5e0a96b02 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Tue, 30 Jun 2026 10:27:14 +0200 Subject: [PATCH 18/68] rqt add ball pose publish --- .../bitbots_team_data_sim_rqt/team_data_ui.py | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py b/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py index 82550e874..258c1b3ba 100755 --- a/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py +++ b/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py @@ -50,6 +50,12 @@ def __init__(self, parent=None): self.main_layout.addWidget(self.position_sliders_x) self.position_sliders_y = PositionCoordsY() self.main_layout.addWidget(self.position_sliders_y) + self.ball_position_sliders_y = BallPositionCoordsY() + self.main_layout.addWidget(self.ball_position_sliders_y) + self.ball_position_sliders_x = BallPositionCoordsX() + self.main_layout.addWidget(self.ball_position_sliders_x) + self.ball_covariance = BallCovariance() + self.main_layout.addWidget(self.ball_covariance) self.strategy_box = StrategyBox() self.main_layout.addWidget(self.strategy_box) self.publish_button = PublishButton() @@ -65,6 +71,9 @@ def id_spin_box_update(self): self.publish_button.setEnabled(enabled) self.position_sliders_x.setEnabled(enabled) self.position_sliders_y.setEnabled(enabled) + self.ball_position_sliders_x.setEnabled(enabled) + self.ball_position_sliders_y.setEnabled(enabled) + self.ball_covariance.setEnabled(enabled) def get_robot_id(self) -> int: return self.id_spin_box.value() @@ -177,6 +186,78 @@ def __init__(self, parent=None): def get_y_position(self) -> float: return float(self.y_pos_spin_box.value() / 100) +class BallPositionCoordsX(QGroupBox): + def __init__(self, parent=None): + super().__init__(parent) + # x position + self.setTitle("Ball X position") + self.setEnabled(False) + # Create layout + self.main_layout = QHBoxLayout() + self.setLayout(self.main_layout) + # Create spin box + self.x_ball_pos_spin_box = QSpinBox() + self.x_ball_pos_spin_box.setRange(-550, 550) + self.main_layout.addWidget(self.x_ball_pos_spin_box) + # Create slider + self.x_ball_pos_slider = QSlider(Qt.Horizontal) # type: ignore[attr-defined] + self.x_ball_pos_slider.setRange(-550, 550) + self.main_layout.addWidget(self.x_ball_pos_slider) + # Connect spin box and slider + self.x_ball_pos_spin_box.valueChanged.connect(self.x_ball_pos_slider.setValue) # type: ignore[attr-defined] + self.x_ball_pos_slider.valueChanged.connect(self.x_ball_pos_spin_box.setValue) # type: ignore[attr-defined] + + def get_x_ball_position(self) -> float: + return float(self.x_ball_pos_spin_box.value() / 100) + + +class PositionCoordsY(QGroupBox): + def __init__(self, parent=None): + super().__init__(parent) + # y position + self.setTitle("Y ball position") + self.setEnabled(False) + # Create layout + self.main_layout = QHBoxLayout() + self.setLayout(self.main_layout) + # Create spin box + self.y_ball_pos_spin_box = QSpinBox() + self.y_ball_pos_spin_box.setRange(-400, 400) + self.main_layout.addWidget(self.y_ball_pos_spin_box) + # Create slider + self.y_ball_pos_slider = QSlider(Qt.Horizontal) # type: ignore[attr-defined] + self.y_ball_pos_slider.setRange(-400, 400) + self.main_layout.addWidget(self.y_ball_pos_slider) + # Connect spin box and slider + self.y_ball_pos_spin_box.valueChanged.connect(self.y_ball_pos_slider.setValue) # type: ignore[attr-defined] + self.y_ball_pos_slider.valueChanged.connect(self.y_ball_pos_spin_box.setValue) # type: ignore[attr-defined] + + def get_y_ball_position(self) -> float: + return float(self.y_ball_pos_spin_box.value() / 100) + +class BallCovariance(QGroupBox): + def __init__(self, parent=None): + super().__init__(parent) + # y position + self.setTitle("Ball covariance in 0.1 sum") + self.setEnabled(False) + # Create layout + self.main_layout = QHBoxLayout() + self.setLayout(self.main_layout) + # Create spin box + self.ball_covariance_box = QSpinBox() + self.ball_covariance_box.setRange(-400, 400) + self.main_layout.addWidget(self.ball_covariance_box) + # Create slider + self.ball_covariance_slider = QSlider(Qt.Horizontal) # type: ignore[attr-defined] + self.ball_covariance_slider.setRange(-400, 400) + self.main_layout.addWidget(self.ball_covariance_slider) + # Connect spin box and slider + self.ball_covariance_box.valueChanged.connect(self.ball_covariance_slider.setValue) # type: ignore[attr-defined] + self.ball_covariance_slider.valueChanged.connect(self.ball_covariance_box.setValue) # type: ignore[attr-defined] + + def get_ball_covariance(self) -> float: + return float(self.ball_covariance_box.value() / 10) class StrategyBox(QGroupBox): _roles: dict[str, int] = { @@ -310,6 +391,14 @@ def timer_callback(self): pose_with_cov = PoseWithCovariance() pose_with_cov.pose.position.x = robot_widget.position_sliders_x.get_x_position() pose_with_cov.pose.position.y = robot_widget.position_sliders_y.get_y_position() + pose_with_cov.covariance = [ + robot_widget.ball_covariance.get_ball_covariance() / 2, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, robot_widget.ball_covariance.get_ball_covariance() / 2, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.05 + ] team_data.robot_position = pose_with_cov team_data.state = robot_widget.state_box.get_state() team_data.time_to_position_at_ball = robot_widget.time_to_position_box.get_time() From 28dbf2ed1767b1d7430cbeab7b9823073eeeff96 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Tue, 30 Jun 2026 10:40:19 +0200 Subject: [PATCH 19/68] add @ in dsd go tos --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 6d477142a..24d3a4072 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -94,10 +94,10 @@ $BallSeen NO_FREEKICK --> #Placing YES --> $RankToBallWithGoalie STRIKER --> #KickWithAvoidance - GOALIE --> GoToFormationPosition - DEFENDER --> @LookAtFieldFeatures, @ChangeAction + action:positioning, GoToFormationPosition + GOALIE --> @GoToFormationPosition + DEFENDER --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition SUPPORTER --> #SupporterRole - ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, GoToFormationPosition + ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition #PlayingBehavior $SecondaryStateDecider From d058eebccfb2457e1e05502192c58185a2bd6d58 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Tue, 30 Jun 2026 11:48:28 +0200 Subject: [PATCH 20/68] fix positioning ready --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index e160905c5..8cc786133 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -48,9 +48,9 @@ $GoalScoreRecently YES --> $ConfigRole GOALIE --> $RobotInOwnPercentOfField + p:40 YES --> @Stand + duration:1.0 + r:false, @PlayAnimationCheering + r:false, @Stand - NO --> @ChangeAction + action:positioning, @PlaySound + file:ole.wav, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToFormationPosition - ELSE --> @ChangeAction + action:positioning, @PlaySound + file:ole.wav, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToFormationPosition - NO --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToFormationPosition + NO --> @ChangeAction + action:positioning, @PlaySound + file:ole.wav, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToRolePosition + ELSE --> @ChangeAction + action:positioning, @PlaySound + file:ole.wav, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToRolePosition + NO --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @Stand + duration:%ready_wait_time, @AvoidBallActive, @GoToRolePosition #SupporterRole $BallSeen @@ -88,7 +88,7 @@ $DoOnce #NormalBehavior $SecondBallTouchAllowed - NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToPassPreparePosition + blocking:true + NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToFormationPosition + blocking:true YES --> $BallSeen NO --> $ConfigRole STRIKER --> #SearchBall From b884405f7529ef5a394c896411379ccdee9409cf Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Tue, 30 Jun 2026 11:55:49 +0200 Subject: [PATCH 21/68] fix hysteresis call --- .../bitbots_blackboard/capsules/positioning_capsule.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 7539d8d6d..c2b093498 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -112,8 +112,8 @@ def __init__(self, node, blackboard): self._inner = InnerPositioningCapsule() self._own_locked_role: str | None = None self._own_lock_until: float = 0.0 - self._hysteresis_min: float = self._blackboard.config["role_hysteresis.min"] - self._hysteresis_max: float = self._blackboard.config["role_hysteresis.max"] + self._hysteresis_min: float = self._blackboard.config["role_hysteresis"]["min"] + self._hysteresis_max: float = self._blackboard.config["role_hysteresis"]["max"] @cached_capsule_function def get_formation_assignment(self) -> dict[int, RobotAssignment]: From 656f27f259b16f5c54a37e49a570a1b4561c8f2f Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Tue, 30 Jun 2026 13:00:11 +0200 Subject: [PATCH 22/68] fix closest to ball decision --- .../behavior_dsd/decisions/closest_to_ball.py | 3 ++- .../bitbots_team_communication.py | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index 0aa20bfe4..4a67e7a2f 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -48,7 +48,8 @@ def __init__(self, blackboard, dsd, parameters): def perform(self, reevaluate=False): role = self.blackboard.positioning.get_own_role() - return self.publish_debug_data("Role from positioning", role) + self.publish_debug_data("Role from positioning", role) + return role """if role == "STRIKER": return "STRIKER" elif role == 2: diff --git a/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py b/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py index 96279558d..9b681e32d 100755 --- a/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py +++ b/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py @@ -14,7 +14,7 @@ from game_controller_hsl_interfaces.msg import GameState, PlayerStatusPose from geometry_msgs.msg import PoseWithCovarianceStamped, Quaternion, Twist, TwistWithCovarianceStamped from numpy import double -from rclpy.callback_groups import MutuallyExclusiveCallbackGroup +from rclpy.callback_groups import ReentrantCallbackGroup from rclpy.duration import Duration from rclpy.experimental.events_executor import EventsExecutor from rclpy.node import Node @@ -66,7 +66,7 @@ def __init__(self): self.run_spin_in_thread() self.try_to_establish_connection() - self.node.create_timer(1 / self.rate, self.send_message, callback_group=MutuallyExclusiveCallbackGroup()) + self.node.create_timer(1 / self.rate, self.send_message, callback_group=ReentrantCallbackGroup()) self.receive_forever() def spin(self): @@ -264,9 +264,10 @@ def handle_message(self, string_message: bytes): def send_message(self): if not self.is_robot_allowed_to_send_message(): - self.logger.debug("Robot is not allowed to send message") + self.logger.warm("Robot is not allowed to send message") return + self.logger.warm("Send message called") now = self.get_current_time() msg = self.create_empty_message(now) From e2c3c4abe6f88e556269efdb9af9c537f44fb53c Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Wed, 1 Jul 2026 09:18:29 +0900 Subject: [PATCH 23/68] no double toch integration with Strategy passiv --- .../capsules/positioning_capsule.py | 173 +++++++++--------- .../capsules/team_data_capsule.py | 9 + 2 files changed, 98 insertions(+), 84 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index c2b093498..92ee4ab09 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -120,13 +120,14 @@ def get_formation_assignment(self) -> dict[int, RobotAssignment]: ball_pose = self._blackboard.world_model.get_best_ball_point_stamped() ball = np.array([ball_pose.point.x, ball_pose.point.y]) robot_poses = self._blackboard.team_data.get_robot_poses() + passive_robot = self._blackboard.team_data.get_index_of_passive_player() self._node.get_logger().info(f"Length of robot_poses: {len(robot_poses)}") formation = self._inner._compute_formation(ball, self._field, len(robot_poses), self._params) new_items = list(formation.items()) ordered_jerseys = sorted(robot_poses.keys()) old_poses = [robot_poses[j] for j in ordered_jerseys] - pairs = self._inner._match_assignment(old_poses, new_items, ball) + pairs = self._inner._match_assignment(old_poses, new_items, ball, passive_robot) return {ordered_jerseys[old_idx]: {"role": role, "goal_pose": new_pose} for old_idx, new_pose, role in pairs} @cached_capsule_function @@ -251,12 +252,7 @@ def _separate( goalie included, gives way around it. In normal play the goalie is far from all teammates so it never moves; it only shifts off its line in the degenerate case where the ball sits right in the goal mouth. Continuous in the inputs, - so small ball moves -> small position moves. - - If `ball`/`aim` are given, teammates inside the corridor in front of the ball - (along the kick direction) are pushed sideways out of it so they don't block - the kick; the push tapers in/out along the corridor to stay smooth. - """ + so small ball moves -> small position moves.""" fixed = {Role.STRIKER} names = list(positions.keys()) sep = params.min_sep @@ -318,45 +314,53 @@ def _clear_ball( # Assignment # --------------------------------------------------------------------------- # - def _match_assignment( - self, - old_poses: list[list[float] | NDArray[np.float64]], - new_items: list[tuple[str, NDArray[np.float64]]], - ball: NDArray[np.float64], - angle_w: float = 0.3, - ) -> list[tuple[int, NDArray[np.float64], str]]: - """Assign physical robots (at `old_poses`) to the new target poses. - - The robot closest to the ball always takes the striker target; the rest are - matched optimally (Hungarian) to minimise total cost = distance + angle_w * - heading difference. Returns a list of (old_idx, new_pose, new_role) where - old_idx is the index into `old_poses`. - `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). - """ - from scipy.optimize import linear_sum_assignment - - old_poses = [np.asarray(p) for p in old_poses] - ball = np.asarray(ball) - n = len(old_poses) - - # striker target -> the old robot nearest the ball - s_j = next(j for j, (r, _) in enumerate(new_items) if r == Role.STRIKER) - s_i = min(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) - pairs = [(s_i, new_items[s_j][1], new_items[s_j][0])] - - rem_i = [i for i in range(n) if i != s_i] - rem_j = [j for j in range(len(new_items)) if j != s_j] - if rem_i: - cost = np.empty((len(rem_i), len(rem_j))) - for a, i in enumerate(rem_i): - for b, j in enumerate(rem_j): - op, npose = old_poses[i], new_items[j][1] - cost[a, b] = np.linalg.norm(op[:2] - npose[:2]) + angle_w * self._angle_diff(op[2], npose[2]) - ri, ci = linear_sum_assignment(cost) - for a, b in zip(ri, ci): - i, j = rem_i[a], rem_j[b] - pairs.append((i, new_items[j][1], new_items[j][0])) - return pairs +def _match_assignment( + self, + old_poses: list[list[float] | NDArray[np.float64]], + new_items: list[tuple[str, NDArray[np.float64]]], + ball: NDArray[np.float64], + passiv_player: int, + angle_w: float = 0.3, +) -> list[tuple[int, NDArray[np.float64], str]]: + """Assign physical robots (at `old_poses`) to the new target poses. + The robot closest to the ball always takes the striker target; the rest are + matched optimally (Hungarian) to minimise total cost = distance + angle_w * + heading difference. Returns a list of (old_idx, new_pose, new_role) where + old_idx is the index into `old_poses`. + `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). + """ + from scipy.optimize import linear_sum_assignment + + old_poses = [np.asarray(p) for p in old_poses] + ball = np.asarray(ball) + n = len(old_poses) + + # striker target -> the old robot nearest the ball + s_j = next(j for j, (r, _) in enumerate(new_items) if r == Role.STRIKER) + + # Kandidaten nach Distanz zum Ball sortiert + candidates = sorted(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) + + # Den passiven Spieler von der Striker-Wahl ausschließen, falls vorhanden + if passiv_player is not None: + s_i = next((i for i in candidates if i != passiv_player), candidates[0]) + else: + s_i = candidates[0] + + pairs = [(s_i, new_items[s_j][1], new_items[s_j][0])] + rem_i = [i for i in range(n) if i != s_i] + rem_j = [j for j in range(len(new_items)) if j != s_j] + if rem_i: + cost = np.empty((len(rem_i), len(rem_j))) + for a, i in enumerate(rem_i): + for b, j in enumerate(rem_j): + op, npose = old_poses[i], new_items[j][1] + cost[a, b] = np.linalg.norm(op[:2] - npose[:2]) + angle_w * self._angle_diff(op[2], npose[2]) + ri, ci = linear_sum_assignment(cost) + for a, b in zip(ri, ci): + i, j = rem_i[a], rem_j[b] + pairs.append((i, new_items[j][1], new_items[j][0])) + return pairs # --------------------------------------------------------------------------- # # Formation computation @@ -389,6 +393,45 @@ def _compute_formation( head = {} # role -> heading (rad); filled lazily, completed after separation kick_aim = None # striker's kick direction; used to clear the kick lane + + # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # + defender_roles = [r for r in roles if r.startswith(Role.DEFENDER + "_")] + m = len(defender_roles) + if m > 0: + depth = np.clip( + params.alpha * d + params.depth_bias, # push up + fwd/back bias + params.D_min, + params.D_max, + ) + depth = min(depth, max(d - params.standoff, 0.0)) # stay goal-side of the ball + depth = max(depth, params.d_g + params.dz) # stay ahead of the goalie + anchor = goal + depth * to_ball + if m == 1: + # a single defender: shade to the centre side so it doesn't sit on the + # striker<->goalie line (otherwise all three are collinear) + side_dir = -1.0 if b[1] >= 0 else 1.0 + offsets = [params.def_side * side_dir] + else: + offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] + for r, off in zip(defender_roles, offsets): + out[r] = self._clamp_field(anchor + off * perp, field) + + # --- supporter: slightly in front of the ball, kept inside the field -------- # + if Role.SUPPORTER in roles: + # always sit to the centre side of the ball; hard swap so it is never + # directly in front of the striker, even when the ball is on the centre line + side_dir = -1.0 if b[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) + sup = b + np.array([params.f, params.supp_side * side_dir]) + sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner + out[Role.SUPPORTER] = self._clamp_field(sup, field) + + # --- min-separation repulsion + kick-lane clearance ----------------------- # + self._separate(out, field, params, b, kick_aim) + + # --- freekick: push every robot outside the mandatory clearance radius ---- # + if params.freekick: + self._clear_ball(out, b, params.freekick_clearance, field) + # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # if Role.STRIKER in roles: if params.freekick: @@ -430,44 +473,6 @@ def _compute_formation( ) out[Role.GOALIE] = g - # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # - defender_roles = [r for r in roles if r.startswith(Role.DEFENDER + "_")] - m = len(defender_roles) - if m > 0: - depth = np.clip( - params.alpha * d + params.depth_bias, # push up + fwd/back bias - params.D_min, - params.D_max, - ) - depth = min(depth, max(d - params.standoff, 0.0)) # stay goal-side of the ball - depth = max(depth, params.d_g + params.dz) # stay ahead of the goalie - anchor = goal + depth * to_ball - if m == 1: - # a single defender: shade to the centre side so it doesn't sit on the - # striker<->goalie line (otherwise all three are collinear) - side_dir = -1.0 if b[1] >= 0 else 1.0 - offsets = [params.def_side * side_dir] - else: - offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] - for r, off in zip(defender_roles, offsets): - out[r] = self._clamp_field(anchor + off * perp, field) - - # --- supporter: slightly in front of the ball, kept inside the field -------- # - if Role.SUPPORTER in roles: - # always sit to the centre side of the ball; hard swap so it is never - # directly in front of the striker, even when the ball is on the centre line - side_dir = -1.0 if b[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) - sup = b + np.array([params.f, params.supp_side * side_dir]) - sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner - out[Role.SUPPORTER] = self._clamp_field(sup, field) - - # --- min-separation repulsion + kick-lane clearance ----------------------- # - self._separate(out, field, params, b, kick_aim) - - # --- freekick: push every robot outside the mandatory clearance radius ---- # - if params.freekick: - self._clear_ball(out, b, params.freekick_clearance, field) - # --- orientations (computed from the final positions) --------------------- # for role, p in out.items(): if role in head: diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index 20d819fa8..1492ffce4 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -188,6 +188,15 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: if self.is_valid(data) and (data.strategy.role != Strategy.ROLE_GOALIE or count_goalies): poses.append(data.robot_position.pose) return poses + + def get_index_of_passive_player(self) -> int: + """Returns the poses of all playing robots""" + index_list = [] + data: TeamData + for data in self.team_data.values(): + if self.is_valid(data) and (data.strategy.action is Strategy.ACTION_PASSIVE): + return data.robot_id + return None def quaternion_to_yaw(self, q) -> float: """Extract yaw (theta) from a quaternion.""" From ab88f08a764988e74e281139f11d58e3b50806e9 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Wed, 1 Jul 2026 09:58:34 +0900 Subject: [PATCH 24/68] change freekick param name and add function to set it --- .../capsules/positioning_capsule.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 92ee4ab09..06880b870 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -82,8 +82,8 @@ class Params: kick_clear: float = 0.7 # half-width of the cleared corridor kick_range: float = 3.0 # how far in front of the ball the corridor extends # opponent free kick / goal kick / penalty: keep all robots outside this radius - freekick: bool = False - freekick_clearance: float = 0.75 + opp_freekick: bool = False + opp_freekick_clearance: float = 0.8 class PositioningCapsule(AbstractBlackboardCapsule): @@ -115,6 +115,9 @@ def __init__(self, node, blackboard): self._hysteresis_min: float = self._blackboard.config["role_hysteresis"]["min"] self._hysteresis_max: float = self._blackboard.config["role_hysteresis"]["max"] + def set_opp_freekick_active(self, b: bool) -> None: + self._params.opp_freekick = b + @cached_capsule_function def get_formation_assignment(self) -> dict[int, RobotAssignment]: ball_pose = self._blackboard.world_model.get_best_ball_point_stamped() @@ -386,7 +389,7 @@ def _compute_formation( perp = np.array([-to_ball[1], to_ball[0]]) roles = self._allocate_roles(n_players, b, field) - if params.freekick and Role.SUPPORTER in roles: + if params.opp_freekick and Role.SUPPORTER in roles: n_def = sum(1 for r in roles if r.startswith(Role.DEFENDER + "_")) roles[roles.index(Role.SUPPORTER)] = f"{Role.DEFENDER}_{n_def}" out = {} @@ -429,15 +432,15 @@ def _compute_formation( self._separate(out, field, params, b, kick_aim) # --- freekick: push every robot outside the mandatory clearance radius ---- # - if params.freekick: - self._clear_ball(out, b, params.freekick_clearance, field) + if params.opp_freekick: + self._clear_ball(out, b, params.opp_freekick_clearance, field) # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # if Role.STRIKER in roles: - if params.freekick: + if params.opp_freekick: # park at the clearance boundary on the goal side, facing the ball dir_to_goal = self._normalize(goal - b, fallback=np.array([-1.0, 0.0])) - out[Role.STRIKER] = self._clamp_field(b + params.freekick_clearance * dir_to_goal, field) + out[Role.STRIKER] = self._clamp_field(b + params.opp_freekick_clearance * dir_to_goal, field) # heading will be computed in the orientation pass (face ball) else: h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth From 2ef42fe57707a6b3881f3da85da6241966d55270 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Wed, 1 Jul 2026 10:56:44 +0900 Subject: [PATCH 25/68] fixes sim errors --- .../capsules/positioning_capsule.py | 94 +++++++++---------- .../bitbots_team_communication.py | 6 +- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 06880b870..39e91a539 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -317,53 +317,53 @@ def _clear_ball( # Assignment # --------------------------------------------------------------------------- # -def _match_assignment( - self, - old_poses: list[list[float] | NDArray[np.float64]], - new_items: list[tuple[str, NDArray[np.float64]]], - ball: NDArray[np.float64], - passiv_player: int, - angle_w: float = 0.3, -) -> list[tuple[int, NDArray[np.float64], str]]: - """Assign physical robots (at `old_poses`) to the new target poses. - The robot closest to the ball always takes the striker target; the rest are - matched optimally (Hungarian) to minimise total cost = distance + angle_w * - heading difference. Returns a list of (old_idx, new_pose, new_role) where - old_idx is the index into `old_poses`. - `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). - """ - from scipy.optimize import linear_sum_assignment - - old_poses = [np.asarray(p) for p in old_poses] - ball = np.asarray(ball) - n = len(old_poses) - - # striker target -> the old robot nearest the ball - s_j = next(j for j, (r, _) in enumerate(new_items) if r == Role.STRIKER) - - # Kandidaten nach Distanz zum Ball sortiert - candidates = sorted(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) - - # Den passiven Spieler von der Striker-Wahl ausschließen, falls vorhanden - if passiv_player is not None: - s_i = next((i for i in candidates if i != passiv_player), candidates[0]) - else: - s_i = candidates[0] - - pairs = [(s_i, new_items[s_j][1], new_items[s_j][0])] - rem_i = [i for i in range(n) if i != s_i] - rem_j = [j for j in range(len(new_items)) if j != s_j] - if rem_i: - cost = np.empty((len(rem_i), len(rem_j))) - for a, i in enumerate(rem_i): - for b, j in enumerate(rem_j): - op, npose = old_poses[i], new_items[j][1] - cost[a, b] = np.linalg.norm(op[:2] - npose[:2]) + angle_w * self._angle_diff(op[2], npose[2]) - ri, ci = linear_sum_assignment(cost) - for a, b in zip(ri, ci): - i, j = rem_i[a], rem_j[b] - pairs.append((i, new_items[j][1], new_items[j][0])) - return pairs + def _match_assignment( + self, + old_poses: list[list[float] | NDArray[np.float64]], + new_items: list[tuple[str, NDArray[np.float64]]], + ball: NDArray[np.float64], + passiv_player: int | None, + angle_w: float = 0.3, + ) -> list[tuple[int, NDArray[np.float64], str]]: + """Assign physical robots (at `old_poses`) to the new target poses. + The robot closest to the ball always takes the striker target; the rest are + matched optimally (Hungarian) to minimise total cost = distance + angle_w * + heading difference. Returns a list of (old_idx, new_pose, new_role) where + old_idx is the index into `old_poses`. + `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). + """ + from scipy.optimize import linear_sum_assignment + + old_poses = [np.asarray(p) for p in old_poses] + ball = np.asarray(ball) + n = len(old_poses) + + # striker target -> the old robot nearest the ball + s_j = next(j for j, (r, _) in enumerate(new_items) if r == Role.STRIKER) + + # Kandidaten nach Distanz zum Ball sortiert + candidates = sorted(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) + + # Den passiven Spieler von der Striker-Wahl ausschließen, falls vorhanden + if passiv_player is not None: + s_i = next((i for i in candidates if i != passiv_player), candidates[0]) + else: + s_i = candidates[0] + + pairs = [(s_i, new_items[s_j][1], new_items[s_j][0])] + rem_i = [i for i in range(n) if i != s_i] + rem_j = [j for j in range(len(new_items)) if j != s_j] + if rem_i: + cost = np.empty((len(rem_i), len(rem_j))) + for a, i in enumerate(rem_i): + for b, j in enumerate(rem_j): + op, npose = old_poses[i], new_items[j][1] + cost[a, b] = np.linalg.norm(op[:2] - npose[:2]) + angle_w * self._angle_diff(op[2], npose[2]) + ri, ci = linear_sum_assignment(cost) + for a, b in zip(ri, ci): + i, j = rem_i[a], rem_j[b] + pairs.append((i, new_items[j][1], new_items[j][0])) + return pairs # --------------------------------------------------------------------------- # # Formation computation diff --git a/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py b/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py index 9b681e32d..c482209a3 100755 --- a/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py +++ b/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py @@ -14,7 +14,7 @@ from game_controller_hsl_interfaces.msg import GameState, PlayerStatusPose from geometry_msgs.msg import PoseWithCovarianceStamped, Quaternion, Twist, TwistWithCovarianceStamped from numpy import double -from rclpy.callback_groups import ReentrantCallbackGroup +from rclpy.callback_groups import MutuallyExclusiveCallbackGroup from rclpy.duration import Duration from rclpy.experimental.events_executor import EventsExecutor from rclpy.node import Node @@ -66,7 +66,7 @@ def __init__(self): self.run_spin_in_thread() self.try_to_establish_connection() - self.node.create_timer(1 / self.rate, self.send_message, callback_group=ReentrantCallbackGroup()) + self.node.create_timer(1 / self.rate, self.send_message, callback_group=MutuallyExclusiveCallbackGroup()) self.receive_forever() def spin(self): @@ -264,7 +264,7 @@ def handle_message(self, string_message: bytes): def send_message(self): if not self.is_robot_allowed_to_send_message(): - self.logger.warm("Robot is not allowed to send message") + self.logger.debug("Robot is not allowed to send message") return self.logger.warm("Send message called") From b9bfea2f2932741fb5843a4e1b8e38046991fe96 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Wed, 1 Jul 2026 10:57:24 +0900 Subject: [PATCH 26/68] this as well --- .../bitbots_blackboard/capsules/team_data_capsule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index 1492ffce4..d21ea67fe 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -189,7 +189,7 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: poses.append(data.robot_position.pose) return poses - def get_index_of_passive_player(self) -> int: + def get_index_of_passive_player(self) -> int | None: """Returns the poses of all playing robots""" index_list = [] data: TeamData From 104cea87c92cc2a83e76e42f4a78f18a12f56255 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Wed, 1 Jul 2026 13:20:07 +0900 Subject: [PATCH 27/68] remove wrong log --- .../bitbots_team_communication/bitbots_team_communication.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py b/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py index c482209a3..96279558d 100755 --- a/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py +++ b/src/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication.py @@ -267,7 +267,6 @@ def send_message(self): self.logger.debug("Robot is not allowed to send message") return - self.logger.warm("Send message called") now = self.get_current_time() msg = self.create_empty_message(now) From b6b222d7df7a89e3c2519051d28e19799353c2f6 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Wed, 1 Jul 2026 15:37:30 +0900 Subject: [PATCH 28/68] add own action to get passive --- .../bitbots_blackboard/capsules/positioning_capsule.py | 2 +- .../bitbots_blackboard/capsules/team_data_capsule.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 39e91a539..ee4776cbf 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -123,7 +123,7 @@ def get_formation_assignment(self) -> dict[int, RobotAssignment]: ball_pose = self._blackboard.world_model.get_best_ball_point_stamped() ball = np.array([ball_pose.point.x, ball_pose.point.y]) robot_poses = self._blackboard.team_data.get_robot_poses() - passive_robot = self._blackboard.team_data.get_index_of_passive_player() + passive_robot = self._blackboard.team_data.get_id_of_passive_player() self._node.get_logger().info(f"Length of robot_poses: {len(robot_poses)}") formation = self._inner._compute_formation(ball, self._field, len(robot_poses), self._params) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index d21ea67fe..161f76d43 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -189,13 +189,16 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: poses.append(data.robot_position.pose) return poses - def get_index_of_passive_player(self) -> int | None: + def get_in_of_passive_player(self) -> int | None: """Returns the poses of all playing robots""" index_list = [] data: TeamData for data in self.team_data.values(): + self._node.getLogger if self.is_valid(data) and (data.strategy.action is Strategy.ACTION_PASSIVE): - return data.robot_id + return data.robot_id + if self.strategy.action is Strategy.ACTION_PASSIVE: + return self._blackboard.gamestate.get_own_id() return None def quaternion_to_yaw(self, q) -> float: From ee12f9080a6cacee648051913a11beb10dfdee98 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Thu, 2 Jul 2026 15:27:04 +0900 Subject: [PATCH 29/68] some more dsd fixes --- .../behavior_dsd/decisions/closest_to_ball.py | 2 +- .../behavior_dsd/main.dsd | 23 +++++++------------ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index 4a67e7a2f..cc83a2842 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -40,7 +40,7 @@ def get_reevaluate(self): return True -class RankToBallWithGoalie(AbstractDecisionElement): +class AssignedRole(AbstractDecisionElement): blackboard: BodyBlackboard def __init__(self, blackboard, dsd, parameters): diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 8cc786133..7f5a3bf36 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -54,7 +54,9 @@ $GoalScoreRecently #SupporterRole $BallSeen - YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + YES --> $PassStarted + YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition @@ -72,16 +74,8 @@ $SecondaryStateTeamDecider #Placing $DoOnce NOT_DONE --> @ForgetBall, @LookAtFieldFeatures - DONE --> $ConfigRole - GOALIE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition - ELSE --> $BallSeen - NO --> #SearchBall - YES --> $RankToBallWithGoalie - STRIKER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition //ugly yet - DEFENDER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition - SUPPORTER --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition - GOALIE --> @GoToGoaliePosition - ELSE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToFormationPosition + DONE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition + #Init @Stand + duration:0.1 + r:false, @ChangeAction + action:waiting, @LookForward, @Stand @@ -96,10 +90,9 @@ $SecondBallTouchAllowed YES --> $KickOffTimeUp NO_NORMAL --> #StandAndLook NO_FREEKICK --> #Placing - YES --> $RankToBallWithGoalie + YES --> $AssignedRole STRIKER --> #KickWithAvoidance - GOALIE --> @GoToFormationPosition - DEFENDER --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + GOALIE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition SUPPORTER --> #SupporterRole ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition @@ -142,7 +135,7 @@ $IsPenalized SET --> $WhistleDetected DETECTED --> $SecondaryStateTeamDecider OUR --> #PlayingBehavior - OTHER --> @GoToFormationPosition + OTHER --> #PositioningReady ELSE --> #PlayingBehavior NOT_DETECTED --> $SecondaryStateDecider PENALTYSHOOT --> $SecondaryStateTeamDecider From 1b03218c75c5f311c39e9a4de164d1e633942b65 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Thu, 2 Jul 2026 19:38:17 +0900 Subject: [PATCH 30/68] check for alingnement with goalPose to stop moving on place --- .../behavior_dsd/main.dsd | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 7f5a3bf36..ecc2a462e 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -54,9 +54,11 @@ $GoalScoreRecently #SupporterRole $BallSeen - YES --> $PassStarted - YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + YES --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true + YES --> #StandAndLook + NO --> $PassStarted + YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition @@ -74,7 +76,9 @@ $SecondaryStateTeamDecider #Placing $DoOnce NOT_DONE --> @ForgetBall, @LookAtFieldFeatures - DONE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition + DONE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true + YES --> #StandAndLook + NO --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition #Init @@ -82,7 +86,9 @@ $DoOnce #NormalBehavior $SecondBallTouchAllowed - NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToFormationPosition + blocking:true + NO --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true + YES --> #StandAndLook + NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToFormationPosition + blocking:true YES --> $BallSeen NO --> $ConfigRole STRIKER --> #SearchBall @@ -92,9 +98,10 @@ $SecondBallTouchAllowed NO_FREEKICK --> #Placing YES --> $AssignedRole STRIKER --> #KickWithAvoidance - GOALIE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition SUPPORTER --> #SupporterRole - ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + ELSE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true + YES --> StandAndLook + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition #ThrowinGoalKickCornerkickBehavior $DoOnce From 5190a1353963623b6a65096ff46697dc8e3849d2 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Thu, 2 Jul 2026 21:16:21 +0900 Subject: [PATCH 31/68] fix for communicated actions --- .../bitbots_blackboard/capsules/team_data_capsule.py | 3 +-- .../bitbots_body_behavior/behavior_dsd/main.dsd | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index 161f76d43..c64eda21c 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -189,12 +189,11 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: poses.append(data.robot_position.pose) return poses - def get_in_of_passive_player(self) -> int | None: + def get_id_of_passive_player(self) -> int | None: """Returns the poses of all playing robots""" index_list = [] data: TeamData for data in self.team_data.values(): - self._node.getLogger if self.is_valid(data) and (data.strategy.action is Strategy.ACTION_PASSIVE): return data.robot_id if self.strategy.action is Strategy.ACTION_PASSIVE: diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index ecc2a462e..45cafdd00 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -55,7 +55,7 @@ $GoalScoreRecently #SupporterRole $BallSeen YES --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true - YES --> #StandAndLook + YES --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @Stand NO --> $PassStarted YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition @@ -77,7 +77,7 @@ $SecondaryStateTeamDecider $DoOnce NOT_DONE --> @ForgetBall, @LookAtFieldFeatures DONE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true - YES --> #StandAndLook + YES --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @Stand NO --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition @@ -87,7 +87,7 @@ $DoOnce #NormalBehavior $SecondBallTouchAllowed NO --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true - YES --> #StandAndLook + YES --> @ChangeAction + action:passive, @LookAtFieldFeatures, @Stand NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToFormationPosition + blocking:true YES --> $BallSeen NO --> $ConfigRole @@ -100,7 +100,7 @@ $SecondBallTouchAllowed STRIKER --> #KickWithAvoidance SUPPORTER --> #SupporterRole ELSE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true - YES --> StandAndLook + YES --> #StandAndLook NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition #ThrowinGoalKickCornerkickBehavior From 09a1641a1b6e6d11fced633e1adaeb0873908ccc Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Fri, 3 Jul 2026 10:05:23 +0900 Subject: [PATCH 32/68] quick save continue in formation position --- .../actions/go_to_formation_position.py | 25 ++++++++++++++++++- .../behavior_dsd/main.dsd | 12 +++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py index f8dce21d5..dcb1d6e27 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py @@ -22,4 +22,27 @@ def perform(self, reevaluate=False): pose_msg.pose.position.y = pose[1] pose_msg.pose.orientation.w = pose[2] - self.blackboard.pathfinding.publish(pose_msg) + if self.latched: + # Cancel the path planning if it is running + self.blackboard.pathfinding.cancel_goal() + # need to keep publishing this since path planning publishes a few more messages + self.blackboard.pathfinding.stop_walk() + + current_pose = self.blackboard.world_model.get_current_position_pose_stamped() + + if current_pose is None or pose is None: + return self.blackboard.pathfinding.publish(pose_msg) + + current_orientation = euler_from_quaternion(numpify(current_pose.pose.orientation)) + goal_orientation = euler_from_quaternion(numpify(goal_pose.pose.orientation)) + angle_to_goal_orientation = abs(math.remainder(current_orientation[2] - goal_orientation[2], math.tau)) + self.publish_debug_data("current_orientation", current_orientation[2]) + self.publish_debug_data("goal_orientation", goal_orientation[2]) + self.publish_debug_data("angle_to_goal_orientation", angle_to_goal_orientation) + + distance = np.linalg.norm(numpify(goal_pose.pose.position) - numpify(current_pose.pose.position)) + self.publish_debug_data("distance", distance) + if distance < self.threshold and angle_to_goal_orientation < self.orientation_threshold: + self.latched = self.latch # Set it to true if we always want to return YES in the future + return "YES" + return "NO" diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 45cafdd00..7c3fb82e7 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -76,9 +76,7 @@ $SecondaryStateTeamDecider #Placing $DoOnce NOT_DONE --> @ForgetBall, @LookAtFieldFeatures - DONE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true - YES --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @Stand - NO --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition + DONE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition #Init @@ -86,9 +84,7 @@ $DoOnce #NormalBehavior $SecondBallTouchAllowed - NO --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true - YES --> @ChangeAction + action:passive, @LookAtFieldFeatures, @Stand - NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToFormationPosition + blocking:true + NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToFormationPosition + blocking:true YES --> $BallSeen NO --> $ConfigRole STRIKER --> #SearchBall @@ -99,9 +95,7 @@ $SecondBallTouchAllowed YES --> $AssignedRole STRIKER --> #KickWithAvoidance SUPPORTER --> #SupporterRole - ELSE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true - YES --> #StandAndLook - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition #ThrowinGoalKickCornerkickBehavior $DoOnce From d86cc96066a91c85037f4f1a7d99dc24d43d5d67 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Fri, 3 Jul 2026 11:59:13 +0900 Subject: [PATCH 33/68] add reached goal logic to go to formation --- .../actions/go_to_formation_position.py | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py index dcb1d6e27..4768ac429 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py @@ -1,7 +1,11 @@ +import math +import numpy as np from bitbots_blackboard.body_blackboard import BodyBlackboard from dynamic_stack_decider.abstract_action_element import AbstractActionElement from tf2_geometry_msgs import PoseStamped +from ros2_numpy import numpify +from tf_transformations import euler_from_quaternion class GoToFormationPosition(AbstractActionElement): @@ -22,27 +26,25 @@ def perform(self, reevaluate=False): pose_msg.pose.position.y = pose[1] pose_msg.pose.orientation.w = pose[2] - if self.latched: - # Cancel the path planning if it is running - self.blackboard.pathfinding.cancel_goal() - # need to keep publishing this since path planning publishes a few more messages - self.blackboard.pathfinding.stop_walk() - current_pose = self.blackboard.world_model.get_current_position_pose_stamped() - if current_pose is None or pose is None: - return self.blackboard.pathfinding.publish(pose_msg) + #Dont try the check without current_pose, we dont want to stop a robot while going to ball, or kicking + if current_pose is None or self.blackboard.team_data.strategy.action == 2 or self.blackboard.team_data.strategy.action == 6: + self.blackboard.pathfinding.publish(pose_msg) + return current_orientation = euler_from_quaternion(numpify(current_pose.pose.orientation)) - goal_orientation = euler_from_quaternion(numpify(goal_pose.pose.orientation)) + goal_orientation = euler_from_quaternion(numpify(pose.pose.orientation)) angle_to_goal_orientation = abs(math.remainder(current_orientation[2] - goal_orientation[2], math.tau)) self.publish_debug_data("current_orientation", current_orientation[2]) self.publish_debug_data("goal_orientation", goal_orientation[2]) self.publish_debug_data("angle_to_goal_orientation", angle_to_goal_orientation) - distance = np.linalg.norm(numpify(goal_pose.pose.position) - numpify(current_pose.pose.position)) + distance = np.linalg.norm(numpify(pose.pose.position) - numpify(current_pose.pose.position)) self.publish_debug_data("distance", distance) - if distance < self.threshold and angle_to_goal_orientation < self.orientation_threshold: - self.latched = self.latch # Set it to true if we always want to return YES in the future - return "YES" - return "NO" + if distance < 0.2 and angle_to_goal_orientation < 0.2: + # Cancel the path planning if it is running + self.blackboard.pathfinding.cancel_goal() + # need to keep publishing this since path planning publishes a few more messages + self.blackboard.pathfinding.stop_walk() + self.blackboard.pathfinding.publish(pose_msg) From e10883c3783f931ff5a70dac376630f415f02f49 Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Fri, 3 Jul 2026 18:09:21 +0900 Subject: [PATCH 34/68] Fix small regressions --- pixi.lock | 4802 ++++++++++++----- .../capsules/positioning_capsule.py | 78 +- .../scripts/debug_positioning.py | 6 +- 3 files changed, 3627 insertions(+), 1259 deletions(-) diff --git a/pixi.lock b/pixi.lock index 00ead1c06..cae2d0fb7 100644 --- a/pixi.lock +++ b/pixi.lock @@ -6,22 +6,12 @@ platforms: - __linux=4.18 - __glibc=2.28 - __archspec=0=x86_64 - virtual-packages: - - __unix=0=0 - - __linux=4.18 - - __glibc=2.28 - - __archspec=0=x86_64 - name: linux-aarch64 virtual-packages: - __unix=0=0 - __linux=4.18 - __glibc=2.28 - __archspec=0=aarch64 - virtual-packages: - - __unix=0=0 - - __linux=4.18 - - __glibc=2.28 - - __archspec=0=aarch64 environments: default: channels: @@ -34,8 +24,8 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/adwaita-icon-theme-3.38.0-hbf89446_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.13.5-py312h5d8c7f2_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.14.1-py312h5d8c7f2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16.1-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-plugins-1.2.12-h989ed37_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aom-3.9.1-hac33072_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/assimp-5.4.3-hecf2907_1.conda @@ -43,7 +33,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/attr-2.5.2-hb03c661_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.6.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bcrypt-5.0.0-py312h868fb18_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/benchmark-1.9.5-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.45.1-default_h4852527_102.conda @@ -71,11 +61,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-14.3.0-he8ccf15_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/console_bridge-1.0.2-h924138e_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py312h0a2e395_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.14.1-py312h8a5da7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.15.0-py312h8a5da7c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cppcheck-2.18.3-py312h014360a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cppzmq-4.11.0-hbe92c44_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-48.0.0-py312ha4b625e_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/curl-8.20.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-49.0.0-py312ha4b625e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/curl-8.21.0-hae6b9f4_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.11.0-hfcd1e18_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hac629b4_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dav1d-1.2.1-hd590300_0.conda @@ -86,7 +76,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-abi-3.4.0.100-h3bcb7cf_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/elfutils-0.194-h849f50c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/epoxy-1.5.10-hb03c661_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fcl-0.7.0-h543440a_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_h43fde53_912.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fftw-3.3.11-nompi_h3b011a4_100.conda @@ -103,19 +93,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.8.0-py312h447239a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-h235f0fe_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h50e9bb6_25.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.6-h2b0a6b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h50e9bb6_27.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.7-h2b0a6b4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-0.25.1-h3f43e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-tools-0.25.1-h3f43e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran-14.3.0-he448592_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_impl_linux-64-14.3.0-h1a219da_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_linux-64-14.3.0-h8bb2d51_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_linux-64-14.3.0-h5ce6d8a_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/git-2.54.0-pl5321h6d3cee1_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gl2ps-1.4.2-h36e74d4_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glew-2.3.0-h71661d4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glfw-3.4-hb03c661_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.88.1-hd810c12_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.88.2-hbe0478d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.2-h8094192_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glslang-16.3.0-h96af755_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gmock-1.17.0-ha770c72_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda @@ -130,14 +120,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/gts-0.7.6-h977cf35_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-14.3.0-he448592_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.3.0-h2185e75_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-h72ca5df_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-hd240bd5_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-cmake3-3.5.5-h05f81b2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-math7-7.5.2-h5bbc156_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-math7-python-7.5.2-py312h89d136e_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-tools-2.0.3-h3f54f1a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-tools2-2.0.3-h89235b8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-utils2-2.2.1-hdaf9e28_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-14.2.1-h6083320_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-14.2.1-ha770c72_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf4-4.2.15-h2a13503_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda @@ -151,7 +141,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py312h0a2e395_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbde042b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lame-3.100-h166bdaf_1003.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda @@ -160,7 +150,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libacl-2.3.2-h0f662aa_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.7-gpl_hc2c16d8_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.8-gpl_hc2c16d8_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-0.25.1-h3f43e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-devel-0.25.1-h3f43e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libass-0.17.4-h96ad9f0_0.conda @@ -179,10 +169,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libccd-double-2.1-h59595ed_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp21.1-21.1.8-default_h99862b1_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.7-default_h99862b1_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.7-default_h746c552_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.8-default_h6c227bf_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_h9692865_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.21.0-hae6b9f4_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.127-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda @@ -190,7 +180,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.4.3-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda @@ -204,7 +194,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-devel-1.7.0-ha4b6fd6_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.1-h0d30a3d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.2-h0d30a3d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglu-9.0.3-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_3.conda @@ -215,6 +205,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-math7-7.5.2-h54a6638_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-tools-2.0.3-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-utils2-2.2.1-h54a6638_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-14.2.1-h17a8019_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-devel-14.2.1-h17a8019_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.13.0-default_he001693_1000.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwy-1.4.0-h10be129_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda @@ -224,7 +216,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapacke-3.11.0-8_h6ae95b6_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.7-hf7376ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libltdl-2.4.3a-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.3-hb03c661_0.conda @@ -256,15 +248,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libopus-1.6.1-h280c20c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-6.31.1-hfb7daa7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.22.0-hd9031aa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libraqm-0.10.5-h6406941_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libraw-0.22.1-h074291d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/librsvg-2.62.3-h4c96295_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-14.3.0-h8f1669f_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsdformat14-14.8.0-py312h1f51ce1_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsndfile-1.2.2-hc60ed4a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.22-h280c20c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.2-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda @@ -279,9 +273,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/liburcu-0.14.0-hac33072_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liburing-2.14-hb700be7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libusb-1.0.29-h73b1eb8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.23.0-he1eb515_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.24.0-he1eb515_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvorbis-1.3.7-h54a6638_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvpl-2.15.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvpx-1.15.2-hecca717_0.conda @@ -304,11 +298,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.10.9-py312h7900ff3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.10.9-py312he3d6523_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.11.0-py312h7900ff3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.11.0-py312hc1765e9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mesalib-26.0.3-h8cca3c9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mpg123-1.32.9-hc50e24c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py312hd9148b4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.2.1-py312h0a2e395_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-3.6.0-h1eba5cb_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-python-3.6.0-np2py312h2fcff2b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-samples-3.6.0-h3c404ae_0.conda @@ -328,12 +322,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/onnxruntime-1.26.0-py312hb39aaa6_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencv-4.12.0-qt6_py312h7bb6282_612.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openexr-3.4.12-h9f1635d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openexr-3.4.13-hf734b31_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-h65dd3cf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openjph-0.27.4-h8d634f6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openjph-0.30.1-h8d634f6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.13-hbde042b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orocos-kdl-1.5.3-hca8cc02_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/p11-kit-0.26.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hda50119_1.conda @@ -364,7 +358,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/pyqt5-sip-12.17.0-py312h1289d80_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyside6-6.10.2-py312h50ac2ff_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.1-hab00c5b_1_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.11.0-py312h5253ce2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.12.0-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-orocos-kdl-1.5.3-py312h1289d80_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda @@ -372,29 +366,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.10.2-pl5321h16c4a6b_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rapidjson-1.1.0.post20240409-h3f2d84a_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rav1e-0.8.1-h1fbca29_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.6.28-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rsync-3.4.3-h5440a77_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rsync-3.4.4-h5440a77_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruby-4.0.5-h95e6935_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.14.14-h40fa522_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdformat14-14.8.0-h5bb51b8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdformat14-python-14.8.0-py312h22a3d64_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl2-2.32.56-h54a6638_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.4.10-hdeec2a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.4.12-hdeec2a5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/shaderc-2025.5-h718be3e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sip-6.10.0-py312h1289d80_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/soxr-0.1.3-h0b41bf4_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/spirv-tools-2026.2-hb700be7_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.2-hbc0de68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.3-hbc0de68_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/svt-av1-4.0.1-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2023.0.0-hab88423_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-devel-2023.0.0-hab88423_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tinyxml2-11.0.0-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.6-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.7-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py312hd9148b4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/uncrustify-0.83.0-h54a6638_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda @@ -407,7 +401,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/vtk-base-9.5.2-py312h6fba518_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/vtk-io-ffmpeg-9.5.2-py312hcdbd8b1_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.25.0-hd6090a7_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.2.1-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.2.2-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/x264-1!164.3095-h166bdaf_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/x265-3.5-h924138e_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda @@ -416,7 +410,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-keysyms-0.4.1-hb711507_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-renderutil-0.3.10-hb711507_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-wm-0.4.2-hb711507_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.47-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.48-h280c20c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda @@ -454,32 +448,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zziplib-0.13.69-he45264a_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/absl-py-2.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.7.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beartype-0.22.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/breathe-4.36.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/catkin_pkg-1.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.6.17-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-argcomplete-0.3.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-bash-0.5.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cd-0.1.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.29-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.30-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-core-0.21.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-defaults-0.2.9-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-devtools-0.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-library-path-0.2.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-metadata-0.2.5-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.13-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.14-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-information-0.4.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-selection-0.2.10-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-parallel-executor-0.4.0-pyhe01879c_0.conda @@ -496,7 +490,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.3.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dnspython-2.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda @@ -505,7 +499,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fabric-3.2.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-7.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-builtins-3.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-comprehensions-3.17.0-pyhd8ed1ab_0.conda @@ -519,26 +513,26 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/git-subrepo-0.4.9-hc364b38_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.19-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.17-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.18-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.15.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.20.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-parser-0.12.0-pyhd8ed1ab_1.conda @@ -587,9 +581,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-7.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-mock-3.15.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-repeat-0.9.4-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda @@ -601,7 +595,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/simpleeval-1.0.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda @@ -613,7 +607,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jquery-4.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-2.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda @@ -621,13 +615,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/transforms3d-0.4.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.4.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.5.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.47-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.49-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.8-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wslink-2.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda @@ -1008,29 +1002,28 @@ environments: - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros-jazzy-zstd-vendor-0.26.9-np2py312h2ed9cc7_16.conda - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros2-distro-mutex-0.14.0-jazzy_16.conda - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda - - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2022_10_07_flo_torso21_yoeox-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/tts-supertonic-1.0.0-h4616a5c_1.conda - - conda_source: bitbots_rust_nav[eb738ce2] @ src/bitbots_navigation/bitbots_rust_nav + - conda_source: bitbots_rust_nav[146a3083] @ src/bitbots_navigation/bitbots_rust_nav - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/de/0880cf8af64b225bc8fde0924f76ea5e6cd8d8dc50c6dd61232beb54327f/mjviser-0.0.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/47/aa/218a0eb34de1f753c83e4d0d1c8e7c4cef27f20dcb8342e024f63a80dc86/tqdm-4.68.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4a/c9/9a4ca25b505303d5557c98786ac0bf7081c76a7262e1b6c87b899bccc7b8/viser-1.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/53/60/7be26e610767316c028a2cbedb9a3beabdbe33e2182c373f71a1c0b88f36/zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5e/f5/0c41cb68dcae6b7de4fac4188a3a9589e21fb31df21ea3a2e888db95e6c9/soupsieve-2.8.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/80/0c7095f357afeb52100d312250354d2e76afb779c81fe3fb52118076fa5a/syrupy-5.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/c6/92fcd42f1ba33e1184263f25bfabf3d27c383410470f169e4b8163bf9c17/beautifulsoup4-4.15.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b5/d1/d4cd9fe89c7d400d7a18f86ccc94daa3f0927f53558846fcb60791dce5d6/msgspec-0.21.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d4/f4/753003ddb0d43247febecd5146391a59b80f77e462b2623396192180f4ee/syrupy-5.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/8e/bb97bb0c71802080bfc8952937d174e49cfc50de5c951dd47b2496f0dcdb/tqdm-4.68.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ea/78/9a8a174011682d71cb4922f4014ebbeb9d3067922678e7059351fd9207cf/exhale-0.3.7-py3-none-any.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/adwaita-icon-theme-3.38.0-h2d234d2_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.13.5-py312he7e3343_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.16-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.14.1-py312he7e3343_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.16.1-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-plugins-1.2.12-haf9f4a6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aom-3.9.1-hcccb83c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/assimp-5.4.3-he8c3857_1.conda @@ -1038,7 +1031,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/at-spi2-core-2.40.3-h1f2db35_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/atk-1.0-2.38.0-hedc4a1f_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/attr-2.5.2-he30d5cf_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.5.0-py312ha46dd1d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.6.0-py312ha46dd1d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bcrypt-5.0.0-py312h5eb8f6c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/benchmark-1.9.5-hfae3067_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.45.1-default_hf1166c9_102.conda @@ -1066,11 +1059,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-gcc-specs-14.3.0-hadff5d6_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/console_bridge-1.0.2-hdd96247_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/contourpy-1.3.3-py312hf18b547_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.14.1-py312hd077ced_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.15.0-py312hd077ced_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cppcheck-2.18.3-py312h5677ec4_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cppzmq-4.11.0-h7be3492_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-48.0.0-py312h96535df_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/curl-8.20.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-49.0.0-py312h96535df_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/curl-8.21.0-h7c59cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.11.0-h7b35c40_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cyrus-sasl-2.1.28-h6598af7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/dav1d-1.2.1-h31becfc_0.conda @@ -1081,7 +1074,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/eigen-abi-3.4.0.100-h9a8c16c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/elfutils-0.194-h7d8af26_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/epoxy-1.5.10-he30d5cf_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fcl-0.7.0-h841ecf2_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ffmpeg-8.0.1-gpl_hd1a4c92_912.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fftw-3.3.11-nompi_h66d8d02_100.conda @@ -1093,24 +1086,24 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fortran-compiler-1.11.0-h151373c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freeglut-3.2.2-hddf9bb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freeimage-3.18.0-he4296dc_25.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freetype-2.14.3-h8af1aa0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freetype-2.14.3-h8af1aa0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fribidi-1.0.16-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.8.0-py312hb10c72c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-14.3.0-h2e72a27_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-14.3.0-h398eab4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h140ef2e_25.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gdk-pixbuf-2.44.6-h90308e0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h140ef2e_27.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gdk-pixbuf-2.44.7-h90308e0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gettext-0.25.1-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gettext-tools-0.25.1-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran-14.3.0-ha28f942_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_impl_linux-aarch64-14.3.0-h6b0ea1e_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_linux-aarch64-14.3.0-h495b507_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_linux-aarch64-14.3.0-h4981040_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/git-2.54.0-pl5321h5dcfaa0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gl2ps-1.4.2-hd9db0c5_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glew-2.3.0-hf9dcc85_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glfw-3.4-he30d5cf_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-2.88.1-h72f18f7_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-tools-2.88.1-h7439e1d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-2.88.2-hdf12349_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-tools-2.88.2-h7aeb4f4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glslang-16.3.0-h124e036_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmock-1.17.0-h8af1aa0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmp-6.3.0-h0a1ffab_2.conda @@ -1125,14 +1118,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gts-0.7.6-he293c15_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-14.3.0-ha28f942_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-14.3.0-h0d4f5d4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h73dd529_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h0da240b_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-cmake3-3.5.5-h740f95d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-math7-7.5.2-h1ad700d_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-math7-python-7.5.2-py312h9452373_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-tools-2.0.3-h8a9b3d2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-tools2-2.0.3-hd91f489_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-utils2-2.2.1-h2ce864c_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-14.2.1-h1134a53_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-14.2.1-h8af1aa0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hdf4-4.2.15-hb6ba311_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hdf5-1.14.6-nompi_hf95b8e7_110.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hicolor-icon-theme-0.17-h8af1aa0_3.conda @@ -1144,7 +1137,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/jxrlib-1.1-h31becfc_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kiwisolver-1.5.0-py312h1683e8e_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-h2fb54aa_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lame-3.100-h4e544f5_1003.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda @@ -1152,7 +1145,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20250512.1-cxx17_h201e9ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libacl-2.3.2-h883460d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libaec-1.1.5-hff7e48a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.7-gpl_hbe7d12b_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.8-gpl_hbe7d12b_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libasprintf-0.25.1-h5e0f5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libasprintf-devel-0.25.1-h5e0f5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libass-0.17.4-hcfe818d_0.conda @@ -1171,10 +1164,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-8_hd72aa62_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libccd-double-2.1-h2f0025b_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp21.1-21.1.8-default_he95a3c9_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.7-default_h2a92e99_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.7-default_h3185f35_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.8-default_h0cc847a_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.8-default_hd92691d_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.20.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.21.0-h7c59cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdrm-2.4.127-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda @@ -1182,11 +1175,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libegl-devel-1.7.0-hd24410f_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libflac-1.4.3-h2f0025b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgd-2.3.3-h88aa843_12.conda @@ -1196,7 +1189,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgl-1.7.0-hd24410f_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgl-devel-1.7.0-hd24410f_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.88.1-h96a7f82_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.88.2-h96a7f82_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglu-9.0.3-h5ad3122_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglvnd-1.7.0-hd24410f_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglx-1.7.0-hd24410f_3.conda @@ -1207,6 +1200,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-math7-7.5.2-h7ac5ae9_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-tools-2.0.3-h7ac5ae9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-utils2-2.2.1-h7ac5ae9_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libharfbuzz-14.2.1-h3a99ef3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libharfbuzz-devel-14.2.1-h3a99ef3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwloc-2.13.0-default_ha95e27d_1000.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwy-1.4.0-h0626a34_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda @@ -1216,7 +1211,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-8_h88aeb00_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapacke-3.11.0-8_hb558247_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm21-21.1.8-hfd2ba90_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.7-hfd2ba90_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.8-hfd2ba90_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libltdl-2.4.3a-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-devel-5.8.3-he30d5cf_0.conda @@ -1246,15 +1241,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopus-1.6.1-h80f16a2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpciaccess-0.19-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpq-18.4-hccacd55_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpq-18.4-hccacd55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-6.31.1-h61c7711_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpsl-0.22.0-h504d594_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libraqm-0.10.5-hd2f8911_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libraw-0.22.1-h6c2e892_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/librsvg-2.62.3-hf685517_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-14.3.0-hedb4206_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsdformat14-14.8.0-py312h39f64fe_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsndfile-1.2.2-h79657aa_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsodium-1.0.22-h80f16a2_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.2-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.3-h10b116e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_19.conda @@ -1269,7 +1266,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liburcu-0.14.0-h0a1ffab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liburing-2.14-hfefdfc9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libusb-1.0.29-h06eaf92_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.2-h1022ec0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.52.1-h80f16a2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvorbis-1.3.7-h7ac5ae9_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvpx-1.15.2-hfae3067_0.conda @@ -1292,11 +1289,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/make-4.4.1-h2a6d0cb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py312hd077ced_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-3.10.9-py312h8025657_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-base-3.10.9-py312h9d0c5ba_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-3.11.0-py312h8025657_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-base-3.11.0-py312h7ee55d7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mesalib-26.0.3-h455aa48_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mpg123-1.32.9-h65af167_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py312h4f740d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.2.1-py312hf18b547_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-3.6.0-h6fc1a30_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-python-3.6.0-np2py312h7d9f038_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-samples-3.6.0-h21f88d6_0.conda @@ -1314,12 +1311,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/octomap-1.10.0-h17cf362_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/onnxruntime-1.26.0-py312hc28d7f2_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/opencv-4.12.0-qt6_py312h750a492_612.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openexr-3.4.12-hda3a014_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openh264-2.6.0-h0564a2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openexr-3.4.13-h95ec230_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openh264-2.6.0-h663e864_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjph-0.27.4-h55827e0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjph-0.30.1-h55827e0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openldap-2.6.13-h2fb54aa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.3-h546c87b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orocos-kdl-1.5.3-hc398517_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/p11-kit-0.26.2-h376a255_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pango-1.56.4-h8547ced_1.conda @@ -1350,7 +1347,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyqt5-sip-12.17.0-py312h1ab2c47_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyside6-6.10.2-py312hfc1e6cc_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.1-h43d1f9e_1_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-librt-0.11.0-py312hd41f8a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-librt-0.12.0-py312hd41f8a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-orocos-kdl-1.5.3-py312h1ab2c47_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py312ha4530ae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qhull-2020.2-h70be974_5.conda @@ -1358,29 +1355,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qt6-main-6.10.2-pl5321h598db47_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rapidjson-1.1.0.post20240409-h5ad3122_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rav1e-0.8.1-h9d4cc37_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py312hcd1a082_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.6.28-py312hcd1a082_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.6-h86ecc28_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rsync-3.4.3-h3aee46b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rsync-3.4.4-h3aee46b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruby-4.0.5-h706e587_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.14.14-he9a2e21_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/scipy-1.17.1-py312ha7f05e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdformat14-14.8.0-hb4dca6f_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdformat14-python-14.8.0-py312he22bb7a_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl2-2.32.56-h7ac5ae9_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl3-3.4.10-had2c13b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl3-3.4.12-had2c13b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/shaderc-2025.5-hfeb5c2c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sip-6.15.3-py312hfcd9f9b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.2.2-he774c54_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/soxr-0.1.3-hb4cce97_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spirv-tools-2026.2-hfefdfc9_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.2-hf1c7be2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.3-hf1c7be2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/svt-av1-4.0.1-hfae3067_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tbb-2023.0.0-h57272ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tbb-devel-2023.0.0-h57272ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tinyxml2-11.0.0-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tornado-6.5.6-py312hefbd42c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tornado-6.5.7-py312hefbd42c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py312h4f740d2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uncrustify-0.83.0-h7ac5ae9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/unicodedata2-17.0.1-py312hcd1a082_0.conda @@ -1393,7 +1390,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/vtk-base-9.5.2-py312h90a26f6_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/vtk-io-ffmpeg-9.5.2-py312haba1314_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wayland-1.25.0-h4f8a99f_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wrapt-2.2.1-py312hcd1a082_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wrapt-2.2.2-py312hcd1a082_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/x264-1!164.3095-h4e544f5_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/x265-3.5-hdd96247_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-0.4.1-hca56bd8_2.conda @@ -1402,7 +1399,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-keysyms-0.4.1-h5c728e9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-renderutil-0.3.10-h5c728e9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-wm-0.4.2-h5c728e9_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xkeyboard-config-2.47-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xkeyboard-config-2.48-h80f16a2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda @@ -1440,32 +1437,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zziplib-0.13.69-h650d8d0_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/absl-py-2.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.7.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beartype-0.22.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/breathe-4.36.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/catkin_pkg-1.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.6.17-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-argcomplete-0.3.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-bash-0.5.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cd-0.1.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.29-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.30-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-core-0.21.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-defaults-0.2.9-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-devtools-0.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-library-path-0.2.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-metadata-0.2.5-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.13-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.14-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-information-0.4.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-selection-0.2.10-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-parallel-executor-0.4.0-pyhe01879c_0.conda @@ -1482,7 +1479,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.3.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dnspython-2.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda @@ -1491,7 +1488,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fabric-3.2.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-7.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-builtins-3.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-comprehensions-3.17.0-pyhd8ed1ab_0.conda @@ -1505,26 +1502,26 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/git-subrepo-0.4.9-hc364b38_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.19-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.17-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.18-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.15.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.20.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda @@ -1574,9 +1571,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-7.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-mock-3.15.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-repeat-0.9.4-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda @@ -1588,7 +1585,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/simpleeval-1.0.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda @@ -1600,7 +1597,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jquery-4.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-2.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda @@ -1609,12 +1606,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/transforms3d-0.4.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.4.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.5.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.8-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wslink-2.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda @@ -1999,18 +1996,18 @@ environments: - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/tts-supertonic-1.0.0-h4616a5c_1.conda - - conda_source: bitbots_rust_nav[77771cb3] @ src/bitbots_navigation/bitbots_rust_nav + - conda_source: bitbots_rust_nav[36aa2fce] @ src/bitbots_navigation/bitbots_rust_nav - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/de/0880cf8af64b225bc8fde0924f76ea5e6cd8d8dc50c6dd61232beb54327f/mjviser-0.0.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/15/efef5a2f204a64bdb5571e6161d49f7ef0fffdbca953a615efbec045f60f/zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/47/aa/218a0eb34de1f753c83e4d0d1c8e7c4cef27f20dcb8342e024f63a80dc86/tqdm-4.68.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4a/c9/9a4ca25b505303d5557c98786ac0bf7081c76a7262e1b6c87b899bccc7b8/viser-1.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/f5/0c41cb68dcae6b7de4fac4188a3a9589e21fb31df21ea3a2e888db95e6c9/soupsieve-2.8.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/80/0c7095f357afeb52100d312250354d2e76afb779c81fe3fb52118076fa5a/syrupy-5.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/c6/92fcd42f1ba33e1184263f25bfabf3d27c383410470f169e4b8163bf9c17/beautifulsoup4-4.15.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8a/37/655101799590bcc5fddb2bd3fe0e6194e816c2d1da7c361725f5eb89a910/msgspec-0.21.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/d4/f4/753003ddb0d43247febecd5146391a59b80f77e462b2623396192180f4ee/syrupy-5.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/8e/bb97bb0c71802080bfc8952937d174e49cfc50de5c951dd47b2496f0dcdb/tqdm-4.68.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ea/78/9a8a174011682d71cb4922f4014ebbeb9d3067922678e7059351fd9207cf/exhale-0.3.7-py3-none-any.whl format: channels: @@ -2028,7 +2025,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp21.1-21.1.8-default_h99862b1_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda @@ -2038,16 +2035,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.3-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.2-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.3-hca6bf5a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.3-h49c6c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre-8.45-h9c3ff4c_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.1-hab00c5b_1_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda @@ -2059,10 +2056,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.3-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.1-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.19-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda @@ -2070,12 +2067,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.6.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.4.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.5.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda linux-aarch64: @@ -2088,7 +2085,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp21.1-21.1.8-default_he95a3c9_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda @@ -2098,16 +2095,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-devel-5.8.3-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.2-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.3-h10b116e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.2-h1022ec0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.3-h79dcc73_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.3-h869d058_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.3-h546c87b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre-8.45-h01db608_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.1-h43d1f9e_1_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py312ha4530ae_1.conda @@ -2119,10 +2116,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-tools-5.8.3-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.1-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.19-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda @@ -2130,12 +2127,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.6.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.4.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.5.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda robot: @@ -2149,8 +2146,8 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/adwaita-icon-theme-3.38.0-hbf89446_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.13.5-py312h5d8c7f2_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.14.1-py312h5d8c7f2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16.1-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-plugins-1.2.12-h989ed37_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aom-3.9.1-hac33072_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/assimp-5.4.3-hecf2907_1.conda @@ -2158,7 +2155,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/attr-2.5.2-hb03c661_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.6.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bcrypt-5.0.0-py312h868fb18_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/benchmark-1.9.5-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.45.1-default_h4852527_102.conda @@ -2186,11 +2183,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-14.3.0-he8ccf15_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/console_bridge-1.0.2-h924138e_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py312h0a2e395_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.14.1-py312h8a5da7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.15.0-py312h8a5da7c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cppcheck-2.18.3-py312h014360a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cppzmq-4.11.0-hbe92c44_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-48.0.0-py312ha4b625e_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/curl-8.20.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-49.0.0-py312ha4b625e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/curl-8.21.0-hae6b9f4_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.11.0-hfcd1e18_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hac629b4_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dav1d-1.2.1-hd590300_0.conda @@ -2201,7 +2198,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-abi-3.4.0.100-h3bcb7cf_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/elfutils-0.194-h849f50c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/epoxy-1.5.10-hb03c661_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fcl-0.7.0-h543440a_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_h43fde53_912.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fftw-3.3.11-nompi_h3b011a4_100.conda @@ -2218,20 +2215,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.8.0-py312h447239a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-h235f0fe_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h50e9bb6_25.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.6-h2b0a6b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h50e9bb6_27.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.7-h2b0a6b4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/geographiclib-cpp-2.7-hb700be7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-0.25.1-h3f43e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-tools-0.25.1-h3f43e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran-14.3.0-he448592_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_impl_linux-64-14.3.0-h1a219da_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_linux-64-14.3.0-h8bb2d51_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_linux-64-14.3.0-h5ce6d8a_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/git-2.54.0-pl5321h6d3cee1_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gl2ps-1.4.2-h36e74d4_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glew-2.3.0-h71661d4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glfw-3.4-hb03c661_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.88.1-hd810c12_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.88.2-hbe0478d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.2-h8094192_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glslang-16.3.0-h96af755_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gmock-1.17.0-ha770c72_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda @@ -2246,14 +2243,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/gts-0.7.6-h977cf35_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-14.3.0-he448592_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.3.0-h2185e75_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-h72ca5df_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-hd240bd5_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-cmake3-3.5.5-h05f81b2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-math7-7.5.2-h5bbc156_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-math7-python-7.5.2-py312h89d136e_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-tools-2.0.3-h3f54f1a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-tools2-2.0.3-h89235b8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-utils2-2.2.1-hdaf9e28_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-14.2.1-h6083320_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-14.2.1-ha770c72_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf4-4.2.15-h2a13503_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda @@ -2267,7 +2264,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py312h0a2e395_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbde042b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lame-3.100-h166bdaf_1003.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda @@ -2276,7 +2273,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libacl-2.3.2-h0f662aa_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.7-gpl_hc2c16d8_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.8-gpl_hc2c16d8_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-0.25.1-h3f43e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-devel-0.25.1-h3f43e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libass-0.17.4-h96ad9f0_0.conda @@ -2295,10 +2292,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libccd-double-2.1-h59595ed_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp21.1-21.1.8-default_h99862b1_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.7-default_h99862b1_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.7-default_h746c552_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.8-default_h6c227bf_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_h9692865_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.21.0-hae6b9f4_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.127-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda @@ -2306,7 +2303,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.4.3-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda @@ -2320,7 +2317,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-devel-1.7.0-ha4b6fd6_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.1-h0d30a3d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.2-h0d30a3d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglu-9.0.3-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_3.conda @@ -2331,6 +2328,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-math7-7.5.2-h54a6638_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-tools-2.0.3-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-utils2-2.2.1-h54a6638_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-14.2.1-h17a8019_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-devel-14.2.1-h17a8019_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.13.0-default_he001693_1000.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwy-1.4.0-h10be129_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda @@ -2340,7 +2339,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapacke-3.11.0-8_h6ae95b6_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.7-hf7376ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libltdl-2.4.3a-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.3-hb03c661_0.conda @@ -2372,15 +2371,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libopus-1.6.1-h280c20c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-6.31.1-hfb7daa7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.22.0-hd9031aa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libraqm-0.10.5-h6406941_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libraw-0.22.1-h074291d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/librsvg-2.62.3-h4c96295_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-14.3.0-h8f1669f_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsdformat14-14.8.0-py312h1f51ce1_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsndfile-1.2.2-hc60ed4a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.22-h280c20c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.2-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda @@ -2395,9 +2396,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/liburcu-0.14.0-hac33072_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liburing-2.14-hb700be7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libusb-1.0.29-h73b1eb8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.23.0-he1eb515_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.24.0-he1eb515_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvorbis-1.3.7-h54a6638_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvpl-2.15.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libvpx-1.15.2-hecca717_0.conda @@ -2420,11 +2421,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.10.9-py312h7900ff3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.10.9-py312he3d6523_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.11.0-py312h7900ff3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.11.0-py312hc1765e9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mesalib-26.0.3-h8cca3c9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mpg123-1.32.9-hc50e24c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py312hd9148b4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.2.1-py312h0a2e395_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-3.6.0-h1eba5cb_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-python-3.6.0-np2py312h2fcff2b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-samples-3.6.0-h3c404ae_0.conda @@ -2444,12 +2445,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/onnxruntime-1.26.0-py312hb39aaa6_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencv-4.12.0-qt6_py312h7bb6282_612.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openexr-3.4.12-h9f1635d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openexr-3.4.13-hf734b31_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-h65dd3cf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openjph-0.27.4-h8d634f6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openjph-0.30.1-h8d634f6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.13-hbde042b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orocos-kdl-1.5.3-hca8cc02_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/p11-kit-0.26.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hda50119_1.conda @@ -2480,7 +2481,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/pyqt5-sip-12.17.0-py312h1289d80_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyside6-6.10.2-py312h50ac2ff_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.1-hab00c5b_1_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.11.0-py312h5253ce2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.12.0-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-orocos-kdl-1.5.3-py312h1289d80_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda @@ -2488,29 +2489,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.10.2-pl5321h16c4a6b_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rapidjson-1.1.0.post20240409-h3f2d84a_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rav1e-0.8.1-h1fbca29_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.6.28-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rsync-3.4.3-h5440a77_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rsync-3.4.4-h5440a77_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruby-4.0.5-h95e6935_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.14.14-h40fa522_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdformat14-14.8.0-h5bb51b8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdformat14-python-14.8.0-py312h22a3d64_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl2-2.32.56-h54a6638_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.4.10-hdeec2a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.4.12-hdeec2a5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/shaderc-2025.5-h718be3e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sip-6.10.0-py312h1289d80_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/soxr-0.1.3-h0b41bf4_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/spirv-tools-2026.2-hb700be7_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.2-hbc0de68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.3-hbc0de68_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/svt-av1-4.0.1-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2023.0.0-hab88423_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-devel-2023.0.0-hab88423_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tinyxml2-11.0.0-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.6-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.7-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py312hd9148b4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/uncrustify-0.83.0-h54a6638_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda @@ -2523,7 +2524,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/vtk-base-9.5.2-py312h6fba518_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/vtk-io-ffmpeg-9.5.2-py312hcdbd8b1_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.25.0-hd6090a7_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.2.1-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.2.2-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/x264-1!164.3095-h166bdaf_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/x265-3.5-h924138e_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda @@ -2532,7 +2533,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-keysyms-0.4.1-hb711507_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-renderutil-0.3.10-hb711507_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-wm-0.4.2-hb711507_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.47-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.48-h280c20c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda @@ -2570,32 +2571,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zziplib-0.13.69-he45264a_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/absl-py-2.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.7.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beartype-0.22.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/breathe-4.36.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/catkin_pkg-1.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.6.17-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-argcomplete-0.3.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-bash-0.5.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cd-0.1.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.29-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.30-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-core-0.21.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-defaults-0.2.9-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-devtools-0.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-library-path-0.2.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-metadata-0.2.5-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.13-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.14-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-information-0.4.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-selection-0.2.10-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-parallel-executor-0.4.0-pyhe01879c_0.conda @@ -2612,7 +2613,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.3.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dnspython-2.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda @@ -2621,7 +2622,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fabric-3.2.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-7.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-builtins-3.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-comprehensions-3.17.0-pyhd8ed1ab_0.conda @@ -2635,26 +2636,26 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/git-subrepo-0.4.9-hc364b38_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.19-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.17-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.18-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.15.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.20.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-parser-0.12.0-pyhd8ed1ab_1.conda @@ -2703,9 +2704,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-7.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-mock-3.15.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-repeat-0.9.4-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda @@ -2717,7 +2718,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/simpleeval-1.0.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda @@ -2729,7 +2730,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jquery-4.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-2.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda @@ -2737,13 +2738,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/transforms3d-0.4.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.4.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.5.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.47-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.49-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.8-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wslink-2.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda @@ -3127,29 +3128,28 @@ environments: - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros-jazzy-zstd-vendor-0.26.9-np2py312h2ed9cc7_16.conda - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros2-distro-mutex-0.14.0-jazzy_16.conda - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda - - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2022_10_07_flo_torso21_yoeox-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/tts-supertonic-1.0.0-h4616a5c_1.conda - - conda_source: bitbots_rust_nav[eb738ce2] @ src/bitbots_navigation/bitbots_rust_nav + - conda_source: bitbots_rust_nav[146a3083] @ src/bitbots_navigation/bitbots_rust_nav - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/de/0880cf8af64b225bc8fde0924f76ea5e6cd8d8dc50c6dd61232beb54327f/mjviser-0.0.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/47/aa/218a0eb34de1f753c83e4d0d1c8e7c4cef27f20dcb8342e024f63a80dc86/tqdm-4.68.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4a/c9/9a4ca25b505303d5557c98786ac0bf7081c76a7262e1b6c87b899bccc7b8/viser-1.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/53/60/7be26e610767316c028a2cbedb9a3beabdbe33e2182c373f71a1c0b88f36/zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5e/f5/0c41cb68dcae6b7de4fac4188a3a9589e21fb31df21ea3a2e888db95e6c9/soupsieve-2.8.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/80/0c7095f357afeb52100d312250354d2e76afb779c81fe3fb52118076fa5a/syrupy-5.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/c6/92fcd42f1ba33e1184263f25bfabf3d27c383410470f169e4b8163bf9c17/beautifulsoup4-4.15.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b5/d1/d4cd9fe89c7d400d7a18f86ccc94daa3f0927f53558846fcb60791dce5d6/msgspec-0.21.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d4/f4/753003ddb0d43247febecd5146391a59b80f77e462b2623396192180f4ee/syrupy-5.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/8e/bb97bb0c71802080bfc8952937d174e49cfc50de5c951dd47b2496f0dcdb/tqdm-4.68.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ea/78/9a8a174011682d71cb4922f4014ebbeb9d3067922678e7059351fd9207cf/exhale-0.3.7-py3-none-any.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/adwaita-icon-theme-3.38.0-h2d234d2_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.13.5-py312he7e3343_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.16-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.14.1-py312he7e3343_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.16.1-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-plugins-1.2.12-haf9f4a6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aom-3.9.1-hcccb83c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/assimp-5.4.3-he8c3857_1.conda @@ -3157,7 +3157,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/at-spi2-core-2.40.3-h1f2db35_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/atk-1.0-2.38.0-hedc4a1f_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/attr-2.5.2-he30d5cf_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.5.0-py312ha46dd1d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.6.0-py312ha46dd1d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bcrypt-5.0.0-py312h5eb8f6c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/benchmark-1.9.5-hfae3067_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.45.1-default_hf1166c9_102.conda @@ -3185,11 +3185,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-gcc-specs-14.3.0-hadff5d6_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/console_bridge-1.0.2-hdd96247_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/contourpy-1.3.3-py312hf18b547_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.14.1-py312hd077ced_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.15.0-py312hd077ced_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cppcheck-2.18.3-py312h5677ec4_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cppzmq-4.11.0-h7be3492_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-48.0.0-py312h96535df_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/curl-8.20.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-49.0.0-py312h96535df_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/curl-8.21.0-h7c59cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.11.0-h7b35c40_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cyrus-sasl-2.1.28-h6598af7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/dav1d-1.2.1-h31becfc_0.conda @@ -3200,7 +3200,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/eigen-abi-3.4.0.100-h9a8c16c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/elfutils-0.194-h7d8af26_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/epoxy-1.5.10-he30d5cf_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fcl-0.7.0-h841ecf2_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ffmpeg-8.0.1-gpl_hd1a4c92_912.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fftw-3.3.11-nompi_h66d8d02_100.conda @@ -3212,25 +3212,25 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fortran-compiler-1.11.0-h151373c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freeglut-3.2.2-hddf9bb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freeimage-3.18.0-he4296dc_25.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freetype-2.14.3-h8af1aa0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freetype-2.14.3-h8af1aa0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fribidi-1.0.16-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.8.0-py312hb10c72c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-14.3.0-h2e72a27_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-14.3.0-h398eab4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h140ef2e_25.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gdk-pixbuf-2.44.6-h90308e0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h140ef2e_27.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gdk-pixbuf-2.44.7-h90308e0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/geographiclib-cpp-2.7-hfefdfc9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gettext-0.25.1-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gettext-tools-0.25.1-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran-14.3.0-ha28f942_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_impl_linux-aarch64-14.3.0-h6b0ea1e_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_linux-aarch64-14.3.0-h495b507_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_linux-aarch64-14.3.0-h4981040_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/git-2.54.0-pl5321h5dcfaa0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gl2ps-1.4.2-hd9db0c5_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glew-2.3.0-hf9dcc85_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glfw-3.4-he30d5cf_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-2.88.1-h72f18f7_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-tools-2.88.1-h7439e1d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-2.88.2-hdf12349_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-tools-2.88.2-h7aeb4f4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glslang-16.3.0-h124e036_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmock-1.17.0-h8af1aa0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmp-6.3.0-h0a1ffab_2.conda @@ -3245,14 +3245,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gts-0.7.6-he293c15_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-14.3.0-ha28f942_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-14.3.0-h0d4f5d4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h73dd529_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h0da240b_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-cmake3-3.5.5-h740f95d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-math7-7.5.2-h1ad700d_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-math7-python-7.5.2-py312h9452373_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-tools-2.0.3-h8a9b3d2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-tools2-2.0.3-hd91f489_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-utils2-2.2.1-h2ce864c_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-14.2.1-h1134a53_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-14.2.1-h8af1aa0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hdf4-4.2.15-hb6ba311_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hdf5-1.14.6-nompi_hf95b8e7_110.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hicolor-icon-theme-0.17-h8af1aa0_3.conda @@ -3264,7 +3264,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/jxrlib-1.1-h31becfc_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kiwisolver-1.5.0-py312h1683e8e_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-h2fb54aa_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lame-3.100-h4e544f5_1003.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda @@ -3272,7 +3272,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20250512.1-cxx17_h201e9ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libacl-2.3.2-h883460d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libaec-1.1.5-hff7e48a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.7-gpl_hbe7d12b_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.8-gpl_hbe7d12b_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libasprintf-0.25.1-h5e0f5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libasprintf-devel-0.25.1-h5e0f5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libass-0.17.4-hcfe818d_0.conda @@ -3291,10 +3291,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-8_hd72aa62_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libccd-double-2.1-h2f0025b_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp21.1-21.1.8-default_he95a3c9_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.7-default_h2a92e99_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.7-default_h3185f35_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.8-default_h0cc847a_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.8-default_hd92691d_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.20.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.21.0-h7c59cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdrm-2.4.127-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda @@ -3302,11 +3302,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libegl-devel-1.7.0-hd24410f_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libflac-1.4.3-h2f0025b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgd-2.3.3-h88aa843_12.conda @@ -3316,7 +3316,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgl-1.7.0-hd24410f_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgl-devel-1.7.0-hd24410f_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.88.1-h96a7f82_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.88.2-h96a7f82_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglu-9.0.3-h5ad3122_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglvnd-1.7.0-hd24410f_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglx-1.7.0-hd24410f_3.conda @@ -3327,6 +3327,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-math7-7.5.2-h7ac5ae9_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-tools-2.0.3-h7ac5ae9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-utils2-2.2.1-h7ac5ae9_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libharfbuzz-14.2.1-h3a99ef3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libharfbuzz-devel-14.2.1-h3a99ef3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwloc-2.13.0-default_ha95e27d_1000.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwy-1.4.0-h0626a34_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda @@ -3336,7 +3338,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-8_h88aeb00_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapacke-3.11.0-8_hb558247_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm21-21.1.8-hfd2ba90_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.7-hfd2ba90_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.8-hfd2ba90_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libltdl-2.4.3a-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-devel-5.8.3-he30d5cf_0.conda @@ -3366,15 +3368,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopus-1.6.1-h80f16a2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpciaccess-0.19-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpq-18.4-hccacd55_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpq-18.4-hccacd55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-6.31.1-h61c7711_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpsl-0.22.0-h504d594_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libraqm-0.10.5-hd2f8911_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libraw-0.22.1-h6c2e892_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/librsvg-2.62.3-hf685517_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-14.3.0-hedb4206_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsdformat14-14.8.0-py312h39f64fe_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsndfile-1.2.2-h79657aa_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsodium-1.0.22-h80f16a2_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.2-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.3-h10b116e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_19.conda @@ -3389,7 +3393,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liburcu-0.14.0-h0a1ffab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liburing-2.14-hfefdfc9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libusb-1.0.29-h06eaf92_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.2-h1022ec0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.52.1-h80f16a2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvorbis-1.3.7-h7ac5ae9_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvpx-1.15.2-hfae3067_0.conda @@ -3412,11 +3416,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/make-4.4.1-h2a6d0cb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py312hd077ced_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-3.10.9-py312h8025657_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-base-3.10.9-py312h9d0c5ba_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-3.11.0-py312h8025657_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-base-3.11.0-py312h7ee55d7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mesalib-26.0.3-h455aa48_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mpg123-1.32.9-h65af167_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py312h4f740d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.2.1-py312hf18b547_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-3.6.0-h6fc1a30_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-python-3.6.0-np2py312h7d9f038_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-samples-3.6.0-h21f88d6_0.conda @@ -3434,12 +3438,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/octomap-1.10.0-h17cf362_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/onnxruntime-1.26.0-py312hc28d7f2_0_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/opencv-4.12.0-qt6_py312h750a492_612.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openexr-3.4.12-hda3a014_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openh264-2.6.0-h0564a2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openexr-3.4.13-h95ec230_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openh264-2.6.0-h663e864_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjph-0.27.4-h55827e0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjph-0.30.1-h55827e0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openldap-2.6.13-h2fb54aa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.3-h546c87b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orocos-kdl-1.5.3-hc398517_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/p11-kit-0.26.2-h376a255_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pango-1.56.4-h8547ced_1.conda @@ -3470,7 +3474,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyqt5-sip-12.17.0-py312h1ab2c47_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyside6-6.10.2-py312hfc1e6cc_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.1-h43d1f9e_1_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-librt-0.11.0-py312hd41f8a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-librt-0.12.0-py312hd41f8a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-orocos-kdl-1.5.3-py312h1ab2c47_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py312ha4530ae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qhull-2020.2-h70be974_5.conda @@ -3478,29 +3482,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qt6-main-6.10.2-pl5321h598db47_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rapidjson-1.1.0.post20240409-h5ad3122_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rav1e-0.8.1-h9d4cc37_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py312hcd1a082_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.6.28-py312hcd1a082_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.6-h86ecc28_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rsync-3.4.3-h3aee46b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rsync-3.4.4-h3aee46b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruby-4.0.5-h706e587_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.14.14-he9a2e21_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/scipy-1.17.1-py312ha7f05e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdformat14-14.8.0-hb4dca6f_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdformat14-python-14.8.0-py312he22bb7a_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl2-2.32.56-h7ac5ae9_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl3-3.4.10-had2c13b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl3-3.4.12-had2c13b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/shaderc-2025.5-hfeb5c2c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sip-6.15.3-py312hfcd9f9b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.2.2-he774c54_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/soxr-0.1.3-hb4cce97_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spirv-tools-2026.2-hfefdfc9_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.2-hf1c7be2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.3-hf1c7be2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/svt-av1-4.0.1-hfae3067_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tbb-2023.0.0-h57272ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tbb-devel-2023.0.0-h57272ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tinyxml2-11.0.0-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tornado-6.5.6-py312hefbd42c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tornado-6.5.7-py312hefbd42c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py312h4f740d2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uncrustify-0.83.0-h7ac5ae9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/unicodedata2-17.0.1-py312hcd1a082_0.conda @@ -3513,7 +3517,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/vtk-base-9.5.2-py312h90a26f6_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/vtk-io-ffmpeg-9.5.2-py312haba1314_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wayland-1.25.0-h4f8a99f_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wrapt-2.2.1-py312hcd1a082_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wrapt-2.2.2-py312hcd1a082_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/x264-1!164.3095-h4e544f5_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/x265-3.5-hdd96247_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-0.4.1-hca56bd8_2.conda @@ -3522,7 +3526,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-keysyms-0.4.1-h5c728e9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-renderutil-0.3.10-h5c728e9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-wm-0.4.2-h5c728e9_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xkeyboard-config-2.47-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xkeyboard-config-2.48-h80f16a2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda @@ -3560,32 +3564,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zziplib-0.13.69-h650d8d0_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/absl-py-2.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.7.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beartype-0.22.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/breathe-4.36.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/catkin_pkg-1.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.6.17-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-argcomplete-0.3.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-bash-0.5.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cd-0.1.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.29-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.30-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-core-0.21.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-defaults-0.2.9-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-devtools-0.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-library-path-0.2.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-metadata-0.2.5-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.13-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.14-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-information-0.4.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-selection-0.2.10-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-parallel-executor-0.4.0-pyhe01879c_0.conda @@ -3602,7 +3606,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.3.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dnspython-2.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda @@ -3611,7 +3615,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fabric-3.2.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-7.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-builtins-3.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-comprehensions-3.17.0-pyhd8ed1ab_0.conda @@ -3625,26 +3629,26 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/git-subrepo-0.4.9-hc364b38_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.19-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.17-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.18-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.15.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.20.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda @@ -3694,9 +3698,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-7.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-mock-3.15.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-repeat-0.9.4-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda @@ -3708,7 +3712,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/simpleeval-1.0.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda @@ -3720,7 +3724,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jquery-4.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-2.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda @@ -3729,12 +3733,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/transforms3d-0.4.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.4.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.5.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.8-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wslink-2.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda @@ -4122,18 +4126,18 @@ environments: - conda: https://data.bit-bots.de/conda-misc/output/noarch/bitbots_model_2023_04_04_philipp_yoeox_with_team_colors-1.0.1-h4616a5c_3.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/tts-supertonic-1.0.0-h4616a5c_1.conda - - conda_source: bitbots_rust_nav[77771cb3] @ src/bitbots_navigation/bitbots_rust_nav + - conda_source: bitbots_rust_nav[36aa2fce] @ src/bitbots_navigation/bitbots_rust_nav - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/de/0880cf8af64b225bc8fde0924f76ea5e6cd8d8dc50c6dd61232beb54327f/mjviser-0.0.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/15/efef5a2f204a64bdb5571e6161d49f7ef0fffdbca953a615efbec045f60f/zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/47/aa/218a0eb34de1f753c83e4d0d1c8e7c4cef27f20dcb8342e024f63a80dc86/tqdm-4.68.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4a/c9/9a4ca25b505303d5557c98786ac0bf7081c76a7262e1b6c87b899bccc7b8/viser-1.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/f5/0c41cb68dcae6b7de4fac4188a3a9589e21fb31df21ea3a2e888db95e6c9/soupsieve-2.8.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/80/0c7095f357afeb52100d312250354d2e76afb779c81fe3fb52118076fa5a/syrupy-5.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/c6/92fcd42f1ba33e1184263f25bfabf3d27c383410470f169e4b8163bf9c17/beautifulsoup4-4.15.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8a/37/655101799590bcc5fddb2bd3fe0e6194e816c2d1da7c361725f5eb89a910/msgspec-0.21.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/d4/f4/753003ddb0d43247febecd5146391a59b80f77e462b2623396192180f4ee/syrupy-5.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/8e/bb97bb0c71802080bfc8952937d174e49cfc50de5c951dd47b2496f0dcdb/tqdm-4.68.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ea/78/9a8a174011682d71cb4922f4014ebbeb9d3067922678e7059351fd9207cf/exhale-0.3.7-py3-none-any.whl packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda @@ -4148,6 +4152,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + strong: + - _openmp_mutex >=4.5 size: 28948 timestamp: 1770939786096 - conda: https://conda.anaconda.org/conda-forge/linux-64/adwaita-icon-theme-3.38.0-hbf89446_1.tar.bz2 @@ -4159,11 +4166,12 @@ packages: license: LGPL-3.0-or-later OR CC-BY-SA-3.0 license_family: LGPL purls: [] + run_exports: {} size: 11217173 timestamp: 1610488699556 -- conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.13.5-py312h5d8c7f2_0.conda - sha256: 52f4d07b10fe4a1ded570b0708594d2d9075223e1dd94d0c5988eb71f724a5f2 - md5: 68edaee7692efb8bbef5e95375090189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.14.1-py312h5d8c7f2_0.conda + sha256: 7e03efaf3671cfca5d3195dc18aa3ca6bc182e0e34d30a95adb4f64f71d8f10c + md5: 10e4a93c73bfe09c5909cb1d41a1e40e depends: - __glibc >=2.17,<3.0.a0 - aiohappyeyeballs >=2.5.0 @@ -4175,24 +4183,29 @@ packages: - propcache >=0.2.0 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 + - typing_extensions >=4.4 - yarl >=1.17.0,<2.0 license: MIT AND Apache-2.0 license_family: Apache purls: - - pkg:pypi/aiohttp?source=hash-mapping - size: 1034187 - timestamp: 1775000054521 -- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16-hb03c661_0.conda - sha256: 64484cb7e7cf65d9c7188498d595125a6e0751604dd7fb483e1bb327eec0f738 - md5: 18d273b22e96c97c2017813f099faa82 + - pkg:pypi/aiohttp?source=compressed-mapping + run_exports: {} + size: 1078273 + timestamp: 1780913823270 +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16.1-hb03c661_0.conda + sha256: cf93ca0f1f107e95a35969a4622684e08fcb8cf37f8cf4a1e9e424828386c921 + md5: 8904e09bda369377b3dd07e2ac828c5d depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: LGPL-2.1-or-later - license_family: GPL + license_family: LGPL purls: [] - size: 591046 - timestamp: 1780398678742 + run_exports: + weak: + - alsa-lib >=1.2.16.1,<1.3.0a0 + size: 592377 + timestamp: 1781521980743 - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-plugins-1.2.12-h989ed37_2.conda sha256: 2b0912f8891f367ea8bdf8a8c65f27a09e275df335bfc876b3b973dfa138ff29 md5: 657d4333ff8d0b9f713c94c0e23ee1a8 @@ -4206,6 +4219,7 @@ packages: license: LGPL-2.1-or-later AND GPL-3.0-or-later license_family: LGPL purls: [] + run_exports: {} size: 254302 timestamp: 1756137041656 - conda: https://conda.anaconda.org/conda-forge/linux-64/aom-3.9.1-hac33072_0.conda @@ -4217,6 +4231,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - aom >=3.9.1,<3.10.0a0 size: 2706396 timestamp: 1718551242397 - conda: https://conda.anaconda.org/conda-forge/linux-64/assimp-5.4.3-hecf2907_1.conda @@ -4232,6 +4249,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - assimp >=5.4.3,<5.4.4.0a0 size: 3645199 timestamp: 1753274588181 - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 @@ -4246,6 +4266,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - at-spi2-atk >=2.38.0,<3.0a0 size: 339899 timestamp: 1619122953439 - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 @@ -4261,6 +4284,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - at-spi2-core >=2.40.3,<2.41.0a0 size: 658390 timestamp: 1625848454791 - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda @@ -4275,6 +4301,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - atk-1.0 >=2.38.0 size: 355900 timestamp: 1713896169874 - conda: https://conda.anaconda.org/conda-forge/linux-64/attr-2.5.2-hb03c661_1.conda @@ -4287,22 +4316,26 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - libattr >=2.5.2,<2.6.0a0 size: 31386 timestamp: 1773595914754 -- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda - sha256: a2b08a4e5e549b5f67c38edffd175437e2208547a7e67b5fa5373b67ef419e50 - md5: b31dba71fe091e7201826e57e0f7b261 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.6.0-py312h90b7ffd_0.conda + sha256: 95b3d6d44c17c4061db703289f39915646e455f75f0c8c9d949bf081d2e61579 + md5: 55811da425538da800b89c0c588652fa depends: - python - libgcc >=14 - __glibc >=2.17,<3.0.a0 - - zstd >=1.5.7,<1.6.0a0 - python_abi 3.12.* *_cp312 + - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=compressed-mapping - size: 239928 - timestamp: 1778594049826 + run_exports: {} + size: 239892 + timestamp: 1781450817988 - conda: https://conda.anaconda.org/conda-forge/linux-64/bcrypt-5.0.0-py312h868fb18_1.conda sha256: 22020286e3d27eba7c9efef79c1020782885992aea0e7d28d7274c4405001521 md5: 8fbbd949c452efde5a75b62b22a88938 @@ -4317,6 +4350,7 @@ packages: license_family: APACHE purls: - pkg:pypi/bcrypt?source=hash-mapping + run_exports: {} size: 292835 timestamp: 1762497719397 - conda: https://conda.anaconda.org/conda-forge/linux-64/benchmark-1.9.5-hecca717_0.conda @@ -4329,6 +4363,7 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: {} size: 290910 timestamp: 1769116980221 - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.45.1-default_h4852527_102.conda @@ -4339,6 +4374,7 @@ packages: license: GPL-3.0-only license_family: GPL purls: [] + run_exports: {} size: 35436 timestamp: 1774197482571 - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda @@ -4351,6 +4387,7 @@ packages: license: GPL-3.0-only license_family: GPL purls: [] + run_exports: {} size: 3661455 timestamp: 1774197460085 - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.45.1-default_h4852527_102.conda @@ -4361,6 +4398,7 @@ packages: license: GPL-3.0-only license_family: GPL purls: [] + run_exports: {} size: 36304 timestamp: 1774197485247 - conda: https://conda.anaconda.org/conda-forge/linux-64/blosc-1.21.6-he440d0b_1.conda @@ -4377,6 +4415,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - blosc >=1.21.6,<2.0a0 size: 48427 timestamp: 1733513201413 - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda @@ -4391,6 +4432,11 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 size: 20103 timestamp: 1764017231353 - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda @@ -4404,6 +4450,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 21021 timestamp: 1764017221344 - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda @@ -4421,6 +4468,7 @@ packages: license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping + run_exports: {} size: 368300 timestamp: 1764017300621 - conda: https://conda.anaconda.org/conda-forge/linux-64/bullet-3.25-h26dfbe5_5.conda @@ -4433,6 +4481,7 @@ packages: - python license: Zlib purls: [] + run_exports: {} size: 11631 timestamp: 1761041385662 - conda: https://conda.anaconda.org/conda-forge/linux-64/bullet-cpp-3.25-hcbe3ca9_5.conda @@ -4449,6 +4498,9 @@ packages: - xorg-libxext >=1.3.6,<2.0a0 license: Zlib purls: [] + run_exports: + weak: + - bullet-cpp >=3.25,<3.26.0a0 size: 42581149 timestamp: 1761041037901 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda @@ -4460,6 +4512,9 @@ packages: license: bzip2-1.0.6 license_family: BSD purls: [] + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 size: 260182 timestamp: 1771350215188 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda @@ -4471,6 +4526,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - c-ares >=1.34.6,<2.0a0 size: 207882 timestamp: 1765214722852 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.11.0-h4d9bdce_0.conda @@ -4483,6 +4541,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 6693 timestamp: 1753098721814 - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda @@ -4510,6 +4569,9 @@ packages: - xorg-libxrender >=0.9.12,<0.10.0a0 license: LGPL-2.1-only or MPL-1.1 purls: [] + run_exports: + weak: + - cairo >=1.18.4,<2.0a0 size: 989514 timestamp: 1766415934926 - conda: https://conda.anaconda.org/conda-forge/linux-64/cbor2-5.9.0-py312h5253ce2_0.conda @@ -4524,6 +4586,7 @@ packages: license_family: MIT purls: - pkg:pypi/cbor2?source=hash-mapping + run_exports: {} size: 116357 timestamp: 1775229769097 - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda @@ -4540,6 +4603,7 @@ packages: license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping + run_exports: {} size: 295716 timestamp: 1761202958833 - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-21-21.1.8-default_h99862b1_4.conda @@ -4554,6 +4618,7 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] + run_exports: {} size: 71485 timestamp: 1777011252467 - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-21.1.8-default_h99862b1_4.conda @@ -4569,6 +4634,7 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] + run_exports: {} size: 28677 timestamp: 1777011299688 - conda: https://conda.anaconda.org/conda-forge/linux-64/cli11-2.6.2-h54a6638_0.conda @@ -4581,6 +4647,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 99051 timestamp: 1772207728613 - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.29.6-hcafd917_0.conda @@ -4601,6 +4668,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 19042008 timestamp: 1718668981413 - conda: https://conda.anaconda.org/conda-forge/linux-64/colcon-common-extensions-0.3.0-py312h7900ff3_4.conda @@ -4632,6 +4700,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-common-extensions?source=hash-mapping + run_exports: {} size: 13032 timestamp: 1759757821346 - conda: https://conda.anaconda.org/conda-forge/linux-64/colcon-notification-0.3.1-py312he626ec8_0.conda @@ -4646,6 +4715,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-notification?source=hash-mapping + run_exports: {} size: 82327 timestamp: 1774664643705 - conda: https://conda.anaconda.org/conda-forge/linux-64/compilers-1.11.0-ha770c72_0.conda @@ -4658,6 +4728,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 7482 timestamp: 1753098722454 - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-14.3.0-he8ccf15_19.conda @@ -4668,6 +4739,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 31751 timestamp: 1778268677594 - conda: https://conda.anaconda.org/conda-forge/linux-64/console_bridge-1.0.2-h924138e_1.tar.bz2 @@ -4679,6 +4751,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - console_bridge >=1.0.2,<1.1.0a0 size: 18460 timestamp: 1648912649612 - conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py312h0a2e395_4.conda @@ -4695,11 +4770,12 @@ packages: license_family: BSD purls: - pkg:pypi/contourpy?source=hash-mapping + run_exports: {} size: 320386 timestamp: 1769155979897 -- conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.14.1-py312h8a5da7c_0.conda - sha256: 80b990c6870c721bcde5e14e71d3560bac3dad93b54d027f723dca2bb7ccda03 - md5: 6668e2af2de730400bdce9cf2ea132f9 +- conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.15.0-py312h8a5da7c_0.conda + sha256: 260364f80ef8c0fbbc244330ac29f863c3c76ff27551a3cd87a45af39a3628aa + md5: 81c362e153956e8b0ab533387443ba27 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -4707,11 +4783,11 @@ packages: - python_abi 3.12.* *_cp312 - tomli license: Apache-2.0 - license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping - size: 389696 - timestamp: 1779838017522 + run_exports: {} + size: 394452 + timestamp: 1783019257881 - conda: https://conda.anaconda.org/conda-forge/linux-64/cppcheck-2.18.3-py312h014360a_1.conda sha256: f4321bdeddc9178f006a8cc3dedeaf32ab7e4c3be843845fbf594bc07999d2d6 md5: ab786ccd5cc6a08c0ebd5f6154c9dfcd @@ -4729,6 +4805,7 @@ packages: license_family: GPL purls: - pkg:pypi/cppcheck-htmlreport?source=hash-mapping + run_exports: {} size: 3065679 timestamp: 1757440259649 - conda: https://conda.anaconda.org/conda-forge/linux-64/cppzmq-4.11.0-hbe92c44_0.conda @@ -4742,16 +4819,17 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 30502 timestamp: 1763728886940 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-48.0.0-py312ha4b625e_0.conda - sha256: 16d3d1e8df34a36430a28f423380fbd93abe5670ca7b52e9f4a64c091fd3ddd9 - md5: c5a8e173200adf567dc2818d8bf1325f +- conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-49.0.0-py312ha4b625e_0.conda + sha256: c12e00af17f1507dbc186c9c663b44ca58b9b2209f59506be05547bd730346e5 + md5: 46142c21318ee17d5beecf0de1fc5d47 depends: - __glibc >=2.17,<3.0.a0 - cffi >=2.0 - libgcc >=14 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 constrains: @@ -4760,25 +4838,28 @@ packages: license_family: BSD purls: - pkg:pypi/cryptography?source=hash-mapping - size: 1912222 - timestamp: 1777966300032 -- conda: https://conda.anaconda.org/conda-forge/linux-64/curl-8.20.0-hcf29cc6_0.conda - sha256: 24b6ccc111388df77c65c68b3f3cad9f066e11741469fa60052ad0773f941c6e - md5: cc1a446bff91be88b2fa1d629e4f348b + run_exports: {} + size: 1912490 + timestamp: 1781385597345 +- conda: https://conda.anaconda.org/conda-forge/linux-64/curl-8.21.0-hae6b9f4_2.conda + sha256: ae0b83efb7545ea40845253b76bbfeb12349bd32001728b8f58d726cd532d467 + md5: d09779693563f4a1a0bdb0f715ba2bf0 depends: - __glibc >=2.17,<3.0.a0 - krb5 >=1.22.2,<1.23.0a0 - - libcurl 8.20.0 hcf29cc6_0 + - libcurl 8.21.0 hae6b9f4_2 - libgcc >=14 + - libpsl >=0.22.0,<0.23.0a0 - libssh2 >=1.11.1,<2.0a0 - libzlib >=1.3.2,<2.0a0 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT purls: [] - size: 191489 - timestamp: 1777461498522 + run_exports: {} + size: 194776 + timestamp: 1782911792708 - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.11.0-hfcd1e18_0.conda sha256: 3fcc97ae3e89c150401a50a4de58794ffc67b1ed0e1851468fcc376980201e25 md5: 5da8c935dca9186673987f79cef0b2a5 @@ -4789,6 +4870,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 6635 timestamp: 1753098722177 - conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hac629b4_1.conda @@ -4805,6 +4887,9 @@ packages: license: BSD-3-Clause-Attribution license_family: BSD purls: [] + run_exports: + weak: + - cyrus-sasl >=2.1.28,<3.0a0 size: 210103 timestamp: 1771943128249 - conda: https://conda.anaconda.org/conda-forge/linux-64/dav1d-1.2.1-hd590300_0.conda @@ -4815,6 +4900,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - dav1d >=1.2.1,<1.2.2.0a0 size: 760229 timestamp: 1685695754230 - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h24cb091_1.conda @@ -4829,6 +4917,9 @@ packages: - libexpat >=2.7.3,<3.0a0 license: AFL-2.1 OR GPL-2.0-or-later purls: [] + run_exports: + weak: + - dbus >=1.16.2,<2.0a0 size: 447649 timestamp: 1764536047944 - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-python-1.3.2-py312h7347394_6.conda @@ -4845,6 +4936,7 @@ packages: license_family: MIT purls: - pkg:pypi/dbus-python?source=hash-mapping + run_exports: {} size: 292892 timestamp: 1759741046729 - conda: https://conda.anaconda.org/conda-forge/linux-64/double-conversion-3.4.0-hecca717_0.conda @@ -4857,6 +4949,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - double-conversion >=3.4.0,<3.5.0a0 size: 71809 timestamp: 1765193127016 - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-3.4.0-h54a6638_2.conda @@ -4869,6 +4964,7 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: {} size: 1173190 timestamp: 1771922274213 - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-abi-3.4.0.100-h3bcb7cf_2.conda @@ -4879,6 +4975,7 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: {} size: 13146 timestamp: 1771922274215 - conda: https://conda.anaconda.org/conda-forge/linux-64/elfutils-0.194-h849f50c_0.conda @@ -4899,6 +4996,9 @@ packages: license: LGPL-3.0-only license_family: LGPL purls: [] + run_exports: + weak: + - elfutils >=0.194,<0.195.0a0 size: 1289929 timestamp: 1765447425767 - conda: https://conda.anaconda.org/conda-forge/linux-64/epoxy-1.5.10-hb03c661_2.conda @@ -4922,20 +5022,26 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - epoxy >=1.5.10,<1.6.0a0 size: 411735 timestamp: 1758743520805 -- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda - sha256: 29a10599d56d93bd750914888ebe6822d47722070762b4647b34d12df9f4476e - md5: d0757fd84af06f065eba49d39af6c546 +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_1.conda + sha256: bc1e8177a4ebbbfcda98b6f4a1575f3337e69f0d2f1025a84570533ca27b89eb + md5: e211a78613b9d50a096644b97cede8f7 depends: - __glibc >=2.17,<3.0.a0 - - libexpat 2.8.1 hecca717_0 + - libexpat 2.8.1 hecca717_1 - libgcc >=14 license: MIT license_family: MIT purls: [] - size: 148238 - timestamp: 1779278694477 + run_exports: + weak: + - libexpat >=2.8.1,<3.0a0 + size: 147797 + timestamp: 1781203608158 - conda: https://conda.anaconda.org/conda-forge/linux-64/fcl-0.7.0-h543440a_8.conda sha256: b082e91c7309ffed0aa01d97aa7c7acc8deddad152211153dce381817a4ef4f6 md5: eb7214feba07f44bff77a3ad510231a9 @@ -4949,6 +5055,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - fcl >=0.7.0,<0.8.0a0 size: 1590323 timestamp: 1736132840079 - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_h43fde53_912.conda @@ -5013,6 +5122,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - ffmpeg >=8.0.1,<9.0a0 size: 12479894 timestamp: 1769713683312 - conda: https://conda.anaconda.org/conda-forge/linux-64/fftw-3.3.11-nompi_h3b011a4_100.conda @@ -5027,6 +5139,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - fftw >=3.3.11,<4.0a0 size: 2195198 timestamp: 1776781721834 - conda: https://conda.anaconda.org/conda-forge/linux-64/flann-1.9.2-he1b7b50_6.conda @@ -5042,6 +5157,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - flann >=1.9.2,<1.9.3.0a0 size: 1990499 timestamp: 1774331944832 - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda @@ -5054,6 +5172,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - fmt >=12.1.0,<12.2.0a0 size: 198107 timestamp: 1767681153946 - conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.1-h27c8c51_0.conda @@ -5070,6 +5191,10 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - fontconfig >=2.18.1,<3.0a0 + - fonts-conda-ecosystem size: 281880 timestamp: 1780450077431 - conda: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.63.0-py312h8a5da7c_0.conda @@ -5087,6 +5212,7 @@ packages: license_family: MIT purls: - pkg:pypi/fonttools?source=hash-mapping + run_exports: {} size: 3007892 timestamp: 1778770568019 - conda: https://conda.anaconda.org/conda-forge/linux-64/foonathan-memory-0.7.3-h5888daf_1.conda @@ -5098,6 +5224,9 @@ packages: - libstdcxx >=13 license: Zlib purls: [] + run_exports: + weak: + - foonathan-memory >=0.7.3,<0.7.4.0a0 size: 227132 timestamp: 1746246721660 - conda: https://conda.anaconda.org/conda-forge/linux-64/fortran-compiler-1.11.0-h9bea470_0.conda @@ -5111,6 +5240,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 6656 timestamp: 1753098722318 - conda: https://conda.anaconda.org/conda-forge/linux-64/freeglut-3.2.2-h215f996_4.conda @@ -5132,6 +5262,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - freeglut >=3.2.2,<4.0a0 size: 146159 timestamp: 1776928018299 - conda: https://conda.anaconda.org/conda-forge/linux-64/freeimage-3.18.0-hd1b7436_25.conda @@ -5153,6 +5286,9 @@ packages: - openjpeg >=2.5.4,<3.0a0 license: GPL-2.0-or-later OR GPL-3.0-or-later OR FreeImage purls: [] + run_exports: + weak: + - freeimage >=3.18.0,<3.19.0a0 size: 469606 timestamp: 1780001489759 - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.3-ha770c72_0.conda @@ -5163,6 +5299,10 @@ packages: - libfreetype6 2.14.3 h73754d4_0 license: GPL-2.0-only OR FTL purls: [] + run_exports: + weak: + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 size: 173839 timestamp: 1774298173462 - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_0.conda @@ -5173,6 +5313,9 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - fribidi >=1.0.16,<2.0a0 size: 61244 timestamp: 1757438574066 - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.8.0-py312h447239a_0.conda @@ -5188,6 +5331,7 @@ packages: license_family: APACHE purls: - pkg:pypi/frozenlist?source=hash-mapping + run_exports: {} size: 55016 timestamp: 1779999817627 - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_19.conda @@ -5199,6 +5343,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 29459 timestamp: 1778268802660 - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-h235f0fe_19.conda @@ -5216,6 +5361,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 77667192 timestamp: 1778268558509 - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda @@ -5232,11 +5378,12 @@ packages: - sysroot_linux-64 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + run_exports: {} size: 81043749 timestamp: 1778860073982 -- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h50e9bb6_25.conda - sha256: 95d22db25f0b8875febe63073f809c0c64f4026cc9e6aa0cca7130de51e4d044 - md5: 0a9089d9eeeeb23313a9ce670fb89052 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h50e9bb6_27.conda + sha256: d7f427d6db94a5eed2a43b186f8dc17cc1fbeb03517442390a36f1cde02548b0 + md5: 90369fa27fae2f7bf7eaaccc34c793e2 depends: - gcc_impl_linux-64 14.3.0.* - binutils_linux-64 @@ -5244,35 +5391,44 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] - size: 29191 - timestamp: 1779371710532 -- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-15.2.0-h7be306e_25.conda - sha256: 3fbe01ebb16418d9f1971a283f969dc0f0e1071119f24164f4293057c79dc58c - md5: 46ca2358101b2477cb098c4248795d12 + run_exports: + strong: + - libgcc >=14 + size: 29324 + timestamp: 1781279939286 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-15.2.0-h7be306e_27.conda + sha256: b24b13d467898a9b9a17a868a2686412a98f8935dc7cc51547dd90645d4e8436 + md5: 28bc49875f9c38e2401696b3e48d0798 depends: - gcc_impl_linux-64 15.2.0.* - binutils_linux-64 - sysroot_linux-64 license: BSD-3-Clause license_family: BSD - size: 29190 - timestamp: 1779371750402 -- conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.6-h2b0a6b4_0.conda - sha256: c5594497f0646e9079705b3199dbb2d5b13c48173cf110000fa1c8818e2b3e0c - md5: 7892f39a39ed39591a89a28eba03e987 + run_exports: + strong: + - libgcc >=15 + size: 29330 + timestamp: 1781279944230 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.7-h2b0a6b4_0.conda + sha256: 1c22e37f9d7e06e9e0582ee5a55c2ddd19ea75f71f44eb13b56f504ef5c37aa5 + md5: 5d355db3e937086e22cf4cb5fe19787c depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - - libglib >=2.86.4,<3.0a0 - - libjpeg-turbo >=3.1.2,<4.0a0 - - liblzma >=5.8.2,<6.0a0 - - libpng >=1.6.56,<1.7.0a0 + - libglib >=2.88.2,<3.0a0 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libpng >=1.6.58,<1.7.0a0 - libtiff >=4.7.1,<4.8.0a0 license: LGPL-2.1-or-later license_family: LGPL purls: [] - size: 577414 - timestamp: 1774985848058 + run_exports: + weak: + - gdk-pixbuf >=2.44.7,<3.0a0 + size: 581631 + timestamp: 1782591374199 - conda: https://conda.anaconda.org/conda-forge/linux-64/geographiclib-cpp-2.7-hb700be7_0.conda sha256: 8d05d60178581a7a5f6cd3266cd5172f9cf18c89c8751ca9c76704f7b1b45916 md5: 4c9ffd9d8888d6e17ea4f2ebfb02ec73 @@ -5283,6 +5439,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - geographiclib-cpp >=2.7,<2.8.0a0 size: 766298 timestamp: 1762551378982 - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-0.25.1-h3f43e3d_1.conda @@ -5300,6 +5459,10 @@ packages: - libstdcxx >=14 license: LGPL-2.1-or-later AND GPL-3.0-or-later purls: [] + run_exports: + weak: + - libasprintf >=0.25.1,<1.0a0 + - libgettextpo >=0.25.1,<1.0a0 size: 541357 timestamp: 1753343006214 - conda: https://conda.anaconda.org/conda-forge/linux-64/gettext-tools-0.25.1-h3f43e3d_1.conda @@ -5312,6 +5475,7 @@ packages: license: GPL-3.0-or-later license_family: GPL purls: [] + run_exports: {} size: 3644103 timestamp: 1753342966311 - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran-14.3.0-he448592_7.conda @@ -5324,6 +5488,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 30407 timestamp: 1759966108779 - conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_impl_linux-64-14.3.0-h1a219da_19.conda @@ -5338,21 +5503,27 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 18551249 timestamp: 1778268735401 -- conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_linux-64-14.3.0-h8bb2d51_25.conda - sha256: dd3712c75de3b07ee5cfd9ae88a3bc2c87a1c2683256c24b27e012e3f9f22cdf - md5: 8f6215a6040fd3c2e03e85a6583d3100 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gfortran_linux-64-14.3.0-h5ce6d8a_27.conda + sha256: b8e6bd99f0b7a5e8757a1cf9bf64edc6217206d8872fb9af5d8204e5b581b3d1 + md5: cedd6fb9fad7611ee0bcb0fb531d77f1 depends: - gfortran_impl_linux-64 14.3.0.* - - gcc_linux-64 ==14.3.0 h50e9bb6_25 + - gcc_linux-64 ==14.3.0 h50e9bb6_27 - binutils_linux-64 - sysroot_linux-64 license: BSD-3-Clause license_family: BSD purls: [] - size: 27402 - timestamp: 1779371710532 + run_exports: + strong: + - libgfortran5 >=14.3.0 + - libgfortran + - libgcc >=14 + size: 27545 + timestamp: 1781279939286 - conda: https://conda.anaconda.org/conda-forge/linux-64/git-2.54.0-pl5321h6d3cee1_1.conda sha256: bc98305103a2754f1b143bc525db9f2c2b0aee6ca278e909ee9eba28c1558c10 md5: ef4ced80193d2a6d4cd92e4b46636b07 @@ -5368,6 +5539,7 @@ packages: - perl 5.* license: GPL-2.0-or-later and LGPL-2.1-or-later purls: [] + run_exports: {} size: 11507059 timestamp: 1780737102525 - conda: https://conda.anaconda.org/conda-forge/linux-64/gl2ps-1.4.2-h36e74d4_2.conda @@ -5383,6 +5555,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gl2ps >=1.4.2,<1.4.3.0a0 size: 75835 timestamp: 1773985381918 - conda: https://conda.anaconda.org/conda-forge/linux-64/glew-2.3.0-h71661d4_0.conda @@ -5398,6 +5573,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - glew >=2.3.0,<2.4.0a0 size: 492673 timestamp: 1766373546677 - conda: https://conda.anaconda.org/conda-forge/linux-64/glfw-3.4-hb03c661_1.conda @@ -5415,32 +5593,39 @@ packages: - xorg-libxrandr >=1.5.4,<2.0a0 license: Zlib purls: [] + run_exports: + weak: + - glfw >=3.4,<4.0a0 size: 166432 timestamp: 1758809197097 -- conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.88.1-hd810c12_2.conda - sha256: 6a97b61cfb30a85c2f4a95f1f7525a873eea0b540f9f11b9cf31ad70d6635fce - md5: 9add1716591862a115c885dda4fcbeb5 +- conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.88.2-hbe0478d_0.conda + sha256: 84448dc33e66a2c74c58fb2a95d9e84547bc65cf44dcebf447b8d236c0ccc68b + md5: 7ac6295be13fafd7f20869b30b47ec2f depends: - python * - packaging - - libglib ==2.88.1 h0d30a3d_2 - - glib-tools ==2.88.1 hee1de02_2 + - libglib ==2.88.2 h0d30a3d_0 + - glib-tools ==2.88.2 h8094192_0 license: LGPL-2.1-or-later purls: [] - size: 85268 - timestamp: 1778508800134 -- conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.1-hee1de02_2.conda - sha256: ae41fd5c867bc4e713a8cc1dc06f5b418026fec116cc222abe33e94235c6b241 - md5: e5a459d2bb98edb88de5a44bfad66b9d - depends: - - libglib ==2.88.1 h0d30a3d_2 + run_exports: + weak: + - libglib >=2.88.2,<3.0a0 + size: 85433 + timestamp: 1782463895250 +- conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.88.2-h8094192_0.conda + sha256: 079757e4e0497d67505b52062668e4cc0d2a86ec065ae2c0c57487a178206061 + md5: cfe66c21ae651b84a3d25a1dbb641a54 + depends: + - libglib ==2.88.2 h0d30a3d_0 - libffi - libgcc >=14 - __glibc >=2.17,<3.0.a0 license: LGPL-2.1-or-later purls: [] - size: 236955 - timestamp: 1778508800134 + run_exports: {} + size: 238517 + timestamp: 1782463895250 - conda: https://conda.anaconda.org/conda-forge/linux-64/glslang-16.3.0-h96af755_0.conda sha256: 3c9b6a90937a96ad27d160304cdbe5e9961db613aba2b84ff673429f0c61d48e md5: d175cb2c14104728ada04883786a309d @@ -5452,6 +5637,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - glslang >=16,<17.0a0 size: 1366082 timestamp: 1777747028121 - conda: https://conda.anaconda.org/conda-forge/linux-64/gmock-1.17.0-ha770c72_1.conda @@ -5462,6 +5650,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 7578 timestamp: 1748320126956 - conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda @@ -5472,6 +5661,9 @@ packages: - libstdcxx-ng >=12 license: GPL-2.0-or-later OR LGPL-3.0-or-later purls: [] + run_exports: + weak: + - gmp >=6.3.0,<7.0a0 size: 460055 timestamp: 1718980856608 - conda: https://conda.anaconda.org/conda-forge/linux-64/gnutls-3.8.13-h18acefa_0.conda @@ -5489,6 +5681,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gnutls >=3.8.13,<3.9.0a0 size: 2054535 timestamp: 1778044634746 - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.15-hecca717_0.conda @@ -5501,6 +5696,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 size: 100054 timestamp: 1780454302233 - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda @@ -5526,6 +5724,9 @@ packages: license: EPL-1.0 license_family: Other purls: [] + run_exports: + weak: + - graphviz >=14.1.2,<15.0a0 size: 2426455 timestamp: 1769427102743 - conda: https://conda.anaconda.org/conda-forge/linux-64/gst-plugins-base-1.26.11-h6d08254_0.conda @@ -5561,6 +5762,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gst-plugins-base >=1.26.11,<1.27.0a0 size: 3199241 timestamp: 1776268376145 - conda: https://conda.anaconda.org/conda-forge/linux-64/gstreamer-1.26.11-h29cf534_0.conda @@ -5577,6 +5781,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gstreamer >=1.26.11,<1.27.0a0 size: 2281638 timestamp: 1776268376145 - conda: https://conda.anaconda.org/conda-forge/linux-64/gstreamer-orc-0.4.42-h82d0256_0.conda @@ -5587,6 +5794,7 @@ packages: - libgcc >=14 license: BSD-2-Clause AND BSD-3-Clause purls: [] + run_exports: {} size: 383443 timestamp: 1768408501404 - conda: https://conda.anaconda.org/conda-forge/linux-64/gtest-1.17.0-h84d6215_1.conda @@ -5601,6 +5809,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - gtest >=1.17.0,<1.17.1.0a0 size: 416610 timestamp: 1748320117187 - conda: https://conda.anaconda.org/conda-forge/linux-64/gtk3-3.24.52-ha5ea40c_0.conda @@ -5644,6 +5855,10 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gtk3 >=3.24.52,<4.0a0 + - adwaita-icon-theme size: 5939083 timestamp: 1774288645605 - conda: https://conda.anaconda.org/conda-forge/linux-64/gts-0.7.6-h977cf35_4.conda @@ -5656,6 +5871,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gts >=0.7.6,<0.8.0a0 size: 318312 timestamp: 1686545244763 - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-14.3.0-he448592_7.conda @@ -5667,6 +5885,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 30403 timestamp: 1759966121169 - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.3.0-h2185e75_19.conda @@ -5680,21 +5899,26 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 15235650 timestamp: 1778268773535 -- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-h72ca5df_25.conda - sha256: 369abc77d74a8275c734f9ca2375892b86d3163a541b1f5a2de946083a9e3ab0 - md5: 4718c7fefd927621bad46a8bcc6387d6 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-hd240bd5_27.conda + sha256: cf5a44d14732b79e3c2bc6ebe1dba4f6b9077939f3093c75e36ad340737b5c15 + md5: 41fae38a424bbc78438cfec6a4fde187 depends: - gxx_impl_linux-64 14.3.0.* - - gcc_linux-64 ==14.3.0 h50e9bb6_25 + - gcc_linux-64 ==14.3.0 h50e9bb6_27 - binutils_linux-64 - sysroot_linux-64 license: BSD-3-Clause license_family: BSD purls: [] - size: 27696 - timestamp: 1779371710532 + run_exports: + strong: + - libstdcxx >=14 + - libgcc >=14 + size: 27854 + timestamp: 1781279939286 - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-cmake3-3.5.5-h05f81b2_0.conda sha256: b654d0102a8b8242836a5863c0157945b5c549d505383f4f8b724926a55f68aa md5: fda2ad837ffe2ed7f73ddfab260d82e3 @@ -5703,6 +5927,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-cmake3 >=3.5.5,<4.0a0 size: 7430 timestamp: 1759138411890 - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-math7-7.5.2-h5bbc156_2.conda @@ -5714,6 +5941,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-math7 >=7.5.2,<8.0a0 size: 8251 timestamp: 1759147748392 - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-math7-python-7.5.2-py312h89d136e_2.conda @@ -5731,6 +5961,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 1029585 timestamp: 1759147748392 - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-tools-2.0.3-h3f54f1a_1.conda @@ -5741,6 +5972,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-tools >=2.0.3,<3.0a0 size: 7803 timestamp: 1759148392717 - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-tools2-2.0.3-h89235b8_1.conda @@ -5751,6 +5985,10 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-tools >=2.0.3,<3.0a0 + - libgz-tools >=2.0.3,<3.0a0 size: 7839 timestamp: 1759148392717 - conda: https://conda.anaconda.org/conda-forge/linux-64/gz-utils2-2.2.1-hdaf9e28_2.conda @@ -5761,28 +5999,24 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-utils2 >=2.2.1,<3.0a0 size: 8042 timestamp: 1767701472560 -- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-14.2.1-h6083320_0.conda - sha256: da9901aa1e20cbc2369fda212039b294dd02bce95f005539bab840b7310bf7d0 - md5: 21ee4640b7c2d94e584349fa12b29b9a +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-14.2.1-ha770c72_1.conda + sha256: 853beec89ff91cbbf630f1d305b69153eb28a3cb78af95ddc1fb4d30e524c6f4 + md5: 72e956a71241633d8c80aa198fd08784 depends: - - __glibc >=2.17,<3.0.a0 - - cairo >=1.18.4,<2.0a0 - - graphite2 >=1.3.14,<2.0a0 - - icu >=78.3,<79.0a0 - - libexpat >=2.8.1,<3.0a0 - - libfreetype >=2.14.3 - - libfreetype6 >=2.14.3 - - libgcc >=14 - - libglib >=2.88.1,<3.0a0 - - libstdcxx >=14 - - libzlib >=1.3.2,<2.0a0 + - libharfbuzz-devel 14.2.1 h17a8019_1 license: MIT license_family: MIT purls: [] - size: 2362258 - timestamp: 1780450503234 + run_exports: + weak: + - libharfbuzz >=14.2.1 + size: 11039 + timestamp: 1782800611635 - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf4-4.2.15-h2a13503_7.conda sha256: 0d09b6dc1ce5c4005ae1c6a19dc10767932ef9a5e9c755cfdbb5189ac8fb0684 md5: bd77f8da987968ec3927990495dc22e4 @@ -5794,6 +6028,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - hdf4 >=4.2.15,<4.2.16.0a0 size: 756742 timestamp: 1695661547874 - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda @@ -5812,6 +6049,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - hdf5 >=1.14.6,<1.14.7.0a0 size: 3721555 timestamp: 1780581675871 - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda @@ -5820,6 +6060,7 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: {} size: 17625 timestamp: 1771539597968 - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda @@ -5832,6 +6073,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - icu >=78.3,<79.0a0 size: 12723451 timestamp: 1773822285671 - conda: https://conda.anaconda.org/conda-forge/linux-64/imath-3.2.2-hde8ca8f_0.conda @@ -5845,6 +6089,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - imath >=3.2.2,<3.2.3.0a0 size: 160289 timestamp: 1759983212466 - conda: https://conda.anaconda.org/conda-forge/linux-64/intel-gmmlib-22.10.0-hb700be7_0.conda @@ -5857,6 +6104,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - intel-gmmlib >=22.10.0,<23.0a0 size: 1013714 timestamp: 1774422680665 - conda: https://conda.anaconda.org/conda-forge/linux-64/intel-media-driver-25.3.4-hecca717_0.conda @@ -5871,6 +6121,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - intel-media-driver >=25.3.4,<25.4.0a0 size: 8424610 timestamp: 1757591682198 - conda: https://conda.anaconda.org/conda-forge/linux-64/jack-1.9.22-hf4617a5_3.conda @@ -5885,6 +6138,9 @@ packages: license: LGPL-2.0-only license_family: LGPL purls: [] + run_exports: + weak: + - jack >=1.9.22,<1.10.0a0 size: 461260 timestamp: 1747574434594 - conda: https://conda.anaconda.org/conda-forge/linux-64/jasper-4.2.9-h1588d4d_1.conda @@ -5901,6 +6157,9 @@ packages: - libjpeg-turbo >=3.1.2,<4.0a0 license: JasPer-2.0 purls: [] + run_exports: + weak: + - jasper >=4.2.9,<5.0a0 size: 684185 timestamp: 1773677703432 - conda: https://conda.anaconda.org/conda-forge/linux-64/jsoncpp-1.9.6-hf42df4d_1.conda @@ -5912,6 +6171,9 @@ packages: - libstdcxx >=13 license: LicenseRef-Public-Domain OR MIT purls: [] + run_exports: + weak: + - jsoncpp >=1.9.6,<1.9.7.0a0 size: 169093 timestamp: 1733780223643 - conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda @@ -5922,6 +6184,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - jxrlib >=1.1,<1.2.0a0 size: 239104 timestamp: 1703333860145 - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda @@ -5932,6 +6197,9 @@ packages: - libgcc >=13 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - keyutils >=1.6.3,<2.0a0 size: 134088 timestamp: 1754905959823 - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py312h0a2e395_0.conda @@ -5947,11 +6215,12 @@ packages: license_family: BSD purls: - pkg:pypi/kiwisolver?source=hash-mapping + run_exports: {} size: 77120 timestamp: 1773067050308 -- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda - sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 - md5: fb53fb07ce46a575c5d004bbc96032c2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbde042b_1.conda + sha256: 9b07046870772f28740e3f6149f09ff222843733087a33c5540b169c6289652d + md5: 54157a1c8c0bb70f62dd0b17fba7e7f2 depends: - __glibc >=2.17,<3.0.a0 - keyutils >=1.6.3,<2.0a0 @@ -5959,12 +6228,15 @@ packages: - libedit >=3.1.20250104,<4.0a0 - libgcc >=14 - libstdcxx >=14 - - openssl >=3.5.5,<4.0a0 + - openssl >=3.5.7,<4.0a0 license: MIT license_family: MIT purls: [] - size: 1386730 - timestamp: 1769769569681 + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 1388990 + timestamp: 1781859420533 - conda: https://conda.anaconda.org/conda-forge/linux-64/lame-3.100-h166bdaf_1003.tar.bz2 sha256: aad2a703b9d7b038c0f745b853c6bb5f122988fe1a7a096e0e606d9cbec4eaab md5: a8832b479f93521a9e7b5b743803be51 @@ -5973,6 +6245,9 @@ packages: license: LGPL-2.0-only license_family: LGPL purls: [] + run_exports: + weak: + - lame >=3.100,<3.101.0a0 size: 508258 timestamp: 1664996250081 - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_1.conda @@ -5986,6 +6261,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - lcms2 >=2.19.1,<3.0a0 size: 251971 timestamp: 1780211695895 - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda @@ -5999,6 +6277,7 @@ packages: license: GPL-3.0-only license_family: GPL purls: [] + run_exports: {} size: 728002 timestamp: 1774197446916 - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda @@ -6011,6 +6290,9 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - lerc >=4.1.0,<5.0a0 size: 261513 timestamp: 1773113328888 - conda: https://conda.anaconda.org/conda-forge/linux-64/level-zero-1.29.0-hb700be7_0.conda @@ -6023,6 +6305,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 875773 timestamp: 1780142086148 - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda @@ -6038,6 +6321,10 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - libabseil >=20250512.1,<20250513.0a0 + - libabseil =*=cxx17* size: 1310612 timestamp: 1750194198254 - conda: https://conda.anaconda.org/conda-forge/linux-64/libacl-2.3.2-h0f662aa_0.conda @@ -6049,6 +6336,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - libacl >=2.3.2,<2.4.0a0 size: 110600 timestamp: 1706132570609 - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda @@ -6061,11 +6351,14 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - libaec >=1.1.5,<2.0a0 size: 36544 timestamp: 1769221884824 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.7-gpl_hc2c16d8_101.conda - sha256: 78dd3d493d72c7d7c7647912fe383a3545a2695ee308037b64e9d0752ccedbe9 - md5: bb1483d91797dae0b466cab86ceb59a7 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.8-gpl_hc2c16d8_100.conda + sha256: f916b51f55f51a9bb2d902e0a5f029490f7b745aee549c349751c1787ddc26b8 + md5: 44652e646cb623f486ea72e7e7479222 depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 @@ -6076,13 +6369,16 @@ packages: - libzlib >=1.3.2,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - lzo >=2.10,<3.0a0 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: [] - size: 890218 - timestamp: 1778486345922 + run_exports: + weak: + - libarchive >=3.8.8,<3.9.0a0 + size: 867280 + timestamp: 1782289011634 - conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-0.25.1-h3f43e3d_1.conda sha256: cb728a2a95557bb6a5184be2b8be83a6f2083000d0c7eff4ad5bbe5792133541 md5: 3b0d184bc9404516d418d4509e418bdc @@ -6092,6 +6388,9 @@ packages: - libstdcxx >=14 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libasprintf >=0.25.1,<1.0a0 size: 53582 timestamp: 1753342901341 - conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-devel-0.25.1-h3f43e3d_1.conda @@ -6103,6 +6402,9 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libasprintf >=0.25.1,<1.0a0 size: 34734 timestamp: 1753342921605 - conda: https://conda.anaconda.org/conda-forge/linux-64/libass-0.17.4-h96ad9f0_0.conda @@ -6121,6 +6423,9 @@ packages: - harfbuzz >=11.0.1 license: ISC purls: [] + run_exports: + weak: + - libass >=0.17.4,<0.17.5.0a0 size: 152179 timestamp: 1749328931930 - conda: https://conda.anaconda.org/conda-forge/linux-64/libattr-2.5.2-hb03c661_1.conda @@ -6132,6 +6437,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - libattr >=2.5.2,<2.6.0a0 size: 53316 timestamp: 1773595896163 - conda: https://conda.anaconda.org/conda-forge/linux-64/libavif16-1.4.2-hcfa2d63_0.conda @@ -6147,6 +6455,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - libavif16 >=1.4.2,<2.0a0 size: 149510 timestamp: 1779847073231 - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-8_h4a7cf45_openblas.conda @@ -6165,6 +6476,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 size: 18804 timestamp: 1779859100675 - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-1.88.0-hd24cca6_7.conda @@ -6183,6 +6497,7 @@ packages: - boost-cpp <0.0a0 license: BSL-1.0 purls: [] + run_exports: {} size: 3072984 timestamp: 1766347479317 - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-devel-1.88.0-hfcd1e18_7.conda @@ -6195,6 +6510,9 @@ packages: - boost-cpp <0.0a0 license: BSL-1.0 purls: [] + run_exports: + weak: + - libboost >=1.88.0,<1.89.0a0 size: 40112 timestamp: 1766347628036 - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-headers-1.88.0-ha770c72_7.conda @@ -6204,6 +6522,7 @@ packages: - boost-cpp <0.0a0 license: BSL-1.0 purls: [] + run_exports: {} size: 14584021 timestamp: 1766347497416 - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-python-1.88.0-py312hf890105_7.conda @@ -6222,6 +6541,7 @@ packages: - boost <0.0a0 license: BSL-1.0 purls: [] + run_exports: {} size: 130172 timestamp: 1766347836920 - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-python-devel-1.88.0-py312h26dfbe5_7.conda @@ -6238,6 +6558,9 @@ packages: - boost <0.0a0 license: BSL-1.0 purls: [] + run_exports: + weak: + - libboost-python >=1.88.0,<1.89.0a0 size: 18972 timestamp: 1766348204323 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda @@ -6249,6 +6572,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 size: 79965 timestamp: 1764017188531 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda @@ -6261,6 +6587,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 size: 34632 timestamp: 1764017199083 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda @@ -6273,6 +6602,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 size: 298378 timestamp: 1764017210931 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcap-2.77-hd0affe5_1.conda @@ -6284,6 +6616,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libcap >=2.77,<2.78.0a0 size: 124432 timestamp: 1774333989027 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda @@ -6299,6 +6634,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 size: 18778 timestamp: 1779859107964 - conda: https://conda.anaconda.org/conda-forge/linux-64/libccd-double-2.1-h59595ed_3.conda @@ -6312,6 +6650,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libccd-double >=2.1,<2.2.0a0 size: 36171 timestamp: 1687341825064 - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp21.1-21.1.8-default_h99862b1_4.conda @@ -6325,34 +6666,44 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] + run_exports: + weak: + - libclang-cpp21.1 >=21.1.8,<21.2.0a0 size: 21066414 timestamp: 1777010859192 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.7-default_h99862b1_1.conda - sha256: e638accaebe12402ce1c80ac2ba04be8114bbaa71d4012fbe8f2661fa76ea841 - md5: 56888f4782b0a0c6fd293d8138c679bf +- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.8-default_h6c227bf_3.conda + sha256: ccb8bd0a8f2d57675b6a60dabb0cc8becb35c2748ac4ec920d7f7625b93c16d8 + md5: 864e6d29ec7378b89ff5b5c9c629099e depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libllvm22 >=22.1.7,<22.2.0a0 - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libllvm22 >=22.1.8,<22.2.0a0 license: Apache-2.0 WITH LLVM-exception - license_family: Apache + license_family: APACHE purls: [] - size: 21680350 - timestamp: 1780522287716 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.7-default_h746c552_1.conda - sha256: 5100d6571c361a3b4123007b71448a15901ad63ac948f3f02bbc7df4079fe4d1 - md5: f5d04d68e7fd19a24f1fe35a74bafabb + run_exports: + weak: + - libclang-cpp22.1 >=22.1.8,<22.2.0a0 + size: 24175081 + timestamp: 1782358841320 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_h9692865_3.conda + sha256: b90ed8467a692788477c06bc0359fac52ed5651d801ddef189ba4b7ecf3ce38c + md5: 2a913525f4201f1adab2711fcf6f89b3 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libllvm22 >=22.1.7,<22.2.0a0 + - libclang-cpp22.1 ==22.1.8 default_h6c227bf_3 - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libllvm22 >=22.1.8,<22.2.0a0 license: Apache-2.0 WITH LLVM-exception - license_family: Apache + license_family: APACHE purls: [] - size: 12818349 - timestamp: 1780522452233 + run_exports: + weak: + - libclang13 >=22.1.8 + size: 14283567 + timestamp: 1782358841320 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 @@ -6365,25 +6716,32 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - libcups >=2.3.3,<2.4.0a0 size: 4518030 timestamp: 1770902209173 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.20.0-hcf29cc6_0.conda - sha256: 75963a5dd913311f59a35dbd307592f4fa754c4808aff9c33edb430c415e38eb - md5: c3cc2864f82a944bc90a7beb4d3b0e88 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.21.0-hae6b9f4_2.conda + sha256: ba8354084b34fce56d5697982fce4a384c148e972e15c0ab891187617fe7ec29 + md5: f9c59d277a16ec8f272b2d5dd2ec3335 depends: - __glibc >=2.17,<3.0.a0 - krb5 >=1.22.2,<1.23.0a0 - libgcc >=14 - libnghttp2 >=1.68.1,<2.0a0 + - libpsl >=0.22.0,<0.23.0a0 - libssh2 >=1.11.1,<2.0a0 - libzlib >=1.3.2,<2.0a0 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT purls: [] - size: 468706 - timestamp: 1777461492876 + run_exports: + weak: + - libcurl >=8.21.0,<9.0a0 + size: 480327 + timestamp: 1782911787190 - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 md5: 6c77a605a7a689d17d4819c0f8ac9a00 @@ -6393,6 +6751,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 size: 73490 timestamp: 1761979956660 - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.127-hb03c661_0.conda @@ -6405,6 +6766,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libdrm >=2.4.127,<2.5.0a0 size: 311505 timestamp: 1778975798004 - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda @@ -6418,6 +6782,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - libedit >=3.1.20250104,<3.2.0a0 size: 134676 timestamp: 1738479519902 - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_3.conda @@ -6428,6 +6795,7 @@ packages: - libglvnd 1.7.0 ha4b6fd6_3 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 46500 timestamp: 1779728188901 - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_3.conda @@ -6440,6 +6808,9 @@ packages: - xorg-libx11 license: LicenseRef-libglvnd purls: [] + run_exports: + weak: + - libegl >=1.7.0,<2.0a0 size: 31718 timestamp: 1779728222280 - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda @@ -6450,6 +6821,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - libev >=4.33,<4.34.0a0 size: 112766 timestamp: 1702146165126 - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda @@ -6461,11 +6835,14 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libevent >=2.1.12,<2.1.13.0a0 size: 427426 timestamp: 1685725977222 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda - sha256: 363018b25fdb5534c79783d912bd4b685a3547f4fc5996357ad548899b0ee8e7 - md5: 93764a5ca80616e9c10106cdaec92f74 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda + sha256: 16feffd9ddbbe5b718515d38ee376c685ba95491cd901244e24671d20b952a77 + md5: b24d3c612f71e7aa74158d92106318b2 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -6474,8 +6851,9 @@ packages: license: MIT license_family: MIT purls: [] - size: 77294 - timestamp: 1779278686680 + run_exports: {} + size: 77856 + timestamp: 1781203599810 - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 md5: a360c33a5abe61c07959e449fa1453eb @@ -6485,6 +6863,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libffi >=3.5.2,<3.6.0a0 size: 58592 timestamp: 1769456073053 - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.4.3-h59595ed_0.conda @@ -6499,6 +6880,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libflac >=1.4.3,<1.5.0a0 size: 394383 timestamp: 1687765514062 - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda @@ -6508,6 +6892,7 @@ packages: - libfreetype6 >=2.14.3 license: GPL-2.0-only OR FTL purls: [] + run_exports: {} size: 8049 timestamp: 1774298163029 - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda @@ -6522,6 +6907,7 @@ packages: - freetype >=2.14.3 license: GPL-2.0-only OR FTL purls: [] + run_exports: {} size: 384575 timestamp: 1774298162622 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda @@ -6536,6 +6922,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 1041084 timestamp: 1778269013026 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda @@ -6546,6 +6933,9 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: + strong: + - libgcc size: 27694 timestamp: 1778269016987 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgd-2.3.3-h5fbf134_12.conda @@ -6568,6 +6958,9 @@ packages: license: GD license_family: BSD purls: [] + run_exports: + weak: + - libgd >=2.3.3,<2.4.0a0 size: 177306 timestamp: 1766331805898 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgettextpo-0.25.1-h3f43e3d_1.conda @@ -6580,6 +6973,9 @@ packages: license: GPL-3.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - libgettextpo >=0.25.1,<1.0a0 size: 188293 timestamp: 1753342911214 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgettextpo-devel-0.25.1-h3f43e3d_1.conda @@ -6593,6 +6989,9 @@ packages: license: GPL-3.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - libgettextpo >=0.25.1,<1.0a0 size: 37407 timestamp: 1753342931100 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda @@ -6605,6 +7004,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 27655 timestamp: 1778269042954 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda @@ -6618,6 +7018,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 2483673 timestamp: 1778269025089 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_3.conda @@ -6629,6 +7030,7 @@ packages: - libglx 1.7.0 ha4b6fd6_3 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 133469 timestamp: 1779728207669 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-devel-1.7.0-ha4b6fd6_3.conda @@ -6640,24 +7042,30 @@ packages: - libglx-devel 1.7.0 ha4b6fd6_3 license: LicenseRef-libglvnd purls: [] + run_exports: + weak: + - libgl >=1.7.0,<2.0a0 size: 115664 timestamp: 1779728218325 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.1-h0d30a3d_2.conda - sha256: 33eb5d5310a5c2c0a4707a0afa644801c2e08c8f70c45e1f62f354116dfe0970 - md5: 17d484ab9c8179c6a6e5b7dbb5065afc +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.2-h0d30a3d_0.conda + sha256: 4bee10e62796f01e4fa2b5849135b1cc061337fe9cf5eb9bd79e9664922ae0e4 + md5: 889febc66cd9e4190f80ef9718fa239b depends: - - __glibc >=2.17,<3.0.a0 - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libiconv >=1.18,<2.0a0 + - libzlib >=1.3.2,<2.0a0 - libffi >=3.5.2,<3.6.0a0 - pcre2 >=10.47,<10.48.0a0 - - libzlib >=1.3.2,<2.0a0 - - libiconv >=1.18,<2.0a0 constrains: - glib >2.66 license: LGPL-2.1-or-later purls: [] - size: 4754097 - timestamp: 1778508800134 + run_exports: + weak: + - libglib >=2.88.2,<3.0a0 + size: 4754220 + timestamp: 1782463895250 - conda: https://conda.anaconda.org/conda-forge/linux-64/libglu-9.0.3-h5888daf_1.conda sha256: a0105eb88f76073bbb30169312e797ed5449ebb4e964a756104d6e54633d17ef md5: 8422fcc9e5e172c91e99aef703b3ce65 @@ -6668,6 +7076,9 @@ packages: - libstdcxx >=13 license: SGI-B-2.0 purls: [] + run_exports: + weak: + - libglu >=9.0.3,<9.1.0a0 size: 325262 timestamp: 1748692137626 - conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_3.conda @@ -6677,6 +7088,7 @@ packages: - __glibc >=2.17,<3.0.a0 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 133586 timestamp: 1779728183422 - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_3.conda @@ -6688,6 +7100,7 @@ packages: - xorg-libx11 >=1.8.13,<2.0a0 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 76586 timestamp: 1779728199059 - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_3.conda @@ -6700,6 +7113,9 @@ packages: - xorg-xorgproto license: LicenseRef-libglvnd purls: [] + run_exports: + weak: + - libglx >=1.7.0,<2.0a0 size: 27363 timestamp: 1779728211402 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda @@ -6710,6 +7126,9 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: + strong: + - _openmp_mutex >=4.5 size: 603817 timestamp: 1778268942614 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-cmake3-3.5.5-h54a6638_0.conda @@ -6723,6 +7142,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-cmake3 >=3.5.5,<4.0a0 size: 217564 timestamp: 1759138411890 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-cmake4-4.2.0-h54a6638_1.conda @@ -6735,6 +7157,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-cmake4 >=4.2.0,<5.0a0 size: 217934 timestamp: 1759138566319 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-math7-7.5.2-h54a6638_2.conda @@ -6750,6 +7175,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-math7 >=7.5.2,<8.0a0 size: 295819 timestamp: 1759147748392 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-tools-2.0.3-h54a6638_1.conda @@ -6764,6 +7192,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-tools >=2.0.3,<3.0a0 size: 49853 timestamp: 1759148392717 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgz-utils2-2.2.1-h54a6638_2.conda @@ -6778,8 +7209,57 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-utils2 >=2.2.1,<3.0a0 size: 63479 timestamp: 1767701472558 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-14.2.1-h17a8019_1.conda + sha256: 821c315f6b5171aa89e735be2ad84e74eb3f898fc7610ee36cfecd95dfa789e8 + md5: fb4669c3990b94ea32fbb81f433e9aa6 + depends: + - __glibc >=2.17,<3.0.a0 + - cairo >=1.18.4,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=14 + - libglib >=2.88.2,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 1297668 + timestamp: 1782800580119 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-devel-14.2.1-h17a8019_1.conda + sha256: 6d8e793042affd18ca1784b7794fab14d16f54f984777ce6ab86bacaa465ab0d + md5: 99cf21100441e51272f1cd6fe0632a20 + depends: + - __glibc >=2.17,<3.0.a0 + - cairo >=1.18.4,<2.0a0 + - freetype + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=14 + - libglib >=2.88.2,<3.0a0 + - libharfbuzz 14.2.1 h17a8019_1 + - libpng >=1.6.58,<1.7.0a0 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libharfbuzz >=14.2.1 + size: 1970690 + timestamp: 1782800603897 - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.13.0-default_he001693_1000.conda sha256: 5041d295813dfb84652557839825880aae296222ab725972285c5abe3b6e4288 md5: c197985b58bc813d26b42881f0021c82 @@ -6792,6 +7272,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libhwloc >=2.13.0,<2.13.1.0a0 size: 2436378 timestamp: 1770953868164 - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwy-1.4.0-h10be129_0.conda @@ -6803,6 +7286,9 @@ packages: - libstdcxx >=14 license: Apache-2.0 OR BSD-3-Clause purls: [] + run_exports: + weak: + - libhwy >=1.4.0,<1.5.0a0 size: 1435782 timestamp: 1776989559668 - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda @@ -6813,6 +7299,9 @@ packages: - libgcc >=14 license: LGPL-2.1-only purls: [] + run_exports: + weak: + - libiconv >=1.18,<2.0a0 size: 790176 timestamp: 1754908768807 - conda: https://conda.anaconda.org/conda-forge/linux-64/libidn2-2.3.8-hfac485b_1.conda @@ -6825,6 +7314,9 @@ packages: license: LGPL-2.0-only license_family: LGPL purls: [] + run_exports: + weak: + - libidn2 >=2,<3.0a0 size: 139036 timestamp: 1760385590993 - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda @@ -6837,6 +7329,9 @@ packages: - jpeg <0.0.0a license: IJG AND BSD-3-Clause AND Zlib purls: [] + run_exports: + weak: + - libjpeg-turbo >=3.1.4.1,<4.0a0 size: 633831 timestamp: 1775962768273 - conda: https://conda.anaconda.org/conda-forge/linux-64/libjxl-0.11.2-h174a0a3_1.conda @@ -6852,6 +7347,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libjxl >=0.11,<1.0a0 size: 1846962 timestamp: 1777065125966 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda @@ -6867,6 +7365,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 size: 18790 timestamp: 1779859115086 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapacke-3.11.0-8_h6ae95b6_openblas.conda @@ -6882,6 +7383,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - liblapacke >=3.11.0,<3.12.0a0 size: 18824 timestamp: 1779859122364 - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda @@ -6898,11 +7402,14 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] + run_exports: + weak: + - libllvm21 >=21.1.8,<21.2.0a0 size: 44333366 timestamp: 1765959132513 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.7-hf7376ad_0.conda - sha256: 7b2cfedb9a0c4d2329e6b5e527f36e23579c985f00073330c5d739cdd4592218 - md5: 963a932cab52c52cb9cda5877d0d8537 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-hf7376ad_1.conda + sha256: e9b5f301d6b001a9b8ce782157f56b75c92c4fbc9eba95dc6345c1139251d13b + md5: 298bb2483fc7d15396147cf1c1465359 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -6914,8 +7421,11 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] - size: 44240299 - timestamp: 1780445743730 + run_exports: + weak: + - libllvm22 >=22.1.8,<22.2.0a0 + size: 44320272 + timestamp: 1781788728739 - conda: https://conda.anaconda.org/conda-forge/linux-64/libltdl-2.4.3a-h5888daf_0.conda sha256: 7620c6425d4491e17083106ca49624448fc16186c30a93cf2b58f862bba416d1 md5: 8e5de39cab514fa908fcaa7ba37a8738 @@ -6925,6 +7435,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - libltdl >=2.4.3a,<2.5.0a0 size: 38472 timestamp: 1740593829307 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda @@ -6937,6 +7450,9 @@ packages: - xz 5.8.3.* license: 0BSD purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 size: 113478 timestamp: 1775825492909 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.3-hb03c661_0.conda @@ -6948,6 +7464,9 @@ packages: - liblzma 5.8.3 hb03c661_0 license: 0BSD purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 size: 491429 timestamp: 1775825511214 - conda: https://conda.anaconda.org/conda-forge/linux-64/libmicrohttpd-1.0.5-hc2fc477_0.conda @@ -6960,6 +7479,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - libmicrohttpd >=1.0.5,<1.1.0a0 size: 287897 timestamp: 1779091106723 - conda: https://conda.anaconda.org/conda-forge/linux-64/libmujoco-3.6.0-h31df9c7_0.conda @@ -6981,6 +7503,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libmujoco >=3.6.0,<3.6.1.0a0 size: 11159916 timestamp: 1773254855824 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnetcdf-4.9.3-nompi_hbf2fc22_104.conda @@ -7006,6 +7531,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libnetcdf >=4.9.3,<4.9.4.0a0 size: 870788 timestamp: 1770718321021 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda @@ -7023,6 +7551,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 size: 663344 timestamp: 1773854035739 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda @@ -7034,6 +7565,9 @@ packages: license: LGPL-2.1-only license_family: GPL purls: [] + run_exports: + weak: + - libnsl >=2.0.1,<2.1.0a0 size: 33731 timestamp: 1750274110928 - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda @@ -7044,6 +7578,9 @@ packages: - libgcc >=13 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libntlm >=1.8,<2.0a0 size: 33418 timestamp: 1734670021371 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnuma-2.0.18-hb03c661_3.conda @@ -7054,6 +7591,9 @@ packages: - libgcc >=14 license: LGPL-2.1-only purls: [] + run_exports: + weak: + - libnuma >=2.0.18,<3.0a0 size: 44408 timestamp: 1772779840609 - conda: https://conda.anaconda.org/conda-forge/linux-64/libogg-1.3.5-hd0c01bc_1.conda @@ -7065,6 +7605,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libogg >=1.3.5,<1.4.0a0 size: 218500 timestamp: 1745825989535 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda @@ -7080,6 +7623,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libopenblas >=0.3.33,<1.0a0 size: 5931919 timestamp: 1776993658641 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopencv-4.12.0-qt6_py312h52d6ec5_612.conda @@ -7133,6 +7679,9 @@ packages: purls: - pkg:pypi/opencv-python?source=hash-mapping - pkg:pypi/opencv-python-headless?source=hash-mapping + run_exports: + weak: + - libopencv >=4.12.0,<4.12.1.0a0 size: 32672205 timestamp: 1766495315053 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_3.conda @@ -7143,6 +7692,7 @@ packages: - libglvnd 1.7.0 ha4b6fd6_3 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 51767 timestamp: 1779728204026 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-devel-1.7.0-ha4b6fd6_3.conda @@ -7153,6 +7703,9 @@ packages: - libopengl 1.7.0 ha4b6fd6_3 license: LicenseRef-libglvnd purls: [] + run_exports: + weak: + - libopengl >=1.7.0,<2.0a0 size: 16667 timestamp: 1779728214747 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-2025.4.1-hb56ce9e_1.conda @@ -7165,6 +7718,9 @@ packages: - pugixml >=1.15,<1.16.0a0 - tbb >=2022.3.0 purls: [] + run_exports: + weak: + - libopenvino >=2025.4.1,<2025.4.2.0a0 size: 6504144 timestamp: 1769904250547 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-auto-batch-plugin-2025.4.1-hd85de46_1.conda @@ -7177,6 +7733,7 @@ packages: - libstdcxx >=14 - tbb >=2022.3.0 purls: [] + run_exports: {} size: 114792 timestamp: 1769904275716 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-auto-plugin-2025.4.1-hd85de46_1.conda @@ -7189,6 +7746,7 @@ packages: - libstdcxx >=14 - tbb >=2022.3.0 purls: [] + run_exports: {} size: 250114 timestamp: 1769904292210 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-hetero-plugin-2025.4.1-hd41364c_1.conda @@ -7201,6 +7759,7 @@ packages: - libstdcxx >=14 - pugixml >=1.15,<1.16.0a0 purls: [] + run_exports: {} size: 212030 timestamp: 1769904308850 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-intel-cpu-plugin-2025.4.1-hb56ce9e_1.conda @@ -7214,6 +7773,7 @@ packages: - pugixml >=1.15,<1.16.0a0 - tbb >=2022.3.0 purls: [] + run_exports: {} size: 12956806 timestamp: 1769904325853 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-intel-gpu-plugin-2025.4.1-hb56ce9e_1.conda @@ -7228,6 +7788,7 @@ packages: - pugixml >=1.15,<1.16.0a0 - tbb >=2022.3.0 purls: [] + run_exports: {} size: 11421657 timestamp: 1769904366195 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-intel-npu-plugin-2025.4.1-hb56ce9e_1.conda @@ -7242,6 +7803,7 @@ packages: - pugixml >=1.15,<1.16.0a0 - tbb >=2022.3.0 purls: [] + run_exports: {} size: 1743490 timestamp: 1769904403110 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-ir-frontend-2025.4.1-hd41364c_1.conda @@ -7254,6 +7816,9 @@ packages: - libstdcxx >=14 - pugixml >=1.15,<1.16.0a0 purls: [] + run_exports: + weak: + - libopenvino-ir-frontend >=2025.4.1,<2025.4.2.0a0 size: 200411 timestamp: 1769904421156 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-onnx-frontend-2025.4.1-h1862bb8_1.conda @@ -7268,6 +7833,9 @@ packages: - libprotobuf >=6.31.1,<6.31.2.0a0 - libstdcxx >=14 purls: [] + run_exports: + weak: + - libopenvino-onnx-frontend >=2025.4.1,<2025.4.2.0a0 size: 1902792 timestamp: 1769904438153 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-paddle-frontend-2025.4.1-h1862bb8_1.conda @@ -7282,6 +7850,9 @@ packages: - libprotobuf >=6.31.1,<6.31.2.0a0 - libstdcxx >=14 purls: [] + run_exports: + weak: + - libopenvino-paddle-frontend >=2025.4.1,<2025.4.2.0a0 size: 745483 timestamp: 1769904456844 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-pytorch-frontend-2025.4.1-hecca717_1.conda @@ -7293,6 +7864,9 @@ packages: - libopenvino 2025.4.1 hb56ce9e_1 - libstdcxx >=14 purls: [] + run_exports: + weak: + - libopenvino-pytorch-frontend >=2025.4.1,<2025.4.2.0a0 size: 1266512 timestamp: 1769904473901 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-tensorflow-frontend-2025.4.1-h0767aad_1.conda @@ -7308,6 +7882,9 @@ packages: - libstdcxx >=14 - snappy >=1.2.2,<1.3.0a0 purls: [] + run_exports: + weak: + - libopenvino-tensorflow-frontend >=2025.4.1,<2025.4.2.0a0 size: 1324086 timestamp: 1769904491964 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-tensorflow-lite-frontend-2025.4.1-hecca717_1.conda @@ -7319,6 +7896,9 @@ packages: - libopenvino 2025.4.1 hb56ce9e_1 - libstdcxx >=14 purls: [] + run_exports: + weak: + - libopenvino-tensorflow-lite-frontend >=2025.4.1,<2025.4.2.0a0 size: 496261 timestamp: 1769904509651 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopus-1.6.1-h280c20c_0.conda @@ -7330,6 +7910,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libopus >=1.6.1,<2.0a0 size: 324993 timestamp: 1768497114401 - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_0.conda @@ -7341,6 +7924,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libpciaccess >=0.19,<0.20.0a0 size: 29147 timestamp: 1773533027610 - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda @@ -7352,22 +7938,28 @@ packages: - libzlib >=1.3.2,<2.0a0 license: zlib-acknowledgement purls: [] + run_exports: + weak: + - libpng >=1.6.58,<1.7.0a0 size: 317729 timestamp: 1776315175087 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda - sha256: 076742d4a9fa88711c5fc6726b967e6a03b5060e669aa03288c684a7ae03583b - md5: 2772b7ab7bc43f24e9585a714761a255 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_1.conda + sha256: f7232cb79a31f5a5bcd499aea930b469cde8b96d26db9541022493fd274d2a6e + md5: 6c9103e7ea739a3bb3505da49a4708c1 depends: - __glibc >=2.17,<3.0.a0 - icu >=78.3,<79.0a0 - krb5 >=1.22.2,<1.23.0a0 - libgcc >=14 - openldap >=2.6.13,<2.7.0a0 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 license: PostgreSQL purls: [] - size: 2754709 - timestamp: 1778786234149 + run_exports: + weak: + - libpq >=18.4,<19.0a0 + size: 2709008 + timestamp: 1782580447454 - conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-6.31.1-hfb7daa7_5.conda sha256: b04322e2128684d4043e256f56b74528b0a0a296ba4a81299056ec04655a0580 md5: da31d891434e50d7e7be8adc5832269b @@ -7381,8 +7973,45 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libprotobuf >=6.31.1,<6.31.2.0a0 size: 4204474 timestamp: 1780003940664 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.22.0-hd9031aa_0.conda + sha256: cd11890a2c1f14d0342bfcbd81f97152d61dc71c27c7085efc13705a8f64f7c9 + md5: e2834a423b3967e7b3b1e901c4a5f42f + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libpsl >=0.22.0,<0.23.0a0 + size: 83067 + timestamp: 1782394772411 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libraqm-0.10.5-h6406941_1.conda + sha256: 7c9e562842f193f772ef0ba681f238a2d9e5ef637588b6e46eb30cc6aa1940c8 + md5: fa63517815747363c41b439ff9301db1 + depends: + - __glibc >=2.28,<3.0.a0 + - libgcc >=14 + - libharfbuzz >=14.2.1 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - fribidi >=1.0.16,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libraqm >=0.10.5,<0.11.0a0 + size: 29441 + timestamp: 1782807076031 - conda: https://conda.anaconda.org/conda-forge/linux-64/libraw-0.22.1-h074291d_0.conda sha256: 2d2eb9147efeec20bcc89313fa55d052829b7d23def0e8eed039d374ecaf785e md5: bbb55eb739ed4188e24904cafa939567 @@ -7397,6 +8026,9 @@ packages: - libzlib >=1.3.2,<2.0a0 license: LGPL-2.1-only purls: [] + run_exports: + weak: + - libraw >=0.22.1,<0.23.0a0 size: 752027 timestamp: 1775541726097 - conda: https://conda.anaconda.org/conda-forge/linux-64/librsvg-2.62.3-h4c96295_0.conda @@ -7417,6 +8049,9 @@ packages: - __glibc >=2.17 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - librsvg >=2.62.3,<3.0a0 size: 3476570 timestamp: 1780450632624 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-14.3.0-h8f1669f_19.conda @@ -7429,6 +8064,9 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: + weak: + - libsanitizer 14.3.0 size: 7947790 timestamp: 1778268494844 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda @@ -7440,6 +8078,9 @@ packages: - libstdcxx >=15.2.0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + run_exports: + weak: + - libsanitizer 15.2.0 size: 7930689 timestamp: 1778269054623 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsdformat14-14.8.0-py312h1f51ce1_2.conda @@ -7459,6 +8100,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libsdformat14 >=14.8.0,<15.0a0 size: 1236819 timestamp: 1759339825312 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsndfile-1.2.2-hc60ed4a_1.conda @@ -7476,6 +8120,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - libsndfile >=1.2.2,<1.3.0a0 size: 354372 timestamp: 1695747735668 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.22-h280c20c_1.conda @@ -7486,19 +8133,25 @@ packages: - libgcc >=14 license: ISC purls: [] + run_exports: + weak: + - libsodium >=1.0.22,<1.0.23.0a0 size: 269272 timestamp: 1779163468406 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.2-h0c1763c_0.conda - sha256: 1ab603b6ec93933e76027e1f23b21b22b858ba1b56f1e1695ef6fe5e80cb7358 - md5: 062b0ac602fb0adf250e3dfa86f221c4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda + sha256: 365376f4815e5e80def2b3462a2419708b7c292da0da85278386c2618621fff4 + md5: 4aed8e657e9ff156bdbe849b4df44389 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libzlib >=1.3.2,<2.0a0 license: blessing purls: [] - size: 957849 - timestamp: 1780574429573 + run_exports: + weak: + - libsqlite >=3.53.3,<4.0a0 + size: 962119 + timestamp: 1782519076616 - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda sha256: fa39bfd69228a13e553bd24601332b7cfeb30ca11a3ca50bb028108fe90a7661 md5: eecce068c7e4eddeb169591baac20ac4 @@ -7510,6 +8163,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libssh2 >=1.11.1,<2.0a0 size: 304790 timestamp: 1745608545575 - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda @@ -7523,6 +8179,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 5852044 timestamp: 1778269036376 - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda @@ -7533,6 +8190,9 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: + strong: + - libstdcxx size: 27776 timestamp: 1778269074600 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsystemd0-257.13-hd0affe5_0.conda @@ -7544,6 +8204,7 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: {} size: 492799 timestamp: 1773797095649 - conda: https://conda.anaconda.org/conda-forge/linux-64/libtasn1-4.21.0-hb03c661_0.conda @@ -7554,6 +8215,9 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libtasn1 >=4.21.0,<5.0a0 size: 116738 timestamp: 1768297813301 - conda: https://conda.anaconda.org/conda-forge/linux-64/libtheora-1.1.1-h4ab18f5_1006.conda @@ -7568,6 +8232,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libtheora >=1.1.1,<1.2.0a0 size: 328924 timestamp: 1719667859099 - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda @@ -7586,6 +8253,9 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: HPND purls: [] + run_exports: + weak: + - libtiff >=4.7.1,<4.8.0a0 size: 435273 timestamp: 1762022005702 - conda: https://conda.anaconda.org/conda-forge/linux-64/libtool-2.5.4-h5888daf_0.conda @@ -7598,6 +8268,7 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: {} size: 415044 timestamp: 1740593851157 - conda: https://conda.anaconda.org/conda-forge/linux-64/libudev1-257.13-hd0affe5_0.conda @@ -7609,6 +8280,7 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: {} size: 145087 timestamp: 1773797108513 - conda: https://conda.anaconda.org/conda-forge/linux-64/libunistring-0.9.10-h7f98852_0.tar.bz2 @@ -7618,6 +8290,9 @@ packages: - libgcc-ng >=9.3.0 license: GPL-3.0-only OR LGPL-3.0-only purls: [] + run_exports: + weak: + - libunistring >=0,<1.0a0 size: 1433436 timestamp: 1626955018689 - conda: https://conda.anaconda.org/conda-forge/linux-64/libunwind-1.8.3-h65a8314_0.conda @@ -7630,6 +8305,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libunwind >=1.8.3,<1.9.0a0 size: 75995 timestamp: 1757032240102 - conda: https://conda.anaconda.org/conda-forge/linux-64/liburcu-0.14.0-hac33072_0.conda @@ -7640,6 +8318,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - liburcu >=0.14.0,<0.15.0a0 size: 176874 timestamp: 1718888439831 - conda: https://conda.anaconda.org/conda-forge/linux-64/liburing-2.14-hb700be7_0.conda @@ -7652,6 +8333,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - liburing >=2.14,<2.15.0a0 size: 154203 timestamp: 1770566529700 - conda: https://conda.anaconda.org/conda-forge/linux-64/libusb-1.0.29-h73b1eb8_0.conda @@ -7663,19 +8347,25 @@ packages: - libudev1 >=257.4 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libusb >=1.0.29,<2.0a0 size: 89551 timestamp: 1748856210075 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda - sha256: 3f0edf1280e2f6684a986f821eaa3e123d2694a00b31b96ca0d4a4c12c129231 - md5: 7d0a66598195ef00b6efc55aefc7453b +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda + sha256: 9b1bdce27a7e31f7d241aeecff67a1f3101d52a2b1e33ccc2cdf2613072bf81f + md5: 01bb81d12c957de066ea7362007df642 depends: - - __glibc >=2.17,<3.0.a0 - libgcc >=14 + - __glibc >=2.17,<3.0.a0 license: BSD-3-Clause license_family: BSD purls: [] - size: 40163 - timestamp: 1779118517630 + run_exports: + weak: + - libuuid >=2.42.2,<3.0a0 + size: 40017 + timestamp: 1781625522462 - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_0.conda sha256: e28e4519223f78b3163599ca89c3f2d80bfb53e907e7fc74e806e60d1efa578b md5: 4e33d49bf4fc853855a3b00643aa5484 @@ -7685,29 +8375,35 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 size: 419935 timestamp: 1779396012261 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.23.0-he1eb515_0.conda - sha256: 255c7d00b54e26f19fad9340db080716bced1d8539606e2b8396c57abd40007c - md5: 25813fe38b3e541fc40007592f12bae5 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.24.0-he1eb515_0.conda + sha256: 96b938e39493331d796e0b0b805038b9ee11b0c192b571bbc6c7adc3701724ef + md5: 14f10db75eec75c02e56c858016f787e depends: - __glibc >=2.17,<3.0.a0 - - libdrm >=2.4.125,<2.5.0a0 + - libdrm >=2.4.127,<2.5.0a0 - libegl >=1.7.0,<2.0a0 - libgcc >=14 - libgl >=1.7.0,<2.0a0 - libglx >=1.7.0,<2.0a0 - libxcb >=1.17.0,<2.0a0 - - wayland >=1.24.0,<2.0a0 + - wayland >=1.25.0,<2.0a0 - wayland-protocols - - xorg-libx11 >=1.8.12,<2.0a0 - - xorg-libxext >=1.3.6,<2.0a0 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 - xorg-libxfixes >=6.0.2,<7.0a0 license: MIT license_family: MIT purls: [] - size: 221308 - timestamp: 1765652453244 + run_exports: + weak: + - libva >=2.24.0,<3.0a0 + size: 223532 + timestamp: 1782992630083 - conda: https://conda.anaconda.org/conda-forge/linux-64/libvorbis-1.3.7-h54a6638_2.conda sha256: ca494c99c7e5ecc1b4cd2f72b5584cef3d4ce631d23511184411abcbb90a21a5 md5: b4ecbefe517ed0157c37f8182768271c @@ -7721,6 +8417,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libvorbis >=1.3.7,<1.4.0a0 size: 285894 timestamp: 1753879378005 - conda: https://conda.anaconda.org/conda-forge/linux-64/libvpl-2.15.0-h54a6638_1.conda @@ -7736,6 +8435,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libvpl >=2.15.0,<2.16.0a0 size: 287944 timestamp: 1757278954789 - conda: https://conda.anaconda.org/conda-forge/linux-64/libvpx-1.15.2-hecca717_0.conda @@ -7748,6 +8450,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libvpx >=1.15.2,<1.16.0a0 size: 1070048 timestamp: 1762010217363 - conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.341.0-h5279c79_0.conda @@ -7764,6 +8469,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libvulkan-loader >=1.4.341.0,<2.0a0 size: 199795 timestamp: 1770077125520 - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda @@ -7777,6 +8485,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 size: 429011 timestamp: 1752159441324 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda @@ -7791,6 +8502,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libxcb >=1.17.0,<2.0a0 size: 395888 timestamp: 1727278577118 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda @@ -7800,6 +8514,9 @@ packages: - libgcc-ng >=12 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libxcrypt >=4.4.36 size: 100393 timestamp: 1702724383534 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.13.2-hca5e8e5_0.conda @@ -7817,6 +8534,9 @@ packages: license: MIT/X11 Derivative license_family: MIT purls: [] + run_exports: + weak: + - libxkbcommon >=1.13.2,<2.0a0 size: 851166 timestamp: 1780213397575 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.3-hca6bf5a_0.conda @@ -7834,6 +8554,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 559775 timestamp: 1776376739004 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.3-h49c6c72_0.conda @@ -7850,6 +8571,10 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.3 size: 46810 timestamp: 1776376751152 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda @@ -7863,6 +8588,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libxslt >=1.1.43,<2.0a0 size: 245434 timestamp: 1757963724977 - conda: https://conda.anaconda.org/conda-forge/linux-64/libzenohc-1.7.2-hfad6b34_0.conda @@ -7877,6 +8605,9 @@ packages: - __glibc >=2.17 license: Apache-2.0 OR EPL-2.0 purls: [] + run_exports: + weak: + - libzenohc >=1.7.2,<1.7.3.0a0 size: 4462657 timestamp: 1767984586418 - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda @@ -7891,6 +8622,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libzip >=1.11.2,<2.0a0 size: 109043 timestamp: 1730442108429 - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda @@ -7903,6 +8637,9 @@ packages: license: Zlib license_family: Other purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 size: 63629 timestamp: 1774072609062 - conda: https://conda.anaconda.org/conda-forge/linux-64/lodepng-20220109-h924138e_0.tar.bz2 @@ -7913,6 +8650,9 @@ packages: - libstdcxx-ng >=12 license: Zlib purls: [] + run_exports: + weak: + - lodepng >=20220109,<20220110.0a0 size: 102103 timestamp: 1654538581172 - conda: https://conda.anaconda.org/conda-forge/linux-64/lttng-ust-2.13.9-hf5eda4c_0.conda @@ -7925,6 +8665,9 @@ packages: - liburcu >=0.14.0,<0.15.0a0 license: LGPL-2.1-only purls: [] + run_exports: + weak: + - lttng-ust >=2.13.9,<2.14.0a0 size: 375355 timestamp: 1745310024643 - conda: https://conda.anaconda.org/conda-forge/linux-64/lxml-6.1.1-py312h63ddcf0_0.conda @@ -7942,6 +8685,7 @@ packages: license: BSD-3-Clause and MIT-CMU purls: - pkg:pypi/lxml?source=hash-mapping + run_exports: {} size: 1571628 timestamp: 1779194839109 - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-4.4.5-py312h3d67a73_1.conda @@ -7958,6 +8702,7 @@ packages: license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping + run_exports: {} size: 44154 timestamp: 1765026394687 - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda @@ -7970,6 +8715,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - lz4-c >=1.10.0,<1.11.0a0 size: 167055 timestamp: 1733741040117 - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda @@ -7981,6 +8729,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - lzo >=2.10,<3.0a0 size: 191060 timestamp: 1753889274283 - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda @@ -7992,6 +8743,7 @@ packages: license: GPL-3.0-or-later license_family: GPL purls: [] + run_exports: {} size: 513088 timestamp: 1727801714848 - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda @@ -8008,25 +8760,28 @@ packages: license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping + run_exports: {} size: 26057 timestamp: 1772445297924 -- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.10.9-py312h7900ff3_0.conda - sha256: cdd59bb1a52b09979f11c68909d53120b2e749edd1992853a74e1604db19c8b0 - md5: 579c6a324b197594fabc9240bddf2d8b +- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.11.0-py312h7900ff3_1.conda + sha256: 957dcd182249a30589db706b21992ea023180f8b78feb8410f36c1c6a80f2198 + md5: 9d60112f925c215d541a6a72c9f3418d depends: - - matplotlib-base >=3.10.9,<3.10.10.0a0 + - matplotlib-base >=3.11.0,<3.11.1.0a0 - pyside6 >=6.7.2 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 - tornado >=5 license: PSF-2.0 license_family: PSF - purls: [] - size: 17831 - timestamp: 1777000588302 -- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.10.9-py312he3d6523_0.conda - sha256: c7e133837376e53e6a52719c205a3067c42f05769bc3e8307417f8d817dfc63e - md5: 7d499b5b6d150f133800dc3a582771c7 + purls: + - pkg:pypi/matplotlib?source=compressed-mapping + run_exports: {} + size: 14887 + timestamp: 1782829550796 +- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.11.0-py312hc1765e9_1.conda + sha256: d983b4ea15841f1fde4ccba4370485e89e696a447fcf5e90a1f75c8487699c68 + md5: 1d06d24525cf2e373310c1131acf12f8 depends: - __glibc >=2.17,<3.0.a0 - contourpy >=1.0.1 @@ -8037,9 +8792,10 @@ packages: - libfreetype >=2.14.3 - libfreetype6 >=2.14.3 - libgcc >=14 + - libraqm >=0.10.5,<0.11.0a0 - libstdcxx >=14 - numpy >=1.23 - - numpy >=1.23,<3 + - numpy >=1.25,<3 - packaging >=20.0 - pillow >=8 - pyparsing >=2.3.1 @@ -8051,26 +8807,27 @@ packages: license: PSF-2.0 license_family: PSF purls: - - pkg:pypi/matplotlib?source=hash-mapping - size: 8336056 - timestamp: 1777000573501 -- conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.13.3-py310h2b5ca13_0.conda + - pkg:pypi/matplotlib?source=compressed-mapping + run_exports: {} + size: 8877024 + timestamp: 1782829532714 +- conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.14.1-py310h2b5ca13_0.conda noarch: python - sha256: 091d0f742e4fa9bab01f9b642795a84884ee6bfc6b8aa426e97c7213fa0fda6e - md5: b1e4804b025e3acee6e93f413c551d0c + sha256: 33604a07d4d10f440fcc1e38d7d33462b3726565c1ad704ccfa189c7934912c6 + md5: 532b0a5340d4431bea91efe4792ceb13 depends: - python - tomli >=1.1.0 - __glibc >=2.17,<3.0.a0 - libgcc >=14 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 constrains: - __glibc >=2.17 license: MIT license_family: MIT run_exports: {} - size: 9793377 - timestamp: 1778496710620 + size: 9808111 + timestamp: 1781871513283 - conda: https://conda.anaconda.org/conda-forge/linux-64/mesalib-26.0.3-h8cca3c9_0.conda sha256: 3e6385e04e5a8f62599a5eb72b9a8c65ac143f0621d57f24688f103276d686eb md5: 823e4ae1d60e97845773f7358585fc56 @@ -8091,6 +8848,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - mesalib >=26.0.3,<26.1.0a0 size: 2964576 timestamp: 1773867966762 - conda: https://conda.anaconda.org/conda-forge/linux-64/mpg123-1.32.9-hc50e24c_0.conda @@ -8103,23 +8863,27 @@ packages: license: LGPL-2.1-only license_family: LGPL purls: [] + run_exports: + weak: + - mpg123 >=1.32.9,<1.33.0a0 size: 491140 timestamp: 1730581373280 -- conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py312hd9148b4_1.conda - sha256: 94068fd39d1a672f8799e3146a18ba4ef553f0fcccefddb3c07fbdabfd73667a - md5: 2e489969e38f0b428c39492619b5e6e5 +- conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.2.1-py312h0a2e395_1.conda + sha256: c9764c77dd7f9c581c1d8a24c3024edf777cacfb5a4180de5badc6638dc8590f + md5: a142257c1b69e37cfefc66dc228a4d93 depends: + - python - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - libstdcxx >=14 - - python >=3.12,<3.13.0a0 + - libgcc >=14 - python_abi 3.12.* *_cp312 license: Apache-2.0 - license_family: Apache + license_family: APACHE purls: - - pkg:pypi/msgpack?source=hash-mapping - size: 102525 - timestamp: 1762504116832 + - pkg:pypi/msgpack?source=compressed-mapping + run_exports: {} + size: 112800 + timestamp: 1782460774570 - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-3.6.0-h1eba5cb_0.conda sha256: c08952543aa98f3f8e166912d0e84bd5ccec54d43ab382d9f06b98a995f78969 md5: e6ce1c14d07de1e193710bd60fcd64a9 @@ -8131,6 +8895,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 17818 timestamp: 1773254855824 - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-python-3.6.0-np2py312h2fcff2b_0.conda @@ -8164,6 +8929,7 @@ packages: license_family: APACHE purls: - pkg:pypi/mujoco?source=hash-mapping + run_exports: {} size: 3091314 timestamp: 1773254855824 - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-samples-3.6.0-h3c404ae_0.conda @@ -8179,6 +8945,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 54920 timestamp: 1773254855824 - conda: https://conda.anaconda.org/conda-forge/linux-64/mujoco-simulate-3.6.0-h530d17e_0.conda @@ -8189,6 +8956,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 17682 timestamp: 1773254855824 - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.7.1-py312h8a5da7c_0.conda @@ -8203,6 +8971,7 @@ packages: license_family: APACHE purls: - pkg:pypi/multidict?source=hash-mapping + run_exports: {} size: 100056 timestamp: 1771611023053 - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.20.2-py312h4c3975b_0.conda @@ -8222,6 +8991,7 @@ packages: license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping + run_exports: {} size: 22035539 timestamp: 1776802000447 - conda: https://conda.anaconda.org/conda-forge/linux-64/nanoflann-1.6.1-hff21bea_0.conda @@ -8229,6 +8999,7 @@ packages: md5: acccd21b34ac988d1b26d15c53b28f65 license: BSD purls: [] + run_exports: {} size: 25915 timestamp: 1728332440211 - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda @@ -8239,6 +9010,9 @@ packages: - libgcc >=14 license: X11 AND BSD-3-Clause purls: [] + run_exports: + weak: + - ncurses >=6.6,<7.0a0 size: 918956 timestamp: 1777422145199 - conda: https://conda.anaconda.org/conda-forge/linux-64/nettle-3.10.1-h4a9d5aa_0.conda @@ -8250,6 +9024,9 @@ packages: - gmp >=6.3.0,<7.0a0 license: GPL-2.0-or-later OR LGPL-3.0-or-later purls: [] + run_exports: + weak: + - nettle >=3.10.1,<3.11.0a0 size: 1047686 timestamp: 1748012178395 - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda @@ -8262,6 +9039,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 186323 timestamp: 1763688260928 - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda @@ -8272,6 +9050,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 136216 timestamp: 1758194284857 - conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda @@ -8284,6 +9063,9 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: + weak: + - nspr >=4.38,<5.0a0 size: 228588 timestamp: 1762348634537 - conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda @@ -8299,6 +9081,9 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: + weak: + - nss >=3.118,<4.0a0 size: 2057773 timestamp: 1763485556350 - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda @@ -8318,6 +9103,9 @@ packages: license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping + run_exports: + weak: + - numpy >=1.26.4,<2.0a0 size: 7484186 timestamp: 1707225809722 - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.4-hb03c661_1.conda @@ -8330,6 +9118,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - ocl-icd >=2.3.4,<3.0a0 size: 109598 timestamp: 1780362789611 - conda: https://conda.anaconda.org/conda-forge/linux-64/octomap-1.10.0-h84d6215_0.conda @@ -8342,6 +9133,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - octomap >=1.10.0,<1.11.0a0 size: 234800 timestamp: 1728635293810 - conda: https://conda.anaconda.org/conda-forge/linux-64/onnxruntime-1.26.0-py312hb39aaa6_0_cpu.conda @@ -8360,6 +9154,7 @@ packages: license: MIT AND BSL-1.0 purls: - pkg:pypi/onnxruntime?source=hash-mapping + run_exports: {} size: 15640884 timestamp: 1778967008489 - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-hecca717_0.conda @@ -8372,6 +9167,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 55754 timestamp: 1773844383536 - conda: https://conda.anaconda.org/conda-forge/linux-64/opencv-4.12.0-qt6_py312h7bb6282_612.conda @@ -8385,36 +9181,43 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: {} size: 28422 timestamp: 1766495425558 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openexr-3.4.12-h9f1635d_0.conda - sha256: 9d75e4982065fb8a79b0f908f63d8a884db6d0f44abcecbbdb28eca35b01aa80 - md5: 705c195cdfe5c3b67e6e9b091fe7b602 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openexr-3.4.13-hf734b31_1.conda + sha256: 17e3d2769dfc018748f0c09757b95744a5e942f74325b605d06303a69ee7955d + md5: 9db8aff65eaea058afc9fe93569b4b14 depends: - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - imath >=3.2.2,<3.2.3.0a0 - - openjph >=0.27.3,<0.28.0a0 - - libzlib >=1.3.2,<2.0a0 + - openjph >=0.30.1,<0.31.0a0 - libdeflate >=1.25,<1.26.0a0 + - libzlib >=1.3.2,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] - size: 1220558 - timestamp: 1779680416588 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda - sha256: 3f231f2747a37a58471c82a9a8a80d92b7fece9f3fce10901a5ac888ce00b747 - md5: b28cf020fd2dead0ca6d113608683842 + run_exports: + weak: + - openexr >=3.4.13,<3.5.0a0 + size: 1223929 + timestamp: 1782198396418 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-h65dd3cf_1.conda + sha256: 5317c5c23762f3fe1c8510565a2bb94c645e1470ff73b386315656404f7eb58a + md5: 69894a95220a17a66272daa701c387bc depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - - libstdcxx >=13 + - libgcc >=14 + - libstdcxx >=14 license: BSD-2-Clause license_family: BSD purls: [] - size: 731471 - timestamp: 1739400677213 + run_exports: + weak: + - openh264 >=2.6.0,<2.6.1.0a0 + size: 726478 + timestamp: 1782685945856 - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda sha256: 3900f9f2dbbf4129cf3ad6acf4e4b6f7101390b53843591c53b00f034343bc4d md5: 11b3379b191f63139e29c0d19dee24cd @@ -8428,21 +9231,27 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - openjpeg >=2.5.4,<3.0a0 size: 355400 timestamp: 1758489294972 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openjph-0.27.4-h8d634f6_0.conda - sha256: b4be74b706500c2f9471135b9a59a0d4325b999d992acf69ad0c598cfc5f9938 - md5: 6fb2763a192402111e655f420f1d88d7 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjph-0.30.1-h8d634f6_0.conda + sha256: e405a62cc16604c4274d1d64387fa62ba5466cc65fa087ae45451d0150f4b698 + md5: 6143d4af035262f7e1b954e1cba9156d depends: + - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - libtiff >=4.7.1,<4.8.0a0 license: BSD-2-Clause license_family: BSD purls: [] - size: 283312 - timestamp: 1780596792557 + run_exports: + weak: + - openjph >=0.30.1,<0.31.0a0 + size: 294315 + timestamp: 1782091151122 - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.13-hbde042b_0.conda sha256: 21c4f6c7f41dc9bec2ea2f9c80440d9a4d45a6f2ac13243e658f10dcf1044146 md5: 680608784722880fbfe1745067570b00 @@ -8456,11 +9265,14 @@ packages: license: OLDAP-2.8 license_family: BSD purls: [] + run_exports: + weak: + - openldap >=2.6.13,<2.7.0a0 size: 786149 timestamp: 1775741359582 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda - sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb - md5: da1b85b6a87e141f5140bb9924cecab0 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_0.conda + sha256: d48f5c22b9897c01e4dff3680f1f57ceb02711ab9c62f74339b080419dfad34b + md5: 79dd2074b5cd5c5c6b2930514a11e22d depends: - __glibc >=2.17,<3.0.a0 - ca-certificates @@ -8468,8 +9280,11 @@ packages: license: Apache-2.0 license_family: Apache purls: [] - size: 3167099 - timestamp: 1775587756857 + run_exports: + weak: + - openssl >=3.6.3,<4.0a0 + size: 3159683 + timestamp: 1781069855778 - conda: https://conda.anaconda.org/conda-forge/linux-64/orocos-kdl-1.5.3-hca8cc02_1.conda sha256: 9d524a5589594054a3f38c350c2b2874d12b2b84096335daca75149d2cb9b49a md5: a720fc27e7526d04473f4fb486a287ee @@ -8482,6 +9297,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - orocos-kdl >=1.5.3,<1.6.0a0 size: 387285 timestamp: 1778003898254 - conda: https://conda.anaconda.org/conda-forge/linux-64/p11-kit-0.26.2-h3435931_0.conda @@ -8495,6 +9313,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - p11-kit >=0.26.2,<0.27.0a0 size: 3831848 timestamp: 1770417713801 - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hda50119_1.conda @@ -8516,6 +9337,9 @@ packages: - libzlib >=1.3.2,<2.0a0 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - pango >=1.56.4,<2.0a0 size: 458036 timestamp: 1774281947855 - conda: https://conda.anaconda.org/conda-forge/linux-64/pcl-1.15.1-h717c489_7.conda @@ -8542,6 +9366,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - pcl >=1.15.1,<1.15.2.0a0 size: 17927710 timestamp: 1772142286027 - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre-8.45-h9c3ff4c_0.tar.bz2 @@ -8553,6 +9380,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - pcre >=8.45,<9.0a0 size: 259377 timestamp: 1623788789327 - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda @@ -8566,6 +9396,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 size: 1222481 timestamp: 1763655398280 - conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda @@ -8577,6 +9410,11 @@ packages: - libxcrypt >=4.4.36 license: GPL-1.0-or-later OR Artistic-1.0-Perl purls: [] + run_exports: + weak: + - perl >=5.32.1,<5.33.0a0 *_perl5 + noarch: + - perl >=5.32.1,<6.0a0 *_perl5 size: 13344463 timestamp: 1703310653947 - conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-11.3.0-py312h7b42cdd_3.conda @@ -8600,6 +9438,7 @@ packages: license: HPND purls: - pkg:pypi/pillow?source=hash-mapping + run_exports: {} size: 1028547 timestamp: 1758208668856 - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda @@ -8613,6 +9452,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 size: 450960 timestamp: 1754665235234 - conda: https://conda.anaconda.org/conda-forge/linux-64/pkg-config-0.29.2-h4bc722e_1009.conda @@ -8624,6 +9466,7 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: {} size: 115175 timestamp: 1720805894943 - conda: https://conda.anaconda.org/conda-forge/linux-64/popt-1.19-h3b78370_0.conda @@ -8636,6 +9479,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - popt >=1.19,<2.0a0 size: 177450 timestamp: 1765445075774 - conda: https://conda.anaconda.org/conda-forge/linux-64/portaudio-19.7.0-hf4617a5_0.conda @@ -8649,6 +9495,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - portaudio >=19.7.0,<19.8.0a0 size: 77342 timestamp: 1730364040048 - conda: https://conda.anaconda.org/conda-forge/linux-64/proj-9.7.1-he0df7b0_3.conda @@ -8669,6 +9518,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - proj >=9.7.1,<9.8.0a0 size: 3593669 timestamp: 1770890751115 - conda: https://conda.anaconda.org/conda-forge/linux-64/propcache-0.5.2-py312h8a5da7c_0.conda @@ -8683,6 +9535,7 @@ packages: license_family: APACHE purls: - pkg:pypi/propcache?source=compressed-mapping + run_exports: {} size: 51586 timestamp: 1780037816755 - conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.31.1-py312hb8af0ac_2.conda @@ -8703,6 +9556,7 @@ packages: license_family: BSD purls: - pkg:pypi/protobuf?source=hash-mapping + run_exports: {} size: 479025 timestamp: 1760393393854 - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda @@ -8717,6 +9571,7 @@ packages: license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping + run_exports: {} size: 225545 timestamp: 1769678155334 - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda @@ -8728,6 +9583,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 8252 timestamp: 1726802366959 - conda: https://conda.anaconda.org/conda-forge/linux-64/pugixml-1.15-h3f63f65_0.conda @@ -8740,6 +9596,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - pugixml >=1.15,<1.16.0a0 size: 118488 timestamp: 1736601364156 - conda: https://conda.anaconda.org/conda-forge/linux-64/pulseaudio-17.0-haebf07f_3.conda @@ -8753,6 +9612,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - pulseaudio-client >=17.0,<17.1.0a0 size: 18408 timestamp: 1763148313744 - conda: https://conda.anaconda.org/conda-forge/linux-64/pulseaudio-client-17.0-h9a6aba3_3.conda @@ -8772,6 +9634,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - pulseaudio-client >=17.0,<17.1.0a0 size: 750785 timestamp: 1763148198088 - conda: https://conda.anaconda.org/conda-forge/linux-64/pulseaudio-daemon-17.0-h33dcb6b_3.conda @@ -8804,6 +9669,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - pulseaudio-daemon >=17.0,<17.1.0a0 size: 876199 timestamp: 1763148300906 - conda: https://conda.anaconda.org/conda-forge/linux-64/py-opencv-4.12.0-qt6_py312h598be00_612.conda @@ -8818,6 +9686,9 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - py-opencv >=4.12.0,<5.0a0 size: 1154634 timestamp: 1766495407579 - conda: https://conda.anaconda.org/conda-forge/linux-64/pybullet-3.25-py312hf49885f_5.conda @@ -8835,6 +9706,7 @@ packages: license: Zlib purls: - pkg:pypi/pybullet?source=hash-mapping + run_exports: {} size: 62838622 timestamp: 1761041325516 - conda: https://conda.anaconda.org/conda-forge/linux-64/pycairo-1.29.0-py312h2596900_1.conda @@ -8851,6 +9723,7 @@ packages: license: LGPL-2.1-only OR MPL-1.1 purls: - pkg:pypi/pycairo?source=hash-mapping + run_exports: {} size: 119839 timestamp: 1770726341594 - conda: https://conda.anaconda.org/conda-forge/linux-64/pymongo-4.17.0-py312h1289d80_0.conda @@ -8867,6 +9740,7 @@ packages: license_family: APACHE purls: - pkg:pypi/pymongo?source=hash-mapping + run_exports: {} size: 2400390 timestamp: 1776765918970 - conda: https://conda.anaconda.org/conda-forge/linux-64/pynacl-1.6.2-py312hf34ed73_2.conda @@ -8884,6 +9758,7 @@ packages: license_family: Apache purls: - pkg:pypi/pynacl?source=hash-mapping + run_exports: {} size: 1180950 timestamp: 1778984876791 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyqt-5.15.11-py312h82c0db2_2.conda @@ -8917,6 +9792,9 @@ packages: license_family: GPL purls: - pkg:pypi/pyqt5?source=hash-mapping + run_exports: + weak: + - pyqt >=5.15.11,<5.16.0a0 size: 5282965 timestamp: 1759498005783 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyqt5-sip-12.17.0-py312h1289d80_2.conda @@ -8935,6 +9813,7 @@ packages: license_family: GPL purls: - pkg:pypi/pyqt5-sip?source=hash-mapping + run_exports: {} size: 85800 timestamp: 1759495565076 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyside6-6.10.2-py312h50ac2ff_3.conda @@ -8961,6 +9840,7 @@ packages: purls: - pkg:pypi/pyside6?source=hash-mapping - pkg:pypi/shiboken6?source=hash-mapping + run_exports: {} size: 13398482 timestamp: 1778394766609 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.1-hab00c5b_1_cpython.conda @@ -8988,6 +9868,11 @@ packages: - python_abi 3.12.* *_cp312 license: Python-2.0 purls: [] + run_exports: + weak: + - python_abi 3.12.* *_cp312 + noarch: + - python size: 32286118 timestamp: 1703320043028 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda @@ -9021,9 +9906,9 @@ packages: - python size: 31608571 timestamp: 1772730708989 -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.11.0-py312h5253ce2_0.conda - sha256: 6aa36a62db36c2aa144640a3fba1cd3c61dd679a979288eae2fd3b9f89ef4eac - md5: 0a73899771633857390eac009995e5f9 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.12.0-py312h5253ce2_0.conda + sha256: 77a0592d53fe3664421926c32677f2829278de19d99c90ada80cd75286f34198 + md5: 8ead1974106b7526f4866326654b99ff depends: - python - libgcc >=14 @@ -9032,9 +9917,10 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/librt?source=hash-mapping - size: 157857 - timestamp: 1778511616936 + - pkg:pypi/librt?source=compressed-mapping + run_exports: {} + size: 160728 + timestamp: 1782847498143 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-orocos-kdl-1.5.3-py312h1289d80_2.conda sha256: 481d724d6f7bbfa931f6f33a7940d3637b7289139526a5952d2289c114c5f5b6 md5: 30d805f6312812a6abef0933e56deefa @@ -9050,6 +9936,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - python-orocos-kdl >=1.5.3,<1.6.0a0 size: 356677 timestamp: 1778045760532 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda @@ -9065,6 +9954,7 @@ packages: license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping + run_exports: {} size: 198293 timestamp: 1770223620706 - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda @@ -9076,6 +9966,9 @@ packages: - libstdcxx-ng >=12 license: LicenseRef-Qhull purls: [] + run_exports: + weak: + - qhull >=2020.2,<2020.3.0a0 size: 552937 timestamp: 1720813982144 - conda: https://conda.anaconda.org/conda-forge/linux-64/qt-main-5.15.15-h0c412b5_8.conda @@ -9136,6 +10029,9 @@ packages: license: LGPL-3.0-only license_family: LGPL purls: [] + run_exports: + weak: + - qt-main >=5.15.15,<5.16.0a0 size: 52674357 timestamp: 1773957808615 - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.10.2-pl5321h16c4a6b_6.conda @@ -9210,6 +10106,9 @@ packages: license: LGPL-3.0-only license_family: LGPL purls: [] + run_exports: + weak: + - qt6-main >=6.10.2,<6.11.0a0 size: 58118322 timestamp: 1773865930316 - conda: https://conda.anaconda.org/conda-forge/linux-64/rapidjson-1.1.0.post20240409-h3f2d84a_2.conda @@ -9223,6 +10122,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 156074 timestamp: 1742820732296 - conda: https://conda.anaconda.org/conda-forge/linux-64/rav1e-0.8.1-h1fbca29_0.conda @@ -9236,11 +10136,14 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - rav1e >=0.8.1,<0.9.0a0 size: 5595970 timestamp: 1772540833621 -- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py312h4c3975b_0.conda - sha256: 2d1d20f24cd3274c91ce62215fd86b28c24c33a9381699b00fd95cffe11c1dc4 - md5: 0cee21f9702469ebdd93b4ddc4a2dc3f +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.6.28-py312h4c3975b_0.conda + sha256: 75d6b6a85799e9e27ee133aa76538ab989f74f89b483da1fe7f1100dfb843e64 + md5: 6a5e4e0d9e5e03621aa2fdf44244db66 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -9250,8 +10153,9 @@ packages: license_family: PSF purls: - pkg:pypi/regex?source=hash-mapping - size: 411061 - timestamp: 1778374143589 + run_exports: {} + size: 413783 + timestamp: 1782695404925 - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda sha256: d5c73079c1dd2c2a313c3bfd81c73dbd066b7eb08d213778c8bff520091ae894 md5: c1c9b02933fdb2cfb791d936c20e887e @@ -9261,26 +10165,30 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - rhash >=1.4.6,<2.0a0 size: 193775 timestamp: 1748644872902 -- conda: https://conda.anaconda.org/conda-forge/linux-64/rsync-3.4.3-h5440a77_0.conda - sha256: 56ac324d6b3552ba9760fc9aa1837e9d39a58cedf135b388d15bb2ad8fe9c033 - md5: 633f4f07bd367f4b66d037c8dcc64b1a +- conda: https://conda.anaconda.org/conda-forge/linux-64/rsync-3.4.4-h5440a77_0.conda + sha256: 0f8b7721bd3c3ccbe88c71211f89783396a1333144963f23105242e808ecd8af + md5: 1f296293c526b4524c374345cf3358f5 depends: - - __glibc >=2.28,<3.0.a0 - libgcc >=14 + - __glibc >=2.28,<3.0.a0 - lz4-c >=1.10.0,<1.11.0a0 - - popt >=1.16,<2.0a0 + - libiconv >=1.18,<2.0a0 + - xxhash >=0.8.3,<0.8.4.0a0 - openssl >=3.5.6,<4.0a0 - - libzlib >=1.3.2,<2.0a0 - zstd >=1.5.7,<1.6.0a0 - - xxhash >=0.8.3,<0.8.4.0a0 - - libiconv >=1.18,<2.0a0 + - popt >=1.16,<2.0a0 + - libzlib >=1.3.2,<2.0a0 license: GPL-3.0-only license_family: GPL purls: [] - size: 375675 - timestamp: 1779304187298 + run_exports: {} + size: 376631 + timestamp: 1780999334789 - conda: https://conda.anaconda.org/conda-forge/linux-64/ruby-4.0.5-h95e6935_0.conda sha256: e39acd0057c89c0cb00cbb8d17b54a5537262d79cdd812c03267ce3f8c0528d3 md5: 7272b40e30d96d6ca49b25b8d4f56368 @@ -9300,6 +10208,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - ruby >=4.0.5,<4.1.0a0 size: 17204486 timestamp: 1779257270967 - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.14.14-h40fa522_1.conda @@ -9316,6 +10227,7 @@ packages: license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping + run_exports: {} size: 9131490 timestamp: 1769520999080 - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.91.1-h53717f1_0.conda @@ -9335,35 +10247,38 @@ packages: - __glibc >=2.17 size: 232940165 timestamp: 1762816703243 -- conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.95.0-h53717f1_1.conda - sha256: 0f7965acec00e5b35d7b4748ea0da57249ab3db2177d13eb87909c0a142148b5 - md5: 26172b61a3f03c31e56065413ffc1f2f +- conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.96.0-h53717f1_0.conda + sha256: d084a53a1ce2cea8d6f9cf45108e516a629118dd3f8fb3113d87d1dcd3eea669 + md5: 5b80270d422d9fddf028cb4ce68370b2 depends: - __glibc >=2.17,<3.0.a0 - gcc_impl_linux-64 - libgcc >=14 - libzlib >=1.3.2,<2.0a0 - - rust-std-x86_64-unknown-linux-gnu 1.95.0 h2c6d0dc_1 + - rust-std-x86_64-unknown-linux-gnu 1.96.0 h2c6d0dc_0 - sysroot_linux-64 >=2.17 license: MIT license_family: MIT - size: 182907915 - timestamp: 1777536012536 -- conda: https://conda.anaconda.org/conda-forge/linux-64/rust_linux-64-1.95.0-hb4ea61c_2.conda - sha256: f0e7e6b6dbec4ff4ef3c9c080a82f52af08c4983b568af0433f217be1045a6fe - md5: 371cfdd3ecb3fd19343bf7f21101da48 + run_exports: + strong_constrains: + - __glibc >=2.17 + size: 171986391 + timestamp: 1780046427552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rust_linux-64-1.96.0-hd58cd63_0.conda + sha256: 5658a122375e3733c53cb9fbd107626f623b5931b0905fc5f72d36ee83fe37f8 + md5: 4172c3ed0c0c8aa610b7d279dc699046 depends: - gcc_linux-64 - - rust 1.95.0.* - - rust-std-x86_64-unknown-linux-gnu 1.95.0.* + - rust 1.96.0.* + - rust-std-x86_64-unknown-linux-gnu 1.96.0.* - sysroot_linux-64 >=2.17 license: BSD-3-Clause license_family: BSD run_exports: strong_constrains: - __glibc >=2.17 - size: 11761 - timestamp: 1780066916977 + size: 11780 + timestamp: 1780932798351 - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_1.conda sha256: d5ac05ad45c0d48731eb189c2cbb2bb99f0e3cb7e1acaad373cb2f1f2597fc75 md5: 15995ecb2ef890778ba9a3750190f09d @@ -9385,6 +10300,7 @@ packages: license_family: BSD purls: - pkg:pypi/scipy?source=hash-mapping + run_exports: {} size: 16828243 timestamp: 1779874781187 - conda: https://conda.anaconda.org/conda-forge/linux-64/sdformat14-14.8.0-h5bb51b8_2.conda @@ -9396,6 +10312,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libsdformat14 >=14.8.0,<15.0a0 size: 14078 timestamp: 1759339825312 - conda: https://conda.anaconda.org/conda-forge/linux-64/sdformat14-python-14.8.0-py312h22a3d64_2.conda @@ -9416,6 +10335,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 680439 timestamp: 1759339825312 - conda: https://conda.anaconda.org/conda-forge/linux-64/sdl2-2.32.56-h54a6638_0.conda @@ -9430,38 +10350,44 @@ packages: - libegl >=1.7.0,<2.0a0 license: Zlib purls: [] + run_exports: + weak: + - sdl2 >=2.32.56,<3.0a0 size: 589145 timestamp: 1757842881000 -- conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.4.10-hdeec2a5_0.conda - sha256: 04fa7dab2b8f688e3fc4b7ae4522fd3935fb0601e3329cda8b40d63c60d6cc05 - md5: 845c0b154836c034f361668bec2a4f20 +- conda: https://conda.anaconda.org/conda-forge/linux-64/sdl3-3.4.12-hdeec2a5_0.conda + sha256: 2607340a7adbf7b7ec902892bce00c9fd35ccdb7f1e8d4ef1efd51641ad36a3c + md5: 1c36b749acf532314ad381f6c1663647 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - libstdcxx >=14 - - xorg-libxcursor >=1.2.3,<2.0a0 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - liburing >=2.14,<2.15.0a0 + - xorg-libxfixes >=6.0.2,<7.0a0 - libusb >=1.0.29,<2.0a0 - - libxkbcommon >=1.13.2,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 - xorg-libx11 >=1.8.13,<2.0a0 - - xorg-libxi >=1.8.3,<2.0a0 - - liburing >=2.14,<2.15.0a0 - - libunwind >=1.8.3,<1.9.0a0 - - xorg-libxtst >=1.2.5,<2.0a0 - - wayland >=1.25.0,<2.0a0 - - dbus >=1.16.2,<2.0a0 - libgl >=1.7.0,<2.0a0 - - xorg-libxscrnsaver >=1.2.4,<2.0a0 - - xorg-libxext >=1.3.7,<2.0a0 + - dbus >=1.16.2,<2.0a0 - libdrm >=2.4.127,<2.5.0a0 - pulseaudio-client >=17.0,<17.1.0a0 - - libvulkan-loader >=1.4.341.0,<2.0a0 + - xorg-libxi >=1.8.3,<2.0a0 + - wayland >=1.25.0,<2.0a0 - libegl >=1.7.0,<2.0a0 - - xorg-libxfixes >=6.0.2,<7.0a0 + - libxkbcommon >=1.13.2,<2.0a0 - libudev1 >=257.13 + - libunwind >=1.8.3,<1.9.0a0 + - xorg-libxscrnsaver >=1.2.4,<2.0a0 + - libvulkan-loader >=1.4.341.0,<2.0a0 + - xorg-libxcursor >=1.2.3,<2.0a0 + - xorg-libxtst >=1.2.5,<2.0a0 license: Zlib purls: [] - size: 2148830 - timestamp: 1780262823658 + run_exports: + weak: + - sdl3 >=3.4.12,<4.0a0 + size: 2156114 + timestamp: 1782948044627 - conda: https://conda.anaconda.org/conda-forge/linux-64/shaderc-2025.5-h718be3e_1.conda sha256: 0c2d6f24ee2b614ee1da4d7d99cc9944ea1ace65455a47d48d8c1f726317168a md5: 8dc8dda113c4c568256bdd486b6e842e @@ -9474,6 +10400,9 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - shaderc >=2025.5,<2025.6.0a0 size: 113513 timestamp: 1770208767759 - conda: https://conda.anaconda.org/conda-forge/linux-64/sip-6.10.0-py312h1289d80_1.conda @@ -9493,6 +10422,9 @@ packages: license_family: BSD purls: - pkg:pypi/sip?source=hash-mapping + run_exports: + weak: + - sip >=6.10.0,<6.11.0a0 size: 680892 timestamp: 1759437964748 - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda @@ -9506,6 +10438,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - snappy >=1.2.2,<1.3.0a0 size: 45829 timestamp: 1762948049098 - conda: https://conda.anaconda.org/conda-forge/linux-64/soxr-0.1.3-h0b41bf4_3.conda @@ -9516,6 +10451,9 @@ packages: - libgcc-ng >=12 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - soxr >=0.1.3,<0.1.4.0a0 size: 131370 timestamp: 1674059502792 - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda @@ -9529,6 +10467,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - spdlog >=1.17.0,<1.18.0a0 size: 196681 timestamp: 1767781665629 - conda: https://conda.anaconda.org/conda-forge/linux-64/spirv-tools-2026.2-hb700be7_0.conda @@ -9543,22 +10484,28 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - spirv-tools >=2026,<2027.0a0 size: 2392190 timestamp: 1780139567779 -- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.2-hbc0de68_0.conda - sha256: b7c3217b437f8aa531b4a18c89dc137b6066757f1e93146dc0d8d999ef55da09 - md5: 38d9bf35a4cc83094a327811e548b660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.3-hbc0de68_0.conda + sha256: ef17725138fa72aa5a0f8ccace9727831c4b333e39575f78fb5ad1755826b687 + md5: b345ea7f13e4cae9809c69b1d1af2c99 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - - libsqlite 3.53.2 h0c1763c_0 + - libsqlite 3.53.3 h0c1763c_0 - libzlib >=1.3.2,<2.0a0 - ncurses >=6.6,<7.0a0 - readline >=8.3,<9.0a0 license: blessing purls: [] - size: 205545 - timestamp: 1780574435288 + run_exports: + weak: + - libsqlite >=3.53.3,<4.0a0 + size: 206481 + timestamp: 1782519082269 - conda: https://conda.anaconda.org/conda-forge/linux-64/svt-av1-4.0.1-hecca717_0.conda sha256: 4a1d2005153b9454fc21c9bad1b539df189905be49e851ec62a6212c2e045381 md5: 2a2170a3e5c9a354d09e4be718c43235 @@ -9569,6 +10516,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - svt-av1 >=4.0.1,<4.0.2.0a0 size: 2619743 timestamp: 1769664536467 - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2023.0.0-hab88423_2.conda @@ -9582,6 +10532,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 182331 timestamp: 1778673758649 - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-devel-2023.0.0-hab88423_2.conda @@ -9593,6 +10544,9 @@ packages: - libstdcxx >=14 - tbb 2023.0.0 hab88423_2 purls: [] + run_exports: + weak: + - tbb >=2023.0.0 size: 1139342 timestamp: 1778673771784 - conda: https://conda.anaconda.org/conda-forge/linux-64/tinyxml2-11.0.0-h3f2d84a_0.conda @@ -9605,6 +10559,9 @@ packages: - libgcc >=13 license: Zlib purls: [] + run_exports: + weak: + - tinyxml2 >=11.0.0,<11.1.0a0 size: 131351 timestamp: 1742246125630 - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda @@ -9619,11 +10576,14 @@ packages: license: TCL license_family: BSD purls: [] + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 size: 3301196 timestamp: 1769460227866 -- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.6-py312h4c3975b_0.conda - sha256: 1a5f2eee536c5ea97dd9674b1b883d8d676ee346f10c8d4ae30626e20aa6d289 - md5: dcbe46475eff6fb9d1adad473c984f39 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.7-py312h4c3975b_0.conda + sha256: f54504d6eeef133ddc2b964b6a021f3faf085bb08bd70debc07f56d6b9b726f1 + md5: 55f526c3fb5302a1ce922612348442e1 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -9632,9 +10592,10 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=hash-mapping - size: 860785 - timestamp: 1779915943143 + - pkg:pypi/tornado?source=compressed-mapping + run_exports: {} + size: 864705 + timestamp: 1781006801632 - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py312hd9148b4_0.conda sha256: c975070ac28fe23a5bbb2b8aeca5976b06630eb2de2dc149782f74018bf07ae8 md5: 55fd03988b1b1bc6faabbfb5b481ecd7 @@ -9649,6 +10610,7 @@ packages: license_family: MIT purls: - pkg:pypi/ukkonen?source=hash-mapping + run_exports: {} size: 14882 timestamp: 1769438717830 - conda: https://conda.anaconda.org/conda-forge/linux-64/uncrustify-0.83.0-h54a6638_0.conda @@ -9661,6 +10623,7 @@ packages: license: GPL-2.0-only license_family: GPL purls: [] + run_exports: {} size: 748418 timestamp: 1779015692186 - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda @@ -9675,6 +10638,7 @@ packages: license_family: Apache purls: - pkg:pypi/unicodedata2?source=hash-mapping + run_exports: {} size: 410641 timestamp: 1770909099497 - conda: https://conda.anaconda.org/conda-forge/linux-64/urdfdom-4.0.1-h8631160_4.conda @@ -9690,6 +10654,10 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - urdfdom_headers >=1.1.2,<2.0a0 + - urdfdom >=4.0.1,<4.1.0a0 size: 119237 timestamp: 1771238079259 - conda: https://conda.anaconda.org/conda-forge/linux-64/urdfdom-py-1.2.1-py312h200335b_6.conda @@ -9704,6 +10672,7 @@ packages: license_family: BSD purls: - pkg:pypi/urdfdom-py?source=hash-mapping + run_exports: {} size: 48834 timestamp: 1756847352648 - conda: https://conda.anaconda.org/conda-forge/linux-64/urdfdom_headers-1.1.2-h84d6215_0.conda @@ -9716,6 +10685,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 19201 timestamp: 1726152409175 - conda: https://conda.anaconda.org/conda-forge/linux-64/utfcpp-4.09-ha770c72_0.conda @@ -9723,11 +10693,12 @@ packages: md5: 99884244028fe76046e3914f90d4ad05 license: BSL-1.0 purls: [] + run_exports: {} size: 14226 timestamp: 1767012219987 -- conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.19-h26efc2c_0.conda - sha256: 29bbedc6b59436d89ac91f6b0fafc73de1ef4c31b77063590c6ced61b3ce0e58 - md5: 1109c2afdae2f3d06b40ab73f82d9b6f +- conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.26-h26efc2c_0.conda + sha256: fc2567e4507d436c247e0d175991c5929011a3141f4a0fabff515ce6328bb3a0 + md5: f34a1bce60a945c8dac9784ebb495d62 depends: - libgcc >=14 - libstdcxx >=14 @@ -9736,8 +10707,8 @@ packages: - __glibc >=2.17 license: Apache-2.0 OR MIT run_exports: {} - size: 19491066 - timestamp: 1780539158388 + size: 20530051 + timestamp: 1782834625037 - conda: https://conda.anaconda.org/conda-forge/linux-64/viskores-1.1.1-cpu_hc82bd48_0.conda sha256: 2ebe8d6ae8c302ca5bf4aec532cd75ebfb00240db1c14dad9a91bace65aa083d md5: 24676eb7fd23ea3d8d69417f5f1224e0 @@ -9755,6 +10726,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - viskores >=1.1.1,<1.2.0a0 size: 25058279 timestamp: 1777494673829 - conda: https://conda.anaconda.org/conda-forge/linux-64/vtk-9.5.2-py312h244374b_7.conda @@ -9774,6 +10748,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - vtk-base >=9.5.2,<9.5.3.0a0 size: 25585 timestamp: 1768718074243 - conda: https://conda.anaconda.org/conda-forge/linux-64/vtk-base-9.5.2-py312h6fba518_7.conda @@ -9829,6 +10806,9 @@ packages: license_family: BSD purls: - pkg:pypi/vtk?source=hash-mapping + run_exports: + weak: + - vtk-base >=9.5.2,<9.5.3.0a0 size: 68877621 timestamp: 1768718074241 - conda: https://conda.anaconda.org/conda-forge/linux-64/vtk-io-ffmpeg-9.5.2-py312hcdbd8b1_7.conda @@ -9842,6 +10822,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - vtk-io-ffmpeg >=9.5.2,<9.5.3.0a0 size: 108379 timestamp: 1768718074243 - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.25.0-hd6090a7_0.conda @@ -9856,11 +10839,14 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - wayland >=1.25.0,<2.0a0 size: 334139 timestamp: 1773959575393 -- conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.2.1-py312h4c3975b_0.conda - sha256: 3d36b297c5f0c1ab0e598760f0033377334a3bfb5c12f4129c2abcb884e2d632 - md5: a4d41bb00f252b99b4b903b3a8fa3ecc +- conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.2.2-py312h4c3975b_0.conda + sha256: 64ae5393d36cc553bcf05d3afbb42aef28b3d1fa986ed5c9358cd32d785940b7 + md5: 8555a1457e54a2b96093140db1b4b28b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -9869,9 +10855,10 @@ packages: license: BSD-2-Clause license_family: BSD purls: - - pkg:pypi/wrapt?source=hash-mapping - size: 114800 - timestamp: 1779477451511 + - pkg:pypi/wrapt?source=compressed-mapping + run_exports: {} + size: 115842 + timestamp: 1782133640094 - conda: https://conda.anaconda.org/conda-forge/linux-64/x264-1!164.3095-h166bdaf_2.tar.bz2 sha256: 175315eb3d6ea1f64a6ce470be00fa2ee59980108f246d3072ab8b977cb048a5 md5: 6c99772d483f566d59e25037fea2c4b1 @@ -9880,6 +10867,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - x264 >=1!164.3095,<1!165 size: 897548 timestamp: 1660323080555 - conda: https://conda.anaconda.org/conda-forge/linux-64/x265-3.5-h924138e_3.tar.bz2 @@ -9891,6 +10881,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - x265 >=3.5,<3.6.0a0 size: 3357188 timestamp: 1646609687141 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda @@ -9903,6 +10896,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util >=0.4.1,<0.5.0a0 size: 20772 timestamp: 1750436796633 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-cursor-0.1.6-hb03c661_0.conda @@ -9918,6 +10914,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-cursor >=0.1.6,<0.2.0a0 size: 20829 timestamp: 1763366954390 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-image-0.4.0-hb711507_2.conda @@ -9930,6 +10929,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-image >=0.4.0,<0.5.0a0 size: 24551 timestamp: 1718880534789 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-keysyms-0.4.1-hb711507_0.conda @@ -9941,6 +10943,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-keysyms >=0.4.1,<0.5.0a0 size: 14314 timestamp: 1718846569232 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-renderutil-0.3.10-hb711507_0.conda @@ -9952,6 +10957,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-renderutil >=0.3.10,<0.4.0a0 size: 16978 timestamp: 1718848865819 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-wm-0.4.2-hb711507_0.conda @@ -9963,20 +10971,24 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-wm >=0.4.2,<0.5.0a0 size: 51689 timestamp: 1718844051451 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.47-hb03c661_0.conda - sha256: 19c2bb14bec84b0e995b56b752369775c75f1589314b43733948bb5f471a6915 - md5: b56e0c8432b56decafae7e78c5f29ba5 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.48-h280c20c_0.conda + sha256: 3b04afd5d1a65d2d27ac2d49a63b01ab8bcd875776779ec63e337370ed38afdc + md5: b233b41be0bf210989d57160ed39b394 depends: - - __glibc >=2.17,<3.0.a0 - libgcc >=14 + - __glibc >=2.17,<3.0.a0 - xorg-libx11 >=1.8.13,<2.0a0 license: MIT license_family: MIT purls: [] - size: 399291 - timestamp: 1772021302485 + run_exports: {} + size: 441670 + timestamp: 1782027360439 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b md5: fb901ff28063514abb6046c9ec2c4a45 @@ -9986,6 +10998,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libice >=1.1.2,<2.0a0 size: 58628 timestamp: 1734227592886 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda @@ -9999,6 +11014,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libsm >=1.2.6,<2.0a0 size: 27590 timestamp: 1741896361728 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda @@ -10011,6 +11029,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libx11 >=1.8.13,<2.0a0 size: 839652 timestamp: 1770819209719 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda @@ -10022,6 +11043,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxau >=1.0.12,<2.0a0 size: 15321 timestamp: 1762976464266 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxaw-1.0.16-hb9d3cd8_0.conda @@ -10038,6 +11062,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 307032 timestamp: 1727870272246 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcomposite-0.4.7-hb03c661_0.conda @@ -10051,6 +11076,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxcomposite >=0.4.7,<1.0a0 size: 14415 timestamp: 1770044404696 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcursor-1.2.3-hb9d3cd8_0.conda @@ -10065,6 +11093,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxcursor >=1.2.3,<2.0a0 size: 32533 timestamp: 1730908305254 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdamage-1.1.6-hb9d3cd8_0.conda @@ -10079,6 +11110,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxdamage >=1.1.6,<2.0a0 size: 13217 timestamp: 1727891438799 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda @@ -10090,6 +11124,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxdmcp >=1.1.5,<2.0a0 size: 20591 timestamp: 1762976546182 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda @@ -10102,6 +11139,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxext >=1.3.7,<2.0a0 size: 50326 timestamp: 1769445253162 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda @@ -10114,6 +11154,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxfixes >=6.0.2,<7.0a0 size: 20071 timestamp: 1759282564045 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.3-hb03c661_0.conda @@ -10128,6 +11171,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxi >=1.8.3,<2.0a0 size: 47717 timestamp: 1779111857071 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxinerama-1.1.6-hecca717_0.conda @@ -10142,6 +11188,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxinerama >=1.1.6,<1.2.0a0 size: 14818 timestamp: 1769432261050 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxmu-1.3.1-hb03c661_0.conda @@ -10156,6 +11205,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxmu >=1.3.1,<2.0a0 size: 90301 timestamp: 1769675723651 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxpm-3.5.19-hb03c661_0.conda @@ -10173,6 +11225,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxpm >=3.5.19,<4.0a0 size: 64386 timestamp: 1776789976572 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda @@ -10187,6 +11242,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxrandr >=1.5.5,<2.0a0 size: 30456 timestamp: 1769445263457 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda @@ -10199,6 +11257,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxrender >=0.9.12,<0.10.0a0 size: 33005 timestamp: 1734229037766 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxscrnsaver-1.2.4-hb9d3cd8_0.conda @@ -10212,6 +11273,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxscrnsaver >=1.2.4,<2.0a0 size: 14412 timestamp: 1727899730073 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxshmfence-1.3.3-hb9d3cd8_0.conda @@ -10223,6 +11287,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxshmfence >=1.3.3,<2.0a0 size: 12302 timestamp: 1734168591429 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda @@ -10237,6 +11304,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxt >=1.3.1,<2.0a0 size: 379686 timestamp: 1731860547604 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda @@ -10251,6 +11321,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxtst >=1.2.5,<2.0a0 size: 32808 timestamp: 1727964811275 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.7-hb03c661_0.conda @@ -10264,6 +11337,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxxf86vm >=1.1.7,<2.0a0 size: 18701 timestamp: 1769434732453 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xorgproto-2025.1-hb03c661_0.conda @@ -10275,6 +11351,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 570010 timestamp: 1766154256151 - conda: https://conda.anaconda.org/conda-forge/linux-64/xxhash-0.8.3-hb47aa4a_0.conda @@ -10286,6 +11363,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - xxhash >=0.8.3,<0.8.4.0a0 size: 108219 timestamp: 1746457673761 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.8.3-ha02ee65_0.conda @@ -10300,6 +11380,9 @@ packages: - xz-tools 5.8.3 hb03c661_0 license: 0BSD AND LGPL-2.1-or-later AND GPL-2.0-or-later purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 size: 24360 timestamp: 1775825568523 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-gpl-tools-5.8.3-ha02ee65_0.conda @@ -10313,6 +11396,9 @@ packages: - xz 5.8.3.* license: 0BSD AND LGPL-2.1-or-later AND GPL-2.0-or-later purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 size: 34213 timestamp: 1775825548743 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.3-hb03c661_0.conda @@ -10326,6 +11412,7 @@ packages: - xz 5.8.3.* license: 0BSD AND LGPL-2.1-or-later purls: [] + run_exports: {} size: 95955 timestamp: 1775825530484 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda @@ -10337,6 +11424,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 size: 85189 timestamp: 1753484064210 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda @@ -10350,6 +11440,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - yaml-cpp >=0.8.0,<0.9.0a0 size: 223526 timestamp: 1745307989800 - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.24.2-py312h8a5da7c_0.conda @@ -10367,6 +11460,7 @@ packages: license_family: Apache purls: - pkg:pypi/yarl?source=hash-mapping + run_exports: {} size: 155061 timestamp: 1779246264888 - conda: https://conda.anaconda.org/conda-forge/linux-64/zenoh-rust-abi-1.7.2.1.85.0-h8619998_0.conda @@ -10378,6 +11472,9 @@ packages: - __glibc >=2.17 license: Apache-2.0 OR EPL-2.0 purls: [] + run_exports: + weak: + - zenoh-rust-abi >=1.7.2.1.85.0,<1.7.2.1.85.1.0a0 size: 49012 timestamp: 1767949916856 - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h09e67af_11.conda @@ -10392,6 +11489,9 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: + weak: + - zeromq >=4.3.5,<4.4.0a0 size: 311184 timestamp: 1779123989774 - conda: https://conda.anaconda.org/conda-forge/linux-64/zfp-1.0.1-h909a3a2_5.conda @@ -10405,6 +11505,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - zfp >=1.0.1,<2.0a0 size: 277694 timestamp: 1766549572069 - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.conda @@ -10416,6 +11519,9 @@ packages: license: Zlib license_family: Other purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 size: 95931 timestamp: 1774072620848 - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda @@ -10427,6 +11533,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 size: 601375 timestamp: 1764777111296 - conda: https://conda.anaconda.org/conda-forge/linux-64/zziplib-0.13.69-he45264a_2.conda @@ -10437,6 +11546,9 @@ packages: - libzlib >=1.3.1,<2.0a0 license: LGPL-2.0-or-later OR MPL-1.1 purls: [] + run_exports: + weak: + - zziplib >=0.13.69,<0.14.0a0 size: 106915 timestamp: 1719242059793 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda @@ -10450,6 +11562,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + strong: + - _openmp_mutex >=4.5 size: 28926 timestamp: 1770939656741 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/adwaita-icon-theme-3.38.0-h2d234d2_1.tar.bz2 @@ -10461,11 +11576,12 @@ packages: license: LGPL-3.0-or-later OR CC-BY-SA-3.0 license_family: LGPL purls: [] + run_exports: {} size: 11238327 timestamp: 1610490614592 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.13.5-py312he7e3343_0.conda - sha256: 79f642056509f7e7f627cce204ec6696e0d1388b86a675938613cd4c0069da30 - md5: 6b7123551168b73a78442df402037343 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.14.1-py312he7e3343_0.conda + sha256: 58b4395fb87a695d3ce78a4495bebd436892899e4ffa905ed1856f377a804835 + md5: 96be2f10e3eec5249c10d6cd4c8bf980 depends: - aiohappyeyeballs >=2.5.0 - aiosignal >=1.4.0 @@ -10477,23 +11593,28 @@ packages: - python >=3.12,<3.13.0a0 - python >=3.12,<3.13.0a0 *_cpython - python_abi 3.12.* *_cp312 + - typing_extensions >=4.4 - yarl >=1.17.0,<2.0 license: MIT AND Apache-2.0 license_family: Apache purls: - pkg:pypi/aiohttp?source=hash-mapping - size: 1024372 - timestamp: 1774999721300 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.16-he30d5cf_0.conda - sha256: 722a24bb4a2faabcedf694ae494393e6f9b698dddbf0782fb0dcd7bfcc0c2027 - md5: 20e118f10dc11b6b2383ae7c1f2c8e8c + run_exports: {} + size: 1068919 + timestamp: 1780913451554 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.16.1-he30d5cf_0.conda + sha256: 105e4c19cfa770affcb9a64b9d2451f406914cd09a67664009910869fa01a639 + md5: 5427b5dcb268bddf1a69c16d1cb77a47 depends: - libgcc >=14 license: LGPL-2.1-or-later - license_family: GPL + license_family: LGPL purls: [] - size: 619180 - timestamp: 1780398750941 + run_exports: + weak: + - alsa-lib >=1.2.16.1,<1.3.0a0 + size: 621865 + timestamp: 1781522013595 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-plugins-1.2.12-haf9f4a6_2.conda sha256: e03e48f4fd5bbd7523b03cdcc803a5654f132fc561e422e2cc2903c883ee0ce1 md5: bf0fa9c73d93fc6b499a4059e82c5aa5 @@ -10506,6 +11627,7 @@ packages: license: LGPL-2.1-or-later AND GPL-3.0-or-later license_family: LGPL purls: [] + run_exports: {} size: 264427 timestamp: 1756137068124 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aom-3.9.1-hcccb83c_0.conda @@ -10517,6 +11639,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - aom >=3.9.1,<3.10.0a0 size: 3250813 timestamp: 1718551360260 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/assimp-5.4.3-he8c3857_1.conda @@ -10531,6 +11656,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - assimp >=5.4.3,<5.4.4.0a0 size: 3572443 timestamp: 1753274717951 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/at-spi2-atk-2.38.0-h1f2db35_3.tar.bz2 @@ -10545,6 +11673,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - at-spi2-atk >=2.38.0,<3.0a0 size: 322172 timestamp: 1619123713021 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/at-spi2-core-2.40.3-h1f2db35_0.tar.bz2 @@ -10560,6 +11691,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - at-spi2-core >=2.40.3,<2.41.0a0 size: 622407 timestamp: 1625848355776 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/atk-1.0-2.38.0-hedc4a1f_2.conda @@ -10574,6 +11708,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - atk-1.0 >=2.38.0 size: 358327 timestamp: 1713898303194 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/attr-2.5.2-he30d5cf_1.conda @@ -10585,21 +11722,25 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - libattr >=2.5.2,<2.6.0a0 size: 33708 timestamp: 1773595939135 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.5.0-py312ha46dd1d_0.conda - sha256: 0c6fcd7ee0d3defcd279f9a144e9d56fe7d100d6a4749c0d0bd5faa302a54a43 - md5: 4e6cc4fee8896183d0bd2b5f32c3d1b5 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.6.0-py312ha46dd1d_0.conda + sha256: dfe925314fd594cd6cefa78d79df8bc6898a3848460db346b87597f77df8442c + md5: 19c1ea1ad92760d8e465a371a40ca125 depends: - python - libgcc >=14 - - zstd >=1.5.7,<1.6.0a0 - python_abi 3.12.* *_cp312 + - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping - size: 241317 - timestamp: 1778594051531 + run_exports: {} + size: 241556 + timestamp: 1781450814407 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bcrypt-5.0.0-py312h5eb8f6c_1.conda sha256: 682dea63cb655efe2e12dc63062f5c719df66d15d98a511b2936b5424b2f4cde md5: 70d8f4f204a16e346871ba4c22a7886e @@ -10614,6 +11755,7 @@ packages: license_family: APACHE purls: - pkg:pypi/bcrypt?source=hash-mapping + run_exports: {} size: 297613 timestamp: 1762497725874 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/benchmark-1.9.5-hfae3067_0.conda @@ -10625,6 +11767,7 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: {} size: 279762 timestamp: 1769117024546 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.45.1-default_hf1166c9_102.conda @@ -10635,6 +11778,7 @@ packages: license: GPL-3.0-only license_family: GPL purls: [] + run_exports: {} size: 35511 timestamp: 1774197558632 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.45.1-default_h5f4c503_102.conda @@ -10647,6 +11791,7 @@ packages: license: GPL-3.0-only license_family: GPL purls: [] + run_exports: {} size: 4683754 timestamp: 1774197535605 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.45.1-default_hf1166c9_102.conda @@ -10657,6 +11802,7 @@ packages: license: GPL-3.0-only license_family: GPL purls: [] + run_exports: {} size: 36267 timestamp: 1774197561368 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/blosc-1.21.6-hb4dfabd_1.conda @@ -10672,6 +11818,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - blosc >=1.21.6,<2.0a0 size: 36414 timestamp: 1733513501944 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-1.2.0-hd651790_1.conda @@ -10685,6 +11834,11 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 size: 20145 timestamp: 1764017310011 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-bin-1.2.0-he30d5cf_1.conda @@ -10697,6 +11851,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 20758 timestamp: 1764017301339 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py312hac7b6a9_1.conda @@ -10714,6 +11869,7 @@ packages: license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping + run_exports: {} size: 373800 timestamp: 1764017545385 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bullet-3.25-h6ffa558_5.conda @@ -10726,6 +11882,7 @@ packages: - python license: Zlib purls: [] + run_exports: {} size: 11685 timestamp: 1761046730469 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bullet-cpp-3.25-py312he7881e2_5.conda @@ -10742,6 +11899,9 @@ packages: - xorg-libxext >=1.3.6,<2.0a0 license: Zlib purls: [] + run_exports: + weak: + - bullet-cpp >=3.25,<3.26.0a0 size: 42319979 timestamp: 1761046342434 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda @@ -10752,6 +11912,9 @@ packages: license: bzip2-1.0.6 license_family: BSD purls: [] + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 size: 192412 timestamp: 1771350241232 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda @@ -10762,6 +11925,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - c-ares >=1.34.6,<2.0a0 size: 217215 timestamp: 1765214743735 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.11.0-hdceaead_0.conda @@ -10774,6 +11940,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 6721 timestamp: 1753098688332 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda @@ -10800,6 +11967,9 @@ packages: - xorg-libxrender >=0.9.12,<0.10.0a0 license: LGPL-2.1-only or MPL-1.1 purls: [] + run_exports: + weak: + - cairo >=1.18.4,<2.0a0 size: 927045 timestamp: 1766416003626 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cbor2-5.9.0-py312hd41f8a7_0.conda @@ -10814,6 +11984,7 @@ packages: license_family: MIT purls: - pkg:pypi/cbor2?source=hash-mapping + run_exports: {} size: 121651 timestamp: 1775229767017 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py312h1b372e3_1.conda @@ -10829,6 +12000,7 @@ packages: license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping + run_exports: {} size: 315113 timestamp: 1761203960926 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-21-21.1.8-default_he95a3c9_4.conda @@ -10842,6 +12014,7 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] + run_exports: {} size: 72089 timestamp: 1777012007789 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-21.1.8-default_he95a3c9_4.conda @@ -10856,6 +12029,7 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] + run_exports: {} size: 28754 timestamp: 1777012040719 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cli11-2.6.2-h7ac5ae9_0.conda @@ -10867,6 +12041,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 99015 timestamp: 1772207983869 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.29.6-h7042e5d_0.conda @@ -10887,6 +12062,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 18297625 timestamp: 1718668828575 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/colcon-common-extensions-0.3.0-py312h996f985_4.conda @@ -10919,6 +12095,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-common-extensions?source=hash-mapping + run_exports: {} size: 13497 timestamp: 1759758075816 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/colcon-notification-0.3.1-py312h72dafdd_0.conda @@ -10934,6 +12111,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-notification?source=hash-mapping + run_exports: {} size: 86300 timestamp: 1774664660377 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/compilers-1.11.0-h8af1aa0_0.conda @@ -10946,6 +12124,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 7575 timestamp: 1753098689062 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-gcc-specs-14.3.0-hadff5d6_19.conda @@ -10956,6 +12135,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 31704 timestamp: 1778268711052 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/console_bridge-1.0.2-hdd96247_1.tar.bz2 @@ -10967,6 +12147,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - console_bridge >=1.0.2,<1.1.0a0 size: 18484 timestamp: 1648912662150 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/contourpy-1.3.3-py312hf18b547_4.conda @@ -10983,22 +12166,23 @@ packages: license_family: BSD purls: - pkg:pypi/contourpy?source=hash-mapping + run_exports: {} size: 339097 timestamp: 1769155976173 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.14.1-py312hd077ced_0.conda - sha256: 9079de8b96c433468f33eb2eb89539e785a564f122ce62a4f1d716f0295edf1c - md5: 803aee59c5fc81cefd35d10dcfca9dc0 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.15.0-py312hd077ced_0.conda + sha256: 60d2e746091877a17664134097bc36fd6b4b12da78c3c921541a8781d5448a16 + md5: 872445d47afa6245bb40f781d6e099ca depends: - libgcc >=14 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 - tomli license: Apache-2.0 - license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping - size: 390698 - timestamp: 1779839029690 + run_exports: {} + size: 395533 + timestamp: 1783020298823 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cppcheck-2.18.3-py312h5677ec4_1.conda sha256: 6540f7d961f6703bab10319cf556db180d00c309575fc64436c7316b3f019682 md5: 6f4302389e8a90b3ca9b1a3c55a80c4a @@ -11015,6 +12199,7 @@ packages: license_family: GPL purls: - pkg:pypi/cppcheck-htmlreport?source=hash-mapping + run_exports: {} size: 2923791 timestamp: 1757440286496 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cppzmq-4.11.0-h7be3492_0.conda @@ -11027,15 +12212,16 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 30681 timestamp: 1763728975675 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-48.0.0-py312h96535df_0.conda - sha256: f1d32d6fdb0d826004f0bc9c1449c72694d5c6c02d1966b9171fac1f486aed93 - md5: 88112c17a679a67d958e0843d494ea42 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-49.0.0-py312h96535df_0.conda + sha256: 6220d057368612e916d265c9eb7cffe65276143bff699aa4120bc14a7ed90ff6 + md5: 8f48b1cbdb64a64e42ee382bed75601a depends: - cffi >=2.0 - libgcc >=14 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 constrains: @@ -11044,24 +12230,27 @@ packages: license_family: BSD purls: - pkg:pypi/cryptography?source=hash-mapping - size: 1957944 - timestamp: 1777966099096 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/curl-8.20.0-hc57f145_0.conda - sha256: 7812bfa95c64f6900deff0d26091599a969b216b9bec1c3156f974cf060e5ca7 - md5: bf7d70846cc20c1bfdc229784c615103 + run_exports: {} + size: 1962389 + timestamp: 1781385371022 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/curl-8.21.0-h7c59cd8_2.conda + sha256: a36ed82bbaebdc59e205d399d6e898bcb20fbcd5aaebb162cdf690ba97173ef5 + md5: a06d829c51a365e8daf0b2a3d4f06d9d depends: - krb5 >=1.22.2,<1.23.0a0 - - libcurl 8.20.0 hc57f145_0 + - libcurl 8.21.0 h7c59cd8_2 - libgcc >=14 + - libpsl >=0.22.0,<0.23.0a0 - libssh2 >=1.11.1,<2.0a0 - libzlib >=1.3.2,<2.0a0 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT purls: [] - size: 197100 - timestamp: 1777461491381 + run_exports: {} + size: 201305 + timestamp: 1782911743345 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.11.0-h7b35c40_0.conda sha256: b87cd33501867d999caa1a57e488e69dc9e08011ec8685586df754302247a7a4 md5: 0234c63e6b36b1677fd6c5238ef0a4ec @@ -11072,6 +12261,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 6705 timestamp: 1753098688728 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cyrus-sasl-2.1.28-h6598af7_1.conda @@ -11087,6 +12277,9 @@ packages: license: BSD-3-Clause-Attribution license_family: BSD purls: [] + run_exports: + weak: + - cyrus-sasl >=2.1.28,<3.0a0 size: 224450 timestamp: 1771943147365 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/dav1d-1.2.1-h31becfc_0.conda @@ -11097,6 +12290,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - dav1d >=1.2.1,<1.2.2.0a0 size: 347363 timestamp: 1685696690003 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/dbus-1.16.2-h70963c4_1.conda @@ -11110,6 +12306,9 @@ packages: - libexpat >=2.7.3,<3.0a0 license: AFL-2.1 OR GPL-2.0-or-later purls: [] + run_exports: + weak: + - dbus >=1.16.2,<2.0a0 size: 480416 timestamp: 1764536098891 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/dbus-python-1.3.2-py312hf371ade_6.conda @@ -11126,6 +12325,7 @@ packages: license_family: MIT purls: - pkg:pypi/dbus-python?source=hash-mapping + run_exports: {} size: 139771 timestamp: 1759741064708 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/double-conversion-3.4.0-hfae3067_0.conda @@ -11137,6 +12337,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - double-conversion >=3.4.0,<3.5.0a0 size: 71905 timestamp: 1765194538141 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/eigen-3.4.0-h7ac5ae9_2.conda @@ -11148,6 +12351,7 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: {} size: 1173140 timestamp: 1771922508919 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/eigen-abi-3.4.0.100-h9a8c16c_2.conda @@ -11158,6 +12362,7 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: {} size: 13127 timestamp: 1771922508962 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/elfutils-0.194-h7d8af26_0.conda @@ -11177,6 +12382,9 @@ packages: license: LGPL-3.0-only license_family: LGPL purls: [] + run_exports: + weak: + - elfutils >=0.194,<0.195.0a0 size: 1408066 timestamp: 1765447462530 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/epoxy-1.5.10-he30d5cf_2.conda @@ -11199,19 +12407,25 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - epoxy >=1.5.10,<1.6.0a0 size: 422103 timestamp: 1758743388115 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda - sha256: a9cd5eb1700e11cc39acc36630a2d72a4e317943bd7c5695cd8804419f04ff42 - md5: 89f0247b3cea528d8ad1a6664a313153 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_1.conda + sha256: e4cc29e20435f2787031eafaf100496cb700d2ebc246e91211cbde023b2600b4 + md5: 4bcb07322aecccd75514fd585ad0b719 depends: - - libexpat 2.8.1 hfae3067_0 + - libexpat 2.8.1 hfae3067_1 - libgcc >=14 license: MIT license_family: MIT purls: [] - size: 140114 - timestamp: 1779278679081 + run_exports: + weak: + - libexpat >=2.8.1,<3.0a0 + size: 141254 + timestamp: 1781203579915 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fcl-0.7.0-h841ecf2_8.conda sha256: e59440ebfb857f843a0678abf6aafb1b0b45c305d6269d27fdff7c45cd63fef1 md5: 2d17602b2516dc91d305c57a872d62c8 @@ -11224,6 +12438,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - fcl >=0.7.0,<0.8.0a0 size: 1454889 timestamp: 1736132812554 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ffmpeg-8.0.1-gpl_hd1a4c92_912.conda @@ -11283,6 +12500,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - ffmpeg >=8.0.1,<9.0a0 size: 12036520 timestamp: 1769713781879 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fftw-3.3.11-nompi_h66d8d02_100.conda @@ -11296,6 +12516,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - fftw >=3.3.11,<4.0a0 size: 1704301 timestamp: 1776781937409 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flann-1.9.2-headf6c6_6.conda @@ -11310,6 +12533,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - flann >=1.9.2,<1.9.3.0a0 size: 1420069 timestamp: 1774331959849 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda @@ -11321,6 +12547,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - fmt >=12.1.0,<12.2.0a0 size: 197671 timestamp: 1767681179883 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.18.1-hba86a56_0.conda @@ -11336,6 +12565,10 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - fontconfig >=2.18.1,<3.0a0 + - fonts-conda-ecosystem size: 290522 timestamp: 1780450108132 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fonttools-4.63.0-py312ha4530ae_0.conda @@ -11353,6 +12586,7 @@ packages: license_family: MIT purls: - pkg:pypi/fonttools?source=hash-mapping + run_exports: {} size: 2952221 timestamp: 1778770458588 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/foonathan-memory-0.7.3-h5ad3122_1.conda @@ -11363,6 +12597,9 @@ packages: - libstdcxx >=13 license: Zlib purls: [] + run_exports: + weak: + - foonathan-memory >=0.7.3,<0.7.4.0a0 size: 225684 timestamp: 1746248561179 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fortran-compiler-1.11.0-h151373c_0.conda @@ -11376,6 +12613,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 6740 timestamp: 1753098688910 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freeglut-3.2.2-hddf9bb5_4.conda @@ -11396,6 +12634,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - freeglut >=3.2.2,<4.0a0 size: 148954 timestamp: 1776928010379 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freeimage-3.18.0-he4296dc_25.conda @@ -11416,18 +12657,25 @@ packages: - openjpeg >=2.5.4,<3.0a0 license: GPL-2.0-or-later OR GPL-3.0-or-later OR FreeImage purls: [] + run_exports: + weak: + - freeimage >=3.18.0,<3.19.0a0 size: 484680 timestamp: 1780001503149 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freetype-2.14.3-h8af1aa0_0.conda - sha256: 5594df70ef3df016b99de44e61b4024b7f3ec3472db83c7ac7723eafa8b26d95 - md5: f11edf8adf0d119148b97f745548390d +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freetype-2.14.3-h8af1aa0_1.conda + sha256: 1112c56bc19cbce233b30d9d31ce8eb6fcc100c9baa5145315aaa1e3a25b5178 + md5: 5e8e88bfb3fbb0df0f9f8bb890721e07 depends: - - libfreetype 2.14.3 h8af1aa0_0 - - libfreetype6 2.14.3 hdae7a39_0 + - libfreetype 2.14.3 h8af1aa0_1 + - libfreetype6 2.14.3 hdae7a39_1 license: GPL-2.0-only OR FTL purls: [] - size: 173735 - timestamp: 1774301100144 + run_exports: + weak: + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + size: 174060 + timestamp: 1780933507786 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fribidi-1.0.16-he30d5cf_0.conda sha256: 1bfcd715bcb49a0b22d5d1899a22c6ff884b06f8e141eb746f3949752469a422 md5: f3ac54914f7d3e1d68cb8d891765e5f9 @@ -11435,6 +12683,9 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - fribidi >=1.0.16,<2.0a0 size: 62909 timestamp: 1757438620177 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.8.0-py312hb10c72c_0.conda @@ -11450,6 +12701,7 @@ packages: license_family: APACHE purls: - pkg:pypi/frozenlist?source=hash-mapping + run_exports: {} size: 54733 timestamp: 1779999833443 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-14.3.0-h2e72a27_19.conda @@ -11461,6 +12713,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 29621 timestamp: 1778268825860 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-14.3.0-h398eab4_19.conda @@ -11478,6 +12731,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 68567347 timestamp: 1778268606528 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-15.2.0-h74e174c_19.conda @@ -11494,11 +12748,12 @@ packages: - sysroot_linux-aarch64 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + run_exports: {} size: 73693226 timestamp: 1778860139481 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h140ef2e_25.conda - sha256: e52a4dc150e9bebefd7aa42147e64f3bb1e05c86128013156867e0f50c793161 - md5: 37f51721bc9aee83218fbe356a65a5c6 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h140ef2e_27.conda + sha256: 524e287b7c1b3e53bc6ba830968c05bc60437cf0a4778c56a2d09235e357517b + md5: 877c135e8aada3eef4aef0bea9102c13 depends: - gcc_impl_linux-aarch64 14.3.0.* - binutils_linux-aarch64 @@ -11506,34 +12761,43 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] - size: 28918 - timestamp: 1779371711447 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-15.2.0-h0bf4bd8_25.conda - sha256: 3959c6c15049c1a86bf60b155b65c2843e888024a19fca7b49300ee233a87e12 - md5: 86d74b60631ae83d3e812d907bb89101 + run_exports: + strong: + - libgcc >=14 + size: 29091 + timestamp: 1781279944723 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-15.2.0-h0bf4bd8_27.conda + sha256: 2450913611189cc3c26062a43a97a93501159335d4d314cca5e2678fb5f4d3b6 + md5: 619b8a05f89220fa8c9536dcfeeddd5b depends: - gcc_impl_linux-aarch64 15.2.0.* - binutils_linux-aarch64 - sysroot_linux-aarch64 license: BSD-3-Clause license_family: BSD - size: 28934 - timestamp: 1779371716472 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gdk-pixbuf-2.44.6-h90308e0_0.conda - sha256: 53ac38045a8c0b6aa9cfaf784443a3744dc86ab4737c1479b44ae85c96926fe1 - md5: bdd860e72c5e10eb4ffa3d61f9b02ee0 + run_exports: + strong: + - libgcc >=15 + size: 29074 + timestamp: 1781279974207 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gdk-pixbuf-2.44.7-h90308e0_0.conda + sha256: f406e0b58a51da8648b100316c7b5893e5585256b67eb410126e2357a901f0d2 + md5: 6b26b46bbc0761e0f256699eab75202d depends: - libgcc >=14 - - libglib >=2.86.4,<3.0a0 - - libjpeg-turbo >=3.1.2,<4.0a0 - - liblzma >=5.8.2,<6.0a0 - - libpng >=1.6.56,<1.7.0a0 + - libglib >=2.88.2,<3.0a0 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libpng >=1.6.58,<1.7.0a0 - libtiff >=4.7.1,<4.8.0a0 license: LGPL-2.1-or-later license_family: LGPL purls: [] - size: 583708 - timestamp: 1774987740322 + run_exports: + weak: + - gdk-pixbuf >=2.44.7,<3.0a0 + size: 588681 + timestamp: 1782593151876 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/geographiclib-cpp-2.7-hfefdfc9_0.conda sha256: 6fe8f80c7fa545c24e3830982bc41a0b02bf101c7bc91955b6db6a22dcfcf30b md5: ddbe1705c348ff1c7946c1416b5d3c84 @@ -11543,6 +12807,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - geographiclib-cpp >=2.7,<2.8.0a0 size: 713193 timestamp: 1762553044644 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gettext-0.25.1-h5ad3122_0.conda @@ -11558,6 +12825,10 @@ packages: - libstdcxx >=13 license: LGPL-2.1-or-later AND GPL-3.0-or-later purls: [] + run_exports: + weak: + - libasprintf >=0.25.1,<1.0a0 + - libgettextpo >=0.25.1,<1.0a0 size: 534760 timestamp: 1751557634743 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gettext-tools-0.25.1-h5ad3122_0.conda @@ -11568,6 +12839,7 @@ packages: license: GPL-3.0-or-later license_family: GPL purls: [] + run_exports: {} size: 3999301 timestamp: 1751557600737 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran-14.3.0-ha28f942_7.conda @@ -11580,6 +12852,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 30531 timestamp: 1759967819421 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_impl_linux-aarch64-14.3.0-h6b0ea1e_19.conda @@ -11594,21 +12867,27 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 14838254 timestamp: 1778268770944 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_linux-aarch64-14.3.0-h495b507_25.conda - sha256: 2d6f8dd4688ce11cbabec04ddbdad6faf7de7f78e4250c7b8d68d54d2aef6565 - md5: e6bed58ea5ceae16d776f30681f7e244 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gfortran_linux-aarch64-14.3.0-h4981040_27.conda + sha256: 5121a773143d441b132c47cfe6ee7f10149fa93e677a11fcceb87156039a289b + md5: 2d97644339032316cf05e1ffbf33cad8 depends: - gfortran_impl_linux-aarch64 14.3.0.* - - gcc_linux-aarch64 ==14.3.0 h140ef2e_25 + - gcc_linux-aarch64 ==14.3.0 h140ef2e_27 - binutils_linux-aarch64 - sysroot_linux-aarch64 license: BSD-3-Clause license_family: BSD purls: [] - size: 27160 - timestamp: 1779371711447 + run_exports: + strong: + - libgfortran5 >=14.3.0 + - libgfortran + - libgcc >=14 + size: 27325 + timestamp: 1781279944723 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/git-2.54.0-pl5321h5dcfaa0_1.conda sha256: 9a5903559d6e66abee4abc92339a8532d8ad9b767252dd273aca96a20e010654 md5: a3ac0b23e49175684b6ee1f845924fb5 @@ -11624,6 +12903,7 @@ packages: - perl 5.* license: GPL-2.0-or-later and LGPL-2.1-or-later purls: [] + run_exports: {} size: 14442457 timestamp: 1780740536301 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gl2ps-1.4.2-hd9db0c5_2.conda @@ -11638,6 +12918,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gl2ps >=1.4.2,<1.4.3.0a0 size: 73898 timestamp: 1773986749310 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glew-2.3.0-hf9dcc85_0.conda @@ -11652,6 +12935,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - glew >=2.3.0,<2.4.0a0 size: 484212 timestamp: 1766373411104 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glfw-3.4-he30d5cf_1.conda @@ -11668,31 +12954,38 @@ packages: - xorg-libxrandr >=1.5.4,<2.0a0 license: Zlib purls: [] + run_exports: + weak: + - glfw >=3.4,<4.0a0 size: 170266 timestamp: 1758809249325 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-2.88.1-h72f18f7_2.conda - sha256: e549384595431504ebd83bab7ad26c79d0d07a7c59fde00e0c56a074e93c3a3c - md5: 89fd41b112496272149273fb3a051e05 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-2.88.2-hdf12349_0.conda + sha256: 1cdb69c2ff6714b0c580f839df05b75f20dd09a7bcf44809ca4c9f6dd607488f + md5: ee8e7987db9670fdf9505aa9f1f5e087 depends: - python * - packaging - - libglib ==2.88.1 h96a7f82_2 - - glib-tools ==2.88.1 h7439e1d_2 + - libglib ==2.88.2 h96a7f82_0 + - glib-tools ==2.88.2 h7aeb4f4_0 license: LGPL-2.1-or-later purls: [] - size: 102948 - timestamp: 1778508920982 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-tools-2.88.1-h7439e1d_2.conda - sha256: a8d09a59c1cd0df08a085f6ed8401139b3301799735511746165e126c29c3fce - md5: 49b98fdeb09f7379d52a167b35b99223 - depends: - - libglib ==2.88.1 h96a7f82_2 + run_exports: + weak: + - libglib >=2.88.2,<3.0a0 + size: 103291 + timestamp: 1782464048865 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glib-tools-2.88.2-h7aeb4f4_0.conda + sha256: cbb0679fccff1b87253d24a8aee96bf3908f16c4a1a828c35578ed8e8d516a61 + md5: c7195d7c970b8bdca5d6b5f6adb66886 + depends: + - libglib ==2.88.2 h96a7f82_0 - libffi - libgcc >=14 license: LGPL-2.1-or-later purls: [] - size: 257707 - timestamp: 1778508920982 + run_exports: {} + size: 260096 + timestamp: 1782464048865 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glslang-16.3.0-h124e036_0.conda sha256: bae4806f4076cf9f91089fbeae7c9357ce4348df3657c25b249ac4487beed230 md5: c0045dffcc3660ecd1b9123df377796f @@ -11703,6 +12996,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - glslang >=16,<17.0a0 size: 1359428 timestamp: 1777747105441 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmock-1.17.0-h8af1aa0_1.conda @@ -11713,6 +13009,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 7659 timestamp: 1748320119582 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmp-6.3.0-h0a1ffab_2.conda @@ -11723,6 +13020,9 @@ packages: - libstdcxx-ng >=12 license: GPL-2.0-or-later OR LGPL-3.0-or-later purls: [] + run_exports: + weak: + - gmp >=6.3.0,<7.0a0 size: 417323 timestamp: 1718980707330 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gnutls-3.8.13-hfe111f1_0.conda @@ -11739,6 +13039,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gnutls >=3.8.13,<3.9.0a0 size: 2124632 timestamp: 1778044273289 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.15-hfae3067_0.conda @@ -11750,6 +13053,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 size: 103119 timestamp: 1780455096710 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphviz-14.1.2-h45e821f_0.conda @@ -11774,6 +13080,9 @@ packages: license: EPL-1.0 license_family: Other purls: [] + run_exports: + weak: + - graphviz >=14.1.2,<15.0a0 size: 2578234 timestamp: 1769427141106 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gst-plugins-base-1.26.11-hd6b5e5b_0.conda @@ -11808,6 +13117,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gst-plugins-base >=1.26.11,<1.27.0a0 size: 3216930 timestamp: 1776268752110 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gstreamer-1.26.11-hf552038_0.conda @@ -11823,6 +13135,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gstreamer >=1.26.11,<1.27.0a0 size: 2304060 timestamp: 1776268752110 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gstreamer-orc-0.4.42-h70b131a_0.conda @@ -11832,6 +13147,7 @@ packages: - libgcc >=14 license: BSD-2-Clause AND BSD-3-Clause purls: [] + run_exports: {} size: 377338 timestamp: 1768408531779 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gtest-1.17.0-h17cf362_1.conda @@ -11845,6 +13161,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - gtest >=1.17.0,<1.17.1.0a0 size: 409213 timestamp: 1748320114722 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gtk3-3.24.52-h75d4e7a_0.conda @@ -11887,6 +13206,10 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gtk3 >=3.24.52,<4.0a0 + - adwaita-icon-theme size: 6023698 timestamp: 1774296668544 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gts-0.7.6-he293c15_4.conda @@ -11899,6 +13222,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - gts >=0.7.6,<0.8.0a0 size: 332673 timestamp: 1686545222091 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-14.3.0-ha28f942_7.conda @@ -11910,6 +13236,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 30526 timestamp: 1759967828504 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-14.3.0-h0d4f5d4_19.conda @@ -11923,21 +13250,26 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 13722799 timestamp: 1778268804579 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h73dd529_25.conda - sha256: ced990f90ab5fb94c88cc2fd37af34ab9e366216770ef66480e0777009108475 - md5: 94f9a4546bd84d4bd86433e589ff365d +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h0da240b_27.conda + sha256: 07df85f4ba8a199afb300fc1239aa72d6d425f4a258d4414102caff800ea8093 + md5: c8776dadbd23bb98b6863b0860047a35 depends: - gxx_impl_linux-aarch64 14.3.0.* - - gcc_linux-aarch64 ==14.3.0 h140ef2e_25 + - gcc_linux-aarch64 ==14.3.0 h140ef2e_27 - binutils_linux-aarch64 - sysroot_linux-aarch64 license: BSD-3-Clause license_family: BSD purls: [] - size: 27479 - timestamp: 1779371711447 + run_exports: + strong: + - libstdcxx >=14 + - libgcc >=14 + size: 27646 + timestamp: 1781279944723 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-cmake3-3.5.5-h740f95d_0.conda sha256: 156c068a26873adeed74deef7cc2788a0d952409c9d70dd62f1b21f94a90b758 md5: fe4f85a94f05fc0ba646a19e642c16c3 @@ -11946,6 +13278,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-cmake3 >=3.5.5,<4.0a0 size: 7440 timestamp: 1759138433911 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-math7-7.5.2-h1ad700d_2.conda @@ -11957,6 +13292,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-math7 >=7.5.2,<8.0a0 size: 8250 timestamp: 1759147772705 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-math7-python-7.5.2-py312h9452373_2.conda @@ -11975,6 +13313,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 881527 timestamp: 1759147772705 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-tools-2.0.3-h8a9b3d2_1.conda @@ -11985,6 +13324,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-tools >=2.0.3,<3.0a0 size: 7807 timestamp: 1759148397768 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-tools2-2.0.3-hd91f489_1.conda @@ -11995,6 +13337,10 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-tools >=2.0.3,<3.0a0 + - libgz-tools >=2.0.3,<3.0a0 size: 7834 timestamp: 1759148397768 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gz-utils2-2.2.1-h2ce864c_2.conda @@ -12005,27 +13351,24 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-utils2 >=2.2.1,<3.0a0 size: 8050 timestamp: 1767701505722 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-14.2.1-h1134a53_0.conda - sha256: 17a671aa62e1f0a8750514353e3d6e9aab80598908d9b107fc7f3cf7972176b6 - md5: 5f3ec279ab7cc391b7dff69dc08298fa +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-14.2.1-h8af1aa0_1.conda + sha256: 57b157674ecee4d16e2873a3624095b4ed1859ce8c574b161e0d9c1723788733 + md5: 41198d1dd71d97c1507e6bd17edd10c7 depends: - - cairo >=1.18.4,<2.0a0 - - graphite2 >=1.3.14,<2.0a0 - - icu >=78.3,<79.0a0 - - libexpat >=2.8.1,<3.0a0 - - libfreetype >=2.14.3 - - libfreetype6 >=2.14.3 - - libgcc >=14 - - libglib >=2.88.1,<3.0a0 - - libstdcxx >=14 - - libzlib >=1.3.2,<2.0a0 + - libharfbuzz-devel 14.2.1 h3a99ef3_1 license: MIT license_family: MIT purls: [] - size: 2786349 - timestamp: 1780454506157 + run_exports: + weak: + - libharfbuzz >=14.2.1 + size: 11079 + timestamp: 1782800518091 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hdf4-4.2.15-hb6ba311_7.conda sha256: 70d1e2d3e0b9ae1b149a31a4270adfbb5a4ceb2f8c36d17feffcd7bcb6208022 md5: e1b6676b77b9690d07ea25de48aed97e @@ -12037,6 +13380,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - hdf4 >=4.2.15,<4.2.16.0a0 size: 773862 timestamp: 1695661552544 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hdf5-1.14.6-nompi_hf95b8e7_110.conda @@ -12054,6 +13400,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - hdf5 >=1.14.6,<1.14.7.0a0 size: 3915784 timestamp: 1780589303795 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hicolor-icon-theme-0.17-h8af1aa0_3.conda @@ -12062,6 +13411,7 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: {} size: 17670 timestamp: 1771540496764 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda @@ -12073,6 +13423,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - icu >=78.3,<79.0a0 size: 12837286 timestamp: 1773822650615 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/imath-3.2.2-h92288e7_0.conda @@ -12085,6 +13438,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - imath >=3.2.2,<3.2.3.0a0 size: 155215 timestamp: 1759984576946 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/jack-1.9.22-h9d01bbc_3.conda @@ -12098,6 +13454,9 @@ packages: license: LGPL-2.0-only license_family: LGPL purls: [] + run_exports: + weak: + - jack >=1.9.22,<1.10.0a0 size: 488216 timestamp: 1747576147517 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/jasper-4.2.9-h850eeee_1.conda @@ -12113,6 +13472,9 @@ packages: - libjpeg-turbo >=3.1.2,<4.0a0 license: JasPer-2.0 purls: [] + run_exports: + weak: + - jasper >=4.2.9,<5.0a0 size: 718811 timestamp: 1773677720825 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/jsoncpp-1.9.6-h34915d9_1.conda @@ -12123,6 +13485,9 @@ packages: - libstdcxx >=13 license: LicenseRef-Public-Domain OR MIT purls: [] + run_exports: + weak: + - jsoncpp >=1.9.6,<1.9.7.0a0 size: 162312 timestamp: 1733779925983 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/jxrlib-1.1-h31becfc_3.conda @@ -12133,6 +13498,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - jxrlib >=1.1,<1.2.0a0 size: 238091 timestamp: 1703333994798 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda @@ -12142,6 +13510,9 @@ packages: - libgcc >=13 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - keyutils >=1.6.3,<2.0a0 size: 129048 timestamp: 1754906002667 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kiwisolver-1.5.0-py312h1683e8e_0.conda @@ -12156,23 +13527,27 @@ packages: license_family: BSD purls: - pkg:pypi/kiwisolver?source=hash-mapping + run_exports: {} size: 82439 timestamp: 1773067307369 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda - sha256: b53999d888dda53c506b264e8c02b5f5c8e022c781eda0718f007339e6bc90ba - md5: d9ca108bd680ea86a963104b6b3e95ca +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-h2fb54aa_1.conda + sha256: b644718416a22b5d57c1194ea7207b7f8d33d6a2b42775763782d76cd7457aea + md5: 5fd2304064ef6199d1f91ec60ee7b820 depends: - keyutils >=1.6.3,<2.0a0 - libedit >=3.1.20250104,<3.2.0a0 - libedit >=3.1.20250104,<4.0a0 - libgcc >=14 - libstdcxx >=14 - - openssl >=3.5.5,<4.0a0 + - openssl >=3.5.7,<4.0a0 license: MIT license_family: MIT purls: [] - size: 1517436 - timestamp: 1769773395215 + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 1518484 + timestamp: 1781859412954 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lame-3.100-h4e544f5_1003.tar.bz2 sha256: 2502904a42df6d94bd743f7b73915415391dd6d31d5f50cb57c0a54a108e7b0a md5: ab05bcf82d8509b4243f07e93bada144 @@ -12181,6 +13556,9 @@ packages: license: LGPL-2.0-only license_family: LGPL purls: [] + run_exports: + weak: + - lame >=3.100,<3.101.0a0 size: 604863 timestamp: 1664997611416 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_1.conda @@ -12193,6 +13571,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - lcms2 >=2.19.1,<3.0a0 size: 296564 timestamp: 1780211834883 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda @@ -12205,6 +13586,7 @@ packages: license: GPL-3.0-only license_family: GPL purls: [] + run_exports: {} size: 875596 timestamp: 1774197520746 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda @@ -12216,6 +13598,9 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - lerc >=4.1.0,<5.0a0 size: 240444 timestamp: 1773114901155 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20250512.1-cxx17_h201e9ed_0.conda @@ -12230,6 +13615,10 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - libabseil >=20250512.1,<20250513.0a0 + - libabseil =*=cxx17* size: 1327580 timestamp: 1750194149128 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libacl-2.3.2-h883460d_0.conda @@ -12241,6 +13630,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - libacl >=2.3.2,<2.4.0a0 size: 115093 timestamp: 1706132568525 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libaec-1.1.5-hff7e48a_0.conda @@ -12252,11 +13644,14 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - libaec >=1.1.5,<2.0a0 size: 37745 timestamp: 1769221878827 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.7-gpl_hbe7d12b_101.conda - sha256: 48382f97e0ab02d758cfaec81d7df6fd1ee665c4e917c02d36b7e1a15369396e - md5: 5420789510bfaf085262fec8f15b7a64 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.8-gpl_hbe7d12b_100.conda + sha256: 74ee8968f3abdb7c1cec4b6701791b8bfcc6ba7b79de2aa76e2042a86fb3a6ec + md5: a023664e901257bc10437c26a4923528 depends: - bzip2 >=1.0.8,<2.0a0 - libgcc >=14 @@ -12266,13 +13661,16 @@ packages: - libzlib >=1.3.2,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - lzo >=2.10,<3.0a0 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: [] - size: 1006349 - timestamp: 1778486388260 + run_exports: + weak: + - libarchive >=3.8.8,<3.9.0a0 + size: 968059 + timestamp: 1782289044270 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libasprintf-0.25.1-h5e0f5ae_0.conda sha256: 146be90c237cf3d8399e44afe5f5d21ef9a15a7983ccea90e72d4ae0362f9b28 md5: 1c5813f6be57f087b6659593248daf00 @@ -12281,6 +13679,9 @@ packages: - libstdcxx >=13 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libasprintf >=0.25.1,<1.0a0 size: 53434 timestamp: 1751557548397 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libasprintf-devel-0.25.1-h5e0f5ae_0.conda @@ -12291,6 +13692,9 @@ packages: - libgcc >=13 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libasprintf >=0.25.1,<1.0a0 size: 34824 timestamp: 1751557562978 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libass-0.17.4-hcfe818d_0.conda @@ -12308,6 +13712,9 @@ packages: - libzlib >=1.3.1,<2.0a0 license: ISC purls: [] + run_exports: + weak: + - libass >=0.17.4,<0.17.5.0a0 size: 171287 timestamp: 1749328949722 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libattr-2.5.2-he30d5cf_1.conda @@ -12318,6 +13725,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - libattr >=2.5.2,<2.6.0a0 size: 54504 timestamp: 1773595923052 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libavif16-1.4.2-ha599f14_0.conda @@ -12332,6 +13742,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - libavif16 >=1.4.2,<2.0a0 size: 149006 timestamp: 1779847094511 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-8_haddc8a3_openblas.conda @@ -12350,6 +13763,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 size: 18843 timestamp: 1779859042591 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libboost-1.88.0-h5651608_7.conda @@ -12367,6 +13783,7 @@ packages: - boost-cpp <0.0a0 license: BSL-1.0 purls: [] + run_exports: {} size: 3167446 timestamp: 1768377608900 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libboost-devel-1.88.0-h37bb5a9_7.conda @@ -12379,6 +13796,9 @@ packages: - boost-cpp <0.0a0 license: BSL-1.0 purls: [] + run_exports: + weak: + - libboost >=1.88.0,<1.89.0a0 size: 38971 timestamp: 1768377704313 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libboost-headers-1.88.0-h8af1aa0_7.conda @@ -12388,6 +13808,7 @@ packages: - boost-cpp <0.0a0 license: BSL-1.0 purls: [] + run_exports: {} size: 14560170 timestamp: 1768377624033 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libboost-python-1.88.0-py312he84d598_7.conda @@ -12406,6 +13827,7 @@ packages: - py-boost <0.0a0 license: BSL-1.0 purls: [] + run_exports: {} size: 124777 timestamp: 1768377925702 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libboost-python-devel-1.88.0-py312h6ffa558_7.conda @@ -12422,6 +13844,9 @@ packages: - py-boost <0.0a0 license: BSL-1.0 purls: [] + run_exports: + weak: + - libboost-python >=1.88.0,<1.89.0a0 size: 19099 timestamp: 1768378287584 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.2.0-he30d5cf_1.conda @@ -12432,6 +13857,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 size: 80030 timestamp: 1764017273715 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.2.0-he30d5cf_1.conda @@ -12443,6 +13871,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 size: 33166 timestamp: 1764017282936 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.2.0-he30d5cf_1.conda @@ -12454,6 +13885,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 size: 309304 timestamp: 1764017292044 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcap-2.77-hf9559e3_1.conda @@ -12464,6 +13898,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libcap >=2.77,<2.78.0a0 size: 109458 timestamp: 1774335293336 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-8_hd72aa62_openblas.conda @@ -12479,6 +13916,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 size: 18817 timestamp: 1779859049133 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libccd-double-2.1-h2f0025b_3.conda @@ -12492,6 +13932,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libccd-double >=2.1,<2.2.0a0 size: 34226 timestamp: 1687341851768 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp21.1-21.1.8-default_he95a3c9_4.conda @@ -12504,32 +13947,42 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] + run_exports: + weak: + - libclang-cpp21.1 >=21.1.8,<21.2.0a0 size: 20653604 timestamp: 1777011685893 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.7-default_h2a92e99_1.conda - sha256: ff9e0d7dbe8abc4192cdbeb8f6339084250937fc68693ad4875782768aa5974b - md5: 4cc8ed1296217914e8de41a47863e83b +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.8-default_h0cc847a_3.conda + sha256: 16ff2afd00acf94320dcfacc7124bbb67ae542d48e5c5ac74627e8690df10dfa + md5: 483b80c996ae6e15317459ebd71d7033 depends: - - libgcc >=14 - - libllvm22 >=22.1.7,<22.2.0a0 - libstdcxx >=14 + - libgcc >=14 + - libllvm22 >=22.1.8,<22.2.0a0 license: Apache-2.0 WITH LLVM-exception - license_family: Apache + license_family: APACHE purls: [] - size: 21293598 - timestamp: 1780520948461 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.7-default_h3185f35_1.conda - sha256: 7583f7803a853cb3f411953d991a96b299ec647d3abeaf936303559354e9bab9 - md5: 8f07cb152d34e3dcfad8cd760e8f4f8a + run_exports: + weak: + - libclang-cpp22.1 >=22.1.8,<22.2.0a0 + size: 24213552 + timestamp: 1782358853037 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.8-default_hd92691d_3.conda + sha256: ef4c63c93751dd2582c4f72d9558faaec68eb26d149406373d5af8e509008c48 + md5: baa5eb601eacb3cc438aad5b343d9b61 depends: - - libgcc >=14 - - libllvm22 >=22.1.7,<22.2.0a0 + - libclang-cpp22.1 ==22.1.8 default_h0cc847a_3 - libstdcxx >=14 + - libgcc >=14 + - libllvm22 >=22.1.8,<22.2.0a0 license: Apache-2.0 WITH LLVM-exception - license_family: Apache + license_family: APACHE purls: [] - size: 12621183 - timestamp: 1780521084113 + run_exports: + weak: + - libclang13 >=22.1.8 + size: 14311328 + timestamp: 1782358853037 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda sha256: 41b04f995c9f63af8c4065a35931e46cbc2fdd6b9bf7e4c19f90d53cbb2bc8e5 md5: 67828c963b17db7dc989fe5d509ef04a @@ -12541,24 +13994,31 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - libcups >=2.3.3,<2.4.0a0 size: 4553739 timestamp: 1770903929794 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.20.0-hc57f145_0.conda - sha256: 1607d3caf58f7d9e9ad9e5f0841737d0cfa47b5501d4e36fbf98e1c645d7393e - md5: 88da514c8db1a7f6a05297941a897af2 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.21.0-h7c59cd8_2.conda + sha256: 5846fa724f4b8eb23751e347fc8b31775c0a28a7a34d1e44f081651613470512 + md5: 0a187db240c503afc7eb5bd865c7ff04 depends: - krb5 >=1.22.2,<1.23.0a0 - libgcc >=14 - libnghttp2 >=1.68.1,<2.0a0 + - libpsl >=0.22.0,<0.23.0a0 - libssh2 >=1.11.1,<2.0a0 - libzlib >=1.3.2,<2.0a0 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT purls: [] - size: 488942 - timestamp: 1777461485901 + run_exports: + weak: + - libcurl >=8.21.0,<9.0a0 + size: 505957 + timestamp: 1782911738398 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 md5: a9138815598fe6b91a1d6782ca657b0c @@ -12567,6 +14027,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 size: 71117 timestamp: 1761979776756 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdrm-2.4.127-he30d5cf_0.conda @@ -12578,6 +14041,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libdrm >=2.4.127,<2.5.0a0 size: 345283 timestamp: 1778975814771 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda @@ -12590,6 +14056,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - libedit >=3.1.20250104,<3.2.0a0 size: 148125 timestamp: 1738479808948 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libegl-1.7.0-hd24410f_3.conda @@ -12599,6 +14068,7 @@ packages: - libglvnd 1.7.0 hd24410f_3 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 54600 timestamp: 1779728234591 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libegl-devel-1.7.0-hd24410f_3.conda @@ -12610,6 +14080,9 @@ packages: - xorg-libx11 license: LicenseRef-libglvnd purls: [] + run_exports: + weak: + - libegl >=1.7.0,<2.0a0 size: 31552 timestamp: 1779728260736 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda @@ -12620,6 +14093,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - libev >=4.33,<4.34.0a0 size: 115123 timestamp: 1702146237623 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda @@ -12631,11 +14107,14 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libevent >=2.1.12,<2.1.13.0a0 size: 438992 timestamp: 1685726046519 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda - sha256: 1fc392b997c6ee2bd3226a7cd870d0edbcbb367e25f9f18dd4a7025fced6efc0 - md5: 513dd884361dfb8a554298ed69b58823 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_1.conda + sha256: 20a5726bc8705d91437c9e6ef83b30da64a1719b869656d20a1ee818333ea5ac + md5: fac3b65a605cd253037fdf3daf2de8d9 depends: - libgcc >=14 constrains: @@ -12643,8 +14122,9 @@ packages: license: MIT license_family: MIT purls: [] - size: 77140 - timestamp: 1779278671302 + run_exports: {} + size: 77649 + timestamp: 1781203572523 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 md5: 2f364feefb6a7c00423e80dcb12db62a @@ -12653,6 +14133,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libffi >=3.5.2,<3.6.0a0 size: 55952 timestamp: 1769456078358 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libflac-1.4.3-h2f0025b_0.conda @@ -12667,30 +14150,35 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libflac >=1.4.3,<1.5.0a0 size: 371550 timestamp: 1687765491794 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda - sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a - md5: a229e22d4d8814a07702b0919d8e6701 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_1.conda + sha256: db75d0fc080992dc67db8e24d7bb2a2f2a0b25bfce8870fa45a82a4b5f6111a2 + md5: a13e600f9d18488b1fd1257344dbfdaa depends: - libfreetype6 >=2.14.3 license: GPL-2.0-only OR FTL purls: [] - size: 8125 - timestamp: 1774301094057 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda - sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c - md5: b99ed99e42dafb27889483b3098cace7 + run_exports: {} + size: 8381 + timestamp: 1780933505754 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_1.conda + sha256: 34fe8276befd6c42956c4acd969caeddbdc7ea8e6ed054b8388709b6c3e94ba4 + md5: 426cc33f8745ce11a73baf73db3954a7 depends: - libgcc >=14 - - libpng >=1.6.55,<1.7.0a0 + - libpng >=1.6.58,<1.7.0a0 - libzlib >=1.3.2,<2.0a0 constrains: - freetype >=2.14.3 license: GPL-2.0-only OR FTL purls: [] - size: 422941 - timestamp: 1774301093473 + run_exports: {} + size: 424236 + timestamp: 1780933505195 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda sha256: 4592b096e553f67799ae70d4b6167eeda3ec74587d68c7aecbf4e7b1df136681 md5: f35b3f52d0a2ec4ffe3c89ba135cdb9a @@ -12702,6 +14190,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 622462 timestamp: 1778268755949 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda @@ -12712,6 +14201,9 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: + strong: + - libgcc size: 27738 timestamp: 1778268759211 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgd-2.3.3-h88aa843_12.conda @@ -12733,6 +14225,9 @@ packages: license: GD license_family: BSD purls: [] + run_exports: + weak: + - libgd >=2.3.3,<2.4.0a0 size: 195554 timestamp: 1766331786625 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgettextpo-0.25.1-h5ad3122_0.conda @@ -12743,6 +14238,9 @@ packages: license: GPL-3.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - libgettextpo >=0.25.1,<1.0a0 size: 225352 timestamp: 1751557555903 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgettextpo-devel-0.25.1-h5ad3122_0.conda @@ -12754,6 +14252,9 @@ packages: license: GPL-3.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - libgettextpo >=0.25.1,<1.0a0 size: 37460 timestamp: 1751557569909 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_19.conda @@ -12766,6 +14267,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 27728 timestamp: 1778268784621 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda @@ -12778,6 +14280,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 1487244 timestamp: 1778268767295 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgl-1.7.0-hd24410f_3.conda @@ -12788,6 +14291,7 @@ packages: - libglx 1.7.0 hd24410f_3 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 148112 timestamp: 1779728248678 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgl-devel-1.7.0-hd24410f_3.conda @@ -12798,23 +14302,29 @@ packages: - libglx-devel 1.7.0 hd24410f_3 license: LicenseRef-libglvnd purls: [] + run_exports: + weak: + - libgl >=1.7.0,<2.0a0 size: 116084 timestamp: 1779728257534 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.88.1-h96a7f82_2.conda - sha256: 050285afdb7bd98b1b8fb052af9da31fafde586a49d3b56dd33d5338b2d0e411 - md5: 16d72f76bf6fead4a29efb2fede0a06b +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.88.2-h96a7f82_0.conda + sha256: 6a13152a81513117b8d41bf64dea56c731d877bcced5a24fab738e3c0f9ac58c + md5: 31d404d8c0755d0f9062a4459f5a1084 depends: - libgcc >=14 - - libiconv >=1.18,<2.0a0 - - libzlib >=1.3.2,<2.0a0 - - pcre2 >=10.47,<10.48.0a0 - libffi >=3.5.2,<3.6.0a0 + - pcre2 >=10.47,<10.48.0a0 + - libzlib >=1.3.2,<2.0a0 + - libiconv >=1.18,<2.0a0 constrains: - glib >2.66 license: LGPL-2.1-or-later purls: [] - size: 4946648 - timestamp: 1778508920982 + run_exports: + weak: + - libglib >=2.88.2,<3.0a0 + size: 4943441 + timestamp: 1782464048865 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglu-9.0.3-h5ad3122_1.conda sha256: ddb72f17f6ec029069cddd2e489e63e371e75661cd2408509370508490bb23ad md5: 4d836b60421894bf9a6c77c8ca36782c @@ -12824,6 +14334,9 @@ packages: - libstdcxx >=13 license: SGI-B-2.0 purls: [] + run_exports: + weak: + - libglu >=9.0.3,<9.1.0a0 size: 310655 timestamp: 1748692200349 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglvnd-1.7.0-hd24410f_3.conda @@ -12831,6 +14344,7 @@ packages: md5: a2ad848c0aab2e326c6af08ea20502f4 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 146645 timestamp: 1779728228274 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglx-1.7.0-hd24410f_3.conda @@ -12841,6 +14355,7 @@ packages: - xorg-libx11 >=1.8.13,<2.0a0 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 76704 timestamp: 1779728242753 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglx-devel-1.7.0-hd24410f_3.conda @@ -12852,6 +14367,9 @@ packages: - xorg-xorgproto license: LicenseRef-libglvnd purls: [] + run_exports: + weak: + - libglx >=1.7.0,<2.0a0 size: 27651 timestamp: 1779728252006 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda @@ -12860,6 +14378,9 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: + strong: + - _openmp_mutex >=4.5 size: 587387 timestamp: 1778268674393 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-cmake3-3.5.5-h7ac5ae9_0.conda @@ -12872,6 +14393,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-cmake3 >=3.5.5,<4.0a0 size: 218713 timestamp: 1759138433911 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-cmake4-4.2.0-h7ac5ae9_1.conda @@ -12884,6 +14408,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-cmake4 >=4.2.0,<5.0a0 size: 218998 timestamp: 1759138590699 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-math7-7.5.2-h7ac5ae9_2.conda @@ -12899,6 +14426,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-math7 >=7.5.2,<8.0a0 size: 297443 timestamp: 1759147772705 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-tools-2.0.3-h7ac5ae9_1.conda @@ -12913,6 +14443,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-tools >=2.0.3,<3.0a0 size: 50928 timestamp: 1759148397768 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgz-utils2-2.2.1-h7ac5ae9_2.conda @@ -12926,8 +14459,55 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libgz-utils2 >=2.2.1,<3.0a0 size: 63399 timestamp: 1767701505720 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libharfbuzz-14.2.1-h3a99ef3_1.conda + sha256: ae1d16dd62f626c4dab1240a49f6b04e14e4f30140e5fb26bb835821dba114b6 + md5: 655cedd9626545089b9e9ead153cf619 + depends: + - cairo >=1.18.4,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=14 + - libglib >=2.88.2,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 1334601 + timestamp: 1782800489368 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libharfbuzz-devel-14.2.1-h3a99ef3_1.conda + sha256: 866b0132df7d080a7b2e3c44e4c79723f007db6c035b1e751612d29db698859b + md5: b6762f2c0386ba4606d5b2cba1e41ca8 + depends: + - cairo >=1.18.4,<2.0a0 + - freetype + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=14 + - libglib >=2.88.2,<3.0a0 + - libharfbuzz 14.2.1 h3a99ef3_1 + - libpng >=1.6.58,<1.7.0a0 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libharfbuzz >=14.2.1 + size: 2050496 + timestamp: 1782800511879 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwloc-2.13.0-default_ha95e27d_1000.conda sha256: 88888d99e81c93e7331f2eb0fec08b3c4a47a1bfa1c88b3e641f6568569b6261 md5: 974183f6420938051e2f3208922d057f @@ -12939,6 +14519,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libhwloc >=2.13.0,<2.13.1.0a0 size: 2453519 timestamp: 1770953713701 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwy-1.4.0-h0626a34_0.conda @@ -12949,6 +14532,9 @@ packages: - libstdcxx >=14 license: Apache-2.0 OR BSD-3-Clause purls: [] + run_exports: + weak: + - libhwy >=1.4.0,<1.5.0a0 size: 945401 timestamp: 1776989517303 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda @@ -12958,6 +14544,9 @@ packages: - libgcc >=14 license: LGPL-2.1-only purls: [] + run_exports: + weak: + - libiconv >=1.18,<2.0a0 size: 791226 timestamp: 1754910975665 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libidn2-2.3.8-h99ff5a0_1.conda @@ -12969,6 +14558,9 @@ packages: license: LGPL-2.0-only license_family: LGPL purls: [] + run_exports: + weak: + - libidn2 >=2,<3.0a0 size: 147165 timestamp: 1760387531719 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda @@ -12980,6 +14572,9 @@ packages: - jpeg <0.0.0a license: IJG AND BSD-3-Clause AND Zlib purls: [] + run_exports: + weak: + - libjpeg-turbo >=3.1.4.1,<4.0a0 size: 693143 timestamp: 1775962625956 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjxl-0.11.2-hbae46ee_1.conda @@ -12994,6 +14589,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libjxl >=0.11,<1.0a0 size: 1489188 timestamp: 1777065125935 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-8_h88aeb00_openblas.conda @@ -13009,6 +14607,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 size: 18828 timestamp: 1779859055749 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapacke-3.11.0-8_hb558247_openblas.conda @@ -13024,6 +14625,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - liblapacke >=3.11.0,<3.12.0a0 size: 18853 timestamp: 1779859062300 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm21-21.1.8-hfd2ba90_0.conda @@ -13039,11 +14643,14 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] + run_exports: + weak: + - libllvm21 >=21.1.8,<21.2.0a0 size: 43148553 timestamp: 1765930975162 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.7-hfd2ba90_0.conda - sha256: a9fa275214f02d0073c261081d57d72c8441e5efda865b31fc7fc003d2412082 - md5: 00e0b8a80486e38ed9e26c16a4e5a30b +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.8-hfd2ba90_1.conda + sha256: dc943f1730a27f5fb36682c9852f7196f671c3a9df4a0a7a8f7ba665637c9151 + md5: 6fc7875f99e39c80dca8fcdc60e6559e depends: - libgcc >=14 - libstdcxx >=14 @@ -13054,8 +14661,11 @@ packages: license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] - size: 43155847 - timestamp: 1780442966200 + run_exports: + weak: + - libllvm22 >=22.1.8,<22.2.0a0 + size: 43302008 + timestamp: 1781785783993 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libltdl-2.4.3a-h5ad3122_0.conda sha256: 079c7786458d2bda55c1c38a429c9bed50678f842284ca7645edcbe0dc13b456 md5: 6e13257812a29efb7cc84aa396c72902 @@ -13064,6 +14674,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - libltdl >=2.4.3a,<2.5.0a0 size: 41874 timestamp: 1740593981564 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda @@ -13075,6 +14688,9 @@ packages: - xz 5.8.3.* license: 0BSD purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 size: 126102 timestamp: 1775828008518 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-devel-5.8.3-he30d5cf_0.conda @@ -13085,6 +14701,9 @@ packages: - liblzma 5.8.3 he30d5cf_0 license: 0BSD purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 size: 493047 timestamp: 1775828222341 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmicrohttpd-1.0.5-h3543b8c_0.conda @@ -13096,6 +14715,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - libmicrohttpd >=1.0.5,<1.1.0a0 size: 296558 timestamp: 1779091126550 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmujoco-3.6.0-h2b9416c_0.conda @@ -13116,6 +14738,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libmujoco >=3.6.0,<3.6.1.0a0 size: 11116191 timestamp: 1773254871641 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnetcdf-4.9.3-nompi_h06de00c_104.conda @@ -13140,6 +14765,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libnetcdf >=4.9.3,<4.9.4.0a0 size: 893278 timestamp: 1770719134169 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.68.1-hd3077d7_0.conda @@ -13156,6 +14784,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 size: 726928 timestamp: 1773854039807 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda @@ -13166,6 +14797,9 @@ packages: license: LGPL-2.1-only license_family: GPL purls: [] + run_exports: + weak: + - libnsl >=2.0.1,<2.1.0a0 size: 34831 timestamp: 1750274211000 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libntlm-1.4-hf897c2e_1002.tar.bz2 @@ -13175,6 +14809,7 @@ packages: - libgcc-ng >=9.3.0 license: LGPL-2.1-or-later purls: [] + run_exports: {} size: 39449 timestamp: 1609781865660 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnuma-2.0.18-he30d5cf_3.conda @@ -13184,6 +14819,9 @@ packages: - libgcc >=14 license: LGPL-2.1-only purls: [] + run_exports: + weak: + - libnuma >=2.0.18,<3.0a0 size: 47706 timestamp: 1772781596087 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libogg-1.3.5-h86ecc28_1.conda @@ -13194,6 +14832,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libogg >=1.3.5,<1.4.0a0 size: 220653 timestamp: 1745826021156 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.33-pthreads_h9d3fd7e_0.conda @@ -13208,6 +14849,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libopenblas >=0.3.33,<1.0a0 size: 5121336 timestamp: 1776993423004 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopencv-4.12.0-qt6_py312h051a780_612.conda @@ -13258,6 +14902,9 @@ packages: purls: - pkg:pypi/opencv-python?source=hash-mapping - pkg:pypi/opencv-python-headless?source=hash-mapping + run_exports: + weak: + - libopencv >=4.12.0,<4.12.1.0a0 size: 21232907 timestamp: 1766496175059 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopengl-1.7.0-hd24410f_3.conda @@ -13267,6 +14914,7 @@ packages: - libglvnd 1.7.0 hd24410f_3 license: LicenseRef-libglvnd purls: [] + run_exports: {} size: 58759 timestamp: 1779728245599 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopengl-devel-1.7.0-hd24410f_3.conda @@ -13276,6 +14924,9 @@ packages: - libopengl 1.7.0 hd24410f_3 license: LicenseRef-libglvnd purls: [] + run_exports: + weak: + - libopengl >=1.7.0,<2.0a0 size: 16727 timestamp: 1779728254657 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-2025.4.1-h1915271_1.conda @@ -13287,6 +14938,9 @@ packages: - pugixml >=1.15,<1.16.0a0 - tbb >=2022.3.0 purls: [] + run_exports: + weak: + - libopenvino >=2025.4.1,<2025.4.2.0a0 size: 5665824 timestamp: 1769898242484 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-arm-cpu-plugin-2025.4.1-h1915271_1.conda @@ -13299,6 +14953,7 @@ packages: - pugixml >=1.15,<1.16.0a0 - tbb >=2022.3.0 purls: [] + run_exports: {} size: 10070230 timestamp: 1769898273278 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-auto-batch-plugin-2025.4.1-h3d5001d_1.conda @@ -13310,6 +14965,7 @@ packages: - libstdcxx >=14 - tbb >=2022.3.0 purls: [] + run_exports: {} size: 111764 timestamp: 1769898305839 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-auto-plugin-2025.4.1-h3d5001d_1.conda @@ -13321,6 +14977,7 @@ packages: - libstdcxx >=14 - tbb >=2022.3.0 purls: [] + run_exports: {} size: 235829 timestamp: 1769898319432 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-hetero-plugin-2025.4.1-he07c6df_1.conda @@ -13332,6 +14989,7 @@ packages: - libstdcxx >=14 - pugixml >=1.15,<1.16.0a0 purls: [] + run_exports: {} size: 204116 timestamp: 1769898333070 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-ir-frontend-2025.4.1-he07c6df_1.conda @@ -13343,6 +15001,9 @@ packages: - libstdcxx >=14 - pugixml >=1.15,<1.16.0a0 purls: [] + run_exports: + weak: + - libopenvino-ir-frontend >=2025.4.1,<2025.4.2.0a0 size: 190629 timestamp: 1769898346574 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-onnx-frontend-2025.4.1-h07d5dce_1.conda @@ -13356,6 +15017,9 @@ packages: - libprotobuf >=6.31.1,<6.31.2.0a0 - libstdcxx >=14 purls: [] + run_exports: + weak: + - libopenvino-onnx-frontend >=2025.4.1,<2025.4.2.0a0 size: 1692258 timestamp: 1769898360577 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-paddle-frontend-2025.4.1-h07d5dce_1.conda @@ -13369,6 +15033,9 @@ packages: - libprotobuf >=6.31.1,<6.31.2.0a0 - libstdcxx >=14 purls: [] + run_exports: + weak: + - libopenvino-paddle-frontend >=2025.4.1,<2025.4.2.0a0 size: 675934 timestamp: 1769898376449 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-pytorch-frontend-2025.4.1-hfae3067_1.conda @@ -13379,6 +15046,9 @@ packages: - libopenvino 2025.4.1 h1915271_1 - libstdcxx >=14 purls: [] + run_exports: + weak: + - libopenvino-pytorch-frontend >=2025.4.1,<2025.4.2.0a0 size: 1142325 timestamp: 1769898392266 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-tensorflow-frontend-2025.4.1-h38473e3_1.conda @@ -13393,6 +15063,9 @@ packages: - libstdcxx >=14 - snappy >=1.2.2,<1.3.0a0 purls: [] + run_exports: + weak: + - libopenvino-tensorflow-frontend >=2025.4.1,<2025.4.2.0a0 size: 1224764 timestamp: 1769898407205 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenvino-tensorflow-lite-frontend-2025.4.1-hfae3067_1.conda @@ -13403,6 +15076,9 @@ packages: - libopenvino 2025.4.1 h1915271_1 - libstdcxx >=14 purls: [] + run_exports: + weak: + - libopenvino-tensorflow-lite-frontend >=2025.4.1,<2025.4.2.0a0 size: 456871 timestamp: 1769898421788 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopus-1.6.1-h80f16a2_0.conda @@ -13413,6 +15089,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libopus >=1.6.1,<2.0a0 size: 383586 timestamp: 1768497303687 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpciaccess-0.19-he30d5cf_0.conda @@ -13423,6 +15102,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libpciaccess >=0.19,<0.20.0a0 size: 30294 timestamp: 1773533057559 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda @@ -13433,21 +15115,27 @@ packages: - libzlib >=1.3.2,<2.0a0 license: zlib-acknowledgement purls: [] + run_exports: + weak: + - libpng >=1.6.58,<1.7.0a0 size: 341202 timestamp: 1776315188425 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpq-18.4-hccacd55_0.conda - sha256: e12b5e6b1c4faffddaa8fa96ca4c75826e1027b8fde30bd89f606c0eb64e2632 - md5: ceebd82dd3ab72dd8d0b365b5bd4327b +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpq-18.4-hccacd55_1.conda + sha256: 8badce81df7b86fde16ad28dea9d5d65ebe318d6eb48865d10fbd4bd296cd152 + md5: aa592f45ebe4bb5a4dd228fdf006b617 depends: - icu >=78.3,<79.0a0 - krb5 >=1.22.2,<1.23.0a0 - libgcc >=14 - openldap >=2.6.13,<2.7.0a0 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 license: PostgreSQL purls: [] - size: 2760912 - timestamp: 1778786280914 + run_exports: + weak: + - libpq >=18.4,<19.0a0 + size: 2911832 + timestamp: 1782580350945 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-6.31.1-h61c7711_5.conda sha256: 08f0fd616f4482963e27e0cd7fd0d1913f33a153d3d97028beb8bc2892ff30a7 md5: ce4282bd8d1af8a2c70d4d05223b89f7 @@ -13460,8 +15148,44 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libprotobuf >=6.31.1,<6.31.2.0a0 size: 3897821 timestamp: 1780003417336 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpsl-0.22.0-h504d594_0.conda + sha256: 8871c428d0c97a75806dec9aee508fe93ce137a3a081866d9c752e5c0f83b091 + md5: 93b1727d5d61b9d70163dfcf5d9aafb9 + depends: + - icu >=78.3,<79.0a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libpsl >=0.22.0,<0.23.0a0 + size: 84305 + timestamp: 1782394815323 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libraqm-0.10.5-hd2f8911_1.conda + sha256: b287b67ba86d625bdaae919bac0a62ca6f5bc61509f034003df3c6b40f584a92 + md5: bf7fa2b700ba2c7b682aec5db14043c7 + depends: + - libgcc >=14 + - __glibc >=2.28,<3.0.a0 + - fribidi >=1.0.16,<2.0a0 + - libharfbuzz >=14.2.1 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libraqm >=0.10.5,<0.11.0a0 + size: 29528 + timestamp: 1782807084739 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libraw-0.22.1-h6c2e892_0.conda sha256: 8b8da9dbd2290ba02185dd6dd5a83a514ef3c0f4f65feb395bd7a41b67e5067a md5: 8a0b1ef545682ef7bdb938bfde168f56 @@ -13475,6 +15199,9 @@ packages: - libjpeg-turbo >=3.1.2,<4.0a0 license: LGPL-2.1-only purls: [] + run_exports: + weak: + - libraw >=0.22.1,<0.23.0a0 size: 803298 timestamp: 1775541734284 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/librsvg-2.62.3-hf685517_0.conda @@ -13494,6 +15221,9 @@ packages: - __glibc >=2.17 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - librsvg >=2.62.3,<3.0a0 size: 3052373 timestamp: 1780456154830 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-14.3.0-hedb4206_19.conda @@ -13505,6 +15235,9 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: + weak: + - libsanitizer 14.3.0 size: 7199495 timestamp: 1778268550110 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-15.2.0-he19c465_19.conda @@ -13515,6 +15248,9 @@ packages: - libstdcxx >=15.2.0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + run_exports: + weak: + - libsanitizer 15.2.0 size: 7067965 timestamp: 1778268796086 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsdformat14-14.8.0-py312h39f64fe_2.conda @@ -13533,6 +15269,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libsdformat14 >=14.8.0,<15.0a0 size: 1173519 timestamp: 1759339827373 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsndfile-1.2.2-h79657aa_1.conda @@ -13550,6 +15289,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - libsndfile >=1.2.2,<1.3.0a0 size: 396501 timestamp: 1695747749825 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsodium-1.0.22-h80f16a2_1.conda @@ -13559,19 +15301,25 @@ packages: - libgcc >=14 license: ISC purls: [] + run_exports: + weak: + - libsodium >=1.0.22,<1.0.23.0a0 size: 283426 timestamp: 1779163468728 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.2-h10b116e_0.conda - sha256: 8d78a9e60ab6d43aa80add48d66aadaa1f2a35833e646d0bb253036f4079ade9 - md5: aec62a5e5f0892cc4cf80f266f3818ee +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.3-h10b116e_0.conda + sha256: a835400072fb638fb582ee9fc2271169da84cbcad664d28b852610201116027e + md5: 2cd50877f494b34383af22560ced8b04 depends: - icu >=78.3,<79.0a0 - libgcc >=14 - libzlib >=1.3.2,<2.0a0 license: blessing purls: [] - size: 962294 - timestamp: 1780574462426 + run_exports: + weak: + - libsqlite >=3.53.3,<4.0a0 + size: 968420 + timestamp: 1782519054102 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda sha256: 1e289bcce4ee6a5817a19c66e296f3c644dcfa6e562e5c1cba807270798814e7 md5: eecc495bcfdd9da8058969656f916cc2 @@ -13582,6 +15330,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libssh2 >=1.11.1,<2.0a0 size: 311396 timestamp: 1745609845915 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda @@ -13594,6 +15345,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 5546559 timestamp: 1778268777463 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_19.conda @@ -13604,6 +15356,9 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: + strong: + - libstdcxx size: 27803 timestamp: 1778268813278 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsystemd0-257.13-hf9559e3_0.conda @@ -13614,6 +15369,7 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: {} size: 516600 timestamp: 1773797150163 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtasn1-4.21.0-he30d5cf_0.conda @@ -13623,6 +15379,9 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libtasn1 >=4.21.0,<5.0a0 size: 126001 timestamp: 1768299601532 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtheora-1.1.1-h68df207_1006.conda @@ -13637,6 +15396,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libtheora >=1.1.1,<1.2.0a0 size: 335103 timestamp: 1719667812650 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda @@ -13654,6 +15416,9 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: HPND purls: [] + run_exports: + weak: + - libtiff >=4.7.1,<4.8.0a0 size: 488407 timestamp: 1762022048105 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtool-2.5.4-h5ad3122_0.conda @@ -13665,6 +15430,7 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: {} size: 416270 timestamp: 1740594010519 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libudev1-257.13-hf9559e3_0.conda @@ -13675,6 +15441,7 @@ packages: - libgcc >=14 license: LGPL-2.1-or-later purls: [] + run_exports: {} size: 156357 timestamp: 1773797159424 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libunistring-0.9.10-hf897c2e_0.tar.bz2 @@ -13684,6 +15451,9 @@ packages: - libgcc-ng >=9.3.0 license: GPL-3.0-only OR LGPL-3.0-only purls: [] + run_exports: + weak: + - libunistring >=0,<1.0a0 size: 1409624 timestamp: 1626959749923 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libunwind-1.8.3-h6470e1d_0.conda @@ -13695,6 +15465,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libunwind >=1.8.3,<1.9.0a0 size: 94555 timestamp: 1757032278900 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liburcu-0.14.0-h0a1ffab_0.conda @@ -13705,6 +15478,9 @@ packages: license: LGPL-2.0-or-later license_family: LGPL purls: [] + run_exports: + weak: + - liburcu >=0.14.0,<0.15.0a0 size: 197399 timestamp: 1718888513454 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liburing-2.14-hfefdfc9_0.conda @@ -13716,6 +15492,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - liburing >=2.14,<2.15.0a0 size: 155011 timestamp: 1770567701524 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libusb-1.0.29-h06eaf92_0.conda @@ -13726,18 +15505,24 @@ packages: - libudev1 >=257.4 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libusb >=1.0.29,<2.0a0 size: 93129 timestamp: 1748856228398 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda - sha256: 1628839b062e98b2192857d4da8496ac9ac6b0dbb77aa040c34efc9192c440ee - md5: 0f42f9fedd2a32d798de95a7f65c456f +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.2-h1022ec0_0.conda + sha256: 7663489f97c104ae3814db10f384932c74b439f3c1fd4247e4fe3599830c090a + md5: 58fa42bc4bc71fc329889497ec15effb depends: - libgcc >=14 license: BSD-3-Clause license_family: BSD purls: [] - size: 43453 - timestamp: 1779118526838 + run_exports: + weak: + - libuuid >=2.42.2,<3.0a0 + size: 43248 + timestamp: 1781625528371 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.52.1-h80f16a2_0.conda sha256: 3e2ead35f47d01364031f323f1be984018c8f19a3a264f952ddcd043685a1c86 md5: ac7bcbd2c77691cd6d1ede8c029e8c8a @@ -13746,6 +15531,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 size: 456627 timestamp: 1779396031450 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvorbis-1.3.7-h7ac5ae9_2.conda @@ -13759,6 +15547,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libvorbis >=1.3.7,<1.4.0a0 size: 289391 timestamp: 1753879417231 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvpx-1.15.2-hfae3067_0.conda @@ -13770,6 +15561,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libvpx >=1.15.2,<1.16.0a0 size: 1296382 timestamp: 1762012332100 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvulkan-loader-1.4.341.0-h8b8848b_0.conda @@ -13785,6 +15579,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libvulkan-loader >=1.4.341.0,<2.0a0 size: 217655 timestamp: 1770077141862 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda @@ -13797,6 +15594,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 size: 359496 timestamp: 1752160685488 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda @@ -13810,6 +15610,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libxcb >=1.17.0,<2.0a0 size: 397493 timestamp: 1727280745441 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda @@ -13819,6 +15622,9 @@ packages: - libgcc-ng >=12 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - libxcrypt >=4.4.36 size: 114269 timestamp: 1702724369203 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxkbcommon-1.13.2-h3c6a4c8_0.conda @@ -13835,6 +15641,9 @@ packages: license: MIT/X11 Derivative license_family: MIT purls: [] + run_exports: + weak: + - libxkbcommon >=1.13.2,<2.0a0 size: 875994 timestamp: 1780213408784 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.3-h79dcc73_0.conda @@ -13851,6 +15660,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 601948 timestamp: 1776376758674 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.3-h869d058_0.conda @@ -13866,6 +15676,10 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.3 size: 48101 timestamp: 1776376766341 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxslt-1.1.43-h6700d25_1.conda @@ -13878,6 +15692,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - libxslt >=1.1.43,<2.0a0 size: 253367 timestamp: 1757964660396 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzenohc-1.7.2-hd661084_0.conda @@ -13891,6 +15708,9 @@ packages: - __glibc >=2.17 license: Apache-2.0 OR EPL-2.0 purls: [] + run_exports: + weak: + - libzenohc >=1.7.2,<1.7.3.0a0 size: 4342299 timestamp: 1767984665690 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzip-1.11.2-h3e8f909_0.conda @@ -13904,6 +15724,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - libzip >=1.11.2,<2.0a0 size: 117603 timestamp: 1730442215935 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda @@ -13914,6 +15737,9 @@ packages: license: Zlib license_family: Other purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 size: 69833 timestamp: 1774072605429 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lodepng-20220109-hdd96247_0.tar.bz2 @@ -13924,6 +15750,9 @@ packages: - libstdcxx-ng >=12 license: Zlib purls: [] + run_exports: + weak: + - lodepng >=20220109,<20220110.0a0 size: 104299 timestamp: 1655914369153 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lttng-ust-2.13.9-h8d236e2_0.conda @@ -13935,6 +15764,9 @@ packages: - liburcu >=0.14.0,<0.15.0a0 license: LGPL-2.1-only purls: [] + run_exports: + weak: + - lttng-ust >=2.13.9,<2.14.0a0 size: 419653 timestamp: 1745310243392 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lxml-6.1.1-py312hfe2c7ef_0.conda @@ -13952,6 +15784,7 @@ packages: license: BSD-3-Clause and MIT-CMU purls: - pkg:pypi/lxml?source=hash-mapping + run_exports: {} size: 1484640 timestamp: 1779194923178 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-4.4.5-py312he78555a_1.conda @@ -13968,6 +15801,7 @@ packages: license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping + run_exports: {} size: 51745 timestamp: 1765026442641 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.10.0-h5ad3122_1.conda @@ -13979,6 +15813,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - lz4-c >=1.10.0,<1.11.0a0 size: 184953 timestamp: 1733740984533 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda @@ -13989,6 +15826,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - lzo >=2.10,<3.0a0 size: 190187 timestamp: 1753889356434 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/make-4.4.1-h2a6d0cb_2.conda @@ -13999,6 +15839,7 @@ packages: license: GPL-3.0-or-later license_family: GPL purls: [] + run_exports: {} size: 528318 timestamp: 1727801707353 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py312hd077ced_1.conda @@ -14014,13 +15855,14 @@ packages: license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping + run_exports: {} size: 26305 timestamp: 1772446326927 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-3.10.9-py312h8025657_0.conda - sha256: 3b61ebdddd86f972acefd8717f8b017ba2d32c421240ad954322b0a0a0aa931f - md5: 92cfc26183bc7d84c62a3f7fd8fd73ca +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-3.11.0-py312h8025657_1.conda + sha256: 8d19f9d3c7df6d76da77a39c774320b1f15f42b69f76d540fae6cfd82c266487 + md5: 5c83f56631a764edd9e3f534e10ef098 depends: - - matplotlib-base >=3.10.9,<3.10.10.0a0 + - matplotlib-base >=3.11.0,<3.11.1.0a0 - pyside6 >=6.7.2 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 @@ -14028,11 +15870,12 @@ packages: license: PSF-2.0 license_family: PSF purls: [] - size: 17860 - timestamp: 1777000675377 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-base-3.10.9-py312h9d0c5ba_0.conda - sha256: 7bad069609cd69159e2658ce7c89c12b3d93b9b6e7e27ef7de31a1daa0f0b092 - md5: 02f91252126f398a45af7c9ff5ac089b + run_exports: {} + size: 14868 + timestamp: 1782829508519 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-base-3.11.0-py312h7ee55d7_1.conda + sha256: 98b98c5022a66c29805278a56380107b55bb44c9b358d35d93f0bfe0f8069efb + md5: bd250e5754cb3ad603ab680ffd28b7a4 depends: - contourpy >=1.0.1 - cycler >=0.10 @@ -14042,14 +15885,14 @@ packages: - libfreetype >=2.14.3 - libfreetype6 >=2.14.3 - libgcc >=14 + - libraqm >=0.10.5,<0.11.0a0 - libstdcxx >=14 - numpy >=1.23 - - numpy >=1.23,<3 + - numpy >=1.25,<3 - packaging >=20.0 - pillow >=8 - pyparsing >=2.3.1 - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - python-dateutil >=2.7 - python_abi 3.12.* *_cp312 - qhull >=2020.2,<2020.3.0a0 @@ -14058,24 +15901,25 @@ packages: license_family: PSF purls: - pkg:pypi/matplotlib?source=hash-mapping - size: 8373442 - timestamp: 1777000661173 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.13.3-py310he8189be_0.conda + run_exports: {} + size: 8975302 + timestamp: 1782829494907 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.14.1-py310he8189be_0.conda noarch: python - sha256: f51d24036ccfba324290daf1c60e5c12a909f3fcb3f437a473f751343ee84190 - md5: f88944037e9cdf5d70ce75eb31157d20 + sha256: 54435e557d2160d0307f69b4ac7926b855446e97cc721d65903da760be9dcb03 + md5: 7bb9ef1f1d810d006c20c9977676be96 depends: - python - tomli >=1.1.0 - libgcc >=14 - - openssl >=3.5.6,<4.0a0 + - openssl >=3.5.7,<4.0a0 constrains: - __glibc >=2.17 license: MIT license_family: MIT run_exports: {} - size: 9711678 - timestamp: 1778496705875 + size: 9724016 + timestamp: 1781871507536 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mesalib-26.0.3-h455aa48_0.conda sha256: e6cf93625ef33463cb08d0e604d8d0be661751d014cf6d5e0e75733b4b992b39 md5: 933a4f20f282b1a9b67dce5852fad614 @@ -14095,6 +15939,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - mesalib >=26.0.3,<26.1.0a0 size: 2876962 timestamp: 1773867973610 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mpg123-1.32.9-h65af167_0.conda @@ -14106,23 +15953,27 @@ packages: license: LGPL-2.1-only license_family: LGPL purls: [] + run_exports: + weak: + - mpg123 >=1.32.9,<1.33.0a0 size: 558708 timestamp: 1730581372400 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py312h4f740d2_1.conda - sha256: 54d29951b12731bbcd01b914f101566fc00da060151e11c295b8eb698d219897 - md5: fa2dab79048dfea842cb4f6eac8301fb +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.2.1-py312hf18b547_1.conda + sha256: dfd1fe17d91863299d7e8673dc11082f3cad5501bbc1c0050765321b6a06f1fd + md5: 4ebf3dfcf27d10f06b247b71fb0aafdf depends: - - libgcc >=14 + - python + - python 3.12.* *_cpython - libstdcxx >=14 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython + - libgcc >=14 - python_abi 3.12.* *_cp312 license: Apache-2.0 - license_family: Apache + license_family: APACHE purls: - pkg:pypi/msgpack?source=hash-mapping - size: 99305 - timestamp: 1762504246142 + run_exports: {} + size: 113665 + timestamp: 1782460796476 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-3.6.0-h6fc1a30_0.conda sha256: 98a69970ef80d88e1ac932444f2c2ea7c3aed8de723cc93ab44209b274a7115c md5: ee31f32f4943c13983d548e52d9bcdf2 @@ -14134,6 +15985,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 17815 timestamp: 1773254871641 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-python-3.6.0-np2py312h7d9f038_0.conda @@ -14167,6 +16019,7 @@ packages: license_family: APACHE purls: - pkg:pypi/mujoco?source=hash-mapping + run_exports: {} size: 2681953 timestamp: 1773254871641 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-samples-3.6.0-h21f88d6_0.conda @@ -14181,6 +16034,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 58442 timestamp: 1773254871641 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mujoco-simulate-3.6.0-hd58b8c5_0.conda @@ -14191,6 +16045,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 17656 timestamp: 1773254871641 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/multidict-6.7.1-py312ha4530ae_0.conda @@ -14205,6 +16060,7 @@ packages: license_family: APACHE purls: - pkg:pypi/multidict?source=hash-mapping + run_exports: {} size: 102146 timestamp: 1771610849986 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.20.2-py312h996f985_0.conda @@ -14224,6 +16080,7 @@ packages: license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping + run_exports: {} size: 19714903 timestamp: 1776801935276 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nanoflann-1.6.1-h17cf362_0.conda @@ -14231,6 +16088,7 @@ packages: md5: 42cc1fd8821a5a824a643a4ed055e24e license: BSD purls: [] + run_exports: {} size: 25905 timestamp: 1728332554740 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda @@ -14240,6 +16098,9 @@ packages: - libgcc >=14 license: X11 AND BSD-3-Clause purls: [] + run_exports: + weak: + - ncurses >=6.6,<7.0a0 size: 960036 timestamp: 1777422174534 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nettle-3.10.1-hfdb7b1a_0.conda @@ -14250,6 +16111,9 @@ packages: - gmp >=6.3.0,<7.0a0 license: GPL-2.0-or-later OR LGPL-3.0-or-later purls: [] + run_exports: + weak: + - nettle >=3.10.1,<3.11.0a0 size: 1151473 timestamp: 1748012425058 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda @@ -14261,6 +16125,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 182666 timestamp: 1763688214250 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nlohmann_json-3.12.0-h7ac5ae9_1.conda @@ -14271,6 +16136,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 136931 timestamp: 1758194316834 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda @@ -14282,6 +16148,9 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: + weak: + - nspr >=4.38,<5.0a0 size: 235140 timestamp: 1762350120355 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda @@ -14296,6 +16165,9 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: + weak: + - nss >=3.118,<4.0a0 size: 2061869 timestamp: 1763490303490 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py312h470d778_0.conda @@ -14316,6 +16188,9 @@ packages: license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping + run_exports: + weak: + - numpy >=1.26.4,<2.0a0 size: 6614296 timestamp: 1707225994762 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/octomap-1.10.0-h17cf362_0.conda @@ -14327,6 +16202,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - octomap >=1.10.0,<1.11.0a0 size: 239860 timestamp: 1728635298509 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/onnxruntime-1.26.0-py312hc28d7f2_0_cpu.conda @@ -14345,6 +16223,7 @@ packages: license: MIT AND BSL-1.0 purls: - pkg:pypi/onnxruntime?source=hash-mapping + run_exports: {} size: 14039987 timestamp: 1778967442914 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/opencv-4.12.0-qt6_py312h750a492_612.conda @@ -14358,34 +16237,41 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: {} size: 27887 timestamp: 1766496259667 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openexr-3.4.12-hda3a014_0.conda - sha256: 12e3d695f721bc1b7a9b9b256c89610b5df0b47b9a51d80cedd30b31ea6018fc - md5: 0b3bcd620bea1e0f3603d62e40ea9405 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openexr-3.4.13-h95ec230_1.conda + sha256: fb008a0d6554d3d84bf78aaf66a167b833b9af6147515b4f4bbfd8b6983bc66f + md5: cecda49f5448d9b737f4adc25514777d depends: - libstdcxx >=14 - libgcc >=14 - - libzlib >=1.3.2,<2.0a0 - - openjph >=0.27.3,<0.28.0a0 - - libdeflate >=1.25,<1.26.0a0 + - openjph >=0.30.1,<0.31.0a0 - imath >=3.2.2,<3.2.3.0a0 + - libdeflate >=1.25,<1.26.0a0 + - libzlib >=1.3.2,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] - size: 1176484 - timestamp: 1779680405266 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openh264-2.6.0-h0564a2a_0.conda - sha256: 3b7a519e3b7d7721a0536f6cba7f1909b878c71962ee67f02242958314748341 - md5: 0abed5d78c07a64e85c54f705ba14d30 + run_exports: + weak: + - openexr >=3.4.13,<3.5.0a0 + size: 1185348 + timestamp: 1782198403352 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openh264-2.6.0-h663e864_1.conda + sha256: c90d20ddcf28537ea6c1bd1c26a7abcba6baf9d7cdec493daa04bf0a968d1264 + md5: 0d86d4becd3cd1ce48011f71099211be depends: - - libgcc >=13 - - libstdcxx >=13 + - libgcc >=14 + - libstdcxx >=14 license: BSD-2-Clause license_family: BSD purls: [] - size: 774512 - timestamp: 1739400731652 + run_exports: + weak: + - openh264 >=2.6.0,<2.6.1.0a0 + size: 795565 + timestamp: 1782685979198 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda sha256: bd1bc8bdde5e6c5cbac42d462b939694e40b59be6d0698f668515908640c77b8 md5: cea962410e327262346d48d01f05936c @@ -14398,11 +16284,14 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - openjpeg >=2.5.4,<3.0a0 size: 392636 timestamp: 1758489353577 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjph-0.27.4-h55827e0_0.conda - sha256: 1ab7452fbe3072bb4e5229dd7af430bff15421171315e81cd93c280910f5034d - md5: 83d45f7a9b54c19b120ac2929149bf72 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjph-0.30.1-h55827e0_0.conda + sha256: 12f6ac15e3bd4de872a28f096817c6c66bd9a058e7d684ee1e57aff118004d42 + md5: 6d8f94ef9f90c0b202d31043a9aab1a8 depends: - libstdcxx >=14 - libgcc >=14 @@ -14410,8 +16299,11 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] - size: 231064 - timestamp: 1780596799608 + run_exports: + weak: + - openjph >=0.30.1,<0.31.0a0 + size: 238874 + timestamp: 1782091147195 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openldap-2.6.13-h2fb54aa_0.conda sha256: 08fab1d144a9790763f30bd44ac4a2f288703ad668d8c31d339ddea23e981147 md5: 67eea19865a3463f75ca0d3a1d096350 @@ -14424,19 +16316,25 @@ packages: license: OLDAP-2.8 license_family: BSD purls: [] + run_exports: + weak: + - openldap >=2.6.13,<2.7.0a0 size: 911524 timestamp: 1775741371965 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda - sha256: 348cb74c1530ac241215d047ef65d134cf797af935c97a68655319362b7e6a01 - md5: 3b129669089e4d6a5c6871dbb4669b99 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.3-h546c87b_0.conda + sha256: da4a5df42614166b69c2f6d8602fc1425f7aaa699f77c3bafb5c7fe69b3d9fb7 + md5: fa6260b3e6eababf6ca85a7eb3336383 depends: - ca-certificates - libgcc >=14 license: Apache-2.0 license_family: Apache purls: [] - size: 3706406 - timestamp: 1775589602258 + run_exports: + weak: + - openssl >=3.6.3,<4.0a0 + size: 3704664 + timestamp: 1781069675555 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orocos-kdl-1.5.3-hc398517_1.conda sha256: 7b2d90bf1c8b9f19f5bbe5e3e32a6a76b71fc6fc77093984bed97989d5eac105 md5: e50880e5906e4c67c9ef89140b296d00 @@ -14448,6 +16346,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - orocos-kdl >=1.5.3,<1.6.0a0 size: 376844 timestamp: 1778003961570 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/p11-kit-0.26.2-h376a255_0.conda @@ -14460,6 +16361,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - p11-kit >=0.26.2,<0.27.0a0 size: 5180065 timestamp: 1770420952184 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pango-1.56.4-h8547ced_1.conda @@ -14480,6 +16384,9 @@ packages: - libzlib >=1.3.2,<2.0a0 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - pango >=1.56.4,<2.0a0 size: 470441 timestamp: 1774284032397 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcl-1.15.1-h4720788_7.conda @@ -14505,6 +16412,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - pcl >=1.15.1,<1.15.2.0a0 size: 17314345 timestamp: 1772142882164 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre-8.45-h01db608_0.tar.bz2 @@ -14516,6 +16426,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - pcre >=8.45,<9.0a0 size: 249883 timestamp: 1623793306266 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda @@ -14528,6 +16441,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 size: 1166552 timestamp: 1763655534263 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda @@ -14539,6 +16455,11 @@ packages: - libxcrypt >=4.4.36 license: GPL-1.0-or-later OR Artistic-1.0-Perl purls: [] + run_exports: + weak: + - perl >=5.32.1,<5.33.0a0 *_perl5 + noarch: + - perl >=5.32.1,<6.0a0 *_perl5 size: 13338804 timestamp: 1703310557094 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-11.3.0-py312h6e23c8a_3.conda @@ -14561,6 +16482,7 @@ packages: license: HPND purls: - pkg:pypi/pillow?source=hash-mapping + run_exports: {} size: 1004533 timestamp: 1758208960718 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda @@ -14573,6 +16495,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 size: 357913 timestamp: 1754665583353 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pkg-config-0.29.2-hce167ba_1009.conda @@ -14584,6 +16509,7 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: {} size: 54834 timestamp: 1720806008171 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/popt-1.19-h90929bb_0.conda @@ -14595,6 +16521,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - popt >=1.19,<2.0a0 size: 179869 timestamp: 1765446323424 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/portaudio-19.7.0-h9d01bbc_0.conda @@ -14607,6 +16536,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - portaudio >=19.7.0,<19.8.0a0 size: 82419 timestamp: 1730364154715 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/proj-9.7.1-hd211770_3.conda @@ -14626,6 +16558,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - proj >=9.7.1,<9.8.0a0 size: 3509940 timestamp: 1770890762505 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/propcache-0.5.2-py312ha4530ae_0.conda @@ -14640,6 +16575,7 @@ packages: license_family: APACHE purls: - pkg:pypi/propcache?source=hash-mapping + run_exports: {} size: 52099 timestamp: 1780037769244 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/protobuf-6.31.1-py312h07dbafa_2.conda @@ -14660,6 +16596,7 @@ packages: license_family: BSD purls: - pkg:pypi/protobuf?source=hash-mapping + run_exports: {} size: 487892 timestamp: 1760393502978 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-7.2.2-py312hd41f8a7_0.conda @@ -14674,6 +16611,7 @@ packages: license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping + run_exports: {} size: 230283 timestamp: 1769678159757 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda @@ -14684,6 +16622,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 8342 timestamp: 1726803319942 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pugixml-1.15-h6ef32b0_0.conda @@ -14695,6 +16634,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - pugixml >=1.15,<1.16.0a0 size: 113424 timestamp: 1737355438448 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pulseaudio-17.0-h3dd60a8_3.conda @@ -14707,6 +16649,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - pulseaudio-client >=17.0,<17.1.0a0 size: 18473 timestamp: 1763148328578 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pulseaudio-client-17.0-hcf98165_3.conda @@ -14725,6 +16670,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - pulseaudio-client >=17.0,<17.1.0a0 size: 760306 timestamp: 1763148231117 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pulseaudio-daemon-17.0-hb9404ba_3.conda @@ -14756,6 +16704,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - pulseaudio-daemon >=17.0,<17.1.0a0 size: 897388 timestamp: 1763148315136 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/py-opencv-4.12.0-qt6_py312h1743b20_612.conda @@ -14770,6 +16721,9 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - py-opencv >=4.12.0,<5.0a0 size: 1154560 timestamp: 1766496246197 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pybullet-3.25-py312h88173f1_5.conda @@ -14787,6 +16741,7 @@ packages: license: Zlib purls: - pkg:pypi/pybullet?source=hash-mapping + run_exports: {} size: 63132892 timestamp: 1761046679147 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycairo-1.29.0-py312h1f35134_1.conda @@ -14802,6 +16757,7 @@ packages: license: LGPL-2.1-only OR MPL-1.1 purls: - pkg:pypi/pycairo?source=hash-mapping + run_exports: {} size: 123069 timestamp: 1770727863809 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pymongo-4.17.0-py312hfcd9f9b_0.conda @@ -14817,6 +16773,7 @@ packages: license_family: APACHE purls: - pkg:pypi/pymongo?source=hash-mapping + run_exports: {} size: 2384320 timestamp: 1776767392027 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pynacl-1.6.2-py312h6ecc08e_2.conda @@ -14834,6 +16791,7 @@ packages: license_family: Apache purls: - pkg:pypi/pynacl?source=hash-mapping + run_exports: {} size: 1183872 timestamp: 1778984925118 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyqt-5.15.11-py312hc13527c_2.conda @@ -14866,6 +16824,9 @@ packages: license_family: GPL purls: - pkg:pypi/pyqt5?source=hash-mapping + run_exports: + weak: + - pyqt >=5.15.11,<5.16.0a0 size: 6433486 timestamp: 1759498273803 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyqt5-sip-12.17.0-py312h1ab2c47_2.conda @@ -14884,6 +16845,7 @@ packages: license_family: GPL purls: - pkg:pypi/pyqt5-sip?source=hash-mapping + run_exports: {} size: 89968 timestamp: 1759495630955 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyside6-6.10.2-py312hfc1e6cc_3.conda @@ -14909,6 +16871,7 @@ packages: purls: - pkg:pypi/pyside6?source=hash-mapping - pkg:pypi/shiboken6?source=hash-mapping + run_exports: {} size: 8727046 timestamp: 1778394772130 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.1-h43d1f9e_1_cpython.conda @@ -14936,6 +16899,11 @@ packages: - python_abi 3.12.* *_cp312 license: Python-2.0 purls: [] + run_exports: + weak: + - python_abi 3.12.* *_cp312 + noarch: + - python size: 13871351 timestamp: 1703338868943 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.13-h91f4b29_0_cpython.conda @@ -14968,9 +16936,9 @@ packages: - python size: 13757191 timestamp: 1772728951853 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-librt-0.11.0-py312hd41f8a7_0.conda - sha256: c73b4654c92f2fef1e6bb462464b464abbcf65cd0ca4b7239ace25204a589c4b - md5: 721092396c3edc8c0cdd921dacf6a276 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-librt-0.12.0-py312hd41f8a7_0.conda + sha256: 6f647dc3d96c351125fcfb104bfbef235324626bd5ddaa7e265b398520f4c620 + md5: 9a2257990790d5601317187ecee320ef depends: - python - libgcc >=14 @@ -14980,8 +16948,9 @@ packages: license_family: MIT purls: - pkg:pypi/librt?source=hash-mapping - size: 157928 - timestamp: 1778511638325 + run_exports: {} + size: 160722 + timestamp: 1782847514830 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-orocos-kdl-1.5.3-py312h1ab2c47_2.conda sha256: 6a5a07185a4509ab13dcef98594d041081dd70d26b23651f4c86cc289f6217f6 md5: 574358b8f203748e7c46ff70a908ee76 @@ -14997,6 +16966,9 @@ packages: license: LGPL-2.1-or-later license_family: LGPL purls: [] + run_exports: + weak: + - python-orocos-kdl >=1.5.3,<1.6.0a0 size: 306903 timestamp: 1778045956966 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py312ha4530ae_1.conda @@ -15012,6 +16984,7 @@ packages: license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping + run_exports: {} size: 192182 timestamp: 1770223431156 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qhull-2020.2-h70be974_5.conda @@ -15022,6 +16995,9 @@ packages: - libstdcxx-ng >=12 license: LicenseRef-Qhull purls: [] + run_exports: + weak: + - qhull >=2020.2,<2020.3.0a0 size: 554571 timestamp: 1720813941183 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qt-main-5.15.15-ha9b3be2_8.conda @@ -15081,6 +17057,9 @@ packages: license: LGPL-3.0-only license_family: LGPL purls: [] + run_exports: + weak: + - qt-main >=5.15.15,<5.16.0a0 size: 51951079 timestamp: 1772794115656 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qt6-main-6.10.2-pl5321h598db47_6.conda @@ -15154,6 +17133,9 @@ packages: license: LGPL-3.0-only license_family: LGPL purls: [] + run_exports: + weak: + - qt6-main >=6.10.2,<6.11.0a0 size: 60839855 timestamp: 1773865968913 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rapidjson-1.1.0.post20240409-h5ad3122_2.conda @@ -15166,6 +17148,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 157209 timestamp: 1742820749175 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rav1e-0.8.1-h9d4cc37_0.conda @@ -15178,11 +17161,14 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - rav1e >=0.8.1,<0.9.0a0 size: 5253980 timestamp: 1772540729272 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py312hcd1a082_0.conda - sha256: 829ea3e284c18d331eaf474f366f1f7c8181470bde215e7ecf7119108b331511 - md5: 29d9375f7e73ce33eeb0609bbcadb267 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.6.28-py312hcd1a082_0.conda + sha256: 15db24f801820298ecd5c5950c442b4d9abc257659798662613bf3a97810577f + md5: c5512c0bf722f663f1b9eb2af4f23611 depends: - libgcc >=14 - python >=3.12,<3.13.0a0 @@ -15192,8 +17178,9 @@ packages: license_family: PSF purls: - pkg:pypi/regex?source=hash-mapping - size: 405735 - timestamp: 1778374200794 + run_exports: {} + size: 408685 + timestamp: 1782695459701 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.6-h86ecc28_1.conda sha256: 0fe6f40213f2d8af4fcb7388eeb782a4e496c8bab32c189c3a34b37e8004e5a4 md5: 745d02c0c22ea2f28fbda2cb5dbec189 @@ -15202,26 +17189,30 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - rhash >=1.4.6,<2.0a0 size: 207475 timestamp: 1748644952027 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rsync-3.4.3-h3aee46b_0.conda - sha256: 55535104610c9484396add6d53c1b2555f5c68d455129947276e708c1043fb30 - md5: ac55909327ea580be6e2ae5439f2cc3b +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rsync-3.4.4-h3aee46b_0.conda + sha256: 19fb70cb5c109c4ce42a0ede1f95c98ea230790a1af10b1927bc48cdf596e53d + md5: 6fe8eeee7f5f1b5006d770721ee8b9f0 depends: - - libgcc >=14 - __glibc >=2.28,<3.0.a0 - - libzlib >=1.3.2,<2.0a0 - - openssl >=3.5.6,<4.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 - popt >=1.16,<2.0a0 - zstd >=1.5.7,<1.6.0a0 - - libiconv >=1.18,<2.0a0 + - openssl >=3.5.6,<4.0a0 + - libzlib >=1.3.2,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - xxhash >=0.8.3,<0.8.4.0a0 license: GPL-3.0-only license_family: GPL purls: [] - size: 394217 - timestamp: 1779304190052 + run_exports: {} + size: 395365 + timestamp: 1780999340933 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruby-4.0.5-h706e587_0.conda sha256: 8ebd3dfff48297043adb0895764c263921bd41b0ce04ad995fb31201ae8c50c3 md5: d16043642ea72bd35ba5af784ae648e4 @@ -15240,6 +17231,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - ruby >=4.0.5,<4.1.0a0 size: 17776666 timestamp: 1779257277421 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.14.14-he9a2e21_1.conda @@ -15255,6 +17249,7 @@ packages: license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping + run_exports: {} size: 8791276 timestamp: 1769521008362 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust-1.91.1-h6cf38e9_0.conda @@ -15273,34 +17268,37 @@ packages: - __glibc >=2.17 size: 195849499 timestamp: 1762817258076 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust-1.95.0-h6cf38e9_1.conda - sha256: 07fc7f5e0e7323bb3bdb33a155e93d6da1f98540fa8acfd229ba27328e036726 - md5: d3b365c484488476bbfcbcb8610f35bf +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust-1.96.0-h6cf38e9_0.conda + sha256: 88f399576f66bc612473248413cbac5624eb00ad1a52831662ce1fc0a38916f8 + md5: 489afc4ab72277b53368d9cbebb9af4d depends: - gcc_impl_linux-aarch64 - libgcc >=14 - libzlib >=1.3.2,<2.0a0 - - rust-std-aarch64-unknown-linux-gnu 1.95.0 hbe8e118_1 + - rust-std-aarch64-unknown-linux-gnu 1.96.0 hbe8e118_0 - sysroot_linux-aarch64 >=2.17 license: MIT license_family: MIT - size: 142750014 - timestamp: 1777536507521 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust_linux-aarch64-1.95.0-hd7b9871_2.conda - sha256: 8e195b303c8c084edde2e6b8f28351f443fe0269c5d95ffe5ca0d542d0977c6a - md5: b744fc0a5b59c237214854870a845166 + run_exports: + strong_constrains: + - __glibc >=2.17 + size: 133391007 + timestamp: 1780047167214 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust_linux-aarch64-1.96.0-hb84128a_0.conda + sha256: 9748059671631c9614324f548556023b0573cd2dac90572042ab492ea7c2de04 + md5: aa0ba9a7c9c623d73caf9d854a47ca36 depends: - gcc_linux-aarch64 - - rust 1.95.0.* - - rust-std-aarch64-unknown-linux-gnu 1.95.0.* + - rust 1.96.0.* + - rust-std-aarch64-unknown-linux-gnu 1.96.0.* - sysroot_linux-aarch64 >=2.17 license: BSD-3-Clause license_family: BSD run_exports: strong_constrains: - __glibc >=2.17 - size: 11784 - timestamp: 1780066885443 + size: 11857 + timestamp: 1780932769886 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/scipy-1.17.1-py312ha7f05e0_1.conda sha256: faad223a5a3318687308cd1ae235ad5aee4de2d090cbc2280b3281e506279249 md5: 60bbefd5c712570fec2b52275f641192 @@ -15321,6 +17319,7 @@ packages: license_family: BSD purls: - pkg:pypi/scipy?source=hash-mapping + run_exports: {} size: 16878451 timestamp: 1779874509446 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdformat14-14.8.0-hb4dca6f_2.conda @@ -15332,6 +17331,9 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - libsdformat14 >=14.8.0,<15.0a0 size: 14075 timestamp: 1759339827373 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdformat14-python-14.8.0-py312he22bb7a_2.conda @@ -15351,6 +17353,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 591957 timestamp: 1759339827373 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl2-2.32.56-h7ac5ae9_0.conda @@ -15364,37 +17367,43 @@ packages: - libegl >=1.7.0,<2.0a0 license: Zlib purls: [] + run_exports: + weak: + - sdl2 >=2.32.56,<3.0a0 size: 597756 timestamp: 1757842928996 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl3-3.4.10-had2c13b_0.conda - sha256: 8fe249e71c077a09f94f49256a8738a2ef22bb018f119194ece94361721dff65 - md5: 90e79fd7ec05af2fb5424cd84fd70d20 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sdl3-3.4.12-had2c13b_0.conda + sha256: 20b512f72fe12bdd07c917f20c437f318a8e1b1fb658278e8da0ba26c6ff6826 + md5: 7d71ee12487f73cf9628f2a6e6081ed5 depends: - - libstdcxx >=14 - libgcc >=14 - - xorg-libxcursor >=1.2.3,<2.0a0 - - xorg-libxscrnsaver >=1.2.4,<2.0a0 + - libstdcxx >=14 - pulseaudio-client >=17.0,<17.1.0a0 + - libgl >=1.7.0,<2.0a0 + - xorg-libxscrnsaver >=1.2.4,<2.0a0 + - wayland >=1.25.0,<2.0a0 + - liburing >=2.14,<2.15.0a0 + - libxkbcommon >=1.13.2,<2.0a0 - libusb >=1.0.29,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libx11 >=1.8.13,<2.0a0 - libvulkan-loader >=1.4.341.0,<2.0a0 - - libgl >=1.7.0,<2.0a0 - libunwind >=1.8.3,<1.9.0a0 - - xorg-libxext >=1.3.7,<2.0a0 - - wayland >=1.25.0,<2.0a0 - - libdrm >=2.4.127,<2.5.0a0 - - libudev1 >=257.13 + - dbus >=1.16.2,<2.0a0 - xorg-libxfixes >=6.0.2,<7.0a0 - - xorg-libxtst >=1.2.5,<2.0a0 - - libxkbcommon >=1.13.2,<2.0a0 - libegl >=1.7.0,<2.0a0 - - liburing >=2.14,<2.15.0a0 - xorg-libxi >=1.8.3,<2.0a0 - - xorg-libx11 >=1.8.13,<2.0a0 - - dbus >=1.16.2,<2.0a0 + - xorg-libxtst >=1.2.5,<2.0a0 + - xorg-libxcursor >=1.2.3,<2.0a0 + - libudev1 >=257.13 + - libdrm >=2.4.127,<2.5.0a0 license: Zlib purls: [] - size: 2144308 - timestamp: 1780262838628 + run_exports: + weak: + - sdl3 >=3.4.12,<4.0a0 + size: 2153567 + timestamp: 1782948073672 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/shaderc-2025.5-hfeb5c2c_1.conda sha256: bf3f47847832e33acbcb7a1aba948f3b574979ad2a91f2ebdc9fc685c09433db md5: 8268bdcd82d8f9abcb7f0fd6a9568ba4 @@ -15406,6 +17415,9 @@ packages: license: Apache-2.0 license_family: Apache purls: [] + run_exports: + weak: + - shaderc >=2025.5,<2025.6.0a0 size: 115498 timestamp: 1770208786806 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sip-6.15.3-py312hfcd9f9b_0.conda @@ -15424,6 +17436,9 @@ packages: license_family: BSD purls: - pkg:pypi/sip?source=hash-mapping + run_exports: + weak: + - sip >=6.15.3,<6.16.0a0 size: 737077 timestamp: 1774375435468 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.2.2-he774c54_1.conda @@ -15436,6 +17451,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - snappy >=1.2.2,<1.3.0a0 size: 47096 timestamp: 1762948094646 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/soxr-0.1.3-hb4cce97_3.conda @@ -15446,6 +17464,9 @@ packages: - libgcc-ng >=12 license: LGPL-2.1-or-later purls: [] + run_exports: + weak: + - soxr >=0.1.3,<0.1.4.0a0 size: 111209 timestamp: 1674059588618 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda @@ -15458,6 +17479,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - spdlog >=1.17.0,<1.18.0a0 size: 195699 timestamp: 1767781668042 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spirv-tools-2026.2-hfefdfc9_0.conda @@ -15471,22 +17495,28 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: + weak: + - spirv-tools >=2026,<2027.0a0 size: 2290233 timestamp: 1780139661664 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.2-hf1c7be2_0.conda - sha256: f13247fa19f51fa37e20d00c88347b671af0f09a41ddd89c2ee6a20001ce5150 - md5: 3ff60ca9e45f67cba6a7070e88862fa3 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.3-hf1c7be2_0.conda + sha256: aa38995231e12c2c9ad1d988561ab02fe1e8b397577bfafc94841b9b0e23e40f + md5: 0f92a462399f790fdfb6e7c5941ae551 depends: - icu >=78.3,<79.0a0 - libgcc >=14 - - libsqlite 3.53.2 h10b116e_0 + - libsqlite 3.53.3 h10b116e_0 - libzlib >=1.3.2,<2.0a0 - ncurses >=6.6,<7.0a0 - readline >=8.3,<9.0a0 license: blessing purls: [] - size: 210202 - timestamp: 1780574468062 + run_exports: + weak: + - libsqlite >=3.53.3,<4.0a0 + size: 215067 + timestamp: 1782519058627 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/svt-av1-4.0.1-hfae3067_0.conda sha256: 6518e4575e83e38b07460f504b6467124f9a16e4d368af42ca54a69603002078 md5: 943fcd76194904358b2587d627ee6388 @@ -15496,6 +17526,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - svt-av1 >=4.0.1,<4.0.2.0a0 size: 2042800 timestamp: 1769668627820 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tbb-2023.0.0-h57272ed_2.conda @@ -15508,6 +17541,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: [] + run_exports: {} size: 145425 timestamp: 1778675412470 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tbb-devel-2023.0.0-h57272ed_2.conda @@ -15518,6 +17552,9 @@ packages: - libstdcxx >=14 - tbb 2023.0.0 h57272ed_2 purls: [] + run_exports: + weak: + - tbb >=2023.0.0 size: 1139148 timestamp: 1778675522611 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tinyxml2-11.0.0-h5ad3122_0.conda @@ -15528,6 +17565,9 @@ packages: - libgcc >=13 license: Zlib purls: [] + run_exports: + weak: + - tinyxml2 >=11.0.0,<11.1.0a0 size: 133310 timestamp: 1742246428717 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda @@ -15541,11 +17581,14 @@ packages: license: TCL license_family: BSD purls: [] + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 size: 3368666 timestamp: 1769464148928 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tornado-6.5.6-py312hefbd42c_0.conda - sha256: da99fc106c2a302697dfd0eb35b24830b3ef8f4862a08e5a35881a59990ebd65 - md5: dff3c4d4f078ce30ee6a0ff1cb2d338c +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tornado-6.5.7-py312hefbd42c_0.conda + sha256: a5abbe4712c2afa68e63e19ebe7bbb425baa4db6240bfa3c8276b4ac917138ca + md5: 5d9619b1f48fbccf87010ea5b340b2d1 depends: - libgcc >=14 - python >=3.12,<3.13.0a0 @@ -15554,8 +17597,9 @@ packages: license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping - size: 862640 - timestamp: 1779916964108 + run_exports: {} + size: 863626 + timestamp: 1781007844330 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py312h4f740d2_0.conda sha256: 782101cc2266b2126c44771e4c03658d0c55d933f34b91523d0bdd38ad2f3e10 md5: 9d8284ec3764a95eff0cde0e70772315 @@ -15570,6 +17614,7 @@ packages: license_family: MIT purls: - pkg:pypi/ukkonen?source=hash-mapping + run_exports: {} size: 15682 timestamp: 1769438785443 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uncrustify-0.83.0-h7ac5ae9_0.conda @@ -15581,6 +17626,7 @@ packages: license: GPL-2.0-only license_family: GPL purls: [] + run_exports: {} size: 741203 timestamp: 1779015701987 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/unicodedata2-17.0.1-py312hcd1a082_0.conda @@ -15595,6 +17641,7 @@ packages: license_family: Apache purls: - pkg:pypi/unicodedata2?source=hash-mapping + run_exports: {} size: 409407 timestamp: 1770909146204 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/urdfdom-4.0.1-hcc88bc6_4.conda @@ -15609,6 +17656,10 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - urdfdom_headers >=1.1.2,<2.0a0 + - urdfdom >=4.0.1,<4.1.0a0 size: 127973 timestamp: 1771238089976 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/urdfdom-py-1.2.1-py312h76ea178_6.conda @@ -15623,6 +17674,7 @@ packages: license_family: BSD purls: - pkg:pypi/urdfdom-py?source=hash-mapping + run_exports: {} size: 49424 timestamp: 1756847510243 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/urdfdom_headers-1.1.2-h17cf362_0.conda @@ -15634,6 +17686,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 19152 timestamp: 1726152459234 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/utfcpp-4.09-h8af1aa0_0.conda @@ -15641,20 +17694,21 @@ packages: md5: daa98fd6d175e72d65c353b6b7504971 license: BSL-1.0 purls: [] + run_exports: {} size: 14197 timestamp: 1767012435525 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uv-0.11.19-haa595b2_0.conda - sha256: 84490de12152f857da253c686622a149cad8d60620735ad389a6c6debd9465d3 - md5: 88ebcb243c3da2a95f2740d03814cff0 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uv-0.11.26-haa595b2_0.conda + sha256: 3cbe21f360080969e588374d70b17514eacac94a4328726ebfe1fbc0aec039f5 + md5: c4ac9fbd7745a2b6c6bdcaac4219bd73 depends: - - libstdcxx >=14 - libgcc >=14 + - libstdcxx >=14 constrains: - __glibc >=2.17 license: Apache-2.0 OR MIT run_exports: {} - size: 18905011 - timestamp: 1780539154841 + size: 20171344 + timestamp: 1782834696757 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/viskores-1.1.1-cpu_hb695247_0.conda sha256: d086e094a199ba83f023fbec3753bcff561677910cac31bd8c38ab84fb764820 md5: 8ce740ca4fe8871e8d90e00063e9a748 @@ -15671,6 +17725,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - viskores >=1.1.1,<1.2.0a0 size: 22924208 timestamp: 1777494708492 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/vtk-9.5.2-py312h4954c87_7.conda @@ -15690,6 +17747,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - vtk-base >=9.5.2,<9.5.3.0a0 size: 25478 timestamp: 1768718080474 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/vtk-base-9.5.2-py312h90a26f6_7.conda @@ -15745,6 +17805,9 @@ packages: license_family: BSD purls: - pkg:pypi/vtk?source=hash-mapping + run_exports: + weak: + - vtk-base >=9.5.2,<9.5.3.0a0 size: 64690746 timestamp: 1768718080472 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/vtk-io-ffmpeg-9.5.2-py312haba1314_7.conda @@ -15758,6 +17821,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - vtk-io-ffmpeg >=9.5.2,<9.5.3.0a0 size: 106747 timestamp: 1768718080474 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wayland-1.25.0-h4f8a99f_0.conda @@ -15771,11 +17837,14 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - wayland >=1.25.0,<2.0a0 size: 335260 timestamp: 1773959583826 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wrapt-2.2.1-py312hcd1a082_0.conda - sha256: 4a2a23309047c6a45131d106316c19bfb4e50ec36e8453c5f674b154197de9b5 - md5: e43ff6a1d7def0b1bb077a02f610cc04 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wrapt-2.2.2-py312hcd1a082_0.conda + sha256: 920a81cd9444293a78fe6e9479bacf8fbf672fc6f5268c7237ba4335376f275e + md5: e2b2d650e49db3cafe5d9e7da964e167 depends: - libgcc >=14 - python >=3.12,<3.13.0a0 @@ -15785,8 +17854,9 @@ packages: license_family: BSD purls: - pkg:pypi/wrapt?source=compressed-mapping - size: 115121 - timestamp: 1779477494775 + run_exports: {} + size: 115536 + timestamp: 1782133697736 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/x264-1!164.3095-h4e544f5_2.tar.bz2 sha256: b48f150db8c052c197691c9d76f59e252d3a7f01de123753d51ebf2eed1cf057 md5: 0efaf807a0b5844ce5f605bd9b668281 @@ -15795,6 +17865,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - x264 >=1!164.3095,<1!165 size: 1000661 timestamp: 1660324722559 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/x265-3.5-hdd96247_3.tar.bz2 @@ -15806,6 +17879,9 @@ packages: license: GPL-2.0-or-later license_family: GPL purls: [] + run_exports: + weak: + - x265 >=3.5,<3.6.0a0 size: 1018181 timestamp: 1646610147365 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-0.4.1-hca56bd8_2.conda @@ -15817,6 +17893,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util >=0.4.1,<0.5.0a0 size: 21517 timestamp: 1750437961489 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-cursor-0.1.6-he30d5cf_0.conda @@ -15831,6 +17910,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-cursor >=0.1.6,<0.2.0a0 size: 21639 timestamp: 1763367131001 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-image-0.4.0-h5c728e9_2.conda @@ -15843,6 +17925,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-image >=0.4.0,<0.5.0a0 size: 24910 timestamp: 1718880504308 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-keysyms-0.4.1-h5c728e9_0.conda @@ -15854,6 +17939,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-keysyms >=0.4.1,<0.5.0a0 size: 14343 timestamp: 1718846624153 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-renderutil-0.3.10-h5c728e9_0.conda @@ -15865,6 +17953,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-renderutil >=0.3.10,<0.4.0a0 size: 18139 timestamp: 1718849914457 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-wm-0.4.2-h5c728e9_0.conda @@ -15876,19 +17967,23 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xcb-util-wm >=0.4.2,<0.5.0a0 size: 50772 timestamp: 1718845072660 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xkeyboard-config-2.47-he30d5cf_0.conda - sha256: ec7ff9dffbd41faa31a30fa0724699f05bca000d57c745a195ecdb56888a8605 - md5: 4ac707a4279972357712af099cd1ae50 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xkeyboard-config-2.48-h80f16a2_0.conda + sha256: 96078068df25ddccc60958be740e6fa99efb1e0fa2dae2f84e775201bf84d70c + md5: 3dbc6d9e1f8a8768e7ef9f57585a43ca depends: - libgcc >=14 - xorg-libx11 >=1.8.13,<2.0a0 license: MIT license_family: MIT purls: [] - size: 399629 - timestamp: 1772021320967 + run_exports: {} + size: 442725 + timestamp: 1782027381059 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda sha256: a2ba1864403c7eb4194dacbfe2777acf3d596feae43aada8d1b478617ce45031 md5: c8d8ec3e00cd0fd8a231789b91a7c5b7 @@ -15897,6 +17992,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libice >=1.1.2,<2.0a0 size: 60433 timestamp: 1734229908988 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda @@ -15909,6 +18007,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libsm >=1.2.6,<2.0a0 size: 28701 timestamp: 1741897678254 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda @@ -15920,6 +18021,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libx11 >=1.8.13,<2.0a0 size: 869058 timestamp: 1770819244991 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda @@ -15930,6 +18034,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxau >=1.0.12,<2.0a0 size: 16317 timestamp: 1762977521691 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxaw-1.0.16-h86ecc28_0.conda @@ -15945,6 +18052,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 331138 timestamp: 1727870334121 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxcomposite-0.4.7-he30d5cf_0.conda @@ -15957,6 +18065,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxcomposite >=0.4.7,<1.0a0 size: 14915 timestamp: 1770044415607 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxcursor-1.2.3-h86ecc28_0.conda @@ -15970,6 +18081,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxcursor >=1.2.3,<2.0a0 size: 34596 timestamp: 1730908388714 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdamage-1.1.6-h86ecc28_0.conda @@ -15983,6 +18097,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxdamage >=1.1.6,<2.0a0 size: 13794 timestamp: 1727891406431 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda @@ -15993,6 +18110,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxdmcp >=1.1.5,<2.0a0 size: 21039 timestamp: 1762979038025 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda @@ -16004,6 +18124,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxext >=1.3.7,<2.0a0 size: 52409 timestamp: 1769446753771 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda @@ -16015,6 +18138,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxfixes >=6.0.2,<7.0a0 size: 20704 timestamp: 1759284028146 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.3-he30d5cf_0.conda @@ -16028,6 +18154,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxi >=1.8.3,<2.0a0 size: 49292 timestamp: 1779113229775 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxinerama-1.1.6-hfae3067_0.conda @@ -16041,6 +18170,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxinerama >=1.1.6,<1.2.0a0 size: 15322 timestamp: 1769432283298 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxmu-1.3.1-he30d5cf_0.conda @@ -16054,6 +18186,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxmu >=1.3.1,<2.0a0 size: 93067 timestamp: 1769675744111 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxpm-3.5.19-he30d5cf_0.conda @@ -16070,6 +18205,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxpm >=3.5.19,<4.0a0 size: 71037 timestamp: 1776789996073 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda @@ -16083,6 +18221,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxrandr >=1.5.5,<2.0a0 size: 31122 timestamp: 1769445286951 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda @@ -16094,6 +18235,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxrender >=0.9.12,<0.10.0a0 size: 33649 timestamp: 1734229123157 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxscrnsaver-1.2.4-h86ecc28_0.conda @@ -16106,6 +18250,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxscrnsaver >=1.2.4,<2.0a0 size: 15720 timestamp: 1750007336692 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxshmfence-1.3.3-h86ecc28_0.conda @@ -16116,6 +18263,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxshmfence >=1.3.3,<2.0a0 size: 13805 timestamp: 1734168631514 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda @@ -16129,6 +18279,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxt >=1.3.1,<2.0a0 size: 384752 timestamp: 1731860572314 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda @@ -16142,6 +18295,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxtst >=1.2.5,<2.0a0 size: 33786 timestamp: 1727964907993 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxxf86vm-1.1.7-he30d5cf_0.conda @@ -16154,6 +18310,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - xorg-libxxf86vm >=1.1.7,<2.0a0 size: 19148 timestamp: 1769434729220 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-xorgproto-2025.1-he30d5cf_0.conda @@ -16164,6 +18323,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 569539 timestamp: 1766155414260 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xxhash-0.8.3-hd794028_0.conda @@ -16174,6 +18334,9 @@ packages: license: BSD-2-Clause license_family: BSD purls: [] + run_exports: + weak: + - xxhash >=0.8.3,<0.8.4.0a0 size: 105762 timestamp: 1746457675564 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.8.3-hd704e39_0.conda @@ -16187,6 +18350,9 @@ packages: - xz-tools 5.8.3 he30d5cf_0 license: 0BSD AND LGPL-2.1-or-later AND GPL-2.0-or-later purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 size: 24330 timestamp: 1775828875434 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-gpl-tools-5.8.3-hd704e39_0.conda @@ -16199,6 +18365,9 @@ packages: - xz 5.8.3.* license: 0BSD AND LGPL-2.1-or-later AND GPL-2.0-or-later purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 size: 34353 timestamp: 1775828661986 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-tools-5.8.3-he30d5cf_0.conda @@ -16211,6 +18380,7 @@ packages: - xz 5.8.3.* license: 0BSD AND LGPL-2.1-or-later purls: [] + run_exports: {} size: 102970 timestamp: 1775828449899 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda @@ -16221,6 +18391,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 size: 88088 timestamp: 1753484092643 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda @@ -16232,6 +18405,9 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: + weak: + - yaml-cpp >=0.8.0,<0.9.0a0 size: 213281 timestamp: 1745308220432 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.24.2-py312ha4530ae_0.conda @@ -16249,6 +18425,7 @@ packages: license_family: Apache purls: - pkg:pypi/yarl?source=hash-mapping + run_exports: {} size: 153517 timestamp: 1779246158183 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zenoh-rust-abi-1.7.2.1.85.0-h4d6d557_0.conda @@ -16258,6 +18435,9 @@ packages: - __glibc >=2.17 license: Apache-2.0 OR EPL-2.0 purls: [] + run_exports: + weak: + - zenoh-rust-abi >=1.7.2.1.85.0,<1.7.2.1.85.1.0a0 size: 48766 timestamp: 1767949969738 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zeromq-4.3.5-hec9560f_11.conda @@ -16271,6 +18451,9 @@ packages: license: MPL-2.0 license_family: MOZILLA purls: [] + run_exports: + weak: + - zeromq >=4.3.5,<4.4.0a0 size: 355573 timestamp: 1779123980042 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zfp-1.0.1-h05c1e92_5.conda @@ -16283,6 +18466,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - zfp >=1.0.1,<2.0a0 size: 248846 timestamp: 1766552554324 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.3.2-hdc9db2a_2.conda @@ -16293,6 +18479,9 @@ packages: license: Zlib license_family: Other purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 size: 100515 timestamp: 1774072641977 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda @@ -16303,6 +18492,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 size: 614429 timestamp: 1764777145593 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zziplib-0.13.69-h650d8d0_2.conda @@ -16313,6 +18505,9 @@ packages: - libzlib >=1.3.1,<2.0a0 license: LGPL-2.0-or-later OR MPL-1.1 purls: [] + run_exports: + weak: + - zziplib >=0.13.69,<0.14.0a0 size: 115725 timestamp: 1719242037690 - conda: https://conda.anaconda.org/conda-forge/noarch/absl-py-2.4.0-pyhd8ed1ab_0.conda @@ -16324,19 +18519,21 @@ packages: license_family: Apache purls: - pkg:pypi/absl-py?source=hash-mapping + run_exports: {} size: 109955 timestamp: 1769637168641 -- conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.2-pyhd8ed1ab_0.conda - sha256: 6c6ddfeefead96d44f09c955b04967a579583af2dc63518faf029e46825e41ab - md5: 8a9936643c4a9565459c4a8eb5d4e3ff +- conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.7.1-pyhd8ed1ab_0.conda + sha256: 5ef589e5fd3736439781a9d48e68ce1e723b7081a471c02169908198eba4f448 + md5: e51e09bf3b91c62b7461a9f94e92c2c9 depends: - python >=3.10 license: PSF-2.0 license_family: PSF purls: - pkg:pypi/aiohappyeyeballs?source=compressed-mapping - size: 20727 - timestamp: 1779297825279 + run_exports: {} + size: 24690 + timestamp: 1782986823268 - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.4.0-pyhd8ed1ab_0.conda sha256: 8dc149a6828d19bf104ea96382a9d04dae185d4a03cc6beb1bc7b84c428e3ca2 md5: 421a865222cd0c9d83ff08bc78bf3a61 @@ -16348,6 +18545,7 @@ packages: license_family: APACHE purls: - pkg:pypi/aiosignal?source=hash-mapping + run_exports: {} size: 13688 timestamp: 1751626573984 - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda @@ -16359,19 +18557,22 @@ packages: license_family: BSD purls: - pkg:pypi/alabaster?source=hash-mapping + run_exports: {} size: 18684 timestamp: 1733750512696 -- conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.6.3-pyhd8ed1ab_0.conda - sha256: a2a1879c53b7a8438c898d20fa5f6274e4b1c30161f93b7818236e9df6adffde - md5: 8f37c8fb7116a18da04e52fa9e2c8df9 +- conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.7.0-pyhcf101f3_0.conda + sha256: fca7deee4f28060413d483851703c1287351797c1f660fb9ab63f8d175576e3f + md5: 4553b661c03a2f435d8c889eca8f2075 depends: - python >=3.10 + - python license: Apache-2.0 - license_family: Apache + license_family: APACHE purls: - - pkg:pypi/argcomplete?source=hash-mapping - size: 42386 - timestamp: 1760975036972 + - pkg:pypi/argcomplete?source=compressed-mapping + run_exports: {} + size: 46445 + timestamp: 1782888485558 - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda sha256: ee4da0f3fe9d59439798ee399ef3e482791e48784873d546e706d0935f9ff010 md5: 9673a61a297b00016442e022d689faa6 @@ -16383,6 +18584,7 @@ packages: license_family: Apache purls: - pkg:pypi/asttokens?source=hash-mapping + run_exports: {} size: 28797 timestamp: 1763410017955 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda @@ -16395,6 +18597,7 @@ packages: license_family: MIT purls: - pkg:pypi/attrs?source=hash-mapping + run_exports: {} size: 64927 timestamp: 1773935801332 - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda @@ -16409,6 +18612,7 @@ packages: license_family: BSD purls: - pkg:pypi/babel?source=hash-mapping + run_exports: {} size: 7684321 timestamp: 1772555330347 - conda: https://conda.anaconda.org/conda-forge/noarch/beartype-0.22.9-pyhd8ed1ab_0.conda @@ -16420,6 +18624,7 @@ packages: license_family: MIT purls: - pkg:pypi/beartype?source=hash-mapping + run_exports: {} size: 1063520 timestamp: 1765715830980 - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda @@ -16431,6 +18636,7 @@ packages: license_family: MIT purls: - pkg:pypi/blinker?source=hash-mapping + run_exports: {} size: 13934 timestamp: 1731096548765 - conda: https://conda.anaconda.org/conda-forge/noarch/breathe-4.36.0-pyhd8ed1ab_0.conda @@ -16447,17 +18653,19 @@ packages: license_family: BSD purls: - pkg:pypi/breathe?source=hash-mapping + run_exports: {} size: 78954 timestamp: 1740314139074 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda - sha256: 9812a303a1395e1dafbd92e5bc8a1ff6013bcbba0a09c7f03a8d23e43560aa9b - md5: 489b8e97e666c93f68fdb35c3c9b957f +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda + sha256: f8e3c730fa14ee3f170493779f06522c4acf89169f43db4f039727709b6419cf + md5: a9965dd99f683c5f444428f896635716 depends: - __unix license: ISC purls: [] - size: 129868 - timestamp: 1779289852439 + run_exports: {} + size: 128866 + timestamp: 1781708962055 - conda: https://conda.anaconda.org/conda-forge/noarch/catkin_pkg-1.1.0-pyhd8ed1ab_0.conda sha256: fe602164dc1920551e1452543e22338d55d8a879959f12598c9674cf295c6341 md5: 3e500faf80e42f26d422d849877d48c4 @@ -16472,18 +18680,20 @@ packages: license_family: BSD purls: - pkg:pypi/catkin-pkg?source=hash-mapping + run_exports: {} size: 54106 timestamp: 1757558592553 -- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda - sha256: 645655a3510e38e625da136595f3f16f2130c3263630cc3bc8f60f619ddbe490 - md5: 9fefff2f745ea1cc2ef15211a20c054a +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.6.17-pyhd8ed1ab_0.conda + sha256: 6c13620e458ba43278379d0cdacc30c497336bddfda81681fd50d114a65c702f + md5: c13824fedced67005d3832c152fe9c2f depends: - python >=3.10 license: ISC purls: - pkg:pypi/certifi?source=compressed-mapping - size: 134201 - timestamp: 1779285131141 + run_exports: {} + size: 133877 + timestamp: 1781719949728 - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda sha256: aa589352e61bb221351a79e5946d56916e3c595783994884accdb3b97fe9d449 md5: 381bd45fb7aa032691f3063aff47e3a1 @@ -16493,6 +18703,7 @@ packages: license_family: MIT purls: - pkg:pypi/cfgv?source=hash-mapping + run_exports: {} size: 13589 timestamp: 1763607964133 - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda @@ -16504,6 +18715,7 @@ packages: license_family: MIT purls: - pkg:pypi/charset-normalizer?source=hash-mapping + run_exports: {} size: 58872 timestamp: 1775127203018 - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.1-pyhc90fa1f_0.conda @@ -16517,6 +18729,7 @@ packages: license_family: BSD purls: - pkg:pypi/click?source=compressed-mapping + run_exports: {} size: 104999 timestamp: 1779900548735 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-argcomplete-0.3.3-pyhd8ed1ab_1.conda @@ -16530,6 +18743,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-argcomplete?source=hash-mapping + run_exports: {} size: 18692 timestamp: 1735452378252 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-bash-0.5.0-pyhd8ed1ab_1.conda @@ -16542,6 +18756,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-bash?source=hash-mapping + run_exports: {} size: 19001 timestamp: 1735646679519 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cd-0.1.1-pyhd8ed1ab_1.conda @@ -16555,11 +18770,12 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-cd?source=hash-mapping + run_exports: {} size: 16858 timestamp: 1735513271475 -- conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.29-pyhd8ed1ab_1.conda - sha256: edc01069635b0bb7d9a58c1f36371d1c841ecf90b8e74397df418436209ce01c - md5: b5b23d06f0def5724475bd12365f1aa5 +- conda: https://conda.anaconda.org/conda-forge/noarch/colcon-cmake-0.2.30-pyhd8ed1ab_0.conda + sha256: 559ce6316dc52cd6d1874825a64da88d3b6d3c3472b6c2f3077e2b22c9417c08 + md5: 01fb794eff29e9b0011f6bc5ab9c39d4 depends: - colcon-core - colcon-library-path @@ -16569,8 +18785,9 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-cmake?source=hash-mapping - size: 26257 - timestamp: 1757616401522 + run_exports: {} + size: 30528 + timestamp: 1781648219269 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-core-0.21.0-pyhcf101f3_0.conda sha256: b30d73297ab86e5117c9eebf11d6bc86616be6a7e0ead9d14fec77077c760261 md5: 16256753ef2123996897bc6773080893 @@ -16591,6 +18808,7 @@ packages: purls: - pkg:pypi/colcon-core?source=hash-mapping - pkg:pypi/colcon-distutils-commands?source=hash-mapping + run_exports: {} size: 96785 timestamp: 1780438171992 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-defaults-0.2.9-pyhd8ed1ab_1.conda @@ -16604,6 +18822,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-defaults?source=hash-mapping + run_exports: {} size: 15580 timestamp: 1757616344706 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-devtools-0.3.0-pyhd8ed1ab_1.conda @@ -16616,6 +18835,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-devtools?source=hash-mapping + run_exports: {} size: 14943 timestamp: 1757616967604 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-library-path-0.2.1-pyhd8ed1ab_1.conda @@ -16628,6 +18848,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-library-path?source=hash-mapping + run_exports: {} size: 13505 timestamp: 1757615646068 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-metadata-0.2.5-pyhd8ed1ab_1.conda @@ -16641,20 +18862,22 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-metadata?source=hash-mapping + run_exports: {} size: 20031 timestamp: 1757624342935 -- conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.13-pyhd8ed1ab_0.conda - sha256: ce2802f9c76f4502d17ff47f76f634449a1ae10fded0bed6a65c05d35ccafb33 - md5: d0294b947e6256444f31979612468bba +- conda: https://conda.anaconda.org/conda-forge/noarch/colcon-output-0.2.14-pyhd8ed1ab_0.conda + sha256: 832624fa22e6e6ce6dd55ad1cea9c719c41e6c8279ff44e0deaba71c797d8bda + md5: 283bd31fe9199004e57966fe177d0dd6 depends: - colcon-core >=0.3.8 - python >=3.5 license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/colcon-output?source=hash-mapping - size: 16174 - timestamp: 1676526311561 + - pkg:pypi/colcon-output?source=compressed-mapping + run_exports: {} + size: 21527 + timestamp: 1782140571074 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-information-0.4.1-pyhd8ed1ab_0.conda sha256: 4b7518952798eefcabfac2a7bb7247c04c204ee3678b83500ed31ced95c907c9 md5: efa0bd9a29645cf88d7cd3297b518ba8 @@ -16665,6 +18888,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-package-information?source=hash-mapping + run_exports: {} size: 19302 timestamp: 1775237925157 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-package-selection-0.2.10-pyhd8ed1ab_1.conda @@ -16677,6 +18901,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-package-selection?source=hash-mapping + run_exports: {} size: 18069 timestamp: 1757614388574 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-parallel-executor-0.4.0-pyhe01879c_0.conda @@ -16690,6 +18915,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-parallel-executor?source=hash-mapping + run_exports: {} size: 20688 timestamp: 1755156877864 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-pkg-config-0.1.0-pyhd8ed1ab_1.conda @@ -16702,6 +18928,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-pkg-config?source=hash-mapping + run_exports: {} size: 13616 timestamp: 1775238006255 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-powershell-0.5.0-pyhd8ed1ab_0.conda @@ -16714,6 +18941,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-powershell?source=hash-mapping + run_exports: {} size: 17608 timestamp: 1770791211378 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-python-setup-py-0.2.9-pyhff2d567_1.conda @@ -16727,6 +18955,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-python-setup-py?source=hash-mapping + run_exports: {} size: 16561 timestamp: 1753971248803 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-recursive-crawl-0.2.3-pyhd8ed1ab_0.conda @@ -16739,6 +18968,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-recursive-crawl?source=hash-mapping + run_exports: {} size: 13254 timestamp: 1696534627965 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-ros-0.5.0-pyhd8ed1ab_0.conda @@ -16756,6 +18986,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-ros?source=hash-mapping + run_exports: {} size: 23852 timestamp: 1719301582281 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-test-result-0.3.8-pyhd8ed1ab_1.conda @@ -16768,6 +18999,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-test-result?source=hash-mapping + run_exports: {} size: 17214 timestamp: 1757615650730 - conda: https://conda.anaconda.org/conda-forge/noarch/colcon-zsh-0.5.0-pyhd8ed1ab_1.conda @@ -16780,6 +19012,7 @@ packages: license_family: APACHE purls: - pkg:pypi/colcon-zsh?source=hash-mapping + run_exports: {} size: 18905 timestamp: 1735357634338 - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda @@ -16791,6 +19024,7 @@ packages: license_family: BSD purls: - pkg:pypi/colorama?source=hash-mapping + run_exports: {} size: 27011 timestamp: 1733218222191 - conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda @@ -16803,6 +19037,7 @@ packages: license_family: MIT purls: - pkg:pypi/coloredlogs?source=hash-mapping + run_exports: {} size: 43758 timestamp: 1733928076798 - conda: https://conda.anaconda.org/conda-forge/noarch/construct-2.10.70-pyhd8ed1ab_0.conda @@ -16814,6 +19049,7 @@ packages: license_family: MIT purls: - pkg:pypi/construct?source=hash-mapping + run_exports: {} size: 58104 timestamp: 1701541902326 - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda @@ -16826,6 +19062,7 @@ packages: license_family: BSD purls: - pkg:pypi/cycler?source=hash-mapping + run_exports: {} size: 14778 timestamp: 1764466758386 - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.3.1-pyhd8ed1ab_0.conda @@ -16837,6 +19074,7 @@ packages: license_family: BSD purls: - pkg:pypi/decorator?source=compressed-mapping + run_exports: {} size: 16102 timestamp: 1779115228886 - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.3.1-pyhd8ed1ab_1.conda @@ -16849,20 +19087,22 @@ packages: license_family: MIT purls: - pkg:pypi/deprecated?source=hash-mapping + run_exports: {} size: 15896 timestamp: 1768934186726 -- conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.1-pyhcf101f3_1.conda - sha256: c691221f821fad3a0fcdedb7b18605edb7117cdaa50b76885619c6a0f66ed761 - md5: f8638ae693ee89e9069ed4f3b77a6be9 +- conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda + sha256: e2753997b8bd34205f42be01b8bab8037423dc30c02a1ec12de23e5b4c0b0a2e + md5: 58638f77697c4f6726753eb8be34818b depends: - python >=3.10 - python license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/distlib?source=hash-mapping - size: 302890 - timestamp: 1780422960389 + - pkg:pypi/distlib?source=compressed-mapping + run_exports: {} + size: 303705 + timestamp: 1781320269259 - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda sha256: 5603c7d0321963bb9b4030eadabc3fd7ca6103a38475b4e0ed13ed6d97c86f4e md5: 0a2014fd9860f8b1eaa0b1f3d3771a08 @@ -16872,6 +19112,7 @@ packages: license_family: APACHE purls: - pkg:pypi/distro?source=hash-mapping + run_exports: {} size: 41773 timestamp: 1734729953882 - conda: https://conda.anaconda.org/conda-forge/noarch/dnspython-2.8.0-pyhcf101f3_0.conda @@ -16893,6 +19134,7 @@ packages: license: ISC purls: - pkg:pypi/dnspython?source=hash-mapping + run_exports: {} size: 196500 timestamp: 1757292856922 - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda @@ -16903,6 +19145,7 @@ packages: license: CC-PDDC AND BSD-3-Clause AND BSD-2-Clause AND ZPL-2.1 purls: - pkg:pypi/docutils?source=hash-mapping + run_exports: {} size: 402700 timestamp: 1733217860944 - conda: https://conda.anaconda.org/conda-forge/noarch/empy-3.3.4-pyh9f0ad1d_1.tar.bz2 @@ -16914,6 +19157,7 @@ packages: license_family: GPL purls: - pkg:pypi/empy?source=hash-mapping + run_exports: {} size: 40210 timestamp: 1586444722817 - conda: https://conda.anaconda.org/conda-forge/noarch/etils-1.12.2-pyhd8ed1ab_0.conda @@ -16925,6 +19169,7 @@ packages: license_family: APACHE purls: - pkg:pypi/etils?source=hash-mapping + run_exports: {} size: 787805 timestamp: 1741838050970 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda @@ -16936,6 +19181,7 @@ packages: license: MIT and PSF-2.0 purls: - pkg:pypi/exceptiongroup?source=hash-mapping + run_exports: {} size: 21333 timestamp: 1763918099466 - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda @@ -16947,6 +19193,7 @@ packages: license_family: MIT purls: - pkg:pypi/executing?source=hash-mapping + run_exports: {} size: 30753 timestamp: 1756729456476 - conda: https://conda.anaconda.org/conda-forge/noarch/fabric-3.2.3-pyhd8ed1ab_0.conda @@ -16962,18 +19209,20 @@ packages: license_family: BSD purls: - pkg:pypi/fabric?source=hash-mapping + run_exports: {} size: 55825 timestamp: 1775457354890 -- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.1-pyhd8ed1ab_0.conda - sha256: ab7c43874d451c36a11b1516a3fbdf23803c05fcb01063a3877549dfb3e34ec4 - md5: 917880ebad7632e8a52eada085b98ce9 +- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.29.5-pyhd8ed1ab_0.conda + sha256: aa1035fbdc0c8fbe66a82ae4630b6ed73b832c2c0c52bd7b45b5f3bd54f51df6 + md5: 288126f559a8a6cacabe59c73327fe1f depends: - python >=3.10 license: Unlicense purls: - - pkg:pypi/filelock?source=hash-mapping - size: 34899 - timestamp: 1780521975987 + - pkg:pypi/filelock?source=compressed-mapping + run_exports: {} + size: 38993 + timestamp: 1783063554943 - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-7.3.0-pyhd8ed1ab_0.conda sha256: a32e511ea71a9667666935fd9f497f00bcc6ed0099ef04b9416ac24606854d58 md5: 04a55140685296b25b79ad942264c0ef @@ -16986,6 +19235,7 @@ packages: license_family: MIT purls: - pkg:pypi/flake8?source=hash-mapping + run_exports: {} size: 111916 timestamp: 1750968083921 - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-builtins-3.1.0-pyhd8ed1ab_0.conda @@ -16998,6 +19248,7 @@ packages: license_family: GPL2 purls: - pkg:pypi/flake8-builtins?source=hash-mapping + run_exports: {} size: 19501 timestamp: 1761594405382 - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-comprehensions-3.17.0-pyhd8ed1ab_0.conda @@ -17010,6 +19261,7 @@ packages: license_family: MIT purls: - pkg:pypi/flake8-comprehensions?source=hash-mapping + run_exports: {} size: 14049 timestamp: 1757526877129 - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-docstrings-1.7.0-pyhd8ed1ab_0.conda @@ -17023,6 +19275,7 @@ packages: license_family: MIT purls: - pkg:pypi/flake8-docstrings?source=hash-mapping + run_exports: {} size: 10395 timestamp: 1675285794906 - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-import-order-0.19.2-pyhd8ed1ab_0.conda @@ -17037,6 +19290,7 @@ packages: license_family: LGPL purls: - pkg:pypi/flake8-import-order?source=hash-mapping + run_exports: {} size: 21041 timestamp: 1750969641622 - conda: https://conda.anaconda.org/conda-forge/noarch/flake8-quotes-3.4.0-pyhd8ed1ab_1.conda @@ -17049,6 +19303,7 @@ packages: license_family: MIT purls: - pkg:pypi/flake8-quotes?source=hash-mapping + run_exports: {} size: 14776 timestamp: 1735335323771 - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.1.3-pyhcf101f3_1.conda @@ -17067,6 +19322,7 @@ packages: license_family: BSD purls: - pkg:pypi/flask?source=hash-mapping + run_exports: {} size: 87428 timestamp: 1771489274528 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 @@ -17075,6 +19331,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 397370 timestamp: 1566932522327 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 @@ -17083,6 +19340,7 @@ packages: license: OFL-1.1 license_family: Other purls: [] + run_exports: {} size: 96530 timestamp: 1620479909603 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 @@ -17091,6 +19349,7 @@ packages: license: OFL-1.1 license_family: Other purls: [] + run_exports: {} size: 700814 timestamp: 1620479612257 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda @@ -17099,6 +19358,7 @@ packages: license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 license_family: Other purls: [] + run_exports: {} size: 1620504 timestamp: 1727511233259 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 @@ -17109,6 +19369,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 3667 timestamp: 1566974674465 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda @@ -17122,19 +19383,21 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 4059 timestamp: 1762351264405 -- conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.4.0-pyhd8ed1ab_0.conda - sha256: 079701b4ff3b317a1a158cabd48cf2b856b8b8d3ef44f152809d9acf20cc8e10 - md5: 2c11aa96ea85ced419de710c1c3a78ff +- conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.6.0-pyhd8ed1ab_0.conda + sha256: fe0156e6d658be3531aad2a99e42e8ad1ee23c69837d469c44c1b6010373913d + md5: 7d7e6c826ba0743fc491ebee0e7b899c depends: - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/fsspec?source=hash-mapping - size: 149694 - timestamp: 1777547807038 + - pkg:pypi/fsspec?source=compressed-mapping + run_exports: {} + size: 149709 + timestamp: 1781615868173 - conda: https://conda.anaconda.org/conda-forge/noarch/git-subrepo-0.4.9-hc364b38_3.conda sha256: 1095cdcb8bb889d50c399e07609b7217a27f8305e4ac70b3f46b9e0d94ed4760 md5: 3057964958da1fc0ec119951dd6775e2 @@ -17143,6 +19406,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 37429 timestamp: 1770108326508 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.12-pyhd8ed1ab_0.conda @@ -17155,6 +19419,7 @@ packages: license_family: BSD purls: - pkg:pypi/gitdb?source=hash-mapping + run_exports: {} size: 53136 timestamp: 1735887290843 - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.50-pyhd8ed1ab_0.conda @@ -17168,6 +19433,7 @@ packages: license_family: BSD purls: - pkg:pypi/gitpython?source=hash-mapping + run_exports: {} size: 162193 timestamp: 1778065820061 - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda @@ -17182,19 +19448,21 @@ packages: license_family: MIT purls: - pkg:pypi/h2?source=hash-mapping + run_exports: {} size: 95967 timestamp: 1756364871835 -- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba - md5: 0a802cb9888dd14eeefc611f05c40b6e +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda + sha256: fdcea5d7cb314485d3907192ef024c704311548c5b0cbeb390cd1951051e29d2 + md5: b395909221b9bd1df066e5930e18855b depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - - pkg:pypi/hpack?source=hash-mapping - size: 30731 - timestamp: 1737618390337 + - pkg:pypi/hpack?source=compressed-mapping + run_exports: {} + size: 32884 + timestamp: 1782283986153 - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d md5: 7fe569c10905402ed47024fc481bb371 @@ -17205,6 +19473,7 @@ packages: license_family: MIT purls: - pkg:pypi/humanfriendly?source=hash-mapping + run_exports: {} size: 73563 timestamp: 1733928021866 - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda @@ -17216,6 +19485,7 @@ packages: license_family: MIT purls: - pkg:pypi/hyperframe?source=hash-mapping + run_exports: {} size: 17397 timestamp: 1737618427549 - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.19-pyhd8ed1ab_0.conda @@ -17228,20 +19498,22 @@ packages: license_family: MIT purls: - pkg:pypi/identify?source=hash-mapping + run_exports: {} size: 79757 timestamp: 1776455344188 -- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.17-pyhcf101f3_0.conda - sha256: f9fe1f9e539c544405ccb7ba632d4ba79edf243c05554d76ace073158a80b691 - md5: c75e517ebd7a5c5272fe111e8b162228 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.18-pyhcf101f3_0.conda + sha256: c75632ea624aa450a394f570749420c5a2e0997d0216bc29d5d45b0f39df0426 + md5: 577b04680ae422adb86fc60d7b940659 depends: - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/idna?source=hash-mapping - size: 56858 - timestamp: 1779999227630 + - pkg:pypi/idna?source=compressed-mapping + run_exports: {} + size: 163869 + timestamp: 1781620148226 - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda sha256: 5a047f9eac290e679b4e6f6f4cbfcc5acdfbf031a4f06824d4ddb590cdbb850b md5: 92617c2ba2847cca7a6ed813b6f4ab79 @@ -17251,6 +19523,7 @@ packages: license_family: MIT purls: - pkg:pypi/imagesize?source=hash-mapping + run_exports: {} size: 15729 timestamp: 1773752188889 - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda @@ -17264,6 +19537,7 @@ packages: license_family: APACHE purls: - pkg:pypi/importlib-metadata?source=compressed-mapping + run_exports: {} size: 34766 timestamp: 1779714582554 - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda @@ -17278,6 +19552,7 @@ packages: license_family: APACHE purls: - pkg:pypi/importlib-resources?source=hash-mapping + run_exports: {} size: 34809 timestamp: 1776068839274 - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda @@ -17289,6 +19564,7 @@ packages: license_family: MIT purls: - pkg:pypi/iniconfig?source=hash-mapping + run_exports: {} size: 13387 timestamp: 1760831448842 - conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda @@ -17300,11 +19576,12 @@ packages: license_family: BSD purls: - pkg:pypi/invoke?source=hash-mapping + run_exports: {} size: 132825 timestamp: 1760146119847 -- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.14.1-pyh53cf698_0.conda - sha256: a3f76e06c31bcf1bda0f633d5c9f1c834286b4f6decc6626067a6cffee283318 - md5: fbd58549b374103c1a80577f09a328ef +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.15.0-pyh53cf698_0.conda + sha256: d9fa14ec35119901bf702a9a3e8a5570daef2aada7d03878e4c24d9de912302b + md5: 2f4ea7f616b30363d8dde5cc15e7af2e depends: - __unix - decorator >=5.1.0 @@ -17323,9 +19600,10 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/ipython?source=hash-mapping - size: 652893 - timestamp: 1780654403616 + - pkg:pypi/ipython?source=compressed-mapping + run_exports: {} + size: 658801 + timestamp: 1782482716877 - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda sha256: 894682a42a7d659ae12878dbcb274516a7031bbea9104e92f8e88c1f2765a104 md5: bd80ba060603cc228d9d81c257093119 @@ -17336,6 +19614,7 @@ packages: license_family: BSD purls: - pkg:pypi/ipython-pygments-lexers?source=hash-mapping + run_exports: {} size: 13993 timestamp: 1737123723464 - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda @@ -17347,31 +19626,35 @@ packages: license_family: BSD purls: - pkg:pypi/itsdangerous?source=hash-mapping + run_exports: {} size: 19180 timestamp: 1733308353037 -- conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.7-pyhd8ed1ab_0.conda - sha256: f6d39c7a9acf6289e75444c032a7154bba5abb45b16feb4013e12250cd485cc2 - md5: 96387643c6c475b099766f98c41242f0 +- conda: https://conda.anaconda.org/conda-forge/noarch/jaxtyping-0.3.11-pyhd8ed1ab_0.conda + sha256: e0c861f192c9640ffdc74c6c813012d1cce48038e456a16fcf464b99b77feae1 + md5: d2fa6995ffc3e55ea22e70c6582489ab depends: - - python >=3.10 + - python >=3.11 - wadler-lindig >=0.1.3 license: MIT license_family: MIT purls: - pkg:pypi/jaxtyping?source=hash-mapping - size: 48435 - timestamp: 1769819488096 -- conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - sha256: 92c4d217e2dc68983f724aa983cca5464dcb929c566627b26a2511159667dba8 - md5: a4f4c5dc9b80bc50e0d3dc4e6e8f1bd9 + run_exports: {} + size: 49623 + timestamp: 1782331952975 +- conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.20.0-pyhcf101f3_0.conda + sha256: 744143551c1c7b528b82533fb641b9d7db20b2203abc4c2635c387fa6c089fc3 + md5: c2b3d37aa1411031126036ee76a8a861 depends: - - parso >=0.8.3,<0.9.0 - - python >=3.9 + - python >=3.10 + - parso >=0.8.6,<0.9.0 + - python license: Apache-2.0 AND MIT purls: - - pkg:pypi/jedi?source=hash-mapping - size: 843646 - timestamp: 1733300981994 + - pkg:pypi/jedi?source=compressed-mapping + run_exports: {} + size: 2715215 + timestamp: 1782251948616 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b md5: 04558c96691bed63104678757beb4f8d @@ -17383,6 +19666,7 @@ packages: license_family: BSD purls: - pkg:pypi/jinja2?source=hash-mapping + run_exports: {} size: 120685 timestamp: 1764517220861 - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda @@ -17393,6 +19677,7 @@ packages: license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later license_family: GPL purls: [] + run_exports: {} size: 1278712 timestamp: 1765578681495 - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda @@ -17403,6 +19688,7 @@ packages: license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later license_family: GPL purls: [] + run_exports: {} size: 1248134 timestamp: 1765578613607 - conda: https://conda.anaconda.org/conda-forge/noarch/lark-parser-0.12.0-pyhd8ed1ab_1.conda @@ -17414,6 +19700,7 @@ packages: license_family: MIT purls: - pkg:pypi/lark-parser?source=hash-mapping + run_exports: {} size: 86134 timestamp: 1725742423890 - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-14.3.0-hf649bbc_119.conda @@ -17424,6 +19711,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 3091520 timestamp: 1778268364856 - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda @@ -17433,6 +19721,7 @@ packages: - __unix license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + run_exports: {} size: 3095909 timestamp: 1778268932148 - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-14.3.0-h25ba3ff_119.conda @@ -17443,6 +19732,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 2346647 timestamp: 1778268433769 - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-15.2.0-h55c397f_119.conda @@ -17452,6 +19742,7 @@ packages: - __unix license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + run_exports: {} size: 2353893 timestamp: 1778268665954 - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-14.3.0-h9f08a49_119.conda @@ -17462,6 +19753,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 20199810 timestamp: 1778268389428 - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda @@ -17471,6 +19763,7 @@ packages: - __unix license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + run_exports: {} size: 20765069 timestamp: 1778268963689 - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-14.3.0-h57c8d61_119.conda @@ -17481,6 +19774,7 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] + run_exports: {} size: 17587589 timestamp: 1778268454520 - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-15.2.0-ha7b1723_119.conda @@ -17490,6 +19784,7 @@ packages: - __unix license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + run_exports: {} size: 17627362 timestamp: 1778268687968 - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda @@ -17502,6 +19797,7 @@ packages: license_family: MIT purls: - pkg:pypi/loguru?source=hash-mapping + run_exports: {} size: 59696 timestamp: 1746634858826 - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda @@ -17514,6 +19810,7 @@ packages: license_family: MIT purls: - pkg:pypi/markdown-it-py?source=hash-mapping + run_exports: {} size: 69017 timestamp: 1778169663339 - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda @@ -17526,6 +19823,7 @@ packages: license_family: BSD purls: - pkg:pypi/matplotlib-inline?source=hash-mapping + run_exports: {} size: 15725 timestamp: 1778264403247 - conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda @@ -17537,6 +19835,7 @@ packages: license_family: MIT purls: - pkg:pypi/mccabe?source=hash-mapping + run_exports: {} size: 12934 timestamp: 1733216573915 - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda @@ -17548,6 +19847,7 @@ packages: license_family: MIT purls: - pkg:pypi/mdurl?source=hash-mapping + run_exports: {} size: 14465 timestamp: 1733255681319 - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda @@ -17559,6 +19859,7 @@ packages: license_family: Apache purls: - pkg:pypi/munkres?source=hash-mapping + run_exports: {} size: 15851 timestamp: 1749895533014 - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda @@ -17570,6 +19871,7 @@ packages: license_family: MIT purls: - pkg:pypi/mypy-extensions?source=hash-mapping + run_exports: {} size: 11766 timestamp: 1745776666688 - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda @@ -17582,6 +19884,7 @@ packages: license_family: BSD purls: - pkg:pypi/nodeenv?source=hash-mapping + run_exports: {} size: 40866 timestamp: 1766261270149 - conda: https://conda.anaconda.org/conda-forge/noarch/notify2-0.3.1-pyhd8ed1ab_0.tar.bz2 @@ -17594,6 +19897,7 @@ packages: license_family: BSD purls: - pkg:pypi/notify2?source=hash-mapping + run_exports: {} size: 11122 timestamp: 1647371622387 - conda: https://conda.anaconda.org/conda-forge/noarch/nvidia-ml-py-13.610.43-pyhd8ed1ab_0.conda @@ -17608,6 +19912,7 @@ packages: license_family: BSD purls: - pkg:pypi/nvidia-ml-py?source=hash-mapping + run_exports: {} size: 50107 timestamp: 1780355713540 - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda @@ -17620,6 +19925,7 @@ packages: license_family: APACHE purls: - pkg:pypi/packaging?source=hash-mapping + run_exports: {} size: 91574 timestamp: 1777103621679 - conda: https://conda.anaconda.org/conda-forge/noarch/paramiko-4.0.0-pyhd8ed1ab_0.conda @@ -17635,6 +19941,7 @@ packages: license_family: LGPL purls: - pkg:pypi/paramiko?source=hash-mapping + run_exports: {} size: 159896 timestamp: 1755102147074 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda @@ -17647,6 +19954,7 @@ packages: license_family: MIT purls: - pkg:pypi/parso?source=hash-mapping + run_exports: {} size: 82472 timestamp: 1777722955579 - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.1.1-pyhd8ed1ab_0.conda @@ -17658,6 +19966,7 @@ packages: license_family: MOZILLA purls: - pkg:pypi/pathspec?source=hash-mapping + run_exports: {} size: 56559 timestamp: 1777271601895 - conda: https://conda.anaconda.org/conda-forge/noarch/pep517-0.13.0-pyhd8ed1ab_0.tar.bz2 @@ -17670,6 +19979,7 @@ packages: license_family: MIT purls: - pkg:pypi/pep517?source=hash-mapping + run_exports: {} size: 19044 timestamp: 1667916747996 - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda @@ -17681,6 +19991,7 @@ packages: license: ISC purls: - pkg:pypi/pexpect?source=hash-mapping + run_exports: {} size: 53561 timestamp: 1733302019362 - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.10.0-pyhcf101f3_0.conda @@ -17693,6 +20004,7 @@ packages: license_family: MIT purls: - pkg:pypi/platformdirs?source=compressed-mapping + run_exports: {} size: 26308 timestamp: 1779972894916 - conda: https://conda.anaconda.org/conda-forge/noarch/playsound-1.3.0-pyhd8ed1ab_1.conda @@ -17704,6 +20016,7 @@ packages: license_family: MIT purls: - pkg:pypi/playsound?source=hash-mapping + run_exports: {} size: 12785 timestamp: 1735588579558 - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda @@ -17716,6 +20029,7 @@ packages: license_family: MIT purls: - pkg:pypi/pluggy?source=hash-mapping + run_exports: {} size: 25877 timestamp: 1764896838868 - conda: https://conda.anaconda.org/conda-forge/noarch/ply-3.11-pyhd8ed1ab_3.conda @@ -17727,6 +20041,7 @@ packages: license_family: BSD purls: - pkg:pypi/ply?source=hash-mapping + run_exports: {} size: 49052 timestamp: 1733239818090 - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.6.0-pyha770c72_0.conda @@ -17743,6 +20058,7 @@ packages: license_family: MIT purls: - pkg:pypi/pre-commit?source=hash-mapping + run_exports: {} size: 201606 timestamp: 1776858157327 - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda @@ -17757,6 +20073,7 @@ packages: license_family: BSD purls: - pkg:pypi/prompt-toolkit?source=hash-mapping + run_exports: {} size: 273927 timestamp: 1756321848365 - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda @@ -17767,6 +20084,7 @@ packages: license: ISC purls: - pkg:pypi/ptyprocess?source=hash-mapping + run_exports: {} size: 19457 timestamp: 1733302371990 - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda @@ -17778,6 +20096,7 @@ packages: license_family: MIT purls: - pkg:pypi/pure-eval?source=hash-mapping + run_exports: {} size: 16668 timestamp: 1733569518868 - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-3.0.3-pyhfe8187e_0.conda @@ -17793,6 +20112,7 @@ packages: license_family: BSD purls: - pkg:pypi/pybind11?source=hash-mapping + run_exports: {} size: 247963 timestamp: 1775004608640 - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda @@ -17801,6 +20121,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: + weak: + - pybind11-abi ==11 size: 14671 timestamp: 1752769938071 - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-global-3.0.3-pyh648e204_0.conda @@ -17816,6 +20139,7 @@ packages: license_family: BSD purls: - pkg:pypi/pybind11-global?source=hash-mapping + run_exports: {} size: 243898 timestamp: 1775004520432 - conda: https://conda.anaconda.org/conda-forge/noarch/pycodestyle-2.14.0-pyhd8ed1ab_0.conda @@ -17827,6 +20151,7 @@ packages: license_family: MIT purls: - pkg:pypi/pycodestyle?source=hash-mapping + run_exports: {} size: 35182 timestamp: 1750616054854 - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda @@ -17839,6 +20164,7 @@ packages: license_family: BSD purls: - pkg:pypi/pycparser?source=compressed-mapping + run_exports: {} size: 55886 timestamp: 1779293633166 - conda: https://conda.anaconda.org/conda-forge/noarch/pydocstyle-6.3.0-pyhd8ed1ab_1.conda @@ -17852,6 +20178,7 @@ packages: license_family: MIT purls: - pkg:pypi/pydocstyle?source=hash-mapping + run_exports: {} size: 40236 timestamp: 1733261742916 - conda: https://conda.anaconda.org/conda-forge/noarch/pydot-4.0.1-pyhcf101f3_2.conda @@ -17866,6 +20193,7 @@ packages: license_family: MIT purls: - pkg:pypi/pydot?source=hash-mapping + run_exports: {} size: 150656 timestamp: 1766345630713 - conda: https://conda.anaconda.org/conda-forge/noarch/pyflakes-3.4.0-pyhd8ed1ab_0.conda @@ -17877,6 +20205,7 @@ packages: license_family: MIT purls: - pkg:pypi/pyflakes?source=hash-mapping + run_exports: {} size: 59592 timestamp: 1750492011671 - conda: https://conda.anaconda.org/conda-forge/noarch/pyglfw-2.10.0-pyha770c72_0.conda @@ -17889,6 +20218,7 @@ packages: license_family: MIT purls: - pkg:pypi/glfw?source=hash-mapping + run_exports: {} size: 31744 timestamp: 1757704430445 - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda @@ -17900,6 +20230,7 @@ packages: license_family: BSD purls: - pkg:pypi/pygments?source=hash-mapping + run_exports: {} size: 893031 timestamp: 1774796815820 - conda: https://conda.anaconda.org/conda-forge/noarch/pyopengl-3.1.10-pyha804496_2.conda @@ -17912,6 +20243,7 @@ packages: license: LicenseRef-pyopengl purls: - pkg:pypi/pyopengl?source=hash-mapping + run_exports: {} size: 1327162 timestamp: 1756496351413 - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda @@ -17924,6 +20256,7 @@ packages: license_family: MIT purls: - pkg:pypi/pyparsing?source=hash-mapping + run_exports: {} size: 110893 timestamp: 1769003998136 - conda: https://conda.anaconda.org/conda-forge/noarch/pyqt-builder-1.18.2-pyhd8ed1ab_1.conda @@ -17938,6 +20271,7 @@ packages: license_family: BSD purls: - pkg:pypi/pyqt-builder?source=hash-mapping + run_exports: {} size: 2952282 timestamp: 1766858321453 - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda @@ -17950,6 +20284,7 @@ packages: license_family: BSD purls: - pkg:pypi/pysocks?source=hash-mapping + run_exports: {} size: 21085 timestamp: 1733217331982 - conda: https://conda.anaconda.org/conda-forge/noarch/pysoundcard-0.4.6-pyha804496_0.conda @@ -17965,6 +20300,7 @@ packages: license_family: BSD purls: - pkg:pypi/soundcard?source=hash-mapping + run_exports: {} size: 42272 timestamp: 1776005577113 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.0.3-pyhc364b38_1.conda @@ -17986,6 +20322,7 @@ packages: license_family: MIT purls: - pkg:pypi/pytest?source=hash-mapping + run_exports: {} size: 299984 timestamp: 1775644472530 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-7.1.0-pyhcf101f3_0.conda @@ -18001,6 +20338,7 @@ packages: license_family: MIT purls: - pkg:pypi/pytest-cov?source=hash-mapping + run_exports: {} size: 29559 timestamp: 1774139250481 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-mock-3.15.1-pyhd8ed1ab_0.conda @@ -18013,6 +20351,7 @@ packages: license_family: MIT purls: - pkg:pypi/pytest-mock?source=hash-mapping + run_exports: {} size: 22968 timestamp: 1758101248317 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-repeat-0.9.4-pyhd8ed1ab_0.conda @@ -18025,11 +20364,12 @@ packages: license_family: MOZILLA purls: - pkg:pypi/pytest-repeat?source=hash-mapping + run_exports: {} size: 10537 timestamp: 1744061283541 -- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.3-pyhd8ed1ab_0.conda - sha256: 442e0dacfd4ec68b8a7387514f0d07e95d6e8f2a8bb0d5592ce13f8b006b047c - md5: 3d7ebbc1b50e40ce47644dd9f710a64e +- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-rerunfailures-16.4-pyhd8ed1ab_0.conda + sha256: d4e2952eb6fd30c2f2b939d6ebbcf27bbc53d543d5605830da2a57b37c28501c + md5: 332b998a40d179d02787c9d7678b6ffb depends: - packaging >=17.1 - pytest !=8.2.2,>=8.1 @@ -18037,9 +20377,10 @@ packages: license: MPL-2.0 license_family: OTHER purls: - - pkg:pypi/pytest-rerunfailures?source=hash-mapping - size: 21401 - timestamp: 1779715182649 + - pkg:pypi/pytest-rerunfailures?source=compressed-mapping + run_exports: {} + size: 22855 + timestamp: 1782920468250 - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 md5: 5b8d21249ff20967101ffa321cab24e8 @@ -18051,11 +20392,12 @@ packages: license_family: APACHE purls: - pkg:pypi/python-dateutil?source=hash-mapping + run_exports: {} size: 233310 timestamp: 1751104122689 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.0-pyhcf101f3_0.conda - sha256: dd709df1ef4e44ea9b6dd48b6e53c062efcc12850b3116b2884cfbef1aa4bd92 - md5: fb1e5c138e2d933e59b3fa0462acc5e6 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.4.2-pyhcf101f3_0.conda + sha256: 6914da740f6e3ec44ffb2f687dbc9c33abf084e42f34e3a8bb8235e475850619 + md5: 7a9095c9300d1b50b1785ca9bc4cadae depends: - python >=3.10 - filelock >=3.15.4 @@ -18065,8 +20407,9 @@ packages: license_family: MIT purls: - pkg:pypi/python-discovery?source=compressed-mapping - size: 34924 - timestamp: 1779967197357 + run_exports: {} + size: 35514 + timestamp: 1781257630962 - conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda sha256: 1933243d9f839bb7bc6c9b75481b6445f50f8b727eb926086e8a2a347fb0467d md5: 611207751a2c0b5b999b07b78985d7a0 @@ -18076,6 +20419,7 @@ packages: license_family: Apache purls: - pkg:pypi/flatbuffers?source=hash-mapping + run_exports: {} size: 34827 timestamp: 1758880404905 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda @@ -18087,6 +20431,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: [] + run_exports: {} size: 6958 timestamp: 1752805918820 - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda @@ -18105,6 +20450,7 @@ packages: license_family: APACHE purls: - pkg:pypi/requests?source=compressed-mapping + run_exports: {} size: 68709 timestamp: 1778851103479 - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.4-pyhcf101f3_0.conda @@ -18120,6 +20466,7 @@ packages: license_family: MIT purls: - pkg:pypi/rich?source=hash-mapping + run_exports: {} size: 208480 timestamp: 1775880677603 - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-4.1.0-pyhd8ed1ab_0.conda @@ -18130,6 +20477,7 @@ packages: license: 0BSD OR CC0-1.0 purls: - pkg:pypi/roman-numerals?source=hash-mapping + run_exports: {} size: 13814 timestamp: 1766003022813 - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-py-4.1.0-pyhd8ed1ab_0.conda @@ -18141,6 +20489,7 @@ packages: license: 0BSD OR CC0-1.0 purls: - pkg:pypi/roman-numerals-py?source=hash-mapping + run_exports: {} size: 11074 timestamp: 1766025162370 - conda: https://conda.anaconda.org/conda-forge/noarch/rosdistro-1.0.1-pyhd8ed1ab_0.conda @@ -18156,6 +20505,7 @@ packages: license_family: BSD purls: - pkg:pypi/rosdistro?source=hash-mapping + run_exports: {} size: 47691 timestamp: 1747826651335 - conda: https://conda.anaconda.org/conda-forge/noarch/rospkg-1.6.1-pyhd8ed1ab_0.conda @@ -18170,6 +20520,7 @@ packages: license_family: BSD purls: - pkg:pypi/rospkg?source=hash-mapping + run_exports: {} size: 31852 timestamp: 1766125246079 - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-unknown-linux-gnu-1.91.1-hbe8e118_0.conda @@ -18181,19 +20532,21 @@ packages: - rust >=1.91.1,<1.91.2.0a0 license: MIT license_family: MIT + run_exports: {} size: 37290717 timestamp: 1762816473116 -- conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-unknown-linux-gnu-1.95.0-hbe8e118_1.conda - sha256: 81dfa70b439e7b8480bcf31d7e2bf1820d9b164f331c56affb04ca058c6d9060 - md5: c2eaad5636abc17f3eea0608674fc852 +- conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-unknown-linux-gnu-1.96.0-hbe8e118_0.conda + sha256: 8e86745ce1655e126d52b6a1908e4cd8721dc031fc944dbc5ba12838f6f945a5 + md5: c6a198001bc91ef594731364d10dbce3 depends: - __unix constrains: - - rust >=1.95.0,<1.95.1.0a0 + - rust >=1.96.0,<1.96.1.0a0 license: MIT license_family: MIT - size: 34966255 - timestamp: 1777536074306 + run_exports: {} + size: 35596879 + timestamp: 1780046657529 - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.91.1-h2c6d0dc_0.conda sha256: 21925ee23f5a7522a191a67f640a765ff67c4f028db95d6f41634e22449cd4af md5: 2a3345e21b15b8659310e01e9c6eda60 @@ -18203,19 +20556,21 @@ packages: - rust >=1.91.1,<1.91.2.0a0 license: MIT license_family: MIT + run_exports: {} size: 38139898 timestamp: 1762816495933 -- conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.95.0-h2c6d0dc_1.conda - sha256: 5d2e2b38a6d2a7653afc93706da04a5a14a6de9834cd34c0a2f4d7af619a3bc6 - md5: 835766243561e6c6f34b617b9eb89110 +- conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.96.0-h2c6d0dc_0.conda + sha256: e8c453fc331eedd6b7a02356d177802a2c03b0bc6490d86c0e63c15ef172d53f + md5: cbbc8546ba8381cb792744564cec0430 depends: - __unix constrains: - - rust >=1.95.0,<1.95.1.0a0 + - rust >=1.96.0,<1.96.1.0a0 license: MIT license_family: MIT - size: 36416714 - timestamp: 1777535938349 + run_exports: {} + size: 36676677 + timestamp: 1780046295074 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.1.2-pyhd8ed1ab_0.conda sha256: dc5a777597e05ceddefc87d2f96389b7ae0afb097e558307af83a453db3e3887 md5: 4fe12573bf499ff85a0a364e00cc5c53 @@ -18225,6 +20580,7 @@ packages: license_family: MIT purls: - pkg:pypi/setuptools?source=hash-mapping + run_exports: {} size: 462324 timestamp: 1692383535614 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda @@ -18234,8 +20590,7 @@ packages: - python >=3.10 license: MIT license_family: MIT - purls: - - pkg:pypi/setuptools?source=hash-mapping + run_exports: {} size: 639697 timestamp: 1773074868565 - conda: https://conda.anaconda.org/conda-forge/noarch/simpleeval-1.0.7-pyhd8ed1ab_0.conda @@ -18247,6 +20602,7 @@ packages: license_family: MIT purls: - pkg:pypi/simpleeval?source=hash-mapping + run_exports: {} size: 24617 timestamp: 1773753246067 - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -18259,19 +20615,22 @@ packages: license_family: MIT purls: - pkg:pypi/six?source=hash-mapping + run_exports: {} size: 18455 timestamp: 1753199211006 -- conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhd8ed1ab_0.conda - sha256: ae723ba6ab7b1998a04ef16b357c1e0043ffd4f4ac9b0da71e393680343a3c86 - md5: 69db183edbe5b7c3e6c157980057a9d0 +- conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.3-pyhcf101f3_1.conda + sha256: bc86861086db65c9b56dd6a1605755f41a9875b94fc3b69e137f686700d91aa1 + md5: b899f1195be56d8215ed1973a8f409c3 depends: - - python >=3.9 + - python >=3.10 + - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/smmap?source=hash-mapping - size: 27064 - timestamp: 1775587040128 + run_exports: {} + size: 27262 + timestamp: 1781021238494 - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad md5: 03fe290994c5e4ec17293cfb6bdce520 @@ -18281,6 +20640,7 @@ packages: license_family: Apache purls: - pkg:pypi/sniffio?source=hash-mapping + run_exports: {} size: 15698 timestamp: 1762941572482 - conda: https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda @@ -18292,6 +20652,7 @@ packages: license_family: BSD purls: - pkg:pypi/snowballstemmer?source=hash-mapping + run_exports: {} size: 74456 timestamp: 1780468201547 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda @@ -18320,6 +20681,7 @@ packages: license_family: BSD purls: - pkg:pypi/sphinx?source=hash-mapping + run_exports: {} size: 1424416 timestamp: 1740956642838 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-rtd-theme-3.1.0-hd8ed1ab_0.conda @@ -18331,6 +20693,7 @@ packages: license: MIT license_family: MIT purls: [] + run_exports: {} size: 7240 timestamp: 1769194861913 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx_rtd_theme-3.1.0-pyha770c72_0.conda @@ -18345,6 +20708,7 @@ packages: license_family: MIT purls: - pkg:pypi/sphinx-rtd-theme?source=hash-mapping + run_exports: {} size: 4626882 timestamp: 1769194859566 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda @@ -18357,6 +20721,7 @@ packages: license_family: BSD purls: - pkg:pypi/sphinxcontrib-applehelp?source=hash-mapping + run_exports: {} size: 29752 timestamp: 1733754216334 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda @@ -18369,6 +20734,7 @@ packages: license_family: BSD purls: - pkg:pypi/sphinxcontrib-devhelp?source=hash-mapping + run_exports: {} size: 24536 timestamp: 1733754232002 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda @@ -18381,6 +20747,7 @@ packages: license_family: BSD purls: - pkg:pypi/sphinxcontrib-htmlhelp?source=hash-mapping + run_exports: {} size: 32895 timestamp: 1733754385092 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jquery-4.1-pyhd8ed1ab_1.conda @@ -18392,6 +20759,7 @@ packages: license: 0BSD AND MIT purls: - pkg:pypi/sphinxcontrib-jquery?source=hash-mapping + run_exports: {} size: 112964 timestamp: 1734344603903 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_1.conda @@ -18403,6 +20771,7 @@ packages: license_family: BSD purls: - pkg:pypi/sphinxcontrib-jsmath?source=hash-mapping + run_exports: {} size: 10462 timestamp: 1733753857224 - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-2.0.0-pyhd8ed1ab_1.conda @@ -18415,20 +20784,22 @@ packages: license_family: BSD purls: - pkg:pypi/sphinxcontrib-qthelp?source=hash-mapping + run_exports: {} size: 26959 timestamp: 1733753505008 -- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_1.conda - sha256: 64d89ecc0264347486971a94487cb8d7c65bfc0176750cf7502b8a272f4ab557 - md5: 3bc61f7161d28137797e038263c04c54 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-2.0.0-pyhd8ed1ab_0.conda + sha256: 20b49741065fd7d3fabf98caf6d19b6436badb06b6d41f66b58f1fc2b52f37a1 + md5: f77df1fcf9af03b7287342638befca77 depends: - - python >=3.9 + - python >=3.10 - sphinx >=5 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/sphinxcontrib-serializinghtml?source=hash-mapping - size: 28669 - timestamp: 1733750596111 + run_exports: {} + size: 30640 + timestamp: 1781260357443 - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda sha256: 570da295d421661af487f1595045760526964f41471021056e993e73089e9c41 md5: b1b505328da7a6b246787df4b5a49fbc @@ -18441,6 +20812,7 @@ packages: license_family: MIT purls: - pkg:pypi/stack-data?source=hash-mapping + run_exports: {} size: 26988 timestamp: 1733569565672 - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda @@ -18453,9 +20825,6 @@ packages: license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later license_family: GPL purls: [] - run_exports: - strong: - - __glibc >=2.28,<3.0.a0 run_exports: strong: - __glibc >=2.28,<3.0.a0 @@ -18471,9 +20840,6 @@ packages: license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later license_family: GPL purls: [] - run_exports: - strong: - - __glibc >=2.28,<3.0.a0 run_exports: strong: - __glibc >=2.28,<3.0.a0 @@ -18489,6 +20855,7 @@ packages: license_family: MIT purls: - pkg:pypi/toml?source=hash-mapping + run_exports: {} size: 24017 timestamp: 1764486833072 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda @@ -18501,6 +20868,7 @@ packages: license_family: MIT purls: - pkg:pypi/tomli?source=hash-mapping + run_exports: {} size: 21561 timestamp: 1774492402955 - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.1-pyhcf101f3_0.conda @@ -18513,6 +20881,7 @@ packages: license_family: BSD purls: - pkg:pypi/traitlets?source=compressed-mapping + run_exports: {} size: 115158 timestamp: 1780507822178 - conda: https://conda.anaconda.org/conda-forge/noarch/transforms3d-0.4.2-pyhd8ed1ab_1.conda @@ -18525,6 +20894,7 @@ packages: license_family: BSD purls: - pkg:pypi/transforms3d?source=hash-mapping + run_exports: {} size: 2690384 timestamp: 1734511238605 - conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda @@ -18541,25 +20911,27 @@ packages: license_family: MIT purls: - pkg:pypi/typeguard?source=hash-mapping + run_exports: {} size: 38297 timestamp: 1778779291237 -- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 - md5: 0caa1af407ecff61170c9437a808404d +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + sha256: 2d888f90af0686044882c74193ec80a90ec1943145d94a7b1b048958acda1848 + md5: c70ad746c22219b9700931707482992c depends: - python >=3.10 - python license: PSF-2.0 - license_family: PSF purls: - - pkg:pypi/typing-extensions?source=hash-mapping - size: 51692 - timestamp: 1756220668932 + - pkg:pypi/typing-extensions?source=compressed-mapping + run_exports: {} + size: 52631 + timestamp: 1783002732887 - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c md5: ad659d0a2b3e47e38d829aa8cad2d610 license: LicenseRef-Public-Domain purls: [] + run_exports: {} size: 119135 timestamp: 1767016325805 - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda @@ -18575,26 +20947,28 @@ packages: license_family: MIT purls: - pkg:pypi/urllib3?source=hash-mapping + run_exports: {} size: 103560 timestamp: 1778188657149 -- conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.4.2-pyhcf101f3_0.conda - sha256: 83d10be1b436fef778e7982f24a1f117b7aa34817135ec8b0ad63ee4455943eb - md5: 52434c636a05a06806d0978128d98c19 +- conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.5.1-pyhcf101f3_0.conda + sha256: 0a7b0a2ada7ad719f9d4f8874eb10911e1fcfdecefc86456105eb806ebd60ac4 + md5: e449fb99b714be1e13fa5564dacd1af5 depends: - python >=3.10 - distlib >=0.3.7,<1 - filelock <4,>=3.24.2 - importlib-metadata >=6.6 - platformdirs >=3.9.1,<5 - - python-discovery >=1.4 + - python-discovery >=1.4.2 - typing_extensions >=4.13.2 - python license: MIT license_family: MIT purls: - pkg:pypi/virtualenv?source=hash-mapping - size: 5151645 - timestamp: 1780253977667 + run_exports: {} + size: 3111990 + timestamp: 1781651033074 - conda: https://conda.anaconda.org/conda-forge/noarch/wadler-lindig-0.1.7-pyhe01879c_0.conda sha256: af400decd8578d521c752594bb9380eb4d1e1e53e919c18dd2d65429f032e36c md5: d93a6a7cf86ac0c6c2f00c287c3a030c @@ -18605,27 +20979,30 @@ packages: license_family: APACHE purls: - pkg:pypi/wadler-lindig?source=hash-mapping + run_exports: {} size: 28051 timestamp: 1752728420929 -- conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.47-hd8ed1ab_0.conda - sha256: 9ab2c12053ea8984228dd573114ffc6d63df42c501d59fda3bf3aeb1eaa1d23e - md5: 7da1571f560d4ba3343f7f4c48a79c76 +- conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.49-hd8ed1ab_0.conda + sha256: 04ce686cd187d379344f9b2be7b4da5f431b265dc0944a6b764fab9da9171948 + md5: 0839a3421140d4a9ba93fb988698fc00 license: MIT license_family: MIT purls: [] - size: 140476 - timestamp: 1765821981856 -- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.0-pyhd8ed1ab_0.conda - sha256: 017f6b2777b3959f82ae1b04024569f7ed22928e58246be17e26a36ff6c85d52 - md5: 65a429ac9a8352c7ba890eb326bbfaf5 + run_exports: {} + size: 147954 + timestamp: 1780946721169 +- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-pyhd8ed1ab_0.conda + sha256: 4acf845da404e84cef1acccc66cc0156af1b83a5b5d7077b2ca19b705c561e57 + md5: 99f7755ec8648a042b0dbe906234f888 depends: - python >=3.10 license: MIT license_family: MIT purls: - - pkg:pypi/wcwidth?source=hash-mapping - size: 136960 - timestamp: 1780736911642 + - pkg:pypi/wcwidth?source=compressed-mapping + run_exports: {} + size: 132415 + timestamp: 1782771807703 - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.8-pyhcf101f3_0.conda sha256: 5108c1bf2f0512e5c9dc8191e31b144c23b7cf0e73423a246173006002368d79 md5: 3eeca039e7316268627f4116da9df64c @@ -18637,6 +21014,7 @@ packages: license_family: BSD purls: - pkg:pypi/werkzeug?source=hash-mapping + run_exports: {} size: 258232 timestamp: 1775160081069 - conda: https://conda.anaconda.org/conda-forge/noarch/wslink-2.5.7-pyhd8ed1ab_0.conda @@ -18650,6 +21028,7 @@ packages: license_family: BSD purls: - pkg:pypi/wslink?source=compressed-mapping + run_exports: {} size: 36803 timestamp: 1778826669944 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda @@ -18662,6 +21041,7 @@ packages: license_family: MIT purls: - pkg:pypi/zipp?source=compressed-mapping + run_exports: {} size: 24190 timestamp: 1779159948016 - conda: https://conda.anaconda.org/robostack-jazzy/linux-64/ros-jazzy-action-msgs-2.0.3-np2py312h2ed9cc7_16.conda @@ -34836,9 +37216,6 @@ packages: license: BSD-3-Clause size: 2334 timestamp: 1771181488082 -- conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda - sha256: 8d6ce89805148cd661bb2f4406631c0251b2ded3a9b42b7d1160eff9b5778c9b - md5: a5a82453b80fcb05372b42cab5c43204 - conda: https://data.bit-bots.de/conda-misc/output/linux-64/libonnxruntime-webgpu-1.24.3-hb0f4dca_3.conda sha256: 8d6ce89805148cd661bb2f4406631c0251b2ded3a9b42b7d1160eff9b5778c9b md5: a5a82453b80fcb05372b42cab5c43204 @@ -34848,8 +37225,6 @@ packages: license: MIT size: 10651622 timestamp: 1782745906333 - size: 10651622 - timestamp: 1782745906333 - conda: https://data.bit-bots.de/conda-misc/output/linux-aarch64/libonnxruntime-webgpu-1.24.3-he8cfe8b_0.conda sha256: 4876857396a9a049cfa8b12e4e450c8f4288f471788817476084945737c1d2ae md5: de18b3bee6102a8ee4212cf6e1d675e9 @@ -34879,14 +37254,82 @@ packages: license: LicenseRef-openrail size: 244991335 timestamp: 1771976595791 -- conda_source: bitbots_rust_nav[77771cb3] @ src/bitbots_navigation/bitbots_rust_nav +- conda_source: bitbots_rust_nav[146a3083] @ src/bitbots_navigation/bitbots_rust_nav variants: c_stdlib: sysroot c_stdlib_version: '2.28' - target_platform: linux-aarch64 + target_platform: linux-64 depends: - python >=3.12 - __glibc >=2.28,<3.0.a0 + - python_abi 3.12.* *_cp312 + constrains: + - __glibc >=2.17 + - __glibc >=2.17 + build_packages: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.45.1-default_h4852527_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-15.2.0-h7be306e_27.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.96.0-h53717f1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust_linux-64-1.96.0-hd58cd63_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.96.0-h2c6d0dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + host_packages: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.14.1-py310h2b5ca13_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.91.1-h53717f1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.26-h26efc2c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.91.1-h2c6d0dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda +- conda_source: bitbots_rust_nav[36aa2fce] @ src/bitbots_navigation/bitbots_rust_nav + variants: + c_stdlib: sysroot + c_stdlib_version: '2.28' + target_platform: linux-aarch64 + depends: + - python >=3.12 - __glibc >=2.28,<3.0.a0 - python_abi 3.12.* *_cp312 constrains: @@ -34897,20 +37340,20 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.45.1-default_h5f4c503_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.45.1-default_hf1166c9_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-15.2.0-h74e174c_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-15.2.0-h0bf4bd8_25.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-15.2.0-h0bf4bd8_27.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-15.2.0-he19c465_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust-1.95.0-h6cf38e9_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust_linux-aarch64-1.95.0-hd7b9871_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust-1.96.0-h6cf38e9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust_linux-aarch64-1.96.0-hb84128a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-15.2.0-h55c397f_119.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-15.2.0-ha7b1723_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-unknown-linux-gnu-1.95.0-hbe8e118_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-unknown-linux-gnu-1.96.0-hbe8e118_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda host_packages: @@ -34920,7 +37363,7 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-15.2.0-h74e174c_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda @@ -34928,20 +37371,20 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-15.2.0-he19c465_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.2-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.3-h10b116e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.2-h1022ec0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.13.3-py310he8189be_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.14.1-py310he8189be_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.3-h546c87b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.13-h91f4b29_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rust-1.91.1-h6cf38e9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uv-0.11.19-haa595b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uv-0.11.26-haa595b2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-15.2.0-h55c397f_119.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-15.2.0-ha7b1723_119.conda @@ -34950,75 +37393,6 @@ packages: - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda -- conda_source: bitbots_rust_nav[eb738ce2] @ src/bitbots_navigation/bitbots_rust_nav - variants: - c_stdlib: sysroot - c_stdlib_version: '2.28' - target_platform: linux-64 - depends: - - python >=3.12 - - __glibc >=2.28,<3.0.a0 - - python_abi 3.12.* *_cp312 - constrains: - - __glibc >=2.17 - - __glibc >=2.17 - build_packages: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.45.1-default_h4852527_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-15.2.0-h7be306e_25.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.95.0-h53717f1_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rust_linux-64-1.95.0-hb4ea61c_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.95.0-h2c6d0dc_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - host_packages: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.2.0-ha6850e4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.2.0-h90f66d4_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.2-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.13.3-py310h2b5ca13_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.91.1-h53717f1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.19-h26efc2c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.2.0-hcc6f6b0_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.2.0-hd446a21_119.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.91.1-h2c6d0dc_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://data.bit-bots.de/conda-misc/output/noarch/readline-8.3-h4616a5c_1.conda - pypi: https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl name: trimesh version: 4.12.2 @@ -35085,19 +37459,6 @@ packages: version: '16.0' sha256: 9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl - name: beautifulsoup4 - version: 4.14.3 - sha256: 0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb - requires_dist: - - soupsieve>=1.6.1 - - typing-extensions>=4.0.0 - - cchardet ; extra == 'cchardet' - - chardet ; extra == 'chardet' - - charset-normalizer ; extra == 'charset-normalizer' - - html5lib ; extra == 'html5lib' - - lxml ; extra == 'lxml' - requires_python: '>=3.7.0' - pypi: https://files.pythonhosted.org/packages/1e/15/efef5a2f204a64bdb5571e6161d49f7ef0fffdbca953a615efbec045f60f/zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl name: zstandard version: 0.25.0 @@ -35106,26 +37467,6 @@ packages: - cffi~=1.17 ; python_full_version < '3.14' and platform_python_implementation != 'PyPy' and extra == 'cffi' - cffi>=2.0.0b0 ; python_full_version >= '3.14' and platform_python_implementation != 'PyPy' and extra == 'cffi' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/47/aa/218a0eb34de1f753c83e4d0d1c8e7c4cef27f20dcb8342e024f63a80dc86/tqdm-4.68.1-py3-none-any.whl - name: tqdm - version: 4.68.1 - sha256: fea4a90e4023f764914569f7802a297277c5ab1a66be5144143e142e1a4031d8 - requires_dist: - - colorama ; sys_platform == 'win32' - - importlib-metadata ; python_full_version < '3.8' - - pytest>=6 ; extra == 'dev' - - pytest-cov ; extra == 'dev' - - pytest-timeout ; extra == 'dev' - - pytest-asyncio>=0.24 ; extra == 'dev' - - nbval ; extra == 'dev' - - requests ; extra == 'discord' - - envwrap ; extra == 'discord' - - slack-sdk ; extra == 'slack' - - envwrap ; extra == 'slack' - - requests ; extra == 'telegram' - - envwrap ; extra == 'telegram' - - ipywidgets>=6 ; extra == 'notebook' - requires_python: '>=3.7' - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl name: imageio version: 2.37.3 @@ -35252,6 +37593,26 @@ packages: version: 2.8.4 sha256: e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65 requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/69/80/0c7095f357afeb52100d312250354d2e76afb779c81fe3fb52118076fa5a/syrupy-5.4.0-py3-none-any.whl + name: syrupy + version: 5.4.0 + sha256: 3079017f0c6d3c1b293b57ad2af15cc7851d8eceba922896bdb3bc4834df4ce8 + requires_dist: + - pytest>=8.0.0 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/88/c6/92fcd42f1ba33e1184263f25bfabf3d27c383410470f169e4b8163bf9c17/beautifulsoup4-4.15.0-py3-none-any.whl + name: beautifulsoup4 + version: 4.15.0 + sha256: d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9 + requires_dist: + - soupsieve>=1.6.1 + - typing-extensions>=4.0.0 + - cchardet ; extra == 'cchardet' + - chardet ; extra == 'chardet' + - charset-normalizer ; extra == 'charset-normalizer' + - html5lib ; extra == 'html5lib' + - lxml ; extra == 'lxml' + requires_python: '>=3.7.0' - pypi: https://files.pythonhosted.org/packages/8a/37/655101799590bcc5fddb2bd3fe0e6194e816c2d1da7c361725f5eb89a910/msgspec-0.21.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl name: msgspec version: 0.21.1 @@ -35275,13 +37636,20 @@ packages: - tomli-w ; extra == 'toml' - pyyaml ; extra == 'yaml' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/d4/f4/753003ddb0d43247febecd5146391a59b80f77e462b2623396192180f4ee/syrupy-5.3.1-py3-none-any.whl - name: syrupy - version: 5.3.1 - sha256: d755c2bb9b78692de1db5efa7b452ebff727df3a8290f740bda5c55a4ea5d7d5 +- pypi: https://files.pythonhosted.org/packages/d8/8e/bb97bb0c71802080bfc8952937d174e49cfc50de5c951dd47b2496f0dcdb/tqdm-4.68.3-py3-none-any.whl + name: tqdm + version: 4.68.3 + sha256: 39832cc2def2789a6f29df83f172db7416cea70052c0907a57801c5f2fdccb03 requires_dist: - - pytest>=8.0.0 - requires_python: '>=3.10' + - colorama ; sys_platform == 'win32' + - requests ; extra == 'discord' + - envwrap ; extra == 'discord' + - slack-sdk ; extra == 'slack' + - envwrap ; extra == 'slack' + - requests ; extra == 'telegram' + - envwrap ; extra == 'telegram' + - ipywidgets>=6 ; extra == 'notebook' + requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/ea/78/9a8a174011682d71cb4922f4014ebbeb9d3067922678e7059351fd9207cf/exhale-0.3.7-py3-none-any.whl name: exhale version: 0.3.7 diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index ee4776cbf..29833ac17 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -396,45 +396,6 @@ def _compute_formation( head = {} # role -> heading (rad); filled lazily, completed after separation kick_aim = None # striker's kick direction; used to clear the kick lane - - # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # - defender_roles = [r for r in roles if r.startswith(Role.DEFENDER + "_")] - m = len(defender_roles) - if m > 0: - depth = np.clip( - params.alpha * d + params.depth_bias, # push up + fwd/back bias - params.D_min, - params.D_max, - ) - depth = min(depth, max(d - params.standoff, 0.0)) # stay goal-side of the ball - depth = max(depth, params.d_g + params.dz) # stay ahead of the goalie - anchor = goal + depth * to_ball - if m == 1: - # a single defender: shade to the centre side so it doesn't sit on the - # striker<->goalie line (otherwise all three are collinear) - side_dir = -1.0 if b[1] >= 0 else 1.0 - offsets = [params.def_side * side_dir] - else: - offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] - for r, off in zip(defender_roles, offsets): - out[r] = self._clamp_field(anchor + off * perp, field) - - # --- supporter: slightly in front of the ball, kept inside the field -------- # - if Role.SUPPORTER in roles: - # always sit to the centre side of the ball; hard swap so it is never - # directly in front of the striker, even when the ball is on the centre line - side_dir = -1.0 if b[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) - sup = b + np.array([params.f, params.supp_side * side_dir]) - sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner - out[Role.SUPPORTER] = self._clamp_field(sup, field) - - # --- min-separation repulsion + kick-lane clearance ----------------------- # - self._separate(out, field, params, b, kick_aim) - - # --- freekick: push every robot outside the mandatory clearance radius ---- # - if params.opp_freekick: - self._clear_ball(out, b, params.opp_freekick_clearance, field) - # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # if Role.STRIKER in roles: if params.opp_freekick: @@ -476,6 +437,45 @@ def _compute_formation( ) out[Role.GOALIE] = g + + # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # + defender_roles = [r for r in roles if r.startswith(Role.DEFENDER + "_")] + m = len(defender_roles) + if m > 0: + depth = np.clip( + params.alpha * d + params.depth_bias, # push up + fwd/back bias + params.D_min, + params.D_max, + ) + depth = min(depth, max(d - params.standoff, 0.0)) # stay goal-side of the ball + depth = max(depth, params.d_g + params.dz) # stay ahead of the goalie + anchor = goal + depth * to_ball + if m == 1: + # a single defender: shade to the centre side so it doesn't sit on the + # striker<->goalie line (otherwise all three are collinear) + side_dir = -1.0 if b[1] >= 0 else 1.0 + offsets = [params.def_side * side_dir] + else: + offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] + for r, off in zip(defender_roles, offsets): + out[r] = self._clamp_field(anchor + off * perp, field) + + # --- supporter: slightly in front of the ball, kept inside the field -------- # + if Role.SUPPORTER in roles: + # always sit to the centre side of the ball; hard swap so it is never + # directly in front of the striker, even when the ball is on the centre line + side_dir = -1.0 if b[1] >= 0 else 1.0 # points toward y=0 (default: centre-ward) + sup = b + np.array([params.f, params.supp_side * side_dir]) + sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner + out[Role.SUPPORTER] = self._clamp_field(sup, field) + + # --- min-separation repulsion + kick-lane clearance ----------------------- # + self._separate(out, field, params, b, kick_aim) + + # --- freekick: push every robot outside the mandatory clearance radius ---- # + if params.opp_freekick: + self._clear_ball(out, b, params.opp_freekick_clearance, field) + # --- orientations (computed from the final positions) --------------------- # for role, p in out.items(): if role in head: diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index 012a2bc34..b6128f52f 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -42,7 +42,7 @@ def _ax(b): s_kclr = Slider(_ax(0.140), "kick clear", 0.0, 1.5, valinit=params.kick_clear) s_gout = Slider(_ax(0.110), "goalie out", 0.2, 2.0, valinit=params.d_g) check_fk = CheckButtons(plt.axes([0.18, 0.073, 0.20, 0.022]), ["freekick"], [False]) - s_fkcl = Slider(_ax(0.050), "fk clearance", 0.1, 2.0, valinit=params.freekick_clearance) + s_fkcl = Slider(_ax(0.050), "fk clearance", 0.1, 2.0, valinit=params.opp_freekick_clearance) def draw(): ax.clear() @@ -66,7 +66,7 @@ def draw(): params.post_margin, params.back_dist = s_pmarg.val, s_back.val params.kick_clear = s_kclr.val params.freekick = check_fk.get_status()[0] - params.freekick_clearance = s_fkcl.val + params.opp_freekick_clearance = s_fkcl.val n = int(s_n.val) if params.freekick: @@ -88,7 +88,7 @@ def draw(): prev = state["prev"] if prev is not None and len(prev) == len(new_items): - for old_idx, new_pose, role in _inner._match_assignment(prev, new_items, state["ball"]): + for old_idx, new_pose, role in _inner._match_assignment(prev, new_items, state["ball"], None): old_pose = prev[old_idx] c = colors.get(role.split("_")[0], "#1f77b4") ax.plot([old_pose[0], new_pose[0]], [old_pose[1], new_pose[1]], ls=":", color=c, lw=1.5, zorder=3) From fa5e0ce1961f949ce675edb777b2ab555c51d615 Mon Sep 17 00:00:00 2001 From: ayin21 Date: Fri, 3 Jul 2026 12:02:42 +0200 Subject: [PATCH 35/68] rewrite action --- .../actions/go_to_formation_position.py | 51 ++++++++++++------- .../behavior_dsd/main.dsd | 18 +++---- .../config/body_behavior.yaml | 15 ++++++ 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py index 4768ac429..149bb20c4 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py @@ -14,37 +14,54 @@ class GoToFormationPosition(AbstractActionElement): def __init__(self, blackboard, dsd, parameters): super().__init__(blackboard, dsd, parameters) + self.stand = parameters.get("stand", False) + self.on_position_threshold = parameters["enter_position"] + self.off_position_threshold = parameters["leave_position"] + self.on_orientation_threshold = parameters["enter_orientation"] + self.off_orientation_threshold = parameters["leave_orientation"] + self.standing_on_target = False + def perform(self, reevaluate=False): - pose_msg = PoseStamped() - pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() - pose_msg.header.frame_id = self.blackboard.map_frame optimal_positioning = self.blackboard.positioning.get_formation_assignment() - own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] - pose = own_position["goal_pose"] - pose_msg.pose.position.x = pose[0] - pose_msg.pose.position.y = pose[1] - pose_msg.pose.orientation.w = pose[2] + own_target = optimal_positioning[self.blackboard.gamestate.get_own_id()] current_pose = self.blackboard.world_model.get_current_position_pose_stamped() - #Dont try the check without current_pose, we dont want to stop a robot while going to ball, or kicking - if current_pose is None or self.blackboard.team_data.strategy.action == 2 or self.blackboard.team_data.strategy.action == 6: - self.blackboard.pathfinding.publish(pose_msg) - return - current_orientation = euler_from_quaternion(numpify(current_pose.pose.orientation)) goal_orientation = euler_from_quaternion(numpify(pose.pose.orientation)) angle_to_goal_orientation = abs(math.remainder(current_orientation[2] - goal_orientation[2], math.tau)) + + + distance = np.linalg.norm(numpify(pose.pose.position) - numpify(current_pose.pose.position)) + self.publish_debug_data("current_orientation", current_orientation[2]) self.publish_debug_data("goal_orientation", goal_orientation[2]) self.publish_debug_data("angle_to_goal_orientation", angle_to_goal_orientation) - - distance = np.linalg.norm(numpify(pose.pose.position) - numpify(current_pose.pose.position)) self.publish_debug_data("distance", distance) - if distance < 0.2 and angle_to_goal_orientation < 0.2: + assert self.on_position_threshold < self.off_position_threshold, "on_position_threshold must be smaller than off_position_threshold" + assert self.on_orientation_threshold < self.off_orientation_threshold, "on_orientation_threshold must be smaller than off_orientation_threshold" + + if distance < self.on_position_threshold and angle_to_goal_orientation < self.on_orientation_threshold and self.stand: + self.standing_on_target = True + + if self.standing_on_target and (distance < self.off_position_threshold or angle_to_goal_orientation < self.off_orientation_threshold): # Cancel the path planning if it is running self.blackboard.pathfinding.cancel_goal() # need to keep publishing this since path planning publishes a few more messages self.blackboard.pathfinding.stop_walk() - self.blackboard.pathfinding.publish(pose_msg) + else: + self.standing_on_target = False + + pose_msg = PoseStamped() + pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() + pose_msg.header.frame_id = self.blackboard.map_frame + + pose = own_target["goal_pose"] + pose_msg.pose.position.x = pose[0] + pose_msg.pose.position.y = pose[1] + pose_msg.pose.orientation.w = pose[2] + + self.blackboard.pathfinding.publish(pose_msg) + + diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 7c3fb82e7..b7b77dbe1 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -54,12 +54,10 @@ $GoalScoreRecently #SupporterRole $BallSeen - YES --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:0.2 + latch:true - YES --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @Stand - NO --> $PassStarted - YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + YES --> $PassStarted + YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + enter_position:%support_enter_position + leave_position:%support_leave_position + enter_orientation:%support_enter_orientation + leave_orientation:%support_leave_orientation + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + enter_position:%support_enter_position + leave_position:%support_leave_position + enter_orientation:%support_enter_orientation + leave_orientation:%support_leave_orientation #PenaltyShootoutBehavior @@ -76,7 +74,7 @@ $SecondaryStateTeamDecider #Placing $DoOnce NOT_DONE --> @ForgetBall, @LookAtFieldFeatures - DONE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition + DONE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition + enter_position:%placing_enter_position + leave_position:%placing_leave_position + enter_orientation:%placing_enter_orientation + leave_orientation:%placing_leave_orientation #Init @@ -84,7 +82,7 @@ $DoOnce #NormalBehavior $SecondBallTouchAllowed - NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToFormationPosition + blocking:true + NO --> @SetNoSecondBallContactVariable + value:false + r:false, @LookAtFieldFeatures + r:false, @ChangeAction + action:passive + r:false, @AvoidBallActive + r:false, @GoToFormationPosition //defender variables YES --> $BallSeen NO --> $ConfigRole STRIKER --> #SearchBall @@ -95,7 +93,9 @@ $SecondBallTouchAllowed YES --> $AssignedRole STRIKER --> #KickWithAvoidance SUPPORTER --> #SupporterRole - ELSE --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + ELSE --> $BallInOwnPercentOfField + p:40 + YES --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + enter_position:%defender_enter_position + leave_position:%defender_leave_position + enter_orientation:%defender_enter_orientation + leave_orientation:%defender_leave_orientation #ThrowinGoalKickCornerkickBehavior $DoOnce diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index 371b8a853..87a930be0 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -53,6 +53,21 @@ body_behavior: 1: [ -0.085, 0.33 ] 2: [ -0.085, -0.33 ] + support_enter_position: 0.1 + support_leave_position: 0.3 + support_enter_orientation: 0.1 + support_leave_orientation: 0.3 + + defender_enter_position: 0.2 + defender_leave_position: 0.5 + defender_enter_orientation: 0.1 + defender_leave_orientation: 0.3 + + placing_enter_position: 0.05 + placing_leave_position: 0.2 + placing_enter_orientation: 0.05 + placing_leave_orientation: 0.1 + # Time to wait in ready state before moving to role position to give the localization time to converge. ready_wait_time: 2.0 From 9ddf72dce9d77e5455282113f43c21ef0b914f99 Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Fri, 3 Jul 2026 21:37:09 +0900 Subject: [PATCH 36/68] Fix various issues with GoToFormationPosition --- .../actions/go_to_formation_position.py | 44 ++++++++++++------- .../behavior_dsd/decisions/closest_to_ball.py | 2 +- .../behavior_dsd/main.dsd | 12 ++--- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py index 149bb20c4..3b7588547 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py @@ -5,7 +5,7 @@ from dynamic_stack_decider.abstract_action_element import AbstractActionElement from tf2_geometry_msgs import PoseStamped from ros2_numpy import numpify -from tf_transformations import euler_from_quaternion +from tf_transformations import euler_from_quaternion, quaternion_from_euler class GoToFormationPosition(AbstractActionElement): @@ -15,37 +15,43 @@ def __init__(self, blackboard, dsd, parameters): super().__init__(blackboard, dsd, parameters) self.stand = parameters.get("stand", False) - self.on_position_threshold = parameters["enter_position"] - self.off_position_threshold = parameters["leave_position"] - self.on_orientation_threshold = parameters["enter_orientation"] - self.off_orientation_threshold = parameters["leave_orientation"] + if self.stand: + self.on_position_threshold = parameters["enter_position"] + self.off_position_threshold = parameters["leave_position"] + self.on_orientation_threshold = parameters["enter_orientation"] + self.off_orientation_threshold = parameters["leave_orientation"] + else: + self.on_position_threshold = None + self.off_position_threshold = None + self.on_orientation_threshold = None + self.off_orientation_threshold = None self.standing_on_target = False def perform(self, reevaluate=False): optimal_positioning = self.blackboard.positioning.get_formation_assignment() own_target = optimal_positioning[self.blackboard.gamestate.get_own_id()] + goal_pose = own_target["goal_pose"] # [x, y, orientation] current_pose = self.blackboard.world_model.get_current_position_pose_stamped() current_orientation = euler_from_quaternion(numpify(current_pose.pose.orientation)) - goal_orientation = euler_from_quaternion(numpify(pose.pose.orientation)) - angle_to_goal_orientation = abs(math.remainder(current_orientation[2] - goal_orientation[2], math.tau)) + angle_to_goal_orientation = abs(math.remainder(current_orientation[2] - goal_pose[2], math.tau)) - distance = np.linalg.norm(numpify(pose.pose.position) - numpify(current_pose.pose.position)) + distance = np.linalg.norm(goal_pose[:2] - numpify(current_pose.pose.position)[:2]) self.publish_debug_data("current_orientation", current_orientation[2]) - self.publish_debug_data("goal_orientation", goal_orientation[2]) + self.publish_debug_data("goal_orientation", goal_pose[2]) self.publish_debug_data("angle_to_goal_orientation", angle_to_goal_orientation) self.publish_debug_data("distance", distance) - assert self.on_position_threshold < self.off_position_threshold, "on_position_threshold must be smaller than off_position_threshold" - assert self.on_orientation_threshold < self.off_orientation_threshold, "on_orientation_threshold must be smaller than off_orientation_threshold" + assert not self.stand or self.on_position_threshold < self.off_position_threshold, "on_position_threshold must be smaller than off_position_threshold" + assert not self.stand or self.on_orientation_threshold < self.off_orientation_threshold, "on_orientation_threshold must be smaller than off_orientation_threshold" - if distance < self.on_position_threshold and angle_to_goal_orientation < self.on_orientation_threshold and self.stand: + if self.stand and distance < self.on_position_threshold and angle_to_goal_orientation < self.on_orientation_threshold: self.standing_on_target = True - if self.standing_on_target and (distance < self.off_position_threshold or angle_to_goal_orientation < self.off_orientation_threshold): + if self.standing_on_target and (distance < self.off_position_threshold and angle_to_goal_orientation < self.off_orientation_threshold): # Cancel the path planning if it is running self.blackboard.pathfinding.cancel_goal() # need to keep publishing this since path planning publishes a few more messages @@ -57,10 +63,14 @@ def perform(self, reevaluate=False): pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() pose_msg.header.frame_id = self.blackboard.map_frame - pose = own_target["goal_pose"] - pose_msg.pose.position.x = pose[0] - pose_msg.pose.position.y = pose[1] - pose_msg.pose.orientation.w = pose[2] + goal_pose = own_target["goal_pose"] + pose_msg.pose.position.x = goal_pose[0] + pose_msg.pose.position.y = goal_pose[1] + quat = quaternion_from_euler(0, 0, goal_pose[2]) + pose_msg.pose.orientation.x = quat[0] + pose_msg.pose.orientation.y = quat[1] + pose_msg.pose.orientation.z = quat[2] + pose_msg.pose.orientation.w = quat[3] self.blackboard.pathfinding.publish(pose_msg) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index cc83a2842..938da5919 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -49,7 +49,7 @@ def __init__(self, blackboard, dsd, parameters): def perform(self, reevaluate=False): role = self.blackboard.positioning.get_own_role() self.publish_debug_data("Role from positioning", role) - return role + return role.upper() """if role == "STRIKER": return "STRIKER" elif role == 2: diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index b7b77dbe1..fae2a45c5 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -56,8 +56,8 @@ $GoalScoreRecently $BallSeen YES --> $PassStarted YES --> @TrackBall, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + enter_position:%support_enter_position + leave_position:%support_leave_position + enter_orientation:%support_enter_orientation + leave_orientation:%support_leave_orientation - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + enter_position:%support_enter_position + leave_position:%support_leave_position + enter_orientation:%support_enter_orientation + leave_orientation:%support_leave_orientation + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + stand:true + enter_position:%support_enter_position + leave_position:%support_leave_position + enter_orientation:%support_enter_orientation + leave_orientation:%support_leave_orientation + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @AvoidBallActive, @GoToFormationPosition + stand:true + enter_position:%support_enter_position + leave_position:%support_leave_position + enter_orientation:%support_enter_orientation + leave_orientation:%support_leave_orientation #PenaltyShootoutBehavior @@ -74,7 +74,7 @@ $SecondaryStateTeamDecider #Placing $DoOnce NOT_DONE --> @ForgetBall, @LookAtFieldFeatures - DONE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition + enter_position:%placing_enter_position + leave_position:%placing_leave_position + enter_orientation:%placing_enter_orientation + leave_orientation:%placing_leave_orientation + DONE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition + stand:true + enter_position:%placing_enter_position + leave_position:%placing_leave_position + enter_orientation:%placing_enter_orientation + leave_orientation:%placing_leave_orientation #Init @@ -93,9 +93,9 @@ $SecondBallTouchAllowed YES --> $AssignedRole STRIKER --> #KickWithAvoidance SUPPORTER --> #SupporterRole - ELSE --> $BallInOwnPercentOfField + p:40 - YES --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + enter_position:%defender_enter_position + leave_position:%defender_leave_position + enter_orientation:%defender_enter_orientation + leave_orientation:%defender_leave_orientation + ELSE --> $BallInOwnPercent + p:40 + YES --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + stand:true + enter_position:%defender_enter_position + leave_position:%defender_leave_position + enter_orientation:%defender_enter_orientation + leave_orientation:%defender_leave_orientation #ThrowinGoalKickCornerkickBehavior $DoOnce From 5551f44319bd5d17d964be49e1e75606e518e23b Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Fri, 3 Jul 2026 23:44:01 +0900 Subject: [PATCH 37/68] Remove Init Animation --- .../capsules/animation_capsule.py | 1 - .../behavior_dsd/actions/play_animation.py | 15 +------- .../behavior_dsd/main.dsd | 2 +- .../config/animations.yaml | 1 - .../hcm_dsd/actions/play_animation.py | 5 --- .../bitbots_hcm/bitbots_hcm/hcm_dsd/hcm.dsd | 4 +-- .../animations/misc/init.json | 34 ------------------- 7 files changed, 3 insertions(+), 59 deletions(-) delete mode 100644 src/bitbots_robot/piplus_animations/animations/misc/init.json diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/animation_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/animation_capsule.py index 22dd79a30..e9edf9938 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/animation_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/animation_capsule.py @@ -20,7 +20,6 @@ def __init__(self, node, blackboard): self.goalie_falling_left_animation: str = self._node.get_parameter("Animations.Goalie.fallLeft").value self.goalie_falling_center_animation: str = self._node.get_parameter("Animations.Goalie.fallCenter").value self.cheering_animation: str = self._node.get_parameter("Animations.Misc.cheering").value - self.init_animation: str = self._node.get_parameter("Animations.Misc.init").value self.animation_client = ActionClient( self._node, PlayAnimation, "animation", callback_group=ReentrantCallbackGroup() diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/play_animation.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/play_animation.py index 53840f312..04ac170f8 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/play_animation.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/play_animation.py @@ -84,17 +84,4 @@ def get_animation_name(self): class PlayAnimationThrow(AbstractPlayAnimation): def get_animation_name(self): self.blackboard.node.get_logger().info("PLAYING THROW-IN ANIMATION") - return self.blackboard.animation.throw_animation - - -class PlayAnimationInit(AbstractPlayAnimation): - def get_animation_name(self): - return self.blackboard.animation.init_animation - - -class PlayAnimationInitInSim(PlayAnimationInit): - def perform(self, reevaluate=False): - if self.blackboard.in_sim: - return super().perform(reevaluate) - else: - return self.pop() + return self.blackboard.animation.throw_animation \ No newline at end of file diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 929595755..93a3f892f 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -18,7 +18,7 @@ $DoOnce @ChangeAction + action:waiting, @LookAtFieldFeatures, @Stand #GetWalkreadyAndLocalize -@ChangeAction + action:waiting + r:false, @PlayAnimationInitInSim + r:false, @LookAtFieldFeatures + r:false, @WalkInPlace +@ChangeAction + action:waiting + r:false, @LookAtFieldFeatures + r:false, @WalkInPlace #Dribble @ChangeAction + action:kicking, @CancelPathplanning, @LookAtFront, @DribbleForward diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/animations.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/animations.yaml index fdfa1bf08..67b33cee9 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/animations.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/animations.yaml @@ -11,4 +11,3 @@ throw: "throw" Misc: cheering: "cheering" - init: "init_sim" diff --git a/src/bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/actions/play_animation.py b/src/bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/actions/play_animation.py index d2678fd71..2002e35c3 100644 --- a/src/bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/actions/play_animation.py +++ b/src/bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/actions/play_animation.py @@ -152,11 +152,6 @@ def choose_animation(self): return self.blackboard.animation_name_stand_up_back -class PlayAnimationInit(AbstractPlayAnimation): - def choose_animation(self): - return self.blackboard.animation_name_init - - class PlayAnimationStartup(AbstractPlayAnimation): def choose_animation(self): return self.blackboard.animation_name_startup diff --git a/src/bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/hcm.dsd b/src/bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/hcm.dsd index 86e1574f5..5978aaeaa 100644 --- a/src/bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/hcm.dsd +++ b/src/bitbots_motion/bitbots_hcm/bitbots_hcm/hcm_dsd/hcm.dsd @@ -6,9 +6,7 @@ -->HCM $StartHCM - START_UP --> $Simulation - YES --> @RobotStateStartup, @PlayAnimationInit, @PlayAnimationWalkReady - NO --> #INIT_PATTERN + START_UP --> #INIT_PATTERN RUNNING --> $CheckBattery LOW --> @CancelGoals, @StopWalking, @Speak + text:Battery_low_so_please_power_me_off_gracefully, @Wait + time:10 + r:false OKAY --> $CheckMotors diff --git a/src/bitbots_robot/piplus_animations/animations/misc/init.json b/src/bitbots_robot/piplus_animations/animations/misc/init.json deleted file mode 100644 index 4b86810a5..000000000 --- a/src/bitbots_robot/piplus_animations/animations/misc/init.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "default_interpolator": "CatmullRomInterpolator", - "name": "init", - "keyframes": [ - { - "duration": 2.0, - "pause": 0.0, - "goals": { - "l_shoulder_pitch_joint": 0.0, - "l_shoulder_roll_joint": 0.0, - "l_upper_arm_joint": 0.0, - "l_elbow_joint": 0.0, - "r_shoulder_pitch_joint": 0.0, - "r_shoulder_roll_joint": 0.0, - "r_upper_arm_joint": 0.0, - "r_elbow_joint": 0.0, - "l_hip_pitch_joint": 0.0, - "l_hip_roll_joint": 0.0, - "l_thigh_joint": 0.0, - "l_calf_joint": 0.0, - "l_ankle_pitch_joint": 0.0, - "l_ankle_roll_joint": 0.0, - "r_hip_pitch_joint": 0.0, - "r_hip_roll_joint": 0.0, - "r_thigh_joint": 0.0, - "r_calf_joint": 0.0, - "r_ankle_pitch_joint": 0.0, - "r_ankle_roll_joint": 0.0, - "head_yaw_joint": 0.0, - "head_pitch_joint": 0.0 - } - } - ] -} From 94408f2b4c5794ae7b36a982543a4a5facdfc9e1 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sat, 4 Jul 2026 00:56:09 +0900 Subject: [PATCH 38/68] update passiv action for multiple players (Needs to be tested!) --- .../capsules/positioning_capsule.py | 17 +++++++---------- .../capsules/team_data_capsule.py | 8 ++++---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 29833ac17..c3c2b9dc9 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -2,6 +2,7 @@ from dataclasses import dataclass from enum import StrEnum from typing import TypedDict +from scipy.optimize import linear_sum_assignment import numpy as np from bitbots_utils.utils import get_parameters_from_other_node @@ -322,7 +323,7 @@ def _match_assignment( old_poses: list[list[float] | NDArray[np.float64]], new_items: list[tuple[str, NDArray[np.float64]]], ball: NDArray[np.float64], - passiv_player: int | None, + passiv_player: list[int], angle_w: float = 0.3, ) -> list[tuple[int, NDArray[np.float64], str]]: """Assign physical robots (at `old_poses`) to the new target poses. @@ -331,25 +332,21 @@ def _match_assignment( heading difference. Returns a list of (old_idx, new_pose, new_role) where old_idx is the index into `old_poses`. `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). + `passiv_player`: list of robot indices that must never be assigned the striker role. + Pass an empty list if there are no passive players. """ - from scipy.optimize import linear_sum_assignment - old_poses = [np.asarray(p) for p in old_poses] ball = np.asarray(ball) n = len(old_poses) - # striker target -> the old robot nearest the ball s_j = next(j for j, (r, _) in enumerate(new_items) if r == Role.STRIKER) - # Kandidaten nach Distanz zum Ball sortiert candidates = sorted(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) - - # Den passiven Spieler von der Striker-Wahl ausschließen, falls vorhanden - if passiv_player is not None: - s_i = next((i for i in candidates if i != passiv_player), candidates[0]) + # Alle passiven Spieler von der Striker-Wahl ausschließen, falls vorhanden + if passiv_player: + s_i = next((i for i in candidates if i not in passiv_player), candidates[0]) else: s_i = candidates[0] - pairs = [(s_i, new_items[s_j][1], new_items[s_j][0])] rem_i = [i for i in range(n) if i != s_i] rem_j = [j for j in range(len(new_items)) if j != s_j] diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index c64eda21c..e70154494 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -189,16 +189,16 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: poses.append(data.robot_position.pose) return poses - def get_id_of_passive_player(self) -> int | None: + def get_id_of_passive_player(self) -> list[int]: """Returns the poses of all playing robots""" index_list = [] data: TeamData for data in self.team_data.values(): if self.is_valid(data) and (data.strategy.action is Strategy.ACTION_PASSIVE): - return data.robot_id + index_list.append(data.robot_id) if self.strategy.action is Strategy.ACTION_PASSIVE: - return self._blackboard.gamestate.get_own_id() - return None + index_list.append(self._blackboard.gamestate.get_own_id()) + return index_list def quaternion_to_yaw(self, q) -> float: """Extract yaw (theta) from a quaternion.""" From 85c0aaa4ae4409b444c4eb24f645e387f72542a7 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Fri, 3 Jul 2026 18:16:24 +0200 Subject: [PATCH 39/68] Remove old goto targets Signed-off-by: Florian Vahl --- .../actions/go_to_block_position.py | 191 ------------------ .../actions/go_to_corner_kick_position.py | 91 --------- .../actions/go_to_defense_position.py | 93 --------- .../actions/go_to_pass_position.py | 62 ------ 4 files changed, 437 deletions(-) delete mode 100644 src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py delete mode 100644 src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_corner_kick_position.py delete mode 100644 src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py delete mode 100644 src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py deleted file mode 100644 index 6d3d73573..000000000 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_block_position.py +++ /dev/null @@ -1,191 +0,0 @@ -import math - -import numpy as np -from bitbots_blackboard.body_blackboard import BodyBlackboard -from bitbots_utils.transforms import quat_from_yaw -from dynamic_stack_decider.abstract_action_element import AbstractActionElement -from tf2_geometry_msgs import PoseStamped - - -class GoToGoaliePosition(AbstractActionElement): - blackboard: BodyBlackboard - - def __init__(self, blackboard, dsd, parameters): - super().__init__(blackboard, dsd, parameters) - - def perform(self, reevaluate=False): - pose_msg = PoseStamped() - pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() - pose_msg.header.frame_id = self.blackboard.map_frame - - optimal_positioning = self.blackboard.positioning.get_formation_assignment() - own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] - pose = own_position["goal_pose"] - pose_msg.pose.position.x = pose[0] - pose_msg.pose.position.y = pose[1] - pose_msg.pose.orientation.w = pose[2] - - self.blackboard.pathfinding.publish(pose_msg) - - -class GoToBlockPosition(AbstractActionElement): - blackboard: BodyBlackboard - - def __init__(self, blackboard, dsd, parameters): - super().__init__(blackboard, dsd, parameters) - self.block_position_goal_offset = self.blackboard.config["block_position_goal_offset"] - self.block_radius = self.blackboard.config["block_radius_robot"] - self.left_goalpost_position = [ - -self.blackboard.world_model.field_length / 2, - self.blackboard.world_model.goal_width / 2, - ] # position of left goalpost - self.right_goalpost_position = [ - -self.blackboard.world_model.field_length / 2, - -self.blackboard.world_model.goal_width / 2, - ] # position of right goalpost - - def perform(self, reevaluate=False): - # The block position should be a position between the ball and the center of the goal - # and always in front of the goal - - # y - # ^ ______________________ - # | M | | | O - # | Y |_ -x, y | x, y _| P - # | G | | | | | P - # 0 + O | | ( ) | | G - # | A |_| | |_| O - # | L | -x,-y | x,-y | A - # | |__________|__________| L - # | - # +------------------+--------------> x - # 0 - ball_position = self.blackboard.world_model.get_ball_position_xy() - - ball_to_line_distance = ball_position[0] - self.left_goalpost_position[0] - - opening_angle = self._calc_opening_angle( - ball_to_line_distance, ball_position - ) # angle of ball to both goalposts - angle_bisector = opening_angle / 2 # of the angle between the goalpost - - goalie_pos = self._get_robot_pose(angle_bisector, ball_to_line_distance, ball_position) - - goalie_pos = self._cut_goalie_pos(goalie_pos, ball_position) - - pose_msg = PoseStamped() - pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() - pose_msg.header.frame_id = self.blackboard.map_frame - - pose_msg.pose.position.x = float(goalie_pos[0]) - pose_msg.pose.position.y = float(goalie_pos[1]) - - yaw = self._calc_turn_to_ball_angle(ball_position, goalie_pos) - pose_msg.pose.orientation = quat_from_yaw(yaw) - - self.blackboard.pathfinding.publish(pose_msg) - - def _calc_opening_angle(self, ball_to_line: float, ball_pos: tuple) -> float: - """ - Calculates the opening angle of the ball to both goalposts. - With it we can get the angle bisector, in which we place the robot. - Args: - ball_to_line: distance of the ball to our goal line - ball_pos: ball position in world koordinate system - - Returns: - float: opening angle - """ - ball_angle_left = np.arctan2( - ball_pos[1] - self.left_goalpost_position[1], ball_to_line - ) # angle of ball to left goalpost - ball_angle_right = np.arctan2( - ball_pos[1] - self.right_goalpost_position[1], ball_to_line - ) # angle of ball to right goalpost - opening_angle_ball = ball_angle_right - ball_angle_left # Subtract to get the opening angle - return opening_angle_ball - - def _get_robot_pose( - self, angle_bisector: float, ball_to_line_distance: float, ball_pos: tuple[float, float] - ) -> tuple[float, float]: - """ - Calculates the position where the robot should be to block the ball. - The position is the place where the circle of the robot blocking radius is touching both lines - from the ball to the goalposts. So the goal is completely guarded. - - Args: - angle_bisector: bisector angle of the ball with goalposts - ball_to_line_distance: distance of the ball to the goal line - ball_pos: ball position in world koordinate system - - Returns: - tuple: goalie_position - """ - left_goalpost_to_ball = math.dist(self.left_goalpost_position, ball_pos) - right_goalpost_to_ball = math.dist(self.right_goalpost_position, ball_pos) - - wanted_distance_robot_to_ball = self.block_radius / np.sin(angle_bisector) # ball obstruction distance of robot - angle_of_left_goalpost_to_ball = np.arccos(ball_to_line_distance / left_goalpost_to_ball) - angle_of_right_goalpost_to_ball = np.arccos(ball_to_line_distance / right_goalpost_to_ball) - - if ball_pos[1] > self.blackboard.world_model.goal_width / 2: - angle_to_bisector = angle_of_left_goalpost_to_ball + angle_bisector # here left goalpost angle used - goalie_x = ball_pos[0] - wanted_distance_robot_to_ball * np.cos(angle_to_bisector) - goalie_y = ball_pos[1] - wanted_distance_robot_to_ball * np.sin(angle_to_bisector) - elif ball_pos[1] < -self.blackboard.world_model.goal_width / 2: - angle_to_bisector = angle_of_right_goalpost_to_ball + angle_bisector # here right goalpost angle used - goalie_x = ball_pos[0] - wanted_distance_robot_to_ball * np.cos(angle_to_bisector) - goalie_y = ball_pos[1] + wanted_distance_robot_to_ball * np.sin(angle_to_bisector) - else: - angle_to_bisector = angle_of_left_goalpost_to_ball - angle_bisector # here right goalpost angle used - goalie_x = ball_pos[0] - wanted_distance_robot_to_ball * np.cos(angle_to_bisector) - goalie_y = ball_pos[1] + wanted_distance_robot_to_ball * np.sin(angle_to_bisector) - # calculate the angle, the robot needs to turn to look at the ball - return (goalie_x, goalie_y) - - def _cut_goalie_pos(self, goalie_pos: tuple[float, float], ball_pos: tuple[float, float]) -> tuple[float, float]: - """ - Cut the goalie position if he is behind the goal or wants to leave the designated - goal area. - - Args: - goalie_pos: a tuple which contains [goalie_y, goalie_x] position - ball_pos: a tuple which contains [ball_y, ball_x] position - - Returns: - tuple: goalie_position - """ - goalie_pos_x, goalie_pos_y = goalie_pos - # cut if goalie is behind the goal happens when the ball is too close to the corner - if goalie_pos_x < -self.blackboard.world_model.field_length / 2: - goalie_pos_x = -self.blackboard.world_model.field_length / 2 + self.block_position_goal_offset - # instead put goalie to goalpost position - if ball_pos[1] > 0: - goalie_pos_y = self.blackboard.world_model.goal_width / 2 - else: - goalie_pos_y = -self.blackboard.world_model.goal_width / 2 - # cut so goalie does not leave goalkeeper area - goalie_pos_x = np.clip( - goalie_pos_x, - -self.blackboard.world_model.field_length / 2, - -self.blackboard.world_model.field_length / 2 - + self.blackboard.world_model.penalty_area_size_x - - self.block_radius, - ) - return (goalie_pos_x, goalie_pos_y) - - def _calc_turn_to_ball_angle(self, ball_pos: tuple[float, float], goalie_pos: tuple[float, float]) -> float: - """ - Calculates the angle the robot needs to turn to look at the ball. - - Args: - ball_pos: a tuple which contains [ball_y, ball_x] position - goalie_pos: a tuple which contains [goalie_y, goalie_x] position - - Returns: - float: angle - """ - robot_to_ball_x = ball_pos[0] - goalie_pos[0] - robot_to_ball_y = ball_pos[1] - goalie_pos[1] - angle = np.arctan2(robot_to_ball_y, robot_to_ball_x) - return angle diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_corner_kick_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_corner_kick_position.py deleted file mode 100644 index 6682b9272..000000000 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_corner_kick_position.py +++ /dev/null @@ -1,91 +0,0 @@ -import math - -from bitbots_blackboard.body_blackboard import BodyBlackboard -from dynamic_stack_decider.abstract_action_element import AbstractActionElement -from geometry_msgs.msg import Quaternion -from tf2_geometry_msgs import PoseStamped -from tf_transformations import quaternion_from_euler - - -class GoToCornerKickPosition(AbstractActionElement): - blackboard: BodyBlackboard - - def __init__(self, blackboard, dsd, parameters): - super().__init__(blackboard, dsd, parameters) - - # optional parameter which goes into the block position at a certain distance to the ball - self.mode = parameters.get("mode", None) - if self.mode is None or self.mode not in ("striker", "supporter", "others"): - self.blackboard.node.get_logger().error("mode for corner kick not specified") - raise ValueError("mode for corner kick not specified") - - def perform(self, reevaluate=False): - # The defense position should be a position between the ball and the own goal. - - # y - # ^ ______________________ - # | M | | | O - # | Y |_ -x, y | x, y _| P - # | G | | | | | P - # 0 + O | | ( ) | | G - # | A |_| | |_| O - # | L | -x,-y | x,-y | A - # | |__________|__________| L - # | - # +------------------+--------------> x - # 0 - - ball_position = self.blackboard.world_model.get_ball_position_xy() - field_length = self.blackboard.world_model.field_length - field_width = self.blackboard.world_model.field_width - - pose_msg = PoseStamped() - pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() - pose_msg.header.frame_id = self.blackboard.map_frame - - # decide if the corner is on the left or right side of our goal - if ball_position[1] > 0: - # on the side of the field where y is positive - sign = 1 - else: - sign = -1 - - if self.mode == "striker": - # position relative to the corner - x_to_corner = 0.5 - y_to_corner = 0.5 - x = field_length / 2 + x_to_corner - y = sign * (field_width / 2 + y_to_corner) - yaw = sign * (5 * math.tau / 8) - elif self.mode == "supporter": - # position relative to the corner - x_to_corner = -1.5 - y_to_corner = -1.5 - x = field_length / 2 + x_to_corner - y = sign * (field_width / 2 + y_to_corner) - yaw = 0 - elif self.mode == "others": - # use fixed position rather than standing between ball and goal since there is the goal post - # x dependent on role position - if self.blackboard.team_data.role == "defense": - # close to post - x_from_goal_line = 0.5 - else: - # offense players further away based on their position number - x_from_goal_line = 1.5 + self.blackboard.misc.position_number - x = x_from_goal_line - (field_length / 2) - # 1 m away on the side line - y = sign * ((field_width / 2) - 1) - yaw = sign * (math.tau / 4) - - pose_msg.pose.position.x = x - pose_msg.pose.position.y = y - quaternion = Quaternion() - x, y, z, w = quaternion_from_euler(0, 0, yaw) - quaternion.x = x - quaternion.y = y - quaternion.z = z - quaternion.w = w - pose_msg.pose.orientation = quaternion - - self.blackboard.pathfinding.publish(pose_msg) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py deleted file mode 100644 index e5b67eafd..000000000 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_defense_position.py +++ /dev/null @@ -1,93 +0,0 @@ -import math - -import numpy as np -from bitbots_blackboard.body_blackboard import BodyBlackboard -from dynamic_stack_decider.abstract_action_element import AbstractActionElement -from geometry_msgs.msg import Quaternion -from tf2_geometry_msgs import PoseStamped -from tf_transformations import quaternion_from_euler - - -class GoToDefensePosition(AbstractActionElement): - blackboard: BodyBlackboard - - def __init__(self, blackboard, dsd, parameters): - super().__init__(blackboard, dsd, parameters) - - # Also apply offset from the ready positions to the defense positions - role_positions = self.blackboard.config["role_positions"] - try: - generalized_role_position = role_positions[self.blackboard.team_data.role]["active"][ - str(self.blackboard.misc.position_number) - ] - except KeyError as e: - raise KeyError(f"Role position for {self.blackboard.team_data.role} not specified in config") from e - - self.y_offset = generalized_role_position[1] * self.blackboard.world_model.field_width / 2 - # optional parameter which goes into the block position at a certain distance to the ball - self.mode = parameters.get("mode", None) - - def perform(self, reevaluate=False): - # The defense position should be a position between the ball and the own goal. - - # y - # ^ ______________________ - # | M | | | O - # | Y |_ -x, y | x, y _| P - # | G | | | | | P - # 0 + O | | ( ) | | G - # | A |_| | |_| O - # | L | -x,-y | x,-y | A - # | |__________|__________| L - # | - # +------------------+--------------> x - # 0 - - goal_position = (-self.blackboard.world_model.field_length / 2, 0) # position of the own goal - ball_position = self.blackboard.world_model.get_ball_position_xy() - robot_x, robot_y, _ = np.array(self.blackboard.world_model.get_current_position()) - our_pose = [robot_x, robot_y] - - pose_msg = PoseStamped() - pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() - pose_msg.header.frame_id = self.blackboard.map_frame - - if self.mode == "freekick_first": - vector_ball_to_goal = np.array(goal_position) - np.array(ball_position) - # pos between ball and goal but 1.5m away from ball - defense_pos = vector_ball_to_goal / np.linalg.norm(vector_ball_to_goal) * 1.5 + np.array(ball_position) - pose_msg.pose.position.x = defense_pos[0] - pose_msg.pose.position.y = defense_pos[1] - yaw = math.atan(-vector_ball_to_goal[1] / -vector_ball_to_goal[0]) - x, y, z, w = quaternion_from_euler(0, 0, yaw) - pose_msg.pose.orientation = Quaternion(x=x, y=y, z=z, w=w) - elif self.mode == "freekick_second": - vector_ball_to_goal = np.array(goal_position) - np.array(ball_position) - # pos between ball and goal but 1.5m away from ball and 1m to the side which is closer to us - defense_pos = vector_ball_to_goal / np.linalg.norm(vector_ball_to_goal) * 1.5 + np.array(ball_position) - yaw = math.atan(-vector_ball_to_goal[1] / -vector_ball_to_goal[0]) - - # decide on side that is closer - pos_1 = np.array([defense_pos[0] + math.sin(yaw) * 1, defense_pos[1] + math.cos(yaw) * 1]) - pos_2 = np.array([defense_pos[0] - math.sin(yaw) * 1, defense_pos[1] - math.cos(yaw) * 1]) - distance_1 = np.linalg.norm(our_pose - pos_1) - distance_2 = np.linalg.norm(our_pose - pos_2) - - if distance_1 < distance_2: - pose_msg.pose.position.x = pos_1[0] - pose_msg.pose.position.y = pos_1[1] - else: - pose_msg.pose.position.x = pos_2[0] - pose_msg.pose.position.y = pos_2[1] - x, y, z, w = quaternion_from_euler(0, 0, yaw) - pose_msg.pose.orientation = Quaternion(x=x, y=y, z=z, w=w) - else: - # center point between ball and own goal - optimal_positioning = self.blackboard.positioning.get_formation_assignment() - own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] - pose = own_position["goal_pose"] - pose_msg.pose.position.x = pose[0] - pose_msg.pose.position.y = pose[1] - pose_msg.pose.orientation.w = pose[2] - - self.blackboard.pathfinding.publish(pose_msg) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py deleted file mode 100644 index 550d7e09a..000000000 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_pass_position.py +++ /dev/null @@ -1,62 +0,0 @@ -from bitbots_blackboard.body_blackboard import BodyBlackboard -from dynamic_stack_decider.abstract_action_element import AbstractActionElement -from tf2_geometry_msgs import PoseStamped - - -class AbstractGoToPassPosition(AbstractActionElement): - blackboard: BodyBlackboard - - def __init__(self, blackboard, dsd, accept, parameters): - super().__init__(blackboard, dsd, parameters) - self.max_x = self.blackboard.config["supporter_max_x"] - self.pass_pos_x = self.blackboard.config["pass_position_x"] - self.pass_pos_y = self.blackboard.config["pass_position_y"] - self.accept = accept - self.blocking = parameters.get("blocking", True) - - def perform(self, reevaluate=False): - # get ball pos - ball_pos = self.blackboard.world_model.get_ball_position_xy() - our_pose = self.blackboard.world_model.get_current_position() - - # compute goal - goal_x = ball_pos[0] - if self.accept: - goal_x += self.pass_pos_x - - # Limit the x position, so that we are not running into the enemy goal - goal_x = min(self.max_x, goal_x) - - pose_msg = PoseStamped() - pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() - pose_msg.header.frame_id = self.blackboard.map_frame - - optimal_positioning = self.blackboard.positioning.get_formation_assignment() - own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] - pose = own_position["goal_pose"] - pose_msg.pose.position.x = pose[0] - pose_msg.pose.position.y = pose[1] - pose_msg.pose.orientation.w = pose[2] - - self.blackboard.pathfinding.publish(pose_msg) - - if not self.blocking: - self.pop() - - -class GoToPassPreparePosition(AbstractGoToPassPosition): - """ - Go to a position 1m left or right from the ball (whichever is closer) as preparation for a pass - """ - - def __init__(self, blackboard, dsd, parameters): - super().__init__(blackboard, dsd, False, parameters) - - -class GoToPassAcceptPosition(AbstractGoToPassPosition): - """ - Go to a position forward of the ball to accept a pass from another robot. - """ - - def __init__(self, blackboard, dsd, parameters): - super().__init__(blackboard, dsd, True, parameters) From 93cd9c4dccf81e2c90fb5ca894f46c4fdfad2748 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Fri, 3 Jul 2026 18:19:18 +0200 Subject: [PATCH 40/68] Remove hysteresis and add set play formation Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 59 +++++++------------ ...rmation_position.py => go_to_formation.py} | 9 ++- .../config/body_behavior.yaml | 7 --- 3 files changed, 27 insertions(+), 48 deletions(-) rename src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/{go_to_formation_position.py => go_to_formation.py} (92%) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 29833ac17..3d0dafbc3 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -81,9 +81,8 @@ class Params: # kick lane: keep teammates out of the corridor in front of the ball kick_clear: float = 0.7 # half-width of the cleared corridor kick_range: float = 3.0 # how far in front of the ball the corridor extends - # opponent free kick / goal kick / penalty: keep all robots outside this radius - opp_freekick: bool = False - opp_freekick_clearance: float = 0.8 + # opponent set play: keep all robots outside this radius + opp_set_play_clearance: float = 1.1 class PositioningCapsule(AbstractBlackboardCapsule): @@ -110,16 +109,19 @@ def __init__(self, node, blackboard): ) self._params = Params() self._inner = InnerPositioningCapsule() - self._own_locked_role: str | None = None - self._own_lock_until: float = 0.0 - self._hysteresis_min: float = self._blackboard.config["role_hysteresis"]["min"] - self._hysteresis_max: float = self._blackboard.config["role_hysteresis"]["max"] - - def set_opp_freekick_active(self, b: bool) -> None: - self._params.opp_freekick = b + # Cached capsule functions can not have parameters or side effects, + # so we have two separate functions for normal and set play formation assignment, + # that are cached separately. @cached_capsule_function def get_formation_assignment(self) -> dict[int, RobotAssignment]: + return self._get_formation_assignment(set_play=False) + + @cached_capsule_function + def get_set_play_formation_assignment(self) -> dict[int, RobotAssignment]: + return self._get_formation_assignment(set_play=True) + + def _get_formation_assignment(self, set_play=False) -> dict[int, RobotAssignment]: ball_pose = self._blackboard.world_model.get_best_ball_point_stamped() ball = np.array([ball_pose.point.x, ball_pose.point.y]) robot_poses = self._blackboard.team_data.get_robot_poses() @@ -133,27 +135,6 @@ def get_formation_assignment(self) -> dict[int, RobotAssignment]: pairs = self._inner._match_assignment(old_poses, new_items, ball, passive_robot) return {ordered_jerseys[old_idx]: {"role": role, "goal_pose": new_pose} for old_idx, new_pose, role in pairs} - @cached_capsule_function - def get_own_role(self) -> str: - """Return our assigned role, locking it in for a random duration on each change. - - Each robot runs this independently with slightly different world state, so - hysteresis is local: once we switch to a new role we commit to it for - Uniform(hysteresis_min, hysteresis_max) seconds before accepting another change. - """ - own_jersey = self._blackboard.gamestate.get_own_id() - assigned_role = self.get_formation_assignment()[own_jersey]["role"] - now = self._node.get_clock().now().nanoseconds / 1e9 - - if now < self._own_lock_until: - return self._own_locked_role # type: ignore[return-value] - - if assigned_role != self._own_locked_role: - self._own_locked_role = assigned_role - self._own_lock_until = now + random.uniform(self._hysteresis_min, self._hysteresis_max) - - return assigned_role - class InnerPositioningCapsule: """Pure & deterministic formation computation, independent of ROS and the rest of the system.""" @@ -370,7 +351,7 @@ def _match_assignment( # --------------------------------------------------------------------------- # def _compute_formation( - self, ball: NDArray[np.float64], field: Field, n_players: int, params: Params + self, ball: NDArray[np.float64], field: Field, n_players: int, params: Params, opp_set_play: bool = False ) -> dict[str, NDArray[np.float64]]: """Map a ball position -> {role: np.array([x, y, yaw])}. Pure & deterministic. @@ -389,7 +370,7 @@ def _compute_formation( perp = np.array([-to_ball[1], to_ball[0]]) roles = self._allocate_roles(n_players, b, field) - if params.opp_freekick and Role.SUPPORTER in roles: + if opp_set_play and Role.SUPPORTER in roles: n_def = sum(1 for r in roles if r.startswith(Role.DEFENDER + "_")) roles[roles.index(Role.SUPPORTER)] = f"{Role.DEFENDER}_{n_def}" out = {} @@ -398,10 +379,10 @@ def _compute_formation( # --- striker: stands behind the ball opposite the smoothly-chosen kick aim --- # if Role.STRIKER in roles: - if params.opp_freekick: + if opp_set_play: # park at the clearance boundary on the goal side, facing the ball dir_to_goal = self._normalize(goal - b, fallback=np.array([-1.0, 0.0])) - out[Role.STRIKER] = self._clamp_field(b + params.opp_freekick_clearance * dir_to_goal, field) + out[Role.STRIKER] = self._clamp_field(b + params.opp_set_play_clearance * dir_to_goal, field) # heading will be computed in the orientation pass (face ball) else: h = max(field.goal_width / 2 - params.post_margin, 0.0) # safe half-mouth @@ -437,7 +418,7 @@ def _compute_formation( ) out[Role.GOALIE] = g - + # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # defender_roles = [r for r in roles if r.startswith(Role.DEFENDER + "_")] m = len(defender_roles) @@ -472,9 +453,9 @@ def _compute_formation( # --- min-separation repulsion + kick-lane clearance ----------------------- # self._separate(out, field, params, b, kick_aim) - # --- freekick: push every robot outside the mandatory clearance radius ---- # - if params.opp_freekick: - self._clear_ball(out, b, params.opp_freekick_clearance, field) + # --- set play: push every robot outside the mandatory clearance radius ---- # + if opp_set_play: + self._clear_ball(out, b, params.opp_set_play_clearance, field) # --- orientations (computed from the final positions) --------------------- # for role, p in out.items(): diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation.py similarity index 92% rename from src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py rename to src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation.py index 3b7588547..c73a1e25f 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation.py @@ -14,6 +14,8 @@ class GoToFormationPosition(AbstractActionElement): def __init__(self, blackboard, dsd, parameters): super().__init__(blackboard, dsd, parameters) + self.set_play = parameters.get("set_play", False) + self.stand = parameters.get("stand", False) if self.stand: self.on_position_threshold = parameters["enter_position"] @@ -28,8 +30,11 @@ def __init__(self, blackboard, dsd, parameters): self.standing_on_target = False def perform(self, reevaluate=False): + if self.set_play: + optimal_positioning = self.blackboard.positioning.get_set_play_formation_assignment() + else: + optimal_positioning = self.blackboard.positioning.get_formation_assignment() - optimal_positioning = self.blackboard.positioning.get_formation_assignment() own_target = optimal_positioning[self.blackboard.gamestate.get_own_id()] goal_pose = own_target["goal_pose"] # [x, y, orientation] @@ -62,7 +67,7 @@ def perform(self, reevaluate=False): pose_msg = PoseStamped() pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() pose_msg.header.frame_id = self.blackboard.map_frame - + goal_pose = own_target["goal_pose"] pose_msg.pose.position.x = goal_pose[0] pose_msg.pose.position.y = goal_pose[1] diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index d3bab7e87..4c80ef85c 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -3,13 +3,6 @@ body_behavior: # Data older than this is seen as non existent team_data_timeout: 2 - # Role hysteresis: when our assigned role changes, lock the new role for a - # random duration in [role_hysteresis_min, role_hysteresis_max] seconds to - # prevent rapid flickering between roles across distributed robot states. - role_hysteresis: - min: 0.0 - max: 2.0 - # The roles that are used in the initial role configuration. roles: - "goalie" From 7c664c7266af10fbb94d8e70991005f32c1c1d4e Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Fri, 3 Jul 2026 18:19:56 +0200 Subject: [PATCH 41/68] Adapt and fix the behavior Signed-off-by: Florian Vahl --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 93a3f892f..be7e729d5 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -72,9 +72,7 @@ $SecondaryStateTeamDecider NO --> @LookAtFieldFeatures, @Stand #Placing -$DoOnce - NOT_DONE --> @ForgetBall, @LookAtFieldFeatures - DONE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToFormationPosition + stand:true + enter_position:%placing_enter_position + leave_position:%placing_leave_position + enter_orientation:%placing_enter_orientation + leave_orientation:%placing_leave_orientation +@ChangeAction + action:positioning, @ForgetBall, @LookAtFieldFeatures, @GoToFormationPosition + set_play:true + stand:true + enter_position:%placing_enter_position + leave_position:%placing_leave_position + enter_orientation:%placing_enter_orientation + leave_orientation:%placing_leave_orientation #Init @@ -87,9 +85,9 @@ $SecondBallTouchAllowed NO --> $ConfigRole STRIKER --> #SearchBall ELSE --> #RolePositionWithPause - YES --> $KickOffTimeUp + YES --> $KickOffTimeUp // TODO ASK Clemens regarding rules NO_NORMAL --> #StandAndLook - NO_FREEKICK --> #Placing + NO_FREEKICK --> #Placing // I think this is unreachable YES --> $AssignedRole STRIKER --> #KickWithAvoidance SUPPORTER --> #SupporterRole @@ -105,7 +103,7 @@ $DoOnce ELSE --> #Placing #PlayingBehavior -$SecondaryStateDecider +$SecondaryStateDecider PENALTYSHOOT --> #PenaltyShootoutBehavior TIMEOUT --> #StandAndLook THROW_IN --> #ThrowinGoalKickCornerkickBehavior @@ -140,7 +138,7 @@ $IsPenalized ELSE --> #PlayingBehavior NOT_DETECTED --> $SecondaryStateDecider PENALTYSHOOT --> $SecondaryStateTeamDecider - OUR --> @Stand + duration:0.1 + r:false, @DeactivateHCM + r:false, @LookForward + r:false, @Stand // we need to also see the goalie + OUR --> @Stand + duration:0.1 + r:false, @LookForward + r:false, @Stand // we need to also see the goalie OTHER --> $BallSeen YES --> @Stand + duration:0.1 + r:false, @DeactivateHCM + r:false, @LookForward + r:false, @TrackBall + r:false, @PlayAnimationGoalieArms + r:false, @Stand // goalie only needs to care about the ball NO --> @Stand + duration:0.1 + r:false, @DeactivateHCM + r:false, @LookForward + r:false, @LookAtFieldFeatures + r:false, @PlayAnimationGoalieArms + r:false, @Stand From 5cf3baba062c143f26480edb3b3f064288a7143c Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Fri, 3 Jul 2026 18:50:18 +0200 Subject: [PATCH 42/68] Fix set play in gui Signed-off-by: Florian Vahl --- .../scripts/debug_positioning.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index b6128f52f..6bae6a5b6 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -41,8 +41,8 @@ def _ax(b): s_back = Slider(_ax(0.170), "back dist", 0.0, 3.0, valinit=params.back_dist) s_kclr = Slider(_ax(0.140), "kick clear", 0.0, 1.5, valinit=params.kick_clear) s_gout = Slider(_ax(0.110), "goalie out", 0.2, 2.0, valinit=params.d_g) - check_fk = CheckButtons(plt.axes([0.18, 0.073, 0.20, 0.022]), ["freekick"], [False]) - s_fkcl = Slider(_ax(0.050), "fk clearance", 0.1, 2.0, valinit=params.opp_freekick_clearance) + check_sp = CheckButtons(plt.axes([0.18, 0.073, 0.20, 0.022]), ["set play"], [False]) + s_spcl = Slider(_ax(0.050), "set play clearance", 0.1, 2.0, valinit=params.opp_set_play_clearance) def draw(): ax.clear() @@ -65,15 +65,15 @@ def draw(): params.supp_max_x, params.def_side = s_smax.val, s_dside.val params.post_margin, params.back_dist = s_pmarg.val, s_back.val params.kick_clear = s_kclr.val - params.freekick = check_fk.get_status()[0] - params.opp_freekick_clearance = s_fkcl.val + opp_set_play = check_sp.get_status()[0] + params.opp_set_play_clearance = s_spcl.val n = int(s_n.val) - if params.freekick: + if opp_set_play: ax.add_patch( Circle( state["ball"], - params.freekick_clearance, + params.opp_set_play_clearance, fill=False, color="yellow", lw=1.5, @@ -83,7 +83,7 @@ def draw(): ) ) - form = _inner._compute_formation(state["ball"], fld, n, params) + form = _inner._compute_formation(state["ball"], fld, n, params, opp_set_play=opp_set_play) new_items = list(form.items()) prev = state["prev"] @@ -164,10 +164,10 @@ def on_click(event): s_back, s_kclr, s_gout, - s_fkcl, + s_spcl, ): s.on_changed(lambda _v: draw()) - check_fk.on_clicked(lambda _label: draw()) + check_sp.on_clicked(lambda _label: draw()) fig.canvas.mpl_connect("button_press_event", on_click) draw() plt.show() From eeed157c0dc2c85eb325a394d5253c3b048b8f98 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Fri, 3 Jul 2026 18:51:12 +0200 Subject: [PATCH 43/68] Fix seperation during complex / crowded set play situations Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 3d0dafbc3..bfc735861 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -229,6 +229,7 @@ def _separate( params: Params, ball: NDArray[np.float64] | None = None, aim: NDArray[np.float64] | None = None, + clear_radius: float | None = None, ) -> None: """In-place relaxation: pairwise min-sep + clearing the striker's kick lane. @@ -236,7 +237,13 @@ def _separate( goalie included, gives way around it. In normal play the goalie is far from all teammates so it never moves; it only shifts off its line in the degenerate case where the ball sits right in the goal mouth. Continuous in the inputs, - so small ball moves -> small position moves.""" + so small ball moves -> small position moves. + + `clear_radius` (opponent set play) is re-enforced at the *start* of every + iteration, so the pairwise pass that follows always gets the last word and + can re-separate robots that the clearance push just bunched together. A + final clearance pass after the loop is the hard guarantee (it's a + referee-enforced rule), even though separation wins within the loop.""" fixed = {Role.STRIKER} names = list(positions.keys()) sep = params.min_sep @@ -248,6 +255,11 @@ def _separate( step = max(params.kick_clear * 0.7, 0.3) lane_pts = [np.asarray(ball) + s * aim for s in np.arange(step, params.kick_range + 1e-9, step)] for _ in range(params.sep_iters): + # enforce set-play clearance first so this iteration's pairwise pass gets the + # last word - otherwise robots bunched by the clearance push in the final + # iteration would have no chance to be re-separated + if clear_radius is not None and ball is not None: + self._clear_ball(positions, ball, clear_radius, field) disp = {n: np.zeros(2) for n in names} for i in range(len(names)): for j in range(i + 1, len(names)): @@ -281,6 +293,10 @@ def _separate( if n in fixed: continue positions[n] = self._clamp_field(positions[n] + disp[n], field) + # hard guarantee: the set-play clearance is a referee-enforced rule, so it always + # wins in the end, even though separation gets the last word during the loop above + if clear_radius is not None and ball is not None: + self._clear_ball(positions, ball, clear_radius, field) def _clear_ball( self, positions: dict[str, NDArray[np.float64]], ball: NDArray[np.float64], radius: float, field: Field @@ -450,12 +466,10 @@ def _compute_formation( sup[0] = min(sup[0], params.supp_max_x) # don't drift into the opponent corner out[Role.SUPPORTER] = self._clamp_field(sup, field) - # --- min-separation repulsion + kick-lane clearance ----------------------- # - self._separate(out, field, params, b, kick_aim) - - # --- set play: push every robot outside the mandatory clearance radius ---- # - if opp_set_play: - self._clear_ball(out, b, params.opp_set_play_clearance, field) + # --- min-separation repulsion + kick-lane clearance + set-play clearance -- # + self._separate( + out, field, params, b, kick_aim, clear_radius=params.opp_set_play_clearance if opp_set_play else None + ) # --- orientations (computed from the final positions) --------------------- # for role, p in out.items(): From 8b636462c05734c00f2202dcdb9e5ffb46989ecf Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Fri, 3 Jul 2026 18:54:35 +0200 Subject: [PATCH 44/68] Apply format Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 4 +- .../capsules/team_data_capsule.py | 4 +- .../behavior_dsd/actions/go_to_ball.py | 2 +- .../behavior_dsd/actions/go_to_formation.py | 27 +++++++---- .../behavior_dsd/actions/play_animation.py | 2 +- .../bitbots_team_data_sim_rqt/team_data_ui.py | 47 ++++++++++++++++--- 6 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index da5f4d0d3..746d98d64 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -1,12 +1,11 @@ -import random from dataclasses import dataclass from enum import StrEnum from typing import TypedDict -from scipy.optimize import linear_sum_assignment import numpy as np from bitbots_utils.utils import get_parameters_from_other_node from numpy.typing import NDArray +from scipy.optimize import linear_sum_assignment from bitbots_blackboard.capsules import AbstractBlackboardCapsule, cached_capsule_function @@ -431,7 +430,6 @@ def _compute_formation( ) out[Role.GOALIE] = g - # --- defenders: anchor on axis at push-up depth, spread along perp ---------- # defender_roles = [r for r in roles if r.startswith(Role.DEFENDER + "_")] m = len(defender_roles) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index e70154494..a51395c28 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -188,14 +188,14 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: if self.is_valid(data) and (data.strategy.role != Strategy.ROLE_GOALIE or count_goalies): poses.append(data.robot_position.pose) return poses - + def get_id_of_passive_player(self) -> list[int]: """Returns the poses of all playing robots""" index_list = [] data: TeamData for data in self.team_data.values(): if self.is_valid(data) and (data.strategy.action is Strategy.ACTION_PASSIVE): - index_list.append(data.robot_id) + index_list.append(data.robot_id) if self.strategy.action is Strategy.ACTION_PASSIVE: index_list.append(self._blackboard.gamestate.get_own_id()) return index_list diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py index e84516b69..00ce5e95a 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py @@ -2,8 +2,8 @@ from bitbots_blackboard.capsules.pathfinding_capsule import BallGoalType from dynamic_stack_decider.abstract_action_element import AbstractActionElement from geometry_msgs.msg import Vector3 -from tf2_geometry_msgs import PoseStamped from std_msgs.msg import ColorRGBA +from tf2_geometry_msgs import PoseStamped from visualization_msgs.msg import Marker diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation.py index c73a1e25f..6c24879ae 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_formation.py @@ -3,8 +3,8 @@ import numpy as np from bitbots_blackboard.body_blackboard import BodyBlackboard from dynamic_stack_decider.abstract_action_element import AbstractActionElement -from tf2_geometry_msgs import PoseStamped from ros2_numpy import numpify +from tf2_geometry_msgs import PoseStamped from tf_transformations import euler_from_quaternion, quaternion_from_euler @@ -36,27 +36,36 @@ def perform(self, reevaluate=False): optimal_positioning = self.blackboard.positioning.get_formation_assignment() own_target = optimal_positioning[self.blackboard.gamestate.get_own_id()] - goal_pose = own_target["goal_pose"] # [x, y, orientation] + goal_pose = own_target["goal_pose"] # [x, y, orientation] current_pose = self.blackboard.world_model.get_current_position_pose_stamped() current_orientation = euler_from_quaternion(numpify(current_pose.pose.orientation)) angle_to_goal_orientation = abs(math.remainder(current_orientation[2] - goal_pose[2], math.tau)) - distance = np.linalg.norm(goal_pose[:2] - numpify(current_pose.pose.position)[:2]) self.publish_debug_data("current_orientation", current_orientation[2]) self.publish_debug_data("goal_orientation", goal_pose[2]) self.publish_debug_data("angle_to_goal_orientation", angle_to_goal_orientation) self.publish_debug_data("distance", distance) - assert not self.stand or self.on_position_threshold < self.off_position_threshold, "on_position_threshold must be smaller than off_position_threshold" - assert not self.stand or self.on_orientation_threshold < self.off_orientation_threshold, "on_orientation_threshold must be smaller than off_orientation_threshold" - - if self.stand and distance < self.on_position_threshold and angle_to_goal_orientation < self.on_orientation_threshold: + assert not self.stand or self.on_position_threshold < self.off_position_threshold, ( + "on_position_threshold must be smaller than off_position_threshold" + ) + assert not self.stand or self.on_orientation_threshold < self.off_orientation_threshold, ( + "on_orientation_threshold must be smaller than off_orientation_threshold" + ) + + if ( + self.stand + and distance < self.on_position_threshold + and angle_to_goal_orientation < self.on_orientation_threshold + ): self.standing_on_target = True - if self.standing_on_target and (distance < self.off_position_threshold and angle_to_goal_orientation < self.off_orientation_threshold): + if self.standing_on_target and ( + distance < self.off_position_threshold and angle_to_goal_orientation < self.off_orientation_threshold + ): # Cancel the path planning if it is running self.blackboard.pathfinding.cancel_goal() # need to keep publishing this since path planning publishes a few more messages @@ -78,5 +87,3 @@ def perform(self, reevaluate=False): pose_msg.pose.orientation.w = quat[3] self.blackboard.pathfinding.publish(pose_msg) - - diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/play_animation.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/play_animation.py index 04ac170f8..b2fb4e6c8 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/play_animation.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/play_animation.py @@ -84,4 +84,4 @@ def get_animation_name(self): class PlayAnimationThrow(AbstractPlayAnimation): def get_animation_name(self): self.blackboard.node.get_logger().info("PLAYING THROW-IN ANIMATION") - return self.blackboard.animation.throw_animation \ No newline at end of file + return self.blackboard.animation.throw_animation diff --git a/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py b/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py index d7ac4d7cb..d055c2c68 100755 --- a/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py +++ b/src/bitbots_team_communication/bitbots_team_data_sim_rqt/bitbots_team_data_sim_rqt/team_data_ui.py @@ -186,6 +186,7 @@ def __init__(self, parent=None): def get_y_position(self) -> float: return float(self.y_pos_spin_box.value() / 100) + class BallPositionCoordsX(QGroupBox): def __init__(self, parent=None): super().__init__(parent) @@ -211,7 +212,7 @@ def get_x_ball_position(self) -> float: return float(self.x_ball_pos_spin_box.value() / 100) -class PositionCoordsY(QGroupBox): +class BallPositionCoordsY(QGroupBox): def __init__(self, parent=None): super().__init__(parent) # y position @@ -235,6 +236,7 @@ def __init__(self, parent=None): def get_y_ball_position(self) -> float: return float(self.y_ball_pos_spin_box.value() / 100) + class BallCovariance(QGroupBox): def __init__(self, parent=None): super().__init__(parent) @@ -259,6 +261,7 @@ def __init__(self, parent=None): def get_ball_covariance(self) -> float: return float(self.ball_covariance_box.value() / 10) + class StrategyBox(QGroupBox): _roles: dict[str, int] = { "Undefined": Strategy.ROLE_UNDEFINED, @@ -393,12 +396,42 @@ def timer_callback(self): pose_with_cov.pose.position.x = robot_widget.position_sliders_x.get_x_position() pose_with_cov.pose.position.y = robot_widget.position_sliders_y.get_y_position() pose_with_cov.covariance = [ - robot_widget.ball_covariance.get_ball_covariance() / 2, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, robot_widget.ball_covariance.get_ball_covariance() / 2, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.05 + robot_widget.ball_covariance.get_ball_covariance() / 2, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + robot_widget.ball_covariance.get_ball_covariance() / 2, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.01, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.01, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.01, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.05, ] team_data.robot_position = pose_with_cov team_data.state = robot_widget.state_box.get_state() From 9a3099b95bc3f4cbae30cddf2b8c3ebbe6326b15 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Fri, 3 Jul 2026 19:13:19 +0200 Subject: [PATCH 45/68] Fix passive robots Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 30 ++++++++++++------- .../capsules/team_data_capsule.py | 10 +++---- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 746d98d64..915a6ec3e 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -125,14 +125,19 @@ def _get_formation_assignment(self, set_play=False) -> dict[int, RobotAssignment ball_pose = self._blackboard.world_model.get_best_ball_point_stamped() ball = np.array([ball_pose.point.x, ball_pose.point.y]) robot_poses = self._blackboard.team_data.get_robot_poses() - passive_robot = self._blackboard.team_data.get_id_of_passive_player() + passive_robot_ids = self._blackboard.team_data.get_id_of_passive_player() self._node.get_logger().info(f"Length of robot_poses: {len(robot_poses)}") - formation = self._inner._compute_formation(ball, self._field, len(robot_poses), self._params) + formation = self._inner._compute_formation( + ball, self._field, len(robot_poses), self._params, opp_set_play=set_play + ) new_items = list(formation.items()) ordered_jerseys = sorted(robot_poses.keys()) old_poses = [robot_poses[j] for j in ordered_jerseys] - pairs = self._inner._match_assignment(old_poses, new_items, ball, passive_robot) + # `_match_assignment` identifies robots by their index into `old_poses`, not by + # jersey/robot id, so translate every passive robot id we know about into its index + passive_indices = [ordered_jerseys.index(rid) for rid in passive_robot_ids if rid in ordered_jerseys] + pairs = self._inner._match_assignment(old_poses, new_items, ball, passive_indices) return {ordered_jerseys[old_idx]: {"role": role, "goal_pose": new_pose} for old_idx, new_pose, role in pairs} @@ -319,28 +324,31 @@ def _match_assignment( old_poses: list[list[float] | NDArray[np.float64]], new_items: list[tuple[str, NDArray[np.float64]]], ball: NDArray[np.float64], - passiv_player: list[int], + passive_indices: list[int], angle_w: float = 0.3, ) -> list[tuple[int, NDArray[np.float64], str]]: """Assign physical robots (at `old_poses`) to the new target poses. The robot closest to the ball always takes the striker target; the rest are - matched optimally (Hungarian) to minimise total cost = distance + angle_w * + matched optimally (Hungarian) to minimize total cost = distance + angle_w * heading difference. Returns a list of (old_idx, new_pose, new_role) where old_idx is the index into `old_poses`. `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). - `passiv_player`: list of robot indices that must never be assigned the striker role. - Pass an empty list if there are no passive players. + `passive_indices`: indices into `old_poses` of robots that should not be assigned + the striker role. Pass an empty list if there are no passive robots. If every + robot is passive, the striker slot must still be filled, so the closest passive + robot is assigned it anyway. """ + assert len(passive_indices) <= len(new_items), "more passive robots reported than robots to assign" old_poses = [np.asarray(p) for p in old_poses] ball = np.asarray(ball) n = len(old_poses) # striker target -> the old robot nearest the ball s_j = next(j for j, (r, _) in enumerate(new_items) if r == Role.STRIKER) - # Kandidaten nach Distanz zum Ball sortiert + # candidates sorted by distance to the ball candidates = sorted(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) - # Alle passiven Spieler von der Striker-Wahl ausschließen, falls vorhanden - if passiv_player: - s_i = next((i for i in candidates if i not in passiv_player), candidates[0]) + # exclude passive robots from the striker choice, unless that would leave no candidate + if passive_indices: + s_i = next((i for i in candidates if i not in passive_indices), candidates[0]) else: s_i = candidates[0] pairs = [(s_i, new_items[s_j][1], new_items[s_j][0])] diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py index a51395c28..b9886333f 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/team_data_capsule.py @@ -190,15 +190,15 @@ def get_active_teammate_poses(self, count_goalies: bool = False) -> list[Pose]: return poses def get_id_of_passive_player(self) -> list[int]: - """Returns the poses of all playing robots""" - index_list = [] + """Returns the robot ids of all robots (including this one) that are currently marked passive.""" + passive_robot_ids = [] data: TeamData for data in self.team_data.values(): if self.is_valid(data) and (data.strategy.action is Strategy.ACTION_PASSIVE): - index_list.append(data.robot_id) + passive_robot_ids.append(data.robot_id) if self.strategy.action is Strategy.ACTION_PASSIVE: - index_list.append(self._blackboard.gamestate.get_own_id()) - return index_list + passive_robot_ids.append(self._blackboard.gamestate.get_own_id()) + return passive_robot_ids def quaternion_to_yaw(self, q) -> float: """Extract yaw (theta) from a quaternion.""" From bcfdbb2cd6c2c38b99e3c83c55eb0e6cd419c7b9 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Fri, 3 Jul 2026 19:53:36 +0200 Subject: [PATCH 46/68] Adapt gui to model passive robots during assignment Signed-off-by: Florian Vahl --- .../scripts/debug_positioning.py | 77 +++++++++++++------ 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index 6bae6a5b6..afd6f3c4c 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -18,7 +18,11 @@ def run_gui(): fld = Field() params = Params() - state = {"ball": np.array([1.0, 0.5]), "n": 5, "prev": None} + # `robots` holds the *persistent* physical robot positions (index = robot identity), + # updated in place every frame via `_match_assignment` - unlike the formation targets + # (which are recomputed from scratch each frame), this gives "robot i" a stable + # identity across ball moves, so marking one passive keeps referring to the same robot. + state = {"ball": np.array([1.0, 0.5]), "n": 5, "robots": None} colors = {"goalie": "#e6b800", "striker": "#d62728", "supporter": "#2ca02c"} @@ -43,6 +47,17 @@ def _ax(b): s_gout = Slider(_ax(0.110), "goalie out", 0.2, 2.0, valinit=params.d_g) check_sp = CheckButtons(plt.axes([0.18, 0.073, 0.20, 0.022]), ["set play"], [False]) s_spcl = Slider(_ax(0.050), "set play clearance", 0.1, 2.0, valinit=params.opp_set_play_clearance) + # one checkbox per possible robot identity (0..max players - 1); checkboxes beyond the + # current player count are simply ignored. CheckButtons (unlike TextBox) doesn't hook + # resize_event, so it doesn't hit the matplotlib bug where TextBox crashes on any + # window resize (ResizeEvent has no .inaxes, but TextBox._resize assumes it does). + max_players = 8 + ax_passive = plt.axes([0.915, 0.05, 0.07, 0.40]) # right of the sliders, below the plot + ax_passive.set_title("passive\nrobot", fontsize=9) + check_passive = CheckButtons(ax_passive, [str(i) for i in range(max_players)], [False] * max_players) + + def get_passive_indices(n_robots): + return [i for i, checked in enumerate(check_passive.get_status()) if checked and i < n_robots] def draw(): ax.clear() @@ -86,16 +101,20 @@ def draw(): form = _inner._compute_formation(state["ball"], fld, n, params, opp_set_play=opp_set_play) new_items = list(form.items()) - prev = state["prev"] - if prev is not None and len(prev) == len(new_items): - for old_idx, new_pose, role in _inner._match_assignment(prev, new_items, state["ball"], None): - old_pose = prev[old_idx] - c = colors.get(role.split("_")[0], "#1f77b4") - ax.plot([old_pose[0], new_pose[0]], [old_pose[1], new_pose[1]], ls=":", color=c, lw=1.5, zorder=3) - ax.add_patch(Circle(old_pose[:2], 0.10, color=c, alpha=0.55, zorder=4)) - state["prev"] = [pose for _role, pose in new_items] + # (re)seed robot identities from scratch whenever the player count changes, since + # there's no sensible way to carry old identities over a different-sized roster + if state["robots"] is None or len(state["robots"]) != len(new_items): + state["robots"] = [pose for _role, pose in new_items] + passive_idxs = get_passive_indices(len(state["robots"])) + robots = state["robots"] + # assign each persistent robot (by index) to a role target for this frame + assignments = _inner._match_assignment(robots, new_items, state["ball"], passive_idxs) + + # ball ax.add_patch(Circle(state["ball"], 0.12, color="white", ec="black", zorder=5)) + + # striker kick lane + aim arrow if "striker" in form: th = form["striker"][2] aim = np.array([np.cos(th), np.sin(th)]) @@ -115,10 +134,20 @@ def draw(): zorder=8, alpha=0.9, ) - for role, pose in form.items(): - p, th = pose[:2], pose[2] - base = role.split("_")[0] - c = colors.get(base, "#1f77b4") + + # draw each robot at its assigned position, colored by its current role. The robot's + # identity (its index) and its passive 'x' stay glued to the same marker even when + # its role - and therefore its color - changes from frame to frame. + new_robots = list(robots) + for old_idx, new_pose, role in assignments: + old_pose = robots[old_idx] + p, th = new_pose[:2], new_pose[2] + c = colors.get(role.split("_")[0], "#1f77b4") + # dashed trail from where this robot was last frame; fixed high-contrast white + # (role colors like the green defender/supporter vanish against the pitch), with + # a hollow ring marking the start so the direction of travel is clear + ax.plot([old_pose[0], p[0]], [old_pose[1], p[1]], ls=(0, (4, 2)), color="white", lw=1.7, alpha=0.95, zorder=3) + ax.add_patch(Circle(old_pose[:2], 0.07, fill=False, ec="white", lw=1.2, alpha=0.8, zorder=3)) ax.add_patch(Circle(p, params.min_sep / 2, color=c, alpha=0.18, zorder=2)) ax.add_patch(Circle(p, 0.16, color=c, ec="black", zorder=6)) ax.plot( @@ -129,20 +158,21 @@ def draw(): zorder=7, solid_capstyle="round", ) - ax.annotate( - role.replace("defender_", "D").replace("supporter", "supp"), - p, - color="white", - fontsize=8, - ha="center", - va="center", - zorder=8, - ) + short = role.replace("defender_", "D").replace("supporter", "supp") + ax.annotate(f"{old_idx}:{short}", (p[0], p[1] - 0.30), color="white", fontsize=8, ha="center", zorder=8) + if old_idx in passive_idxs: + ax.plot(p[0], p[1], marker="x", color="black", markersize=13, mew=2.5, zorder=9) + new_robots[old_idx] = new_pose + state["robots"] = new_robots ax.set_xlim(-fld.length / 2 - 0.5, fld.length / 2 + 0.5) ax.set_ylim(-fld.width / 2 - 0.5, fld.width / 2 + 0.5) ax.set_aspect("equal") - ax.set_title("click to move the ball · dots = previous assignment (dotted = who moves where)", color="black") + ax.set_title( + "click to move the ball · label = robot#:role · dotted trail = movement since last frame · " + "'x' = passive (never assigned striker)", + color="black", + ) fig.canvas.draw_idle() def on_click(event): @@ -168,6 +198,7 @@ def on_click(event): ): s.on_changed(lambda _v: draw()) check_sp.on_clicked(lambda _label: draw()) + check_passive.on_clicked(lambda _label: draw()) fig.canvas.mpl_connect("button_press_event", on_click) draw() plt.show() From 426c857ade9fda1beeb8bf23a613f017d9d9e904 Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Sat, 4 Jul 2026 08:30:21 +0900 Subject: [PATCH 47/68] Fix typing for positoning capsule --- .../capsules/positioning_capsule.py | 30 ++++++++++++------- .../scripts/debug_positioning.py | 23 +++++++++----- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 915a6ec3e..b7406ad57 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -1,6 +1,6 @@ from dataclasses import dataclass from enum import StrEnum -from typing import TypedDict +from typing import Sequence, TypedDict import numpy as np from bitbots_utils.utils import get_parameters_from_other_node @@ -21,6 +21,14 @@ class Role(StrEnum): DEFENDER = "defender" SUPPORTER = "supporter" + DEFENDER_0 = "defender_0" + DEFENDER_1 = "defender_1" + DEFENDER_2 = "defender_2" + DEFENDER_3 = "defender_3" + DEFENDER_4 = "defender_4" + DEFENDER_5 = "defender_5" + DEFENDER_6 = "defender_6" + @dataclass class Field: @@ -190,7 +198,7 @@ def _clamp_field(p: NDArray[np.float64], fld: Field, margin: float | None = None # --------------------------------------------------------------------------- # @staticmethod - def _allocate_roles(n: int, ball: NDArray[np.float64] | None = None, field: Field | None = None) -> list[str]: + def _allocate_roles(n: int, ball: NDArray[np.float64] | None = None, field: Field | None = None) -> list[Role]: """Keep-priority as the count drops: striker > goalie > 1st defender > supporter > 2nd defender (and any further players are extra defenders). @@ -218,7 +226,7 @@ def _allocate_roles(n: int, ball: NDArray[np.float64] | None = None, field: Fiel roles.append(Role.STRIKER) if n >= 2: roles.append(Role.GOALIE) - roles += [f"{Role.DEFENDER}_{i}" for i in range(n_def)] + roles += [Role(f"{Role.DEFENDER}_{i}") for i in range(n_def)] if has_support: roles.append(Role.SUPPORTER) return roles @@ -229,7 +237,7 @@ def _allocate_roles(n: int, ball: NDArray[np.float64] | None = None, field: Fiel def _separate( self, - positions: dict[str, NDArray[np.float64]], + positions: dict[Role, NDArray[np.float64]], field: Field, params: Params, ball: NDArray[np.float64] | None = None, @@ -304,7 +312,7 @@ def _separate( self._clear_ball(positions, ball, clear_radius, field) def _clear_ball( - self, positions: dict[str, NDArray[np.float64]], ball: NDArray[np.float64], radius: float, field: Field + self, positions: dict[Role, NDArray[np.float64]], ball: NDArray[np.float64], radius: float, field: Field ) -> None: """Push all robots to at least `radius` distance from `ball` (in-place).""" ball = np.asarray(ball) @@ -321,9 +329,9 @@ def _clear_ball( def _match_assignment( self, - old_poses: list[list[float] | NDArray[np.float64]], + old_poses: Sequence[list[float] | NDArray[np.float64]], new_items: list[tuple[str, NDArray[np.float64]]], - ball: NDArray[np.float64], + ball: NDArray[np.float64] | tuple[float, float], passive_indices: list[int], angle_w: float = 0.3, ) -> list[tuple[int, NDArray[np.float64], str]]: @@ -371,7 +379,7 @@ def _match_assignment( # --------------------------------------------------------------------------- # def _compute_formation( - self, ball: NDArray[np.float64], field: Field, n_players: int, params: Params, opp_set_play: bool = False + self, ball: NDArray[np.float64] | tuple[float, float], field: Field, n_players: int, params: Params, opp_set_play: bool = False ) -> dict[str, NDArray[np.float64]]: """Map a ball position -> {role: np.array([x, y, yaw])}. Pure & deterministic. @@ -381,7 +389,7 @@ def _compute_formation( xyzw order (ROS/tf convention). Internally, transforms3d uses wxyz order; `bitbots_utils.transforms` handles the conversion. """ - b = ball + b = np.asarray(ball) goal = np.array([-field.length / 2.0, 0.0]) opp = np.array([+field.length / 2.0, 0.0]) @@ -392,7 +400,7 @@ def _compute_formation( roles = self._allocate_roles(n_players, b, field) if opp_set_play and Role.SUPPORTER in roles: n_def = sum(1 for r in roles if r.startswith(Role.DEFENDER + "_")) - roles[roles.index(Role.SUPPORTER)] = f"{Role.DEFENDER}_{n_def}" + roles[roles.index(Role.SUPPORTER)] = Role(f"{Role.DEFENDER}_{n_def}") out = {} head = {} # role -> heading (rad); filled lazily, completed after separation kick_aim = None # striker's kick direction; used to clear the kick lane @@ -457,7 +465,7 @@ def _compute_formation( offsets = [params.def_side * side_dir] else: offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] - for r, off in zip(defender_roles, offsets): + for r, off in zip(defender_roles, offsets, strict=True): out[r] = self._clamp_field(anchor + off * perp, field) # --- supporter: slightly in front of the ball, kept inside the field -------- # diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index afd6f3c4c..c2a8be09d 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -5,11 +5,18 @@ Click the field to move the ball; use the sliders to tweak params. """ +from typing import TypedDict + import numpy as np from bitbots_blackboard.capsules.positioning_capsule import Field, InnerPositioningCapsule, Params _inner = InnerPositioningCapsule() +class State(TypedDict): + ball: tuple[float, float] + n: int + robots: list[np.ndarray] + def run_gui(): import matplotlib.pyplot as plt @@ -22,7 +29,7 @@ def run_gui(): # updated in place every frame via `_match_assignment` - unlike the formation targets # (which are recomputed from scratch each frame), this gives "robot i" a stable # identity across ball moves, so marking one passive keeps referring to the same robot. - state = {"ball": np.array([1.0, 0.5]), "n": 5, "robots": None} + state: State = {"ball": (1.0, 0.5), "n": 5, "robots": []} colors = {"goalie": "#e6b800", "striker": "#d62728", "supporter": "#2ca02c"} @@ -30,7 +37,7 @@ def run_gui(): plt.subplots_adjust(left=0.08, right=0.97, top=0.98, bottom=0.50) def _ax(b): - return plt.axes([0.18, b, 0.72, 0.015]) + return plt.axes((0.18, b, 0.72, 0.015)) s_n = Slider(_ax(0.470), "players", 1, 8, valinit=state["n"], valstep=1) s_sep = Slider(_ax(0.440), "min_sep", 0.3, 2.0, valinit=params.min_sep) @@ -45,14 +52,14 @@ def _ax(b): s_back = Slider(_ax(0.170), "back dist", 0.0, 3.0, valinit=params.back_dist) s_kclr = Slider(_ax(0.140), "kick clear", 0.0, 1.5, valinit=params.kick_clear) s_gout = Slider(_ax(0.110), "goalie out", 0.2, 2.0, valinit=params.d_g) - check_sp = CheckButtons(plt.axes([0.18, 0.073, 0.20, 0.022]), ["set play"], [False]) + check_sp = CheckButtons(plt.axes((0.18, 0.073, 0.20, 0.022)), ["set play"], [False]) s_spcl = Slider(_ax(0.050), "set play clearance", 0.1, 2.0, valinit=params.opp_set_play_clearance) # one checkbox per possible robot identity (0..max players - 1); checkboxes beyond the # current player count are simply ignored. CheckButtons (unlike TextBox) doesn't hook # resize_event, so it doesn't hit the matplotlib bug where TextBox crashes on any # window resize (ResizeEvent has no .inaxes, but TextBox._resize assumes it does). max_players = 8 - ax_passive = plt.axes([0.915, 0.05, 0.07, 0.40]) # right of the sliders, below the plot + ax_passive = plt.axes((0.915, 0.05, 0.07, 0.40)) # right of the sliders, below the plot ax_passive.set_title("passive\nrobot", fontsize=9) check_passive = CheckButtons(ax_passive, [str(i) for i in range(max_players)], [False] * max_players) @@ -147,9 +154,9 @@ def draw(): # (role colors like the green defender/supporter vanish against the pitch), with # a hollow ring marking the start so the direction of travel is clear ax.plot([old_pose[0], p[0]], [old_pose[1], p[1]], ls=(0, (4, 2)), color="white", lw=1.7, alpha=0.95, zorder=3) - ax.add_patch(Circle(old_pose[:2], 0.07, fill=False, ec="white", lw=1.2, alpha=0.8, zorder=3)) - ax.add_patch(Circle(p, params.min_sep / 2, color=c, alpha=0.18, zorder=2)) - ax.add_patch(Circle(p, 0.16, color=c, ec="black", zorder=6)) + ax.add_patch(Circle(tuple(old_pose[:2]), 0.07, fill=False, ec="white", lw=1.2, alpha=0.8, zorder=3)) + ax.add_patch(Circle(tuple(p), params.min_sep / 2, color=c, alpha=0.18, zorder=2)) + ax.add_patch(Circle(tuple(p), 0.16, color=c, ec="black", zorder=6)) ax.plot( [p[0], p[0] + 0.45 * np.cos(th)], [p[1], p[1] + 0.45 * np.sin(th)], @@ -177,7 +184,7 @@ def draw(): def on_click(event): if event.inaxes is ax and event.xdata is not None: - state["ball"] = np.array([event.xdata, event.ydata]) + state["ball"] = (event.xdata, event.ydata) draw() for s in ( From a093312193c3197a746ebbeeffe2893c0357aa1a Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Sat, 4 Jul 2026 08:34:14 +0900 Subject: [PATCH 48/68] pixi format --- .../bitbots_blackboard/capsules/positioning_capsule.py | 10 ++++++++-- .../bitbots_blackboard/scripts/debug_positioning.py | 5 ++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index b7406ad57..3e60635ae 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -1,6 +1,7 @@ +from collections.abc import Sequence from dataclasses import dataclass from enum import StrEnum -from typing import Sequence, TypedDict +from typing import TypedDict import numpy as np from bitbots_utils.utils import get_parameters_from_other_node @@ -379,7 +380,12 @@ def _match_assignment( # --------------------------------------------------------------------------- # def _compute_formation( - self, ball: NDArray[np.float64] | tuple[float, float], field: Field, n_players: int, params: Params, opp_set_play: bool = False + self, + ball: NDArray[np.float64] | tuple[float, float], + field: Field, + n_players: int, + params: Params, + opp_set_play: bool = False, ) -> dict[str, NDArray[np.float64]]: """Map a ball position -> {role: np.array([x, y, yaw])}. Pure & deterministic. diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index c2a8be09d..96138b693 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -12,6 +12,7 @@ _inner = InnerPositioningCapsule() + class State(TypedDict): ball: tuple[float, float] n: int @@ -153,7 +154,9 @@ def draw(): # dashed trail from where this robot was last frame; fixed high-contrast white # (role colors like the green defender/supporter vanish against the pitch), with # a hollow ring marking the start so the direction of travel is clear - ax.plot([old_pose[0], p[0]], [old_pose[1], p[1]], ls=(0, (4, 2)), color="white", lw=1.7, alpha=0.95, zorder=3) + ax.plot( + [old_pose[0], p[0]], [old_pose[1], p[1]], ls=(0, (4, 2)), color="white", lw=1.7, alpha=0.95, zorder=3 + ) ax.add_patch(Circle(tuple(old_pose[:2]), 0.07, fill=False, ec="white", lw=1.2, alpha=0.8, zorder=3)) ax.add_patch(Circle(tuple(p), params.min_sep / 2, color=c, alpha=0.18, zorder=2)) ax.add_patch(Circle(tuple(p), 0.16, color=c, ec="black", zorder=6)) From 33a0ff262f0c7d6629e70b101ac263e1e3a47ddc Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Sat, 4 Jul 2026 02:53:54 +0200 Subject: [PATCH 49/68] Fix formatting Signed-off-by: Florian Vahl --- .../soccer_vision_3d_rviz_markers/visualizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/soccer_vision_3d_rviz_markers/soccer_vision_3d_rviz_markers/visualizer.py b/src/lib/soccer_vision_3d_rviz_markers/soccer_vision_3d_rviz_markers/visualizer.py index 3fcf1ff54..79d6abb7c 100755 --- a/src/lib/soccer_vision_3d_rviz_markers/soccer_vision_3d_rviz_markers/visualizer.py +++ b/src/lib/soccer_vision_3d_rviz_markers/soccer_vision_3d_rviz_markers/visualizer.py @@ -14,8 +14,8 @@ # limitations under the License. import rclpy -from rclpy.node import Node from rclpy.experimental.events_executor import EventsExecutor +from rclpy.node import Node from soccer_vision_3d_msgs.msg import ( BallArray, FieldBoundary, GoalpostArray, MarkingArray, ObstacleArray, RobotArray) @@ -98,7 +98,7 @@ def main(args=None): executor.spin() except KeyboardInterrupt: pass - + if __name__ == '__main__': main() From 0e885e37bf5f0f0b68e5c8db545f8f785df84d69 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Sat, 4 Jul 2026 02:54:18 +0200 Subject: [PATCH 50/68] Remove unreachable code Signed-off-by: Florian Vahl --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index be7e729d5..14fec6b9b 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -85,15 +85,12 @@ $SecondBallTouchAllowed NO --> $ConfigRole STRIKER --> #SearchBall ELSE --> #RolePositionWithPause - YES --> $KickOffTimeUp // TODO ASK Clemens regarding rules - NO_NORMAL --> #StandAndLook - NO_FREEKICK --> #Placing // I think this is unreachable - YES --> $AssignedRole - STRIKER --> #KickWithAvoidance - SUPPORTER --> #SupporterRole - ELSE --> $BallInOwnPercent + p:40 - YES --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition - NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + stand:true + enter_position:%defender_enter_position + leave_position:%defender_leave_position + enter_orientation:%defender_enter_orientation + leave_orientation:%defender_leave_orientation + YES --> $AssignedRole + STRIKER --> #KickWithAvoidance + SUPPORTER --> #SupporterRole + ELSE --> $BallInOwnPercent + p:40 + YES --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + stand:true + enter_position:%defender_enter_position + leave_position:%defender_leave_position + enter_orientation:%defender_enter_orientation + leave_orientation:%defender_leave_orientation #ThrowinGoalKickCornerkickBehavior $DoOnce From 5904a096531796f17383e45f8d8f520069c8bd4e Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Sat, 4 Jul 2026 02:54:45 +0200 Subject: [PATCH 51/68] Rework set play situation Signed-off-by: Florian Vahl --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 14fec6b9b..aa438ace1 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -71,10 +71,6 @@ $SecondaryStateTeamDecider YES --> @TrackBall, @Stand NO --> @LookAtFieldFeatures, @Stand -#Placing -@ChangeAction + action:positioning, @ForgetBall, @LookAtFieldFeatures, @GoToFormationPosition + set_play:true + stand:true + enter_position:%placing_enter_position + leave_position:%placing_leave_position + enter_orientation:%placing_enter_orientation + leave_orientation:%placing_leave_orientation - - #Init @Stand + duration:0.1 + r:false, @ChangeAction + action:waiting, @LookForward, @Stand @@ -92,23 +88,18 @@ $SecondBallTouchAllowed YES --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition NO --> @LookAtFieldFeatures, @ChangeAction + action:positioning, @GoToFormationPosition + stand:true + enter_position:%defender_enter_position + leave_position:%defender_leave_position + enter_orientation:%defender_enter_orientation + leave_orientation:%defender_leave_orientation -#ThrowinGoalKickCornerkickBehavior +#SetPlaySituation $DoOnce NOT_DONE --> @SetNoSecondBallContactVariable + value:true, @ForgetBallStartPosition + r:false DONE --> $SecondaryStateTeamDecider OUR --> #NormalBehavior - ELSE --> #Placing + ELSE --> @ChangeAction + action:positioning, @ForgetBall, @LookAtFieldFeatures, @GoToFormationPosition + set_play:true + stand:true + enter_position:%placing_enter_position + leave_position:%placing_leave_position + enter_orientation:%placing_enter_orientation + leave_orientation:%placing_leave_orientation #PlayingBehavior $SecondaryStateDecider PENALTYSHOOT --> #PenaltyShootoutBehavior TIMEOUT --> #StandAndLook - THROW_IN --> #ThrowinGoalKickCornerkickBehavior - CORNER_KICK --> #ThrowinGoalKickCornerkickBehavior - GOAL_KICK --> #ThrowinGoalKickCornerkickBehavior - ELSE --> $SecondaryStateTeamDecider - OUR --> #NormalBehavior - ELSE --> #Placing + ELSE --> #SetPlaySituation NORMAL --> #NormalBehavior OVERTIME --> #NormalBehavior From 1b38e337412c13b1bd3255ba2b773ec7e3015e9a Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Sat, 4 Jul 2026 03:03:02 +0200 Subject: [PATCH 52/68] Add method to retrieve robot's own role and clean up role assignment logic Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 6 ++++++ .../behavior_dsd/decisions/closest_to_ball.py | 18 ------------------ 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 3e60635ae..bcf0879f4 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -130,6 +130,12 @@ def get_formation_assignment(self) -> dict[int, RobotAssignment]: def get_set_play_formation_assignment(self) -> dict[int, RobotAssignment]: return self._get_formation_assignment(set_play=True) + def get_own_role(self) -> Role: + """Return the role of the robot with the own_id.""" + own_id = self._blackboard.gamestate.get_own_id() + assignment = self.get_formation_assignment() + return Role(assignment[own_id]["role"]) + def _get_formation_assignment(self, set_play=False) -> dict[int, RobotAssignment]: ball_pose = self._blackboard.world_model.get_best_ball_point_stamped() ball = np.array([ball_pose.point.x, ball_pose.point.y]) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py index 938da5919..33c02777b 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/closest_to_ball.py @@ -50,24 +50,6 @@ def perform(self, reevaluate=False): role = self.blackboard.positioning.get_own_role() self.publish_debug_data("Role from positioning", role) return role.upper() - """if role == "STRIKER": - return "STRIKER" - elif role == 2: - return "GOALIE" - elif role == 3: - return "DEFENDER" - elif role == 4: - return "SUPPORTER" - elif role == 5: - return "DEFENDER" - elif role == 6: - return "DEFENDER" - elif role == 7: - return "DEFENDER" - else: - # emergency fall back if something goes wrong - self.blackboard.node.get_logger().warning("Rank to ball had some issues. Role" + role) - return "STRIKER" """ def get_reevaluate(self): return True From d35ad73d4dafd0375d9a4780811c9d5d6bc6fb3c Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Sat, 4 Jul 2026 16:31:05 +0900 Subject: [PATCH 53/68] Correct unit of parameter --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 2 +- .../bitbots_body_behavior/config/body_behavior.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index bc82ec7dd..f1f8d4d53 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -38,7 +38,7 @@ $DoOnce $KickOrDribble + map_goal_distance:%ball_approach_dist // should be same as below $GoToBall + target:map action KICK --> $DoOnce NOT_DONE --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToBall + target:rl_kick + blocking:false - DONE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:%rl_kick_approach_tolerance_pos + orientation_threshold:%rl_kick_approach_tolerance_rad + latch:true + DONE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:%rl_kick_approach_tolerance_pos + orientation_threshold:%rl_kick_approach_tolerance_deg + latch:true NO --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToBall + target:rl_kick YES --> $DoOnce NOT_DONE --> @StoreBallMovementDetectionStartPosition diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index f302942d9..c45bf4624 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -170,7 +170,7 @@ body_behavior: kick_decision_smoothing: 10.0 rl_kick_approach_tolerance_pos: 0.20 - rl_kick_approach_tolerance_rad: 0.3 + rl_kick_approach_tolerance_deg: 20.0 rl_kick: timeout: 2.0 # how long the kick policy is active From 888ea17219137fa7046239ffe610703bbc14c724 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sat, 4 Jul 2026 16:55:38 +0900 Subject: [PATCH 54/68] remove latch --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index f1f8d4d53..32c7940ca 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -30,15 +30,11 @@ $DoOnce YES --> #StandAndLook NO --> @LookAtFieldFeatures, @GoToRolePosition - -#Kick - - #KickWithAvoidance $KickOrDribble + map_goal_distance:%ball_approach_dist // should be same as below $GoToBall + target:map action KICK --> $DoOnce NOT_DONE --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToBall + target:rl_kick + blocking:false - DONE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:%rl_kick_approach_tolerance_pos + orientation_threshold:%rl_kick_approach_tolerance_deg + latch:true + DONE --> $ReachedAndAlignedToPathPlanningGoalPosition + threshold:%rl_kick_approach_tolerance_pos + orientation_threshold:%rl_kick_approach_tolerance_deg NO --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToBall + target:rl_kick YES --> $DoOnce NOT_DONE --> @StoreBallMovementDetectionStartPosition From 1ece6ee8e60781b5aa5d23bcf512e88cda91d5ee Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sat, 4 Jul 2026 16:57:10 +0900 Subject: [PATCH 55/68] dont reevaluate Forget Ball --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 32c7940ca..3a043bff9 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -38,7 +38,7 @@ $KickOrDribble + map_goal_distance:%ball_approach_dist // should be same as belo NO --> @ChangeAction + action:going_to_ball, @LookAtFieldFeatures, @GoToBall + target:rl_kick YES --> $DoOnce NOT_DONE --> @StoreBallMovementDetectionStartPosition - DONE --> @ChangeAction + action:kicking, @Stand + duration:0.1 + r:false, @LookAtBallPenalty + r:false, @RLKickTowardsGoal + strength:3.0 + r:false, @ForgetBall + DONE --> @ChangeAction + action:kicking, @Stand + duration:0.1 + r:false, @LookAtBallPenalty + r:false, @RLKickTowardsGoal + strength:3.0 + r:false, @ForgetBall + r:false DRIBBLE --> $AvoidBall // old behavior before kick when we want to kick the ball in NO --> $BallClose + distance:%ball_reapproach_dist + angle:%ball_reapproach_angle YES --> $BallKickArea From 3e11e17e198e7b866a4051c765f0573057687d1e Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Sat, 4 Jul 2026 11:04:13 +0200 Subject: [PATCH 56/68] Add deadband filter for with player number prio for striker assignment Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 35 ++++++++++++------- .../scripts/debug_positioning.py | 2 +- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index bcf0879f4..e35835ba8 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -152,7 +152,7 @@ def _get_formation_assignment(self, set_play=False) -> dict[int, RobotAssignment # `_match_assignment` identifies robots by their index into `old_poses`, not by # jersey/robot id, so translate every passive robot id we know about into its index passive_indices = [ordered_jerseys.index(rid) for rid in passive_robot_ids if rid in ordered_jerseys] - pairs = self._inner._match_assignment(old_poses, new_items, ball, passive_indices) + pairs = self._inner._match_assignment(ordered_jerseys, old_poses, new_items, ball, passive_indices) return {ordered_jerseys[old_idx]: {"role": role, "goal_pose": new_pose} for old_idx, new_pose, role in pairs} @@ -336,36 +336,47 @@ def _clear_ball( def _match_assignment( self, + player_ids: Sequence[int], old_poses: Sequence[list[float] | NDArray[np.float64]], new_items: list[tuple[str, NDArray[np.float64]]], ball: NDArray[np.float64] | tuple[float, float], passive_indices: list[int], angle_w: float = 0.3, + striker_deadband: float = 0.2, ) -> list[tuple[int, NDArray[np.float64], str]]: """Assign physical robots (at `old_poses`) to the new target poses. - The robot closest to the ball always takes the striker target; the rest are + The striker target goes to the robot with the lowest player number among all + robots whose distance to the ball is within `striker_deadband` metres of the + robot closest to the ball. Grouping the near-equidistant robots and breaking + the tie on the player number keeps two robots from both deferring to each other + when their ball-distance estimates disagree by a few centimetres. The rest are matched optimally (Hungarian) to minimize total cost = distance + angle_w * heading difference. Returns a list of (old_idx, new_pose, new_role) where old_idx is the index into `old_poses`. + `player_ids`: player number of each robot, aligned with `old_poses`. `old_poses`: list of [x, y, theta]; `new_items`: list of (role, [x, y, theta]). `passive_indices`: indices into `old_poses` of robots that should not be assigned the striker role. Pass an empty list if there are no passive robots. If every - robot is passive, the striker slot must still be filled, so the closest passive - robot is assigned it anyway. + robot is passive, the striker slot must still be filled, so a passive robot is + assigned it anyway. """ assert len(passive_indices) <= len(new_items), "more passive robots reported than robots to assign" + assert len(player_ids) == len(old_poses), "player_ids must be aligned with old_poses" old_poses = [np.asarray(p) for p in old_poses] ball = np.asarray(ball) n = len(old_poses) - # striker target -> the old robot nearest the ball + # striker target -> chosen from the robots nearest the ball s_j = next(j for j, (r, _) in enumerate(new_items) if r == Role.STRIKER) - # candidates sorted by distance to the ball - candidates = sorted(range(n), key=lambda i: np.linalg.norm(old_poses[i][:2] - ball)) - # exclude passive robots from the striker choice, unless that would leave no candidate - if passive_indices: - s_i = next((i for i in candidates if i not in passive_indices), candidates[0]) - else: - s_i = candidates[0] + # distance of every robot to the ball + ball_dists = [float(np.linalg.norm(old_poses[i][:2] - ball)) for i in range(n)] + # exclude passive robots from the striker choice, unless every robot is passive + eligible = [i for i in range(n) if i not in passive_indices] or list(range(n)) + # treat every eligible robot within the deadband of the closest one as equally + # close to the ball, then take the lowest player number as a deterministic + # tie-break so both robots agree on who becomes striker + closest_dist = min(ball_dists[i] for i in eligible) + group = [i for i in eligible if ball_dists[i] <= closest_dist + striker_deadband] + s_i = min(group, key=lambda i: player_ids[i]) pairs = [(s_i, new_items[s_j][1], new_items[s_j][0])] rem_i = [i for i in range(n) if i != s_i] rem_j = [j for j in range(len(new_items)) if j != s_j] diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index 96138b693..e2281cc06 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -117,7 +117,7 @@ def draw(): passive_idxs = get_passive_indices(len(state["robots"])) robots = state["robots"] # assign each persistent robot (by index) to a role target for this frame - assignments = _inner._match_assignment(robots, new_items, state["ball"], passive_idxs) + assignments = _inner._match_assignment(list(range(len(robots))), robots, new_items, state["ball"], passive_idxs) # ball ax.add_patch(Circle(state["ball"], 0.12, color="white", ec="black", zorder=5)) From bb646bfee272c26c40e183b911fc72e494d29d76 Mon Sep 17 00:00:00 2001 From: sWintermoor Date: Sat, 4 Jul 2026 22:19:29 +0900 Subject: [PATCH 57/68] Wait after kick-off logic --- .../actions/wait_after_kick_off.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py new file mode 100644 index 000000000..f053f9407 --- /dev/null +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py @@ -0,0 +1,31 @@ +import numpy as np +from bitbots_blackboard.body_blackboard import BodyBlackboard +from dynamic_stack_decider.abstract_action_element import AbstractActionElement + + +class WaitAfterKickOff(AbstractActionElement): + """Logic for waiting after kick off.""" + + def __init__(self, blackboard, dsd, parameters): + super().__init__(blackboard, dsd, parameters) + self.blackboard: BodyBlackboard + + self.wait_after_kick_time = self.blackboard.config["waiting_after_kick_time"] + self.wait_after_kick_effective_radius = self.blackboard.config["waiting_after_kick_effective_radius"] + self.wait_after_kick_bool = self.blackboard.config["waiting_after_kick_bool"] + + def perform(self, reevaluate=False) -> int: + """If activated: Waits till a ball is out of the efffective zone or the waiting time is over.""" + ball_position_uv = self.blackboard.world_model.get_ball_position_uv() + + if self.wait_after_kick_bool: + stop_time = self._node.get_clock().now() + self.wait_after_kick_time + + if self._node.get_clock().now() < stop_time: + if np.square(self.wait_after_kick_effective) < np.square(ball_position_uv[0]) + np.square( + ball_position_uv[1] + ): + return + + self._node.get_clock().sleep_for(0.1) + return From a618b30e529dee21584287a47c1a3546ab708fc3 Mon Sep 17 00:00:00 2001 From: sWintermoor Date: Sat, 4 Jul 2026 22:32:07 +0900 Subject: [PATCH 58/68] config params for 'waiting after kick-off' --- .../behavior_dsd/actions/wait_after_kick_off.py | 6 +++--- .../bitbots_body_behavior/config/body_behavior.yaml | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py index f053f9407..b7b29f3ad 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py @@ -10,9 +10,9 @@ def __init__(self, blackboard, dsd, parameters): super().__init__(blackboard, dsd, parameters) self.blackboard: BodyBlackboard - self.wait_after_kick_time = self.blackboard.config["waiting_after_kick_time"] - self.wait_after_kick_effective_radius = self.blackboard.config["waiting_after_kick_effective_radius"] - self.wait_after_kick_bool = self.blackboard.config["waiting_after_kick_bool"] + self.wait_after_kick_time = self.blackboard.config["wait_after_kick_off_time"] + self.wait_after_kick_effective_radius = self.blackboard.config["wait_after_kick_off_effective_radius"] + self.wait_after_kick_bool = self.blackboard.config["wait_after_kick_off_bool"] def perform(self, reevaluate=False) -> int: """If activated: Waits till a ball is out of the efffective zone or the waiting time is over.""" diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index 0b537f3ee..c151d6019 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -218,3 +218,11 @@ body_behavior: # factor by which the difference in starting and goal angle is weighted (only if not turning to ball i.e. <1m) time_to_ball_cost_start_to_goal_angle: 3.82 + + ############################# + # waiting for kick-off params + ############################# + + wait_after_kick_off_bool: true + wait_after_kick_off_time: 15 + wait_after_kick_off_effective_radius: 0.5 From 6e49a6c0df60fe2ce78d6c39686a4ef17c5f001a Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Sat, 4 Jul 2026 18:04:58 +0200 Subject: [PATCH 59/68] Make supporter optional Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 20 +++++++++++++++++-- .../scripts/debug_positioning.py | 3 +++ .../config/body_behavior.yaml | 4 ++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index e35835ba8..57afe950f 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -77,6 +77,7 @@ class Params: gap: float = 1.1 # lateral spacing between adjacent defenders def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) # supporter + include_supporter: bool = False # if False, no supporter is assigned; its slot becomes an extra defender f: float = 1.6 # how far in front of the ball (toward opp goal) the supporter sits supp_side: float = 1.2 # supporter lateral offset magnitude (auto-leans toward centre) supp_max_x: float = 3.0 # supporter never goes past this x (keeps it out of the opp corner) @@ -117,6 +118,9 @@ def __init__(self, node, blackboard): goal_width=parameters["field.goal.width"], ) self._params = Params() + # Whether the formation includes a supporter. Off by default; enabling it lets one + # field player push up as a supporter instead of being an extra defender. + self._params.include_supporter = bool(blackboard.config.get("formation_include_supporter", False)) self._inner = InnerPositioningCapsule() # Cached capsule functions can not have parameters or side effects, @@ -205,7 +209,12 @@ def _clamp_field(p: NDArray[np.float64], fld: Field, margin: float | None = None # --------------------------------------------------------------------------- # @staticmethod - def _allocate_roles(n: int, ball: NDArray[np.float64] | None = None, field: Field | None = None) -> list[Role]: + def _allocate_roles( + n: int, + ball: NDArray[np.float64] | None = None, + field: Field | None = None, + include_supporter: bool = True, + ) -> list[Role]: """Keep-priority as the count drops: striker > goalie > 1st defender > supporter > 2nd defender (and any further players are extra defenders). @@ -214,6 +223,9 @@ def _allocate_roles(n: int, ball: NDArray[np.float64] | None = None, field: Fiel Short-handed (n < 5) with the ball in our own defensive third, the supporter is reassigned as an extra defender (note: this is a discrete role switch). + + When `include_supporter` is False, no supporter is allocated at all; its slot + becomes an extra defender instead. """ n_def = 0 has_support = False @@ -228,6 +240,10 @@ def _allocate_roles(n: int, ball: NDArray[np.float64] | None = None, field: Fiel if ball[0] < own_third: has_support, n_def = False, n_def + 1 + # supporter disabled by config: reassign its slot as an extra defender + if has_support and not include_supporter: + has_support, n_def = False, n_def + 1 + roles = [] if n >= 1: roles.append(Role.STRIKER) @@ -420,7 +436,7 @@ def _compute_formation( to_ball = self._normalize(b - goal) # our-goal -> ball perp = np.array([-to_ball[1], to_ball[0]]) - roles = self._allocate_roles(n_players, b, field) + roles = self._allocate_roles(n_players, b, field, include_supporter=params.include_supporter) if opp_set_play and Role.SUPPORTER in roles: n_def = sum(1 for r in roles if r.startswith(Role.DEFENDER + "_")) roles[roles.index(Role.SUPPORTER)] = Role(f"{Role.DEFENDER}_{n_def}") diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index e2281cc06..82eaaba0b 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -54,6 +54,7 @@ def _ax(b): s_kclr = Slider(_ax(0.140), "kick clear", 0.0, 1.5, valinit=params.kick_clear) s_gout = Slider(_ax(0.110), "goalie out", 0.2, 2.0, valinit=params.d_g) check_sp = CheckButtons(plt.axes((0.18, 0.073, 0.20, 0.022)), ["set play"], [False]) + check_supp = CheckButtons(plt.axes((0.42, 0.073, 0.20, 0.022)), ["supporter"], [params.include_supporter]) s_spcl = Slider(_ax(0.050), "set play clearance", 0.1, 2.0, valinit=params.opp_set_play_clearance) # one checkbox per possible robot identity (0..max players - 1); checkboxes beyond the # current player count are simply ignored. CheckButtons (unlike TextBox) doesn't hook @@ -89,6 +90,7 @@ def draw(): params.post_margin, params.back_dist = s_pmarg.val, s_back.val params.kick_clear = s_kclr.val opp_set_play = check_sp.get_status()[0] + params.include_supporter = check_supp.get_status()[0] params.opp_set_play_clearance = s_spcl.val n = int(s_n.val) @@ -208,6 +210,7 @@ def on_click(event): ): s.on_changed(lambda _v: draw()) check_sp.on_clicked(lambda _label: draw()) + check_supp.on_clicked(lambda _label: draw()) check_passive.on_clicked(lambda _label: draw()) fig.canvas.mpl_connect("button_press_event", on_click) draw() diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index c45bf4624..0cf650dc3 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -46,6 +46,10 @@ body_behavior: 1: [ -0.085, 0.33 ] 2: [ -0.085, -0.33 ] + # Whether the formation assignment includes a supporter role. + # If false, the supporter's slot is filled by an extra defender instead. + formation_include_supporter: false + support_enter_position: 0.1 support_leave_position: 0.3 support_enter_orientation: 0.1 From 6818fa5684cb9c49b4900936a5a240e8b0fa8e6a Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Sat, 4 Jul 2026 18:23:40 +0200 Subject: [PATCH 60/68] Add variable defender gap Signed-off-by: Florian Vahl --- .../capsules/positioning_capsule.py | 9 ++++-- .../scripts/debug_positioning.py | 31 ++++++++++--------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py index 57afe950f..4b71c4954 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/positioning_capsule.py @@ -74,7 +74,8 @@ class Params: D_max: float = 3.8 # max defender depth from goal (high-line cap) dz: float = 0.45 # keep defenders at least this far ahead of the goalie standoff: float = 1.0 # keep defenders at least this far (goal-side) of the ball - gap: float = 1.1 # lateral spacing between adjacent defenders + gap: float = 1.7 # lateral spacing between adjacent defenders (ball at/beyond the centre circle) + gap_close: float = 0.6 # lateral spacing when the ball is at our goal (defenders tuck in) def_side: float = 0.9 # lateral offset for a lone defender (so it's not on the axis) # supporter include_supporter: bool = False # if False, no supporter is assigned; its slot becomes an extra defender @@ -503,7 +504,11 @@ def _compute_formation( side_dir = -1.0 if b[1] >= 0 else 1.0 offsets = [params.def_side * side_dir] else: - offsets = [(k - (m - 1) / 2.0) * params.gap for k in range(m)] + # tighten the defender line as the ball nears our goal: full `gap` at the + # centre circle (and beyond), shrinking smoothly to `gap_close` at the goal + t = self._smoothstep(d, 0.0, field.length / 2.0) + gap = params.gap_close + t * (params.gap - params.gap_close) + offsets = [(k - (m - 1) / 2.0) * gap for k in range(m)] for r, off in zip(defender_roles, offsets, strict=True): out[r] = self._clamp_field(anchor + off * perp, field) diff --git a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py index 82eaaba0b..c16f95d40 100755 --- a/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py +++ b/src/bitbots_behavior/bitbots_blackboard/scripts/debug_positioning.py @@ -41,20 +41,21 @@ def _ax(b): return plt.axes((0.18, b, 0.72, 0.015)) s_n = Slider(_ax(0.470), "players", 1, 8, valinit=state["n"], valstep=1) - s_sep = Slider(_ax(0.440), "min_sep", 0.3, 2.0, valinit=params.min_sep) - s_alpha = Slider(_ax(0.410), "push α", 0.1, 0.8, valinit=params.alpha) - s_dbias = Slider(_ax(0.380), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) - s_dside = Slider(_ax(0.350), "def side", 0.0, 2.0, valinit=params.def_side) - s_gap = Slider(_ax(0.320), "def gap", 0.5, 2.0, valinit=params.gap) - s_f = Slider(_ax(0.290), "supp lead", 0.0, 3.0, valinit=params.f) - s_side = Slider(_ax(0.260), "supp side", 0.0, 2.5, valinit=params.supp_side) - s_smax = Slider(_ax(0.230), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) - s_pmarg = Slider(_ax(0.200), "post margin", 0.0, 1.3, valinit=params.post_margin) - s_back = Slider(_ax(0.170), "back dist", 0.0, 3.0, valinit=params.back_dist) - s_kclr = Slider(_ax(0.140), "kick clear", 0.0, 1.5, valinit=params.kick_clear) - s_gout = Slider(_ax(0.110), "goalie out", 0.2, 2.0, valinit=params.d_g) - check_sp = CheckButtons(plt.axes((0.18, 0.073, 0.20, 0.022)), ["set play"], [False]) - check_supp = CheckButtons(plt.axes((0.42, 0.073, 0.20, 0.022)), ["supporter"], [params.include_supporter]) + s_sep = Slider(_ax(0.442), "min_sep", 0.3, 2.0, valinit=params.min_sep) + s_alpha = Slider(_ax(0.414), "push α", 0.1, 0.8, valinit=params.alpha) + s_dbias = Slider(_ax(0.386), "def fwd/back", -2.0, 3.0, valinit=params.depth_bias) + s_dside = Slider(_ax(0.358), "def side", 0.0, 2.0, valinit=params.def_side) + s_gap = Slider(_ax(0.330), "def gap", 0.5, 2.0, valinit=params.gap) + s_gapc = Slider(_ax(0.302), "def gap @goal", 0.2, 2.0, valinit=params.gap_close) + s_f = Slider(_ax(0.274), "supp lead", 0.0, 3.0, valinit=params.f) + s_side = Slider(_ax(0.246), "supp side", 0.0, 2.5, valinit=params.supp_side) + s_smax = Slider(_ax(0.218), "supp max x", 0.0, 4.2, valinit=params.supp_max_x) + s_pmarg = Slider(_ax(0.190), "post margin", 0.0, 1.3, valinit=params.post_margin) + s_back = Slider(_ax(0.162), "back dist", 0.0, 3.0, valinit=params.back_dist) + s_kclr = Slider(_ax(0.134), "kick clear", 0.0, 1.5, valinit=params.kick_clear) + s_gout = Slider(_ax(0.106), "goalie out", 0.2, 2.0, valinit=params.d_g) + check_sp = CheckButtons(plt.axes((0.18, 0.078, 0.20, 0.022)), ["set play"], [False]) + check_supp = CheckButtons(plt.axes((0.42, 0.078, 0.20, 0.022)), ["supporter"], [params.include_supporter]) s_spcl = Slider(_ax(0.050), "set play clearance", 0.1, 2.0, valinit=params.opp_set_play_clearance) # one checkbox per possible robot identity (0..max players - 1); checkboxes beyond the # current player count are simply ignored. CheckButtons (unlike TextBox) doesn't hook @@ -85,6 +86,7 @@ def draw(): ax.set_facecolor("#2e7d32") params.min_sep, params.alpha, params.gap, params.f = s_sep.val, s_alpha.val, s_gap.val, s_f.val + params.gap_close = s_gapc.val params.depth_bias, params.supp_side, params.d_g = s_dbias.val, s_side.val, s_gout.val params.supp_max_x, params.def_side = s_smax.val, s_dside.val params.post_margin, params.back_dist = s_pmarg.val, s_back.val @@ -199,6 +201,7 @@ def on_click(event): s_dbias, s_dside, s_gap, + s_gapc, s_f, s_side, s_smax, From 463144b2e7a674895ab8e15157fb0eed8fa4c217 Mon Sep 17 00:00:00 2001 From: Florian Vahl Date: Sat, 4 Jul 2026 18:39:00 +0200 Subject: [PATCH 61/68] Add better defensive positions Signed-off-by: Florian Vahl --- .../bitbots_body_behavior/config/body_behavior.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index 2b0ae5ce7..a939350de 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -25,17 +25,17 @@ body_behavior: # To be useful for different field sizes, use values in [-1, 1] for x and y role_positions: - goalie: [ -0.7, 0.0 ] + goalie: [ -0.9, 0.0 ] defense: passive: # passive: opponent has kickoff, active: we have kickoff # position number 0 = center, 1 = left, 2 = right 0: [ -0.5, 0.0 ] - 1: [ -0.45, 0.5 ] - 2: [ -0.45, -0.5 ] + 1: [ -0.6, 0.2 ] + 2: [ -0.6, -0.2 ] active: 0: [ -0.5, 0.0 ] - 1: [ -0.45, 0.5 ] - 2: [ -0.45, -0.5 ] + 1: [ -0.6, 0.2 ] + 2: [ -0.6, -0.2 ] offense: passive: 0: [ -0.27, 0.0 ] From ae6c633e3a3fb963f9b0ca2922f48cfda94b8189 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sun, 5 Jul 2026 01:52:17 +0900 Subject: [PATCH 62/68] everything :) --- .../actions/go_to_role_position.py | 8 ++++- .../actions/wait_after_kick_off.py | 31 ------------------- .../behavior_dsd/actions/walk.py | 18 +++++++++++ .../behavior_dsd/main.dsd | 8 ++++- .../config/body_behavior.yaml | 2 +- 5 files changed, 33 insertions(+), 34 deletions(-) delete mode 100644 src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_role_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_role_position.py index b7e31edf4..ed110ba8d 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_role_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_role_position.py @@ -23,9 +23,15 @@ def __init__(self, blackboard, dsd, parameters): # Adapt position to field size # TODO know where map frame is located + try: + rotation = generalized_role_position[2] + except: + rotation = 1.0 + self.role_position = [ generalized_role_position[0] * self.blackboard.world_model.field_length / 2, generalized_role_position[1] * self.blackboard.world_model.field_width / 2, + rotation ] self.blocking = parameters.get("blocking", True) @@ -37,7 +43,7 @@ def perform(self, reevaluate=False): pose_msg.pose.position.x = self.role_position[0] pose_msg.pose.position.y = self.role_position[1] - pose_msg.pose.orientation.w = 1.0 + pose_msg.pose.orientation.w = self.role_position[2] self.blackboard.pathfinding.publish(pose_msg) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py deleted file mode 100644 index b7b29f3ad..000000000 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/wait_after_kick_off.py +++ /dev/null @@ -1,31 +0,0 @@ -import numpy as np -from bitbots_blackboard.body_blackboard import BodyBlackboard -from dynamic_stack_decider.abstract_action_element import AbstractActionElement - - -class WaitAfterKickOff(AbstractActionElement): - """Logic for waiting after kick off.""" - - def __init__(self, blackboard, dsd, parameters): - super().__init__(blackboard, dsd, parameters) - self.blackboard: BodyBlackboard - - self.wait_after_kick_time = self.blackboard.config["wait_after_kick_off_time"] - self.wait_after_kick_effective_radius = self.blackboard.config["wait_after_kick_off_effective_radius"] - self.wait_after_kick_bool = self.blackboard.config["wait_after_kick_off_bool"] - - def perform(self, reevaluate=False) -> int: - """If activated: Waits till a ball is out of the efffective zone or the waiting time is over.""" - ball_position_uv = self.blackboard.world_model.get_ball_position_uv() - - if self.wait_after_kick_bool: - stop_time = self._node.get_clock().now() + self.wait_after_kick_time - - if self._node.get_clock().now() < stop_time: - if np.square(self.wait_after_kick_effective) < np.square(ball_position_uv[0]) + np.square( - ball_position_uv[1] - ): - return - - self._node.get_clock().sleep_for(0.1) - return diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/walk.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/walk.py index 249271701..11553ed20 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/walk.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/walk.py @@ -20,3 +20,21 @@ def perform(self, reevaluate=False): self.blackboard.pathfinding.direct_cmd_vel_pub.publish(cmd_vel) else: self.pop() + +class WalkBackward(AbstractActionElement): + def __init__(self, blackboard, dsd, parameters): + super().__init__(blackboard, dsd, parameters) + self.time = parameters.get("time", 0.5) + self.start_time = self.blackboard.node.get_clock().now() + + def perform(self, reevaluate=False): + if self.blackboard.node.get_clock().now() - self.start_time < Duration(seconds=self.time): + # Cancel the path planning if it is running + self.blackboard.pathfinding.cancel_goal() + + # Publish the walk command + cmd_vel = Twist() + cmd_vel.linear.x = -0.8 + self.blackboard.pathfinding.direct_cmd_vel_pub.publish(cmd_vel) + else: + self.pop() diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 7851fbf80..edea7711b 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -188,6 +188,12 @@ $IsPenalized FINISHED --> $CurrentScore AHEAD --> @Stand + duration:0.5 + r:false, @PlaySound + file:fanfare.wav, @PlayAnimationCheering + r:false, @LookForward, @Stand ELSE --> #Init - PLAYING --> #PlayingBehavior + PLAYING --> $DoOnce //replace PlayingBehavior to fix + NOT_DONE --> $ConfigRole + STRIKER --> $SecondaryStateTeamDecider + OUR --> @Stand + duration:10.0 + r:false, @WalkForward + time:2 + r:false, @ChangeAction + action:passive + r:false, @WalkBackward + time:1 + r:false + ELSE --> #PlayingBehavior + ELSE --> #PlayingBehavior + DONE --> #PlayingBehavior STANDBY --> #StandAndLook STOPPED --> #DoNothing diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index c151d6019..5f50acca4 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -41,7 +41,7 @@ body_behavior: 1: [ -0.2, 0.33 ] 2: [ -0.2, -0.33 ] active: - 0: [ -0.1, 0.0 ] + 0: [ 0.07, -0.04, 0.342] 1: [ -0.085, 0.33 ] 2: [ -0.085, -0.33 ] From 701d866abb6947512bda07e747fdac5d0699cc6e Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sun, 5 Jul 2026 07:28:15 +0900 Subject: [PATCH 63/68] fixes mit Flo --- .../capsules/game_status_capsule.py | 7 +++++++ .../set_no_kick_off_or_throw_in_variable.py | 17 +++++++++++++++++ .../decisions/game_state_decider.py | 12 ++++++++++++ .../bitbots_body_behavior/behavior_dsd/main.dsd | 8 ++++---- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py index 740f04e2c..90eacdb67 100644 --- a/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py +++ b/src/bitbots_behavior/bitbots_blackboard/bitbots_blackboard/capsules/game_status_capsule.py @@ -23,11 +23,15 @@ def __init__(self, node, blackboard=None): self.free_kick_kickoff_team: bool | None = None self.game_controller_stop: bool = False self.last_timestep_whistle_detected: Time | None = None + self.last_timestep_in_set: float = 0.0 # publish stopped msg for hcm self.stop_pub = node.create_publisher(Bool, "game_controller/stop_msg", 1) # last kicking team self.last_kicking_team: int | None = None + def set_set_timestep(self): + self.last_timestep_in_set = self._node.get_clock().now().nanoseconds / 1e9 + def get_main_state(self) -> int: # Init, ready, set, playing, finished return self.gamestate.main_state @@ -67,6 +71,9 @@ def get_rival_score(self) -> int: def get_seconds_since_own_goal(self) -> float: return self._node.get_clock().now().nanoseconds / 1e9 - self.last_goal_from_us_time + + def get_seconds_since_kickoff(self) -> float: + return self._node.get_clock().now().nanoseconds / 1e9 - self.last_timestep_in_set def get_seconds_since_any_goal(self) -> float: return self._node.get_clock().now().nanoseconds / 1e9 - self.last_goal_time diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/set_no_kick_off_or_throw_in_variable.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/set_no_kick_off_or_throw_in_variable.py index f4826b530..34e1eb648 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/set_no_kick_off_or_throw_in_variable.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/set_no_kick_off_or_throw_in_variable.py @@ -18,3 +18,20 @@ def __init__(self, blackboard, dsd, parameters): def perform(self, reevaluate=False): self.pop() + +class SetTimerKickoff(AbstractActionElement): + """ + Sets the no_second_ball_contact variable. + """ + + blackboard: BodyBlackboard + + def __init__(self, blackboard, dsd, parameters): + super().__init__(blackboard, dsd, parameters) + self.do_not_reevaluate() + self.blackboard = blackboard + + self.blackboard.gamestate.set_set_timestep() + + def perform(self, reevaluate=False): + self.pop() diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/game_state_decider.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/game_state_decider.py index 76d38db49..71f120600 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/game_state_decider.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/decisions/game_state_decider.py @@ -44,3 +44,15 @@ def get_reevaluate(self): Game state can change during the game """ return True + +class WasKickoff(AbstractDecisionElement): + blackboard: BodyBlackboard + + def __init__(self, blackboard, dsd, parameters): + super().__init__(blackboard, dsd, parameters) + + def perform(self, reevaluate=False): + if self.blackboard.gamestate.get_seconds_since_kickoff() < 5.0: + return "YES" + else: + return "NO" diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index edea7711b..698503296 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -184,15 +184,15 @@ $IsPenalized OTHER --> $BallSeen YES --> @Stand + duration:0.1 + r:false, @DeactivateHCM + r:false, @LookForward + r:false, @TrackBall + r:false, @PlayAnimationGoalieArms + r:false, @Stand // goalie only needs to care about the ball NO --> @Stand + duration:0.1 + r:false, @DeactivateHCM + r:false, @LookForward + r:false, @LookAtFieldFeatures + r:false, @PlayAnimationGoalieArms + r:false, @Stand - ELSE --> #StandAndLook + ELSE --> @ChangeAction + action:waiting, @LookAtFieldFeatures, @Stand + duration:0.1, @SetTimerKickoff FINISHED --> $CurrentScore AHEAD --> @Stand + duration:0.5 + r:false, @PlaySound + file:fanfare.wav, @PlayAnimationCheering + r:false, @LookForward, @Stand ELSE --> #Init PLAYING --> $DoOnce //replace PlayingBehavior to fix NOT_DONE --> $ConfigRole - STRIKER --> $SecondaryStateTeamDecider - OUR --> @Stand + duration:10.0 + r:false, @WalkForward + time:2 + r:false, @ChangeAction + action:passive + r:false, @WalkBackward + time:1 + r:false - ELSE --> #PlayingBehavior + STRIKER --> $WasKickoff + YES --> @Stand + duration:10.0 + r:false, @WalkForward + time:2 + r:false, @ChangeAction + action:passive + r:false, @WalkBackward + time:1 + r:false, @Stand + duration:5.0 + NO --> #PlayingBehavior ELSE --> #PlayingBehavior DONE --> #PlayingBehavior STANDBY --> #StandAndLook From c80d5f6bd2d2bb40f0e7892a7a18bbe74f958d96 Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Sun, 5 Jul 2026 06:44:23 +0800 Subject: [PATCH 64/68] Fix rotation handling --- .../behavior_dsd/actions/go_to_role_position.py | 12 +++++++++--- .../bitbots_body_behavior/config/body_behavior.yaml | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_role_position.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_role_position.py index ed110ba8d..2ae984c59 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_role_position.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_role_position.py @@ -1,6 +1,7 @@ from bitbots_blackboard.body_blackboard import BodyBlackboard from dynamic_stack_decider.abstract_action_element import AbstractActionElement from tf2_geometry_msgs import PoseStamped +from tf_transformations import euler_from_quaternion, quaternion_from_euler class GoToRolePosition(AbstractActionElement): @@ -25,8 +26,8 @@ def __init__(self, blackboard, dsd, parameters): # TODO know where map frame is located try: rotation = generalized_role_position[2] - except: - rotation = 1.0 + except IndexError: + rotation = 0.0 self.role_position = [ generalized_role_position[0] * self.blackboard.world_model.field_length / 2, @@ -43,7 +44,12 @@ def perform(self, reevaluate=False): pose_msg.pose.position.x = self.role_position[0] pose_msg.pose.position.y = self.role_position[1] - pose_msg.pose.orientation.w = self.role_position[2] + self.blackboard.node.get_logger().info(f"Going to role position: {self.role_position[0]}, {self.role_position[1]}, {self.role_position[2]}") + x,y,z,w = quaternion_from_euler(0, 0, self.role_position[2]) + pose_msg.pose.orientation.x = x + pose_msg.pose.orientation.y = y + pose_msg.pose.orientation.z = z + pose_msg.pose.orientation.w = w self.blackboard.pathfinding.publish(pose_msg) diff --git a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml index 5f50acca4..f55c589bf 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml +++ b/src/bitbots_behavior/bitbots_body_behavior/config/body_behavior.yaml @@ -41,7 +41,7 @@ body_behavior: 1: [ -0.2, 0.33 ] 2: [ -0.2, -0.33 ] active: - 0: [ 0.07, -0.04, 0.342] + 0: [ 0.07, -0.04, 2.53] 1: [ -0.085, 0.33 ] 2: [ -0.085, -0.33 ] From 07f098aea2478a649123b0d41485d5e9d02bd6d7 Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Sun, 5 Jul 2026 06:52:11 +0800 Subject: [PATCH 65/68] Correct role name --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 698503296..086eb890b 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -190,7 +190,7 @@ $IsPenalized ELSE --> #Init PLAYING --> $DoOnce //replace PlayingBehavior to fix NOT_DONE --> $ConfigRole - STRIKER --> $WasKickoff + OFFENSE --> $WasKickoff YES --> @Stand + duration:10.0 + r:false, @WalkForward + time:2 + r:false, @ChangeAction + action:passive + r:false, @WalkBackward + time:1 + r:false, @Stand + duration:5.0 NO --> #PlayingBehavior ELSE --> #PlayingBehavior From b673429d7bc1a9079d1d7020bcda6b6caa65feb9 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sun, 5 Jul 2026 07:56:15 +0900 Subject: [PATCH 66/68] fix opp kick off --- .../bitbots_body_behavior/behavior_dsd/main.dsd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 086eb890b..e87fe5302 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -184,7 +184,9 @@ $IsPenalized OTHER --> $BallSeen YES --> @Stand + duration:0.1 + r:false, @DeactivateHCM + r:false, @LookForward + r:false, @TrackBall + r:false, @PlayAnimationGoalieArms + r:false, @Stand // goalie only needs to care about the ball NO --> @Stand + duration:0.1 + r:false, @DeactivateHCM + r:false, @LookForward + r:false, @LookAtFieldFeatures + r:false, @PlayAnimationGoalieArms + r:false, @Stand - ELSE --> @ChangeAction + action:waiting, @LookAtFieldFeatures, @Stand + duration:0.1, @SetTimerKickoff + ELSE --> $SecondaryStateTeamDecider + OUR --> @ChangeAction + action:waiting, @LookAtFieldFeatures, @Stand + duration:0.1, @SetTimerKickoff + ELSE --> #StandAndLook FINISHED --> $CurrentScore AHEAD --> @Stand + duration:0.5 + r:false, @PlaySound + file:fanfare.wav, @PlayAnimationCheering + r:false, @LookForward, @Stand ELSE --> #Init From 7f5fc561ac032a0ada355975b78851448199fc48 Mon Sep 17 00:00:00 2001 From: Cornelius Krupp Date: Sun, 5 Jul 2026 07:09:12 +0800 Subject: [PATCH 67/68] Fix GoToBall --- .../behavior_dsd/actions/go_to_ball.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py index 39744ace8..2baea172c 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/go_to_ball.py @@ -3,7 +3,6 @@ from dynamic_stack_decider.abstract_action_element import AbstractActionElement from geometry_msgs.msg import Vector3 from std_msgs.msg import ColorRGBA -from tf2_geometry_msgs import PoseStamped from visualization_msgs.msg import Marker @@ -26,15 +25,7 @@ def __init__(self, blackboard, dsd, parameters): self.side_offset = parameters.get("side_offset", 0.00) def perform(self, reevaluate=False): - pose_msg = PoseStamped() - pose_msg.header.stamp = self.blackboard.node.get_clock().now().to_msg() - pose_msg.header.frame_id = self.blackboard.map_frame - optimal_positioning = self.blackboard.positioning.get_formation_assignment() - own_position = optimal_positioning[self.blackboard.gamestate.get_own_id()] - pose = own_position["goal_pose"] - pose_msg.pose.position.x = pose[0] - pose_msg.pose.position.y = pose[1] - pose_msg.pose.orientation.w = pose[2] + pose_msg = self.blackboard.pathfinding.get_ball_goal(self.target, self.distance, self.side_offset) self.blackboard.pathfinding.publish(pose_msg) if self.target != BallGoalType.RL_KICK: From bef968c33b67380fa5fbe70672338f4ba29f04f0 Mon Sep 17 00:00:00 2001 From: Clemens Wulff Date: Sun, 5 Jul 2026 08:25:37 +0900 Subject: [PATCH 68/68] update times --- .../bitbots_body_behavior/behavior_dsd/actions/walk.py | 2 +- .../bitbots_body_behavior/behavior_dsd/main.dsd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/walk.py b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/walk.py index 11553ed20..073ddf9dc 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/walk.py +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/actions/walk.py @@ -16,7 +16,7 @@ def perform(self, reevaluate=False): # Publish the walk command cmd_vel = Twist() - cmd_vel.linear.x = 0.8 + cmd_vel.linear.x = 0.4 self.blackboard.pathfinding.direct_cmd_vel_pub.publish(cmd_vel) else: self.pop() diff --git a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd index 0254f71c6..45a5321e9 100644 --- a/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd +++ b/src/bitbots_behavior/bitbots_body_behavior/bitbots_body_behavior/behavior_dsd/main.dsd @@ -153,7 +153,7 @@ $IsPenalized PLAYING --> $DoOnce //replace PlayingBehavior to fix NOT_DONE --> $ConfigRole OFFENSE --> $WasKickoff - YES --> @Stand + duration:10.0 + r:false, @WalkForward + time:2 + r:false, @ChangeAction + action:passive + r:false, @WalkBackward + time:1 + r:false, @Stand + duration:5.0 + YES --> @Stand + duration:8.0 + r:false, @WalkForward + time:2 + r:false, @ChangeAction + action:passive + r:false, @WalkBackward + time:2 + r:false, @Stand + duration:5.0 NO --> #PlayingBehavior ELSE --> #PlayingBehavior DONE --> #PlayingBehavior