11/* *
2- (C) Copyright 2022 DQ Robotics Developers
2+ (C) Copyright 2022-2023 DQ Robotics Developers
33
44This file is part of DQ Robotics.
55
@@ -18,6 +18,9 @@ This file is part of DQ Robotics.
1818
1919Contributors:
2020- Murilo M. Marinho (murilo@g.ecc.u-tokyo.ac.jp)
21+ - initial implementation
22+ - Quentin Lin (qlin1806@g.ecc.u-tokyo.ac.jp)
23+ - added check for equality constraints
2124*/
2225
2326#include < iostream>
@@ -30,8 +33,10 @@ This file is part of DQ Robotics.
3033
3134using namespace DQ_robotics ;
3235
33- int main (void )
34- {
36+ /* *
37+ * @brief Test solver
38+ */
39+ void test_solver (void ) {
3540 DQ_QPOASESSolver qpoases_solver;
3641 DQ_SerialManipulatorDH robot = KukaLw4Robot::kinematics ();
3742
@@ -41,15 +46,76 @@ int main(void)
4146 classic_qp_controller.set_damping (0.01 );
4247
4348 VectorXd theta_init (7 );
44- theta_init << 0 .,pi/4 .,0 .,0 .,pi/4 .,0 .,0 .;
49+ theta_init << 0 ., pi/4 ., 0 ., 0 ., pi/4 ., 0 ., 0 .;
4550
4651 VectorXd theta_xd (7 );
47- theta_xd << 0 .,pi/2 .,0 .,0 .,pi/2 .,0 .,0 .;
52+ theta_xd << 0 ., pi/2 ., 0 ., 0 ., pi/2 ., 0 ., 0 .;
4853 DQ xd = robot.fkm (theta_xd);
4954
5055 VectorXd qd = classic_qp_controller.compute_setpoint_control_signal (theta_init,vec8 (xd));
5156
5257 std::cout << " q_dot is " << qd.transpose () << std::endl;
58+ }
59+
60+ /* *
61+ * @brief Check if two vectors are equal within a tolerance
62+ * @param a Vector 1
63+ * @param b Vector 2
64+ * @param tolerance default to 1e-3
65+ * @return true if pass
66+ */
67+ bool check_if_vectors_equal (const Eigen::VectorXd &a, const Eigen::VectorXd &b, double tolerance = 1e-3 ) {
68+ if (a.size () != b.size ()) {
69+ return false ; // Vectors have different dimensions
70+ }
71+ for (int i = 0 ; i < a.size (); ++i) {
72+ if (std::abs (a (i) - b (i)) > tolerance) {
73+ std::cout << " CHECK::index: " << i << " exceed error: " << std::abs (a (i) - b (i)) << std::endl;
74+ return false ; // Elements at (i) differ by more than the tolerance
75+ }
76+ }
77+ return true ;
78+ }
79+
80+ /* *
81+ * @brief Test equality constraints
82+ */
83+ void test_equality (void ) {
84+ DQ_QPOASESSolver qpoases_solver;
85+ auto tolerance = qpoases_solver.get_equality_constraints_tolerance ();
86+ std::cout << " current equality tolerance: " << tolerance << std::endl;
87+ qpoases_solver.set_equality_constraints_tolerance (tolerance);
88+
89+ for (int problem_size = 5 ; problem_size <= 10 ; problem_size += 1 ) {
90+ qpoases_solver = DQ_QPOASESSolver ();
91+
92+ MatrixXd H = MatrixXd::Identity (problem_size, problem_size);
93+ VectorXd f = VectorXd::Ones (problem_size);
94+ std::cout << " Checking Problem Size: " << problem_size << std::endl;
95+ for (int iter = 0 ; iter < 10 ; iter += 1 ) {
96+ srand (iter);
97+ VectorXd a_diag = VectorXd::Random (problem_size);
98+ MatrixXd Aeq = a_diag.asDiagonal ();
99+ VectorXd beq = VectorXd::Random (problem_size);
100+ auto out = qpoases_solver.solve_quadratic_program (H, f, MatrixXd (), VectorXd (), Aeq, beq);
101+ // just plain tolerance is too tight for the check
102+ if (!check_if_vectors_equal (beq, Aeq * out, tolerance+DQ_threshold)) {
103+ std::cout << " Solver Failed equality check on a_diag: " << a_diag.transpose () <<
104+ std::endl << " beq: " << beq.transpose () <<
105+ std::endl << " Solution: " << out.transpose () <<
106+ std::endl << " check " << (Aeq * out).transpose () << std::endl;
107+ throw std::runtime_error (" solver equality check failed" );
108+ }
109+ }
110+ }
111+ }
112+
113+
114+ int main (void ) {
115+ test_solver ();
116+ test_equality ();
53117
54118 return 0 ;
55119}
120+
121+
0 commit comments