maptor#

The primary MAPTOR interface with all public exports.

MAPTOR: Multiphase Adaptive Trajectory Optimizer

A Python framework for trajectory optimization using optimal control. MAPTOR solves problems involving the motion of vehicles, robots, spacecraft, and other dynamic systems through space and time using the Legendre-Gauss-Radau pseudospectral method and phs-adaptive mesh refinement.

Key Features:
  • Intuitive problem definition API

  • Adaptive mesh refinement for high-precision solutions

  • Multiphase trajectory support with automatic phase linking

  • Built-in plotting and solution analysis tools

  • Full type safety with comprehensive type hints

Quick Start:
>>> import maptor as mtor
>>> problem = mtor.Problem("Minimum Time Problem")
>>> phase = problem.set_phase(1)
>>> t = phase.time(initial=0.0)
>>> x = phase.state("position", initial=0.0, final=1.0)
>>> u = phase.control("force", boundary=(-1.0, 1.0))
>>> phase.dynamics({x: u})
>>> problem.minimize(t.final)
>>> phase.mesh([8], [-1.0, 1.0])
>>> solution = mtor.solve_adaptive(problem)
>>> if solution.status["success"]:
...     solution.plot()
Documentation:

https://maptor.github.io/maptor/

Repository:

maptor/maptor

Logging:

import logging logging.getLogger(‘maptor’).setLevel(logging.INFO) # Major operations logging.getLogger(‘maptor’).setLevel(logging.DEBUG) # Detailed debugging

exception maptor.ConfigurationError(message, context=None)[source]#

Bases: MAPTORBaseError

Raised when there is an invalid or incomplete MAPTOR configuration.

This exception indicates that the user has provided invalid parameters, missing required configuration, or conflicting settings that prevent the problem from being solved.

Examples:
  • Invalid polynomial degrees

  • Missing dynamics or objective function

  • Incompatible constraint specifications

  • Invalid mesh configuration

Parameters:
  • message (str)

  • context (str | None)

Return type:

None

exception maptor.DataIntegrityError(message, context=None)[source]#

Bases: MAPTORBaseError

Raised when internal data corruption or inconsistency is detected.

This exception indicates an internal MAPTOR error where data structures have become corrupted or inconsistent. This typically represents a bug in MAPTOR rather than user error.

Examples:
  • NaN or infinite values in computed results

  • Mismatched array dimensions in internal calculations

  • Corrupted solution data structures

Parameters:
  • message (str)

  • context (str | None)

Return type:

None

exception maptor.InterpolationError(message, context=None)[source]#

Bases: MAPTORBaseError

Raised when adaptive mesh interpolation operations fail.

This exception occurs during adaptive mesh refinement when MAPTOR cannot successfully interpolate solution data between different mesh configurations, typically due to numerical issues or corrupted trajectory data.

Parameters:
  • message (str)

  • context (str | None)

Return type:

None

exception maptor.MAPTORBaseError(message, context=None)[source]#

Bases: Exception

Base class for all MAPTOR-specific errors.

All MAPTOR exceptions inherit from this class, allowing users to catch any MAPTOR-specific error with a single except clause.

Args:

message: The error message describing what went wrong context: Optional additional context about where the error occurred

Parameters:
  • message (str)

  • context (str | None)

Return type:

None

__init__(message, context=None)[source]#
Parameters:
  • message (str)

  • context (str | None)

Return type:

None

class maptor.Problem(name='Multiphase Problem')[source]#

Bases: object

Multiphase optimal control problem definition and configuration interface.

The Problem class is the main entry point for defining optimal control problems in MAPTOR. It supports both single-phase and multiphase trajectory optimization with automatic phase linking, static parameter optimization, and comprehensive constraint specification.

Key capabilities:

  • Multiphase trajectory definition with automatic continuity

  • Static parameter optimization (design variables)

  • Flexible objective functions (minimize/maximize any expression)

  • Initial guess specification for improved convergence

  • Solver configuration and validation

  • Cross-phase constraints and event handling

The Problem follows a builder pattern where you incrementally define phases, variables, dynamics, constraints, and objectives before solving.

Examples:

Single-phase minimum time problem:

>>> import maptor as mtor
>>>
>>> problem = mtor.Problem("Minimum Time")
>>> phase = problem.set_phase(1)
>>>
>>> # Variables and dynamics
>>> t = phase.time(initial=0.0)
>>> x = phase.state("position", initial=0, final=1)
>>> v = phase.state("velocity", initial=0)
>>> u = phase.control("force", boundary=(-1, 1))
>>>
>>> phase.dynamics({x: v, v: u})
>>> problem.minimize(t.final)
>>>
>>> # Solve
>>> phase.mesh([5, 5], [-1, 0, 1])
>>> solution = mtor.solve_fixed_mesh(problem)

