COPP C++ API
C++ interface for COPP trajectory optimization
Loading...
Searching...
No Matches
robot_inverse_dynamics.cpp
Go to the documentation of this file.
1// Tutorial example: install a C++ inverse-dynamics callback.
2//
3// The callback is used by torque limits and torque objectives. This example
4// keeps the dynamics intentionally small so the data flow is visible:
5// tau = inertia * ddq + damping * dq + gravity * sin(q).
6
7#include <cmath>
8#include <iostream>
9#include <vector>
10
11#include <copp/copp.hpp>
12
14{
15 std::vector<double> inertia{1.2, 0.8};
16 std::vector<double> damping{0.08, 0.05};
17 std::vector<double> gravity{0.4, 0.25};
18
23 copp::Span<double> tau) const
24 {
25 // The callback receives one state at a time. All spans have length equal
26 // to the robot dimension, and `tau` must be fully overwritten.
27 for (std::size_t i = 0; i < tau.size(); ++i)
28 {
29 tau[i] = inertia[i] * ddq[i] + damping[i] * dq[i] + gravity[i] * std::sin(q[i]);
30 }
31 }
32};
33
34int main()
35{
36 // Step 1: Create stations and joint/torque limits. Torque limits will use
37 // the callback below instead of the default point-mass model.
38 std::vector<double> s{0.0, 0.25, 0.5, 0.75, 1.0};
39 std::vector<double> upper{3.0, 3.0};
40 std::vector<double> lower{-3.0, -3.0};
41 std::vector<double> torque_upper{50.0, 50.0};
42 std::vector<double> torque_lower{-50.0, -50.0};
43
44 // Step 2: Build a path with derivatives available through Jet3.
46 [](copp::Jet3 x)
47 {
48 return std::vector<copp::Jet3>{
49 x,
50 copp::sin(x),
51 };
52 },
53 0.0,
54 1.0);
55
56 ToyArmDynamics dynamics;
57
58 // Step 3: Install the callback. Captured objects must remain valid for the
59 // period in which torque constraints/objectives are constructed.
60 copp::Robot robot(2, s.size());
62 [dynamics](
67 {
68 dynamics(q, dq, ddq, tau);
69 });
70
71 // Step 4: Add velocity, acceleration, and torque constraints. The torque
72 // call crosses the Rust/C++ bridge into `ToyArmDynamics`.
73 robot.append_s(s)
74 .set_q_from_path_2nd(path, 0, s.size())
75 .add_velocity_limits(upper, lower, 0, s.size())
76 .add_acceleration_limits(upper, lower, 0, s.size())
77 .add_torque_limits(torque_upper, torque_lower, 0, s.size());
78
79 namespace copp2 = copp::solver::copp2_socp;
80
81 // Step 5: ThermalEnergy uses inverse dynamics as part of the objective.
82 copp2::Problem problem{
83 robot,
84 {
86 copp::objective::ThermalEnergy(0.05, {1.0, 1.0}),
87 },
88 copp::IndexInterval{0, s.size() - 1},
89 copp::Boundary2{0.0, 0.0},
90 };
91
92 // Step 6: Expert output exposes accepted profile and objective diagnostics.
93 auto expert = copp2::solve_expert(problem);
94 if (!expert.a)
95 {
96 std::cerr << "Clarabel did not return an accepted profile\n";
97 return 1;
98 }
99
100 auto time = copp::interpolation::s_to_t_topp2(s, *expert.a, 0.0);
101 std::cout << "has_inverse_dynamics = " << robot.has_inverse_dynamics() << "\n";
102 std::cout << "accepted a length = " << expert.a->size() << "\n";
103 std::cout << "t_final = " << time.t_final << "\n";
104 std::cout << "objective = " << *expert.objective_value << "\n";
105
106 return 0;
107}
static Path from_parametric(PathParametric parametric, double s_min, double s_max)
Build a path from a scalar-parametric formula.
Robot facade backed by Rust Robot<CppRobotModel>.
Definition robot.hpp:318
Robot & add_torque_limits(Span< const double > upper, Span< const double > lower, std::size_t start_idx_s, std::size_t length=0)
Add torque limits from broadcast vectors.
Robot & set_q_from_path_2nd(const Path &path, std::size_t idx_s_from, std::size_t idx_s_to)
Sample a path and store derivatives up to second order.
Robot & add_acceleration_limits(Span< const double > upper, Span< const double > lower, std::size_t start_idx_s, std::size_t length=0)
Add acceleration limits from broadcast vectors.
bool has_inverse_dynamics() const
Return whether a user inverse-dynamics callback is installed.
Robot & append_s(Span< const double > s)
Append strictly increasing path station samples.
Robot & add_velocity_limits(Span< const double > upper, Span< const double > lower, std::size_t start_idx_s, std::size_t length=0)
Add velocity limits from broadcast vectors.
Robot & set_inverse_dynamics(InverseDynamics inverse_dynamics)
Replace the inverse-dynamics callback.
Non-owning view of a contiguous one-dimensional array.
Definition core.hpp:139
constexpr std::size_t size() const noexcept
Definition core.hpp:169
COPP_API TimeProfile s_to_t_topp2(Span< const double > s, Span< const double > a, double t0=0.0)
Convert a second-order path profile a(s) = ds/dt squared to t(s).
Objective ThermalEnergy(double weight, Span< const double > normalize)
Objective Time(double weight=1.0)
Second-order convex-objective Clarabel SOCP backend with normal profile-returning APIs and expert dia...
Jet3 sin(Jet3 x) noexcept
Definition path.hpp:156
void operator()(copp::Span< const double > q, copp::Span< const double > dq, copp::Span< const double > ddq, copp::Span< double > tau) const
std::vector< double > damping
std::vector< double > inertia
std::vector< double > gravity
Second-order endpoint boundary values.
Definition core.hpp:77
Closed station-index interval used by TOPP/COPP problem descriptors.
Definition core.hpp:67
Third-order forward-mode automatic-differentiation scalar.
Definition path.hpp:44