generate_motion_graph
Compute velocity and acceleration from position data over time, extracting X, Y, Z, or magnitude component for motion graph generation.
Instructions
Generate motion graph data (position, velocity, acceleration vs time).
Calculates velocity and acceleration from position data and extracts
the specified component for graphing.
Args:
times: Time values in seconds (or JSON string)
positions: Position vectors [[x,y,z], ...] in meters (or JSON string)
component: Which component to analyze - "x", "y", "z", or "magnitude" (default)
Returns:
Dict containing:
- times: Time values
- positions: Position values (selected component)
- velocities: Velocity values (selected component)
- accelerations: Acceleration values (selected component)
- max_velocity: Maximum velocity magnitude
- max_acceleration: Maximum acceleration magnitude
- component: Which component was analyzed
Example:
result = await generate_motion_graph(
times=[0, 1, 2, 3],
positions=[[0,0,0], [5,0,0], [20,0,0], [45,0,0]],
component="x"
)
# Automatically calculates v and aInput Schema
| Name | Required | Description | Default |
|---|---|---|---|
| times | Yes | ||
| positions | Yes | ||
| component | No | magnitude |
Implementation Reference
- MCP tool handler that parses inputs, creates a MotionGraphRequest, delegates to the core generate_motion_graph function, and returns the response dict.
async def generate_motion_graph( times: Union[list[float], str], positions: Union[list[list[float]], str], component: str = "magnitude", ) -> dict: """Generate motion graph data (position, velocity, acceleration vs time). Calculates velocity and acceleration from position data and extracts the specified component for graphing. Args: times: Time values in seconds (or JSON string) positions: Position vectors [[x,y,z], ...] in meters (or JSON string) component: Which component to analyze - "x", "y", "z", or "magnitude" (default) Returns: Dict containing: - times: Time values - positions: Position values (selected component) - velocities: Velocity values (selected component) - accelerations: Acceleration values (selected component) - max_velocity: Maximum velocity magnitude - max_acceleration: Maximum acceleration magnitude - component: Which component was analyzed Example: result = await generate_motion_graph( times=[0, 1, 2, 3], positions=[[0,0,0], [5,0,0], [20,0,0], [45,0,0]], component="x" ) # Automatically calculates v and a """ from ..kinematics import MotionGraphRequest, generate_motion_graph as gen_graph # Parse inputs parsed_times = json.loads(times) if isinstance(times, str) else times parsed_positions = json.loads(positions) if isinstance(positions, str) else positions request = MotionGraphRequest( times=parsed_times, positions=parsed_positions, component=component, # type: ignore ) response = gen_graph(request) return response.model_dump() - Core implementation: validates input lengths, computes numerical derivatives for velocity and acceleration, extracts requested component (x/y/z/magnitude), and returns MotionGraphResponse.
def generate_motion_graph(request: MotionGraphRequest) -> MotionGraphResponse: """Generate motion graph data (position, velocity, acceleration vs time). Args: request: Motion graph generation request Returns: Graph data for specified component """ if len(request.positions) != len(request.times): raise ValueError("Number of positions must equal number of times") # Get component index component_map = {"x": 0, "y": 1, "z": 2} # Calculate derivatives velocities_vec = _numerical_derivative(request.positions, request.times) accelerations_vec = _numerical_derivative(velocities_vec, request.times) if request.component == "magnitude": positions = [_vector_magnitude(p) for p in request.positions] velocities = [_vector_magnitude(v) for v in velocities_vec] accelerations = [_vector_magnitude(a) for a in accelerations_vec] else: idx = component_map[request.component] positions = [p[idx] for p in request.positions] velocities = [v[idx] for v in velocities_vec] accelerations = [a[idx] for a in accelerations_vec] return MotionGraphResponse( times=request.times, positions=positions, velocities=velocities, accelerations=accelerations, component=request.component, ) - Input schema for generate_motion_graph: requires positions, times, and optional component (default: 'magnitude').
class MotionGraphRequest(BaseModel): """Request for motion graph data generation.""" positions: list[list[float]] = Field(..., description="Position data [x, y, z] in meters") times: list[float] = Field(..., description="Time values in seconds") component: Literal["x", "y", "z", "magnitude"] = Field( default="magnitude", description="Which component to analyze" ) - Output schema with times, positions, velocities, accelerations, and analyzed component.
class MotionGraphResponse(BaseModel): """Response for motion graph data.""" times: list[float] = Field(..., description="Time values in seconds") positions: list[float] = Field(..., description="Position values in meters") velocities: list[float] = Field(..., description="Velocity values in m/s") accelerations: list[float] = Field(..., description="Acceleration values in m/s²") component: str = Field(..., description="Component analyzed") - Helper that computes numerical derivatives using forward/backward/central differences, used by generate_motion_graph for velocity and acceleration.
def _numerical_derivative(values: list[list[float]], times: list[float]) -> list[list[float]]: """Calculate numerical derivative using central differences.""" if len(values) < 2: return [[0.0] * len(values[0])] derivatives = [] for i in range(len(values)): if i == 0: # Forward difference for first point dt = times[1] - times[0] deriv = [(values[1][j] - values[0][j]) / dt for j in range(len(values[0]))] elif i == len(values) - 1: # Backward difference for last point dt = times[-1] - times[-2] deriv = [(values[-1][j] - values[-2][j]) / dt for j in range(len(values[0]))] else: # Central difference for interior points dt = times[i + 1] - times[i - 1] deriv = [(values[i + 1][j] - values[i - 1][j]) / dt for j in range(len(values[0]))] derivatives.append(deriv) return derivatives