TOPP3 and COPP3 Solvers

Use LP and SOCP solvers for third-order models.

Third-order solvers add jerk-level feasibility and return copp.Profile3rd objects. A Profile3rd stores the node profiles and stationary-prefix metadata needed by the third-order interpolation helpers. User code usually treats it as an opaque solver result: pass it to copp.interpolation.s_to_t_topp3 or inspect its public fields when comparing solver output.

Shape summary:

Which third-order solver should I use?

Lazy linearization

Third-order Problem objects store MATLAB-owned descriptors. They do not refresh native third-order linearized constraints during construction. The solve call performs lazy linearization using the selected a_linearization profile and mutates the robot's native third-order cache. Rebuild Problem descriptors after changing the robot or the linearization profile.

Build a shared third-order robot

MATLAB
n = 7;
s = linspace(0.0, 1.0, n).';
scales = [1; 2];

robot = copp.Robot(2, Capacity=n);
cleanup = onCleanup(@() robot.release());
robot.append_s(s);
robot.set_q_3rd( ...
    scales .* s.', ...
    repmat(scales, 1, n), ...
    zeros(2, n), ...
    zeros(2, n));

upper = 100.0 * ones(robot.dim, 1);
robot.add_velocity_limits(upper, -upper);
robot.add_acceleration_limits(upper, -upper);
robot.add_jerk_limits(upper, -upper);

a_linearization = ones(n, 1);

TOPP3-LP and TOPP3-SOCP

MATLAB
lp_problem = copp.solver.topp3_lp.Problem( ...
    robot, ...
    a_linearization, ...
    idx_s_start=1, ...
    a_boundary=[0, 0], ...
    b_boundary=[0, 0], ...
    num_stationary_max=1);
profile_lp = copp.solver.topp3_lp.solve(lp_problem);

socp_problem = copp.solver.topp3_socp.Problem( ...
    robot, ...
    a_linearization, ...
    idx_s_start=1, ...
    a_boundary=[0, 0], ...
    b_boundary=[0, 0], ...
    num_stationary_max=1);
profile_socp = copp.solver.topp3_socp.solve(socp_problem);

fprintf("TOPP3-LP max(a)=%.6f, TOPP3-SOCP max(a)=%.6f\n", ...
    max(profile_lp.a), max(profile_socp.a));
fprintf("TOPP3 profile shapes a/b: %d x %d / %d x %d\n", ...
    size(profile_lp.a, 1), size(profile_lp.a, 2), ...
    size(profile_lp.b, 1), size(profile_lp.b, 2));

COPP3-SOCP

MATLAB
objectives = {
    copp.objective.time(1.0)
    copp.objective.thermal_energy(0.1, ones(robot.dim, 1))
};
% COPP3 linear objectives, if used, require both alpha and beta to have length
% s_len. Torque objective normalize vectors have length dim=robot.dim.
copp3_problem = copp.solver.copp3_socp.Problem( ...
    robot, ...
    objectives, ...
    a_linearization, ...
    idx_s_start=1, ...
    a_boundary=[0, 0], ...
    b_boundary=[0, 0], ...
    num_stationary_max=1);
profile_copp3 = copp.solver.copp3_socp.solve(copp3_problem);
result_copp3 = copp.solver.copp3_socp.solve_expert(copp3_problem);

fprintf("COPP3-SOCP status=%s, objective=%.6f\n", ...
    result_copp3.solver_status, result_copp3.objective_value);

Interpolate a Profile3rd

MATLAB
[t_final, t_s] = copp.interpolation.s_to_t_topp3(s, profile_socp);
profile_table = table(s, profile_socp.a, profile_socp.b, t_s, ...
    'VariableNames', {'s', 'a', 'b', 't_s'});
disp(profile_table)
fprintf("TOPP3-SOCP final traversal time: %.6f seconds\n", t_final);

Expert results

topp3_lp.solve_expert, topp3_socp.solve_expert, and copp3_socp.solve_expert return Result objects with raw Clarabel vectors, solver status, iteration count, residuals, objective terms, and linear-solver metadata. Use them for diagnostics; use normal solve functions when you only need an accepted Profile3rd.