{
  "schema_version": "1",
  "id": "ruckig-offline-trajectory",
  "name": "Offline position jerk-limited trajectory",
  "summary": "Offline position jerk-limited trajectory. Parameterized bounded JSON adapter; numerical operation, no hardware execution.",
  "capabilities": [
    "trajectory_generator",
    "offline",
    "executable-json",
    "source-adaptation"
  ],
  "aliases": [
    "offline",
    "Offline position jerk-limited trajectory"
  ],
  "source": {
    "repository": "https://github.com/pantor/ruckig",
    "commit": "a8db97a4e9c55e5160a3855f739fa3b270df8e4c",
    "paths": [
      "LICENSE",
      "examples/02_position_offline.py"
    ],
    "archive_url": "https://codeload.github.com/pantor/ruckig/tar.gz/a8db97a4e9c55e5160a3855f739fa3b270df8e4c",
    "archive_sha256": "2a935bfbe02f9236ecd138aee13b52fef2a43e67853179b727d394508ef98b08",
    "archive_bytes": 882738,
    "authors": [
      "Lars Berscheid and Ruckig contributors"
    ]
  },
  "license": {
    "spdx": "MIT",
    "url": "https://github.com/pantor/ruckig/blob/a8db97a4e9c55e5160a3855f739fa3b270df8e4c/LICENSE",
    "verified": true,
    "scope": "Selected Ruckig Community example source code only; preserve the upstream MIT copyright and permission notice. This selection excludes cloud-dependent intermediate-waypoint examples and Ruckig Pro-only tracking/speed features. Third-party dependencies and separately licensed products retain their own terms."
  },
  "compatibility": [
    {
      "runtime": "ruckig",
      "runtime_version": "0.19.4",
      "robot": "independent-axes",
      "controller": "json-contract-v1",
      "observation": "explicit-json-input",
      "os": "windows",
      "architecture": "x86_64",
      "python": "3.10",
      "status": "hub_verified"
    },
    {
      "runtime": "ruckig",
      "runtime_version": "0.19.4",
      "robot": "independent-axes",
      "controller": "json-contract-v1",
      "observation": "explicit-json-input",
      "os": "linux",
      "architecture": "x86_64",
      "python": "3.10",
      "status": "hub_verified"
    }
  ],
  "observation": {
    "required": [
      "explicit_json_task_input"
    ],
    "privileged_state": false,
    "description": "All inputs and outputs follow interface v1. Simulation adapters query exact synthetic simulator state; no perception or physical sensor compatibility."
  },
  "requirements": {
    "python": ">=3.10,<3.11",
    "packages": [
      "ruckig==0.19.4"
    ],
    "hardware": [
      "x86_64 CPU; no GPU or robot required"
    ],
    "rendering": "No display. Matplotlib Agg for numerical imports; PyBullet DIRECT for simulation.",
    "api_keys": [],
    "network": [
      "Pinned source archive once during preparation",
      "PyPI for declared dependency installation"
    ],
    "dependency_lock": "Runtime dependency versions are pinned for the supported Python 3.10 x86_64 CPU environments and checked against execution receipts. Platform-specific wheel hashes are not represented as a universal artifact lock; prepare captures pip freeze."
  },
  "invocation": {
    "entrypoint": "python run.py",
    "argv": [
      "{python}",
      "{recipe_dir}/run.py",
      "--source-dir",
      "{source_dir}",
      "--example"
    ],
    "inputs": {
      "current_position": [
        0,
        0,
        0.5
      ],
      "current_velocity": [
        0,
        0,
        0
      ],
      "current_acceleration": [
        0,
        0,
        0
      ],
      "target_position": [
        1,
        -0.5,
        0.25
      ],
      "target_velocity": [
        0,
        0,
        0
      ],
      "target_acceleration": [
        0,
        0,
        0
      ],
      "max_velocity": [
        1,
        1,
        1
      ],
      "max_acceleration": [
        2,
        2,
        2
      ],
      "max_jerk": [
        4,
        4,
        4
      ],
      "dt": 0.01,
      "coordinate_type": "revolute_rad"
    },
    "outputs": {
      "format": "single JSON object on stdout",
      "payload_selector": "outputs",
      "schema": {
        "type": "object",
        "required": [
          "time_s",
          "position",
          "velocity",
          "acceleration",
          "coordinate_type",
          "duration_s"
        ],
        "additionalProperties": false,
        "properties": {
          "time_s": {
            "type": "array",
            "minItems": 2,
            "maxItems": 3000,
            "items": {
              "type": "number",
              "minimum": 0,
              "maximum": 150
            },
            "x-unit": "s",
            "x-frame": "independent_axes_in_input_array_order",
            "description": "time_s; units=s; frame=independent_axes_in_input_array_order"
          },
          "position": {
            "type": "array",
            "minItems": 2,
            "maxItems": 3000,
            "items": {
              "type": "array",
              "minItems": 1,
              "maxItems": 8,
              "items": {
                "type": "number",
                "minimum": -10000,
                "maximum": 10000
              }
            },
            "x-unit": "coordinate_type:m_or_rad",
            "x-frame": "independent_axes_in_input_array_order",
            "description": "position; units=coordinate_type:m_or_rad; frame=independent_axes_in_input_array_order"
          },
          "velocity": {
            "type": "array",
            "minItems": 2,
            "maxItems": 3000,
            "items": {
              "type": "array",
              "minItems": 1,
              "maxItems": 8,
              "items": {
                "type": "number",
                "minimum": -1000,
                "maximum": 1000
              }
            },
            "x-unit": "coordinate_type:m/s_or_rad/s",
            "x-frame": "independent_axes_in_input_array_order",
            "description": "velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order"
          },
          "acceleration": {
            "type": "array",
            "minItems": 2,
            "maxItems": 3000,
            "items": {
              "type": "array",
              "minItems": 1,
              "maxItems": 8,
              "items": {
                "type": "number",
                "minimum": -1000,
                "maximum": 1000
              }
            },
            "x-unit": "coordinate_type:m/s^2_or_rad/s^2",
            "x-frame": "independent_axes_in_input_array_order",
            "description": "acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order"
          },
          "coordinate_type": {
            "type": "string",
            "enum": [
              "revolute_rad",
              "linear_m"
            ],
            "x-unit": "dimensionless",
            "x-frame": "independent_axes_in_input_array_order",
            "description": "coordinate_type; units=dimensionless; frame=independent_axes_in_input_array_order"
          },
          "duration_s": {
            "type": "number",
            "minimum": 0,
            "maximum": 150,
            "x-unit": "s",
            "x-frame": "independent_axes_in_input_array_order",
            "description": "duration_s; units=s; frame=independent_axes_in_input_array_order"
          }
        }
      }
    },
    "example": "After prepare, replace --example in next_command with --input /absolute/path/task.json; use --describe for the exact contract without execution."
  },
  "interface": {
    "version": "1",
    "kind": "trajectory_generator",
    "abstraction_level": 0,
    "execution_domain": "computation",
    "language": "python",
    "input_transport": "json_file_or_inline",
    "output_transport": "json_stdout",
    "conventions": {
      "linear_unit": "m",
      "angular_unit": "rad",
      "time_unit": "s",
      "coordinate_frame": "independent_axes_in_input_array_order",
      "joint_order": "input_array_order",
      "quaternion_order": "not_used"
    },
    "input_schema": {
      "type": "object",
      "required": [
        "current_position",
        "current_velocity",
        "current_acceleration",
        "target_position",
        "target_velocity",
        "target_acceleration",
        "max_velocity",
        "max_acceleration",
        "max_jerk",
        "dt",
        "coordinate_type"
      ],
      "additionalProperties": false,
      "properties": {
        "current_position": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m_or_rad",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "current_position; units=coordinate_type:m_or_rad; frame=independent_axes_in_input_array_order"
        },
        "current_velocity": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m/s_or_rad/s",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "current_velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order"
        },
        "current_acceleration": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m/s^2_or_rad/s^2",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "current_acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order"
        },
        "target_position": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m_or_rad",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "target_position; units=coordinate_type:m_or_rad; frame=independent_axes_in_input_array_order"
        },
        "target_velocity": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m/s_or_rad/s",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "target_velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order"
        },
        "target_acceleration": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m/s^2_or_rad/s^2",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "target_acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order"
        },
        "max_velocity": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m/s_or_rad/s",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "max_velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order"
        },
        "max_acceleration": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m/s^2_or_rad/s^2",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "max_acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order"
        },
        "max_jerk": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "number",
            "minimum": -10,
            "maximum": 10
          },
          "x-unit": "coordinate_type:m/s^3_or_rad/s^3",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "max_jerk; units=coordinate_type:m/s^3_or_rad/s^3; frame=independent_axes_in_input_array_order"
        },
        "dt": {
          "type": "number",
          "minimum": 0.01,
          "maximum": 0.05,
          "x-unit": "s",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "dt; units=s; frame=independent_axes_in_input_array_order"
        },
        "coordinate_type": {
          "type": "string",
          "enum": [
            "revolute_rad",
            "linear_m"
          ],
          "x-unit": "dimensionless",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "coordinate_type; units=dimensionless; frame=independent_axes_in_input_array_order"
        }
      }
    },
    "output_schema": {
      "type": "object",
      "required": [
        "time_s",
        "position",
        "velocity",
        "acceleration",
        "coordinate_type",
        "duration_s"
      ],
      "additionalProperties": false,
      "properties": {
        "time_s": {
          "type": "array",
          "minItems": 2,
          "maxItems": 3000,
          "items": {
            "type": "number",
            "minimum": 0,
            "maximum": 150
          },
          "x-unit": "s",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "time_s; units=s; frame=independent_axes_in_input_array_order"
        },
        "position": {
          "type": "array",
          "minItems": 2,
          "maxItems": 3000,
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 8,
            "items": {
              "type": "number",
              "minimum": -10000,
              "maximum": 10000
            }
          },
          "x-unit": "coordinate_type:m_or_rad",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "position; units=coordinate_type:m_or_rad; frame=independent_axes_in_input_array_order"
        },
        "velocity": {
          "type": "array",
          "minItems": 2,
          "maxItems": 3000,
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 8,
            "items": {
              "type": "number",
              "minimum": -1000,
              "maximum": 1000
            }
          },
          "x-unit": "coordinate_type:m/s_or_rad/s",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order"
        },
        "acceleration": {
          "type": "array",
          "minItems": 2,
          "maxItems": 3000,
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 8,
            "items": {
              "type": "number",
              "minimum": -1000,
              "maximum": 1000
            }
          },
          "x-unit": "coordinate_type:m/s^2_or_rad/s^2",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order"
        },
        "coordinate_type": {
          "type": "string",
          "enum": [
            "revolute_rad",
            "linear_m"
          ],
          "x-unit": "dimensionless",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "coordinate_type; units=dimensionless; frame=independent_axes_in_input_array_order"
        },
        "duration_s": {
          "type": "number",
          "minimum": 0,
          "maximum": 150,
          "x-unit": "s",
          "x-frame": "independent_axes_in_input_array_order",
          "description": "duration_s; units=s; frame=independent_axes_in_input_array_order"
        }
      }
    },
    "preconditions": [
      "Ruckig Community 0.19.4; no cloud client, IK, collision or physical control.",
      "All axes share coordinate_type; m or rad and corresponding derivatives per second.",
      "Velocity/stop modes do not guarantee target position. Maximum 3000 online cycles or 30 s offline trajectory."
    ],
    "postconditions": [
      "All declared checks must pass and all outputs must be finite.",
      "Success applies only to this operation and model, not higher-level task completion."
    ],
    "failure_codes": [
      "invalid_input_or_environment",
      "execution_failed",
      "task_failed"
    ],
    "composition": {
      "depends_on": [],
      "automatic_frame_conversion": false,
      "automatic_hardware_execution": false
    },
    "output_selector": "outputs",
    "origin_reference_ids": [
      "ruckig-examples-02-position-offline-py"
    ],
    "origin_relationship": "adapted_from; inspect declared model and inputs, not original robot compatibility"
  },
  "completion": {
    "success_condition": "Exit 0, status=task_complete, success=true, finite outputs satisfying interface.output_schema and all declared numerical/model checks. This is not a physical robot or general task-success claim.",
    "timeout_seconds": 30,
    "failure_modes": [
      "Invalid or oversized JSON",
      "Source checksum mismatch",
      "Unavailable pinned dependency",
      "No valid path or postcondition failure",
      "Execution exceeding the declared bounded algorithm budget"
    ],
    "stop_condition": "Caller must terminate the separate adapter process after 30 seconds; adapters bound iterations/scene steps and close simulation clients."
  },
  "preparation": {
    "recipe_path": "recipes/ruckig-offline-trajectory",
    "requirements_file": "recipes/ruckig-offline-trajectory/requirements.txt",
    "source_selection": "declared_paths",
    "install_argv": [
      "{python}",
      "-m",
      "pip",
      "install",
      "--only-binary=:all:",
      "-r",
      "{recipe_dir}/requirements.txt"
    ],
    "execution_separate": true,
    "files": {
      "run.py": "# Generated from tools/recipe_adapters and catalog/executable-conversions.json.\n# Hub adapter: MIT. Adapted upstream example retains its original license and authors.\n\"\"\"Source template for standalone, bounded JSON recipe adapters (MIT, Hub authors).\n\nThe generator embeds this template and a reviewed backend in each published\nrecipe. Importing this template does not import or execute upstream source.\n\"\"\"\nimport argparse\nimport contextlib\nimport hashlib\nimport importlib.util\nimport io\nimport json\nimport math\nimport os\nfrom pathlib import Path\nimport random\nimport sys\n\n\nclass ContractError(ValueError):\n    pass\n\n\ndef validate_data(value, schema, path='$'):\n    \"\"\"Supported, published JSON Schema subset; bool is never a number.\"\"\"\n    kind = schema.get('type')\n    checks = {'object': lambda: isinstance(value, dict), 'array': lambda: isinstance(value, list),\n              'number': lambda: type(value) in (int, float) and math.isfinite(value),\n              'integer': lambda: type(value) is int, 'string': lambda: isinstance(value, str),\n              'boolean': lambda: isinstance(value, bool), 'null': lambda: value is None}\n    if kind and (kind not in checks or not checks[kind]()):\n        raise ContractError(path + ': expected ' + str(kind))\n    if 'enum' in schema and value not in schema['enum']:\n        raise ContractError(path + ': unsupported value')\n    if type(value) in (int, float):\n        if not math.isfinite(value) or value < schema.get('minimum', value) or value > schema.get('maximum', value):\n            raise ContractError(path + ': outside numeric bounds')\n    if isinstance(value, dict):\n        if len(value) > 32: raise ContractError(path + ': too many keys')\n        for name in schema.get('required', []):\n            if name not in value: raise ContractError(path + '.' + name + ': required')\n        props = schema.get('properties', {})\n        for name, item in value.items():\n            if name not in props and schema.get('additionalProperties') is False:\n                raise ContractError(path + '.' + name + ': unknown field')\n            validate_data(item, props.get(name, {}), path + '.' + name)\n    elif isinstance(value, list):\n        if not schema.get('minItems', 0) <= len(value) <= schema.get('maxItems', 4096):\n            raise ContractError(path + ': invalid array length')\n        for i, item in enumerate(value): validate_data(item, schema.get('items', {}), path + '[' + str(i) + ']')\n    elif isinstance(value, str) and len(value) > schema.get('maxLength', 4096):\n        raise ContractError(path + ': string too long')\n\n\ndef verify_source(root, spec):\n    root = Path(root).resolve()\n    for name, expected in spec['source_hashes'].items():\n        target = root / name\n        if target.is_symlink() or not target.resolve().is_relative_to(root) or not target.is_file():\n            raise ContractError('Pinned source missing or outside source root: ' + name)\n        if hashlib.sha256(target.read_bytes()).hexdigest() != expected:\n            raise ContractError('Pinned source checksum changed: ' + name)\n    return root\n\n\ndef load_upstream(root, relative):\n    \"\"\"Only a generator-pinned path is accepted; never a path from task input.\"\"\"\n    target = root / relative\n    for directory in [root, root / 'PathPlanning', target.parent]:\n        sys.path.insert(0, str(directory))\n    module_spec = importlib.util.spec_from_file_location('rsh_upstream', target)\n    module = importlib.util.module_from_spec(module_spec)\n    module_spec.loader.exec_module(module)\n    if hasattr(module, 'show_animation'): module.show_animation = False\n    return module\n\n\ndef clean_json(value):\n    if hasattr(value, 'tolist'): return clean_json(value.tolist())\n    if isinstance(value, dict): return {k: clean_json(v) for k,v in value.items()}\n    if isinstance(value, (tuple, list)): return [clean_json(v) for v in value]\n    if hasattr(value, 'item'): return clean_json(value.item())\n    if isinstance(value, float) and not math.isfinite(value): raise ContractError('Non-finite output')\n    return value\n\n\ndef adapter_main(spec, backend):\n    parser = argparse.ArgumentParser(description=spec['name'])\n    parser.add_argument('--source-dir')\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument('--input', type=Path, help='UTF-8 JSON file; no code or paths inside task input')\n    group.add_argument('--input-json', help='Inline JSON task input')\n    group.add_argument('--example', action='store_true', help='Run the declared example input')\n    group.add_argument('--describe', action='store_true', help='Read the contract without importing upstream code')\n    args = parser.parse_args()\n    try:\n        if args.describe:\n            print(json.dumps({'skill_id': spec['id'], 'interface': spec['interface'], 'example_input': spec['example']}, allow_nan=False))\n            return 0\n        if args.input:\n            with args.input.open('rb') as stream: raw=stream.read(65537)\n        else: raw=args.input_json.encode() if args.input_json else None\n        if raw is not None and len(raw) > 65536: raise ContractError('Input exceeds 64 KiB')\n        data = json.loads(raw) if raw is not None else spec['example']\n        validate_data(data, spec['interface']['input_schema'])\n        if not args.source_dir: raise ContractError('--source-dir is required for execution')\n        root = verify_source(args.source_dir, spec)\n        os.environ['MPLBACKEND'] = 'Agg'\n        os.environ.setdefault('OMP_NUM_THREADS', '1')\n        random.seed(data.get('seed', 0))\n        # Upstream diagnostic prints do not contaminate the machine response.\n        with contextlib.redirect_stdout(sys.stderr):\n            outputs, checks = backend(root, data, spec)\n        outputs, checks = clean_json(outputs), clean_json(checks)\n        validate_data(outputs, spec['interface']['output_schema'])\n        if not checks or not all(type(v) is bool for v in checks.values()): raise ContractError('Invalid postcondition report')\n        ok = all(checks.values())\n        print(json.dumps({'schema_version':'1','skill_id':spec['id'],'status':'task_complete' if ok else 'task_failed',\n            'success':ok,'outputs':outputs,'checks':checks,'execution_domain':spec['interface']['execution_domain'],\n            'source_commit':spec['source_commit'],'interface_version':'1','hardware_execution':False}, allow_nan=False, separators=(',',':')))\n        return 0 if ok else 1\n    except (ContractError, ValueError, OSError, ImportError) as error:\n        print(json.dumps({'schema_version':'1','skill_id':spec['id'],'status':'failed','success':False,\n            'reason_code':'invalid_input_or_environment','message':str(error),'hardware_execution':False}, allow_nan=False))\n        return 2\n    except Exception as error:\n        print(json.dumps({'schema_version':'1','skill_id':spec['id'],'status':'failed','success':False,\n            'reason_code':'execution_failed','message':str(error)[:1000],'hardware_execution':False}, allow_nan=False))\n        return 1\n\n\n\"\"\"Parameterized local-only Ruckig Community example adaptations (MIT).\"\"\"\n\n\ndef ruckig_backend(root, d, spec):\n    from importlib.metadata import version\n    if version('ruckig')!='0.19.4': raise ContractError('Requires the tested ruckig==0.19.4 binding')\n    from ruckig import InputParameter, OutputParameter, Result, Ruckig, Trajectory, ControlInterface, Synchronization\n    n=len(d['current_position'])\n    fields=['current_position','current_velocity','current_acceleration','target_position','target_velocity','target_acceleration','max_velocity','max_acceleration','max_jerk']\n    if any(len(d[key])!=n for key in fields): raise ContractError('All axis arrays must have the same length')\n    if any(v<=0 for key in ['max_velocity','max_acceleration','max_jerk'] for v in d[key]): raise ContractError('Kinematic limits must be positive')\n    if any(abs(v)>lim for key,limit in [('current_velocity','max_velocity'),('target_velocity','max_velocity'),('current_acceleration','max_acceleration'),('target_acceleration','max_acceleration')] for v,lim in zip(d[key],d[limit])):\n        raise ContractError('Boundary state exceeds declared limits')\n    inp=InputParameter(n)\n    for key in fields: setattr(inp,key,d[key])\n    op=spec['operation']\n    if op=='velocity': inp.control_interface=ControlInterface.Velocity\n    if op=='minimum_duration': inp.minimum_duration=d['minimum_duration']\n    generator=Ruckig(n,d['dt'])\n    time_values=[]; positions=[]; velocities=[]; accelerations=[]\n    stopped=False\n    if op=='offline':\n        trajectory=Trajectory(n)\n        result=generator.calculate(inp,trajectory)\n        if result!=Result.Working or trajectory.duration>30: raise ContractError('Trajectory calculation failed or exceeded 30 s budget')\n        count=min(3000,max(2,int(math.ceil(trajectory.duration/d['dt']))+1))\n        for i in range(count):\n            t=trajectory.duration*i/(count-1)\n            p,v,a=trajectory.at_time(t)\n            time_values.append(t); positions.append(p); velocities.append(v); accelerations.append(a)\n    else:\n        out=OutputParameter(n)\n        for tick in range(3000):\n            result=generator.update(inp,out)\n            if result not in (Result.Working,Result.Finished): raise ContractError('Ruckig rejected the trajectory')\n            time_values.append((tick+1)*d['dt']); positions.append(list(out.new_position)); velocities.append(list(out.new_velocity)); accelerations.append(list(out.new_acceleration))\n            out.pass_to_input(inp)\n            if op=='stop' and not stopped and (tick+1)*d['dt']>=d['stop_time']:\n                inp.control_interface=ControlInterface.Velocity; inp.synchronization=Synchronization.No\n                inp.target_velocity=[0.]*n; inp.target_acceleration=[0.]*n; stopped=True\n                result=Result.Working\n            if result==Result.Finished: break\n        else: raise ContractError('Trajectory exceeded 3000-cycle budget')\n    target_velocity=[0.]*n if op=='stop' else d['target_velocity']\n    target_acceleration=[0.]*n if op=='stop' else d['target_acceleration']\n    checks={'terminal_velocity':max(abs(a-b) for a,b in zip(velocities[-1],target_velocity))<1e-7,\n            'terminal_acceleration':max(abs(a-b) for a,b in zip(accelerations[-1],target_acceleration))<1e-7,\n            'acceleration_bounds':all(abs(a)<=lim+1e-7 for sample in accelerations for a,lim in zip(sample,d['max_acceleration'])),\n            'sampled_jerk_bounds':all(abs(a-b)/(t2-t1)<=lim+1e-5 for before,after,t1,t2 in zip(accelerations,accelerations[1:],time_values,time_values[1:]) for a,b,lim in zip(before,after,d['max_jerk']))}\n    if op not in ['velocity','stop']:\n        # Online mode reports the first control sample at/after completion. With\n        # nonzero target velocity compare its analytic continuation, not zero drift.\n        duration=out.trajectory.duration if op!='offline' else trajectory.duration\n        extra=max(0.,time_values[-1]-duration)\n        expected=[p+v*extra+.5*a*extra*extra for p,v,a in zip(d['target_position'],d['target_velocity'],d['target_acceleration'])]\n        checks['terminal_position']=max(abs(a-b) for a,b in zip(positions[-1],expected))<1e-6\n        checks['velocity_bounds']=all(abs(v)<=lim+1e-7 for sample in velocities for v,lim in zip(sample,d['max_velocity']))\n    if op=='minimum_duration': checks['minimum_duration']=time_values[-1]+1e-8>=d['minimum_duration']\n    if op=='stop': checks['stop_triggered']=stopped\n    return {'time_s':time_values,'position':positions,'velocity':velocities,'acceleration':accelerations,\n            'coordinate_type':d['coordinate_type'],'duration_s':time_values[-1]},checks\n\nSPEC = json.loads('{\"id\":\"ruckig-offline-trajectory\",\"name\":\"Offline position jerk-limited trajectory\",\"operation\":\"offline\",\"source_path\":\"examples/02_position_offline.py\",\"source_commit\":\"a8db97a4e9c55e5160a3855f739fa3b270df8e4c\",\"source_hashes\":{\"LICENSE\":\"f0880ac5e5026c92e12c9e2859a7b338c593aaca1a435f29498bd96cbb64d7d3\",\"examples/02_position_offline.py\":\"448af28371b3fe96beae7905c567909d30087d9fc2a6dfc58d64ef880de9d3b8\"},\"interface\":{\"version\":\"1\",\"kind\":\"trajectory_generator\",\"abstraction_level\":0,\"execution_domain\":\"computation\",\"language\":\"python\",\"input_transport\":\"json_file_or_inline\",\"output_transport\":\"json_stdout\",\"conventions\":{\"linear_unit\":\"m\",\"angular_unit\":\"rad\",\"time_unit\":\"s\",\"coordinate_frame\":\"independent_axes_in_input_array_order\",\"joint_order\":\"input_array_order\",\"quaternion_order\":\"not_used\"},\"input_schema\":{\"type\":\"object\",\"required\":[\"current_position\",\"current_velocity\",\"current_acceleration\",\"target_position\",\"target_velocity\",\"target_acceleration\",\"max_velocity\",\"max_acceleration\",\"max_jerk\",\"dt\",\"coordinate_type\"],\"additionalProperties\":false,\"properties\":{\"current_position\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m_or_rad\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"current_position; units=coordinate_type:m_or_rad; frame=independent_axes_in_input_array_order\"},\"current_velocity\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m/s_or_rad/s\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"current_velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order\"},\"current_acceleration\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m/s^2_or_rad/s^2\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"current_acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order\"},\"target_position\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m_or_rad\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"target_position; units=coordinate_type:m_or_rad; frame=independent_axes_in_input_array_order\"},\"target_velocity\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m/s_or_rad/s\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"target_velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order\"},\"target_acceleration\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m/s^2_or_rad/s^2\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"target_acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order\"},\"max_velocity\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m/s_or_rad/s\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"max_velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order\"},\"max_acceleration\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m/s^2_or_rad/s^2\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"max_acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order\"},\"max_jerk\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10,\"maximum\":10},\"x-unit\":\"coordinate_type:m/s^3_or_rad/s^3\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"max_jerk; units=coordinate_type:m/s^3_or_rad/s^3; frame=independent_axes_in_input_array_order\"},\"dt\":{\"type\":\"number\",\"minimum\":0.01,\"maximum\":0.05,\"x-unit\":\"s\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"dt; units=s; frame=independent_axes_in_input_array_order\"},\"coordinate_type\":{\"type\":\"string\",\"enum\":[\"revolute_rad\",\"linear_m\"],\"x-unit\":\"dimensionless\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"coordinate_type; units=dimensionless; frame=independent_axes_in_input_array_order\"}}},\"output_schema\":{\"type\":\"object\",\"required\":[\"time_s\",\"position\",\"velocity\",\"acceleration\",\"coordinate_type\",\"duration_s\"],\"additionalProperties\":false,\"properties\":{\"time_s\":{\"type\":\"array\",\"minItems\":2,\"maxItems\":3000,\"items\":{\"type\":\"number\",\"minimum\":0,\"maximum\":150},\"x-unit\":\"s\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"time_s; units=s; frame=independent_axes_in_input_array_order\"},\"position\":{\"type\":\"array\",\"minItems\":2,\"maxItems\":3000,\"items\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-10000,\"maximum\":10000}},\"x-unit\":\"coordinate_type:m_or_rad\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"position; units=coordinate_type:m_or_rad; frame=independent_axes_in_input_array_order\"},\"velocity\":{\"type\":\"array\",\"minItems\":2,\"maxItems\":3000,\"items\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-1000,\"maximum\":1000}},\"x-unit\":\"coordinate_type:m/s_or_rad/s\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"velocity; units=coordinate_type:m/s_or_rad/s; frame=independent_axes_in_input_array_order\"},\"acceleration\":{\"type\":\"array\",\"minItems\":2,\"maxItems\":3000,\"items\":{\"type\":\"array\",\"minItems\":1,\"maxItems\":8,\"items\":{\"type\":\"number\",\"minimum\":-1000,\"maximum\":1000}},\"x-unit\":\"coordinate_type:m/s^2_or_rad/s^2\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"acceleration; units=coordinate_type:m/s^2_or_rad/s^2; frame=independent_axes_in_input_array_order\"},\"coordinate_type\":{\"type\":\"string\",\"enum\":[\"revolute_rad\",\"linear_m\"],\"x-unit\":\"dimensionless\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"coordinate_type; units=dimensionless; frame=independent_axes_in_input_array_order\"},\"duration_s\":{\"type\":\"number\",\"minimum\":0,\"maximum\":150,\"x-unit\":\"s\",\"x-frame\":\"independent_axes_in_input_array_order\",\"description\":\"duration_s; units=s; frame=independent_axes_in_input_array_order\"}}},\"preconditions\":[\"Ruckig Community 0.19.4; no cloud client, IK, collision or physical control.\",\"All axes share coordinate_type; m or rad and corresponding derivatives per second.\",\"Velocity/stop modes do not guarantee target position. Maximum 3000 online cycles or 30 s offline trajectory.\"],\"postconditions\":[\"All declared checks must pass and all outputs must be finite.\",\"Success applies only to this operation and model, not higher-level task completion.\"],\"failure_codes\":[\"invalid_input_or_environment\",\"execution_failed\",\"task_failed\"],\"composition\":{\"depends_on\":[],\"automatic_frame_conversion\":false,\"automatic_hardware_execution\":false},\"output_selector\":\"outputs\"},\"example\":{\"current_position\":[0,0,0.5],\"current_velocity\":[0,0,0],\"current_acceleration\":[0,0,0],\"target_position\":[1,-0.5,0.25],\"target_velocity\":[0,0,0],\"target_acceleration\":[0,0,0],\"max_velocity\":[1,1,1],\"max_acceleration\":[2,2,2],\"max_jerk\":[4,4,4],\"dt\":0.01,\"coordinate_type\":\"revolute_rad\"}}')\n\nif __name__ == \"__main__\":\n    raise SystemExit(adapter_main(SPEC, ruckig_backend))\n",
      "requirements.txt": "ruckig==0.19.4\n"
    }
  },
  "evidence": {
    "level": "task_complete",
    "verified_by": "Hub maintainer runtime harness",
    "date": "2026-10-19",
    "environment": {
      "scope": "computation",
      "platforms": [
        "linux",
        "windows"
      ],
      "physical_robot": false
    },
    "commands": [
      "python tools/verify_executable_recipes.py --source-cache SOURCE_CACHE --output OUTPUT --backend ruckig"
    ],
    "result": "Three frozen positive cases passed against this exact adapter; see per-case receipts. This does not estimate general accuracy.",
    "artifacts": [
      "https://raw.githubusercontent.com/Superfast-Robotics/robot-skill-hub/39b06d7a6016edcea27e348e49ffd86f29ec1811/evidence/runtime/executable-conversions-v1/ruckig-offline-trajectory.json"
    ],
    "runtime_verification": "task_complete",
    "contributor_reported": null,
    "hub_verification": {
      "runtime": "task_complete",
      "scope": "computation",
      "case_count": 3,
      "source_unchanged": true
    }
  },
  "maintenance": {
    "record_version": "1.0.0",
    "last_checked": "2026-10-19",
    "upstream_status": "immutable_source_and_explicit_dependency_versions"
  },
  "contribution": {
    "allowed_paths": [
      "catalog/records/ruckig-offline-trajectory.json",
      "docs/recipes/ruckig-offline-trajectory.md",
      "recipes/ruckig-offline-trajectory/run.py",
      "recipes/ruckig-offline-trajectory/requirements.txt"
    ],
    "instructions": "Preserve upstream origin/license and interface semantics. Edit the finite manifest/templates and regenerate; record new exact-byte evidence for behavior changes."
  }
}