Multiphase rocket trajectory:

>>> problem = mtor.Problem("Rocket Launch")
>>>
>>> # Boost phase
>>> boost = problem.set_phase(1)
>>> t1 = boost.time(initial=0, final=120)
>>> h1 = boost.state("altitude", initial=0)
>>> v1 = boost.state("velocity", initial=0)
>>> m1 = boost.state("mass", initial=1000)
>>> T1 = boost.control("thrust", boundary=(0, 2000))
>>>
>>> boost.dynamics({
...     h1: v1,
...     v1: T1/m1 - 9.81,
...     m1: -T1 * 0.001
... })
>>>
>>> # Coast phase with automatic continuity
>>> coast = problem.set_phase(2)
>>> t2 = coast.time(initial=t1.final, final=300)
>>> h2 = coast.state("altitude", initial=h1.final)
>>> v2 = coast.state("velocity", initial=v1.final)
>>> m2 = coast.state("mass", initial=m1.final)
>>>
>>> coast.dynamics({h2: v2, v2: -9.81, m2: 0})
>>>
>>> # Objective and solve
>>> problem.minimize(-h2.final)  # Maximize final altitude
>>> # ... mesh configuration and solve

Problem with static parameters:

>>> problem = mtor.Problem("Design Optimization")
>>>
>>> # Design parameters to optimize
>>> engine_mass = problem.parameter("engine_mass", boundary=(50, 200))
>>> thrust_level = problem.parameter("max_thrust", boundary=(1000, 5000))
>>>
>>> # Use parameters in dynamics
>>> total_mass = vehicle_mass + engine_mass
>>> phase.dynamics({v: thrust_level/total_mass - 9.81})
>>>
>>> # Multi-objective: maximize performance, minimize mass
>>> performance = altitude.final
>>> mass_penalty = engine_mass * 10
>>> problem.minimize(mass_penalty - performance)
Parameters:

name (str)

__init__(name='Multiphase Problem')[source]#

Initialize a new optimal control problem.

Args:

name: Descriptive name for the problem (used in logging and output)

Examples:
>>> problem = mtor.Problem("Spacecraft Trajectory")
>>> problem = mtor.Problem("Robot Path Planning")
>>> problem = mtor.Problem()  # Uses default name
Parameters:

name (str)

Return type:

None

set_phase(phase_id)[source]#

Create and configure a new phase in the multiphase problem.

Each phase represents a distinct segment of the trajectory with its own time domain, dynamics, and constraints. Phases can be linked through symbolic boundary constraints for trajectory continuity.

Return type:

Phase

Parameters:

phase_id (int)

Args:
phase_id: Unique integer identifier for this phase. Phases are solved

in order of their IDs, so use sequential numbering (1, 2, 3…).

Returns:

Phase: Phase object for defining variables, dynamics, and constraints

Raises:

ValueError: If phase_id already exists

Examples:

Single phase problem:

>>> problem = mtor.Problem("Single Phase")
>>> phase = problem.set_phase(1)
>>> # Define phase variables, dynamics, constraints...

Sequential multiphase problem:

>>> problem = mtor.Problem("Three Phase Mission")
>>>
>>> # Launch phase
>>> launch = problem.set_phase(1)
>>> # ... configure launch phase
>>>
>>> # Coast phase
>>> coast = problem.set_phase(2)
>>> # ... configure coast phase
>>>
>>> # Landing phase
>>> landing = problem.set_phase(3)
>>> # ... configure landing phase

Phase naming convention:

>>> # Use descriptive variable names for clarity
>>> ascent_phase = problem.set_phase(1)
>>> orbit_phase = problem.set_phase(2)
>>> descent_phase = problem.set_phase(3)
parameter(name, boundary=None)[source]#

Define a static parameter for design optimization with exhaustive constraint syntax.

Creates optimization variables that remain constant throughout the mission but can be varied to optimize performance. Supports all constraint types for comprehensive design space specification.

Return type:

MX

Parameters:
Args:

name: Unique parameter name boundary: Parameter constraint with full syntax:

  • float: Fixed parameter value (e.g., 1000.0)

  • (lower, upper): Bounded parameter range (e.g., (100, 500))

  • (None, upper): Upper bounded only (e.g., (None, 1000))

  • (lower, None): Lower bounded only (e.g., (0, None))

  • None: Unconstrained parameter

Returns:

ca.MX: Parameter variable for use across all phases

Examples:

Bounded parameter:

>>> mass = problem.parameter("mass", boundary=(100, 500))

Single-sided bounds:

