{
  "openapi": "3.1.1",
  "info": {
    "title": "Kinetica Trajectory Planner API",
    "version": "1.0.0",
    "summary": "Waypoints (PTP, LIN, CIRC) + limits → timed joint samples, cycle time and peak velocities.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://kineticatrajectoryplanner.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Waypoints (PTP, LIN, CIRC) + limits → timed joint samples, cycle time and peak velocities.",
        "description": "Plans a robot motion program from waypoints: synchronous joint moves (PTP), straight TCP lines (LIN) and circular arcs (CIRC) with trapezoidal, quintic or jerk-limited S-curve profiles that respect the joint velocity and acceleration limits, blend radii and dwell times. Returns the cycle time, per-segment timing, peak joint velocities and accelerations, a sampled joint/TCP trajectory and a CSV.\n\nMethodology:\n- PTP: synchronous joint interpolation q(s) = q₀ + s·Δq with one profile on s ∈ [0, 1]; the limits on s are min over joints of vmaxᵢ/|Δqᵢ| (and the same for acceleration and jerk), so every joint starts and stops together and none exceeds its limits.\n- Trapezoid: if h ≥ v²/a then Ta = v/a and T = h/v + v/a, else triangular with Ta = √(h/a), T = 2√(h/a). Quintic: s = 10τ³ − 15τ⁴ + 6τ⁵ with T = max(1.875·h/v, √(5.7735·h/a)). S-curve: double-S with jerk limit (Biagiotti & Melchiorri §3.4).\n- LIN/CIRC: the TCP follows the line or the circle through start, via and end point, orientation by quaternion slerp; IK runs per sample seeded from the previous one. If a joint would exceed its velocity/acceleration limit the segment is slowed down uniformly and re-planned (reported as speed scale).\n- Blending: consecutive moves overlap by the time the TCP spends inside the blend radius (capped at half of each move) and are superposed in joint space, which rounds the corner without stopping.\n- Velocities/accelerations in the output are central differences of the sampled trajectory; the cycle time includes dwell times.\n\nKinematic simulation for planning and teaching. It is not a certified safety function: verify every program on the real controller with reduced speed and the cell safety system active. Real controllers add their own look-ahead, dynamics limits and servo lag, so measured cycle times differ.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "kinetica_trajectory_planner",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KineticaTrajectoryPlannerInput"
              },
              "examples": {
                "example1": {
                  "summary": "6-axis arm: two PTP moves and a LIN line",
                  "value": {
                    "robot": "kx6-1400",
                    "profile": "trapezoid",
                    "waypoints": [
                      {
                        "name": "Home",
                        "type": "PTP",
                        "target": "j: 0, 0, 0, 0, 90, 0"
                      },
                      {
                        "name": "Above",
                        "type": "PTP",
                        "target": "p: 800, -200, 700, 180, 0, 0",
                        "vel": 80,
                        "acc": 80,
                        "blend": 30
                      },
                      {
                        "name": "Line",
                        "type": "LIN",
                        "target": "p: 800, 200, 700, 180, 0, 0",
                        "vel": 250,
                        "acc": 1500
                      },
                      {
                        "name": "Home",
                        "type": "PTP",
                        "target": "j: 0, 0, 0, 0, 90, 0",
                        "vel": 100,
                        "acc": 100
                      }
                    ]
                  }
                },
                "example2": {
                  "summary": "Single joint, trapezoid timing check (90° at 156°/s, 400°/s²)",
                  "value": {
                    "robot": "kx6-1400",
                    "profile": "trapezoid",
                    "waypoints": [
                      {
                        "name": "A",
                        "type": "PTP",
                        "target": "j: 0, 0, 0, 0, 90, 0"
                      },
                      {
                        "name": "B",
                        "type": "PTP",
                        "target": "j: 90, 0, 0, 0, 90, 0",
                        "vel": 100,
                        "acc": 100
                      }
                    ]
                  }
                },
                "example3": {
                  "summary": "SCARA pick with S-curve profile and CIRC",
                  "value": {
                    "robot": "scara-550",
                    "profile": "scurve",
                    "waypoints": [
                      {
                        "name": "Start",
                        "type": "PTP",
                        "target": "j: -30, 60, 50, 0"
                      },
                      {
                        "name": "P1",
                        "type": "LIN",
                        "target": "p: 350, -200, 250, 180, 0, 0",
                        "vel": 500,
                        "acc": 4000
                      },
                      {
                        "name": "Arc",
                        "type": "CIRC",
                        "target": "p: 350, 200, 250, 180, 0, 0",
                        "via": "450, 0, 250",
                        "vel": 500,
                        "acc": 4000
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KineticaTrajectoryPlannerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "KineticaTrajectoryPlannerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "robot": {
            "title": "Robot",
            "description": "A library robot, or choose a custom DH table, URDF or Kinetica robot JSON.",
            "type": "string",
            "enum": [
              "kx6-1400",
              "ur5-like",
              "puma560",
              "scara-550",
              "gantry-xyz",
              "planar2",
              "custom-dh",
              "urdf",
              "json"
            ],
            "default": "kx6-1400"
          },
          "convention": {
            "title": "DH convention (custom table)",
            "type": "string",
            "enum": [
              "dh",
              "mdh"
            ],
            "default": "dh"
          },
          "dh": {
            "title": "DH table (custom)",
            "description": "One row per joint. Lengths in mm, angles in degrees. For revolute joints θ is the zero offset, for prismatic joints d is.",
            "type": "array",
            "maxItems": 12,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "type": {
                  "title": "Type",
                  "type": "string",
                  "enum": [
                    "revolute",
                    "prismatic"
                  ],
                  "default": "revolute"
                },
                "a": {
                  "title": "a (mm)",
                  "type": "number",
                  "default": 0
                },
                "alpha": {
                  "title": "α (deg)",
                  "type": "number",
                  "default": 0
                },
                "d": {
                  "title": "d (mm)",
                  "type": "number",
                  "default": 0
                },
                "theta": {
                  "title": "θ (deg)",
                  "type": "number",
                  "default": 0
                },
                "min": {
                  "title": "min",
                  "type": "number"
                },
                "max": {
                  "title": "max",
                  "type": "number"
                },
                "vmax": {
                  "title": "v max (/s)",
                  "type": "number"
                },
                "amax": {
                  "title": "a max (/s²)",
                  "type": "number"
                }
              },
              "required": []
            }
          },
          "robotText": {
            "title": "URDF or robot JSON",
            "description": "Used when Robot is “URDF” or “Kinetica robot JSON”. URDF subset: links with box/cylinder/sphere, revolute/continuous/prismatic/fixed joints.",
            "type": "string",
            "maxLength": 400000
          },
          "tool": {
            "title": "Tool offset (TCP)",
            "description": "x, y, z (mm), roll, pitch, yaw (deg) in the flange frame, e.g. “0, 0, 150, 0, 0, 0”. Empty = robot default.",
            "type": "string",
            "default": ""
          },
          "waypoints": {
            "title": "Waypoints",
            "description": "Row 1 is the start. Target “j: 0, -90, 90, 0, 0, 0” (joints) or “p: x, y, z, roll, pitch, yaw” (TCP pose, mm/deg). PTP speed/accel in % of the joint limits; LIN/CIRC in mm/s and mm/s². CIRC needs a via point “x, y, z”.",
            "type": "array",
            "maxItems": 60,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "name": {
                  "title": "Name",
                  "type": "string",
                  "maxLength": 40
                },
                "type": {
                  "title": "Move",
                  "type": "string",
                  "enum": [
                    "PTP",
                    "LIN",
                    "CIRC"
                  ],
                  "default": "PTP"
                },
                "target": {
                  "title": "Target",
                  "type": "string",
                  "maxLength": 200
                },
                "via": {
                  "title": "Via (CIRC)",
                  "type": "string",
                  "maxLength": 100
                },
                "vel": {
                  "title": "Speed",
                  "type": "number",
                  "minimum": 0.01
                },
                "acc": {
                  "title": "Accel",
                  "type": "number",
                  "minimum": 0.01
                },
                "blend": {
                  "title": "Blend (mm)",
                  "type": "number",
                  "minimum": 0,
                  "default": 0
                },
                "dwell": {
                  "title": "Dwell (s)",
                  "type": "number",
                  "minimum": 0,
                  "default": 0
                }
              },
              "required": [
                "target"
              ]
            }
          },
          "projectJson": {
            "title": "Kinetica project JSON (optional)",
            "description": "A complete .kinetica.json project; when given, its robot, work objects and program are used instead of the fields above.",
            "type": "string",
            "maxLength": 1000000
          },
          "profile": {
            "title": "Velocity profile",
            "type": "string",
            "enum": [
              "trapezoid",
              "quintic",
              "scurve"
            ],
            "default": "trapezoid"
          },
          "override": {
            "title": "Speed override",
            "type": "number",
            "minimum": 1,
            "maximum": 100,
            "default": 100,
            "x-unit": "%"
          },
          "outputDt": {
            "title": "Output sample period",
            "type": "number",
            "minimum": 0.005,
            "maximum": 1,
            "default": 0.05,
            "x-unit": "s"
          }
        },
        "required": []
      },
      "KineticaTrajectoryPlannerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "required": [
              "ok",
              "cycleTime",
              "segments",
              "peaks",
              "samples",
              "joints"
            ],
            "properties": {
              "ok": {
                "type": "boolean"
              },
              "cycleTime": {
                "type": "number"
              },
              "pathLength": {
                "type": "number"
              },
              "joints": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "segments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    },
                    "start": {
                      "type": "number"
                    },
                    "duration": {
                      "type": "number"
                    },
                    "blendOverlap": {
                      "type": "number"
                    },
                    "dwell": {
                      "type": "number"
                    },
                    "speedScale": {
                      "type": "number"
                    }
                  }
                }
              },
              "peaks": {
                "type": "object",
                "properties": {
                  "jointVel": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    }
                  },
                  "jointAcc": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    }
                  },
                  "jointVelPercent": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    }
                  },
                  "tcpSpeed": {
                    "type": "number"
                  }
                }
              },
              "samples": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "t": {
                      "type": "number"
                    },
                    "joints": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      }
                    },
                    "tcp": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      }
                    }
                  }
                }
              },
              "errors": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}