COPP C ABI
C interface for COPP trajectory optimization
Loading...
Searching...
No Matches
copp3_socp.c
Go to the documentation of this file.
1#include "example_common.h"
2
3static int solve_copp3_socp_with_temporary_diagnostics(const char *label,
4 struct Copp3Problem problem,
5 struct CoppClarabelOptions options,
6 struct CoppProfile3rd *out_profile)
7{
8 enum CoppStatus status = copp3_socp(problem, options, out_profile);
9 if (status == COPP_STATUS_OK)
10 {
11 return 0;
12 }
13
14 fprintf(stderr, "%s failed: %s\n", label, copp_status_message(status));
15 fprintf(stderr, "%s last error: %s\n", label, copp_last_error_message());
16
17 struct Copp3SocpResult result;
18 enum CoppStatus expert_status = copp3_socp_expert(problem, options, &result);
19 if (expert_status != COPP_STATUS_OK)
20 {
21 fprintf(stderr,
22 "%s expert diagnostics failed: %s\n",
23 label,
24 copp_status_message(expert_status));
25 fprintf(stderr, "%s expert last error: %s\n", label, copp_last_error_message());
26 return 1;
27 }
28
29 fprintf(stderr,
30 "%s expert diagnostics: solver_status=%d, has_profile=%d, iterations=%u, "
31 "r_prim=%.17g, r_dual=%.17g, obj_val=%.17g, obj_val_dual=%.17g, solve_time=%.17g, "
32 "x.len=%zu, z.len=%zu, s.len=%zu\n",
33 label,
34 (int)result.solver_status,
35 (int)result.has_profile,
36 result.iterations,
37 result.r_prim,
38 result.r_dual,
39 result.obj_val,
40 result.obj_val_dual,
41 result.solve_time,
42 result.x.len,
43 result.z.len,
44 result.s.len);
46 return 1;
47}
48
49int main(void)
50{
51 /*
52 * 1) Deterministic 3-axis Lissajous path q(s), s in [0, 1].
53 */
54 double s[EXAMPLE_NUM_POINTS];
55 double normalize[EXAMPLE_DIM] = {1.0, 1.0, 1.0};
56 struct CoppPath *path = NULL;
57 struct CoppRobot *robot = NULL;
58 struct CoppVecF64 a_ra0 = {NULL, 0, 0};
59 struct CoppProfile3rd profile_qp1 = {{NULL, 0, 0}, {NULL, 0, 0}, 0, 0};
60 struct CoppProfile3rd profile_qp2 = {{NULL, 0, 0}, {NULL, 0, 0}, 0, 0};
61 struct CoppVecF64 t_s1 = {NULL, 0, 0};
62 struct CoppVecF64 t_s2 = {NULL, 0, 0};
63 struct CoppVecF64 s_t1 = {NULL, 0, 0};
64 struct CoppVecF64 s_t2 = {NULL, 0, 0};
65 int rc = 1;
66
67 example_fill_stations(s, EXAMPLE_NUM_POINTS);
68 if (example_create_analytic_path_3rd(&path))
69 {
70 goto cleanup;
71 }
72
73 /*
74 * 2) Build robot constraints (3-axis), then apply symmetric limits
75 * velocity/acceleration/jerk = [-1, 1].
76 */
77 if (example_create_robot_3rd(path, s, EXAMPLE_NUM_POINTS, &robot))
78 {
79 goto cleanup;
80 }
81
82 /*
83 * 3) Solve TOPP2-RA to get a feasible linearization profile for TOPP3.
84 */
85 if (example_seed_third_order_problem(robot, EXAMPLE_NUM_POINTS, &a_ra0))
86 {
87 goto cleanup;
88 }
89
90 /*
91 * 4) Solve COPP3-SOCP with the linearization profile from TOPP2-RA.
92 *
93 * The objective is 1.0 * time + 0.1 * thermal energy. With no
94 * inverse-dynamics callback installed, torque objectives use point
95 * dynamics (`tau = ddq`).
96 */
97 struct CoppClarabelOptions options_socp;
98 enum CoppStatus status = copp_clarabel_default_options(&options_socp);
99 if (example_expect_ok(status, "copp_clarabel_default_options"))
100 {
101 goto cleanup;
102 }
103 options_socp.allow_almost_solved = true;
104 options_socp.allow_insufficient_progress = true;
105
106 struct CoppSliceF64 empty = {NULL, 0};
107 struct CoppSliceF64 normalize_slice = {normalize, EXAMPLE_DIM};
108 struct CoppObjective objectives[2] = {
109 {COPP_OBJECTIVE_KIND_TIME, 1.0, empty, empty, empty},
110 {COPP_OBJECTIVE_KIND_THERMAL_ENERGY, 0.1, empty, empty, normalize_slice},
111 };
112 struct Copp3Problem problem1 = {
113 robot,
114 0,
115 (struct CoppSliceF64){a_ra0.data, a_ra0.len},
116 0.0,
117 0.0,
118 0.0,
119 0.0,
120 1,
121 1,
122 1e-10,
123 objectives,
124 2,
125 };
126
127 if (solve_copp3_socp_with_temporary_diagnostics(
128 "copp3_socp first iteration",
129 problem1,
130 options_socp,
131 &profile_qp1))
132 {
133 goto cleanup;
134 }
135
136 double t_final1 = 0.0;
137 if (example_time_from_third_order(s, EXAMPLE_NUM_POINTS, profile_qp1, &t_final1, &t_s1) ||
138 example_interpolate_third_order(s, EXAMPLE_NUM_POINTS, profile_qp1, t_s1, &s_t1))
139 {
140 goto cleanup;
141 }
142
143 printf("COPP3-SOCP done. (The first-iteration)\n");
144 printf("dim = %d, N = %d\n", EXAMPLE_DIM, EXAMPLE_NUM_POINTS);
145 printf("t_final = %.6f s\n", t_final1);
146 printf("a_profile.len() = %zu\n", profile_qp1.a.len);
147 printf("b_profile.len() = %zu\n", profile_qp1.b.len);
148 printf("s(t) samples = %zu\n", s_t1.len);
149
150 /*
151 * 5) Solve COPP3-SOCP with the first SOCP profile as the new linearization
152 * point, matching the tutorial's second SCP iteration.
153 */
154 struct Copp3Problem problem2 = {
155 robot,
156 0,
157 (struct CoppSliceF64){profile_qp1.a.data, profile_qp1.a.len},
158 0.0,
159 0.0,
160 0.0,
161 0.0,
162 1,
163 1,
164 1e-10,
165 objectives,
166 2,
167 };
168 if (solve_copp3_socp_with_temporary_diagnostics(
169 "copp3_socp second iteration",
170 problem2,
171 options_socp,
172 &profile_qp2))
173 {
174 goto cleanup;
175 }
176
177 double t_final2 = 0.0;
178 if (example_time_from_third_order(s, EXAMPLE_NUM_POINTS, profile_qp2, &t_final2, &t_s2) ||
179 example_interpolate_third_order(s, EXAMPLE_NUM_POINTS, profile_qp2, t_s2, &s_t2))
180 {
181 goto cleanup;
182 }
183
184 printf("---------\nCOPP3-SOCP done. (The second-iteration)\n");
185 printf("dim = %d, N = %d\n", EXAMPLE_DIM, EXAMPLE_NUM_POINTS);
186 printf("t_final = %.6f s <= %.6f s\n", t_final2, t_final1);
187 printf("a_profile.len() = %zu\n", profile_qp2.a.len);
188 printf("b_profile.len() = %zu\n", profile_qp2.b.len);
189 printf("s(t) samples = %zu\n", s_t2.len);
190 rc = 0;
191
192cleanup:
193 copp_vec_f64_free(s_t2);
194 copp_vec_f64_free(s_t1);
195 copp_vec_f64_free(t_s2);
196 copp_vec_f64_free(t_s1);
197 copp_profile_3rd_free(profile_qp2);
198 copp_profile_3rd_free(profile_qp1);
199 copp_vec_f64_free(a_ra0);
200 copp_robot_free(robot);
201 copp_path_free(path);
202 return rc;
203}
int main(void)
Definition copp3_socp.c:49
@ EXAMPLE_NUM_POINTS
@ EXAMPLE_DIM
enum CoppStatus copp3_socp(struct Copp3Problem problem, struct CoppClarabelOptions options, struct CoppProfile3rd *out_profile)
Solve a COPP3-SOCP problem.
void copp3_socp_result_free(struct Copp3SocpResult result)
Release memory owned by a Copp3SocpResult.
enum CoppStatus copp3_socp_expert(struct Copp3Problem problem, struct CoppClarabelOptions options, struct Copp3SocpResult *out_result)
Solve a COPP3-SOCP problem and always return Clarabel diagnostics.
const char * copp_status_message(enum CoppStatus status)
Return a short static message for a COPP status code.
CoppStatus
C ABI status code returned by COPP FFI functions.
Definition core.h:34
void copp_vec_f64_free(struct CoppVecF64 vec)
Release a library-owned f64 vector returned by COPP.
const char * copp_last_error_message(void)
Return the current thread's last detailed error message as UTF-8.
enum CoppStatus copp_clarabel_default_options(struct CoppClarabelOptions *out_options)
Write default shared Clarabel options into out_options.
@ COPP_STATUS_OK
Operation completed successfully.
Definition core.h:38
void copp_profile_3rd_free(struct CoppProfile3rd profile)
Release a third-order profile returned by COPP.
@ COPP_OBJECTIVE_KIND_TIME
Time objective: weight * integral dt.
Definition formulation.h:35
@ COPP_OBJECTIVE_KIND_THERMAL_ENERGY
Thermal-energy objective.
Definition formulation.h:48
struct CoppPath CoppPath
Opaque C handle for a library-owned Path.
Definition path.h:36
void copp_path_free(struct CoppPath *path)
Release a path handle created by this module.
struct CoppRobot CoppRobot
Opaque C handle for a library-owned robot and constraint buffer.
Definition robot.h:35
void copp_robot_free(struct CoppRobot *robot)
Release a robot handle created by copp_robot_create.
Borrowed value descriptor for a COPP3 problem solved from C.
struct CoppRobot * robot
Mutable robot handle that owns station-indexed constraint storage.
Compact COPP3-SOCP expert result returned to C.
Definition copp3.h:39
struct CoppVecF64 s
Raw Clarabel primal-cone slack vector.
Definition copp3.h:60
Shared Clarabel options for COPP SOCP solvers.
Definition core.h:627
bool allow_insufficient_progress
Accept Clarabel status InsufficientProgress as usable.
Definition core.h:651
bool allow_almost_solved
Accept Clarabel status AlmostSolved as usable.
Definition core.h:635
Borrowed objective descriptor for COPP solvers.
Definition formulation.h:86
Owned third-order profile returned by TOPP3/COPP3 C ABI solvers.
struct CoppVecF64 b
Node-based profile b[k] = ddot{s}_k.
struct CoppVecF64 a
Node-based profile a[k] = dot{s}_k^2.
Borrowed immutable f64 slice passed from C to COPP.
Definition core.h:781
Library-owned f64 vector returned to C.
Definition core.h:828
size_t len
Number of initialized elements.
Definition core.h:836
double * data
Pointer to the first element, or null for an empty vector.
Definition core.h:832