>>> area = problem.parameter("area", boundary=(10, None))
>>> drag = problem.parameter("drag", boundary=(None, 0.5))

Fixed parameter:

>>> gravity = problem.parameter("gravity", boundary=9.81)

Unconstrained:

>>> free_param = problem.parameter("design_var")
parameter_guess(**parameter_guesses)[source]#

Set initial guesses for static parameters.

Return type:

None

Parameters:

parameter_guesses (float)

Args:

**parameter_guesses: Parameter names mapped to guess values

Examples:
>>> mass = problem.parameter("mass", boundary=(100, 500))
>>> drag = problem.parameter("drag", boundary=(0, 0.1))
>>> problem.parameter_guess(mass=300.0, drag=0.05)
minimize(objective_expr)[source]#

Set objective function with comprehensive expression support.

Defines scalar optimization objective supporting final states, integral terms, static parameters, and complex multi-phase expressions. Can combine multiple objective components with arbitrary mathematical relationships.

Return type:

None

Parameters:

objective_expr (MX | float | int)

Args:

objective_expr: Scalar expression to minimize. Supports:

  • Final state values (state.final)

  • Integral terms (from add_integral())

  • Static parameters (from parameter())

  • Time variables (time.final)

  • Complex mathematical combinations

Examples:

Minimum time:

>>> problem.minimize(t.final)

Final state:

>>> problem.minimize(-altitude.final)  # Maximize altitude

Integral cost:

>>> energy = phase.add_integral(thrust**2)
>>> problem.minimize(energy)

Multi-objective:

>>> fuel_cost = phase.add_integral(thrust * price)
>>> time_cost = t.final * rate
>>> problem.minimize(fuel_cost + time_cost)

Parameter optimization:

>>> mass = problem.parameter("mass")
>>> problem.minimize(mass - performance)
validate_multiphase_configuration()[source]#
Return type:

None

exception maptor.SolutionExtractionError(message, context=None)[source]#

Bases: MAPTORBaseError

Raised when solution data cannot be extracted from the optimization result.

This exception occurs when MAPTOR fails to process the raw solver output into the user-friendly Solution format, typically due to unexpected solver behavior or corrupted optimization results.

Parameters:
  • message (str)

  • context (str | None)

Return type:

None

maptor.solve_adaptive(problem, error_tolerance=1e-06, max_iterations=30, min_polynomial_degree=3, max_polynomial_degree=8, ode_solver_tolerance=1e-06, ode_method='RK45', ode_max_step=None, ode_atol_factor=1e-08, num_error_sim_points=50, ode_solver=None, nlp_options=None, show_summary=True)[source]#

Solve optimal control problem using adaptive mesh refinement.

Automatically refines mesh until target error tolerance is achieved across all phases. Provides high-accuracy solutions with computational efficiency through adaptive polynomial degree and interval refinement.

Return type:

Solution

Parameters:
  • problem (Problem)

  • error_tolerance (float)

  • max_iterations (int)

  • min_polynomial_degree (int)

  • max_polynomial_degree (int)

  • ode_solver_tolerance (float)

  • ode_method (str)

  • ode_max_step (float | None)

  • ode_atol_factor (float)

  • num_error_sim_points (int)

  • ode_solver (Callable[[...], ODESolverResult] | None)

  • nlp_options (dict[str, object] | None)

  • show_summary (bool)

Args:

problem: Configured Problem instance with initial mesh configurations

error_tolerance: Target relative error tolerance with ranges:
  • 1e-3: Coarse accuracy, fast solving

  • 1e-6: Standard accuracy (default)

  • 1e-9: High accuracy, slower convergence

max_iterations: Maximum refinement iterations:
  • 5-10: Standard problems

  • 15-25: Complex problems

  • 30+: Very challenging problems (default: 30)

min_polynomial_degree: Minimum polynomial degree per interval:
  • 3: Fast, lower accuracy (default)

  • 4-5: Balanced accuracy/speed

  • 6+: High accuracy start

max_polynomial_degree: Maximum polynomial degree per interval:
  • 8-10: Standard limit (default: 10)

  • 12-15: High accuracy problems

  • 20+: Very smooth solutions only

ode_solver_tolerance: ODE integration tolerance for error estimation:
  • 1e-6: Standard (default)

  • 1e-9: High accuracy error estimation

  • 1e-5: Faster, less accurate

ode_method: ODE integration method options:
  • “RK45”: Runge-Kutta 4(5) (default)

  • “RK23”: Runge-Kutta 2(3)

  • “DOP853”: Dormand-Prince 8(5,3)

  • “LSODA”: Automatic stiff/non-stiff

  • “Radau”: Implicit Runge-Kutta

ode_max_step: Maximum ODE step size:
  • None: Automatic (default)

  • float: Fixed maximum step

ode_atol_factor: Absolute tolerance factor (atol = rtol * factor):
  • 1e-8 (default)

num_error_sim_points: Points for error simulation:
  • 30-50: Standard (default: 50)

  • 100+: High-resolution error estimation

ode_solver: Custom ODE solver function:
  • None: Use scipy.solve_ivp (default)

  • Callable: Custom solver implementation

nlp_options: IPOPT options for each NLP solve (same as solve_fixed_mesh)

show_summary: Display solution summary (default: True)

Returns:

Solution: High-accuracy adaptive solution with refinement diagnostics

Examples:

Basic adaptive solving:

>>> solution = mtor.solve_adaptive(problem)

High-accuracy solving:

>>> solution = mtor.solve_adaptive(
...     problem,
...     error_tolerance=1e-8,
...     max_iterations=20,
...     max_polynomial_degree=15
... )

Fast approximate solving:

>>> solution = mtor.solve_adaptive(
...     problem,
...     error_tolerance=1e-3,
...     max_iterations=5,
...     min_polynomial_degree=3,
...     max_polynomial_degree=6
... )

Custom ODE solver settings:

>>> solution = mtor.solve_adaptive(
...     problem,
...     ode_method="LSODA",
...     ode_solver_tolerance=1e-9,
...     num_error_sim_points=100
... )

Complex problem settings:

>>> solution = mtor.solve_adaptive(
...     problem,
...     error_tolerance=1e-6,
...     max_iterations=30,
...     min_polynomial_degree=4,
...     max_polynomial_degree=12,
...     nlp_options={
...         "ipopt.max_iter": 3000,
...         "ipopt.tol": 1e-8,
...         "ipopt.linear_solver": "mumps"
...     }
... )

Override initial guess:

>>> custom_guess = MultiPhaseInitialGuess(...)
>>> solution = mtor.solve_adaptive(
...     problem,
...     initial_guess=custom_guess
... )

Silent adaptive solving:

>>> solution = mtor.solve_adaptive(
...     problem,
...     nlp_options={"ipopt.print_level": 0},
...     show_summary=False
... )

Polynomial degree ranges:

>>> # Conservative polynomial progression
>>> solution = mtor.solve_adaptive(
...     problem,
...     min_polynomial_degree=3,
...     max_polynomial_degree=8
... )
>>>
>>> # Aggressive high-accuracy
>>> solution = mtor.solve_adaptive(
...     problem,
...     min_polynomial_degree=6,
...     max_polynomial_degree=20
... )

Error tolerance ranges:

>>> # Quick verification
>>> solution = mtor.solve_adaptive(problem, error_tolerance=1e-3)
>>> # Production accuracy
>>> solution = mtor.solve_adaptive(problem, error_tolerance=1e-6)
>>> # Research accuracy
>>> solution = mtor.solve_adaptive(problem, error_tolerance=1e-9)
maptor.solve_fixed_mesh(problem, nlp_options=None, show_summary=True)[source]#

Solve optimal control problem using fixed pseudospectral meshes.

Solves the problem using the exact mesh configuration specified in each phase without adaptive refinement. Provides direct control over mesh discretization for computational efficiency or specific accuracy requirements.

Return type:

Solution

Parameters:
Args:

problem: Configured Problem instance with mesh, dynamics, and objective nlp_options: IPOPT solver options with full customization:

  • Any IPOPT option as “ipopt.option_name”: value

show_summary: Whether to display solution summary (default: True)

Returns:

Solution: Optimization results with trajectories and solver diagnostics

Examples:

Basic usage:

>>> solution = mtor.solve_fixed_mesh(problem)

Custom solver options:

>>> solution = mtor.solve_fixed_mesh(
...     problem,
...     nlp_options={
...         "ipopt.print_level": 5,       # Verbose output
...         "ipopt.max_iter": 1000,       # Iteration limit
...         "ipopt.tol": 1e-6             # Tolerance
...     }
... )

High-accuracy solver settings:

>>> solution = mtor.solve_fixed_mesh(
...     problem,
...     nlp_options={
...         "ipopt.tol": 1e-10,
...         "ipopt.constr_viol_tol": 1e-9,
...         "ipopt.hessian_approximation": "exact"
...     }
... )

Linear solver options:

>>> solution = mtor.solve_fixed_mesh(
...     problem,
...     nlp_options={
...         "ipopt.linear_solver": "mumps",
...         "ipopt.mumps_mem_percent": 50000
...     }
... )

Silent solving:

>>> solution = mtor.solve_fixed_mesh(
...     problem,
...     nlp_options={"ipopt.print_level": 0},
...     show_summary=False
... )