From 78b0c2ddc0f8c2fe103f4fce730adc46ef29956f Mon Sep 17 00:00:00 2001 From: ishiguro Date: Mon, 30 May 2016 20:45:18 +0900 Subject: [PATCH 001/217] init commit --- rtc/AutoBalancer/AutoBalancer.cpp | 249 +++++++++++++++++++++++++++++- rtc/AutoBalancer/AutoBalancer.h | 16 ++ rtc/AutoBalancer/CMakeLists.txt | 4 +- rtc/AutoBalancer/GaitGenerator.h | 8 +- 4 files changed, 268 insertions(+), 9 deletions(-) diff --git a/rtc/AutoBalancer/AutoBalancer.cpp b/rtc/AutoBalancer/AutoBalancer.cpp index 8edc84ad2aa..454f9c3b3cc 100644 --- a/rtc/AutoBalancer/AutoBalancer.cpp +++ b/rtc/AutoBalancer/AutoBalancer.cpp @@ -16,6 +16,28 @@ #include #include "hrpsys/util/Hrpsys.h" +//SHM関連 +#include +#include +#include +#include +#include +int shmid; +key_t key; +typedef struct{ + double com[3]; + double rfpos[3]; + double lfpos[3]; + double rhpos[3]; + double lhpos[3]; + double rfwrench[6]; + double lfwrench[6]; + double zmp[3]; + bool startsync; +}humanpose_t; +humanpose_t *humanpose; +humanpose_t filt_hp_data,hp_data_old; + typedef coil::Guard Guard; using namespace rats; @@ -49,6 +71,14 @@ AutoBalancer::AutoBalancer(RTC::Manager* manager) m_zmpIn("zmpIn", m_zmp), m_optionalDataIn("optionalData", m_optionalData), m_emergencySignalIn("emergencySignal", m_emergencySignal), + //ishiguro + m_htzmpIn("htzmpIn", m_htzmp), + m_htcomIn("htcomIn", m_htcom), + m_htrfIn("htrfIn", m_htrf), + m_htlfIn("htlfIn", m_htlf), + m_htrhIn("htrhIn", m_htrh), + m_htlhIn("htlhIn", m_htlh), + m_qOut("q", m_qRef), m_zmpOut("zmpOut", m_zmp), m_basePosOut("basePosOut", m_basePos), @@ -90,6 +120,13 @@ RTC::ReturnCode_t AutoBalancer::onInitialize() addInPort("zmpIn", m_zmpIn); addInPort("optionalData", m_optionalDataIn); addInPort("emergencySignal", m_emergencySignalIn); + //ishiguro + addInPort("htzmpIn", m_htzmpIn); + addInPort("htcomIn", m_htcomIn); + addInPort("htrfIn", m_htrfIn); + addInPort("htlfIn", m_htlfIn); + addInPort("htrhIn", m_htrhIn); + addInPort("htlhIn", m_htlhIn); // Set OutPort buffer addOutPort("q", m_qOut); @@ -339,6 +376,30 @@ RTC::ReturnCode_t AutoBalancer::onInitialize() rot_ik_thre = (1e-2)*M_PI/180.0; // [rad] ik_error_debug_print_freq = static_cast(0.2/m_dt); // once per 0.2 [s] + + //SHM my2 + if((key = ftok("/tmp/shm.dat", 'R')) == -1){ + printf("WARN: ftok() failed retry\n"); + system("touch /tmp/shm.dat"); + if((key = ftok("/tmp/shm.dat", 'R')) == -1){ + perror("ERROR: ftok() failed exit\n"); + return RTC::RTC_ERROR; + } + } + if((shmid = shmget(key, sizeof(humanpose_t), 0666)) < 0){ + printf("WARN: shmget() failed retry\n"); + shmid = shmget(key, sizeof(humanpose_t), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | IPC_CREAT); + if (shmid == -1) { + perror("ERROR: shmget() failed exit\n"); + return RTC::RTC_ERROR; + } + } + humanpose = (humanpose_t *)shmat(shmid, (void *)0, 0); + if (humanpose == NULL) { + perror("shmat"); + return RTC::RTC_ERROR; + } + return RTC::RTC_OK; } @@ -346,6 +407,10 @@ RTC::ReturnCode_t AutoBalancer::onInitialize() RTC::ReturnCode_t AutoBalancer::onFinalize() { + //SHM + if (shmdt(humanpose) == -1){ perror("shmdt"); } + if (shmctl(shmid, IPC_RMID, 0) == -1){ perror("shmctl"); } + delete zmp_offset_interpolator; delete transition_interpolator; delete adjust_footstep_interpolator; @@ -442,6 +507,43 @@ RTC::ReturnCode_t AutoBalancer::onExecute(RTC::UniqueId ec_id) // gg->emergency_stop(); // } } + //for human tracker + if (m_htzmpIn.isNew()){ + m_htzmpIn.read(); + input_htzmp(0) = m_htzmp.data.x; + input_htzmp(1) = m_htzmp.data.y; + input_htzmp(2) = m_htzmp.data.z; + } + if (m_htcomIn.isNew()){ + m_htcomIn.read(); + input_htcom(0) = m_htcom.data.x; + input_htcom(1) = m_htcom.data.y; + input_htcom(2) = m_htcom.data.z; + } + if (m_htrfIn.isNew()){ + m_htrfIn.read(); + input_htrf(0) = m_htrf.data.x; + input_htrf(1) = m_htrf.data.y; + input_htrf(2) = m_htrf.data.z; + } + if (m_htlfIn.isNew()){ + m_htlfIn.read(); + input_htlf(0) = m_htlf.data.x; + input_htlf(1) = m_htlf.data.y; + input_htlf(2) = m_htlf.data.z; + } + if (m_htrhIn.isNew()){ + m_htrhIn.read(); + input_htrh(0) = m_htrh.data.x; + input_htrh(1) = m_htrh.data.y; + input_htrh(2) = m_htrh.data.z; + } + if (m_htlhIn.isNew()){ + m_htlhIn.read(); + input_htlh(0) = m_htlh.data.x; + input_htlh(1) = m_htlh.data.y; + input_htlh(2) = m_htlh.data.z; + } Guard guard(m_mutex); hrp::Vector3 ref_basePos; @@ -530,6 +632,45 @@ RTC::ReturnCode_t AutoBalancer::onExecute(RTC::UniqueId ec_id) m_cog.data.y = ref_cog(1); m_cog.data.z = ref_cog(2); m_cog.tm = m_qRef.tm; + + + // my test zmp SHM + + double rfzmp[2],lfzmp[2]; + const double F_H_OFFSET = 0.03; + const double rfpos[3] = {0,-0.1,0},lfpos[3] = {0,0.1,0}; + + if( humanpose->rfwrench[2] > 1.0e-6 ){ + rfzmp[0] = ( -humanpose->rfwrench[4] - humanpose->rfwrench[0] * F_H_OFFSET + humanpose->rfwrench[2] * 0 ) / humanpose->rfwrench[2]; + rfzmp[1] = ( humanpose->rfwrench[3] - humanpose->rfwrench[1] * F_H_OFFSET + humanpose->rfwrench[2] * 0 ) / humanpose->rfwrench[2]; + } + if( humanpose->lfwrench[2] > 1.0e-6 ){ + lfzmp[0] = ( -humanpose->lfwrench[4] - humanpose->lfwrench[0] * F_H_OFFSET + humanpose->lfwrench[2] * 0 ) / humanpose->lfwrench[2]; + lfzmp[1] = ( humanpose->lfwrench[3] - humanpose->lfwrench[1] * F_H_OFFSET + humanpose->lfwrench[2] * 0 ) / humanpose->lfwrench[2]; + } + humanpose->zmp[0] = ( rfzmp[0]*humanpose->rfwrench[2] + lfzmp[0]*humanpose->lfwrench[2] ) / ( humanpose->rfwrench[2] + humanpose->lfwrench[2] ); + humanpose->zmp[1] = ( rfzmp[1]*humanpose->rfwrench[2] + lfzmp[1]*humanpose->lfwrench[2] ) / ( humanpose->rfwrench[2] + humanpose->lfwrench[2]); + humanpose->zmp[2] = 0; + +// for(int i=0;i<6;i++)cout<<"rfw["<rfwrench[i]; +// for(int i=0;i<6;i++)cout<<"lfw["<lfwrench[i]; +// for(int i=0;i<2;i++)cout<<"zmp["<zmp[i]; + + //debug表示 +// printf("[L] %+06.1f,%+06.1f,%+06.1f,%+06.1f,%+06.1f,%+06.1f [R] %+06.1f,%+06.1f,%+06.1f,%+06.1f,%+06.1f,%+06.1f [ZMP] %+06.3f,%+06.3f\n", +// humanpose->lfwrench[0],humanpose->lfwrench[1],humanpose->lfwrench[2],humanpose->lfwrench[3],humanpose->lfwrench[4],humanpose->lfwrench[5], +// humanpose->rfwrench[0],humanpose->rfwrench[1],humanpose->rfwrench[2],humanpose->rfwrench[3],humanpose->rfwrench[4],humanpose->rfwrench[5], +// humanpose->zmp[0],humanpose->zmp[1]); + humanpose->startsync = true;//test + if(humanpose->startsync){ +//ZMP上書き +// m_zmp.data.x = humanpose->zmp[0]*0.5 - filt_hp_data.com[0];// + m_zmp.data.y = filt_hp_data.zmp[1] - filt_hp_data.com[1];// +// COM上書き +// m_cog.data.x = 0.0558423 + filt_hp_data.com[0]; + m_cog.data.y = filt_hp_data.com[1]; + } + // sbpCogOffset m_sbpCogOffset.data.x = sbp_cog_offset(0); m_sbpCogOffset.data.y = sbp_cog_offset(1); @@ -686,15 +827,15 @@ void AutoBalancer::getTargetParameters() ABCIKparam& tmpikp = ikp[leg_names[i]]; ee_pos.push_back(tmpikp.target_p0 + tmpikp.target_r0 * tmpikp.localPos + tmpikp.target_r0 * tmpikp.localR * default_zmp_offsets[i]); } - double alpha = (ref_zmp - ee_pos[1]).norm() / ((ee_pos[0] - ref_zmp).norm() + (ee_pos[1] - ref_zmp).norm()); + double alpha = (ref_zmp - ee_pos[1]).norm() / (ee_pos[0] - ee_pos[1]).norm(); if (alpha>1.0) alpha = 1.0; if (alpha<0.0) alpha = 0.0; if (DEBUGP) { std::cerr << "[" << m_profile.instance_name << "] alpha:" << alpha << std::endl; } double mg = m_robot->totalMass() * gg->get_gravitational_acceleration(); - m_force[0].data[2] = alpha * mg; - m_force[1].data[2] = (1-alpha) * mg; + m_force[0].data[0] = alpha * mg; + m_force[1].data[0] = (1-alpha) * mg; } // set limbCOPOffset { @@ -857,6 +998,7 @@ void AutoBalancer::getTargetParameters() if ( gg_is_walking && gg->get_lcg_count() == gg->get_overwrite_check_timing()+2 ) { hrp::Vector3 vel_htc(calc_vel_from_hand_error(tmp_fix_coords)); gg->set_offset_velocity_param(vel_htc(0), vel_htc(1) ,vel_htc(2)); + gg->set_offset_velocity_param(1,2,3); }// else { // if ( gg_is_walking && gg->get_lcg_count() == static_cast(gg->get_default_step_time()/(2*m_dt))-1) { // gg->set_offset_velocity_param(0,0,0); @@ -914,8 +1056,66 @@ void AutoBalancer::fixLegToCoords (const hrp::Vector3& fix_pos, const hrp::Matri m_robot->calcForwardKinematics(); } +static bool moveleft = false; bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) { +// cout<<"****************** test ********************"<startsync){ + if(param.target_link->name == "RLEG_JOINT5"){ + if(humanpose->rfwrench[2] < 20.0 && humanpose->lfwrench[2] > 20.0){ +// if(humanpose->rfwrench[2] < 20.0){ + if(rfuplevel < 100){ + rfuplevel++; + filt_hp_data.rfpos[2] = 0.025 - 0.025*cos(M_PI*rfuplevel/100); + //filt_hp_data.rfpos[1] -= 0.001;//歩行遊び + } + cout<<"RUP"< 0){ + rfuplevel--; + filt_hp_data.rfpos[2] = 0.025 - 0.025*cos(M_PI*rfuplevel/100); + //if(filt_hp_data.rfpos[2] == 0.0)moveleft = true;//歩行遊び + } + } + param.target_p0(0) = 0.0 + filt_hp_data.rfpos[0]; + param.target_p0(1) = -0.1 + filt_hp_data.rfpos[1]; + param.target_p0(2) = 0.1 + filt_hp_data.rfpos[2]; + } + if(param.target_link->name == "LLEG_JOINT5"){ + if(humanpose->lfwrench[2] < 20.0 && humanpose->rfwrench[2] > 20.0){ +// if(humanpose->lfwrench[2] < 20.0){ + if(lfuplevel < 100){ + lfuplevel++; + filt_hp_data.lfpos[2] = 0.025 - 0.025*cos(M_PI*lfuplevel/100); + //filt_hp_data.lfpos[1] -= 0.001;//歩行遊び + } + cout<<"LUP"< 0){ + lfuplevel--; + filt_hp_data.lfpos[2] = 0.025 - 0.025*cos(M_PI*lfuplevel/100); + //if(filt_hp_data.lfpos[2] == 0.0)moveleft = true;//歩行遊び + } + } + param.target_p0(0) = 0.0 + filt_hp_data.lfpos[0]; + param.target_p0(1) = 0.1 + filt_hp_data.lfpos[1]; + param.target_p0(2) = 0.1 + filt_hp_data.lfpos[2]; + } + if(param.target_link->name == "RARM_JOINT7"){ + param.target_p0(0) = 0.151 + filt_hp_data.rhpos[0]; + param.target_p0(1) = -0.374 + filt_hp_data.rhpos[1]; + param.target_p0(2) = 0.973 + filt_hp_data.rhpos[2]; + } + if(param.target_link->name == "LARM_JOINT7"){ + param.target_p0(0) = 0.151 + filt_hp_data.lhpos[0]; + param.target_p0(1) = 0.374 + filt_hp_data.lhpos[1]; + param.target_p0(2) = 0.973 + filt_hp_data.lhpos[2]; + } + } + + param.manip->calcInverseKinematics2Loop(param.target_p0, param.target_r0, 1.0, param.avoid_gain, param.reference_gain, &qrefv, transition_interpolator_ratio * leg_names_interpolator_ratio); // IK check hrp::Vector3 vel_p, vel_r; @@ -942,6 +1142,7 @@ bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) return true; } + void AutoBalancer::solveLimbIK () { for ( std::map::iterator it = ikp.begin(); it != ikp.end(); it++ ) { @@ -962,6 +1163,48 @@ void AutoBalancer::solveLimbIK () dif_cog(2) = m_robot->rootLink()->p(2) - target_root_p(2); m_robot->rootLink()->p = m_robot->rootLink()->p + -1 * move_base_gain * dif_cog; m_robot->rootLink()->R = target_root_R; +//mytest + #define MAXVEL 0.002 + + for(int i=0;i<3;i++){ +// filt_hp_data.com[i] = 0.99*filt_hp_data.com[i] + 0.01*(humanpose->com[i]); +// filt_hp_data.rfpos[i] = 0.99*filt_hp_data.rfpos[i] + 0.01*(humanpose->rfpos[i]);//足ロック +// filt_hp_data.lfpos[i] = 0.99*filt_hp_data.lfpos[i] + 0.01*(humanpose->lfpos[i]);//足ロック +// filt_hp_data.rhpos[i] = 0.99*filt_hp_data.rhpos[i] + 0.01*(humanpose->rhpos[i]); +// filt_hp_data.lhpos[i] = 0.99*filt_hp_data.lhpos[i] + 0.01*(humanpose->lhpos[i]); +// filt_hp_data.zmp[i] = 0.99*filt_hp_data.zmp[i] + 0.01*(humanpose->zmp[i]); + + filt_hp_data.zmp[i] = 0.99*filt_hp_data.zmp[i] + 0.01*(input_htzmp(i)); + filt_hp_data.com[i] = 0.99*filt_hp_data.com[i] + 0.01*(input_htcom(i)); + filt_hp_data.rfpos[i] = 0.99*filt_hp_data.rfpos[i] + 0.01*(input_htrf(i)); + filt_hp_data.lfpos[i] = 0.99*filt_hp_data.lfpos[i] + 0.01*(input_htlf(i)); + filt_hp_data.rhpos[i] = 0.99*filt_hp_data.rhpos[i] + 0.01*(input_htrh(i)); + filt_hp_data.lhpos[i] = 0.99*filt_hp_data.lhpos[i] + 0.01*(input_htlh(i)); + + + + if(filt_hp_data.com[i] - hp_data_old.com[i] > MAXVEL)filt_hp_data.com[i] = hp_data_old.com[i] + MAXVEL; + if(filt_hp_data.com[i] - hp_data_old.com[i] < -MAXVEL)filt_hp_data.com[i] = hp_data_old.com[i] - MAXVEL; + hp_data_old.com[i] = filt_hp_data.com[i]; + } +// cout<<"COM"<calcCM()[0]<<","<calcCM()[1]<<","<calcCM()[2]<rootLink()->p(0) = 0.0558423 + filt_hp_data.com[0]; + m_robot->rootLink()->p(1) = 0+ filt_hp_data.com[1];//safetest + m_robot->rootLink()->p(2) = 0.976372 + filt_hp_data.com[2]; + +static int movelcnt; + if(moveleft){ + if(movelcnt<5000){ + m_robot->rootLink()->p(1) += 0.00001;//遊び + movelcnt++; + }else{ + movelcnt = 0; + moveleft = false; + } + } + // Fix for toe joint for ( std::map::iterator it = ikp.begin(); it != ikp.end(); it++ ) { if (it->second.is_active && it->second.has_toe_joint && gg->get_use_toe_joint()) { diff --git a/rtc/AutoBalancer/AutoBalancer.h b/rtc/AutoBalancer/AutoBalancer.h index e2c03e6e2e1..e8214e339b9 100644 --- a/rtc/AutoBalancer/AutoBalancer.h +++ b/rtc/AutoBalancer/AutoBalancer.h @@ -135,6 +135,19 @@ class AutoBalancer InPort m_emergencySignalIn; // for debug TimedPoint3D m_cog; + //for human tracker + TimedPoint3D m_htzmp; + InPort m_htzmpIn; + TimedPoint3D m_htcom; + InPort m_htcomIn; + TimedPoint3D m_htrf; + InPort m_htrfIn; + TimedPoint3D m_htlf; + InPort m_htlfIn; + TimedPoint3D m_htrh; + InPort m_htrhIn; + TimedPoint3D m_htlh; + InPort m_htlhIn; // @@ -251,6 +264,9 @@ class AutoBalancer enum {MODE_NO_FORCE, MODE_REF_FORCE} use_force; std::vector ref_forces; + //for human tracker + hrp::Vector3 input_htzmp, input_htcom, input_htrf, input_htlf, input_htrh, input_htlh; + unsigned int m_debugLevel; bool is_legged_robot, is_stop_mode, has_ik_failed, is_hand_fix_mode, is_hand_fix_initial; int loop, ik_error_debug_print_freq; diff --git a/rtc/AutoBalancer/CMakeLists.txt b/rtc/AutoBalancer/CMakeLists.txt index 76d3149ce01..7f959e0f66d 100644 --- a/rtc/AutoBalancer/CMakeLists.txt +++ b/rtc/AutoBalancer/CMakeLists.txt @@ -33,7 +33,7 @@ add_test(testGaitGeneratorTest11 testGaitGenerator --test11 --use-gnuplot false) add_test(testGaitGeneratorTest12 testGaitGenerator --test12 --use-gnuplot false) install(TARGETS ${target} - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib + RUNTIME DESTINATION bin CONFIGURATIONS Release Debug + LIBRARY DESTINATION lib CONFIGURATIONS Release Debug ) diff --git a/rtc/AutoBalancer/GaitGenerator.h b/rtc/AutoBalancer/GaitGenerator.h index e39e77ff191..7f56a295707 100644 --- a/rtc/AutoBalancer/GaitGenerator.h +++ b/rtc/AutoBalancer/GaitGenerator.h @@ -279,7 +279,7 @@ namespace rats zmp_weight_interpolator->clear(); double zmp_weight_initial_value[4] = {zmp_weight_map[RLEG], zmp_weight_map[LLEG], zmp_weight_map[RARM], zmp_weight_map[LARM]}; zmp_weight_interpolator->set(zmp_weight_initial_value); - zmp_weight_interpolator->setGoal(zmp_weight_array, 2.0, true); + zmp_weight_interpolator->go(zmp_weight_array, 2.0, true); } else { std::cerr << "zmp_weight_map cannot be set because interpolating." << std::endl; } @@ -311,10 +311,10 @@ namespace rats hrp::Vector3 pos, vel, acc; // [m], [m/s], [m/s^2] double dt; // [s] // Implement hoffarbib to configure remain_time; - void hoffarbib_interpolation (const double tmp_remain_time, const hrp::Vector3& tmp_goal, const hrp::Vector3 tmp_goal_vel = hrp::Vector3::Zero(), const hrp::Vector3 tmp_goal_acc = hrp::Vector3::Zero()) + void hoffarbib_interpolation (const double tmp_remain_time, const hrp::Vector3& tmp_goal) { - hrp::Vector3 jerk = (-9.0/ tmp_remain_time) * (acc - tmp_goal_acc / 3.0) + - (-36.0 / (tmp_remain_time * tmp_remain_time)) * (tmp_goal_vel * 2.0 / 3.0 + vel) + + hrp::Vector3 jerk = (-9.0/ tmp_remain_time) * acc + + (-36.0 / (tmp_remain_time * tmp_remain_time)) * vel + (60.0 / (tmp_remain_time * tmp_remain_time * tmp_remain_time)) * (tmp_goal - pos); acc = acc + dt * jerk; vel = vel + dt * acc; From 00b702ba4e5db86b46d2f91e2c926d6973c00537 Mon Sep 17 00:00:00 2001 From: ishiguro Date: Wed, 8 Jun 2016 13:56:18 +0900 Subject: [PATCH 002/217] test for human tracker --- idl/AutoBalancerService.idl | 7 + python/hrpsys_config.py | 8 + rtc/AutoBalancer/AutoBalancer.cpp | 233 ++++++++++-------- rtc/AutoBalancer/AutoBalancer.h | 8 +- rtc/AutoBalancer/AutoBalancerService_impl.cpp | 7 +- rtc/AutoBalancer/AutoBalancerService_impl.h | 1 + 6 files changed, 164 insertions(+), 100 deletions(-) diff --git a/idl/AutoBalancerService.idl b/idl/AutoBalancerService.idl index ccbc974b5bc..a278d03bc69 100644 --- a/idl/AutoBalancerService.idl +++ b/idl/AutoBalancerService.idl @@ -413,5 +413,12 @@ module OpenHRP * @return true if set successfully, false otherwise */ boolean releaseEmergencyStop(); + + /** + * @brief Stop stepping immediately. + * @param + * @return true if set successfully, false otherwise + */ + boolean startHumanSyncAfter5sec(); }; }; diff --git a/python/hrpsys_config.py b/python/hrpsys_config.py index aaef962ff4f..f6c1e1db542 100755 --- a/python/hrpsys_config.py +++ b/python/hrpsys_config.py @@ -2080,6 +2080,14 @@ def setFootStepsWithParam(self, footstep, stepparams, overwrite_fs_idx = 0): ''' self.abc_svc.setFootStepsWithParam(footstep, stepparams, overwrite_fs_idx) + + def startHumanSyncAfter5sec(self): + '''!@brief + startHumanSyncAfter5sec mode + ''' + self.abc_svc.startHumanSyncAfter5sec() + + # ## # ## initialize # ## diff --git a/rtc/AutoBalancer/AutoBalancer.cpp b/rtc/AutoBalancer/AutoBalancer.cpp index 454f9c3b3cc..d3adac1a290 100644 --- a/rtc/AutoBalancer/AutoBalancer.cpp +++ b/rtc/AutoBalancer/AutoBalancer.cpp @@ -17,13 +17,13 @@ #include "hrpsys/util/Hrpsys.h" //SHM関連 -#include -#include -#include -#include -#include -int shmid; -key_t key; +//#include +//#include +//#include +//#include +//#include +//int shmid; +//key_t key; typedef struct{ double com[3]; double rfpos[3]; @@ -35,8 +35,10 @@ typedef struct{ double zmp[3]; bool startsync; }humanpose_t; -humanpose_t *humanpose; +humanpose_t humanpose; humanpose_t filt_hp_data,hp_data_old; +bool startCountdownForHumanSync = false; +bool HumanSyncOn = false; typedef coil::Guard Guard; @@ -73,6 +75,8 @@ AutoBalancer::AutoBalancer(RTC::Manager* manager) m_emergencySignalIn("emergencySignal", m_emergencySignal), //ishiguro m_htzmpIn("htzmpIn", m_htzmp), + m_htrfwIn("htrfwIn", m_htrfw), + m_htlfwIn("htlfwIn", m_htlfw), m_htcomIn("htcomIn", m_htcom), m_htrfIn("htrfIn", m_htrf), m_htlfIn("htlfIn", m_htlf), @@ -122,6 +126,8 @@ RTC::ReturnCode_t AutoBalancer::onInitialize() addInPort("emergencySignal", m_emergencySignalIn); //ishiguro addInPort("htzmpIn", m_htzmpIn); + addInPort("htrfwIn", m_htrfwIn); + addInPort("htlfwIn", m_htlfwIn); addInPort("htcomIn", m_htcomIn); addInPort("htrfIn", m_htrfIn); addInPort("htlfIn", m_htlfIn); @@ -180,6 +186,9 @@ RTC::ReturnCode_t AutoBalancer::onInitialize() qorg.resize(m_robot->numJoints()); qrefv.resize(m_robot->numJoints()); m_baseTform.data.length(12); + //ishiguro + m_htrfw.data.length(6); + m_htlfw.data.length(6); control_mode = MODE_IDLE; loop = 0; @@ -377,28 +386,28 @@ RTC::ReturnCode_t AutoBalancer::onInitialize() ik_error_debug_print_freq = static_cast(0.2/m_dt); // once per 0.2 [s] - //SHM my2 - if((key = ftok("/tmp/shm.dat", 'R')) == -1){ - printf("WARN: ftok() failed retry\n"); - system("touch /tmp/shm.dat"); - if((key = ftok("/tmp/shm.dat", 'R')) == -1){ - perror("ERROR: ftok() failed exit\n"); - return RTC::RTC_ERROR; - } - } - if((shmid = shmget(key, sizeof(humanpose_t), 0666)) < 0){ - printf("WARN: shmget() failed retry\n"); - shmid = shmget(key, sizeof(humanpose_t), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | IPC_CREAT); - if (shmid == -1) { - perror("ERROR: shmget() failed exit\n"); - return RTC::RTC_ERROR; - } - } - humanpose = (humanpose_t *)shmat(shmid, (void *)0, 0); - if (humanpose == NULL) { - perror("shmat"); - return RTC::RTC_ERROR; - } +// //SHM my2 +// if((key = ftok("/tmp/shm.dat", 'R')) == -1){ +// printf("WARN: ftok() failed retry\n"); +// system("touch /tmp/shm.dat"); +// if((key = ftok("/tmp/shm.dat", 'R')) == -1){ +// perror("ERROR: ftok() failed exit\n"); +// return RTC::RTC_ERROR; +// } +// } +// if((shmid = shmget(key, sizeof(humanpose_t), 0666)) < 0){ +// printf("WARN: shmget() failed retry\n"); +// shmid = shmget(key, sizeof(humanpose_t), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | IPC_CREAT); +// if (shmid == -1) { +// perror("ERROR: shmget() failed exit\n"); +// return RTC::RTC_ERROR; +// } +// } +// humanpose = (humanpose_t *)shmat(shmid, (void *)0, 0); +// if (humanpose == NULL) { +// perror("shmat"); +// return RTC::RTC_ERROR; +// } return RTC::RTC_OK; } @@ -408,8 +417,8 @@ RTC::ReturnCode_t AutoBalancer::onInitialize() RTC::ReturnCode_t AutoBalancer::onFinalize() { //SHM - if (shmdt(humanpose) == -1){ perror("shmdt"); } - if (shmctl(shmid, IPC_RMID, 0) == -1){ perror("shmctl"); } +// if (shmdt(humanpose) == -1){ perror("shmdt"); } +// if (shmctl(shmid, IPC_RMID, 0) == -1){ perror("shmctl"); } delete zmp_offset_interpolator; delete transition_interpolator; @@ -510,39 +519,51 @@ RTC::ReturnCode_t AutoBalancer::onExecute(RTC::UniqueId ec_id) //for human tracker if (m_htzmpIn.isNew()){ m_htzmpIn.read(); - input_htzmp(0) = m_htzmp.data.x; - input_htzmp(1) = m_htzmp.data.y; - input_htzmp(2) = m_htzmp.data.z; +// humanpose.zmp[0] = m_htzmp.data.x;//zmpはこっちで計算 +// humanpose.zmp[1] = m_htzmp.data.y; +// humanpose.zmp[2] = m_htzmp.data.z; + } + if (m_htrfwIn.isNew()){ + m_htrfwIn.read(); + for(int i=0;i<6;i++){ + humanpose.rfwrench[i] = m_htrfw.data[i]; + } + } + if (m_htlfwIn.isNew()){ + m_htlfwIn.read(); + for(int i=0;i<6;i++){ + humanpose.lfwrench[i] = m_htlfw.data[i]; + } } if (m_htcomIn.isNew()){ m_htcomIn.read(); - input_htcom(0) = m_htcom.data.x; - input_htcom(1) = m_htcom.data.y; - input_htcom(2) = m_htcom.data.z; + humanpose.com[0] = m_htcom.data.x; + humanpose.com[1] = m_htcom.data.y; + humanpose.com[2] = m_htcom.data.z; } if (m_htrfIn.isNew()){ m_htrfIn.read(); - input_htrf(0) = m_htrf.data.x; - input_htrf(1) = m_htrf.data.y; - input_htrf(2) = m_htrf.data.z; + humanpose.rfpos[0] = m_htrf.data.x; + humanpose.rfpos[1] = m_htrf.data.y; + humanpose.rfpos[2] = m_htrf.data.z; } if (m_htlfIn.isNew()){ m_htlfIn.read(); - input_htlf(0) = m_htlf.data.x; - input_htlf(1) = m_htlf.data.y; - input_htlf(2) = m_htlf.data.z; + humanpose.lfpos[0] = m_htlf.data.x; + humanpose.lfpos[1] = m_htlf.data.y; + humanpose.lfpos[2] = m_htlf.data.z; } if (m_htrhIn.isNew()){ m_htrhIn.read(); - input_htrh(0) = m_htrh.data.x; - input_htrh(1) = m_htrh.data.y; - input_htrh(2) = m_htrh.data.z; + humanpose.rhpos[0] = m_htrh.data.x; + humanpose.rhpos[1] = m_htrh.data.y; + humanpose.rhpos[2] = m_htrh.data.z; } if (m_htlhIn.isNew()){ m_htlhIn.read(); - input_htlh(0) = m_htlh.data.x; - input_htlh(1) = m_htlh.data.y; - input_htlh(2) = m_htlh.data.z; + humanpose.lhpos[0] = m_htlh.data.x; + humanpose.lhpos[1] = m_htlh.data.y; + humanpose.lhpos[2] = m_htlh.data.z; } Guard guard(m_mutex); @@ -640,32 +661,33 @@ RTC::ReturnCode_t AutoBalancer::onExecute(RTC::UniqueId ec_id) const double F_H_OFFSET = 0.03; const double rfpos[3] = {0,-0.1,0},lfpos[3] = {0,0.1,0}; - if( humanpose->rfwrench[2] > 1.0e-6 ){ - rfzmp[0] = ( -humanpose->rfwrench[4] - humanpose->rfwrench[0] * F_H_OFFSET + humanpose->rfwrench[2] * 0 ) / humanpose->rfwrench[2]; - rfzmp[1] = ( humanpose->rfwrench[3] - humanpose->rfwrench[1] * F_H_OFFSET + humanpose->rfwrench[2] * 0 ) / humanpose->rfwrench[2]; + if( humanpose.rfwrench[2] > 1.0e-6 ){ + rfzmp[0] = ( -humanpose.rfwrench[4] - humanpose.rfwrench[0] * F_H_OFFSET + humanpose.rfwrench[2] * 0 ) / humanpose.rfwrench[2] + rfpos[0]; + rfzmp[1] = ( humanpose.rfwrench[3] - humanpose.rfwrench[1] * F_H_OFFSET + humanpose.rfwrench[2] * 0 ) / humanpose.rfwrench[2] + rfpos[1]; } - if( humanpose->lfwrench[2] > 1.0e-6 ){ - lfzmp[0] = ( -humanpose->lfwrench[4] - humanpose->lfwrench[0] * F_H_OFFSET + humanpose->lfwrench[2] * 0 ) / humanpose->lfwrench[2]; - lfzmp[1] = ( humanpose->lfwrench[3] - humanpose->lfwrench[1] * F_H_OFFSET + humanpose->lfwrench[2] * 0 ) / humanpose->lfwrench[2]; + if( humanpose.lfwrench[2] > 1.0e-6 ){ + lfzmp[0] = ( -humanpose.lfwrench[4] - humanpose.lfwrench[0] * F_H_OFFSET + humanpose.lfwrench[2] * 0 ) / humanpose.lfwrench[2] + lfpos[0]; + lfzmp[1] = ( humanpose.lfwrench[3] - humanpose.lfwrench[1] * F_H_OFFSET + humanpose.lfwrench[2] * 0 ) / humanpose.lfwrench[2] + lfpos[1]; } - humanpose->zmp[0] = ( rfzmp[0]*humanpose->rfwrench[2] + lfzmp[0]*humanpose->lfwrench[2] ) / ( humanpose->rfwrench[2] + humanpose->lfwrench[2] ); - humanpose->zmp[1] = ( rfzmp[1]*humanpose->rfwrench[2] + lfzmp[1]*humanpose->lfwrench[2] ) / ( humanpose->rfwrench[2] + humanpose->lfwrench[2]); - humanpose->zmp[2] = 0; + //humanpose.zmpをrfw,lfwから計算して上書き -// for(int i=0;i<6;i++)cout<<"rfw["<rfwrench[i]; -// for(int i=0;i<6;i++)cout<<"lfw["<lfwrench[i]; -// for(int i=0;i<2;i++)cout<<"zmp["<zmp[i]; + if( humanpose.rfwrench[2] > 1.0e-6 || humanpose.lfwrench[2] > 1.0e-6 ){ + humanpose.zmp[0] = ( rfzmp[0]*humanpose.rfwrench[2] + lfzmp[0]*humanpose.lfwrench[2] ) / ( humanpose.rfwrench[2] + humanpose.lfwrench[2]); + humanpose.zmp[1] = ( rfzmp[1]*humanpose.rfwrench[2] + lfzmp[1]*humanpose.lfwrench[2] ) / ( humanpose.rfwrench[2] + humanpose.lfwrench[2]); + humanpose.zmp[2] = 0; + }else{ + humanpose.zmp[0] = 0; humanpose.zmp[1] = 0; humanpose.zmp[2] = 0; + } //debug表示 // printf("[L] %+06.1f,%+06.1f,%+06.1f,%+06.1f,%+06.1f,%+06.1f [R] %+06.1f,%+06.1f,%+06.1f,%+06.1f,%+06.1f,%+06.1f [ZMP] %+06.3f,%+06.3f\n", -// humanpose->lfwrench[0],humanpose->lfwrench[1],humanpose->lfwrench[2],humanpose->lfwrench[3],humanpose->lfwrench[4],humanpose->lfwrench[5], -// humanpose->rfwrench[0],humanpose->rfwrench[1],humanpose->rfwrench[2],humanpose->rfwrench[3],humanpose->rfwrench[4],humanpose->rfwrench[5], -// humanpose->zmp[0],humanpose->zmp[1]); - humanpose->startsync = true;//test - if(humanpose->startsync){ +// humanpose.lfwrench[0],humanpose.lfwrench[1],humanpose.lfwrench[2],humanpose.lfwrench[3],humanpose.lfwrench[4],humanpose.lfwrench[5], +// humanpose.rfwrench[0],humanpose.rfwrench[1],humanpose.rfwrench[2],humanpose.rfwrench[3],humanpose.rfwrench[4],humanpose.rfwrench[5], +// humanpose.zmp[0],humanpose.zmp[1]); + if(HumanSyncOn){ //ZMP上書き -// m_zmp.data.x = humanpose->zmp[0]*0.5 - filt_hp_data.com[0];// - m_zmp.data.y = filt_hp_data.zmp[1] - filt_hp_data.com[1];// +// m_zmp.data.x = humanpose.zmp[0]*0.5 - filt_hp_data.com[0];// + m_zmp.data.y = filt_hp_data.zmp[1] - filt_hp_data.com[1];//test // COM上書き // m_cog.data.x = 0.0558423 + filt_hp_data.com[0]; m_cog.data.y = filt_hp_data.com[1]; @@ -1059,13 +1081,12 @@ void AutoBalancer::fixLegToCoords (const hrp::Vector3& fix_pos, const hrp::Matri static bool moveleft = false; bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) { -// cout<<"****************** test ********************"<startsync){ + if(HumanSyncOn){ if(param.target_link->name == "RLEG_JOINT5"){ - if(humanpose->rfwrench[2] < 20.0 && humanpose->lfwrench[2] > 20.0){ -// if(humanpose->rfwrench[2] < 20.0){ + if(humanpose.rfwrench[2] < 20.0 && humanpose.lfwrench[2] > 20.0){ +// if(humanpose.rfwrench[2] < 20.0){ if(rfuplevel < 100){ rfuplevel++; filt_hp_data.rfpos[2] = 0.025 - 0.025*cos(M_PI*rfuplevel/100); @@ -1084,8 +1105,8 @@ bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) param.target_p0(2) = 0.1 + filt_hp_data.rfpos[2]; } if(param.target_link->name == "LLEG_JOINT5"){ - if(humanpose->lfwrench[2] < 20.0 && humanpose->rfwrench[2] > 20.0){ -// if(humanpose->lfwrench[2] < 20.0){ + if(humanpose.lfwrench[2] < 20.0 && humanpose.rfwrench[2] > 20.0){ +// if(humanpose.lfwrench[2] < 20.0){ if(lfuplevel < 100){ lfuplevel++; filt_hp_data.lfpos[2] = 0.025 - 0.025*cos(M_PI*lfuplevel/100); @@ -1164,30 +1185,42 @@ void AutoBalancer::solveLimbIK () m_robot->rootLink()->p = m_robot->rootLink()->p + -1 * move_base_gain * dif_cog; m_robot->rootLink()->R = target_root_R; //mytest - #define MAXVEL 0.002 - - for(int i=0;i<3;i++){ -// filt_hp_data.com[i] = 0.99*filt_hp_data.com[i] + 0.01*(humanpose->com[i]); -// filt_hp_data.rfpos[i] = 0.99*filt_hp_data.rfpos[i] + 0.01*(humanpose->rfpos[i]);//足ロック -// filt_hp_data.lfpos[i] = 0.99*filt_hp_data.lfpos[i] + 0.01*(humanpose->lfpos[i]);//足ロック -// filt_hp_data.rhpos[i] = 0.99*filt_hp_data.rhpos[i] + 0.01*(humanpose->rhpos[i]); -// filt_hp_data.lhpos[i] = 0.99*filt_hp_data.lhpos[i] + 0.01*(humanpose->lhpos[i]); -// filt_hp_data.zmp[i] = 0.99*filt_hp_data.zmp[i] + 0.01*(humanpose->zmp[i]); - - filt_hp_data.zmp[i] = 0.99*filt_hp_data.zmp[i] + 0.01*(input_htzmp(i)); - filt_hp_data.com[i] = 0.99*filt_hp_data.com[i] + 0.01*(input_htcom(i)); - filt_hp_data.rfpos[i] = 0.99*filt_hp_data.rfpos[i] + 0.01*(input_htrf(i)); - filt_hp_data.lfpos[i] = 0.99*filt_hp_data.lfpos[i] + 0.01*(input_htlf(i)); - filt_hp_data.rhpos[i] = 0.99*filt_hp_data.rhpos[i] + 0.01*(input_htrh(i)); - filt_hp_data.lhpos[i] = 0.99*filt_hp_data.lhpos[i] + 0.01*(input_htlh(i)); - + #define MAXVEL 0.004 + + static humanpose_t init_humanpose; + static int HumanSyncCountdownNum = 5 * (1/m_dt); + if(startCountdownForHumanSync){ + if(HumanSyncCountdownNum == 0){ + HumanSyncOn = true; + }else{ + HumanSyncCountdownNum--; + } + } + if(HumanSyncOn){ + for(int i=0;i<3;i++){ + filt_hp_data.zmp[i] = 0.99*filt_hp_data.zmp[i] + 0.01*(humanpose.zmp[i]); + filt_hp_data.com[i] = 0.99*filt_hp_data.com[i] + 0.01*(humanpose.com[i] - init_humanpose.com[i]); + filt_hp_data.rfwrench[i] = 0.99*filt_hp_data.rfwrench[i] + 0.01*(humanpose.rfwrench[i]); + filt_hp_data.lfwrench[i] = 0.99*filt_hp_data.lfwrench[i] + 0.01*(humanpose.lfwrench[i]); + // filt_hp_data.rfpos[i] = 0.99*filt_hp_data.rfpos[i] + 0.01*(humanpose.rfpos[i] - init_humanpose.rfpos[i]);//足ロック + // filt_hp_data.lfpos[i] = 0.99*filt_hp_data.lfpos[i] + 0.01*(humanpose.lfpos[i] - init_humanpose.lfpos[i]);//足ロック + filt_hp_data.rhpos[i] = 0.99*filt_hp_data.rhpos[i] + 0.01*(humanpose.rhpos[i] - init_humanpose.rhpos[i]); + filt_hp_data.lhpos[i] = 0.99*filt_hp_data.lhpos[i] + 0.01*(humanpose.lhpos[i] - init_humanpose.lhpos[i]); + + if(filt_hp_data.com[i] - hp_data_old.com[i] > MAXVEL)filt_hp_data.com[i] = hp_data_old.com[i] + MAXVEL; + if(filt_hp_data.com[i] - hp_data_old.com[i] < -MAXVEL)filt_hp_data.com[i] = hp_data_old.com[i] - MAXVEL; + hp_data_old.com[i] = filt_hp_data.com[i]; + } - if(filt_hp_data.com[i] - hp_data_old.com[i] > MAXVEL)filt_hp_data.com[i] = hp_data_old.com[i] + MAXVEL; - if(filt_hp_data.com[i] - hp_data_old.com[i] < -MAXVEL)filt_hp_data.com[i] = hp_data_old.com[i] - MAXVEL; - hp_data_old.com[i] = filt_hp_data.com[i]; + printf("[COM] %+06.3f,%+06.3f,%+06.3f [ZMP] %+06.3f,%+06.3f\n", filt_hp_data.com[0],filt_hp_data.com[1],filt_hp_data.com[2],filt_hp_data.zmp[0],filt_hp_data.zmp[1],filt_hp_data.zmp[2]); + }else{ + for(int i=0;i<3;i++)init_humanpose.com[i] = humanpose.com[i]; + for(int i=0;i<3;i++)init_humanpose.rfpos[i] = humanpose.rfpos[i]; + for(int i=0;i<3;i++)init_humanpose.lfpos[i] = humanpose.lfpos[i]; + for(int i=0;i<3;i++)init_humanpose.rhpos[i] = humanpose.rhpos[i]; + for(int i=0;i<3;i++)init_humanpose.lhpos[i] = humanpose.lhpos[i]; } -// cout<<"COM"<calcCM()[0]<<","<calcCM()[1]<<","<calcCM()[2]<rootLink()->p(0) = 0.0558423 + filt_hp_data.com[0]; @@ -1259,6 +1292,14 @@ static int movelcnt; } */ + +bool AutoBalancer::startHumanSyncAfter5sec() +{ + std::cerr << "[" << m_profile.instance_name << "] start HumanSync after 5 sec" << std::endl; + startCountdownForHumanSync = true; + return true; +} + void AutoBalancer::startABCparam(const OpenHRP::AutoBalancerService::StrSequence& limbs) { std::cerr << "[" << m_profile.instance_name << "] start auto balancer mode" << std::endl; diff --git a/rtc/AutoBalancer/AutoBalancer.h b/rtc/AutoBalancer/AutoBalancer.h index e8214e339b9..989a2f2f800 100644 --- a/rtc/AutoBalancer/AutoBalancer.h +++ b/rtc/AutoBalancer/AutoBalancer.h @@ -110,6 +110,7 @@ class AutoBalancer bool getRemainingFootstepSequence(OpenHRP::AutoBalancerService::FootstepSequence_out o_footstep, CORBA::Long& o_current_fs_idx); bool getGoPosFootstepsSequence(const double& x, const double& y, const double& th, OpenHRP::AutoBalancerService::FootstepsSequence_out o_footstep); bool releaseEmergencyStop(); + bool startHumanSyncAfter5sec(); protected: // Configuration variable declaration @@ -138,6 +139,10 @@ class AutoBalancer //for human tracker TimedPoint3D m_htzmp; InPort m_htzmpIn; + TimedDoubleSeq m_htrfw; + InPort m_htrfwIn; + TimedDoubleSeq m_htlfw; + InPort m_htlfwIn; TimedPoint3D m_htcom; InPort m_htcomIn; TimedPoint3D m_htrf; @@ -264,9 +269,6 @@ class AutoBalancer enum {MODE_NO_FORCE, MODE_REF_FORCE} use_force; std::vector ref_forces; - //for human tracker - hrp::Vector3 input_htzmp, input_htcom, input_htrf, input_htlf, input_htrh, input_htlh; - unsigned int m_debugLevel; bool is_legged_robot, is_stop_mode, has_ik_failed, is_hand_fix_mode, is_hand_fix_initial; int loop, ik_error_debug_print_freq; diff --git a/rtc/AutoBalancer/AutoBalancerService_impl.cpp b/rtc/AutoBalancer/AutoBalancerService_impl.cpp index e4faf4ab27e..e2b75b3c99f 100644 --- a/rtc/AutoBalancer/AutoBalancerService_impl.cpp +++ b/rtc/AutoBalancer/AutoBalancerService_impl.cpp @@ -113,5 +113,10 @@ CORBA::Boolean AutoBalancerService_impl::releaseEmergencyStop() void AutoBalancerService_impl::autobalancer(AutoBalancer *i_autobalancer) { m_autobalancer = i_autobalancer; -} +} + +CORBA::Boolean AutoBalancerService_impl::startHumanSyncAfter5sec() +{ + return m_autobalancer->startHumanSyncAfter5sec(); +}; diff --git a/rtc/AutoBalancer/AutoBalancerService_impl.h b/rtc/AutoBalancer/AutoBalancerService_impl.h index c6cfe9b04bf..cab43ea2da5 100644 --- a/rtc/AutoBalancer/AutoBalancerService_impl.h +++ b/rtc/AutoBalancer/AutoBalancerService_impl.h @@ -34,6 +34,7 @@ class AutoBalancerService_impl CORBA::Boolean getRemainingFootstepSequence(OpenHRP::AutoBalancerService::FootstepSequence_out o_footstep , CORBA::Long& o_current_fs_idx); CORBA::Boolean getGoPosFootstepsSequence(CORBA::Double x, CORBA::Double y, CORBA::Double th, OpenHRP::AutoBalancerService::FootstepsSequence_out o_footstep); CORBA::Boolean releaseEmergencyStop(); + CORBA::Boolean startHumanSyncAfter5sec(); // // void autobalancer(AutoBalancer *i_autobalancer); From 125286d2b29019e68e9af4e1ca4c758db555107e Mon Sep 17 00:00:00 2001 From: ishiguro Date: Wed, 15 Jun 2016 17:34:38 +0900 Subject: [PATCH 003/217] modify foot ik jump for CHIDORI --- python/hrpsys_config.py | 7 ---- rtc/AutoBalancer/AutoBalancer.cpp | 41 ++++++++++++++----- rtc/AutoBalancer/AutoBalancer.h | 1 + rtc/AutoBalancer/AutoBalancerService_impl.cpp | 5 +++ rtc/AutoBalancer/AutoBalancerService_impl.h | 1 + rtc/Stabilizer/Stabilizer.cpp | 2 +- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/python/hrpsys_config.py b/python/hrpsys_config.py index f6c1e1db542..0f121447aad 100755 --- a/python/hrpsys_config.py +++ b/python/hrpsys_config.py @@ -2081,13 +2081,6 @@ def setFootStepsWithParam(self, footstep, stepparams, overwrite_fs_idx = 0): self.abc_svc.setFootStepsWithParam(footstep, stepparams, overwrite_fs_idx) - def startHumanSyncAfter5sec(self): - '''!@brief - startHumanSyncAfter5sec mode - ''' - self.abc_svc.startHumanSyncAfter5sec() - - # ## # ## initialize # ## diff --git a/rtc/AutoBalancer/AutoBalancer.cpp b/rtc/AutoBalancer/AutoBalancer.cpp index d3adac1a290..deba4531776 100644 --- a/rtc/AutoBalancer/AutoBalancer.cpp +++ b/rtc/AutoBalancer/AutoBalancer.cpp @@ -1079,10 +1079,11 @@ void AutoBalancer::fixLegToCoords (const hrp::Vector3& fix_pos, const hrp::Matri } static bool moveleft = false; +static bool ht_first_call = true; +hrp::Vector3 rfinitpos,lfinitpos; bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) { static int rfuplevel,lfuplevel; - if(HumanSyncOn){ if(param.target_link->name == "RLEG_JOINT5"){ if(humanpose.rfwrench[2] < 20.0 && humanpose.lfwrench[2] > 20.0){ @@ -1100,9 +1101,9 @@ bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) //if(filt_hp_data.rfpos[2] == 0.0)moveleft = true;//歩行遊び } } - param.target_p0(0) = 0.0 + filt_hp_data.rfpos[0]; - param.target_p0(1) = -0.1 + filt_hp_data.rfpos[1]; - param.target_p0(2) = 0.1 + filt_hp_data.rfpos[2]; + param.target_p0(0) = rfinitpos(0) + filt_hp_data.rfpos[0]; + param.target_p0(1) = rfinitpos(1) + filt_hp_data.rfpos[1]; + param.target_p0(2) = rfinitpos(2) + filt_hp_data.rfpos[2]; } if(param.target_link->name == "LLEG_JOINT5"){ if(humanpose.lfwrench[2] < 20.0 && humanpose.rfwrench[2] > 20.0){ @@ -1120,9 +1121,9 @@ bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) //if(filt_hp_data.lfpos[2] == 0.0)moveleft = true;//歩行遊び } } - param.target_p0(0) = 0.0 + filt_hp_data.lfpos[0]; - param.target_p0(1) = 0.1 + filt_hp_data.lfpos[1]; - param.target_p0(2) = 0.1 + filt_hp_data.lfpos[2]; + param.target_p0(0) = lfinitpos(0) + filt_hp_data.lfpos[0]; + param.target_p0(1) = lfinitpos(1) + filt_hp_data.lfpos[1]; + param.target_p0(2) = lfinitpos(2) + filt_hp_data.lfpos[2]; } if(param.target_link->name == "RARM_JOINT7"){ param.target_p0(0) = 0.151 + filt_hp_data.rhpos[0]; @@ -1190,8 +1191,10 @@ void AutoBalancer::solveLimbIK () static humanpose_t init_humanpose; static int HumanSyncCountdownNum = 5 * (1/m_dt); if(startCountdownForHumanSync){ + printf("Start Count Down for HumanSync [%d]\r", HumanSyncCountdownNum); if(HumanSyncCountdownNum == 0){ HumanSyncOn = true; + startCountdownForHumanSync = false; }else{ HumanSyncCountdownNum--; } @@ -1213,19 +1216,28 @@ void AutoBalancer::solveLimbIK () hp_data_old.com[i] = filt_hp_data.com[i]; } - printf("[COM] %+06.3f,%+06.3f,%+06.3f [ZMP] %+06.3f,%+06.3f\n", filt_hp_data.com[0],filt_hp_data.com[1],filt_hp_data.com[2],filt_hp_data.zmp[0],filt_hp_data.zmp[1],filt_hp_data.zmp[2]); + if(loop%100==0)printf("[COM] %+06.3f,%+06.3f,%+06.3f [ZMP] %+06.3f,%+06.3f\n", filt_hp_data.com[0],filt_hp_data.com[1],filt_hp_data.com[2],filt_hp_data.zmp[0],filt_hp_data.zmp[1],filt_hp_data.zmp[2]); + if(ht_first_call){ht_first_call=false; + rfinitpos = ikp["rleg"].target_p0; + lfinitpos = ikp["lleg"].target_p0; + } }else{ for(int i=0;i<3;i++)init_humanpose.com[i] = humanpose.com[i]; for(int i=0;i<3;i++)init_humanpose.rfpos[i] = humanpose.rfpos[i]; for(int i=0;i<3;i++)init_humanpose.lfpos[i] = humanpose.lfpos[i]; for(int i=0;i<3;i++)init_humanpose.rhpos[i] = humanpose.rhpos[i]; for(int i=0;i<3;i++)init_humanpose.lhpos[i] = humanpose.lhpos[i]; + if(loop%100==0)printf("[pre-COM] %+06.3f,%+06.3f,%+06.3f [pre-ZMP] %+06.3f,%+06.3f\n", humanpose.com[0],humanpose.com[1],humanpose.com[2],humanpose.zmp[0],humanpose.zmp[1],humanpose.zmp[2]); + } filt_hp_data.com[0] = 0.0;//重心前方向ロック - m_robot->rootLink()->p(0) = 0.0558423 + filt_hp_data.com[0]; - m_robot->rootLink()->p(1) = 0+ filt_hp_data.com[1];//safetest - m_robot->rootLink()->p(2) = 0.976372 + filt_hp_data.com[2]; +// m_robot->rootLink()->p(0) = 0.0558423 + filt_hp_data.com[0]; +// m_robot->rootLink()->p(1) = 0+ filt_hp_data.com[1];//safetest +// m_robot->rootLink()->p(2) = 0.976372 + filt_hp_data.com[2]; + m_robot->rootLink()->p(0) += filt_hp_data.com[0]; + m_robot->rootLink()->p(1) += filt_hp_data.com[1];//safetest + m_robot->rootLink()->p(2) += filt_hp_data.com[2]; static int movelcnt; if(moveleft){ @@ -1300,6 +1312,13 @@ bool AutoBalancer::startHumanSyncAfter5sec() return true; } +bool AutoBalancer::stopHumanSync() +{ + std::cerr << "[" << m_profile.instance_name << "] stop HumanSync Now" << std::endl; + HumanSyncOn = false; + return true; +} + void AutoBalancer::startABCparam(const OpenHRP::AutoBalancerService::StrSequence& limbs) { std::cerr << "[" << m_profile.instance_name << "] start auto balancer mode" << std::endl; diff --git a/rtc/AutoBalancer/AutoBalancer.h b/rtc/AutoBalancer/AutoBalancer.h index 989a2f2f800..ff748dfff0e 100644 --- a/rtc/AutoBalancer/AutoBalancer.h +++ b/rtc/AutoBalancer/AutoBalancer.h @@ -111,6 +111,7 @@ class AutoBalancer bool getGoPosFootstepsSequence(const double& x, const double& y, const double& th, OpenHRP::AutoBalancerService::FootstepsSequence_out o_footstep); bool releaseEmergencyStop(); bool startHumanSyncAfter5sec(); + bool stopHumanSync(); protected: // Configuration variable declaration diff --git a/rtc/AutoBalancer/AutoBalancerService_impl.cpp b/rtc/AutoBalancer/AutoBalancerService_impl.cpp index e2b75b3c99f..0c899349cd8 100644 --- a/rtc/AutoBalancer/AutoBalancerService_impl.cpp +++ b/rtc/AutoBalancer/AutoBalancerService_impl.cpp @@ -120,3 +120,8 @@ CORBA::Boolean AutoBalancerService_impl::startHumanSyncAfter5sec() return m_autobalancer->startHumanSyncAfter5sec(); }; +CORBA::Boolean AutoBalancerService_impl::stopHumanSync() +{ + return m_autobalancer->stopHumanSync(); +}; + diff --git a/rtc/AutoBalancer/AutoBalancerService_impl.h b/rtc/AutoBalancer/AutoBalancerService_impl.h index cab43ea2da5..01c0f4977b1 100644 --- a/rtc/AutoBalancer/AutoBalancerService_impl.h +++ b/rtc/AutoBalancer/AutoBalancerService_impl.h @@ -35,6 +35,7 @@ class AutoBalancerService_impl CORBA::Boolean getGoPosFootstepsSequence(CORBA::Double x, CORBA::Double y, CORBA::Double th, OpenHRP::AutoBalancerService::FootstepsSequence_out o_footstep); CORBA::Boolean releaseEmergencyStop(); CORBA::Boolean startHumanSyncAfter5sec(); + CORBA::Boolean stopHumanSync(); // // void autobalancer(AutoBalancer *i_autobalancer); diff --git a/rtc/Stabilizer/Stabilizer.cpp b/rtc/Stabilizer/Stabilizer.cpp index b6acbf9fbd9..b5175201764 100644 --- a/rtc/Stabilizer/Stabilizer.cpp +++ b/rtc/Stabilizer/Stabilizer.cpp @@ -1320,12 +1320,12 @@ void Stabilizer::calcTPCC() { + k_tpcc_x[i] * transition_smooth_gain * dcog(i); newcog(i) = uu * dt + cog(i); } - moveBasePosRotForBodyRPYControl (); // target at ee => target at link-origin hrp::Vector3 target_link_p[stikp.size()]; hrp::Matrix33 target_link_R[stikp.size()]; + for (size_t i = 0; i < stikp.size(); i++) { rats::rotm3times(target_link_R[i], target_ee_R[i], stikp[i].localR.transpose()); target_link_p[i] = target_ee_p[i] - target_ee_R[i] * stikp[i].localCOPPos; From 427febb8da1469fbd8c8fc8f52d4ee0ff316eb7c Mon Sep 17 00:00:00 2001 From: ishiguro Date: Wed, 15 Jun 2016 18:48:53 +0900 Subject: [PATCH 004/217] add service stopHumanSync --- idl/AutoBalancerService.idl | 1 + rtc/AutoBalancer/AutoBalancer.cpp | 38 +++++++++++++++---------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/idl/AutoBalancerService.idl b/idl/AutoBalancerService.idl index a278d03bc69..071bc5d3f62 100644 --- a/idl/AutoBalancerService.idl +++ b/idl/AutoBalancerService.idl @@ -420,5 +420,6 @@ module OpenHRP * @return true if set successfully, false otherwise */ boolean startHumanSyncAfter5sec(); + boolean stopHumanSync(); }; }; diff --git a/rtc/AutoBalancer/AutoBalancer.cpp b/rtc/AutoBalancer/AutoBalancer.cpp index deba4531776..8515563c653 100644 --- a/rtc/AutoBalancer/AutoBalancer.cpp +++ b/rtc/AutoBalancer/AutoBalancer.cpp @@ -1081,19 +1081,18 @@ void AutoBalancer::fixLegToCoords (const hrp::Vector3& fix_pos, const hrp::Matri static bool moveleft = false; static bool ht_first_call = true; hrp::Vector3 rfinitpos,lfinitpos; +static int rfuplevel,lfuplevel; bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) { - static int rfuplevel,lfuplevel; - if(HumanSyncOn){ if(param.target_link->name == "RLEG_JOINT5"){ - if(humanpose.rfwrench[2] < 20.0 && humanpose.lfwrench[2] > 20.0){ + if(humanpose.rfwrench[2] < 20.0 && humanpose.lfwrench[2] > 20.0 && HumanSyncOn){ // if(humanpose.rfwrench[2] < 20.0){ if(rfuplevel < 100){ rfuplevel++; filt_hp_data.rfpos[2] = 0.025 - 0.025*cos(M_PI*rfuplevel/100); //filt_hp_data.rfpos[1] -= 0.001;//歩行遊び } - cout<<"RUP"< 0){ rfuplevel--; @@ -1106,14 +1105,14 @@ bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) param.target_p0(2) = rfinitpos(2) + filt_hp_data.rfpos[2]; } if(param.target_link->name == "LLEG_JOINT5"){ - if(humanpose.lfwrench[2] < 20.0 && humanpose.rfwrench[2] > 20.0){ + if(humanpose.lfwrench[2] < 20.0 && humanpose.rfwrench[2] > 20.0 && HumanSyncOn){ // if(humanpose.lfwrench[2] < 20.0){ if(lfuplevel < 100){ lfuplevel++; filt_hp_data.lfpos[2] = 0.025 - 0.025*cos(M_PI*lfuplevel/100); //filt_hp_data.lfpos[1] -= 0.001;//歩行遊び } - cout<<"LUP"< 0){ lfuplevel--; @@ -1125,17 +1124,16 @@ bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) param.target_p0(1) = lfinitpos(1) + filt_hp_data.lfpos[1]; param.target_p0(2) = lfinitpos(2) + filt_hp_data.lfpos[2]; } - if(param.target_link->name == "RARM_JOINT7"){ + if(param.target_link->name == "RARM_JOINT7" && HumanSyncOn){ param.target_p0(0) = 0.151 + filt_hp_data.rhpos[0]; param.target_p0(1) = -0.374 + filt_hp_data.rhpos[1]; param.target_p0(2) = 0.973 + filt_hp_data.rhpos[2]; } - if(param.target_link->name == "LARM_JOINT7"){ + if(param.target_link->name == "LARM_JOINT7" && HumanSyncOn){ param.target_p0(0) = 0.151 + filt_hp_data.lhpos[0]; param.target_p0(1) = 0.374 + filt_hp_data.lhpos[1]; param.target_p0(2) = 0.973 + filt_hp_data.lhpos[2]; } - } param.manip->calcInverseKinematics2Loop(param.target_p0, param.target_r0, 1.0, param.avoid_gain, param.reference_gain, &qrefv, transition_interpolator_ratio * leg_names_interpolator_ratio); @@ -1195,10 +1193,16 @@ void AutoBalancer::solveLimbIK () if(HumanSyncCountdownNum == 0){ HumanSyncOn = true; startCountdownForHumanSync = false; + HumanSyncCountdownNum = 5 * (1/m_dt); }else{ HumanSyncCountdownNum--; } } + if(ht_first_call){ + rfinitpos = ikp["rleg"].target_p0; + lfinitpos = ikp["lleg"].target_p0; + ht_first_call=false; + } if(HumanSyncOn){ for(int i=0;i<3;i++){ @@ -1213,31 +1217,27 @@ void AutoBalancer::solveLimbIK () if(filt_hp_data.com[i] - hp_data_old.com[i] > MAXVEL)filt_hp_data.com[i] = hp_data_old.com[i] + MAXVEL; if(filt_hp_data.com[i] - hp_data_old.com[i] < -MAXVEL)filt_hp_data.com[i] = hp_data_old.com[i] - MAXVEL; - hp_data_old.com[i] = filt_hp_data.com[i]; } if(loop%100==0)printf("[COM] %+06.3f,%+06.3f,%+06.3f [ZMP] %+06.3f,%+06.3f\n", filt_hp_data.com[0],filt_hp_data.com[1],filt_hp_data.com[2],filt_hp_data.zmp[0],filt_hp_data.zmp[1],filt_hp_data.zmp[2]); - if(ht_first_call){ht_first_call=false; - rfinitpos = ikp["rleg"].target_p0; - lfinitpos = ikp["lleg"].target_p0; - } }else{ for(int i=0;i<3;i++)init_humanpose.com[i] = humanpose.com[i]; for(int i=0;i<3;i++)init_humanpose.rfpos[i] = humanpose.rfpos[i]; for(int i=0;i<3;i++)init_humanpose.lfpos[i] = humanpose.lfpos[i]; for(int i=0;i<3;i++)init_humanpose.rhpos[i] = humanpose.rhpos[i]; for(int i=0;i<3;i++)init_humanpose.lhpos[i] = humanpose.lhpos[i]; + for(int i=0;i<3;i++){ + if(filt_hp_data.com[i]>0)filt_hp_data.com[i] -= 0.0001; + if(filt_hp_data.com[i]<0)filt_hp_data.com[i] += 0.0001; + } if(loop%100==0)printf("[pre-COM] %+06.3f,%+06.3f,%+06.3f [pre-ZMP] %+06.3f,%+06.3f\n", humanpose.com[0],humanpose.com[1],humanpose.com[2],humanpose.zmp[0],humanpose.zmp[1],humanpose.zmp[2]); } filt_hp_data.com[0] = 0.0;//重心前方向ロック - -// m_robot->rootLink()->p(0) = 0.0558423 + filt_hp_data.com[0]; -// m_robot->rootLink()->p(1) = 0+ filt_hp_data.com[1];//safetest -// m_robot->rootLink()->p(2) = 0.976372 + filt_hp_data.com[2]; m_robot->rootLink()->p(0) += filt_hp_data.com[0]; - m_robot->rootLink()->p(1) += filt_hp_data.com[1];//safetest + m_robot->rootLink()->p(1) += filt_hp_data.com[1]; m_robot->rootLink()->p(2) += filt_hp_data.com[2]; + for(int i=0;i<3;i++)hp_data_old.com[i] = filt_hp_data.com[i]; static int movelcnt; if(moveleft){ From 6674eace1372d06f4f4355b5f7e2fc655109a668 Mon Sep 17 00:00:00 2001 From: ishiguro Date: Wed, 29 Jun 2016 21:06:48 +0900 Subject: [PATCH 005/217] add X move --- rtc/AutoBalancer/AutoBalancer.cpp | 38 +++++++++++++++++++------------ 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/rtc/AutoBalancer/AutoBalancer.cpp b/rtc/AutoBalancer/AutoBalancer.cpp index 8515563c653..a986518ca64 100644 --- a/rtc/AutoBalancer/AutoBalancer.cpp +++ b/rtc/AutoBalancer/AutoBalancer.cpp @@ -39,6 +39,7 @@ humanpose_t humanpose; humanpose_t filt_hp_data,hp_data_old; bool startCountdownForHumanSync = false; bool HumanSyncOn = false; +#define true typedef coil::Guard Guard; @@ -519,7 +520,7 @@ RTC::ReturnCode_t AutoBalancer::onExecute(RTC::UniqueId ec_id) //for human tracker if (m_htzmpIn.isNew()){ m_htzmpIn.read(); -// humanpose.zmp[0] = m_htzmp.data.x;//zmpはこっちで計算 +// humanpose.zmp[0] = m_htzmp.data.x;//zmpは外部から読まずに両足wrenchからこのソースの中で計算 // humanpose.zmp[1] = m_htzmp.data.y; // humanpose.zmp[2] = m_htzmp.data.z; } @@ -686,11 +687,11 @@ RTC::ReturnCode_t AutoBalancer::onExecute(RTC::UniqueId ec_id) // humanpose.zmp[0],humanpose.zmp[1]); if(HumanSyncOn){ //ZMP上書き -// m_zmp.data.x = humanpose.zmp[0]*0.5 - filt_hp_data.com[0];// - m_zmp.data.y = filt_hp_data.zmp[1] - filt_hp_data.com[1];//test + if(USEX)m_zmp.data.x = filt_hp_data.zmp[0] - filt_hp_data.com[0];// + m_zmp.data.y = filt_hp_data.zmp[1] - filt_hp_data.com[1];// // COM上書き -// m_cog.data.x = 0.0558423 + filt_hp_data.com[0]; - m_cog.data.y = filt_hp_data.com[1]; + if(USEX)m_cog.data.x = filt_hp_data.com[0]; + m_cog.data.y = filt_hp_data.com[1]; } // sbpCogOffset @@ -1044,6 +1045,12 @@ void AutoBalancer::getTargetParameters() ref_zmp(1) = ref_cog(1); ref_zmp(2) = tmp_foot_mid_pos(2); } + //ishiguro + if (HumanSyncOn) { + if(USEX)ref_zmp(0) = humanpose.zmp[0]; + ref_zmp(1) = humanpose.zmp[1]; + ref_zmp(2) = tmp_foot_mid_pos(2); + } } }; @@ -1082,21 +1089,23 @@ static bool moveleft = false; static bool ht_first_call = true; hrp::Vector3 rfinitpos,lfinitpos; static int rfuplevel,lfuplevel; +#define LEVELNUM 200 +#define FUPHIGHT 0.03 bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) { if(param.target_link->name == "RLEG_JOINT5"){ if(humanpose.rfwrench[2] < 20.0 && humanpose.lfwrench[2] > 20.0 && HumanSyncOn){ // if(humanpose.rfwrench[2] < 20.0){ - if(rfuplevel < 100){ + if(rfuplevel < LEVELNUM){ rfuplevel++; - filt_hp_data.rfpos[2] = 0.025 - 0.025*cos(M_PI*rfuplevel/100); + filt_hp_data.rfpos[2] = FUPHIGHT/2*(1-cos(M_PI*rfuplevel/LEVELNUM)); //filt_hp_data.rfpos[1] -= 0.001;//歩行遊び } if(loop%100==0)cout<<"RUP"< 0){ rfuplevel--; - filt_hp_data.rfpos[2] = 0.025 - 0.025*cos(M_PI*rfuplevel/100); + filt_hp_data.rfpos[2] = FUPHIGHT/2*(1-cos(M_PI*rfuplevel/LEVELNUM)); //if(filt_hp_data.rfpos[2] == 0.0)moveleft = true;//歩行遊び } } @@ -1107,16 +1116,16 @@ bool AutoBalancer::solveLimbIKforLimb (ABCIKparam& param) if(param.target_link->name == "LLEG_JOINT5"){ if(humanpose.lfwrench[2] < 20.0 && humanpose.rfwrench[2] > 20.0 && HumanSyncOn){ // if(humanpose.lfwrench[2] < 20.0){ - if(lfuplevel < 100){ + if(lfuplevel < LEVELNUM){ lfuplevel++; - filt_hp_data.lfpos[2] = 0.025 - 0.025*cos(M_PI*lfuplevel/100); + filt_hp_data.lfpos[2] = FUPHIGHT/2*(1-cos(M_PI*lfuplevel/LEVELNUM)); //filt_hp_data.lfpos[1] -= 0.001;//歩行遊び } if(loop%100==0)cout<<"LUP"< 0){ lfuplevel--; - filt_hp_data.lfpos[2] = 0.025 - 0.025*cos(M_PI*lfuplevel/100); + filt_hp_data.lfpos[2] = FUPHIGHT/2*(1-cos(M_PI*lfuplevel/LEVELNUM)); //if(filt_hp_data.lfpos[2] == 0.0)moveleft = true;//歩行遊び } } @@ -1207,7 +1216,7 @@ void AutoBalancer::solveLimbIK () if(HumanSyncOn){ for(int i=0;i<3;i++){ filt_hp_data.zmp[i] = 0.99*filt_hp_data.zmp[i] + 0.01*(humanpose.zmp[i]); - filt_hp_data.com[i] = 0.99*filt_hp_data.com[i] + 0.01*(humanpose.com[i] - init_humanpose.com[i]); + filt_hp_data.com[i] = 0.99*filt_hp_data.com[i] + 0.01*(humanpose.com[i] - init_humanpose.com[i] + init_humanpose.zmp[i]);//Sync開始時のzmpのオフセットはつまり重心のオフセット filt_hp_data.rfwrench[i] = 0.99*filt_hp_data.rfwrench[i] + 0.01*(humanpose.rfwrench[i]); filt_hp_data.lfwrench[i] = 0.99*filt_hp_data.lfwrench[i] + 0.01*(humanpose.lfwrench[i]); // filt_hp_data.rfpos[i] = 0.99*filt_hp_data.rfpos[i] + 0.01*(humanpose.rfpos[i] - init_humanpose.rfpos[i]);//足ロック @@ -1222,6 +1231,7 @@ void AutoBalancer::solveLimbIK () if(loop%100==0)printf("[COM] %+06.3f,%+06.3f,%+06.3f [ZMP] %+06.3f,%+06.3f\n", filt_hp_data.com[0],filt_hp_data.com[1],filt_hp_data.com[2],filt_hp_data.zmp[0],filt_hp_data.zmp[1],filt_hp_data.zmp[2]); }else{ for(int i=0;i<3;i++)init_humanpose.com[i] = humanpose.com[i]; + for(int i=0;i<3;i++)init_humanpose.zmp[i] = humanpose.zmp[i]; for(int i=0;i<3;i++)init_humanpose.rfpos[i] = humanpose.rfpos[i]; for(int i=0;i<3;i++)init_humanpose.lfpos[i] = humanpose.lfpos[i]; for(int i=0;i<3;i++)init_humanpose.rhpos[i] = humanpose.rhpos[i]; @@ -1233,8 +1243,7 @@ void AutoBalancer::solveLimbIK () if(loop%100==0)printf("[pre-COM] %+06.3f,%+06.3f,%+06.3f [pre-ZMP] %+06.3f,%+06.3f\n", humanpose.com[0],humanpose.com[1],humanpose.com[2],humanpose.zmp[0],humanpose.zmp[1],humanpose.zmp[2]); } - filt_hp_data.com[0] = 0.0;//重心前方向ロック - m_robot->rootLink()->p(0) += filt_hp_data.com[0]; + if(USEX)m_robot->rootLink()->p(0) += filt_hp_data.com[0]; m_robot->rootLink()->p(1) += filt_hp_data.com[1]; m_robot->rootLink()->p(2) += filt_hp_data.com[2]; for(int i=0;i<3;i++)hp_data_old.com[i] = filt_hp_data.com[i]; @@ -1304,7 +1313,6 @@ static int movelcnt; } */ - bool AutoBalancer::startHumanSyncAfter5sec() { std::cerr << "[" << m_profile.instance_name << "] start HumanSync after 5 sec" << std::endl; From 25a860a18a65e5d1cef22d5c7655c7a9052baa31 Mon Sep 17 00:00:00 2001 From: ishiguro Date: Fri, 1 Jul 2016 21:39:12 +0900 Subject: [PATCH 006/217] mod zmp ref --- 3rdparty/qpOASES/qpOASES-3.0/AUTHORS | 74 + 3rdparty/qpOASES/qpOASES-3.0/AUTHORS.txt | 74 + 3rdparty/qpOASES/qpOASES-3.0/CMakeLists.txt | 150 + .../qpOASES/qpOASES-3.0/CTestTestfile.cmake | 6 + 3rdparty/qpOASES/qpOASES-3.0/INSTALL | 79 + 3rdparty/qpOASES/qpOASES-3.0/INSTALL.txt | 79 + 3rdparty/qpOASES/qpOASES-3.0/LICENSE | 503 ++ 3rdparty/qpOASES/qpOASES-3.0/LICENSE.txt | 503 ++ 3rdparty/qpOASES/qpOASES-3.0/README | 84 + 3rdparty/qpOASES/qpOASES-3.0/README.txt | 84 + 3rdparty/qpOASES/qpOASES-3.0/VERSIONS | 106 + 3rdparty/qpOASES/qpOASES-3.0/VERSIONS.txt | 106 + 3rdparty/qpOASES/qpOASES-3.0/bin/example1 | Bin 0 -> 32801 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/example1a | Bin 0 -> 28799 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/example1b | Bin 0 -> 31765 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/example2 | Bin 0 -> 31208 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/example3 | Bin 0 -> 30847 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/example3b | Bin 0 -> 30848 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/example4 | Bin 0 -> 34008 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/example5 | Bin 0 -> 39753 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/exampleLP | Bin 0 -> 31905 bytes 3rdparty/qpOASES/qpOASES-3.0/bin/index.html | 7 + 3rdparty/qpOASES/qpOASES-3.0/bin/qrecipe | Bin 0 -> 57832 bytes .../qpOASES/qpOASES-3.0/doc/DoxygenLayout.xml | 189 + .../qpOASES/qpOASES-3.0/doc/doxygen.config | 1123 +++ 3rdparty/qpOASES/qpOASES-3.0/doc/index.html | 12 + 3rdparty/qpOASES/qpOASES-3.0/doc/mainpage.dox | 120 + 3rdparty/qpOASES/qpOASES-3.0/doc/manual.pdf | Bin 0 -> 710503 bytes .../qpOASES/qpOASES-3.0/examples/example1.cpp | 97 + .../qpOASES-3.0/examples/example1a.cpp | 85 + .../qpOASES-3.0/examples/example1b.cpp | 86 + .../qpOASES/qpOASES-3.0/examples/example2.cpp | 124 + .../qpOASES/qpOASES-3.0/examples/example3.cpp | 88 + .../qpOASES-3.0/examples/example3b.cpp | 88 + .../qpOASES/qpOASES-3.0/examples/example4.cpp | 172 + .../qpOASES-3.0/examples/example4CP.cpp | 111 + .../qpOASES/qpOASES-3.0/examples/example5.cpp | 200 + .../qpOASES-3.0/examples/exampleLP.cpp | 87 + .../qpOASES/qpOASES-3.0/examples/index.html | 19 + .../qpOASES/qpOASES-3.0/examples/qrecipe.cpp | 495 ++ .../qpOASES/qpOASES-3.0/include/index.html | 9 + .../qpOASES/qpOASES-3.0/include/qpOASES.hpp | 59 + .../qpOASES-3.0/include/qpOASES/Bounds.hpp | 256 + .../qpOASES-3.0/include/qpOASES/Bounds.ipp | 120 + .../qpOASES-3.0/include/qpOASES/Constants.hpp | 77 + .../include/qpOASES/ConstraintProduct.hpp | 91 + .../include/qpOASES/Constraints.hpp | 246 + .../include/qpOASES/Constraints.ipp | 122 + .../qpOASES-3.0/include/qpOASES/Flipper.hpp | 155 + .../qpOASES-3.0/include/qpOASES/Indexlist.hpp | 199 + .../qpOASES-3.0/include/qpOASES/Indexlist.ipp | 92 + .../qpOASES-3.0/include/qpOASES/Matrices.hpp | 867 +++ .../include/qpOASES/MessageHandling.hpp | 472 ++ .../include/qpOASES/MessageHandling.ipp | 144 + .../qpOASES-3.0/include/qpOASES/Options.hpp | 170 + .../qpOASES-3.0/include/qpOASES/QProblem.hpp | 1163 +++ .../qpOASES-3.0/include/qpOASES/QProblem.ipp | 283 + .../qpOASES-3.0/include/qpOASES/QProblemB.hpp | 1091 +++ .../qpOASES-3.0/include/qpOASES/QProblemB.ipp | 477 ++ .../qpOASES-3.0/include/qpOASES/SQProblem.hpp | 394 + .../qpOASES-3.0/include/qpOASES/SQProblem.ipp | 51 + .../qpOASES-3.0/include/qpOASES/SubjectTo.hpp | 229 + .../qpOASES-3.0/include/qpOASES/SubjectTo.ipp | 158 + .../qpOASES-3.0/include/qpOASES/Types.hpp | 281 + .../include/qpOASES/UnitTesting.hpp | 79 + .../qpOASES-3.0/include/qpOASES/Utils.hpp | 370 + .../qpOASES-3.0/include/qpOASES/Utils.ipp | 174 + .../include/qpOASES/extras/OQPinterface.hpp | 250 + .../qpOASES/extras/SolutionAnalysis.hpp | 155 + .../qpOASES/extras/SolutionAnalysis.ipp | 51 + .../include/qpOASES/extras/index.html | 10 + .../qpOASES-3.0/include/qpOASES/index.html | 33 + 3rdparty/qpOASES/qpOASES-3.0/index.html | 31 + .../qpOASES/qpOASES-3.0/interfaces/index.html | 12 + .../interfaces/matlab/example1.mat | Bin 0 -> 790 bytes .../interfaces/matlab/example1a.mat | Bin 0 -> 896 bytes .../interfaces/matlab/example1b.mat | Bin 0 -> 549 bytes .../qpOASES-3.0/interfaces/matlab/index.html | 20 + .../qpOASES-3.0/interfaces/matlab/make.m | 238 + .../qpOASES-3.0/interfaces/matlab/qpOASES.cpp | 557 ++ .../qpOASES-3.0/interfaces/matlab/qpOASES.m | 77 + .../interfaces/matlab/qpOASES_auxInput.m | 103 + .../matlab/qpOASES_matlab_utils.cpp | 885 +++ .../matlab/qpOASES_matlab_utils.hpp | 92 + .../interfaces/matlab/qpOASES_options.m | 251 + .../interfaces/matlab/qpOASES_sequence.cpp | 1061 +++ .../interfaces/matlab/qpOASES_sequence.m | 112 + .../qpOASES-3.0/interfaces/octave/clean | 3 + .../qpOASES-3.0/interfaces/octave/clean.sh | 3 + .../interfaces/octave/example1.mat | Bin 0 -> 790 bytes .../interfaces/octave/example1a.mat | Bin 0 -> 896 bytes .../interfaces/octave/example1b.mat | Bin 0 -> 549 bytes .../qpOASES-3.0/interfaces/octave/index.html | 21 + .../qpOASES-3.0/interfaces/octave/make.m | 238 + .../qpOASES-3.0/interfaces/octave/qpOASES.cpp | 557 ++ .../qpOASES-3.0/interfaces/octave/qpOASES.m | 77 + .../interfaces/octave/qpOASES_auxInput.m | 103 + .../octave/qpOASES_octave_utils.cpp | 884 +++ .../octave/qpOASES_octave_utils.hpp | 92 + .../interfaces/octave/qpOASES_options.m | 251 + .../interfaces/octave/qpOASES_sequence.cpp | 1061 +++ .../interfaces/octave/qpOASES_sequence.m | 112 + .../qpOASES-3.0/interfaces/python/README.rst | 68 + .../python/examples/cython/example1.pyx | 73 + .../python/examples/cython/index.html | 9 + .../python/examples/cython/setup.py | 16 + .../interfaces/python/examples/example1.py | 76 + .../interfaces/python/examples/example1b.py | 72 + .../interfaces/python/examples/example2.py | 90 + .../interfaces/python/examples/index.html | 11 + .../qpOASES-3.0/interfaces/python/index.html | 13 + .../qpOASES-3.0/interfaces/python/qpoases.pxd | 476 ++ .../qpOASES-3.0/interfaces/python/qpoases.pyx | 779 ++ .../qpOASES-3.0/interfaces/python/setup.py | 72 + .../interfaces/python/tests/__init__.py | 1 + .../interfaces/python/tests/index.html | 11 + .../interfaces/python/tests/test_examples.py | 328 + .../interfaces/python/tests/test_idhessian.py | 94 + .../interfaces/python/tests/test_testbench.py | 332 + .../interfaces/scilab/example1.dat | Bin 0 -> 656 bytes .../interfaces/scilab/example1a.dat | Bin 0 -> 784 bytes .../interfaces/scilab/example1b.dat | Bin 0 -> 408 bytes .../qpOASES-3.0/interfaces/scilab/index.html | 14 + .../interfaces/scilab/qpOASESinterface.c | 1061 +++ .../interfaces/scilab/qpOASESinterface.sce | 41 + .../interfaces/scilab/qpOASESroutines.cpp | 365 + .../interfaces/simulink/example_QProblem.mdl | 803 +++ .../interfaces/simulink/example_QProblemB.mdl | 745 ++ .../interfaces/simulink/example_SQProblem.mdl | 797 +++ .../interfaces/simulink/index.html | 17 + .../simulink/load_example_QProblem.m | 93 + .../simulink/load_example_QProblemB.m | 75 + .../simulink/load_example_SQProblem.m | 93 + .../qpOASES-3.0/interfaces/simulink/make.m | 239 + .../interfaces/simulink/qpOASES_QProblem.cpp | 447 ++ .../interfaces/simulink/qpOASES_QProblemB.cpp | 392 + .../interfaces/simulink/qpOASES_SQProblem.cpp | 460 ++ .../qpOASES/qpOASES-3.0/libs/libqpOASES.so | 1 + .../qpOASES-3.0/libs/libqpOASES.so.3.0 | Bin 0 -> 1269403 bytes 3rdparty/qpOASES/qpOASES-3.0/make.mk | 38 + 3rdparty/qpOASES/qpOASES-3.0/make_cygwin.mk | 106 + 3rdparty/qpOASES/qpOASES-3.0/make_linux.mk | 107 + 3rdparty/qpOASES/qpOASES-3.0/make_osx.mk | 99 + 3rdparty/qpOASES/qpOASES-3.0/make_windows.mk | 114 + .../qpOASES-3.0/src/BLASReplacement.cpp | 145 + 3rdparty/qpOASES/qpOASES-3.0/src/Bounds.cpp | 515 ++ .../qpOASES/qpOASES-3.0/src/Constraints.cpp | 500 ++ 3rdparty/qpOASES/qpOASES-3.0/src/Flipper.cpp | 273 + .../qpOASES/qpOASES-3.0/src/Indexlist.cpp | 319 + .../qpOASES-3.0/src/LAPACKReplacement.cpp | 120 + 3rdparty/qpOASES/qpOASES-3.0/src/Matrices.cpp | 1967 +++++ .../qpOASES-3.0/src/MessageHandling.cpp | 612 ++ .../qpOASES/qpOASES-3.0/src/OQPinterface.cpp | 670 ++ 3rdparty/qpOASES/qpOASES-3.0/src/Options.cpp | 553 ++ 3rdparty/qpOASES/qpOASES-3.0/src/QProblem.cpp | 6338 +++++++++++++++++ .../qpOASES/qpOASES-3.0/src/QProblemB.cpp | 3862 ++++++++++ .../qpOASES/qpOASES-3.0/src/SQProblem.cpp | 553 ++ .../qpOASES-3.0/src/SolutionAnalysis.cpp | 567 ++ .../qpOASES/qpOASES-3.0/src/SubjectTo.cpp | 289 + 3rdparty/qpOASES/qpOASES-3.0/src/Utils.cpp | 984 +++ 3rdparty/qpOASES/qpOASES-3.0/src/index.html | 24 + .../qpOASES-3.0/testing/checkForMemoryLeaks | 106 + .../testing/cpp/data/fetch_cpp_data | 34 + .../qpOASES-3.0/testing/cpp/data/index.html | 8 + .../qpOASES-3.0/testing/cpp/index.html | 33 + .../qpOASES-3.0/testing/cpp/test_bench.cpp | 309 + .../testing/cpp/test_constraintProduct1.cpp | 197 + .../testing/cpp/test_constraintProduct2.cpp | 196 + .../qpOASES-3.0/testing/cpp/test_example1.cpp | 123 + .../testing/cpp/test_example1a.cpp | 118 + .../testing/cpp/test_example1b.cpp | 119 + .../qpOASES-3.0/testing/cpp/test_example2.cpp | 132 + .../qpOASES-3.0/testing/cpp/test_example4.cpp | 211 + .../qpOASES-3.0/testing/cpp/test_example5.cpp | 204 + .../qpOASES-3.0/testing/cpp/test_example6.cpp | 112 + .../qpOASES-3.0/testing/cpp/test_example7.cpp | 90 + .../testing/cpp/test_exampleLP.cpp | 121 + .../testing/cpp/test_gradientShift.cpp | 125 + .../testing/cpp/test_guessedWS1.cpp | 164 + .../testing/cpp/test_indexlist.cpp | 96 + .../qpOASES-3.0/testing/cpp/test_janick1.cpp | 197 + .../qpOASES-3.0/testing/cpp/test_janick2.cpp | 251 + .../qpOASES-3.0/testing/cpp/test_matrices.cpp | 903 +++ .../testing/cpp/test_matrices2.cpp | 113 + .../testing/cpp/test_matrices3.cpp | 90 + .../qpOASES-3.0/testing/cpp/test_qrecipe.cpp | 149 + .../testing/cpp/test_qrecipe_data.hpp | 401 ++ .../testing/cpp/test_runAllOqpExamples.cpp | 177 + .../testing/cpp/test_sebastien1.cpp | 74 + .../testing/cpp/test_vanBarelsUnboundedQP.cpp | 69 + .../qpOASES/qpOASES-3.0/testing/index.html | 12 + .../testing/matlab/auxFiles/generateExample.m | 25 + .../matlab/auxFiles/generateRandomQp.m | 110 + .../testing/matlab/auxFiles/getKktResidual.m | 134 + .../testing/matlab/auxFiles/index.html | 13 + .../testing/matlab/auxFiles/isoctave.m | 21 + .../matlab/auxFiles/setupQpDataStruct.m | 18 + .../matlab/auxFiles/setupQpFeaturesStruct.m | 21 + .../testing/matlab/data/fetch_matlab_data | 34 + .../testing/matlab/data/index.html | 8 + .../qpOASES-3.0/testing/matlab/index.html | 11 + .../qpOASES-3.0/testing/matlab/runAllTests.m | 153 + .../testing/matlab/tests/index.html | 37 + .../testing/matlab/tests/runAlexInfeas1.m | 30 + .../testing/matlab/tests/runAlexInfeas2.m | 35 + .../matlab/tests/runAlternativeX0Test.m | 84 + .../testing/matlab/tests/runBenchmarkCHAIN1.m | 56 + .../matlab/tests/runBenchmarkCHAIN1A.m | 57 + .../testing/matlab/tests/runBenchmarkCRANE1.m | 51 + .../testing/matlab/tests/runBenchmarkCRANE2.m | 52 + .../testing/matlab/tests/runBenchmarkCRANE3.m | 51 + .../testing/matlab/tests/runBenchmarkDIESEL.m | 55 + .../matlab/tests/runBenchmarkEQUALITY1.m | 52 + .../matlab/tests/runBenchmarkEQUALITY2.m | 56 + .../matlab/tests/runBenchmarkEXAMPLE1.m | 52 + .../matlab/tests/runBenchmarkEXAMPLE1A.m | 52 + .../matlab/tests/runBenchmarkEXAMPLE1B.m | 52 + .../matlab/tests/runBenchmarkIDHESSIAN1.m | 55 + .../matlab/tests/runInterfaceSeqTest.m | 428 ++ .../testing/matlab/tests/runInterfaceTest.m | 459 ++ .../testing/matlab/tests/runQAP8.m | 36 + .../testing/matlab/tests/runQSHARE1B.m | 43 + .../testing/matlab/tests/runRandomIdHessian.m | 428 ++ .../matlab/tests/runRandomZeroHessian.m | 426 ++ .../matlab/tests/runSimpleSpringExample.m | 34 + .../matlab/tests/runTestAPrioriKnownSeq1.m | 87 + .../testing/matlab/tests/runTestSeq.m | 104 + .../testing/matlab/tests/runTestSparse.m | 33 + .../testing/matlab/tests/runTestSparse2.m | 33 + .../testing/matlab/tests/runTestSparse3.m | 39 + .../testing/matlab/tests/runTestSparse4.m | 29 + .../matlab/tests/runTestWorkingSetLI.m | 50 + .../matlab/tests/runVanBarelsUnboundedQP.m | 25 + .../qpOASES/qpOASES-3.0/testing/runUnitTests | 106 + CMakeLists.txt | 2 +- idl/AutoBalancerService.idl | 1 + rtc/AutoBalancer/AutoBalancer.cpp | 101 +- rtc/Stabilizer/Stabilizer.cpp | 1 + 238 files changed, 55775 insertions(+), 38 deletions(-) create mode 100644 3rdparty/qpOASES/qpOASES-3.0/AUTHORS create mode 100644 3rdparty/qpOASES/qpOASES-3.0/AUTHORS.txt create mode 100644 3rdparty/qpOASES/qpOASES-3.0/CMakeLists.txt create mode 100644 3rdparty/qpOASES/qpOASES-3.0/CTestTestfile.cmake create mode 100644 3rdparty/qpOASES/qpOASES-3.0/INSTALL create mode 100644 3rdparty/qpOASES/qpOASES-3.0/INSTALL.txt create mode 100644 3rdparty/qpOASES/qpOASES-3.0/LICENSE create mode 100644 3rdparty/qpOASES/qpOASES-3.0/LICENSE.txt create mode 100644 3rdparty/qpOASES/qpOASES-3.0/README create mode 100644 3rdparty/qpOASES/qpOASES-3.0/README.txt create mode 100644 3rdparty/qpOASES/qpOASES-3.0/VERSIONS create mode 100644 3rdparty/qpOASES/qpOASES-3.0/VERSIONS.txt create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/example1 create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/example1a create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/example1b create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/example2 create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/example3 create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/example3b create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/example4 create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/example5 create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/exampleLP create mode 100644 3rdparty/qpOASES/qpOASES-3.0/bin/index.html create mode 100755 3rdparty/qpOASES/qpOASES-3.0/bin/qrecipe create mode 100644 3rdparty/qpOASES/qpOASES-3.0/doc/DoxygenLayout.xml create mode 100644 3rdparty/qpOASES/qpOASES-3.0/doc/doxygen.config create mode 100644 3rdparty/qpOASES/qpOASES-3.0/doc/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/doc/mainpage.dox create mode 100644 3rdparty/qpOASES/qpOASES-3.0/doc/manual.pdf create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example1.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example1a.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example1b.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example2.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example3.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example3b.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example4.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example4CP.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/example5.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/exampleLP.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/examples/qrecipe.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Bounds.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Bounds.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constants.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/ConstraintProduct.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constraints.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constraints.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Flipper.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Indexlist.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Indexlist.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Matrices.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/MessageHandling.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/MessageHandling.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Options.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblem.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblem.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblemB.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblemB.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SQProblem.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SQProblem.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SubjectTo.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SubjectTo.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Types.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/UnitTesting.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Utils.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Utils.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/OQPinterface.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/SolutionAnalysis.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/SolutionAnalysis.ipp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1.mat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1a.mat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1b.mat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/make.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_auxInput.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_matlab_utils.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_matlab_utils.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_options.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_sequence.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_sequence.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/clean create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/clean.sh create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1.mat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1a.mat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1b.mat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/make.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_auxInput.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_octave_utils.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_octave_utils.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_options.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_sequence.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_sequence.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/README.rst create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/example1.pyx create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/setup.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example1.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example1b.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example2.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/qpoases.pxd create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/qpoases.pyx create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/setup.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/__init__.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_examples.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_idhessian.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_testbench.py create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/example1.dat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/example1a.dat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/example1b.dat create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESinterface.c create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESinterface.sce create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESroutines.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_QProblem.mdl create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_QProblemB.mdl create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_SQProblem.mdl create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_QProblem.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_QProblemB.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_SQProblem.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/make.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_QProblem.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_QProblemB.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_SQProblem.cpp create mode 120000 3rdparty/qpOASES/qpOASES-3.0/libs/libqpOASES.so create mode 100755 3rdparty/qpOASES/qpOASES-3.0/libs/libqpOASES.so.3.0 create mode 100644 3rdparty/qpOASES/qpOASES-3.0/make.mk create mode 100644 3rdparty/qpOASES/qpOASES-3.0/make_cygwin.mk create mode 100644 3rdparty/qpOASES/qpOASES-3.0/make_linux.mk create mode 100644 3rdparty/qpOASES/qpOASES-3.0/make_osx.mk create mode 100644 3rdparty/qpOASES/qpOASES-3.0/make_windows.mk create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/BLASReplacement.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/Bounds.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/Constraints.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/Flipper.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/Indexlist.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/LAPACKReplacement.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/Matrices.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/MessageHandling.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/OQPinterface.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/Options.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/QProblem.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/QProblemB.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/SQProblem.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/SolutionAnalysis.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/SubjectTo.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/Utils.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/src/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/checkForMemoryLeaks create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/data/fetch_cpp_data create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/data/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_bench.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_constraintProduct1.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_constraintProduct2.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_example1.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_example1a.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_example1b.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_example2.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_example4.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_example5.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_example6.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_example7.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_exampleLP.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_gradientShift.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_guessedWS1.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_indexlist.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_janick1.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_janick2.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_matrices.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_matrices2.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_matrices3.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_qrecipe.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_qrecipe_data.hpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_runAllOqpExamples.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_sebastien1.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/cpp/test_vanBarelsUnboundedQP.cpp create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/auxFiles/generateExample.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/auxFiles/generateRandomQp.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/auxFiles/getKktResidual.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/auxFiles/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/auxFiles/isoctave.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/auxFiles/setupQpDataStruct.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/auxFiles/setupQpFeaturesStruct.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/data/fetch_matlab_data create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/data/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/runAllTests.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/index.html create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runAlexInfeas1.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runAlexInfeas2.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runAlternativeX0Test.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkCHAIN1.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkCHAIN1A.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkCRANE1.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkCRANE2.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkCRANE3.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkDIESEL.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkEQUALITY1.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkEQUALITY2.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkEXAMPLE1.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkEXAMPLE1A.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkEXAMPLE1B.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runBenchmarkIDHESSIAN1.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runInterfaceSeqTest.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runInterfaceTest.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runQAP8.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runQSHARE1B.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runRandomIdHessian.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runRandomZeroHessian.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runSimpleSpringExample.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runTestAPrioriKnownSeq1.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runTestSeq.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runTestSparse.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runTestSparse2.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runTestSparse3.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runTestSparse4.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runTestWorkingSetLI.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/matlab/tests/runVanBarelsUnboundedQP.m create mode 100644 3rdparty/qpOASES/qpOASES-3.0/testing/runUnitTests diff --git a/3rdparty/qpOASES/qpOASES-3.0/AUTHORS b/3rdparty/qpOASES/qpOASES-3.0/AUTHORS new file mode 100644 index 00000000000..49b20f8dc7d --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/AUTHORS @@ -0,0 +1,74 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +MAIN AUTHORS +============ + +qpOASES's core functionality and software design have been developed by the +following main developers (in alphabetical order): + + Hans Joachim Ferreau + Christian Kirches + Andreas Potschka + + + +FURTHER AUTHORS +=============== + +Moreover, the following developers have contributed code to qpOASES's +third-party interfaces (in alphabetical order): + + Alexander Buchner + Holger Diedam + Manuel Kudruss + Sebastian F. Walter + + + +CONTRIBUTORS +============ + +Finally, the following people have not contributed to the source code, +but have helped making qpOASES even more useful by testing, reporting +bugs or proposing algorithmic improvements (in alphabetical order): + + Eckhard Arnold + Boris Houska + Aude Perrin + Milan Vukov + Thomas Wiese + Leonard Wirsching + + + +All users are invited to further improve qpOASES by providing comments, +code enhancements, bug reports, additional documentation or whatever you +feel is missing. + + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/AUTHORS.txt b/3rdparty/qpOASES/qpOASES-3.0/AUTHORS.txt new file mode 100644 index 00000000000..5132d8c105e --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/AUTHORS.txt @@ -0,0 +1,74 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +MAIN AUTHORS +============ + +qpOASES's core functionality and software design have been developed by the +following main developers (in alphabetical order): + + Hans Joachim Ferreau + Christian Kirches + Andreas Potschka + + + +FURTHER AUTHORS +=============== + +Moreover, the following developers have contributed code to qpOASES's +third-party interfaces (in alphabetical order): + + Alexander Buchner + Holger Diedam + Manuel Kudruss + Sebastian F. Walter + + + +CONTRIBUTORS +============ + +Finally, the following people have not contributed to the source code, +but have helped making qpOASES even more useful by testing, reporting +bugs or proposing algorithmic improvements (in alphabetical order): + + Eckhard Arnold + Boris Houska + Aude Perrin + Milan Vukov + Thomas Wiese + Leonard Wirsching + + + +All users are invited to further improve qpOASES by providing comments, +code enhancements, bug reports, additional documentation or whatever you +feel is missing. + + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/CMakeLists.txt b/3rdparty/qpOASES/qpOASES-3.0/CMakeLists.txt new file mode 100644 index 00000000000..fa0c2a3d123 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/CMakeLists.txt @@ -0,0 +1,150 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +## +## Filename: CMakeLists.txt +## Author: Hans Joachim Ferreau (thanks to Milan Vukov) +## Version: 3.0 +## Date: 2007-2014 +## + +cmake_minimum_required(VERSION 2.6) + +PROJECT(qpOASES CXX) +SET(PACKAGE_NAME "qpOASES") +SET(PACKAGE_VERSION "3.0.1") +SET(PACKAGE_SO_VERSION "3.0") +SET(PACKAGE_DESCRIPTION "QP solver using the online active set strategy") +SET(PACKAGE_AUTHOR "Hans Joachim Ferreau") +SET(PACKAGE_MAINTAINER "Hans Joachim Ferreau") +SET(PACKAGE_URL "https://projects.coin-or.org/qpOASES") + +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/libs) + +IF( NOT CMAKE_VERBOSE_MAKEFILE ) + SET( CMAKE_VERBOSE_MAKEFILE OFF ) +ENDIF( NOT CMAKE_VERBOSE_MAKEFILE ) + +IF( NOT CMAKE_BUILD_TYPE ) + SET(CMAKE_BUILD_TYPE Release CACHE STRING + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." + FORCE + ) +ENDIF( NOT CMAKE_BUILD_TYPE ) + + +############################################################ +#################### compiler flags ######################## +############################################################ +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__NO_COPYRIGHT__") +IF ( UNIX ) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wfloat-equal -Wshadow -DLINUX") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_DEBUG} -O3 -finline-functions") +ELSEIF( WINDOWS ) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nologo -EHsc -DWIN32") +ENDIF() + +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D__DEBUG__") + +############################################################ +######################## rpath ############################# +############################################################ +# use, i.e. don't skip the full RPATH for the build tree +set(CMAKE_SKIP_BUILD_RPATH FALSE) + +# when building, don't use the install RPATH already +# (but later on when installing) +set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/lib/casadi") + +# add the automatically determined parts of the RPATH +# which point to directories outside the build tree to the install RPATH +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +# the RPATH to be used when installing, but only if it's not a system directory +list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) +if("${isSystemDir}" STREQUAL "-1") + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/lib/casadi") +endif("${isSystemDir}" STREQUAL "-1") + + + +############################################################ +#################### build and install ##################### +############################################################ +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include) + +# compile qpOASES libraries +FILE(GLOB SRC src/*.cpp) + +# library +#ADD_LIBRARY(qpOASES STATIC ${SRC}) +ADD_LIBRARY(qpOASES SHARED ${SRC}) +INSTALL(TARGETS qpOASES + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION lib +) +SET_TARGET_PROPERTIES( + qpOASES + PROPERTIES + SOVERSION ${PACKAGE_SO_VERSION} + ) + +# headers +INSTALL(FILES include/qpOASES.hpp + DESTINATION include) +INSTALL(DIRECTORY include/qpOASES + DESTINATION include + FILES_MATCHING PATTERN "*.hpp" + PATTERN ".svn" EXCLUDE) + +############################################################ +######################### examples ######################### +############################################################ +# compile qpOASES examples +SET(EXAMPLE_NAMES + example1 + example1a + example1b + example2 + example3 + example3b + example4 + example5 + exampleLP + qrecipe +) + +FOREACH(ELEMENT ${EXAMPLE_NAMES}) + ADD_EXECUTABLE(${ELEMENT} examples/${ELEMENT}.cpp) + TARGET_LINK_LIBRARIES(${ELEMENT} qpOASES) +ENDFOREACH(ELEMENT ${EXAMPLE_NAMES}) + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/CTestTestfile.cmake b/3rdparty/qpOASES/qpOASES-3.0/CTestTestfile.cmake new file mode 100644 index 00000000000..321a6fdcdf6 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/CTestTestfile.cmake @@ -0,0 +1,6 @@ +# CMake generated Testfile for +# Source directory: /home/ishiguro/catkin_ws/chidori/build/hrpsys/3rdparty/qpOASES/qpOASES-3.0 +# Build directory: /home/ishiguro/catkin_ws/chidori/build/hrpsys/3rdparty/qpOASES/qpOASES-3.0 +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. diff --git a/3rdparty/qpOASES/qpOASES-3.0/INSTALL b/3rdparty/qpOASES/qpOASES-3.0/INSTALL new file mode 100644 index 00000000000..69852192cec --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/INSTALL @@ -0,0 +1,79 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +INSTALLATION UNDER LINUX +======================== + +0. Obtain qpOASES from COIN-OR: + +Download a zipped archive containg the latest stable release and unpack it +into . Alternatively, you check out the latest stable branch, +e.g. by running + +svn co https://projects.coin-or.org/svn/qpOASES/stable/3.0 + +from your shell. + + +1. Compilation of the qpOASES library libqpOASES.a and test examples: + +cd +make + +The library libqpOASES.a provides the complete functionality of the qpOASES +software package. It can be used by, e.g., linking it against a main function +from the examples folder. The make also compiles a couple of test examples; +executables are stored within the directory /bin. + + +2. Running a simple test example: + +Among others, an executable called example1 should have been created; run +it in order to test your installation: + +cd /bin +./example1 + +If it terminates after successfully solving two QP problems, qpOASES has been +successfully installed! + + +3. Optional, create source code documentation (using doxygen): + +cd /doc +doxygen doxygen.config + +Afterwards, you can open the file /doc/html/index.html with +your favorite browser in order to view qpOASES's source code documentation. + + +NOTE: More detailed installation instructions, including information on how + to run unit tests can be found in the qpOASES User's Manual located + at /doc/manual.pdf! + + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/INSTALL.txt b/3rdparty/qpOASES/qpOASES-3.0/INSTALL.txt new file mode 100644 index 00000000000..89eb3abb47d --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/INSTALL.txt @@ -0,0 +1,79 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +INSTALLATION UNDER LINUX +======================== + +0. Obtain qpOASES from COIN-OR: + +Download a zipped archive containg the latest stable release and unpack it +into . Alternatively, you check out the latest stable branch, +e.g. by running + +svn co https://projects.coin-or.org/svn/qpOASES/stable/3.0 + +from your shell. + + +1. Compilation of the qpOASES library libqpOASES.a and test examples: + +cd +make + +The library libqpOASES.a provides the complete functionality of the qpOASES +software package. It can be used by, e.g., linking it against a main function +from the examples folder. The make also compiles a couple of test examples; +executables are stored within the directory /bin. + + +2. Running a simple test example: + +Among others, an executable called example1 should have been created; run +it in order to test your installation: + +cd /bin +./example1 + +If it terminates after successfully solving two QP problems, qpOASES has been +successfully installed! + + +3. Optional, create source code documentation (using doxygen): + +cd /doc +doxygen doxygen.config + +Afterwards, you can open the file /doc/html/index.html with +your favorite browser in order to view qpOASES's source code documentation. + + +NOTE: More detailed installation instructions, including information on how + to run unit tests can be found in the qpOASES User's Manual located + at /doc/manual.pdf! + + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/LICENSE b/3rdparty/qpOASES/qpOASES-3.0/LICENSE new file mode 100644 index 00000000000..9ef3d701d14 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/LICENSE @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/3rdparty/qpOASES/qpOASES-3.0/LICENSE.txt b/3rdparty/qpOASES/qpOASES-3.0/LICENSE.txt new file mode 100644 index 00000000000..2d59e84cd83 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/LICENSE.txt @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/3rdparty/qpOASES/qpOASES-3.0/README b/3rdparty/qpOASES/qpOASES-3.0/README new file mode 100644 index 00000000000..2147a72fb67 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/README @@ -0,0 +1,84 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +INTRODUCTION +============ + +qpOASES is an open-source C++ implementation of the recently proposed +online active set strategy, which was inspired by important observations +from the field of parametric quadratic programming (QP). It has several +theoretical features that make it particularly suited for model predictive +control (MPC) applications. Further numerical modifications have made +qpOASES a reliable QP solver, even when tackling semi-definite, ill-posed or +degenerated QP problems. Moreover, several interfaces to third-party software +like ​Matlab or ​Simulink are provided that make qpOASES easy-to-use even for +users without knowledge of C/C++. + + + +GETTING STARTED +=============== + +1. For installation, usage and additional information on this software package + see the qpOASES User's Manual located at doc/manual.pdf or check its + source code documentation! + + +2. The file LICENSE.txt contains a copy of the GNU Lesser General Public + License (v2.1). Please read it carefully before using qpOASES! + + +3. The whole software package can be obtained from + + http://www.qpOASES.org/ or + https://projects.coin-or.org/qpOASES/ + + On this webpage you will also find further support such as a list of + questions posed by other users. + + + +CONTACT THE AUTHORS +=================== + +If you have got questions, remarks or comments on qpOASES, it is strongly +encouraged to report them by creating a new ticket at the qpOASES webpage. +In case you do not want to disclose your feedback to the public, you may +send an e-mail to + + support@qpOASES.org + +Finally, you may contact one of the main authors directly: + + Hans Joachim Ferreau, joachim.ferreau@ch.abb.com + Andreas Potschka, potschka@iwr.uni-heidelberg.de + Christian Kirches, christian.kirches@iwr.uni-heidelberg.de + +Also bug reports, source code enhancements or success stories are most welcome! + + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/README.txt b/3rdparty/qpOASES/qpOASES-3.0/README.txt new file mode 100644 index 00000000000..561939fa534 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/README.txt @@ -0,0 +1,84 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +INTRODUCTION +============ + +qpOASES is an open-source C++ implementation of the recently proposed +online active set strategy, which was inspired by important observations +from the field of parametric quadratic programming (QP). It has several +theoretical features that make it particularly suited for model predictive +control (MPC) applications. Further numerical modifications have made +qpOASES a reliable QP solver, even when tackling semi-definite, ill-posed or +degenerated QP problems. Moreover, several interfaces to third-party software +like ​Matlab or ​Simulink are provided that make qpOASES easy-to-use even for +users without knowledge of C/C++. + + + +GETTING STARTED +=============== + +1. For installation, usage and additional information on this software package + see the qpOASES User's Manual located at doc/manual.pdf or check its + source code documentation! + + +2. The file LICENSE.txt contains a copy of the GNU Lesser General Public + License (v2.1). Please read it carefully before using qpOASES! + + +3. The whole software package can be obtained from + + http://www.qpOASES.org/ or + https://projects.coin-or.org/qpOASES/ + + On this webpage you will also find further support such as a list of + questions posed by other users. + + + +CONTACT THE AUTHORS +=================== + +If you have got questions, remarks or comments on qpOASES, it is strongly +encouraged to report them by creating a new ticket at the qpOASES webpage. +In case you do not want to disclose your feedback to the public, you may +send an e-mail to + + support@qpOASES.org + +Finally, you may contact one of the main authors directly: + + Hans Joachim Ferreau, joachim.ferreau@ch.abb.com + Andreas Potschka, potschka@iwr.uni-heidelberg.de + Christian Kirches, christian.kirches@iwr.uni-heidelberg.de + +Also bug reports, source code enhancements or success stories are most welcome! + + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/VERSIONS b/3rdparty/qpOASES/qpOASES-3.0/VERSIONS new file mode 100644 index 00000000000..4681efc920e --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/VERSIONS @@ -0,0 +1,106 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +VERSION HISTORY +=============== + + +3.0 (released on 29th July 2014, last updated on 17th December 2014): +--------------------------------------------------------------------- + ++ Addition of unit testing ++ Several bugfixes + + +3.0beta (released on 16th August 2011, last updated on 4th April 2014): +----------------------------------------------------------------------- + ++ Improved ratio tests and termination check for increased reliabilty ++ Introduction of iterative refinement in step determination and + drift correction to handle ill-conditioned QPs ++ Introduction of ramping strategy to handle degenerated QPs ++ Addition of far bounds and flipping bounds strategy to handle + semi-definite and unbounded QPs more reliably ++ Limited support of sparse QP matrices (also in Matlab interface) ++ Optional linking of LAPACK/BLAS for linear algebra operations ++ Addition of a number of algorithmic options, summarised in an option struct ++ Improved Matlab interface ++ Python interface added ++ Several bugfixes + + +2.0 (released on 10th February 2009, last updated on 7th December 2009): +------------------------------------------------------------------------ + ++ Implementation of regularisation scheme for treating QPs with + semi-definite Hessians ++ Addition of convenience functionality for Bounds and Constraints + objects for specifying guessed active sets ++ Allows to specify a CPU time in addition to an iteration limit ++ Improved efficiency for QPs comprising many constraints ++ Source code cleanup and bugfixing + + +1.3 (released on 2nd June 2008, last updated on 13th August 2008): +------------------------------------------------------------------ + ++ Implementation of "initialised homotopy" concept ++ Addition of the SolutionAnalysis class ++ Utility functions for solving test problems in OQP format added ++ Flexibility of Matlab(R) interface enhanced ++ Major source code cleanup + (Attention: a few class names and calling interfaces have changed!) + + +1.2 (released on 9th October 2007): +----------------------------------- + ++ Special treatment of diagonal Hessians ++ Improved infeasibility detection ++ Further improved Matlab(R) interface ++ Extended Simulink(R) interface ++ scilab interface added ++ Code cleanup and several bugfixes + + +1.1 (released on 8th July 2007): +-------------------------------- + ++ Implementation of the QProblemB class ++ Basic implementation of the SQProblem class ++ Improved Matlab(R) interface ++ Enabling/Disabling of constraints introduced ++ Several bugfixes + + +1.0 (released on 17th April 2007): +---------------------------------- + +Initial release. + + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/VERSIONS.txt b/3rdparty/qpOASES/qpOASES-3.0/VERSIONS.txt new file mode 100644 index 00000000000..8824a9dd5ef --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/VERSIONS.txt @@ -0,0 +1,106 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + + + +VERSION HISTORY +=============== + + +3.0 (released on 29th July 2014, last updated on 17th December 2014): +--------------------------------------------------------------------- + ++ Addition of unit testing ++ Several bugfixes + + +3.0beta (released on 16th August 2011, last updated on 4th April 2014): +----------------------------------------------------------------------- + ++ Improved ratio tests and termination check for increased reliabilty ++ Introduction of iterative refinement in step determination and + drift correction to handle ill-conditioned QPs ++ Introduction of ramping strategy to handle degenerated QPs ++ Addition of far bounds and flipping bounds strategy to handle + semi-definite and unbounded QPs more reliably ++ Limited support of sparse QP matrices (also in Matlab interface) ++ Optional linking of LAPACK/BLAS for linear algebra operations ++ Addition of a number of algorithmic options, summarised in an option struct ++ Improved Matlab interface ++ Python interface added ++ Several bugfixes + + +2.0 (released on 10th February 2009, last updated on 7th December 2009): +------------------------------------------------------------------------ + ++ Implementation of regularisation scheme for treating QPs with + semi-definite Hessians ++ Addition of convenience functionality for Bounds and Constraints + objects for specifying guessed active sets ++ Allows to specify a CPU time in addition to an iteration limit ++ Improved efficiency for QPs comprising many constraints ++ Source code cleanup and bugfixing + + +1.3 (released on 2nd June 2008, last updated on 13th August 2008): +------------------------------------------------------------------ + ++ Implementation of "initialised homotopy" concept ++ Addition of the SolutionAnalysis class ++ Utility functions for solving test problems in OQP format added ++ Flexibility of Matlab(R) interface enhanced ++ Major source code cleanup + (Attention: a few class names and calling interfaces have changed!) + + +1.2 (released on 9th October 2007): +----------------------------------- + ++ Special treatment of diagonal Hessians ++ Improved infeasibility detection ++ Further improved Matlab(R) interface ++ Extended Simulink(R) interface ++ scilab interface added ++ Code cleanup and several bugfixes + + +1.1 (released on 8th July 2007): +-------------------------------- + ++ Implementation of the QProblemB class ++ Basic implementation of the SQProblem class ++ Improved Matlab(R) interface ++ Enabling/Disabling of constraints introduced ++ Several bugfixes + + +1.0 (released on 17th April 2007): +---------------------------------- + +Initial release. + + + +## +## end of file +## diff --git a/3rdparty/qpOASES/qpOASES-3.0/bin/example1 b/3rdparty/qpOASES/qpOASES-3.0/bin/example1 new file mode 100755 index 0000000000000000000000000000000000000000..6a0a92bb236a494c7bbbafe9dd0767a1d92c0e03 GIT binary patch literal 32801 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

htO{=xh(6YKsu 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 literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/bin/example1b b/3rdparty/qpOASES/qpOASES-3.0/bin/example1b new file mode 100755 index 0000000000000000000000000000000000000000..f1a19d4c515cc9a87fab518fe5968868794398b2 GIT binary patch literal 31765 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 J27HtKzX5|-s!;#{ literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/bin/example3 b/3rdparty/qpOASES/qpOASES-3.0/bin/example3 new file mode 100755 index 0000000000000000000000000000000000000000..b10c54a32773d7cbd8045c64e10d34c3cae0bb92 GIT binary patch literal 30847 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 z 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 literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/bin/example4 b/3rdparty/qpOASES/qpOASES-3.0/bin/example4 new file mode 100755 index 0000000000000000000000000000000000000000..564bfb13c1d076357ad3aac2d760341c21d17216 GIT binary patch literal 34008 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 literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/bin/example5 b/3rdparty/qpOASES/qpOASES-3.0/bin/example5 new file mode 100755 index 0000000000000000000000000000000000000000..67c0493f8c2aa81031ac0ac699c9d76e239fb470 GIT binary patch literal 39753 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 literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/bin/exampleLP b/3rdparty/qpOASES/qpOASES-3.0/bin/exampleLP new file mode 100755 index 0000000000000000000000000000000000000000..87ee8a1ed82c272ebc3adca06654f738e83a0d3d GIT binary patch literal 31905 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 - Revision 198: /stable/3.0/bin + +

qpOASES - Revision 198: /stable/3.0/bin

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/bin/qrecipe b/3rdparty/qpOASES/qpOASES-3.0/bin/qrecipe new file mode 100755 index 0000000000000000000000000000000000000000..49be1d1d5539fadb962463eb7fdf0024e54f7b21 GIT binary patch literal 57832 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 OC--aqFfSk2*#86JBkkq@ literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/doc/DoxygenLayout.xml b/3rdparty/qpOASES/qpOASES-3.0/doc/DoxygenLayout.xml new file mode 100644 index 00000000000..927d94d2e54 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/doc/DoxygenLayout.xml @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/qpOASES/qpOASES-3.0/doc/doxygen.config b/3rdparty/qpOASES/qpOASES-3.0/doc/doxygen.config new file mode 100644 index 00000000000..6433bfd0933 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/doc/doxygen.config @@ -0,0 +1,1123 @@ +# Doxyfile 1.3.8 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = qpOASES + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 3.0.1 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of source +# files, where putting all generated files in the same directory would otherwise +# cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = NO + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = .. + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +LAYOUT_FILE = DoxygenLayout.xml + + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ./mainpage.dox ../src ../include/qpOASES ../examples + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.cpp *.ipp *.hpp *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = ../examples + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = RTF + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = MAN + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = XML + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMGs Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/3rdparty/qpOASES/qpOASES-3.0/doc/index.html b/3rdparty/qpOASES/qpOASES-3.0/doc/index.html new file mode 100644 index 00000000000..9211a5de060 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/doc/index.html @@ -0,0 +1,12 @@ +qpOASES - Revision 198: /stable/3.0/doc + +

qpOASES - Revision 198: /stable/3.0/doc

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/doc/mainpage.dox b/3rdparty/qpOASES/qpOASES-3.0/doc/mainpage.dox new file mode 100644 index 00000000000..c945b356e0c --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/doc/mainpage.dox @@ -0,0 +1,120 @@ +/** + * \mainpage Main Page + * + *

 

+ * + * \section sec_copyright Copyright + * + * qpOASES -- An Implementation of the Online Active Set Strategy. \n + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

 

+ * + * + * \section sec_developers Authors and Contributors + * + * qpOASES's core functionality and software design have been developed by + * the following main developers (in alphabetical order): + *
    + *
  • Hans Joachim Ferreau + *
  • Christian Kirches + *
  • Andreas Potschka + *
+ * + * Moreover, the following developers have contributed code to qpOASES's + * third-party interfaces (in alphabetical order): + *
    + *
  • Alexander Buchner + *
  • Holger Diedam + *
  • Manuel Kudruss + *
  • Sebastian F. Walter + *
+ * + * Finally, the following people have not contributed to the source code, + * but have helped making qpOASES even more useful by testing, reporting + * bugs or proposing algorithmic improvements (in alphabetical order): + *
    + *
  • Eckhard Arnold + *
  • Boris Houska + *
  • Aude Perrin + *
  • Milan Vukov + *
  • Thomas Wiese + *
  • Leonard Wirsching + *
+ * + * All users are invited to further improve qpOASES by providing comments, code enhancements, + * bug reports, additional documentation or whatever you feel is missing. The preferred way + * of doing so is to create a new ticket + * at the qpOASES webpage. In case you do not want to disclose your feedback to the public, + * you may send an e-mail to support@qpOASES.org + * or contact one of the main developers directly. + *

 

+ * + * + * \section sec_citing Citing qpOASES + * + * If you use qpOASES within your scientific work, we strongly encourage you to cite at least + * one of the following publications: + * + *
    + *
  • Reference to the software: + * \code + * @ARTICLE{Ferreau2014, + * author = {H.J. Ferreau and C. Kirches and A. Potschka and H.G. Bock and M. Diehl}, + * title = {{qpOASES}: A parametric active-set algorithm for quadratic programming}, + * journal = {Mathematical Programming Computation}, + * year = {2014}, + * volume = {6}, + * number = {4}, + * pages = {327--363}, + * keywords = {qpOASES, parametric quadratic programming, active set method, model predictive control} + * } + * \endcode + * + *
  • Reference to the online active set strategy: + * \code + * @ARTICLE{Ferreau2008, + * author = {H.J. Ferreau and H.G. Bock and M. Diehl}, + * title = {An online active set strategy to overcome the limitations of explicit MPC}, + * journal = {International Journal of Robust and Nonlinear Control}, + * year = {2008}, + * volume = {18}, + * number = {8}, + * pages = {816--830}, + * keywords = {model predictive control, parametric quadratic programming, online active set strategy} + * } + * \endcode + * + *
  • Reference to the webpage: + * \code + * @MISC{qpOASES2014, + * author = {H.J. Ferreau and A. Potschka and C. Kirches}, + * title = {{qpOASES} webpage}, + * howpublished = {http://www.qpOASES.org/}, + * year = {2007--2014}, + * keywords = {qpOASES, model predictive control, parametric quadratic programming, online active set strategy} + * } + * \endcode + *
+ *

 

+ * + * \section sec_moreinfo More Information + * + * More information can be found on http://www.qpOASES.org/ + * and in the qpOASES User's Manual. +*

 

+ */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/doc/manual.pdf b/3rdparty/qpOASES/qpOASES-3.0/doc/manual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5cadc179aacfecee0a4bac7b50679b85ebebdae3 GIT binary patch literal 710503 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

@Kq8#i|SVwmcdSHUsBmZ4j3 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≧kfCxHZPq;+2obia5%#+ zD8f99kxy-uQsn(Oe6}zxIoiCvEHMFo3O^{w6b~XdR0_OLLa-o%1SD&D&wuTFn`1YgHEaD;Uml9*TkhhLlU$SOJRksea5@-F)n4(YT{W zW3r*@w$Zr=ZIH*0`*c>~AT}6Z%tK!%V|b8viODOWkgxXNBnt#&wMHJUPmoAUt!mQd z6BSf%!(_jaId}wkz42^aAs9nL@JPGfkQJ`Dhi`124~9}YSTdlLE8!-#Zq7Ke69d@` z&)|@u^f9;qC6%Lt+}vT&<6FDVycFvfHPZ^at5e20RncI zVRv9xUz_gSZfHOwIon(pp6jdHtY3wIU-h2azW^AOYdpV!rpzfg?|WaohSmZ0IG;|Mu=cdYI!N^D7iFLXL#FWzgJh>A#2w7CLp)Mjh~clB_ldq~Kwe>9!_ zZIMX{ppV_euOEvvO(L=%wo)zfu$I!=);w`{uy1%ThX5jgPK3MY&{%y*U|=MP0x5xR ze6$a@x_h!V(a_o)Qp~hqv_SSq%kt^MNowlwU=jp%#DbBUY*n_R?bKLm>SIqdzS+zj zIh}XA^A7|bOLWSXzw}pd(O|234ky?+a1lDl!ypOYMU>~!NLn@>hT^9eYYUEoB9c4n z?BL0Jq*bjVwwspWJM@68`Pm~avsk<4oZbV#&I1Dr36s_xxgC-$-%;BYOwit7A?MYt zZ#+=snAf_Yl?!4@Nr~vRjVpu8Nw#qhj&^!DL4m=uvja2_9 z@5?GZlm=6mDo-AuU32T!q#dXdo*kPH^8f(43YX~b2iBfN%GjXq^C>uN7c5+B9m82XlZ^Y$o405sci<@T(nrrgHd8OLKhp4*2FhQ zfsWll>%Wbsz9*k${}B(lKcD@Yll_v<{)No^A(`d(e3t#kKK>UN=Bppyp_Ko;auG=W z{yPQ#&Gs7%17K#L`vSTA+PPr-iBSCy#%#<$QVGz*Uya$=e@y=W!I%}e$drxko@NcO z`}41EvjW$Lvfd}S0z`)X)tH3?D18H*>fhb|wE*~Ovj4)Z06?9edq@5er~8Lv2J%(t z06_Bo?<4=%tNABmAZLXGNXhxl7>I2B>oGI40!4X%{kPwZe=H>aVPwWHR2v|M_q*|b zygI*47$XY@9S5+q`pp>d<1zmqfxdszy7{wW3b=sw?+N@~OtAvb(;pU7o$5Qbv+QVh z87+c|a>v;Ql#0uS_D_fscd)c~Nv*x6!5wb1G%AXVY3gDhc3(^_AOQI?q_2DTz@XnU zW-@mqFK~-1*sduY%y%wqV5{*3^ube&Co*j#qFnaFN}3cnm?F>p_C`EFH&AJJ3YQw^gis!dx3Bi?QhJ`ard~k;MA*K=(H@n;q!EWgMr!t&duf6Jp_|& zs~CW~JxH?b1fov9xcI~q2`@znz=TOE_Dp>2a*{Y^v#>-f`SwabukF;Ly59}FR6~~z zL?8T$(HV;>Q}CpugB<^G@I+->Y+P^{uQHOj8AyIYDTV&a-OF)lsV4@VOOmt9w>#%1 zKDS5nvsX$-9B#2F%TdAa4f%1)t{2`B&iZwazDtO?LoffDLJs1cqv|C zmJ4*jK6+$1HR;>FM%q9|FQ+I^|0cKWiD|0U!)>|+UO|KaEm!wP1C=Gy9FHFw4j98( zfo}<5wQ<1kq6%}2iB{LHAKP0Fx3qSm$b;@Y_P07C@56?i>LWj1XJ^R6;0p_qH=0B@m;Sprm&& z8ChZ`STQk(F!#=>BG8+DW|Rum%gCupR{m@Y^)awN5h^SRmO#Eh5x2#!Tieu8kD-F& zG<}d_+Sk+Kb4m`kMlgLO4GM`;L81g4@%6i+)#U3}gQ`^pGfDDLTIkQD1q&RMd+%uJ zWY@h#jG{yrp#{1=TccLJRWyx+bcU8n!;3 zl_g>wNYRWCZ2!dJraW7$@%n2U?bHV^L*wJ3g2Aqr2T8bNHG2QD?0@No?`m zBqvroEG>ejEB*x4KW#TA(^Px?Sly~7F%FWwR=uZ7fS*V6DYV{VTNR9F&Ky1^H3G>3 zy_lsnh5rXjwG>mN-D>Bm8!In(&zq_`KB1x^FwMABv_17m+i(@3{GvL7*|){W9jAj4 zq*D<^D5GzBA~6>kC|BnpC+!(gS?6h)UO!ROLkffD9Uw*$S$Sw+J(jUs@vtJO@dK{7 z9x(|}%rj^Gqn!SDx9oEW_= zRX)QreD+!PBc?P0*%Hy0Ch7e=ycW0ukBhM{9wsqKUegJo1_`6O`+lj=fJBgIU8Ckk zLN~s(S`ATPgOj$zT$scqR{!jkqxW1oR?fa;N@R3!U(FakLEr&;qi3c(`T@GvWjk2| z_9LdVS}b2?P-J=(KVc0Q@?wVr*E_4B#*YGY*&|Yf2k#ECG8&+{Jw1p&S$Z`z)P3$Q z-Ool}I2jHRYN5`$zKyMkE5IfTdTYMVd|866i8RHW$7K+Eb5cm{0cMzLA@Hu8w~Z2n z3;kwn(UZE_CxT$p&LpJ3g3rzkVC5OvQ&P;f*bP6ctxO)!+&-8bj2M9t=>k%^uc|W3 zwy-L*jF$Mq27@s28L_)Kk-QgO#Y(>xm!QVQ4U6hKVU6g}o@Y+;)w2gBCFeIh5?B%% zRjS6X3f1CDK(O#%c`xsOTucfVF}!T)-jMB!a5%zVqp_~^q^0pMxolS$AmeLlxb3~f z4rh3B7(JyDg6-DuN{z)OCjlDvwkGyK1ccO0s*7lAlUaZs zMryj4)$!fwGxgfnCELttuNhn`Weh1I8GMII7|&z&kEu9`8gZlQ;b0cQswVZgsB_*( zdXeZ0zKqPfvwmBtm1HD<5uET5(py7gG(^kg5j4Jc?=-&I~ogLEHkCI=^B zcDiAhi#Le5bn;?Jr?uXd<7wcccZ|TMn>eVuwTF%9XEo(*#=3^QdM6`VLQ?%jk4cHmjXqY$%Y(%a7zy;?J>v#2sZ8=k5+09CKw6@RTfOjXNXVU)Ygb zdCPkif#?{Awp<5B9#BZZG*zx2g67Fc#u^QMD}{#m8IuW;k@bN$a+|A@$Xk>cD&t_^ z$F{8@FZZp_HeLxkGs104_R&XJroJr{fRv}gumO!nZkKCLlCH6XAHjbsV_Npu@`E8} z>!vTG&eO9xPCXg}?oZYFU{ul7tl{lZZif_%($@P+rxTj*;otB@kcTzt^?0Mo2>GTct zjclE4ZLKWLo#<>GOsRmC#1HI;E`CMKZ#Dm&A?^Jr)eoI-J1XGcqYCI$u$qu=K8#|rwtJdMUW;S-9w@gI96)#_?mjCV^HUi^M%Vz$;_{)=y9jLkctJ`c} zALZX?`yT*}pZH1tfyVTcUN7+eWBMk+_N%V%Pfg@6*B%~ z{a3;;04PHC_c{9u24Uy;tEEiz@0z_4DpHO>!c+5(nw^KAi6jI)+A5=SoN}^Bn)0y` zQ#CRRY;V#rvC=E8iz(M<%1J!@d4 z9?Fytt#BImte(#)9=Um)dNy%(umndYsygI!WK-#;VJB|_nrWcKA`?ecidAz#L%Fzb z*qR@ZV_K>X8S2;<;OC9|23r?v*SS4Za&0sfO%+u}%S))eKiaWNtKG1gn+GrkYs_?O zQypgjG4$$lol{#vxnsT{9kCieD+cNdP63LzY;iFmo}%X_%AKz@ru{t`h;iv|a>d1G z7Y$?*uLj|D2vV#!RyT5oA#4Zq64st_am*q@&vxnN$X~oLx6XKxlUe~JFXfC|F|L>_ z%vdP*rq)}gjy@+05Nag`p%4z&N4DpU&vSsK6t(iU>dPq##)kLou4O4M;7Wa=uev|r z58p7DC1JfE&(0|4y-tFwHP`34X^i=}Vq1P`#GKIX4kX&bKsv%eKQa#@>ytiXA-^*H z<{M9z+5&0JYvJi=zb=flmVl(mI&3g|6t6OWf3Ez4531hDhs`s?T!uQVpo&EY+J_L|?GDJ$33GwmaJ*A|*H!R*YXTpO&Wcc{7}u+~`=^2DRt zNA==|O>gh$GLYExA2IC6U*uJbiBG#wq_K3t?GSchGGNBvml-7q^JLC@!La z`xqlfKmbCKC@Kt=E_`H;_LLiM$&Asm`VBYBVPt$WJ@d|u2z5SGhDOjLTR&o`(t*D$ zU(CBSG^xds6gRicepBwCEiki9@_Javu!3-76lxh~ zjEI1)nJ66E5Z`>CgyChWfOG3)xa0Hpaz*bGTS00eWtP>n&YvdnyHCT$i6Mthu1H_u zPQYS7b=7p(d}yCcgb~Gl(XehXW(Pv`%n52?Awj}{;F3EsxTD)8bS0tkMz_t~&kGJ! zIU)*%v*EOD_po+gTRX}K_L($d4i6U+4HRJ5R_p|MG)vFV0`t8XDlBN94&W?nw;?*4SjD$`t6?o zDI*0ieoY|%TMo_-87c6Q@g?&F05h`RGSII-`~HmlKc*(kz?H4QF@RAH7)FSgf!I3m z(}C^-6O=DW-#vQ!U-Bklb7M0g&ceWG@JrhC&ENk|z5ydLBXA;Ffol6Kz^og%IE0P? z_KM0|2*zD+b^9UCg7^wUt{98i|PBE{zFXsDGdG;Ab(y2``?nJ0AFL~_rd=PXuvkc zU$1`;Xw35BY7Fvr8%+E;>4LSV^9ZyU2#BXNh%|_pf}x52-=eD6v8qdp7ZtLp6c&-v?o05463Zzts6&qsusdfY4; zdmT+-MzxgMl;||0n-Fu1X_$ni4z_DNdahw+txh-EIp}dj?%wnmsmU_&aqbD3u1~{N z>RZKxRIMy5-8W2aO!^W_5e<$ijv$aR(HXM5wp!2Bt4}2}%I4~` zx9lLm=UU?Zinc~7nWESg&*RK_fvq1izc`4g9`WWTFySVh)OH{lz%)TK#o>n8cx8Wi zx^XtU!_lGyiDI(SRWftBxyEI<9rSIx1CC*L}=7HVl|qNnZ13A}Z-LLSD#>u!D*>o+GJgKKJTOFP>!F8ZpV8ZeA>)`Bt1?H``534$t(^U%K7OyBXzH0Ff8kfZ>+`6M?xr)tBO zI*;4RVtf(CVfmnyF|k^QR_(#@^|e~{b9tI7B?JStI+hkiHe+1C2IkS$@C`-1WFKx# zcdH=D#;}G~kU8}@ta%%JHJDrUa5jno2B;lM4;_ZO8GD&W%gI_~f?PdnF`_mlTXt|E zK!n2r|1nY&t-xmt)5ir#s>>X&yglj`NG$WT1mfSh8(Rl*o;JTc&gS8vi-5CxMeV*I zjo9Bg3Z((Yfa1?=kjPe$n(+z(OPu6Mk7K;CLLxi8Qvah zNC-D5hIU&zHJ5GpN|Z~7r)Mjn#&zS5cG=w#q$XnxeCd01 ze5Q*!Q`fhdKSe-?PpaiyO@!PsudpZdvyHJ4CKvwKJzvmtTZmb6|HU-Y--jx&r zl;vai8&o*LFoqk;*BCPLer8?vAn)5pUNL%{tEXYZLRc9ZdPle)pE`5bGL*m(rFBx9*DdISq;mL2F7*;V| zvoNH9{{p^l*7UQ>f9>}3KM?6(yZOM;tC<@Cx9s8IfTI^THa9hM0!p#70{6i( zcXE_Bb`Y|)wzIYQA`QtK2QY8|zY(&vvUO0h(>DZer6p|aVs2=xC?@!KWEU1v z{%y0LyXm_{5EMyK2~iMGP*4zY;4hH7SrDNw-~IRk`})n7Kf%7gz`-HFzr4V}zWf8? z%L@z~5)uLe_!|P^%ZL2+0YED-2yo!L{_EFWD+nqKNC$`^I4B7S7%C_@D(Kxi5JC`8 z5OAQgVBnx2f4!h#VBw&^AwVJF!GLezLIDARga8490fPm)^yN+95Rg#NAfR9{u&8M0 z7&uSVlP29JFtLc)ITCAX$KkL^NEroinOs?b#(3X8`F}q8i!~%D1QZxF@P~A$AYfo1 zkf2bIkl)_`3Oq1KC{&>62O~3^eK|BbiDRXL{xiRr!@Cb42*A<7P{C0__&|2$94;75 zRT5c8LVKpn2~Ekh(_>UggD2S{(g)d?V*Dv-MP8>Q`@`9glbsIx!Lou1>z?Cw(;UN1 z>swX!BQOPU9ooK+ot*F}oV)|^nd)rh3xCC9W&Q96VxN*1IX4DGwUwQcdP zt)Dqiu^k;0L+Yhp7BTX1>kv^$p#I9mDlZv|C&&3%l)7}tj={voXhpW(Y|0%PSqoEJ zqyf8hd7{wD|Hs{1#>KI1?Y@mW!D%G8JB!( zYrp&5S!?fg&U?H0u;EJZE&WyrYai z260LqK@BJ*vdeuDj?w$X8a##U(sx(a#3NT7>ltCj(<9ANs2mRDMCQ%4P*J_oP=U_W z)g^U-Zslqfu^jseu;A?F{elJc`|tiKqWK>g78YW_6-Qp;AuL()j(rO~P->Qmzl`WX z>ks!LQ1+(-BCeK8I1Y}zXBeEH03+f3Jdc*s*i)4jh*ZDdn%MgHwr^1>pWE(5Zzkm; zT%6d^&q&`Z&PXJ4aH9IC6ctjd-M*=>=}bnM!IP=?=o!URTDbrW48uG0!D%_Q-K5tE z_)9-;rw-`Ywhr6+e>kB=tqGWaZVjE;HJ1dDZ&*Z9gbmKE%C#YFEt`t#GMSTqx((3{ zXZa}iX+WS}=+yUgvKbaVtH?e&GQ-tZXs4-?Gf4@`g#+hGo;}L!Bi??3SBP0;ejmHq z2xJ%wR4NE)3SfZ@qXJrnX{`#hg<;t!b0z3OS~|9qpzXovGHE!ti`Q)t!_v^ASw9TU|F6} zXDAK3I1_KgIEXCxb5=dTlnaS5nK@D<5Q7`dGdLq-6}fMisQ5_8X!bCi-mgT!2ALPw zu=z@A24Y4(#E;bw!@2~{RhFm3L@I1uJ{;+@%=S)>v)#^Un`uHjHB>7XyV!E$Ah<}~ z8gg#Z7HMu)Q8ceYi=^cW=1aT1lwB=Z0TLWvhT?MKl^c4aJ|nA}wNQdkH<2mNN6k0l zW&vX+uyP#ePCS8Z`R;MkM?x-@ZOF}fO(GamuTG6}cGew8DZhOheW~^^AWGP=&3p`O zW*rYPpH{*i!D08({;))H1Uhutf?v|Yq`2bC=M=vhAr^!XW|O}gO)GtX@WOOb;i41w zm~d>3f5ii+E<84cFTBQz)a3i&^$kf{J|aKF7`{+O8|#_}6H6@sksQ{U?@NGNsti=> zy3uwxK5bjOJ6byX-ouu@FV=#*y^C)+UL_(_mJt;+6~S9tWK3fhmSed=3o!%=m}oOU zL4cx(B7i}Z0Qaf}HYRE|#jRkqfu2v3RMl1wt)-RSmG72V+pI%=ru9KmIa!`Jfk;wC zJGw7XTW(Y@U?)w`#UdD8lcDLzkooc$lmhGHRBa)pyb&rCqs^MoLCnNH-mdh8VDg4# z6@(Yojykx87galO0_u+DPDNvgC~d?(w>v2<^r`+x%ABDk{?z|Hz)9nKNt&PoXwc@f zIp@U>5<+lYT=V$VmQVRn;nV1M&EytWDyj4=PON zUggabs!YbL16lc5G$N&S<)J_Nmd(RNR{5CYJh$^$!ku3pu1i+xWI8ub=;p!ay5`zD zf8Qhbs+rohC&b+0`@_j}n{K+}clA~3v_j^Fzi)n_Qrhg`%LN=s+C7dv=1j=Tb1@dWP#3x{q1)42I$qjZYJLLT8aX}>--_7hI}yJUJV_#JH+!FL zbqf)sRZexHt%);6Wxk*{^lA7#Utf=BA=Rtcnz8M6X4|Vnec05I)49%gm_+rSdu?EA zr=;H@^DzwVJ7~?7ic*c9i0T~deZR9E=Q0aA}A0xZ_v z&8_VN+x4mC#b`_3 z>^@x|%C;D!y7expSEkgZXP2tq6K}qMqhEPbRr8~-uAe?!ZqYAp;U#QIfvgLn8PDdr zWau`|wCw{MhQw(!ZHKl44o?$RET=AQS;)7M_DRbCuh;}XBjb(lhN(6+G%&O>5HczO zDk=Hcz!9e$Hm0aJzB=?Fkmu=%(_P;y$5^k@#lDlx$?uZrA89SMEjd zsXS7}vurdaF6;S(k?9P2045^$cG3VM;9KW@0$tN%j&`Y+kuUz_hjoh`pytxL7W@0n zil$e&T#R)cjH^D(nM^n@Bhjcyr36gTODZX~Z!^G=W0m}N7;L&B@oTYgI|AM>KFRbl zwtwBDn`CAaaj(Z-A~q2;KW=>qt(sV2N(rEZR){`viPLV!wtxmcwOQDvTs~zeCF9Jh1P3sE=X40OCy!img*MWMkmhCSbLj7TTuZl?9lp4}41NH3 zzqlvSAlO#zm>wJpK58xYn$G^VycoZ{Y$9PzC!!3^mTk_dvE=bE#;65h#!~gB&rJDePg(kWMF( zBwo~b;=v}q^vQAAO3iI<=75dNGq7>jy>JNdu|04v%Lu&zzb}M|L|>pTGCsQ+T;Rdf z;3Zz+_Z98w+OGUF54n}c&yJ@#wCy7**}~>F77l}UAv=@&-Y7hcplS2q%1Am1BxpT# zG}%JE!U*9gny~;g9QSYHeRupt1LEmqZRCR^n})6SH%0W#u*u|iE~?Va3CB*&GAWXT zvyDqM%-9T&?&LM8Bq*_{=tVs%5P{3{8=4OOR+f z+ptVq_|che(i5GQ&3Tq_Cik4>wZ#tGYqDY3pY>Rr;0d9S5D0#2-FZft9lksl$y99J z#DOl5@CX_bs++u8G_V+?88@TxqgCJOIs_XVQo$2<&@8{fRCUq>4FIqG)}etlwT#B2q;Kp!*8< zlQQP^eUx_WS(Bd~*rC`rTTRJ6x9?tk*X5fbElyLrGji)I=eutC6CjI!f8y=-`${nE z4iquoV{_6%c-j3#*oT;Vb(P5MSTnNtA*sZbBz)casQIaCYz2TzUpri?xJyTe}bLXeD6&MOBkEaLBH)c3jCT#v1HYU~#8Do)JfPAB`IPl`l z(Q7a&0}>M)0C9L$k@4#Cm?SvOf#J^!?`|6E{D*5KwvIVJXQTA*P^NHFNwP9cz!qDp zCw)u&%z>^An=8z2K0GT<;f#@lh^+v{rb_UfOrl$E5 zut~kSMpz6so8^$E#&%8x8~PohKdPoy_DwawTM z%cVta>MI-{A|QX{_hOycqVY2lg=XUCv!D5>2WsOrw_QUruCG^qh$;5&ne^GmldYfK zdv_zhe*Qg1J=`I=$3qHq-m>+Jz7f~bdT*;A^c2nPqiW-w|NOEv ztYWj$!76W7YcR|2V+h06ol7X0twb;y8ttv3y z;s+y0?T$FrI_y8g%Ak)KU3Z|ljEe&x#J-%h1Ul0gK}5m%j$aSR3HOi@eqheR%MStD z%o6g5*(xAhO?b}b8edRG3_#B~^D59_xAvrvere>NrCWfJqGVyCqjmMd-Gk47q@r@L zX6%`V0l2WJT9EL48W`C-Pe}R(;j;(z8JaH9N{1UvJiJ> zU1Tt4WC>VkFgYRt$x??0cI9xpLIIMK3|1l&ez&BbSusq z77BE_1+g?ezAIUUImziMb~)h-KfHPW6HxXdc$)Y(O`5ug`J%W6_YS$d?kAu}vA3N^ zrX1G?Mf;K-;P1lqE>p8BK%`OU9!bmG8AY1k9Noe`cRq0eLjkrhtx|2^Cx8Z7Z`2fG zV>=41;4sV+A@n>>>(F-PzU9;#$_)J4fLLwgEnjMDBZEZ$CcfHc9C0{QRb5>*5Wj3L zWg-KURFcKWcVv?l29xi4ij@uQKfqAuvvJ>juHljbqkcwREP!&WIXf=7fAib&txbiH zy1|aO=+>sXA78V-p*pVL&MDfgAJ zPr%$v#lXycFa1^hBKXg~&ZyqaJ7uco^SpiA7|EJPeZ+VglDd&yL5qE-;-Q>(QQB`o z?XW>9B(ij7XI5-sYB4!u`;UG~5ipOM!_`BJUvI(;13q(bB0*)XBi1)IGL34}^dX`@ zmgW@CC@3qiu3u9nt#?N_W9GgcQ_>xG;5w?$VLYYl3sWDFGBo2c<>rE3W8sLo__N4{jH7IO$EDHkpXVtRm< zT#QL<>iCi!3=-c@Kz@sRFTRtu0)hUHvo^==vihikOvjLZG*4_ox_Qq;m$Iw%$&VsK zrqraq5)``%Y*5YFQMe~VX0t9!VI#9Z9!s)tFW<1V$q9!{K3|R9_g4Oq zozQ|$9hDTwloE)nH46VdD?#+@#pAV19aZg`KFKqQ;7ekD|L)P$5)PkAzRwviPrVco zxn%UHqTf|S$AgRk#c0aL)4@p!$hFLxL<^HxD(4tmZ z_1ng@zb(_iL;X21!|>EOqbg!+-baU7Z(iA(*L!7Tam$LHIS|FW4Rrsj!uV=!1* zqHge#CAv$l?kCFbZ>;d!vYJ@QUp_UcNo;-7K*ckQhdwlJ`y6nsd)yOd)kr0=TQga= z935phY)+!K6&yVe&~tA3YV03i6q);A8hdU;{iu=xE8q+?Vcq+@v^6)9xLhL*k>kFB$9T2qwrCHPiXmKHz$ zt^6-z2QZi%HP4`kUg<$gBYjM28XD||8T5|wRzap0K9r00Rv?yd)Y68hA+pOK&f9cQ2dHrVvHuv%nj#0L7NnSG5@Hd^}skvdq`R zCr|cTKC~eGglEcjUg;FKs@2b>!VXa9MwC2+8PRW62P}}B$)yh9v=n4jxrK(1WF~IS zo|Dm|_pE!Y)NYz*N*W0W$JYiA!&Y_Lua;^VT+)s?Ov;K=UyTcqRc^RiCwQ+g2FVOF znuiU}U`_!zqS~gAjaPiXl!&&%&Ye^R+@qHT1C*FVXEu0!X=VMn%)# zZIXthhV2t4$B$R!7fHLWw?#^~Y({ZhJM7rSyBAmU2e> z{6s~Pez=|Da0*{___uCb*$T?BXmSMDST}qpVnQLZG>VlR5!|6^9^G{?_N}>;wrjBc zDaJ2)Z!ckXOrBgm5UgwrQj?2yZY;3E@~`8yW(c)oj0ccB5XDAUuYDgCm(|zyyvQs? z)Fnj%Lg~Uz=Mpf$mm*sqlmqktjX>uiu=GbLIE=GL+cHm+bZlv5q5ItDC9S3Err&z= zRU^3Ip#+De0>BD3_BKXR>q{^N)spqPqV?$mQ3q4u;A7q0?fq22m!ANpbmrDZ;MuIb z@R9@lvL@9K{JH(f!Su*V()MgW>#8tE4KX=&Bt?Ge=hs@5P71Oei431%q|L;k4y2+3 zWWGaZi4qD;;N#LstKR5;`i5yse+nQ#06K8NL^5O3zW>kJrk)?pF zAKg2TVBDwYmZy!NoevV(qGhOaNrx)0{p|^)@Y}N1J*z|MJut5|cN#k>X@>l>)~ZF? z2Qrq=*^6m$HC@RHDJBG}kIy~dT+sb-bab2AZONm815J#V#;CYcG|@zXhu6&q^50Tk zKMs_m9`oX%te5RDHtM*SPuq*2cg!Rvi!f;9#l1-sT>Iy|Fi-SqhIQHETw7u`++E1`@b#anPu^g?os!$QS9DOGyoVpJT z^}4=+fbA$NMSm{6HbK+i%o8Jt1XyizF0;Y1P@z#iUWT;`g@#_f0%Cf;LqkQ}#A+Nq z9n#9@umIoDQ&#^nq$7xKAu(*=yggOFa$j@SojpRXHR#9Da zlRJ{RKAsHXG>G&tGE{}LZ$N#RC)4ME_G$r{9^k2v7+{Cy2f_N)bo}nRC*6kgOJxDG zokjDfYnNlQFl%^Om$z0)ms$#BG`UWrOZXsIleL7xcNrm9V_OL6s~KK~r z@NR`PN@y$5JwTadPEKRMVU`|0(Jm($n9q)Y`D5MWm=o`w)Z+B9$J$&?5&(gWMd~CQ z>9Vb}ef0{-l&Xd;i%Hxf>N>J|%|I`H5!SUnO(S8fk{*N=Q&LU_RFVQQ;lay|RE&)k zvk~@aA!Mqv8Ew*sv1FKMuK(S@bU=ILid!WD#&w*(+`?C}n5A>Tr3YWJ4x1FpNr$<} z5~ljZ=#QeB3DLoR{Ns^XI-3Xyd4pro1eO{M&sYA`PfWID z%D49CAg;UDyLBw9d2TibQWiI@U9U?jdS^oAj|HL$IanduUz~~B9mY7W+Cw|H-{b@z znNJEUh8K!Ow=_yen}QR_bGK2})VFsc#`H~VaXvMBdrp*_0Q+UE)Y^ULwacwHP}yC9 zvbAUm3xe8t{D0drvp7{eg#(gZUU3T!Y)VYE#ao>O>c~}IM28D%^40Wt9VXw6h^_d1 zA9jZ%zTOOjoSenRNuj6c4-|eMi!@~Z{b&OhuszakxXQw=_fPx73>T#0wMv!|rIL%6 z>5YtsJIL~x`s-Rvq)jRq7iEGXmSYNg#P}MKk(PKZXU5ZTrdU3%js21T{2HqH?_}t| zR)~Kt|A$%8Kc*-DJjM8bt1$Vc>fizkE!eriN(j&&0tpb<+v8W^NS41t=&X#L-kQ5G z{Z(D^kJ-}y7}ozpT>^ID0}C^_z&;;fz>w{iH8l@7Dlp;4{mUf#e<&`oH@3EW>-fgi z&B@8p<*ksjlcKPyxaz-aOSt}+(fyCH{-0}0*ujK77{v#Hez_2Gk+5@c{h?3*v9W`V z1%C->{sxjXbM*AGG#R zn(h>s{V^5)f7_vdZZQy8b@hiY`Y)9gxYQ}Qw!$x4bXE{pmBaI& zvC@A9_HS3kA5P}~4D1&Z_+PH>|AQK@tbeNS_ix|*-w>t0pF)50UG`tD=>JI^@`s!K z-v<4U9|pGx6VHDz&gA+7zxd~u|0BuBEb$v=`WIXD-*MDm#N&U#6C`|mzpx1~iTnp( z@xPE;fVVQXG#CAoClS{l_M88V>AzqKu=?wNT&F!(`xh1YhY32l<#-<&K#{sdy@73) zTfM85ty1mujsI3c!azv)glOKfVeh&Xpb#r=cr-Zxc4__lBQ%yLFZ0DlwSm3H;(vRf zTO3D{m|ORCQ+&>d2yLV7j{kA&=MPkW*OKPELyi2-^rxhonwv)e!u{#Ws{5+`rw@)- z4c~Og4(z23Kb&QWs%xIceLY8Qw`_lGe(-W@()KfOR-(ITPnTdwz$-^(kS zC%Xl2LEYE+Q68EhrD6T;J%_*YKp%I5ZuWCLec~f*gf$DxTU|1{GWvRY!2B%Vd!mnN zJpMC+WFC%;Niiixu^g{5(O4TeSb9F_gbVL%YP_)Yv61HM+>PLvaL10J%5Gt*Z_k1gD)e8|3SqraNmjp0?QW$nnR~Ma@8m6k;^~~_8 z8RT*=HiKxsH`Yb*ALZ#LIIC3lyrFYFvESrye+7{#yjHf%lOVpxo?+U@;6)V9Z3^Mh znH4U44!=rvzsn)D5pMk)c=GHXlE9BR%l) zxu-9m`Lo7Y#>h}HJmYW_-p~g|b_b_#Y%MJwFx$yEI7;~XFr773{ld4=M+tAEg1Dkn)PWhb!OAt*9QqeHwvei47nv`%rsicvq<| zsj{j|%^JNY&evS2)NizpA5#*NG+)tA(m~FrUxp?`PHo?mTU1PNI3-Qz4_Io;$?=+%U5b4X$*Kx-?5gh zw;>ig$hl1oGw&En;9tM3{6$n7dkL|t2-#{N?!)@P)0 z#f-2qY3nj{xAi+EP+GEvT_6y8HTOum0#!W_+hr~%FsMVvX7`MW@pVt=Q0i0A&;?9M zW^1uOmU)Jwki`6~6VQGg<|Y8W2?u=%g6f(Hv@OvAZD*DAb9$m8*E$d-sLULw#b3E*Cjvn?UXybt^IUBSEaImIp2&T)f!&bPOjNXEErG)j_2o3H7i;Ndm= z6e;cNX_fodN%*;xMMYS%#UXdlmiHd3aDc`P#g`R#+Zoci*GTmW z1yE2iu=vU!J{s{JcC<+@G#Lce=-?Ayd#h+fpK1$belYr+JJ94lj@GKGn?Vr_BjTfu zksM3*&W0Wtr;*z3>{{aJI@#u(krBn4$XCs~)kG?7_8Kt{rkZ&%%!6A6szu(AmY-ml z8lhglX!6~dc%_wP!)J~+n+8lWN%jNFU2d!iGd_gdxb}9!1P{%6^`H(o6UQ;07f^p?LpMMs<;=YVhy>v{=pokS* zQL82e{FrD1Mf|Go+CiuBg<62?Q=%ylq#J zFlN;EnqP!N9+QYYn+gnqe5DO7;yhnk5xR-H=EIliL(F?ypBLF6kQA|UBx9)aVbyRy z^s4Y4&}D=mQW-Ek$U&QL-LPD=WF#@5HxUTls@LXW1U$)P-c>IN&d}*pR~{p*B50a6 zc(2kROcqg?gPbZ#L*CLnhY#o4;1b*hL{6+T3%FcHW<{B64lGtCjH10SZH2d*5OI8c zotzGkLfg+z`Z?t7nWMy(_UGz zq|=?H;bpsii3w7PZQ-DRd|;rDndl8?nLwr5s&A#_RUNrOX1T!@miPD&yTNPa1CA68 z@6=cNNNr5(?Y$&BFJ?f2Z!eh2**0xlHzsw=mc0AklH}!}bu(Mpz7va!tBFg1mcRRR z#whpP8AjNh&1iD8Ba=gow-tJqS1&M=&zR3m`!N5Vm0KglA8CU=W7{f)+_ye$=$JSoJA?5Kz#Kj|{ zU~MM{aSOLmN_%)kwhptgD|3j7s|5ZnYYPbt`-`>Z|HayZ=~@_QSa?{dKLP=-p+m!9 zkg~!GD;qmwk_8sPfm{4JzhiCm}>?)ZHVf7)Fod*p~r+F+4NBmVoPh-4P>grrdhi#I&97Lap;6^NQt zyEUdNm2^W(P087|$VC7a#D#W8L;rwQ9ovDyDeF5#-J020sR{34{#fIBiyM?{$mBd=x40(fMl4xQ#~yyT@lU6hRp01 z&))c<)wrxgW;Ki|?icVA82Jf>EPV{0Xj$_Kj%_n5l!Mw;=UY<&#=>CP(haGYgg1 zVash$=-SatZE!oT<2NB^W98$W#3WeX_=b*-9=+R(apdp?UI`Dvg1{EbDRhY_1y0`` zm``-qg!Xy;Lc9=lMt&eqj1!{1TYm%t;pno0fJw|mMC_Qp9iMYJ;;FDCu^)qtQqq0E ztWtz59`dbU)%B_J!W|Di+$$=N6Iu$#NaJ zne;*#T8T}-2%8PU-RNj{CqKEUEk1jRayxFiSS=M3UKrg6-Sn&dd%v{`8K`(`+?`w2 zpMbOr!MUBP29*CVI}#iJK)bkzV8<>o!I=AYiea3TrHob=metIaG4sr~1X5KUXC_o? zoCTm#)p-_q3VGKN3{yA$p4TT+kj~VO7AC=Lt?NzHuALvYxZ4$8%;%GcCn#n2UXuGL zR5Z~QU@aP;%M~veO#~1j(o&c6zE-|#qv|_~fz7+w7k#IfK_Bxp<1}W0eKGQ*=wv5VgX&8F04eg8LD8sDxB~-o3I;j~4 zX*g=GS@E4cZRv*Ri-`-O4F2hN9?p%8ET!2do}`0u`_!tbAc7&)ADZ2@Z16&|f)+mk zM-&`F48f?jYfv=uQ99)M-cZ{kqXf6cX{p23I~Z6h)MyHcM0XODtc50_DL93PCv0_+dX0wfI zL$W!TEmOE2oIQnyxC67X{%JLKr!MpI+XA_4_oj)FKLHKrMnCL*)Mq!~A35LuzS5?W zdg1crNPH-q(6R@J{}6YDDTv7!J%)!%x&PMLDhE+Cf@Mt`VI(_>b$NMi9-hpc7TwxG z)ESqq|15@eE`U&b0DdOCBBL&hN_!$>`1Sq>Gj49BYp6MpO+hr0+so(UUFX7L3I%r| z=&t$AUCV$>(7BK6Q=QN1b5-@LBk|MlRRIK{u(RA+6|~YoY!$fjIdsrW)*}_k)N- zu!H!FecOqTl3r}@+zko8t;7;j_K31{mLU*Hg&dG$4U@_<9>u71uiJ{GRTCEOwfm^0D?U&c&WXRHT|4>RlnP50xx1*xuYXya+!JSnHF$r#UMRo*8f8kX ztX`X5Y0VfhD2O0LoJhqDddCr=7OLY(!C9<{nQ8L;&2jg5*((OtMXQ8_eL0p!!aysP zV$0;=$&<8i8+W#z`dxjfBHgUit!q>iDl$Qi_bc~xg*8tNxHca8FmL=0Xf@igQ$I~g zU#u0#8tn9^>=b_28AhcfoPTpWZ=+_L>~?$R`+?{F`@7|pyVT5!)9-!*jcE+R1H7*} zzx@#Qb%H`>=4R{4C7X?ztM)j-&}I0r1+a^r(<5)!+RK+JdMY5fT|41Da)O0|L=O-K z!V(}u0jf#j7Tb6Y7JmYG4Z(EXcmH0y1^bz(dCB#3?okdJdCxxQ3A1#`@X;$z>%uY2 zm>(4{U|bl=`G1-D{QE;v6D4ky5U;Y~E9BHQi}*fNPTIt~3AWdWZTMbmEt03fqD0Kv{WSAJ;-cDvw*$>CrV4Q= zjQd5?f$Huj0Ixm{6iYL2NpLr7YrvKkkefeV4)+{AqG|@K*ZwFDsP|a_P8X^>5gFUO zJ{=L$6}#jl8C)WR{uEt52T2=qd1A~JY8uh69cgMVZu@e8w~j;LKFO{(WPP9~k;Mvc zfoy_3=+k@gq%l3Ew@{?gtBLon1ov5%42+At>rhqx`ckVJh+}CvzxToC2U6GWJysR& zSLGSnIUhksDluj|*Ap-MyseXHJZ9nrdw*3QgF9qYR5la}y2wK#?Uyy%*D+@SBzakj zXZA&JOVp3sUR&&&G->jcS4+^+^dZ$DlVTNN=XplS@;GMOC9%ZdkkQI$B7i|{A=7Z2 zZs*0qTMt7 zR^-@q<=oc@+c{#kpS~BN?-CmMhETvfpLjvqgyKJ#tsjOpej+ES$~EcQ^?7}0+prOz z&NTlpqrkYi75j8e9QbbWgQbqDLAGY~{PMCrrMoUQu782?XiKO;IuhR3u5@Q;Q*7TX z{qctpm6SS=0(f$g(8d%w!i>9XkIWAzUcMm7{jzyv$7RUu3b=ZuYCke?j7|iRSz?Cq=>Rjj%<}%&G|c~;EbBEx z%ll^g6aDPqr@MI>^}JyB`LE=3#*x#^HF}HKF4xXyX*{%pL(b#dN$k1K@3|I-d!HV# zj`cj=p`5554{<=KDh2Ybi5Djhi^do4>^>p<^TahZf+k6U_fW@BTUU z{9VOM%m$mtD_yRb!I`GmxqZ=~srt zpM0HsRa*~@+DLYba`+0ROt}-Tp<{Rb*{Zd*SOcOCT|N_m!ZTfPWwBsiy3!7crIr~$ zUZElvo1NX!i?4|XbZ$vJ#^^N0nkF(P@Lh)-)5HeT#eXeM8 zQ&J*i;UQikLWtJSNGXzXl9J148Zi^Jq)CEg8^n?TE1%#21bz!GHQZQWMqLuzfA zmw%tm>)Kx9GT$skwyYnF847+=p)?Cw^1=d+biF=tj?8=AxOdNkv@*pM|9YqS?C|Gn zSG#7g>lwY*-}Hj{@jm8Q#^zr6C!qRBU{m!cU`j@u`1$H4{yO0|EeN>(v5?rmQiv!E zx-FqN=1IB1Srb-c5`i{o9TjS6Qw9tLPC3QGUN74wq2F(;UnQjMsCRgvLhEss-$wgV zzj?e_jPp!1O|wI681#}$w66=GQzw}vOv&F4Y2H%1@cW=A>ZU_oTkRlvbbnTL(@JtEiBSN(%v@~vT1KmT0R46{t8 zHw^7UfldzMbhVU|T8V~oVEs6I5tL7e5Sq9#v~c&SkHKQg@lth*dhv3)dMa(o#nvdJ zGL2tK#@=}`-k{6ji;?$f+yS8;$4D3cF@lo$kW&!sPXN~R1~PwX!ph?75?}J(rImNQ z!hzRzD(V$JGR0j>F-SSEnIDc?#=C=TG8i%vBlA?^TUJgoW<2MhNxG+`vYtQL={I)K zrPWzBtFgx5R`mz8b6d#DIXR8Z`sm6IvtAk zd$j!Bo8{qffe*(UBQm$XyrS=^>Z@bHvsmA7lPG=ykYi1>KWvkkRhWH7m6AQjl|&D) z03>9tXP8&>y4F!AzC1k4oN9svZ#USU{}6jVl#CP4#%a}P=Y#4-emp;eeWj*p0W zlJ|#TO_n}b{`N&(&KY(2d{0xH<0l|eLvc#0j(Hcs#xtdg=lHVoSqx=8ij^vn)YwHA zJB93Rdk@JZ9Do~;dW1@8Z55~Z%oCQD-;HUqBOhVtLQZJ*!8niLQg4{K$M%kQMG{y= z<91FaUo_NJ;u7DQr`x_Md(aTL4{0fWN~@DrCG4V7r$jDwE)@3xtWX2X@j8Dg)bcC# z-ue53)nj0x-V2N&LU2rLd)+XDcA9Zyt0m@k$3_+Z=?}`$4h-l4T_S^Mi5b>vAJR-D zpOs;;GlYIJ+p{rGi4BpDuU!+%)v^|py(W4{ra66;c}FuP_3x4qdHYM9V|<4r4=*%u zV*=CjsD|?;(ZmsS2JQ}tya)=*u#Vn^x&MG3C-5K!Xq&Q-hztDIR%%y*y@Fuj8d%u& zBdD_E!tSc;uK?hJ<-*X53HY zawIf(gpdNGkTMEvPEOiJS|+S~fmKfh>|8*?w%_}-ol17Qro+qo73r{Q58G;1DJ`uK z)nbx~rzzsj@T@fP8VSZ#Kc>)*dZ>dD5K#D$1quiY5u(}h4lg)5k!6i5r^N0}a?{0! zM7&w;AKS;fuwIek1@=5Mf-sEvZCoq`RB~Jv#a~g9SQvCx$rL8f-_j{`nn{*39UY&X zz+v8LVZqUf{{(1sp~p7vVM;}=o+N^VBa3)csH>~vPG;RuYLg%tsYsE6lG6GJRUvXQ zX5}<&Le`gq6tKS~%8TC}Im8u4nmBtYeyWZ2sy&CB=$DawRWQhMjwJtnaS2m^sZUSK z^^SS?gtWKc(KOIL3>9 zMqNmL4UMUU(|QRri*i#97AAoN$17Ma4f9v|BjuqxPl;lxXd4$I>BcdTw61SLhzMmR zQt6^AbXMIuqs{%UTypYs!CqzGR()6f87PwazM7`BRIZ-z50uJR<8`@T!LII<`4Lj{ zvrvqDH^krNYR?H_TOE#PDQU2v`b0xA;LbowDIRKsdVrKsOXA@}pl$mDEcJNQ`3cz1 znyZW%sb;gZ+0ZZF$fIDfQba%Ltav`F2LK&l1RYGIuJ9tz*@*M6n!c#af!EOa7dOTx}A+f_lqDO=()7>VRiEjSn=O-g!UG#sxt~08d=#YctVY>^|2y)G@-U0 z!0J@6UiNJjSk)`6`loBGS}{h0|2^k!IFKs)oUdNHPJd$Mgeb5F4$@IOEuTi#n&9}! zZ+?7~77c&kc}TlrBW$CoTsh0D%8O}~RBzgqYxI4=BS*DqHg0J`e znOEgmLMswkWnY9RnfAv?$Pw2o$^d{1F1#L_u>jZdJy)P-mAxl#6dNSF}jx{-|Z{@OnsSSQddx+Q4D!0obU|+({o%`r30R~@QgK*{I6j~Jt zKu-Q_VQ>8aR?maP%y0LohZoC18%`*?+c8FW=*tf`8kbnK z7^mvFQ@E1QUFE7zqIVLCCsEf4fZxVQn4jr7O=X>xQCuGEpj^vIQF~vd9OWM|gyY#Y z1^4&o2gH=GB8bn{%+s7{cskt5z1ebWZ(!9LX+jBIf(?hCC(a}K5{X+Lf4w@ zPjS9z*aJu-_+rZeS1Pe5jCo3#ibj)?#ydXyy04fe9A37VJl|gt#=a5GDee%Yyu^+A z(MZ|uPK`TRAFe0ZtQ8Mw{-L=Iy;1g3R`)+@Im@Ii?Kv)yWs!tdvk#y% zXo)4z@606R{kO4ILBw$NBkzCs;?Om)eD%6X&F@aUJaq*(TD zxdB)5Ge|bl7&Fv5l`^K8vw*EjpIi$71c_O?YrD6fkF}UIW=r;>p>haj=_$T&?|9E= zL1AC-yQ9G}QSLPW3e@;VIlGnai9mw^-Q{4l~R( z`f(Q$^Hq0r{TbR7OaSCP=r22k8vi|SP$sh5mTvSRg*J@2uEVZ=O36Q?f)S1ZtqU#; zLr&Ac)S09e2%ccaNmXZW?9iGhr+A6H>`cJ?cf;~G?EGh zNg?**`8jCm|SbtP;pvgInpkPfgGqQfrd?6a@i z33jdY)_vFGk?28V#pc!bWaKdTl%1b|5Vfd}YB92yT-6kFGLf&-wE8Bf zbR4=A?Hp%64>^0OL|d13vM;hfPlqLI`JtM|c{(_R(T3KWe%HiDnWSUI6Ttz$Yu689 zk0lXcy*gVKU454KNqp|@B)~7+20)?(khXMaa{m4VsC5dDWDo$qHE{B9HaH*?(~FX! zuLWa$diDKN;wIxk8lLKdvb&{Kqefdxxt)4W3YEf#vQ+y@yr6uzH%V(?|LFG0T6$nh zOL2(8%6W^Gt8g~Ee?j@e+XncQYg8lRp;oqu>{)>*}E^GC&*?Br5a zBX=>;B;9OBU;J85t4L%Z@@o2LX}@?cd{F``a^DT*>?xNm}Sqk> zQsK6NAFfCy2ix>M-7(ObqE)joIBT*gUV&3xvHD3(@LX5`r3}D`hCtQhhAnZ>6x57D#{TSBc2R47W=m#A@sk$OIC&N=F!_I428;q zHmVN~9wrvOL1F2}cABxkA~w7rAyM}^BF}xKmKT#K?%PJJZw5< zzx^!4P492*GJLa}Mz3K@%pIe!^?k~nn?wGJZ;Up6J0@E;rH73vdqjDV9EFJ5z$HoS z2d#Gz5=rgNEi?w|(&;M8&L;;G>>8h@!zL*|u%b|D8f-nwc8%fGv6P0463l+i>EOUM zvJx0dSQIsH8e?2R?{uIrZndLGYld9i=;gB9wTJ1HLplWJ@nTC;L=CPOJT!32; z-u`CT8P?G<6_i}|u8JnjF6EGBtr(vTsM}F%IkF(|rYMegA0{eA=W7;jkKPR77p@Wy zRyI)^+iLpy5|M6<>*ZpBMh?w#tN3=+DT{>1k$HoHLV;}|HPLnp>D79w%pDqo;gXoK z=3Q}vo9QV3-JmQ>Mz&PcX(@Iy5ane$MKS-{g2{ZZ*GME=Zg-|2{4ncb_IaP5tzv|)Ku zd>yBts8HOEosH+u5|pHMesr(p6xh>ykR8-@zL|3jyZJe(iIJ5 z^2EVLRBiv(fpvM&5wMZmM0=T3hc*r2O|?y~ks?d*1>|yWqcl%&3F*2mwrO4>_5BlE z^*zU%sSox*1?e%`=8j&I)-$Z%Va22pv=jkJ*O^ z%6K#Tcd(0HxM=cN)!>UE-b&?EYd3~StMSH)G-5|nyCNBvCV}im@2lT@dl%kf;KLri zAW?aXf_{(a1s0ZS<5$hGORmu?iNt%;(tEC9@phtwdWdE$6-SaPm(GxeZNBE(evjZ7 zyR*-*iCzEyF!$C`Rc>v=FQRmJN_Vq>MT3&k-OZxArA4~COS-$HyHmQmq)Tb>EcgEQ zdD!)g_q^Xf$A1{ZdtGDBd)9r`ynf2Gj?Q?o7!>oknAkgOV?!j9S?BQVswI_~W2E0> zO4@`)yt*@=H39kSVtL0?V#l3HJzaGv{$4n5%Izd~lfiLy1fa!{8sVJOO)tXK+A&WC zCMDt2z^H@+ZO=bD7})6hVr{;y++%5_)YuHl7#QVELTK@Uz46n%eed^Dj-b?$8uz0h zu851w2;-Hz0DJ8S??FTH8P>XRV&Nb0QzQ)7NgJ8i_n_zZ zUTAh&$POE7^qcib<=_smN!lTczoi1DbzOSu`{_uUJ4CgTxynWyWWmR2EGG1Hg}h9Y z2!(_1rB_Y>h2Z+wJ2_Jo8;P~%#(m~>$>Un)l1SsA6E8D19Fv?ge`VGr{q}CG_)6sB7#BG25&vu!8$Y|+0+*XFsk8?SC}KL3%hhnJpT z%44u{eDRq(0P`e+?eWs4{03FJYR7@)ww@;%J;vje?pt)RYz0--mq>xh^1?$h@fc>C zeEjVL6mv!$(%3=Ax7=5c+OSKz8HA z5N`!5U)|JuYX3rPGx=i`2rf}JtG+qK>uC~!8A0bpOR-`HV3RX;y|Cb#c;oV9qFu`6 zQikkVzTDR2*j7G~abj`f`JclAtMw?ubvsN$LqmP|LRZ%WLoQos?tIyuM=E)Fsis#} zFcg42X<0BWN`7*iMGLNs(@1!%{xY|xS>-^B>Ek95ttG|BT#>}Fe%>OixMCXLxUj|K z^P9mUN5W;}stViSe#g+0W{1UOZZ{Nc`ecxDx!kP-Qg9yXelM*qTA3n77o7CDa1IBp zv}|EdBE>K~!$xu4)3g2Xe9H+_%4eJ}B$%oW8nlqs&^!1yQI+gRI1B=?k1dqnF~d80 zhN6&AE^%qtkYn(uM=j(HrYayxVFrJCWl$kN${Iu$-eKgQ$F(ADbW#^Vr0F(8*yB^! zR31kd$xNOmHM*&h@liG?jJ%LX43?bW}I>ce<-tjcY3> zADY48Il5IfkYBy%c^TEk5NA5oR|!q zG#VaT6U7-Y)LUhB?lo~cfK+%jwhq&ydFT}FEk%eS$Rg_FU}1Ecpg%IjP>n;XCB~v} zrZol|BHinMe^MQ6CJev1*&>#BVg6iC7qy1UAlr;0RHbe@D>y#6mc%M4Zt z(JZeL&Fb-!wP;nvWq4X@LL2E4RbOV@D4+u4a1+7hixu86$U(0lM)$u$;~O+&fWKyw`{noqExJ9$NZe|9^GRxh}UXq1CzZ!rRz%?xth{ zhnE>izNDBG7~%@#9X+&j!}p@YxTt+EN%tnX|F(0z>uiOTZ7a7-$pd-X&`EQJjqh9^ z_Am4C;uCjTpv{<7>>btH@nx0JJZ^;sa?F0*%@RDH%#8&BQ5;Ze{aD_K+l$bt+Vt09 zNtwel5$?)1G_h2&Yw8d}(aBjb9;uVvu@Zic${%PLhj5Vs8F7~%Y{;3Y<}*O;$UgOr zWu55Ks0Rc#wl5E3(Q>MpteK6=s*w10X$ghwn4PmY81J9W<$aDu%usykb2Yvg4P zKynROC&f1NVKG!h|Dk#VTT~=;TmE`L+xV>EgsYCr-j-h#ns8v=5xV&e3Q0wW$sB{9 zsC`(pwf>Kr&%BQJM9&VH#cpuyUtKQsN@IYT$h=Y+5Q>-5C|GY?th?Lc$6py$YYl8| zGo*3iTCvia#zu@8S=fxZo0+6+r;?e+{gy=79pFUV?dqt|jAu**HzscCe{2ee7?X0v zq&9q_p{K3VGJMShQ*%2_vS)293?yxjCD`wk9VTHbzlj)2QEBn)HI-zghq8P;irJ92+ zH9fDz$&Bhq(Fu;%cJb#bUGdXBDlfbVta(>APUyWm@ExvLb$M;@MJ%d%18( zL1UE3A78l0qZC6j&6aMnW2d5t;3io!S&uIlpxYXoSo{!5ipL51m#)1q%rV<3zc8DE zOWRh?)DQWHFQJ_fDqtiLE3~8O(Anew%q~%8HzKl=VXwtw;%=}s`aaKkL9o$-->Y#2zbk={6g^^FntQuVTP;g8Ny@BK6Y7YKAA_DN^Wp`E zq+zd_pT4>U0@B&2L4D^6k7E2Q`&hd@veB{f<3&HL?eMbkFU_acG8$CKi#*m=N)Ej$ zGt{K!&_1;`FM?lhFdDdsdN}TSEM-rSxeI??S8;a>e(=&Pk;hUS%#6P0oYl=V6j+!0 zUp~{pbIsdnBu3Qbnz~yN)~aG(hmq808IXu<8e-LYu`u}~YmNeGoEXuT6)z+W=VmOZ zn6!(Q6c-bAIT>S^TLR`OIAN+b>H}Qc*m?z(`sTU@E9n_aeQG64mJjLyY(3jX6{7bjp8y!*mMns z*0)B6VfifSyQRpmrkUTdEyf= z^;n_l2~nl>BJ+Fm(zI}6n#Li6&Ax&}ZCy}rB4s2+qFpolRn0Jn7n?v-x>1Q2LElJo533eo~Z0ImZqJ~Kq^gZ9Bb$u^vGN7hy9j-xAA!}ZyFH_?TlOruZ zO4kD+z8ZOhVg~GBa;ZNAfeQ(~!SIru4NswVOxy7?pMU(w=5gu`wrMvTcPeDhHsj)B z1VeR;@q*G;QPX|jF28<&idAPEB&{zOoboAY7x@-6*B%NN4;rtQR1 z_j`PLYPhNvwAm?9!Il-MJOxB*(Sf|mFv>mr8V?|h*kALA_WI2-Q?tRV*^rR)@*fw& ztt`q&fH$xm=&lIV?ewi@FYn5&KA|FhuN^O}r5i}S3DiuesD|CpoG+iW65g0-N~{m2 z9V25ENL%VKdOa1e4-Th{)ZVOr`npl#oXnM8qCnJb8^?#xb2t!z`PpEpB8NN`c$*cv z!Cgog{1!gYtSQ|e3O(i({0by};u3mj<2-x|xB!-Ti$e8J2y|Ggqqq3Dx$1#05Z~=| zmBTJV8#z~!aA?PuD=Mnsnw>ZW6fz(%g}*uTri+KK$m&c52;a!%j$Ku+239H|FPI&D z*3CJtWZ6!q#H^NH9yQ=@w?rHBzO0dy^W{iw{*GVvAt+Aa>qG5ctJ>8m*E+N;d@@MQ zSt9$vip7O>xP>G2IMXdAYy=fM-N&0r)?5w4N&_ni)l4ZlIoHPU0>e^!wlEbT*#CWSQDdPP7c(#Ol(W*6-^RNuPz zX}sR4PRMy#`**NV!Ib4YuYz6Zc5k4{Dc?bPKxryke#0q>PD1*gh~V0p;}rGD<3^FyV5yjMZ0 z_wM())C`%jG67kI`^gFSo}D$fdQIn|;-0)D_D8(CLpz^Uuf&D6*uMMHom^p;Y{Z04 zYRR2NYGpE3ZX(_Y3N$@Tcjd?NmA9(2q(VO-W_1%ZN|4!oAxR0{3~;=jpQA>yNl#IU zEssnlPrJ>J0yE=hwqbd8`S@Dmd3Y`!Si`sC5@Hn0qrcA1 zbO|dj+ZMQiY2<=SRJPBKc|LG~m|QQFgFW&Sa6vUaD&E0u0)tV}KrL;&swesZ-29AH z=k!(0>blo8@Jo9Ieg361@KEreM@4$KQMUb||OVx1{r;eUc z8I`TqM8EO0CnsUT(CQ<=A(r|=YL=Yk$|DCO`W-K*L%&7}s_7N5zVQBk{uxpk zvD_eJtgD5V0b&RoAs6;-$j_u7Yq(z_%m0L+)io2}NYR+mLAA+uulC)bNz*2+FJnW* z6G=4Bnsx`5B^68OK|f(aq&A#A4pazj+r+N3_XJhGu@t55$77Nrbs^2perW-r1IRmz zLReW&JKZopf`F8y>XK9!GV43=AZ@VboiJxlGr937lrfqyrs*4&V}_@P+Z@{Bli?t| z;M;!16Efax%rmFSVjIvP_3?sdI|4OhdimuyZ!mg%-wRTvSt`0$3hE9)1) z%gMx)u@9bmLUAit=%f*EB%2IKa+FZT-725WlC$atX}7JT6HZ8?`1{4ycOLAFM5TjT z*(nxGdzl*H6yp|oU#5m769%(ghU5+9d2lgH;bjYU^I5#c{A^|)is$R@K^=y*bxYQq zCiz-lrVC229)S6;YPq**TU&>kj4!x>yA#yFwQ}X5)l6!tHE*c@@};>1wfobp%wN-*YEPu^QWrIOpx*zG~<Jgr%SxOnX`kZA9r`>UdI2igUWQiFEQICpP$Ti5VJ!gH|%@_sVoCATyVJ0*hq^yPz3GLchcsp)2xRIlYT!62aY-;X??Q-h}LqIs)uu zpA{+wM^&=uZ0ZM5m?TTz?ypnk96To?PR;MQHJC!YPVOjbmR%*NmL+iGZ_34?x*9T{Eq$K=A}qB-lS%y{`{_1B@C;_p^OAGpPi-}j+?w% z$N@i2>b&n=qqt&?nBt4gX%*9O$@dFF0z zAN>Fap`bP-69AY)lVq|&BIdA=$|2~nmQ;~=;1uyLSRn#+Agnbwjjq02*Ilu7 z+PbyI;6ItqLLM(GZo^D3S`z6;F94Ki&Y?r^t>qPSQz<54M0}ef&cc~`Vd0mxCsVvH zcy>&%?S=LSwf#xftn#HqZ@{T0g)*E7WYdZ=1*u=BwWnF8EK#!KE`IopHlyB-h2F$U zf2KO}$W1{T749g^W~8m&q+y}p6tC5EfI!z$z3x?XF!uLB3hO1SD5JrIRpV40i% z&u8tUk%y)wSB~ z)s;OnVpQ-{ zV$S6%GQm_wne3)$hMm-1abSQ zBTFx6CXPclxctJf$}F5IaM9x3RUjBHkr<3q)uGX#r<~m$EE>X$MKA2rwPe_*WgN^4 z$Jp-+BvUQvv+`*bQhueinIId~U)u(IBX#zDAPB3=0g7$x8Fu}sfx#PD?@eYErb}B+ zGBOLL(jad#Y`en`NFJZKvDFl$k002WG-sGoKTHUvN72`yjpMH%b_&U8YvT@`E8)`H zfefMOf%#;UhfA+>>rlj;)%%Sj^Z}zvUlmGUtP70mE?p-nDx1nEIkLK99s_&F3 z!C8-uh%{4umcOzd?Sjeb!C8;jZKWJs=4C2j+inA*pJs|Uj>Kzs zCG34iQasjrAWiB`2Ttif+~m+PdT3s^segLrtu{sWUO|%V)fy>nk%3u~aq1cR`IcUFAZcf42;gXSko`l^qNATc}2E-k(^J!U|f8acD_mUlBY7mbk zwp4Toy>jrYX{@*#7kH)WQLeE$bT2r8GD#34SM*O6L;~F2PysbutC9w1vHM znD1xl*mhPmNdQi$y<7j0tq~M`oB0-aXiV1a-qf%_uUX}R5WE1GJD8{mHx%TEULY*1 z&P5hakN201d|l~K$z(^pS$vnwPRW&wii^P5Vbx*hP%R;p42m3b@W&VjOj!?Yo_EuZ zt9!D#x=uOD@6NUdx3*w3MU`{IiIp7^^5^oO92RV;w$)bHaS##C?R`(|2#VR6&tV`X zr`kLrOi17~pB!nalAx&xa2CCKtvjtshPgPuTt!-0O0AKVHS%rZE~xgUJH&{tmk?$tMTCTLMbPHYT3fkWx-Qy&_9}1Q zq(sR9pg9MpWb(eeFFNHIa}fQ6KiWtoYhHf8-Jph44tjN;>=Sxi!|Tr%H>@?>G*3*z zL}^ae7MAAhVQ+su5-5X4z#fKXg$!tVccogtGc{y6+}I@n4y0|@mGk55*+x)~_!MWiyy($y+`W3@)|>KxuRhBKGP-aX5Y}+$XXTq%WAUAV zGYhe^Q2MZ{KDhPrODO}WYN+Y~+V6`>Ngz{$Y7*uBAcGyZ z7~N+K|E$}R+scEDC%HXKBzi166zpReyifUaZ6g!-y-DOcEPYWfj%d3koQxI|=5U`+ z@$~npiS-`4hs|tNXFsi190uH5wX`MfRM59VI zgZOOKtdor{mbia=T4;gsfYA+D(IiT-6JedqpXAQ28s-PYMhDkQ;o4gI>tpr&%E>>| zlY8dnQa=g@9+WDu!XGE=vP43 z^49a1p2>2O&maVplEawGUEo}0N2vGODpHg%XEcNykMpo_| zNsl{<5}MLtJbi1yXFi_HXKudUJK*dEL0{mzi_n87F>}XcsrsR2tQeQ_G;N(LL`q%R z342dd(q`8{ptpL4vQA(1rrq)^cRs14GZKAhZAlN4M#x=-=y=*D#t^rq>LxE~OwCmw z=W;>vNj@4d906_JybfyuK0A}q%D;9{ON&GfK2=u@)4f`!41r-7qvZwr<-^0rO7CYq zx)nY6j8Ziyia@X8v^7tJh=I;m;WY?ORJWy-qm#S;cw3Juh#HIz_Lx&H z&=$7#ruoz|ZVm-Yxm^I&ez@c#Zg0`Rj#QIZEWv3EZiAOvkk{ag=QaXw&%`vE(EHCY z>vG{JW_pszQ{*fhfu{56jtP#L-J&|qBM|^?hG3P7JO}}B4*yp_s_ja5{-^sB)>AHhPzpNfxl-;g?S^P`HRQ=o+)K- zQBQ;gsW|d0QwkO?{K@W6Aet zV|MtTjFhtL@4oQf3D!A;pW=47qzGG%!p8#bQw*&}b^y}SGn+(qBF&N!_+(**GH zhRf>F*X5gTS4idd>ab5(;G*R4@drWuV|a&@J~HQmG44NAO@ z|AM8+K`~nGFr&uM4^j|^caSuzYO)VVcXs*e63@#&J_2c2e!C}RC_%tp{fx3OC63HM9++MeiT;aV!jON7DB+uQh zFXQK!W!3DiDmSp~eWO}`;_cG$6GHCErDI*;zT9>*KF~c1tGu(BDvE}SvStQ%75t6| z`=ud`OxBT<=@M3D`i+pJ*WEfNi%4e^38idtCSI!pY*smYH_aH@Nf`6G3=2_Wiaooo zruZD*jiih0t$gK+R&5?eUU*$DwhbEWiQiez{Hb9uzs{mUwxe>uel%c|=i%zA9dd9iyMVADYE)QzKDiAcpeAXtasIe7!kzKGYDtV1gk zwuGVMQR31#*~a|E7DT)95@$ZUmLc4_WsWXDXWf~jl}!G`D_x;^q^K2!;>sd{xh+JQ zi0|=Mlj@mj&K6|w5*COhB^%LUJ>%;S~N;lVOuRT@F5mSP3fRv?D&qK${y_sGU}G=FCjW5({5N0K5L{ zl*(A&KG6i9Qnr&yN*FXowq57>kr&lvWW$Ot-1W(tLVDfEs`D2%0=J=#Nv=Mxi^*_r zK2Y9vERLy7g9%f$XQusn?QnjZvK_A+q!un@4j=M_PL<=WSfZt@OXFwXp^kDmjipD@0LpeZ<8o zHD)BC>4Kf=wrwgrxO~dnvYIYqm99;~YtW*Z3)nf{OwOY^D&WjC%FTr@ zFoh->rbG!Wb>f~AHl_`gSf{3mp^<;v`*FeJ*&cl!88v)L-?a{27^~hq6CBa_Oc8yD z6J+B}oz&Yu5v5p=5f|<#O@zIaBV%GjM^N!KA1Sq+%*jn1^|pWnsrevSu?m5gQXcoN zCld~)-=n%;6)lpqTKWT`(UP{-xmh?FUnDKA*#*y4m`c%k5qhEq)ce9BzRl|wHj6>H zyjQ4|9>=f$nghoU24wtkOSe>OHIgaM+Y<=cv%E*@4{SSz!Je!~`VFo6i_D(ca?G?5W)G3VmVsjzm_7FwAFCOX{FsI-Vz!Q1u?G~P%CtZgB^uaFMj)YuvKbQsE}F?`HpOJJ zUIWp{jYb<1$j2V@PZQ9Ok6@Z97#4be?UQts_;KqvqvGPVQ2$pFTo^UU^g2FcX~8Ia z0tLhrY@UV7)HfA?aH#P3F&Ag;@GvG_%tJYLzqwb~3|GEoX?her3z5d2AKkne1^_L) z!9v=`@n;nNKmk3<{x7R5??9Kxk1>y;_53?1^R)2o=f0=c9W^?w605BjS6v-~;L`Gk zrCLvIg_%fqzW}D-TISzRUU(JWKYRpq!yTzAb#nz#a_p)CUHj#&KW(d;$09~A6KNI? zeQbM7Fb{v}Ytm<#L?CmB zf!3dI<&Fu7m6RXXi%i(=|Ez{%+R%T*#>q!iCUUc-ozT9HLaQ^djvaeLLSC)b^uB<| zm2-cmzFr56nw_tE-nlHsvUQ2N2a4@?$oLsY$lzNH;mXKoxZ9ttw8uRKi6D32Xhw|Q zZXPR=jgpw4nw$GVq$>D99FqjU?cjEtXLR=fMfVfg3E;htkg`wH#Yz}Rzwp4n=H}xF zmwjm*!bQQ#F|0VcMs2DYpl^&bP8^6T)ZNp=gbzKA#6wKv+yFrx=a1?=ac0x*_mtk7AClB?7 zK4P#`@bhK5|2jS#ihsG3a(M>^8GsSL&MM%$WV-WFLDJ-)@^sg5D`2;!XQf(C9rq;` z#{k!E`-PLeey934T*hL++Qw&|m#Tlg(vSE23L(^> z0(Xx3(oO`upQEo5YUP_IF034FiL54*SbL%RZWcuFt!r@g0IY!Du16CC6`0lyPAOS4 zK6Ud*L<85cc)xBgVExeL8pEB(YwO)1&0G?CYmyV+-T?O&n!MTapl&*!#^t~3BT4UQ?K$xaO2_szY4sCF|iJ=Sx_fL!LpQe56DK1IG+c?t>K zQj~mAlRinrSftAJotE*nEoUEYUP}>{%k$Ow=gpiwTy;&ZNnOp@*SM>mw}@BCGW4nh zbsQ9>e>`YAfp=M7{%OT|R&E^07wNd9Mqp+7FbeVp$M$w*-f{9!&{%6=t@#MPCy25Z=MMEqa24Jg(rNVXPH3%~0!utHyAlnsdmnldCOmQZ=P znLA?9H-V1W7eLnReL$ceM=F#q)BB26Op#&(O$|xd zxp;Be)WB*QLx3hEkw>KDz;ydjy-uG401}E^Ur_JuL+-owAz1qKr|mHPr!PWB)B+B) zr1uxE!tUEl@#|U=w%ru9f$C}AjwN$tH(pIKIJO}7bY0Tfsz9KSLSx2~Vse8MDNQF7 zHxLGW2tT28@niOE5RK&=etKQ|4vXd!s;EdPUfCf)r2)!paF1;?*x`yjVpPsnT4ShhjV#f-Ne*X9RPf$A2tb5-dxn7$f6 z?mn~A%CPABLt*%fUG+?r_+LEvXC%dMwLAZ)ul|3>1z-c$+2`P5BLRZ{vT?AJuz~ps z9AIDpke!tYzybWPU;qv#_P>Dv{$9-Ve+|pvU}Itja*_bSNQGZz`~kpUlnQQePk~JA z0JeYZ+5d}D_!}7DxALa{+aY5i0T)XJH>hX~aw5@UXJ-SG3cy1J01p)a%+25ccjy;J z157dia{hD2K;}-yO#cNz!Os4y(&{gMz;9Jy6-j>M7J#`NEZ|bCTr4b1U{rvOvz3(& zynq0Sv5gV7=vt$ zjKO0L@95-UY+w!Vy40t+`aZ1@{lkRbrnqN=>Ld>OL!!y*48M8o-1yk_@hXh3L^mV! z{F}JP8{T_}m!z_f)%yasB!28{_+yVI?6JI!1dV>vxhS={H^kM1`Z#wLQ82a3AJ52r z58k|UbvI&3LwRy|m1D-0lW8Yg(+40jqz+Nt>l>hG90~d`AwV2qDlQns673A*Dic7u zp5$j||80K#R3CX=07YA5bJp*)36~{2MhdqsuIt;^qnKr^2-4wr63a~nHwy56G|oaYWU^iC@J_+ImRYcz$-R${Z z%RLOT;S?vH+>S?kNS5?NDcd1 zpCst+M}@Nu{S{PWf1R=bJOvzs2~M&u`ANLF%o1}|Hm;jW=ugkj4rC@M&Uw=hI8gSk!^y7Ik6 zYPq6*ulj;-*RCnpzc^vX0w{{mf)q?l&Uam1Tpl;MXFh6?lHSDW_!MYY=N_NT4s^rF zQClz8$4qkK;#GQGNwK`bWsKb@nD1wat?DHRN4z1xn-jyfe00n(&eFG6=`~1sRWfmy zaiF{+UZAko5VLyy5zs}~IWt}tOe9`Hu#gFZ+8taYCKAl@iCN8FbLINph(C#IEQ}_Z zK=8nH*l2npi5bIqEcgO@BKy?_S_dR=TV_xGjDZu%#A0eM^u(qjgs;{*N|HoMsotkp zE^E4>90UA-s^f(rM-Y}Ac7u~h-HY>rnUKMie(}BZ$Lq8MptYa2uBb9wT!VBq1gtqr*>WU2NldHU5gyZ;_R(?}fuff*NhsGHe|OPaAL?@L{-Ebsvb%PWw%GuY_0!_7avNO z`w8emD{evmVstxtXVICf<14E(^fm2*L2@@X7EAruH*$)fpWJVSd@g8~rSxLSy80q> z-fK(W5BB9THiy3V=iJViC~<`;7i+zmXDV2_D0eGJabtpna9EYxA~<1iwkc@Q^6jc5 zk+q`uHcyoOldsrCb?L($hS3tjk^L+C^SZ==zJ_;(e2z92KM9Hwj3ogR3vCm};iN*%)Wz$~YjddX_Dh~O-%}a%qXeiQ=d-Sn4vV=@s z+etLhJ)Ef=ET{HTO>clRvNtXdFE5u}dH4l>dfRifv>v`>DFK=peKJRdziVnaV&{Q{ zeh@w0yk;*;+1Yg{CZ{QD(QrO|b)b|mP*629=}4c#8LI=rECa$6J-I`jX#UR zy<}M%VQR>$8e;Il1l@igy+Y-)-dfypbFjbrvApw5$rdpnJ>(>pC8xn~EfW4HP(Ivq z3eDT^Mc|^MZJO%EYFmV;xoU5=Xl1A7W&|z$dY`$b7RaRqL;2u@dYv*9ZGBcHjbGZq z5}m+Ganf)q(09A`X!~qBiLJ$tr6ENp>|)0gkVg1PreIsZu9pXb$d~)0hDY+}6g|0n z7m&ZOA{??4YD4oQP0O&r(I(w!!xM=%<%{iOhKt)Htgmihh#v!+F$=DXr$;gk7t~Hz z%kVn)IRq@ZfXzsyJj6Ufmpmy1n#s?C%(pd6lmd&k_V`r0d?h>-*C#@|?bn_`sG)f! zHtd!k?PH1>1Dj;6h@G!rmLY{28S_kxA*k@pu1a%Yu89ba?6G3)@c^((AucU>2Thie zmwRY`&@pXw#=3r?esqr&L{#q@;iDT(hH)I~Y^6KKdg+Xjol=lALdQoCjG*jrT?A~q zFCqsP8p}B=C(hi>mt^`o44zy=wlUILb@P$zYJ6!w^dlUFyVUkX&0KjI6wR1fE4SY7 zrA=vt+ty>3fDWfu*XZ5EllGm9zpJW)1ZGnbRxJHN?_o4^@pL}gR;)Bv~F(SYMU zW^0^n5qi=$P2Z!}ybVyKab~bBlsG=j_pE9#Gwhn8#p5h|+x2gCy0L(5=jkl(X0n|O zu8=p=`#W-G6m^WT16iQH!L(R*MKf|N^2~baW29sGNVk>%vKVACONdH~n#~lbM77V( zf3}e$9Xr;o8(cJC0=Yhu?W%Hbi=7F)QaV~?EMT4+IKCSoy}d`Y?_TyaNOA+D$TE$4 zv?2kqOPE?8B+=?|RurxyYd?;&oDAwx-k|XC%@WPijLvaT?=i@jlZ88KHRfC&voM|F zpzZt^Buc3}eTbMbyz@sCi{4`)Eg|?Yx^~;*dv0m-Fcv6apVR8Pd8oVJy}oBbps{WV zR~sO!M)5`@mX<_b#w*8MwNm2 zr&rKh4sTKVT>3HbU3!&{wOZwz4f)oSQ)IJI@!s843lFq%8$Xts&mATWYsKh^RYgfB z{S0Y5G8@-lEQxkE>43E*!;&|9r-svH5D+64CrTb2RPGEpPP(h!;n+nlT~A7j7u1Ry znu*A}#L8A4@m7AkEU6h=`X|uCb4J*|fF6ERW&aF%;QXZq!!yem8<`sj*}9Tw{ZfTF zxH*^rV5}Dx*i8Ek*(Yz{U~J{Z?gX#i3Zl;|4X~S%l@L#fnk1swMsbIf4%e{eg6M!Sv)fs{%lzMtBLR@dy0eY zS>u102CQJH-~Z4w7}JpYMK5cgsN66>QKs}gr+8yar&4?EIzl@j3mBeLHFn&1hZ|-b z8Y?k;`S@_s?}tt~9!{*3#t--EZ5FZKhgGD>9UY;#54w*aZ&r^X>28`K^YPd_>+WJw zv09O|^z(4)E8|P?druWB-eu_mvgu-~+q8VTzr|&5Ci>+I9 zTWySgY}~zHcf0$^frhDUt-yxreywOaP>?$m&qj8&V*BKw;}SaGdXRYIqHWMn-a>#?xDo#k6LW9uQ*9^<4#~Y z`Vn_HMewoI;+>bVR5)}Jb03V!m>w_M%Z;>Ik6JZM!%kdAZInp4UtGk|#`!y*bX*oG zKoFa~bVl5AK@+gNO za3OQJM6d`jl+hWvHojJczxob?2_fAVoYRPI_R8}x@u{KoXgX^m8d?2N+ru`G{^yU< ztho2v=uR&9oLv}cAHzhrUev8|d)q0wj^B76vl^zo!L;lEdQz}-)8Ck!iHaRLyDSSh zGT}D=4XV7~k$Gzef^oC|sh6b9NG9FNe#7`+gXT zB0F074u^Z^bMPnFG?>v(v}8t4Rd+q9AMb_`umZq(QF%w`-oAIK$7p__uQN!2gi<0diZ3>r30+J9R4iwM{vREbj+M%6C@^% zH#}5z6Wxk=!nPrfgqsgUNaNUFJxo#9OrrRghJgGY%}WQJb8R;RS5Wi*mS|I=Sq~$- zH51sj$4|Ajec4P_ClXX#`%qp+{(u#P9EL(!iUmmU?J%dQhgU^b^Q|3iBWpQpP#mN@(FXUQ2C5-7Q zIwwA6_0h(8kMo(XyC5<{U*e_o)XYipl(sNVo;%7|WySvfCS^=En;B*i)gFSMrE5B- zFD?oH3a$SfbJG008nc*|urThKsNHkZt48ZVY!3A7lLmWu&np*MD_H$I@Mg%_Y|=0-;3qZ z_|HYTrqba+$z|8)_3tKroMUF%PXa+~zq)@aJQ>WI|D6U7QjQPg9ML<`vY@&y$`LFaI(#v>Tl1XH`@=F z6D*@*+V^cI?v9V%{dA%Eep6k!_Kj1HT2r4pU{{SGwA4>lFFDYBuw(Bh$%5)c4!U9lWTXs-jNrd(d{uq3T7yt0M2WgJ^ut!<4Y8=oq6_HqZK1nU;oT8) z1wOt+(gr_GYf9JCxF@K=|IxH=S!#e_z$3P9D>|=lny@rpYRV5(`E-)N@8`OAkL2!| z5;>3PMNa{$b*-f@#r^P9@gw6z%!X{3i9PQ+PUpCJtDq(ddk1e4?;+9m(e2|T0}{f# zK;Xk*7asA`X-3Dv$4MgdrgWBdqDp=FxmOd*6x-9v76E3a-3R+Ds+>DPXs; zp!Xgz_O0x9VY`6_4Mi_V*93?G3l_gZG=@0bwV!(yc0VSHUZm}5Q0Y`d8t3*NeGtBK zW!p@}Dq?N6d9VU5zeK(ExMbCKMT@dzPuLNs83@wBU`pCJLjO6wt$Xmt%uu)h7@T=A@6|M7p3{oR|+2@V%U1@b3+C{CaV4Fy`;V&yAXY69!|? zIoP@XLHM~7{$GUI!QJKt2dMtmGVrhV#Xr0=8`w#^A zO#^(sxc-k#!^-|YCo<2fNkuIKQQIHXzGCC4+uy~~&`c49+)d6(+d%e41hey_t)$tldk(3WViMpwv1P!wiD=^@ zS&FVyeCk+TLGox4i81e#Z%uVvOcMM{jr)aGnKTv>zOP5ef{8TEGLgi~3iiW_|$=)0Ct= z^=&zESY2yR(7L?Iy0z)cK}FfdL!`&@vM9a1HwY3&#HN1EvS2!EpO^nnx+6%3;GjYm z;A=qaH~f%k&SI#}jA-@#4OU4C=luI8^?8)qbu7zy-SJ!8pC6QRTdwCO+R|F3GH`Tq zG~SbuCo?*BVpX7gy*Kf5caa^LgZh71d*|>zzij_IPSY5TZQHhOr?G7}Mq@i^Y}-y_ z+h}Yzd@`LgXWH*{=Jfo|lRtA^>)QKs?;Ef6UhlOxaCJ?!j&$&BZ}oK0ZP7P)82~^; zkX*nFTuQ`uQPCk`7u9M0l2MWdYxXQyZ+n*GzzY?=9hWzr^i?%N--1fb`s!h<3Fy6G z1xM|DyG&nlN-$D`5`0x0sfhlOUcIW%o9ARyJsd})1oJEFW4Rla>r1Ik^5%sFI@L>L z_RX4cq73Ga_zEFa*17>} zm4K{9zEGYFGh1J{x1AB^mT3_;`p@-&!YFo*ugGN$H=zhkGHjeZT$_Mlx_On1Q@VGm z0DXVokzk*8upCvJyzPdPVn)Z6HHI_p+023cG-%I8iaVXx8s}@=T=2Bl1L38bI=0L! zJ1pRg=PE*VeUJ?L=For>5@fG?ATT^E8S#_w?j9E2OUHKAbc_5q`MEu>;ZE|9#F@g=A5`?7vqEAQ|;idYO^K$n%M3B!I{XD`Mbt-OZ$RChgasPX{nRflnX=@%$Vl0 z1Dk&JhLa=mj#Nv02>4bMr28U+w!9u)ga>8-gfy!ILp#Azd12U zqp}B%LFOK}%2JX!HqDR@bCqVJ%bC!5-<_Ur%l!S|?TyL8Ju}wu8xCatnNohwfj_<% zzj7e+k8jrhL5O7jE2R9G$A5v<{~$!N{S`BQiT#g4B+DDN{Q9l`O)N7TBQ+!KZ#)if zpUD3?n2C;>ndvut!~9pi`Q6BGaK!kA-T#6pEPv&j-vl$!Gf}g=EzG|L|CMik6U@lU zKut^cubvPVmY?&4zroROf`1rFe#1sT?vnov8~sW^|B00T4G#So0I~cAfc}9$xVZnb z--AI`RE1X7W{;jXC!N3XdKHQa2@3j}5}FeF1OF6K7^UR3q!jcAO353jFscvy@<`cC zBT$U`0<9a(ngWdg;o5K#zj+Yf3_1V2xqkm3{+Rc#4{5oxg z8er#eM;od?A8UpLvIM>L(V+p;(@DDKk&{A2salIC^0n!4qKwBC2aJGhMYY$d>dZ_h zlDOST2z6>{{4#SbW^ylt#@}9HM@_dMkp`*#>T#vrWvqy7>V_E2Jz9ZFJ=tk&h?C{O z1wWmb0uuR!%ELA@H?oDQbx>yj@mt@QZ3uWtPCPD@$lCrsD@+%_C1Qbl{WTN(x+7PM zm1fg=YZ>W`jEoiU1{RlNhYPFCgt}?)I%vZfr7AvS%9ei z;GLNwB&M^@57{HmNaCR2aj^GsPT`)(+rk##`x%uIVxI1_s!L<&x<3(Jy{Bth+;}ww zy=z*;#q^z6B&JZ9_Qz@W2V`Bmt7XvPnO94ZEDi9L($9MJ8Au_QQEm*9A0yftGmwZ~ zC%F6=VN^@7&3ezh4^q{WRHC8>(<1oAJ|o!?hQll>y`_M%jTxYY#2ga)GqD;LL=`AF zrI`7l^eSkDYVJ`L(wMhC79@!)?T4?xU(yx}`W8pO?+l&V2{mV$Da>|EJW`T5iH!}Z zc(28%1j-v~CsXycntWx6vb6Jkx$wB1E5LsQayK6Jp(^!QWTQJw6V-SML%hjCq@l9} zTCX}lG}+@4s-Pc)nZ)QX{gMtj$4O<0M3u_vOQIG|4|Z)-YTV;nt`x%yTaBPKo(tMT zXt^;yiT457se`Z}4`)bg7J6ybdiYUm)Lp}SV^~D5)8AgB?>%X* zNijVRA)HQQ^yM9t9viPvdkJm~7vtbNG)(WEWl=DiXasjrK^|a;S0zzWcn+M2)u*+f zfEZrDZP7)wPX|)7A3s7<7v5eqr*}w)D%D8aO-pNE)k_d6%``G`3RuOat!7PiiwgAl zKB*anq0NXbMk>Smo~y4Bfyh;IX95uU!@yg%6Mm;>s5871WzAQ$l?qSSvQ&$n7@gL^ zP@sgSp=<%dJgb6I_cw%dQmt=C=TCXtR%TTx52(o>c|C(m|G0oI7;?vM<_ zXz-iJ@v8z6;}c(J9QUqg9`Ih6vDa`h5~b0>jQ9s9)F@%8^l}`_imvIzQ&1Z7;oh8d zh&v?}g^*6;#N{teFm3}44!v=4^_Y``B^K+Btg>Nb&?L;jN=U3BmNnh=qx^C~Br~t` zPJ%NqT`O~kKnQTu7&{EdVSx%L>KrOgMRnGAmP((>_Ex!_a-gs(w=yCUZnq>o^FWtm z@gJ)w2+l~OzsSt*^GL0F41;UM`k;A*!I*3*mOkzWgH8IBAUm zektE688c6Ai)=vQnATFTVqFuL&EVIxfcK$`$C=>prj7}p_3aw1_X*re4IiaY{S=57 z+T6cRUCH`s)>tdP`|8nQOKw{*YlF*eAtTvHN?UzSpi;K#=x8HpJ$flX&nr?p?wZ{z zaUHN5c4Z>+;Zv{9N6H@z4K-t?Y;npwX8ltsD8atxxnaT&7^MJ zyP6j&<>MA84ephv;w~}is4i8U)#7uzYu@iNe%nS+f)gN968#NDr^rmhQ^lpw4rmf7 zO#$5ft-@emFhFfp1~ih0{F{uzge8HAf{I2u2|@unsMMfDTzK!!<1QWCKYJH661>a>W^Ei{8;LPAa*1Yqfq5^;XsJ_s0gldE?bR+&B=ZD#Nt(+Bi|!Nlg+$V0h?JH_9c#W`jTmja|-ZE z7d|82#A1Hl&t%6e*dFUDn5dLfQ2EszUla>Um%RA8bFzEJ#=J1`^8ET~{rllcjZR9S z$vhZ26iT6^2yg`JSao2SqRE3%o%krZ_*~A?&CjeBzS!h7x;S&BdOdws@$`SZ%Qp;+ zaQ1h{hR{)8%q0E-v-P7&bPt( zca{AoTQ}=p`Txy={X-f2n-2Y-(@|ro;aQE&nx`=}oYI1HHe-ve5l}o&U|iOmBV{+TSSP40L}@cz*MXnP}hC;5Wnm zUq@#Ar5f>XMrLGsbKLw(C$mO?YKGsLbLf6X_kVM>=xN_n``_LmKc_tZCYX-pEuUul&9r|!Q~xpf zpb>scZs^~tK>wR-oyy2|%);X0i4#q` zSd@k&(#hu{PB?WRQNX+^^w(Am>i4bbBWVm*Coo-5@7zk$=_li12)~ff;CX^dVQb-c zu}2P(irRm5ai3_%Sh>Tt#(o$tvt>7EAaggSAHj{JbQsbfB^$SGl%8OU2P26!Ywcm(#r=$czt*LUWIoD6QX<^j zs)MwAz^Pa_+gf8qHqg;-+-GK;S~0B0ko+O&rL~xOo`1$MeA$fNvu9SGQA3dBm!#ISzs3w-@F>43fh^Xl~-dM+QB9>(}et#n@4Z;}uu*2F0B+5X9+MZI)o z#MR!29X3`C2y&!1exVp|fd@L4G|P=JdCdr!(zQP{Obzks05_tWQ9L{(x`r+#tjC1; zY|(Bmg-5!ZEO|4b)gSsR>%zIbSbI6r@&dS0mF^VGthPHJv5(&6#_ng!qg7Uyr|Vfz z)bP~hz5`ZF8T}RO!6Ag>+xz$^8%!D7H3EvH+@`u`%`*Fp#VWpR2bkv%QrX|OX<;%F zX~XIkyMjluZGfc1wroXd9Tgwb3A^M{$?u4V3@}TB46xHqC@|hbVFwz3eQn{0MM`p< z;+bi`yxR2v$ST~*zE?UsMRPnUzDR~P(q;cl$ti~rv1fnI9$jWvaYm{ zbGe08O5wA1ivNW_fQu<>rc`N&yDg_g`!WTGT8@|Xd4HYBOj6Y@w3l1%1&7?hDK@9J z)u2LjfYDyzHzsuNs9KlNCVTI^&eHC8_sS=$v?%<|1J2osYY%4)J#v^*VsO!{5yG|z zeY<=J9$J8wR_;#Pt#q!)0aq&XLG9Q+51Pq`6Aj`E=3rkJ;Hg$hnq!W+k~9Q5!8<Z}ApZDaG13TqMKYe+jw=#~yfp|zVHK8w>_#s?#H znZu`uvH&4RRfdCM>Zj$>Fupj1nA&LXgfQ&6raCU5?7&G*M};)6whiov4=`a=!rpL6 znbk_xUX{8;>mRgU$R9!xWoEkGjv&A>O;7f7DJU~(koCo|HCZORyNOVJ7nq_dOzz<5 z?A))3B0hxxu{x@*=?swLTo24x>D=bH=-b251qmwEjBx@364{Nx0s-W>|2&^W%~pBi z7IYseY_h+>M@>wDVaEE69AU7kmwYpjPYPzMQoB z=+Z_sIttjLB9p?RDc@dqYR%N!5}v48vCeye$wCLkX`#Xt;KHt!wOpb0sL9Ym8fP^9}B=Voy{^iKSEkq zkh>??OYoB~iQ+8Q3=y0D(_M1KkA1^{{O@sf8}Y`AF1P?81(6B|0?DG68j$$J(ge0{r`qL-dLahM_%?fN6IhG zm4D0Ge>1hP{H;0q2ZR3^b+i49PyeU}&@(XoDWJrwN!f2RBeWfbUGoX$UMJNK0AW0qy_E%N9X z;cycLk*f6#%+iHuUz*g2Z+TXS-v;Tou9f8^QaaTySTOQ5a3gXf6 zdOAO-v|nH2>L1{;SZ%+ldl;WijMQn~ds3)hR;?KE(-G9>>AY?sP2}-J-(w=sY+F8h@?JN&)amFu?Dw8a_>q>+ z!ZdSNz8CYS6mmL+#|aPNR*w2Nc^X|6tJxn(#CAM4E#pRpg=bfbW44B>=L{?DUBe<% zxzy#ALCZ#kx2{p7Mmg9h3hBW^Hh9Gpl<9`d4aXF3A>@~h&-xv@IR*%+uw$AotX5CK zgqwx2*mLr=j=7^+g*C-5hwc|K9q^twbs0K~$DLR<(Nf~OWj+B@Tq_IMtA?Z|yWh3@WU)J@^=BHR!b*TLt1tY@`INQ&G{mh|gb(&iA}(xHyk) z+-G!L9N4+xk$nYgV#GeI$dJE4NSsuR%{pu1 z+_vxG$*P(~5u>aA#aV*vVQIlp2`DT5I}j)?xp6kdwsa`;9~G!gG29W+Z7{jb)|up( zuL}4fwn2v1v+2_~prk)j=Md{kJMTz}fwH7d@K54ak!K^d6Wrs|HrAmi4NujP(Fb`6 zNVsvegp)1@XmZ`pp>w-r%{Ppp;^J>d1)h++L&{AbGl(6?Swd@NL$aCz(EoP#9<<5K zOn%v+y(+u&Q;L*KFbW)1nSc!*i43Ta>!B1`^vMYr!O~ZAvT9=JJ9CNoV7rs%d2Z8+ z(3Uc6S7?YJGvPyS;rL2hVP89?JC8DC3$NkqfX%782t>1C5c0|7=(aV z=U5?@cZ|KOATGSZvss8-zH_J5)qA{RGqz~mV#^zq6jZ0Es#NbylTgEf9Lh9K*?>`2 z8cX-sFQl1tSCpmb^}sTQ$`fiP7<38k$i&Y^sPzI7v%eM!u4vbGe{!4PokUfUob}=V z&a7IwvdYCFc=XOFW0rL5GOPuc@2kT#=B#g|aOe{ITI?O;8fBf4hPm)VTr1z!0k6S3 zB(NgBWhGE5#R^-f;fXvNXZ4EOnpnaIFN^h2|S$BhBvXPCu!SD1d2B1LH`&S`ocFXA#}E zImPdhZv)BV+5IHH=Y^)TRSlWo`Mw=lHkW542sB!*gArH;6i2gfWRY?0ZyUD?e46g^ z1?qqiokAHf1(1%@+5N5+1f-=BS|DyodGIpw?wJ`WOO69fV_RDD{2OoPnu#?{+#~xo zx%wG}cV7~yR{3)BLcZJ`Agc=B#cU`*0K@FJcX+%}OrWEJv@wq$E${H3)0%?Rpq9LS zP3C>(NE z3qGbnb(zFbt2<>qJ~{QE6J@R6uX_8yE4c<0HrUOvhlokSgz{vEL>jt!(E<~CwpO6G zAe`Tuz{kv%Y5;U2kO@y3!@=vy1%KP4eGvfW2Rq!M{BhJ;<27^n;_`X27KL?T|AV;8 zJe3(71riT#O*^km%UT%!Gzt0gT%9&-kzos$V*l~`QCc)dISE9X$j8Ob|^ zUN7X>pX=y@mW}^{+46LAxfGcS?5BcX6$S%slFClVJ7lmF=ca6WMwLIjLSn%BEPQRa z0#rBFX%3HKD()arf*kQ_>zy5JKBoo)V;B_QE|LVWjj69IEnSH4Qe1WADkEbZ)-aNv z58b|*pPE7LW}`bwU|@7FtnSVvvE_E};&!ONpT^OB$?<|Ekt7Z&n{ zmf(@Td|w!)k}8Nj?>XPult45-xr41rg3Qmeuwzfw%|S`&Szz$BGP*^$95gM#R~&4P zR$_13Q?T&{vavhzERtq!C~!#p4EJ^v#V}+B?cXT$Oo1BCgs}A z6w{ua{a)Yf2%w8tB)dFK(CLoa=t=bkzP}K!jpX{$8os8=;{}cPu}tF?QldF>G3vW@ zNFcb1DGjxFK|{KK|A&Roq!WUbaKh_&l+6OTo@y%2O4D|m@*2i;x7LIf4i&t*q-F&A zw?X4!Ecw7EuxOjI?pp@xJRfL3Fz*dx5Z!rN;$t{?=O1BUX%Sa9w-Gfk8;yuED(8uW7W_Ww$dAkK||Axfpig-%#kA)AxT;zkcA-uj<#2 zZp;4*g}&*n{~Y#j!t9TE{E_;_@=L4dzahzA;PL-~5Pt^Ue-I+w+pa!;C}D-GY1uE= zBY56bZ0vtqVqhjXoIdolLs(W4ag^6c=15=Tej`L(Nd$5LbtP|46cA*>`^_C9VgZB& zF8AAGYDSpbE>@S;`y+hcj&0oc$|W`kQhwh~C^g@jhgm!Bx5sUxI%{-%ZCL|e*_Et! zyC_4uFATuu)z0lMmirdUZ*1K!Hu2DD{0tk_BXT~bf=wF0k6GUnE~HB6z3g!6lI4Unx##fHYbRl3q;wqe-t_I*^^|81r{iv6 zYCktU6E#8`e^#93+XO={6!``` z)Lq&fcq;C_dhe~5$ZUvwZC`cTa8}9Yp15kza$XKi(mo%!Ca20)~3(`;5CYgC09}0ODNzaIopq*hKl8teTug z+jf1>Q)j)yiH^)B-2lEIU_c?g`lLqHkZM|gO={c@4~7mpw*+uHDAOU! zQHdw$2s%UA6y$z5Km|$cFIEur zXwEZ)XQ{=RIRlQN#tVhAkKh-bwDAwAC2bd=zSx4^7lZ^Oi%y4+*{UmJS9kQGjG`Ky z(uJUQhnv$ilWp%k7t5G-dOLkD|EOk>qiISgc;DoqI$!DSxStMFP4a3#76$ST9S;!< zj68EekkG6)WTc_REYi6BY1ppJ*4&oF%3xuT`AMwyehw7ktJYprjH0;zZ3&ieah z`!}u_*PZOtFOpi$az24J;A^{OUt4+y>$K;kRAjg*0Br>Hd1J9HK7k1e04su5cd3UA zPD3bq;5NR48!y_Og4=5m?HCETrag}&u$VjnODw)#V zDFKB#oNVT$bBzR&>O2bOfTT>u6;+ahq8*wvr?pTx3+9Z!zEMVzh#R~?O<0R4gcL5; z;%QACf7w-?5v!s?a%E)@{Y6q&o7)9UCQNak8JY|#JwtgujNH6-#z$z+a!}?NniZl! zNGCW8wH`Bu>KzwIcwwqF@lrhfG*nE2cJXYPVB*}0zVeXr7$TYL2pB1pU>-hEm3fZB z*Rg(pZr-Yjsw=W(teP-T4)TLT(XF1+QAAFAs;g)|H&+aM4eJ%bTG|7K|Y5{!omdw9RV zI!FXHdO~o8YGOQ>jq9FSX@rvY-LY(_9N|gqFG0k|URp+T0A&iA$>t^lj8?vVomEH5 z-klOIxe^jGn5%mkPv6BA4QREn z=Trm*AzOjvU5RdH@D*~q&g z*enEg+PTspFRhMaf$Q%(+(!+}n~Lp;BV6n5awpg@CYoj~%+ldy>24kScC=Rn9J((s zrB}v;>8B@S@oGz_lw?cKKpqO_q7NC4uhBgRnJr6ngx?o*GbYXW^bge;=ND*6B#bGG zASkZPgN`t!M_HvN!xdU_aGsg+mTGA|&uTgmQRN>G2A zR>JO&#Lka4AC68x6tD~in2}y3^i4dLrW}%|q$Ahc@9x2A-Ko*q3Q!fyHXVvwW!57t z-MgE^v>GNDuj^s63(mM0(4Rvgfj#bK(D_uvJiCN^;m*uzjYD|NWuQ8I`X*o9Ioe`R zaFxTwc%NFgE%_BZvcI^4X0#`(P)5ONBFY8fIOQV=Nksh3qN+3*w!L2DSp!%Mv$rv= zR?$-tJ+8VUugkUV9*x}U`-hHjMq)b8+VE9`QTf+}5Gb6i{Zbner%_WIl{4+D`4a?0 z=k6V1o+JwN?XY@9_i@b=JCR@@G{_C0Q3rD5A*R)blBA)v$+SXYie(7U9V$Z0DLr1M z)7r*;3+doub8m%V3`phk#>^IOPQeB~Mi`at`0r)r+^_}PVm1uv0mI*BRGX9B*H^4* zUO<&JgLHm}a6eZPe=j7y?HBk~qW(ol{Lwu4e?qvQ^~)a!_qTcc7sCB##|X^b! z)K#3coTU21Mt3%c6| zUOo<@S+tKSo9=mtBC=MhRx>`}UM7Cr6G%C`+$odv%Jgp5L@tqHF0dSI@0zt@d5xof z@p$|eL^IxUG2c>fT^W@3Sg}Ua;pO)H#NN7hR=t}4Fw}ZKL{azYoAu{WH|gv6EVsnx zr+^Q&RE64lx8E&qxu@4lV<}y|#OG6iRhy(>gZ6Swj5=PMq{UrsC90)a&MP!tjbbfo zD7E%98p~tn7dwp2$M0^q7ySm0)`}^?GaD)o!B$+BVER9Jmu6P?9YT~oggf^LO^Y#U ze#nh=XjI&L!OvVD`)o00Za+YAM&~lvr*cKZ{lt|*Qg^F7W!Fex^f|%&u4{J|kINz> zT*(+;dPXO3hRLeWUu}oqUr!N+MN2~-UNxuCB)1A_q&!eUwaep*ejzR!dJ)fa?F@`S z93>?)Jkj939luh!%Pjx2=T+@9WU42Ic6F$nOBrTHYh})aPROGTjY(eSd;K&=yL$yk z%P*+bK^)ZQo22rOU7|t}b&H4!atK0tXkYiLfpd=pW%Xw#7i31HckFy9;TO=g8Mw7T zcy97p_6hP~D)9&gYxoMk!sX;u!D25wEnpdb^kH>`w*0WGqTabOhLi)8bG{a zPEBuRx~krl_AC)oZq3dx2BLzG`{;4Mo;9@)z-t4$W1Pt!`=c=$s=pYmlfb#%3 z2mUOa^7)2TT^!Xrb{X9_7gAwmplDT!+XfRwxiGUEAPjcz@$zxLc%~21v%~W z{5t)282HRW&`MM5i~%w_}bfjAYlZTR}w&R&50QGXNVnY`%L zNDsN5@G^1MU_^vjWjJfE=}880)o(L;QWxIzBbuV&bFnC@+lS;^ED`IfA*W{;>;=5| za^VL>)BL!x!4?@&T^8~l7|X%=vtwWf=H??IGi7~vWqVKKPYOrxyLFM^8J7^S>Z615 zN6V2}d|CL8bu7ZE^$i0V6+eQrEy2M<6te0mzF!lk)#jw6YKhD3)DR2@3AZG;aGDoY z*P&u)zNMc;!*f;#I(8gFm_!o{W=(J|n$4wW>fhmipt7IY7blMYDDs)lvJEyc`0gta zkCT}{lEr}ANfA+W_{c-8<<4j4hcl895hq~|4v7I(iK$2dq zkNotjLsq!#OMxlxSKt*MMI*RPf+GR!IhL`3PU>~#n;VtBmJ@gy<}z1fKIfD2TS>ww z00(+8+EEFXvOCj9ae*iW<$s-%b*lgba26I=N_+2ypM88q3f%nZc_d&XRQQ{31z<)L zG6yBrn|YHWVP+98s16RgEP}sYZ;FI*d^DSQL^1SZ0Ru8M7|sG{tz4-DpKI`eb7Lv+ zkrZuSrM9Qmr)T(thZZ?pNG?9U_8w`_v70>8G<~ZU(drI4Ia)Mi6KkUlP8SlF=hbhM z_Uw!+6m@bb%DP=g>LL&9L`z?6wwVmfn8?Asgy(T4fwIZr zEKhT?)Ea1A$x32@irxYwsaxy$*Qv0p>VzX7gWth|iK%s-!z0)@_1ZZ^yUaQY^U3*&@hGP&DkSzD zr5y~Mz({)5{`^BKz2L~(p*3b20!G3c%C5ccQ>LmBkvaDFMw1mA}o+ZioW;=V=EH=fiO4Qb%qhmH805?eCu zT!`@`h`qqI`R&XpZeTIry@;b4}i%2CtQ zew=;o!F027+3X1!D|gqw3rcF+8p1H|u~jbrY1u!{t}LDq(Pb5X+G z2_17-7731)oBN{sW$-LSi_S{6_6}S;5Q6U!V6m!%UdmCDEH)`ZIqu255K{chJnXuU zpI2%A6c5`ZAsm{-^_L!ZV-YIaVK37>LsE2Mw@y%NPTYuekEBeN)cDP$PFVA|-iuk- z0;2F5vCk9BT z1$nW= zNMI;6BYzaeS9b`-yji5fCbFLttbE)Ye?K;%Vx2T938j7q`3cX+ZfBo>@ODUCJutcM zoFIUkCKRUwk58~S@1-z*XbsTuE2Omq#Sl8`qN;=n5b7MH&rD6|sYCF!e8c`Xm#qx- zt=>*LOsI*5SDL`Q`9)zs2YlzHt$u_$07zE>5CPM9H6qIb<3S3?ngRtkVI<&i9!kRF z>Bs?GD>+tTe^U`w_H;00xq=Kp04GTpG|^X+;Evk>9$upsspfT(l2POr3ov_UjzY?Uw*5=5-yz)3McLmX+~48mF9`Qv<>CKV4;m}&&*I+?g!?;g{lVrFEWh+f{)BM< zgtotwaR1jT94qZ_+>viq&p%e--s-e}+eV=6tOCxi2xY;M^2E)up#VvA2?;b5Ujs=f z1(-^X88O5`)J*I35vI>NbjV6Nfif9$tku=psFfV1ulWAk;gJ$VW=S@sQ;VU}+K1GW zXS;@FWJm9ti|JyMjYaD|Ggok(^Z}N~t#-=9l0)qBmaU%IOcjcnx$#JqiuL#ssVcQo z=8|d`i_g_=s%zHseY;+5E2kSJ`S*<`Y)2K=^UmLZ4kE!I?XpC-gx53K6}K@wsUnjO zDdy^v5Zxx6?~iyhWP^$rC1#nByPpCN##7R%t>TYlB5k6!oElbEEoop|&K>!dXhL!cz-L)e0XFl z*Z8f!yv_C!n?thX6C4U`KLg#-yJtO}^HY*bV&*Dg?sCzyyCIByE{nsR339Z%)AN88scmz;>=CM2n{2- zbzj7hHH#=;##ln&LXod%3StY;=8{5S&9H7YI*Vx4(HMS;nwpr>Kzb?U)F5sB$~WA_&gyb_u$Tl zT+~9cJZpl0Nqq?lr*&!%4XN_uS5JcF^a&P$7Dw^i-YXMXLa^3cyKU>2udjJCyCD^E zZbKZlVz})zE-qz6pAzanjqja5SwdvOd&Mee2-v&$CIx=ieap$e3Ha}rec2+EZVZ%l z?5EB%%_U;028A>=#ssP6eqTCSrD+&Hgj9ph-m}MyI+*d{xJd7T=oTm%$k`G^FLqd$ zTxOLp67w^`Q3?czs65-L?QxS?u^tJ`DKH0hJ*f$V)L@ptp4zhu&!D!1Io`(sq+|s2 z9IO>|?0kVprF_0)$*uH$$xqoIf(21gSVXhMsu%fD$JB!b!s3p_7GP=IA9fswIyt z=)XWa5+w%(1|#sUa63}tDNfYl z+PX;J>sDalq!^jTj8r|5v`{!9gJFBUaJ{86cRz|m%_PLg$PVmS9*lAm9^vNhBph`a5C zm0cE;oR!SUR|IUW>SY+oldN*yS z3P_YlHwrf*ECOmX5pc}GCr0vgn}!)-s|m=1C~u#ITYDO4;}(-jw5yyh7RgGaGmRKc@C7C4<0QHO3uZb;I^q{Y;_%t)IO~aDS+u{f)P_nW5VDR6yDo0qL!d z4K62_krqzCkx4_*kVu!Xku=0+>I^FkNMgNprjUswoT^VuvwIW14v1XJ)ud(Q4E-ZPvM{2V zd^&5;X@6{7zFuGB6nUijn=LNy;pW>-kNI7i_mCUbCdt)?xohcO<+EeE`WUL0Jf_Uz z7EUa}b4WfrJTX;dso=MY^U;L3t$GX(C-sRrX< zEhbeglgC&=MeI7U#Q5Der)JRD#4;sYAnpp?`5XIM0fEUznXRm(W}&MBmnJbInyUh1 zT3MECqo6eB65j%2;sEOAyouFy`IPk|hLQ^f`bYEctzmm~FX1iL=%b_Cs|*_+1f%BJ zv>3F403%*YB9F8643tzQscd_q14#o{V@6k2<*dUa+47q9YO$Vc?k12){j&|t8u^BR zN5w@=hwYu2*3G+p+1BIbH6nBiB5FaSYbJS71@J8q;gaTZ;@fRej%bZt>#j?+v@~H9 z^heydVPc;*Cn8F|+HdRhb&*PEY}2y@=?Hleo3y|sB(uJ^y6v#Z1MRYh)z*(=jX>4S z3^*sZlbxp=$71>YlbN+X z59{D@@kDv^Za=-lp39DzE>tGLa6s3tDtW3*Pv=hBL5j5UN}A`kq$wh7_NJJo%g1b^ zfJ`#ov`?1em6%=_kiq3HO9aWZPi~elDGfyvWh`Mywxl$@2z&8^B@7BA_N9~@9PfLD zF67wh(e7gs{DChprhui%Eb8Zs$qkYx>JWm!EHR<2ce@|2Z12a?Iql$40xu%Oz%|~E z@0cS@$k#OIk+#Ib^z~FU+{8<;rIJR#H`u7K6Ac$SLsD>PXWZ(x(;z&O zyW0y_^M%2#lTLqwbY-RMnZv@l^}8i8HU*DyG5G{+R7*Y)p(yHkFz_-1&6`8!^Dcob zxO6-@Ys15H^Qy%`+M8ISRm4mV(2xM`J$DmO>E=Z+sQ4rYh@r&j8w&3 zl^VZ_iXsKER1=>NU1b#oA|Ww_q-73KbR=CKqQ`9plt*!sB{VsWu4}v~ChdO~DWlDT zAe#082le9=pegEH1%%z-!X&K!K02X_hc`0eY3)45&&PL@1W97xuvi%P*vkFxKoH8} zD8_a|aq__X3E)Ju?ZXEX05x-C051}|hyzphW#e+fd}FJ*1k7eav`uN8^M+|2WV}^z z7K-P<+@=g6x0m-?ylL_|76zx}IYR5~!nsqNJWKLRPF`I%1R0G4EeQ$1tb=ZX*No?1&6_!SLjt@ieHZ)k4vKHiB=EJel^z{g1 zp&Zrp6u=1@XPD$go`zQ=wrm=szNX34f*xMCyq|xUrcqj$A7H}h!@~gYaU>;*rE6O5H+t8Z?r}KKe@n2QpMhrZ{5k?o zo@JeIB|WejPZd70!t@RhR&GWBB+$6y(#zO1=)E@(Eg*X%z_ZDoVit&`b$uTn_UE{D zC1O}0){o8u>uw&^j01e+V8D5_ZfcF?1K4|;Ip^xTSI&j={CYJQP0v06_BtQ2g(jlY z5NuTx@LaLOKu?i3*hQ4?T@A?TbeC2w+48@3Ck41GHV9e!kAKY8XvApPjdG7?MyYm| ztKR=SotsCHkWmh>e!#xn7v7N*ddI}`5!zQ|uc0b?o9=Dnf!lV)h#}NM6VUWoVndA= zFoD}_=T{-fXPpbw`ov16@NM1w%y=2N?9CPxUwaM4voA2sUS6A{^vfw&HY0)~*W zSKln2Fx`YjY&)*RP0cbF?>KO%&CRN!u)yT86d_i~C2D#-ym#!a5l4#ELE^qDa<@Yh zXrQc+--?bV0Y7a(8l|1<)zXl0vhuDo$V(EEMJDkYq&H2BfyN$qrZ>XI&V_QN)}BC% zzaoEORBupmTj zu*S#IWfk}Qrc881BqN7TFqwt02K%=J^>PXwGp=!4X+u3zHCRlY$LxQ z(ykH9RRgKN9iQyfa(KLY-0IBTD)j;yT7M+{J3#xnq43`T+7IFCS3vt;wZ#7h(0-f( z_7BMV0cbz;wm;dLmGuq8{>hX-0ownM>ew&M@Bd9}e}1M|y4tYS5i{KC9)-VE3P4B& zj+jMG3y{<#KB)SN1+`U67SWJigyjg9MENXw5weO9oE#al;A{~vpA9anYJ^^Hm+ z9U>v6C@Bq_Qd&YJM39n@mXtSvu4d&-!;FzXI_oORr_=s-MKr< zQ@-Lszl=rj!Y#jX`MsJ|d4=03u|v+8Zn?{s_WUT!lU4aNvv|{78;yi!<9ey(Ap7#| z`O`{g)f8#3PiyNLx6BuKPLOinefrr@%Gs0u8N0^jrb)fSPvLUG+?p!cvZycm4^y3A z-wJ-W_@m)*-`AUYBNUV=n-R5&2CR4|w(XDGK4@e`r35hhy<@#Az#;d0DQ9tkS~R>L zt6#(UoturHu2_W3@%v1TWYX*ES0Z5i$N>5Iov_*zv9ID!mM_>tb;L6aD~`=L_Q03*Vf z+P-rCdH%j@7KI$TVHYjhHfoRZ?x(P~Ic8rT1j-=97HMBl=IAZtG)BK1>7(gg@=FC* z>a8CCy9XHdv>^8YE1WKUTF_XeaPE; zqyNlxud*yOPxtW6cAs}V8CmYPZ*sbH`j76>PSL+wJtVhmSs)Zv9r0(o{f@O_H%fN=JeYBAHKt$i%f<1r+Ou@AJVSqM9Zqn=_XEpEzwbo) ziUjGWUkkz@l`pa|L;IRVqU^M@7#U3gTR_VqpHyN-%{nO?+RsE$_MOm$ zLKSqO?tyeay%&-EygTk4m3w-cH>{A;1JoS18eDUSywb5I7!Q}QL?dWIKB0(R7EuIgQ zEK+5%2ENeFyZ4e@VDMUgNa#K?f^4OdiG?CN$7i$q?`dau z#1Z-HHNIBOK2*X>&lmPhw+^l|d4zDNR}rit^PnKzYQ8A$bkl;KY~qLWG>WI1&kaN- zrIfw~CJN_TthNsQubZBxNs_U{4}UR+77^^d-tIH%y0)B)`ulb%$1a;iR7KAEJ@sYk z8&AphXl$D}I2rcB-C0pR?86V4L(zyHnyh+Lhd89Q$tp>V^tHRXR z^Jzc13PmCwZKgyI%>5J_R2dRC;X%~uE}oL9^Pk9=40hgeLZ7+8Vf{;SRg|v&Vaukl z9Ture^E>Rgsy7dc=CldIrN;`AA0j$Y*J{QS&(qAmyTv}_`t6CyD>?Ge82LJb92r!P z#2(F&)|#HaRX+D#G!o<%)}ZKnY_-HZY~D-Dl0}lgoE6(4A#5#sM*XbDM2bwNh1b$C~ljxJ*BS4e3`rf6`A59t|w(n}fP=O3TisEW*o=Efm;(I(;DFCSyp!VEuFniR@u z#|kmUMm@;LkeNGvoZgl|rh}r8j<+YYQWs2p=8|$Jku|>jxXEz97PXh6Ghy3hU+rhh zN7kZOJ?+08%M?Rpgap}C=(2~Lq#!SPNFRpATCQ36jCw>S`phV(&OSZT{VA^EE$vihAT=5)k{4x*d0qAw|B&O z6-Vj#aojY|E@GC^^r?s)u1VT{vna`ZYo;|V{at??8aYl(2D+|u+33C zUp=B;P0)FE#JOzWSYz)@el!;IjMVe1#wTBD&W1dG zQrtW2i2PC=X%(b*8+k9N7J;YFS7jzXnHxVxIId7LD{mf~rxb+zT>kE|+a}Mda)B5o zEjaQ|fZyK^j``=n4~ByN_F9w|c2v!OWoHhYQu-Hog91NTKmNU)xxby0a|QVQ*LLRE zufoYcupT(8{@>l1%Tt@MndT*M?ba6QY!A!+rgw`V$!|G<- z-sDlkqb2H9HTPVhM^0kzoT4_SQ+!|2%apd8iq)^#WpJqrBL^!E%|NuwpRP?SB_}Hw ze^{H?IkeL#E{)mS9#=5^$Z3Y+Kl{pFY6$;en8;#}aD?&pLbco7EzHOI`hCG4wt`O~?UZkO}EPgePg;y*4Ga??PG(*I_BXpHZGddUMnN5g?%QkST^&llWVnN z3|aCJNm;#5*)9M5ulrQ-Y`OIj-t{Q`3;qTI$6?eLs6AwGB=oT$Uvbc-uS)Bz!6_TX*a3{6mZt|`> z*2TLE6uL=bRA@=5i-k%_Eou%*B$#>@6A`98`{9c=f`(U>Y`4&X;1tZ(H>)L~z?Y2a z&x2=}aQLPsUcJgt@Q#Z@>(+~~+#lo_9Y&)j zCbSrgT-A`(L*Fkt_R%apD2NSSopn}C)UJ!*3+gmP%EBte?|;pi=F#;=^;Dvf#b*X0 z^K+5nAZ2VeMbM1ivEI=8T%lNdn~sNMI`$BQ*{#q-kFv&(Gp}mFN(@zWLq48*mqKdr z69*RllXr%B0=Vo=-9+jt{mgvm*M6t?KKbsqr!zJp5+Ol0KQWTOrePCLbbqyo#;FjM zm%ven#l@j+V)$Lt>PR>pTPLBwyHq^toBCX69>e4*by(dyB_=;;l&q86rKLXe#|H0o zxP||^_-VQ8z30}ReAtUg*1=mOD)WfNWh!}kyPINmgr%WCa3*)laY^H4lR_Qw*6TvA zXT4T&-&sP+i)rKe&eP^z6V6N?Kpa)OoR>zZ4z;bwD;trVAG?^kilfIqc$a<4e-ULo zvY#@Z8R9seq_^=j{^GSqY}r^@^vthU#o6{{8H<5(XmUIdzjE4;cw40D6i&ja!|UY1 z3^5XDw`8*iczp;B3Hs(0ZjoY-e_28fuNIL&3+lg4U@-mq7#q1@FBxk!4*Yg3ieiuh z#bg?};BYFccMRgik)zOFWb|glp0q9IJ1gI4Ol(E7_JQ}uWS$!io8hO46pI`eE#YP% z(KfgF4Qf8)t$DS3S)2#^e5`pZga4hLxhR)OSx+l6=cu*woZIMWtD}{It8LDhk;3z~ z@aN;(-EEa;Q}_H-R5Fx5{_1@53lkWjurh_rmmVS}qC^_9sgK{+-+ZlSZLcUGX@L2l z!QjX#Dg`lzK3!e>=ekJ|l1aGwq*GI|}foaOzXm<$wInbx-T5nkigo)1Gq!JinZXdEDn=@{yrT@xC zmE(@Dt8$;2WFcrr0OPZiub|&@hw<-6WswHrtXOvMPVYQN^hOc$ z4aTKgrh@5(R5`N>Li|1B*DlEWj?QF|8cO9#DVrezcX{iA#?g0-Wxw7Dn;;Nb_~;TY zFR1$Zp4IOs3Fw@+1Ny_~veAMyB<$*Tm*yL+;;AD&u6IHNvO8^PmtTFcBOq*UP$ey=lMuwHrxD}I)>#cxRN#@jr`M_kKT?@uqbeR*$ zQGOTrS=-&-v*WImQ{ubv1!)SkVUAM~)*rk^!ap%?XWWhI%J~$ynLZ~oBYb$BCR`bB zyjyKVW0*zbdz^z^ahov}8~#Ik|NYtkl?*;64E0e7u>~?}y5z*>R)%M07e3L_wgdq$ zW#gt^e;!yeHfiB&PvoHGpsZ!zo_sdF#pb>e_H5q~g2!=)5Zp!=_Jn@)#R==Af~2FY zd>{6Q@?Tn?1N|*Z=86dAjyrExnrz{%_HN&&!MyeM(~+W(r_mQgxz*3lw=6z=OXKWK zv^_prr>YH8KtEq1^jpj+xPzdFy~gXR(H38iu)`oqR?t%&NL^`YaD(nWnQ0AWTb#5& z`GQ%q`-PI>Jo$Me_r^ukdufRUp0o1X<|=f^`;)cm9rGHXNhhQS7aJ#FO#5^-1(-0;>C7?<~l?UCnoGk%aCeVNRsU%QFSW ze(1?#S8u=JRk4wB%zF2DEPKxTm!`7YXoEqz67Ogv)^~ymwOOL~=>bNpMUhp-CQ)*y&N>lE$jCg18mgSS_IW%@7R?d2xsUpHj& z!j5tLFTvZZ+o>>k3;T7*zqPOVw=*QKz}x=^_cdY1DgLqTdWm(xL7Z@?`){0`Z}3br zq@NAXxx0Yvz&cAjC?SLv)eG5orh;zWH?+r!;MFwkQ^M-u{OnUFh~`3mx;*7bwLnP; zga-TNtm!7tWFf~_KRm8!_SS7LjIan3bjnX8SySu5Y-CNnQzU$$UN&th$gkyHkq;1d zN(G4;<8F0vgg*^qm-EM->h-66^SGEd{f?~E(}?ez(c`R9uR6p=mR+=ISe$b3x%+OD z?2S{0H{}nd?p9CSHyAVgivR7tV}+!1kKsyyTK#k}XBGP#n-o$OdG{B-+iw_?B#Un- zed9CvqMT!QL8cdq)s_WtV8Nh$kf^o1o$}I{F+bkm7aYswuCHaw?KsFUUJj!!rS>!` zGvObM{cb4Z`avLD6Wtb>n^uY^PAt>){HY^T&@R9HNU*2|j)KKdyMvalP*H1a<(^tL zd76upe%q^J0{vE$&JtV7pP4I9r6&$~l%L{iOlpSsCV$s^SK?kL>2Bf3B%EX&s{hGh z{E33~uZ3AuTff_G7J*vY^??)BE;mbJC6{rENA0s4$DS{hy2PF|+IC5IKWMLyyDxmG zkgbmEYuRqXgq_e#VXl^3bQ(Rl@DLiu~lMmdeH!o^p` z-Df!VcBM+|@$*J1$wuw{VQJ^k^Yyjy_X zyY+{XL)RdzAOB{EdG%`=SJvQvDa7RY<4j2m4G!3g56~BhSGJl^k%4|<@ci*M}S z^B+@oHV$y9;U8Uub@V^3@b5ppWPSPXYQ4WdxfBnq?Y}?yTh+fkx+1YZb&L}T1{|9P zqgO=&7ZoQL2MajZ7$&x>E&k`ya6VTlY(cd5kR+0-Q4hRPq zG@k>?jfa~PPmBrv4U~qCpBv~CA2skvpbi%Vsw-ST3xRe*Eg0a%4s8$g zo&!h?0>;A)#tbOn#qpPzIWM6JFk>8`@hcDhbS1nT5a=j?`2+g=4{3PLe@xlgAYi~( zcwe54h@rs^TOV-B3wjB36-GI@!1?mj96T^P4Y$_+fV*~1qK1G z1c6Zqpd8fjp#ut2WT3)a&;`i@N^$c-4G6px5129#Ie}9&xnM?z2dE8nd4Owofnfmm z!BWFZ@Bl>u^|^U~;4jkp-MpSY`OPVi>r(g(m?^WRhf^aIQZOgVVjp$q)qbm*7mxPU?d1%ZtQ zp1!2OyzySq&&w}s1O5E(4}<>y3gfPb`|?#75I4-o{15#f3H%!pxS~LRf^=@EiHG^s zzf$ne|1pL6256Q4d)598rf{zV>k_;)EaPwO{grd2@L!o%k?LQ$SBi3g8x>(6Apr9L zLky$5zy$zT2BT0P&kZhn0frey;U!>0g*tuU0ATb=C*f^^-`_$J2h6u}12+ON7r++4 zJi|~DxZMV{#tp6+1?|8v4jkz~;Cw)=58;KnO?D187zhS{1{xqifiDDHVh&&&u;2jM z!oVB^fE&;~zy=D!pza#N&H*SNFBBy40KW`;6NDE~9ssKT806If|1Et5;zJ=99C-bm zUe5LvE&4N}Of0y!$3bDY+$^=?E>He;{|;Rq2`3m`BnOt)^Nc@&JF570K$YJM@|?=*yL~lhY#|> ztN{vcrs3v+_Ma0rw_HG^pk+`F1Z_Ys08#_@5kbJz0`v*`21S{5RJAB^>?7k{m#@peW=odI?$CprD!?M&UU; zpbXF~ZfGC?F4Tn%2&OgA#Q+8W(82J6a09Bd(2|^R_zbWIm_VSRU@`#chE5S@D{|!U@bw{32cm@U7-J*(D;vw2gV-&chDY)e*g!tQh>1ly#y-=)CJHM z)*Egp@VzqLKZDJy%jT~|4>tvzKpO!1gc*lR>jCo@|GV^6b8^+Fz^4sPFFgs=q_DxQ z9LyvG4dc5s6cC`PK-BOB1j=15D=>VZeXu?Oy9qWKpaO-NCU_pqFkEs6p%qw&Fc)xX z@?j>74a^bTqF;W5TmQcX`oE_B`V40VH?ddKoN#jvb*QlB;59CDVQs;4pbHFuc(`x+ zvozelaDo|x23^oOg-;8t++VW>j!M1U&E$rU3`Tij5`j|=V2r_W|1gL6&t{2-6Bf=4@WDZ+VjvO_ohU?t!~fR=@&pf2GLE%`sKP4Hg8`*l^D{^kqe zpa3Qb_^fk-?E|nJAkY!OOTu*yJ|%EIu-n6dKZb2k0eo?(l`siI;Jn~zU=M*?fWwMQ zCj^x#oG;u({jE1J8_NN6QBdh!NnLTeTrf`DFkQY>t}E#)$_2~4I?G@u2|DBO9>P=y z&ILC6u+s3)oUoBW%>&%bfOP?H0XE+dSUwjl4Wn0-?$3P@PFRO86#=$5x&I3k&IeAR zXbM=^E0i1DP6*xig5_T>d8iGC?<4ZUJUI_+NIbxD0tW^BFVvwyjRW+qKH!4js1UkE z07nlnL0v8u7+-k(%QnE&Tw*}jroq)k#m){Gf+nu4GYCwVu8QIx)9@S!s0H1h0EPi9 zZ-4~hTV!C@0ca7}>;j$_3W!pi{H2;I(V`ooD`y08D9jth#rff7UAA1n%l`9bgj{J*l` z{@g#|-~kvLwpgI4%SaF&5B{eplnaa}kRCJuf(Aoe0D*%D5k}#l76RT&Ln9vmbzxib zJm75()Jecx1=xLnzNvvl#=sW=XazhO=o^TQ!3+V!51FL=un4rw2fk?(@HCuq!lH6cP#(Y&5cvTA z4KE2cOF(ZyoDPMp(DWq*F7nC-_8+(ZVrW3UDHs;aiNh%`3|7M_2OONkp91>@Uc~(E z5BjjiJ9>Y;PjKatEHwr`y zAQfzcaJgMVAULjv<#WP%&JE`Pi_YL%FMKdC2(NoduW*CDae&6pP-Ju2BCIYv&CYfS zsA13s)))j9(R0Ffk>E1?BMkyS_^@CU_I?5mQ!gh8w$}n{h!Y0TVPb)m_}gT|h5^sv zh0heM%wMIsVV^l+{on%cOhFtDRwXoSfVBWj2oDT3{$WtKz+Ms86_fJUZVuQS1M2%f z^uLD$u1w+8uW-V@Bgsz9&c_SEV1<7I>z<39gZGb*0JZ&*q-N&^UgY0A(I;ph>2;dM zK?COZM3M+U{xbF=a{)qovyn3HB6GRG>vUyn`noIg@x(Uc7YE8?8k&P=r$4ovUKNyn zqP-WXl0w8*%zn-Px2ixNM<4rZL@#}>NG}r7YgkwvwpdtCUZrU1ojn%Q;~qJjF zyM$>Pw55^s_ww8?T7z(cZzP$S%x@MD-MghHN$lc8Jt?O1$`JjF{o(M8zB%$2H0KI5 zdTA-7Su>BH7m88m(TLcS6N3nBeeCB$qxB9K20uEEH#(2Ky&=!bj(=Jh{-nL8$0{+$Z5Cw>^~9tX z1aA6Mb1zNxFxk$fkQWUMu}%*?c3$^5pdym5CAe!*Uc5Ne_SDlyCW$5GN5pccHT?P7 zE!WN0qvc{c?lvn@4^`&2=<+b3JWj~zc+e)p|~98Y9CDagNjCznO?>{I+j zH6y+8492F8K0*&i5yv$W(mGcZ=QGF6V{L(pyau=83k}8s%l(bT^Op)=e-EQ>M*Gwk zAJR{_aaf%@*eIMj+0r9itcd=cPtEYS<}XB()Y;IcbGX%fc<~1Be0=+&;Nqfq`$7=$ zg6Hm2I+^x*BKq^Zt&7woO9R8DeajCapY5$rN$^PHLfDJW>$6Q7+=5E6dVX}YE??w7 z=3REf@^>%wn{zXLHBW6akHHnrW5dODrb2hNKrh&#@lg$F&YZmCyvp&~mq0A63!^o? zT`Xon7Gj?eq?4iWx~A{s{O2xZZtR?rd{;-pv4O9zI?V`|E=ptalHnv5&kbkV0x_sDV=_w)zxA+A1R z&#en2Azkhx)?#OIqh&+WW2?3E-owz?GbACzqC+%Saor=_Q}pI#T-OfzGodFgFCOed zE*e7GhCwxQzEdQj?2SX*)6EsYaC7ApO19Br1y8Hak%UgG&VnxbL%iko_o=W?4w$!l zb1$aqCy0fUn0oLmUX8beGWFE36rLqZT>Jjs-ZK8y_Jci<1V8(l$yy;1gHIusd(UhxV9hD?*c_eO*6bnMALx<}&0|OC#2bo1HGI4rU;O(*h6tzVmR9Q>LKq=t{F2(c#Z7m&BoNiSn@|cNNpVbp;_dvv`a&uefwTZq z1%gFdFqiPRCHa02)|ekvzwE#JNYpRAbsrJ2#ND%0!`&s1dr0tz&J5Sv0^iSB|Bafw9*$>dn$3+fTff5u4dg` z!w?_Cb^QJhn4-@+R3f>mZn-Xth#8W%DviGPn5dQXiW9hXYei)`OYes?%gbm(R+q7a zdb?gcT4Tz{z4nnir|hyadNC?IE(h6and4-F3EihjY=&8NM)KX(-?d8ZBBUR*KB=*? z&X%^v6{p081oie%{^s6yeR5orYG0k9lOlfCki}k5LC&hk-+61~S=Ye6@^7!T=;*26 z*|NsV&mnIMOW6nqTp0?R10PWb9-0hNoGk+48 zC;Q?4$m3mavf!`@719#U!0mNxV-j$cp;}ddQFnC2=Y8ULL+?kuUx`T(5AF==uf!y2 z-gtgvV$^F^91&YT-i`*VG_dal#SUXPzVEx26&zJPBQM{z{|b``J)*mVp-Aj4e$Al3 zY3BC&5Ail^{<7fZssSgLo7IY2u2u}1J_9H(aegsvnVP(7B{U@%}Sq{Gof_3OCN1M9P%0$q5y{j2icv zk}nO{)RbN;Z*9ri{32?7xNzbTa{KNb?K}9DvXVAsq;-;#IM@1K7imVE9V*zEYw8yg z^O8N!UJwmA>-2m?i;VUxUNyAm`gLC1eLd=v2*n{+wB^r*Uj?&lQ9u0{cN3YI59<&Q zE%3}RsN!NUxX#<4Wuv-1;bs+r!|zQiRR5`MC+cNZVvxeXnEE*b^D@wLa7{_&?#>(Pp>Lc=nO6S87*+oTER}B|| z3P1Qc)02gKr6Iv=X@>iOq9zw#}qO4At2c_`#nY5 zxr3%`D^WsE>sa=N6@eiZ$Fo7Rc^I6%4#94h8S_Uk4tLZG;7ofMKwX<%xSX`Hw5LZH z(PZxYHj(ps$*yaBoIxVwvn3IxLKgN<(frBrmeDS3r=CV)b^*-Fa5D%xp;*=P$7DYV zam=vKFlb(o-yC*Gl3a@;^m0JC-tp_4Gqs(+%4qXTDw|JJC+-rav464DTwQco#_e<^ zvo0pAWtnK4E`&n=peey zlxa+BF;nP>P9{uoR3B&{67fal_D$Z&xTqMurtYvb^uq=O7S@3W262lgx8vQuI@XrI z#5X&cBRN<_U)IU=eTuLt_2G%E_)gmLWPIVra;vSDV(Cdn-AMk|Pr#{>IXyq*7?RPY zg#0*V#~-vVlmGVbyr{^3RkrCU-QfA zsQ1WOdnJXEh{n5gw2sr3&uhl(-Z@o}lile=d{;F*6;yvdS@KCycuSMtHrTVI!BdJ{ zMsOlMP`Oi$0--ulLDypqa|H2uCFa@SmwTW6_-+adMe)-pyeBLo_Iy;nFDJgpHCrnX zEVEa#pwpQ8^cSv8W994-goYuHg>pt7<^3#~T=R;_GY77>W_>-c>5sPKXAQXL@sc>e zuapV~ooS8N<2dJA(VKtun}@ugqzd~%ZE1Lr(A&<4W$}#c<<7Jde|Dy7&Wa3gCEsT( zM@Hd8ZcFipJ4;D;{t;?Flz*QW*Q88FCw$gUS zqhArhW{lc(bqS+M_&AcGBviVRH3QKczaF9SJ;bfV+7(hNpBWSonck)M7JJs2i}+Oc z7dRiLDGQHM49x&3PgnUh?Q9p#!*mpdmSiCh3Vx?72R&9Kd^1Kn#-rGoF*!}N5g=I-`c;S~lg!NA zFf6z7K^Yyfh4gY7zQ`jy%D{vn5dlB6VBtygI`VVbF`B^2-TU?mh39R$j~i7 zUnCpkc1^Ai)Qu9Ei1SRn6PnM+qc5|zk-1%*m_zgQtIT%D4ZmlV6%ohpld8?$2@*Zw zs@-{WD}`9j0S6J82yvF;(`%0TleDS^W+neA9ks`s<`VPjF;uiZ6bL6V^^aa7ZU_As zdzLoIi=8r?oScp*YSH}hv5s2!6fRow*X_q)_EK_ek2w*n4rLxK%8jrQjG4W-{kvQD zm3@*x5Q%5EQ7GZDXU48LQzW}C`Uq;~tuR~Tjm;Y7!`XB4F9k&!Gx!DV+Qcm-7~mSr zueK$mjz5lAJtp?Q59JXD79$R&i#9pj$u~97e^!Y*@p{o#tZLR{@Uf6?)x3U;r3NeN zM>7*%2v;;|tk-O2Q6)bPPF4F%Fme=eP(+{Y5j!?wZKMyDPR~MXfHs|$sJ@t^{Hq%l zIHnd;FKi`0yJB-_SbSi7x}3BlmpnHe{efq@R92&hx+jF(+dA2cm7DjTN#~uOg$X~2 zNMg@B%-J%AxJ9`mA&LieqaJDv>yCjhNZiBoX_S^JF>8D7z8snPZNi07H|_>XTWC1s2`jg!A%6(Q^*uSojhSer!f ztY>5)tA+=se=dSY*D7-$)k@c5(&uLAy%x+q?%a#KiJPxbF>kdcO&L2zCZHirb@G$6 z-^~rkeN^(I;>PA{@@JSE-ZMc)5L(F|?K`No!G(TzEXw_ttv?fdc5J&#-&40E+NX6p zZ;-}La>6hs;+gDNP)Ioc9OA-EA|DTX3Em!IE=l|*G41(%btyH5*%Z>o2)Ucvy!d24 z%6|xmwxuh5YyODw`7u6PoEKh^H)kOG$@kIgW!PE-nwv$apF{e#^=>RH5g|P3CD2j9 z2|v3pD|(w`J`~F=Qp<_Ru)KN2@!7ZLdo3gbOP%O+(R&J>NTK|8b4XhpX{7Q^GnQdt zbB?L*cLyR}gzQEJi^qCD6Z}@vHf|XU3u^JkM!T-4tRG9ny`%f##gSUycM&4r5g+mg z{Odd_g%Kv}#y3+P8{Y;QrtMP9;=SN#+O2x5Hu1n69b4|i#fuYi-xp2m#D4AE?sIsR znlZUAGZq=KoibioS42y&FpfIcGZ$~paw4y#d%+lA9;i>Go!XdxjKy=^Vyc>(BvIoa zBYgL^OHj=h9pPh~rz)2S%Fu1m&1swOtASL#Z)!Bf4L)+B)29w8b%*s&_`QrbNq#AJ z5W@Cs^P~B*?+K#64N#aDv#Wkhkcqv~_jxZvx6{J+q;5nw=Pt9-M`X37i`|kX5s&Pz zjbc7-gvI9swKfXoo)~7URJ6H;jtOO0OGFN4ET2aS!c^> zeiMGsOc<1V$jKn%{#)8r-PExLmo$lIXDXyL;{eldg8tzcyD@s+NogC;CYgFJ2THo2 zxl13u7}9s4-1t%&!h*%Vut3j%#h&Z2*j$>%S+9yF*J#5XPwVc~$wWs*SC^j1PJ8eR z*ZdTJh1lZOwX(3Wm(+ZF=&^W^moEjn6xMPZA+u4KYkBL|y_b&_!LLzw`%lIy5Ir|7 zMF~s?PKc;Cn4`xfD0V6P6INCjKYg_w@RTPZqMhZW_p-*JR1on?!oA^I6s3Amv;IlV zm_9DNEW5Xzu75)NK8Fv*Ic18ALe0V1V9sQE))e0L)rQp$?uM!BUzAb&+l4EOSrA3` zUkU}=G4RpOdcRE@pz%;?A^b*s{Cl%KZ*k6mp;RY*K|~%y^#MkrB4Ji{F@ED-gzN$S zgB1n@qNmRJO`bNU?+0UZNtyB~;y=iqwjGOquC%ch8%Vu476_wLs^2BO@$#B8j-%Xm z-rFd6+=_+sSKUSmyQOlB$0`q&hDjfY1I)qwISL^oXMmX zAgb7e4zBEBRO{rv)HUR?MrVk-mHL-?oTPR&pW5&6{J5m>rwHs&LxNco+(F^1>(@Jy?b|Tl6uzlys zX6&-oEhecm9B!AH`jRGv*dZZ{&M-3fWMkK*E>9n)Az;t+czX4H)YcPH5jUfi3Bi{h z5M>>0B3JyM9$zWK`l)tJjX(VmtxD;h8Y=tw41JuuPF#@SZ9j(F>(X1BcURMs-I?l2 zi?Q19>u3{k^lsQ;2&?cQC8l%Mp=x5oQQbMqb}6QG#2`6RbkRMbX@0M{w2+?ap0b|dxuQtRi;W_1kum+Y zHM?cbkK-KGUO^;$L*#8KVxrinKYy$KWXCnlGdoJvh`8HQ_r)7xg)PC znWEr*g)t%q)TGbPA9u~=)mseV8kR^EN|TTg z=1>!gTDPP;No9OL#JxfKk*JFXSNsz%k)C=egSy=D?S$yHoV>?Ra0%IoqwR;;yX`Tp z$vf_T?#}7H6{BBJ{CnLaEqj?eJnJE%-CNZ{4c-Yuf zkzNwr^Smij^3jWvri}fq`)|&SI-52*9?P$T)7B`D1^vp&aLZa*jSv}1ZqhxU?D zki9}VWcbqHgfE(*O~2mwCR1SmOPkxe7>CX6F+j(<@YK=GWAFtM!Fw#be?=F$vV&y%6RcY-Hxd< zJo5<>73wwtHUq0nX%?ze-?zSTEfSU^yGC@~&o!lbD^8?z757QzD+3tPL*8 z^A?;57vDtZda@o+136CnrZk{nJoaJumuQ?8K~vIK`8)LH5|~cOkdINCrv}__>L9OD zD;n6qRcyGaEd0BQ6{Zo&-1^N0DN!W;CIP3fi!1m}^sKZs)Kgk2inok+Db3iBXmgrb zQ?jnd1&`k^>&RB?GIXcIz?yL~Cy?Xl7Qv1&iqT$&jHx0lVquXX_Nv&@=u#t+bKe{& zAzOT(GGXo*=eD}qxOhXg&v5eQ+?yuijwOqdnT-scLCm9C_t8|e2HVjmAtg~b1k!6+ z=mj`LLX+`b^BLmT1yqVeva`N&NAG=Zfb8=dm5!xUc0NG0dXPN%R&t!Bj8Pp8^T|$K zb+Bu|E#n!iBmMN2i?c*y4x+$2_UogSc2+S(-hJPyV^uNsbKWlzX36-x!T)YvUb{JP zltFUxLanR0PI$_8gvd-GU4JmXZ1S6fnll0&1NBl#&$&T~G?k9KlJPC6{duh8*0V&4 z5BH?K91(O6h9_#*;%sC#$1KCVD|-TOc)uYtBe8jP#FiC4?XR76G!@Oammnv}{?k5E zH9?D`KE>|g+;z87+7|XfoF~23ZDk92MMK-h>o(rkKGF0K~R#z_Bod_YJh z3>=SJJH{Gyih7z>VP&j)RL-@XHextGdz@WqCvA@^bsX_KJxe9f?6b1hv}W`;=H8*K zC#oNoBVoM7SA#oieBZ*T*oR(ukdR9k`0s=xeOxDO?K%s4aq=T=vylriJ1| z4r$9yt;4G?`AKz0>R!^$s5f?(#l=&+4^*8D@T2I zK%s4^+iKl)VV6I3;4uhrc=j|m_*Jpw^G2ulJ;I8F()YE3b^HwNkQW$Ni>6I05&!6E7uz($KGFM%AJy63HtL-k zso&Udi169z`0>yd6ZS?wg+6+f{QQHdtU7G8_(TZ< zY1-2~|?jcmnY!rFN97rl?45%xt0e6i?L({AoH%bu=}0B52w~8~Y2T zd(Q<(V<4@ct+GqHX(LNh#~Ya#H#}oT%GcTA6i)?jZhJN>X}T_m1n?5H?N#5njdopN zjEDctNIkouXMk}wl5$P99POJABtzHl@VpM}ZF}4i&iF%zRPT}Ge34)L;RCy>m=0B1 z^SbM)Kg>nGZ+ulh>r2UJM{xSR<}0X=$VW@;{Cu0zihWf#K<86>l3%Q?#q&q!+lq2G z;++KoADlxl7O8qbQEC&EWX5sd?^{#A3XWd=w1yrh?;-%Lk`obsJXWWMgOu3}cKa1X;?cUnG_` zPavnmyYs(k`B&_!QzG#4W3$hUe~5{luRM*vxwW^EW?ee@{c|_u)$KF`@ikga6J(E~ zVd4)cs8nu=iAk*39X+Sbokfpkl8lI)ztu|XE6os~g*Kb8-pw$J@9KESv!^I}(;$Mm z?1p&fwc+gk!Q;CAuV3p5(s;PGB=Vp65&S;Zn0rlmgHh=7%TG^Y(4~BqxlB$q94w|e z=0Bn{E_{EMN8#Hl`C9|C;wSZK!|{Xk_X1?rG*&;G8F$qld@>EQtvOzNai&;fxfQct zw;+-m?I0E7#q>Khmq3u#OLI12=%s{LGaB1(Gkcui7Z?hoA{C$ezupQ&m6+Xf*7(7U z`JuwQxlZ=_-H$?Z!fga^b~_TgS?X&o0_!Mm<0YE>D%V_5R+>tF-|0Jpiaw;BsjIrM zhM!Y<#QZ)W>0NjCt1UA59e%2j8MTef+V38pl-|(1JV&2sUYi*TYVUfF2KIMK7tA$h zw$$%DGQ@o8Xq9aLYlO^zvTHL&!_*gf+TmKvsC{FN;iIp|pZY!*s)W}0+$B}CQq0DX zq8;+l9E>cra!WTz!JUgDMkA$$_w+?}n?vKCfYiY2iT;4D%S8y zrK;TZWpjKC?_vCN{|zr2S6>rZzm7~2^eL3Y%+&XgltsI=kQSj|ZzHfe?&Ea%d_=T6YBF?--|=AqgAS!BC=i8e6BGC#=X{=m1p z1NWc4_YRP099^+E897CE@$;S}%h1=bTxvYra2|`lcZa5AuAi9I+6*ZMuK@DZH;eJVBL7q{!}uOqncwXli^rbQ2t2ImmcA%fPPiob(VMI zM4bddysvPi$5&W?XXOq_2=$MZD-;v&`U|FoZjpTtmVq(vZLvvPMGY3tJ z^orySIgvwwCSEIp&>_Mm|N73zUQJU&%4FKcBS%JE&r~F-nb-2tYZYkabB~qP9-pdn zFlv5m*VFI{HXsSY+%pwpJed4oHgIyww4@e;fsk_#QrBXU;C|q4_&y53ZNL>v_D2v? zYcDDq8tW)=@6LU_I)k2oSVKGm#_3>7A>3VQA)lb?W|8S5Nx@2%H{U%f{31DS{&>7^ zyv%Ho^YiR8S$OWN4-GF?Ci(ZZkF!#H&(4nu5xu%yQdADg3|>j^&u!UR=J7Nt3e8ei zy&;BVr1&_f=RW_GHFMzg;^}idYeGqUne!uSDGX%Mc@}xnQjBgy!#=xa>qsjBw6&_Z z*9e&<-W8Qin5VW{nkNrr=6CwT8<1%>#5{LRk+4=udb26bMQH@i&HU^$6x1*#Wis~U zO6RAhN5ZP$pyX7od0b0o_BZbd6eKU#dJbED7 zk#=O<&hn^tsz7)D+Q{z_HT$g^{`jXYD@F|`xwq**PY{GR6^%({Qy|Y~-1{c4kh4aS z5hq6H7Q2i;LlhlzkjWh}{l%`JK4551RE87VF9YK?&UJ&xmxXf-xrEQUd$^;RX(}yG zJ}6n4VbYr>BMjYBFl=UAV!H2N(Il&j7L6*ZVS0_yF5_Locx^=o-P0Y^0ql zHfN5_LR3;mMQeTgY#Fj2Iei(0v@Y%AHUk0)PCqzE?O%j56y2eE#lv-z;A8imL1@Ah zAwHSn2Va4J6E%_-m4u_uJ2JMBB$)XT(9*+;sPo%i3I#2(=!MK$GQKXHlwc1Ei0xtu zZmTb@>Pewd_jS4H5sUFa=icr$6?B{LkBiI|9occS&?jjT__R@*rQ14r5&WV%qjPR6 z4L|=JXWkqt5uTAafRv_=EoD2qKFE8`xuj34$jav@F$Irv76P+9%8!Jnk4|4{+rA-5 zYfUhUY%dZ5!FcRG%;%zNwiULtf7A z!=q5a+xJ@K-W&-cj_F23-ZD?}QfP};zRhh=gG8|YtCL7(!YnqV!?l($kUYr4D{Cy; zF~4v~>=F5x$;&>|4&?JzAf%K$Ji+|Ro6x%_4tj7Gb^sh^oW}M ze5lGsT7k-5fO~z;-GIYfwK^xQD}g*r z``u19Ca~cunX)`+S~eTiQl64Qql>i#ys8=S#kOJosZw5?!$x}=XeH#{y(jXQ#w-3H z62emr05(q~P7*9KX;9L)&`$a)H_J>z7--p;?qijmWDG+$g|bzT#4=@rCM=I*`nEX- z=YITMdQ)6#SnKXBy)ml30hJ5UqPe*2lu}`F>`O<+iK?{Ct$UW4M!e_IG<4BD0f*p= zP9l`Ln>%GIw}l@9bFPM^nAhxxkc;!j8{^Ej?cq0Kt>Dx9Vk1e_>u>l9p#=}2M(^c` zyuFd>%*L{i;^&EDA;ke-JBX|-$YI8qizqtKXP{X7u-CTR@^EX#cN8 z80|4xxGGonL=R1sU5T4DCKahpZ;k~si92LtQKWtq7!G0g4e8>(eQZYa_0t*#6l|W~ zo2ZlN;X!$L1w4`zG~%fM#8EvL3g*jh@L~lZCwt z8ixu=tk;HUESG0EkOUaoF5^9zE_&2tGwP^$F>-nzYl_F*GtVhNzE`~ zNJYAYeSp*M8IK*stmpGI6u4$L8Q=*N?e0-4$miNc2o=bjIXB2v65~t~LywJf;bAOL z=z%uUAH$KRidU6u$T%kmAqp(*upW&}d(2^%G~jof$dl4|=Xr6d3|!PoV>6L+DW3{p zH}gqaS8X#*6y{z(xvV>UnA}@V*K=Zjy)?u9N!%3-39}u?!-w*kb!kJig3|(^+G4iX zfrf-ky_@f+yh7%I^R2E#K5EXC7z4xbL+4kwr(&tkih~Lq#Q&LLPa>gh%}RmE^ja<( zYp=fbX|A+Lmu7Vx6m)9@Wj2hki%I)>sm%~l*uH^1(Mx?_W2M#3E2Ief$xi3R!-)W; zh?NVz%0xCoK%G^cylg;!yT2OKY!8ljz(3M6^P+y0Ow{g1BvXyKg=BF=2?3f2J&kA? zNdH24VleC9`MoT@`Z^iZd`@FRB>=-%2l*`jt;;p)*5B0)RAR6?d}TxcvjqJ3cW5Qi zmYnvzFH1GY)nNB{UIoST$=PuYT!k7CU`@5amZ6el_f%|;IP$(w;Ag({ZN7aqW1fi; z?5reC32QaAIa|cnpASYe4``pCGuN9{BCBd>5$p+X=t|IaN-S3nYzt~#9Vs6`Op0DB5s(bTB zJ?5 zo(h;x-<)J9Bu;ebR1v0XJ7~#2+~a+hg}v)(L-hgsd_s%n+QeMRo+M~w9BC5n$x1s8 zbAKl4@+XAX+T4dG?(U8iz#SknT4`jUzX3uOlhs46>8i{w9Y*VSX3^YjITE zFY^_xrCBSTlNDw{GJEJKNrO5`q1COL?rVu_wc}*o{MZvNF@2yptsU}KyA^93`P7<9 zG?{5n=F~!%DJK0W+jJ*i_GAWg8DpT|zD$IQu_7wU^})RxN#ZhdMqqdo+2xTUumiyx zWN3sGE)A>(*?Nz;{poW}dh)i#yvpO4BDh)a3z=c7mi70_!Ehm3c`S9CV|wQ*{w%0I zek#{AZy6C_qYyEOb=F1;cPoMKmrx;9Kg66fwR*jOn>w1o)4XGubDt3l;x6^6vyvezC&|Da5 zJR)N&K%DS84Os|G%F5mnK3GNLSu$f=GQtCk5npPaY@7}aqm;!c>Ow-SLmK4z<3kErk|58x9GsCtam%-KHiExN>EO{|s1oK?=SpkJ|Hz$20RnxP z*n#H+H+Sk?PQNll2sAWJIFF_Hr&3(fDaG^8w8K?3nL-{6{j~v5edid7w*7NR6wM&| zOJ#ur>mXpL!n7gRM$&Ks;~b@N*>bS>sT8&|-mfBi#zJQh&qM7Efx?HsU1uUwca>be ze!YH1EXh4vyUsp3{T4?Q%3Lt@mM=opU)P>$I3qrhdgNh3IOz)smFh98P(>rxdxbD*gO% zr8W5jq~xcZK;U|JP&Ly>r*iV3D#%*^%nXvprbe=2D=_uqDH!tSk5%xznM) zBT&2>lA6wL74X8>*VjOcO>{rO7EFgqtR94cc5-IVs=8__kEH~p6iA~dW_~wwr?c{M zT^{>%VLtrH!MgK7Gs~Aw$Y7~`(EB;|Gc(Em4IItz{PRNP`!pANwzMGxPZH+|d}lh; zR=BVhp*vSQGiQPyOqM9!2|mNv{WC@yrsVyts+3tBPDWh-==~&0KMHz5%`qYowS?ZR zCr%ZPowc-5(JGsEvpBRz+f4c!Kv*61ef;F*LsC(Tb(Omex3eg3xBqZkvs-&TE-_}@ zL49m8HN6E{Rjr=!m+maU_kt}5Ubnc&fn-G#bW zB^E4Ot;p6zcV%_(>*oV1*>qJQ5vh$WX2vcw&0`^laE(ZZ5|X8^P2k)P(5!;4V*$K@J9Tdqq1F zr>vkSpg$Cj<&PWHI#e*8@->Y{;Bl$%lOppU8EhQZmX8vC_K$0CS~Ij6d%BlK1V z9U$@`u)q(g^ zy-Z|o`WcDC+-NUIn+CX9km47YNf@o)B2ZQOK10^hM<}31p z#rqceQ`Q^#N3`8ro48ZSEs`^32F2r65j-v z&yE3|W;t?6`Gf=fmYoVEB#r$abedH_81yM#`xR;%JVxedtlbaDlEo=IGa^?k$U2VZ zx6%;uPmIuE?VyXe?w{YAeqrIddW5M-hR#hIbUt|#xMvj+88g$$i9273cSH>9 z3izo$Yy|goLtUhKMth|@R?$yroN5Q~Grtwa2eszbo{j%r-w~ z$qmEj8Y>Kdp^kuhBdRm5Wvy$2xvG?aSA?KB%Y|DV?`6zcj&-xMPU$LZ6`2EKV#!n# zUiC?%d|XF&1!})Fjg?wXuJXl+2~pQLx8Yo>8jh}Ku|juzp#rw2=Tq6Bo=|RQD00T> z=vaK>g4^&aj1vr9pi?eo;i5SK^=!>z(<0#wa zWZLCedr}VqMfHaWJ@dMT2NhdZRn1HT$1lSThGB^^VIz#RMgnWstwC_GPN^{?4kN7J z1=F(`Su%VWi;9@?!h`6AHg^Tm@V6nqo{kwKPCjG4XSkUr`-|i~#Rd0_w>YrdCJvR5 ztaTq{=a92>{wmIckkR)kZSrV6psq+QP5&6$1LOn4Z`O@-Fq?NaP+N8Hdd?gq>Zcg| zj=Nx|86#QTuh35Ghp?biY4KtUIigt1 z{8oEV082BsnuL8`T!KtWvAlreB!ATX8S{qpGnJ|(AH$#<{&`G{15Z%q>=7vX@k~Q3 zzUmSL?!HosprdI{*=+1olyq>|b5_1Fr3WAl{Q#`pQwVW5+A%Rqh?q?*DcXh-e`-zK zLYylBN;Hh)pL-X3&O3RYL&%SHszquEA$_P|E~oozxI3Nr2^ry+z%3Zw__epJZ>y~MmGuEvFK%Ld zqUaShHHrkM#KGK;>{?QBP(~>>oJ=?Q5>Vwm)@sa~J%#-ZgOS~Z@3$+~m*-5uBhK;T zJ%#v<)DA@0-+l46leI>-Agg%_}%Udgc!Uandu=npMOKXq2V4I@R&IDCFu>fE4 zjA_(-vLf|M30s8r(GdG@MIVG<{?Vze^^YQTE41SWQckb0@RAtCEw_zJfx{`EhD#<2sK z(^ljWjDq@y{bCr%U=S{bU>K|c+Jn@D$jSyuqu-X$t}XzGixsm4oEFhnhmHOo%U#`v z*_g3?lGEmgZW~R9 zC`X!sZCeUQi&nwT&SWlV@5og6WtW}+QZ!fR{-IJ6eN%~+00Qf-dCI^PJHFi?*IBa9 z*K{bA`!*{s`cQg|)$P57`r2rO&P7lE7be?|Y4BAl+?B3bR%gv)zuy23op0|^e+zJZn#MMa5Cx6dh=FP&(;}|Xl7g2E(lJwy* zW52^1YGlUo=Zfu{bEa9Neqg_$WyK3V=#s#b*s@VQTjqHOMU|McwVQaxIaQ)$`35gEv^}w$XUgbg(rN#1S`+O!Q)w zr`w$ymVS#cszfMJg!;Sk-Lequoj3KoV~7B1bR9Z`;AO%e?Q@zG_iA=?!lz(3ylYW4ddlRM z1&BhyFe<51qam*+>Ygkiom%1M&`wcCuEq%~SR8n3#YGkwQDT~8GB%f>Nq3582%-b%N9 zmDX-E)fBV01|o!k(nwi@5Ue|x4^#2TnUHz| z1jG|~Qo}|)(pppG0*7dh454&LYQl;o4ihrH_jW>I*E7{w=swC!Rso?|DV0|6SteGy zmt5XeM@&4KVAy59#3f}W*5D>)oA!otBY(Q2?5%kY9Cb=CaO;t{o#S)ykk_?@%Ab zyygSzpD?UJD{>Oa2LVQxvOHrt;p@4HS(ih8xMUxI8~FC2*Iu zkUc?R%c*iQ_}gz#JL2b_?_sJ2sVtsm8z{EiokSsR);5wiU2BSJ!U?u6Rkx?nn{e^U#58w= z`1c!Fm>IwCH#c-tHgzVX1PB6z0KxzffG9v5APJBL$N*#k@&E;ZGC&2O3Qz}V05k!H z03(1gzyx3l_z5rrn0wfpo7w^_09F8NfDOPFUOUjc-x`Vk2wH#JHJF*%|6}yu6WGj5?Eea2|9`aE z#Hc`VsJy=;m|{s2*AF>VY5wdpupS}|ssosw$EF+O4o{|m2}=Zjzv_~Rg_3DQMl<@C zex0ZlB)7VVDyml~yy6M9ynpe}Tt83VXK`M?`)*&pe|pD;mS>iBvxXqSt}~zD`oJRF zfd7dA1pr{N1q$I3%o~A)ga=^uW_z1}ga#l?>WIL%E(j2LU`QPda_J&|kVL?8{TVF= z{%(^qwhm=v6fOk*!GhfaZBjc4q^*Q10vs;Un;;0W1_{R#G-fQgr~tod{)je9Zuf(M zBP(Ltk;?!NxSo(H0v=H^OMwC8N`ib2NFE#ugtL=C%3M3xkwb6}b8;RKy%eFCXz;doT&9KZ3kY0LXQgkV(R9fK!JH z%mmopt2gNnY%7!C8++|NyFY%dBNq^OgeFZ(VwVbJ0e~WD)IEHZCu-ATf7A$QYET*(d#9*3Zc-np&>zuWcS_LUFGL4x zB~(az4IKu)tK0wrI#BQ*3WQ7$kl?=&@ou}gF2IGm*BHPw6kz|vg<^#R&r0_+wFsn{ zpn_))zr*WynTO3T;j^mEX`{m&2VmvAuzxv%@Jq+()$Ckpv#65qNYY16!++hFGgbWiZJ!1dN(E{il}- zsMClCvEP6w#daAJCa*G8XNMNozh1k+ATm#9g;rS@=&^$xn#}(VlPv@WFtjR_4;f6N+^PUK-sc^2htnK6)Gn>pg)pInYv9 zat#N!wurT*Zr7mKS+-I<_1EgtU-(>wthaJCjb=~z4Fax#85yI}WUoq=Ty~M}Cen-| z-h6dFGCH34Oxd?qvhM}&BcImA!P_y{A3tCxC?cHOK3C9bLo`#o%Ds(f^A^&jydv?$!j$M5U_V!Bm~kQdkQ{Ct&B2z> z&W#xw)P^)XJBA7qSGc9JDd(W$(i)guIKB(tIDMhq?TeKVTzj^De*sso@xp39*S^$JC66+JWT#`-mHJ1z2>mh{oB$DBh8Nc6T&QMrTRrdZFG z&&e#4zVHCp8(44p>YM$&eHV46VY9EJzFx_3$nHOfw^de{>|XT!Ti}nmKe?`C8{-@$ zqk(vQuM8+pxzx}^FQP*H>ss@N=3*aX)K<5*8rFs)k7BF+dO}&U?G(KxjDnqPGsC^+ z$dM_1QH``gy6nw$8dB-YbJ(ooI1_J5FVR?zz4K%yJse8c@3u1P1p~mk!nT&!P+++m zF!dBv^^S0n=yZBS&v4Tz?pF~R<$Ho7lzZz+HPKozq_BalF;$q4%8Ik;jEw$)LYpbm zp=YlXB1U19ZE{@{ZYHL*^O#-9f3vrLvMSp_`BfkC%HP9w+32*Yl=#GrcNyQm;GW5i z8{yuaMl6b~pWpHDNvZz13wxIP`C z6v_eVJ$THSy6W0~g9~1Tsh(i#7EdnOHxt|0Xe8uN1IM|baILNjfwW%jchgO(#EZ$~ z$+$ny9GK)Y6IL)c!1Sg}quFT|jlPmG=-3!vq&M1|@#^1d`_!OKaifRCrw;iZedkkk zeHhE!B~Hq7_2kAGn^&)Wqoumq1dqPgo@9+=E6y|R-g#t0<}V))bM$NI?~VrU6cqa^ z_HCUczVn6WYYcA%A>*WebP;4`>ZT@V<*t@Jpz&vp+gf#9pZ%|M&)EyYEx~k4O{CJ? z#qW>-RdteZN368eiSa6DPPHdF3K@5`i6CZvU^w%hOB{Uo?WsHqT|@C)F3v%Q$2fz+&mP!%?x)jt8L_6sU!?V0UJlXXitHC?tX zD+g)TFSC5QBnd<G0k+-0iS7?2>%G7MYo%1Vwmhsd56*z~;)rSt2rp<|& zh-v2Q=Q(w=Bwd4YX(NHPU08@(CllpshQRi_JJo9K$5;0KLqC>XXp7$Xm$s||(Ys4q zPq(vBQRC29Z92wf>~jXBv|rz=0ma6bYeheMLAJ}77~RSw=!vN7ns4h}8A6wKXa$ep zXj9JQfRm5uLu2Q;Oj(zxNmzqpZqKxxheztD&ce?y}97;1u9Q-m>R-1;{G~+(j zPU-?Ba_cP!r3UVlm({7i_*}-{{!S}8er+?~B0J9Dipxs<6c|JV|j@0Rt36gWHM0s6^`dNz?mzshcU!fjT z221DTzCw?}Fh+(B3yOLF(S~q@*!r{Xw~oW`mb9m0N74hkm>NrmZNbIe!|MY$n%HG> zyWr9$;=bRz?}DiGbgk~ER;Jw*C z9!F^;4(j=-H<`F`R^J&Pi?INZ9AOnI%7`49r5=Y(F>w-=T?}e2NygXlheRL=HPe5J zyt6H$#w)x$yZjW~ZeP|LZ>Z!+p0CU$?j(BJKiyw4@d~{TkcwJDH26NH`(ZHr=+oHM zR)2dj&(tlgbv!TL$5`ty4Z7iP*gI(-T`VNbtLuJ-HB7)W>m87kg>^q!=5DOX*1sU2 z7;t&~Z+MgS--W$|JUq~V{}*qn%ZZAJN`3RDq>9S_i8mR)d6W5{HiB;vA1B*?;pVsA z?SJ6rKg0jPO*$r~Z?OFD#7XxLoc@bB**O0%%qjZKn92ZqfW!Yl#eW0C|A~tK?ymi} zY5pfFemfNZ0}lTw72x=Oh<{!C@2JShz|8co=F@K)wXk+Jb^NYnv^I1$6)`ooGco-J zQfMb94?4zXh&XK0FU<` z5EvaDD_TPGLPi0)Rv3Y; zDJURRAfS+;0OCDwZy;YjzPg?O`yvhjqzm{4VDnp`#a(&@RK^Mr+})7iwY5SxU_X0>Ri#YLr@EDkT`QxL4iM9*d0QFG*XzZJw?J2uOYyc5>Vpz-t_i3eD{}CMw z!T?Q?#<~a=;^5#^7eEZ0b^+wWD(epqa&||daWCI%+^atX4CLYe75qN&u1=UXVP{s` z#JY(E?0Os6whC-*DEIBxsV7HRNBP7Aa;1Le;DgXvexjd=tbY5>#|2MZ1cRxj3%XpV{iee@7Ta$Uoa#zfP$O4*y8olkF$dRuc()gP~5C9~D#{$*KR2(vjb zbZj?Hq=@uY(GXMsEaY843{oHjR7L}IW??h)P6Ip& z1N>m`52Qa`DEK16PnaQZ#P_`3D+M6zQ}D<8*PYO>Yza)k^K+1fRFTlXwJ$hd}>Bi)f;8%MGkAM%iD32yMG*y*fZGQ_s z;uQ7pub^&r(f>f$-^1Jj`+El#03l5V?f4D9mV)>-d{r%h4gBTW`id+&GJ=8lkh+Zm zEAjSYcKEVlS^Zkaf$#MznGH1t$A&iea{D{=68uuhXxIC7P4{wn=ZEuGU-575{nrkK zlB<*Bn~m8Q%8lP@-!ub7O%GyPfUB@^iZD#9CQ|BGD7N6&ra4_1+~m}2PnD%P!%xWr zoePGbX*kq_U6c=H1YxQHo_w};hQ_AP+<^x-b_UKY19}Br4(O-zy*~Hb+s{?GGWGwr`%%&$GXsskM9gMks%Of1gIC1u^0#m6tK5{+F?_G z=ieL;AV3@pZj1x40mnPA^{&L8ehfM~$j$ht(r1du3vg%omxPcJkly4xchJ`y&?_iV zr|VaEKW6Jz%{h|tfFDs>ciH;`Vbe(+zla42I`zir?za%8X@Vg?eBmRELI#H7uA z{R9G(k^7bxf`_WDcnKLF-x<0RHou9UYYNIm6iZniPWYA-_bY|Z&eukz*y$iIQw3x@ z_Q%DvT(8>RK*X&o7Na)In%rNU#kXP}^)O}DyR+qV*Pa=?&zHSsZK1c>sec&R3-2=U zNJw2jj$W2E0%xFj?>RJoEYlR4yh7{^joQ-chC<%45o6(W*!rk3?T9aBqd?(XtJM4w zT@=n}(q5<5H?ve)h{CeH4b9>sm0jUC-X)Qt%I1^KiPum{C>U}ixg9f=uKF-%&qEYAs=F?fbU5dbyf$ii z?f825Eo4RT*2xZTQ_ry>w;uWo3k0O)C(4T+9o2L1&v@s#=+*lYAY*7?U?n#V%eFqe?RA1K&=B$wzU{yj z4+uKCJ8R`?G$eY(-wz0!&G6p*r2Wpm ztpp?-XKt%!uATzf7!7jUb+WhnNnpk{u0uT^xg;4#%ky=wCD}^NK`CH3r|jdj&ZCs! z*c}v|-COLA7usr-pcZPt2DDYdT9DD7k0!3YJM3itj3b9D@SMl!#3w*mqiwNYO+)Ep z)DmTH_UU+SQXwRY(-@1JoDv4+=2{Pu`OO_&LYETF9*@&{NWg!13I}sE;}!S@b@mjK zhShRy3|KKWb*A-yUfGrZrO4%gJA(qF;b!yljKfRZw9|v9`ioELf%{F8BO7hSCegXn z<6ReRcGtqAcI%w`rAk0T+PLHmr?y5l%14Fq086|hO!B6>i3%rIcyGqim=>uA5lWz891C?Gk%-4it5KuU*{-;yrbmol7`#hl{j9Xf>D^>(EF^r~SJ z4^7YD1U#uqfNTh#_-I$Qimc;(17w8vb01&81uu+lzbwAzAKFe){xKug{(iuLyblNUSYZ7=St=0)5^Ge}{T_1;(JaH}1 zhT?OB#~b%BC+e_Q3xPE|tZTIGQ-C3B1^aNxvZ#l#0q6FSa~ztlUK)KLn3*OD@}xUA zgJC`MxlXAbhQdiLEb8$1C>E2{d8H`zvtav{oAgwJ1pv;T(9paU%Q$KYt$CAxAGJ3{ zS3#+0A39TW16QB&+9f2j)9|`$EKf)InRrJQ5E5oIC$D*uB%H~u%YkE%7Bf~m6liT# z1xvKYCL<8o&85)Yp%@G7>2RC(d~?D!&2X;`cmAjqZ&wMobfvxr*`Q6_lqRpA zCu|J@5@@z#ZWnr&sXfpeH4+HHuG9gWn_zLh)m1`sLC3M7%1U10Jq1r8qvyU^RlKx5 ziQzt}x$!u!I~sQ^o3Am~HIDn!(Egq~l3O9^(YZ$hcNf{0KgOUNPkKP=tnWDibm2$m zP`}OJPr%C)-r@d$S9P{)5%1n{G&^ZeMTUs#(;v@vW#86wjM~b{sl>i4;Cv&annza^ z?*a%x>BWa_O*cyOlW|8<&E;-C+80+;{Ttd#`|h7d!-BEQ1LL-&7h{>_mc&m51jwHO zzvLz0Fmq`L39WKX$>g}vY6tVqt;b6)kOnDQ*}9e28N?`QHxL^&SB0L&^7x!OM+4jwfxSD*@dsjoa_Q3guw2(<%;*GhhP z+x~!GoR>0=T>@T`8Q!wVsH1Z!t?}H4Rich#P65&~lshI=ed9|_u&RlsFB6oXnIfYW zfp;UnC*u+EcbHwtLQ*iyY3`Id-ooUl(49^Z$t=5D0;1H$86ThtrJLifbhR>;SmRD8 zE+gwT2vq-pGjf_)Ra<&4ME@fJ!=WimUp2m*+76E5{FQ}tj4^+2zGxig>a}<}-bV`A73_Rp4Z*9qT0yGg+H! zX+tYTC75W(TDI$7$w?Hg-BdLTh9g$2`@Z9-9$$h_C7u*@)DXOPV-D7I11S0XA7+Hu z;Uxq$4|(w*p%gG*1o?WI);-Q_hdA85_* zznrDGPT@soW+h+7FMsg@PusyG#BepBvWu(`YdnejJU67D{nDTI!**Y@m+jyyPAB|U zRjwXM*0*Cz>nb~zN)o(-!ZkJIoUd;sdAlfQxchB5IO5igj1~8@?p$kv%-oBA@&b`w zvrC^m66}uw8Jh$`Nx}~w4!0k7WvvFKu-LJ}=kFXd?Ok9GDqUGuAvJ9QTvG6Mi@L+X z6eEV@XjqLfuuoSVuKZPR2^df^JTP=z;_qXl`P{1y48o6-z`PxR za3R4}$*?T-Vjw-REM7bzqH$@9KOVBng;7vBMmH+MFr|KZ$wSLD1q?5JW~$3pXj|6w zKx^o>9qWG{MGfo8aDmv|9DY=t)cK)_7}AU1vYK0IocU)G+Icx*4!F&KFs& z9`O^q-;ilap`>k+Jk$CTNzN_S`_jmgbxvdXG8$)lwam{O`U|W@5IeQQJ6DvIZ=EW1 z&L-N;)VJ0}Vf7!r1wKd{>CL=36(5loV}d{E+m@8~(-&&f%h-hn$Py^$r^k-U{#+mP zjB@r%WkEnlm5^<6n5sW&i@Plc>O*+?N$5ogrtBx!&_>syj`tAF4IcSmy$g2==Da~N z@IA-S353vlnIN8!PnyNnLzBkx%iPJ@Ng31>piia)e(HZw>H7@H?yi1xGj>p{)!E

~#$XIUa{=u5nI)w24>jtmm-BG%F(W{hSLz=8U7t*z1h3j1qcz{-XVQ4FuhBCl|bu zTGX8Ox;qgkua=E!2EBL8;D`Hb|8b5!=zZ@nP5}3erV@DtN^0&m_B;A2ZuFy;CS40h_Fe8o2k*N6?@*) zj|3?}o7bPXpR8e~e%7fj@lO>JE}F^f^49hoY9=iG;UYwZ4yE;!QC_7v)a*PC`N1Zc zEL;@%r}8AOxYQ}hzXh15^d$%y{M~{q9!qFu6q_Ti?_kI$vwl?K1>8_qFPQ}!{;0Tb z1-_KRF^t~|AAvrshRC+gS08p`U%F%V99D8jAebyU=L+Q8_U@St>aW_|$HE{*;j>Y5HI|f5|8arf4Y>>~eqTBfr6BHAXbKya;LV9t1 zsgP6pwQwsorm~V$qYb1&vn8)c2LdlnJI|MF9_`eo!Jl(% z&c&1ncBFw@s17FW-3cPxG1Cr7p*hnA@ZV50OQhObxVJ+)qtkmgieNBzPHDt_?r~c` z#IR-o`~)mjspOgqs1nRlcZ`5Fl__%urt_$E!F4m|@zScWlFB&JPd=Z{+HxBdkGP)o zs+J2j^Vr9s!EU3bVzWBWL|8|aG|BTaJnEF|Q__d)*9bXjG*v@0Yp-VO;%iXeiaQlJ{mg-8?K08q(r7NRkUb zmGyQ-(Vw5VR<0+K8FTqN5h+rLAWCM-@745mbp#YL5pP_lNM%}j!wk66{Zl!)wtmEJ z2NFRkeINX@i2n%i+frxP<(Cy-@#2smab+N<<{w90!(@ueyW(A( zl?{g2UQ^&aHVtY_14WZto{0x^Mt2l+Of zc#K2q9v#L9FfVkmnJ~I+Fgcf&Pf|)b=_=AO+QQ!J@XzbLA}dbr$UI9^`}sUq`Poj-RsUhNWeSigl99YAI4BEOa+ z+T;`Fc3{@2Ns_TfMdLL~ZI_NaJNisa+wpB=l)x2F%xg#=R2Z%%QsD~%CCNWY&=x2? zUn_hH8Wx||_zh4NGkTE}IyaXKrY7{M4Y=HV$3%zwxF1-?8-xG?upD;7>#dY?bhns8aK|I?{%Yw)5-OH@?_)4r6m3jJ+m?hRAY_u=;bR}qY-8?Co57-*y zx6;tN$me#Y4qtRwnLWo7}0QvYUmzZXB=ix{K2AqaMkE>{o_N9wlGkBT|j{q2Y{ zEoD-pxEAhquH`=y4=kt-Y|abS+`9N%9z8$6%bS{zM0yk>Iuh2v8FpL$)^^-|MvBWG zR{pcq`9;My4n=$u&IFZ=6XY$)Z3>2|8rn5+`zspo&eu|XSDaeF3ye^~hc{SXQsUBi zf)?y=FS^~__$PBGXw$-0AAM9O=0nN;fKaHb~ot(EfsU=E&8nzye!Ac z4=Ad6Se;*|W;30lW1KLc_(Ig( z{1PN>G0U(hc-4E-uc%ktEbVgz_x{G)j}y>sj>s95niLS+`r{4lwZCxyMv=}1qmE75 zXXF7Nku=3dBI4F$D${oUN58Pf3R1z=jH%=&MxT^^bUriM+}8xVKn~y@l%|N73Yp}5 zX($eQ5rm+L+hO~h6sK{lN&T@_F?nUcM+WYee0uzor_i89=(Pd$Bgm(Zw+vyE=S-6j zv_T*@i*}${}sh<#BKo@K>tzYgU-f48XEk zvDt#X1i;;={BbOC z85cF@=!hG|!C!eEkm zbXGLu_;b*+a;v_Z+)9=r&wVHi*fZL6^73l(ZafXIbnDCDvLqTyz>czx{hLfff_Uil z7VYy&F_jNZ$cBa>akYYiC$LK$X;D0AfPnhSOpHo_pct20{sRd=n1}Osh;g6SPvJr| z7n^-^hVHxtWl15wesj0N5E?g(z!L)t>_H{hJv)0mmLQvtprEHaWqm??o1EC}IXO>z z%E0r?4N3he*VQN*Qe;T9D|oHw#m1YvjP#MuYlPW2z24O07^MwJ)oqV=y2&y>cvK_k zQE2tKU$;%F!H$d9?pQ+E`bfGZgs?>0u=qaznMK zBq7xfFX0GVy<0nBQ#7Bxs*h(k?8V?6aDkoEBE0J%Gf_qM3`gemLK`0TlIMXe(3+Zi zkn21?GHF|uWKGPvttvR?M1{rNU*2U#x!2pVLJ>=hyNG6To_g4Cg<#ezej<()o?tso zQRI7fWR<#LZ%FR6o|zWs^K2^Luop5~tw29dTqo_4_nbl5zln5jFk2t_>BpTTpg+sG z*BcqGC+nW@>^7i_j-mD&9^+_cm8gQxD2aq zWa<9XR-9PcC|p*61z2Q28K~v#%_l7h4`S=Y7pA%O?x6pzSsMf(4CIm z+wykXqPUX4ufyUXnVT(^9M!1u`!3lLV=9&4_B?1_wr4&!Z4Qx2=?+>r72(GfG zu0)*R_rzN+DZeC3*58YJtW}r1w-J~b*c7^|`dM3{2eBq^PoMG|e75sI@2RaDu#5cqLbi6_3D|zMI|AAQHkIZH@Id1Pb%1c`;?{l zWR#Ina9fvQiy7UB_7Kr=KUoP=sZ-=lP7d|)sRaLF{v=ILRL|^lWL*Y|T?bqkW5^wa3hGsV5)1zGOG|5hz_Z7j+<|OSc ztN7QsN3#OOl#U-+mJ=3SQo)&u(SwWQRG*OTpCJ#mG^PkWp3{5D74O(~vE9GB>*W1R z;!n(5F-8Z$psZeZtDf(D9$pJcyLLZY{c$+)V6KF3pM-S-GrX=#YS4*F;YgA;O<{(v zZw4ZXmcUu_Uy>xuwc<BbqGlL>&^>l_aBLrit*& z$9&Ndf^;u}Lb(o?<}dI%aL5R+ljNQJ<$^g=UUr_5bOM^@F_iW}s$nW59g>~{NlaB% zhO%0iE1n!EfC-Mu`iHc{K5$s5J_x#0=Ma&@kX8Q|Yv&XtTexWFwr$(CZ5z97?zV00 zwr%gWZQHhOyE}bygL{&5lbbQ}SYtiZsP#~_>i_2aCM#pqrIooCXmDuFegvL~?_V9( z&50BB9$ikFW4((XUxz^`RK0&C6Vq%4sQm7JldqrPQ@Uy$b^S>60alenE1P!#?vMPKKhf@dCq zoWWqzSWbuB!~~fQ(9VVULn~r3AuXj5?B}4F%*$PsO-u;+O1TJXe)2$!B&AkG61>kw z+hd=MI%`E`p!2dlqfsl)8g6|5;A%H^Tfr>~7wd^GlVJ;@junKmvfCqBiGly^S`sAJ z0|Z;#q6xkI0e=fK?O(U!;)B}t4`Y`z)Tr*0aCbfN5yigoAk0~+!p~9{m_ZE$X=Etf zzkhukMnubXzxp{f5=WIimJ_Ty?oXQ@(3Q!*rj{)ychLgM_=Hc8kQ#X%0_Xw}KNuSA zvsy}7wC-!JlJ*#8ap0J!bKs_DA;|!Ve93Miv`E3_4QpP*3Z0=@yY?!D9EnvU(#QA_ zW|u6aS9}&f!PJh;?Whx_NccIZOBZS5ZoYOU&tkJY+wm`-dL{}JG2PI*X?2uHsSw0p zqVLuhqSiEKl;u&cU$6Iu*rOsLIB{uFR5;{A!J2PtOJSk~DBDz1hB&v^R4yvQL@8e@ ztu}=+oY9MX5hO^&w{;m3&$sxjgy^dW)Il<+xC#Yk*5c!AaHEYUUMOTh%xj{Z#PO z`uzPe{aGW&dSi??z`C^#<~KYhz6FUC6#4pNtsfV)mD&PgCfg^1Zx#wlk83ZmI1^AB z%uU4OUp8*XReZ=xOP)?qU%2e=O65HfOHi|aYonkf2o0(A1ad%ogOc*y}dx-bt{p=lw?zTO1S zZzzlxYKm!<#|_qgt0j~`R1Q?IA^#bSyYrF4?2EQE6KVYw4Q^Z36<#k>p>k>D>eqb) zWWORdEWiIovxW^=cY-&nexWajd}n*hw(=8iN_q2MVNdma(cK2KL{WrQ&^0(}dy3X{ z>Q32hG_nxN>A3(l0KV`byRcYO$3g4}k+;kaz&Dikve_QNsrPsR+|utHVA#O6$`whM z!p&Mi_{5`G(ohF~Fzxibo}lbTj@5^0+2?AX-9vDER%5`Nf;ZgKKb(=K?*<%d$if0C zON=|uU)_d#uRBeA9G(68(RvQV=E=b3A1ZMZr+#eX*ZWb4v zZ=nPes27_}0VCrfa?8{x2xHpQt)?J;Ki8G892~vp;{skmo|8AG=y0iUuaB3Y`fF@Z z)+u+G`LR$cz*-{5`wlnZW1Ct#-s83>{7PhAlj4sNk>`b)m4mS3yxp^pCw$P2+s5CV zE$k9Y&87yF+l!ZMrcHeUs=PdQ(UX%))b#I_z6wBve6h#Nfg%B0~3QvtB$gl{+yzo)iX zmQuP#psPmJRT+w1X?H>dm?7o0+)K{ItoJBgOg}DmKtTq5@Niojy5dh;{~A&G)`0Sx z+rYP3YJa-i=U>0ALY2z|hsjy#>pw&#IuBV2IbNswMtKimb1zZ$Q-h_zk@MMGo3K97 zvhY2c8)EJpd(soqQNBy{^A153Uw$AumS+y7!cF$bTH7v*Q^tgc{;>fOK;NBF+(~E} z`vxQ@Og;KnF{PhG4uP$q<$o%sB&Q}KE+O_4Q<9bZ4^m3BKarmQR*U(mmHbmJ=4aad zpK?n7z7|8v_>YVKK~Cxa*o~2(H?p<1Hu!11nEgbBelkQqwHGTBM@M?Af9v(o+nG36 z*c$(%_VUk3rhnv?{yE9?-!_u}ImyJr@b7j9*%&zgW$ERoaKQ1OPBJ-xv#ejfH!mvv zWB?-a|0b=JTMkiJDmREA4M_Z15v@#K^Ng9psI^SiY*f9>r)acHQnFlnE4jS?$o{_f z+;-f0KFGAa`mLAq{-(_iUy_{{iv(i=3|wIP(TR@05llnFQDjvher%D z1o@Sco;eH>?IN5TTlYOK2nrjjf5W8;0d`#yC8UO|aK7jykP>^WB=8Sp@+B;(Z2u$vt#F2 z1BL_s0D_qb=IH+>Kqfl|#8@TX_&R}AY{HO-z=G?c&O}h)n1jXNjSlLa1@N->%PVHv z>4L_29oBe{2_)F5ZU^)W68x5YR)44#fjGFE;aPcSTM3mt6qwRx)Yk^-v8*(!M z0Yo6VNFg2=g$<4gbrV34L%{Cnzn&rlsEOwT2mpUU=V7P7+6}Nrb`j?I44}B9hW$!j zjAcMgtY^jvvnT#u%%K8;4c)8W)H;|p#*L$pFTBCAm1>Yl@PZ}0KN_AS4K`0&zEpaan2foQ?+LyP_< zes&IY>jA`Q;NF;i{s{`v#svxhU;u>!uJl|YNZk3>?JwG`^E3Ipm%^;kKD7WRyxl?)(-CG?D2i1); z^6kPJ{H=^lLK|3n@I{b4^SU zQW5|pD#R^eAJRXCl#B-c2jf#I?wgu+ z0XJ%B`EwG?YqI-r8yh~cqDMidwHieADJy5lHj|sH!kvtJ22}7lh?%J<2%PT;mB-b*?t}j z+q<+Q)+1XsdY{YR1o(cI3PFS`JydWcG?>?Z0hx@DJ6q3IAQ&_VP8x zs{QdI`eGm)#=!)%U5$Sro|68%&=GemuLeVx_^u(>20m5TmZkg-99{f*lT34Y8`ttf zgss1_slO#SYYWXR;IrD@#`E0ib0=Z) zJYuuRND|9d66Jb4ZwGuIDs?)^!J{l~z5vE5;L)Aw@5Qoxdc}1fmAr9~-kB|Yc-nhT zxR1*VcB&KogOA~7e#obY!`d@))ao2R%6_AYgYg<$(|gKs3V>3}QS>o{*8|R>HsY?3 zn=gsxP~5Hx4C^nAp7E^17_-}g9A`HJ8s-ewJClMSUdk3>{M+us0;yZb{Ssui1PL7B zV$NT}qe(uaDtd|!I!F;*c|`XtyA3Nc;QbiuPM8`K33(J4>** za@LxCk$Zmh)+FQxSht*e^hNBvVDeDtw0Zm15qkE|oBQ}EgOg30lWrSI65%1{ZGO~t zsPoERI>4W{EbQkmu3g+DvF}_p>?KbJkDEj<{xb0sfv9PLkQbx)Ou${uJS179^WNaH ztx{oj$<2W^R7_YI1gEyx*krm#6|%GPzs()z@9Bp#+^pau;^1wY6zo}3tq@mfjGqG> zpKlp+b)a!-;&_z}rw;y~ne;XYW=2h7B2nmivz=&)n&i#h5chNU3qHH`Xs->I9SPjd zH($&1phSb>f?yy!vas~J1MYY(acp{hXfE&;+sSl5p8oYm`Wz-X+$ zK*}_3RcR z5%#9a6ESyTEwOw?`hI&?tXX;^YO1;A)y2c~>pnE0CF4xohu?O1E!*P99b@?RrzCsLz0& zH3^6IiDjL8c;n^VuRv^i--ztq(r42Bmc9O>-$tfHa2j-7kl2H$G|*?QaS&C^j=JYv zNW*J5N;+y7fvb~?lAk?lUFT=6F|u{;Yl!7sX$dXa}?s~E<2d_ z&0uKHepr7`!nq#{Z(qUYp@%)&_j^{)gsN)}zREA694#970y)Nb2nOyg4qAfH!fWWl zTqpw9&)lxDnO%q`8ywV!d1k(XN~Clcf4&0rM06f>OaU&UvP9VKyQ;Y7II&lR`$wG? z-&jn9(Va?qEy>T{3MR}rH=}KhyVSD=bo{E>>>{Y1Jh*fbg5rCG(o|gkIy&tfZp|d* zrb!$5Rg%|dfEE}u>$l=7HQRm`GLHKYq}@3Oe>7CO(4}9hE$=)S=w6R#bT@&(kIQ>D zB7lS4Ub$C^k?pU)nswB;MtOR>(42xV=B=u_YvDX;lil0WFb`xN(`Y-JRgX#oanjdq zMI=+atULSyLA->}kTGpIvla8;nrbg>8SU_4tjdRF+kn6Hs`ols`@NzlusDRO6;0P- zD(=vqLY=V5wp{FUh&=x*uUn(A%oIt!w1PF`-iupP+*rwR%b+Io1?$Y($yHgzP_On` z{!-@{adKBP{ug4sbJUmW>=C@|ee)Ctb=NY}t!uVM4|MQ{tXTPW1-irbXG>3%<$gZ% zYq8<;d@SXWPuW{`=a&)LQ33~2;265nRfAUfRb1lXZJAD0hLCRD9Zg6(e^h2S{rRO7 zo`p^DG4zG3i`>8rdKW~=QYyO@e%IiOk;so8$ByU=Qymi%!@-5Xo!&}BkQc;^W8jyT zP+aXw$lvnRZ?E?Hc#cJ%w$*k$hNjUS@X3@ldgxzELfk8%ZfoYI1@aF2QBs#(@b-Nc z>7MU_df~F=wsfkI>rSI&nU;vZ-^8P>G0=kk?0r#D8;TTlw{de3@m< z&c~3AE7hd#M&LPqQ4s}JU4Bl84H#<=Xu*wgEO2dnL zz6TsPr)nXmoaz?SqXoZ!&2IVjpXG>b7?0T(Iwa2&4-`dW7Y$)TFFc1)Ydv-76B9Do zNL(ObHIukC@cfvZDrUBYEg0i$-uP@D?`)!%C{LUSq9=oUN$i6Au{Al@6J(3)zBi8D z8p93J(_Z^m*e`xZlM}ht8@vmZ>^aBrU9GBiZj`Tmo~;L@92hl&_C-a6^To>E6-r@n z@volVC)oOmx#j?U9z1C5F^aSK9;35F^44gF9!!_y-x=S(r>}Nt&j7fUM;@Eh+(pGTtinC63%$K{=ZkZ9=;8h# z$X`IbL_hV|Z*TE?JVd-qp7&VBjZ0noX-5DW_<3^wegm$k5ivagX5Pnt9HS;HvOsGp z@sEvQU45Oi1xxqr^6*Uw)2*^X{!5J(TjlI8)A8a+yjkR^(?6Lut2mX57F!L{7{jX*mPLYv53!BcLbw!Bs`V0B1FgH8F+R9L#liNN0ap%UX4=WzEB`yP9YJ!;wiA|Bz^G|W< zF7_a%3upqL=VABtrXyRnd%qQlyYv-~M2n${a!>8~;d|o&qib3=*jz%YB3?l2KUzg< z%_ zhvL@qzWYL1QIvJ1;$BxYd!Ry#qZUJ#LCzr|`;B9hI>zg&`f>`HHI*oH*_6bFj%~4G z78WsU`MaWj<2>CI--N$iyx0&B20QRuv zh@Iq3>JYUiFciof^GrQii<0=QRDltBv+?F+D=MenD$V42Bb`KD!_j@$48tyF*Cmvs z?p%5e;c;<9%G63{5SX{=z4&X-ox-ptck%UCuwmR`&2T`(3V3L5;sn3B+F1OYYelGU zcvGncc?ta_q8&0GYZ_a{*$u~VMZCq9foK=b$BPlcMyx->``5bAn7Yv6gSvKP55JD| zP<{$p`dT_kPKS>Jvky$?(*fS=j_DAlYF(v$h<;Z9M5hT!!S|u=ovuMl^aU8w;Qm)2 zi4NL6_dvO>d`o=?9Ktb(6X4T6wq@k>Z!Ule=9YtWY9)1U&X5cxt-8)I!;_nl=9;H< zQ(@ed3)P?DZsAN&>Hbht@ozK9@+5d0a9CZs0`oUM)}Iv;JfRHji+XsIXWgm&@aMMn z_p^3)g+!q=eZUE=uru?D%Udo^@S#Mae86I+&{QjqNk#Q=VkV*ss8zlwtw&FOgQ7V< z2dMH$AsL^K4&h@OQ&c2Fj`U{#0l`xIE6k-v`!UPF=~plCQ~2iMi-)eZ131(EF6tZC zoRA@J0_G{Fh%!FXk)wAuBwHvUo@!*g+df=%1fNbkRP6-#*fi1E6txyEuFeSfZgfH) zHaSKG#KiQ<#0TC4B0L{D%#O`&q^4JuB!3-47JM7YIMOxls(VaR*9oCEiKYw& zY%*=Vt9a}HB%Y@pDv*JhQ8Ut0$IA<-=YnmXK`u_fwH2SGob&i+GhH+fkMxnH+zM4! z3FWw!oMHg!wizq+beN`F>**I#2;-1kd}3W- zu6_lT?C66!Y$#Y6>?inFclCVXHgh?uP}B4t+L`UlS&UEhUBh@Xc!hK=CKih;Y8&ri zVR>tL3Q9GO_|4i@wM)UZbPZv?#=nRXq@P-Tz0N0SrJpG zUE_2gUmSFr5VzdAge_TybdBhfffj!L3tBh;MG6tm;;ns0{%RJVDpb5Btpn9iYkS(9 z`!O;Eb%kcmk$c2jVeWCmKvAT(1AkM_IWK&#aU48k7fw=WPJ__*m9R2Lrhw{@7 zYTSvmxIA~)9$SHK?^E?@@Jl47$5ZOKHMrUf`qFB3vlQ-(yC52xCOi(#XC^srRo$#V z9?TU!U2J6nH)<5?I1IgS9*nGF3dzxn)`k3CD(0!67=lKR;dz|uBsIZvqN!x4L#8YZ zi$Dpe+}FZG-a>{#fz-&~?~bR3#<0z>WEom{!6D&F(_GZ;%;UKIV2W29lx35Ii6Xg1 z*TjLNoB8H-sYX(NUYGZ3Wa%>(3PXA00D?S(jCZ7%p3h^Asz)id9M*NkHjU0$93IS~ z8c~*c$$zmz){+x6d$ZeGCE}2v4s%i&j#Y8`KXIr!WxZlY7@r8yZ2@VC`(F2r%7G#+g_cY?7dgU=f@`22YkUbPE6(3;t!kjFd+ z)mA3LSbC(2)X4W8ht|PR(V9+bnHL*|J7S83<}#l7&3zERe3BxkI&eicECH=-PDLtJ zv+6o_Fce6gcI|^gc~l#C_kB039YvGEhV3rAjEgz3`Z8&+wud^}tL%L(RGZOJ1h<$U zpnD@3UINBLWM|kIsjr7^`7JP!GMX*DPDAWmnKYr<+x<7ocCJFAzsysMqA;%BuT4$( z59cq-*HQ|t@5uT{Cc2Pw02E<902};98O03#;>|cGj=5H|E_>$Kb6uN>c5X{475>C) z@V$YV=XUn6JI%LA)E>OnJ!a^@YinNa!%3lxNrWx)T{H7|Tl2%OrH4PT7yGa6G}T#A zlT?vAoXsBHCM`qR3r3Ytc;q0&eTO)C+<>PS=i*YbZ6s=0#Btvg3 z(d)0`P&{I73yB`!sN5C;nXK{2=yVYv2|xs6fr$R za`&6-+8~Vsj~jEi{7ggQg<^|#^)SexUiWDmAGo2OHeBhy=Y$z8h$Dxd;;t0?8D~l@ z$OFNrjzjnNq#}rZlrRhOtJ#xST~~y;zUdRGMW&c%2$Wj~BQAUOCrx}MIW>8tdD!`K z<+`J?#dCQEQ``jRcUh`Dq6bNQjpwblCBN_D*b~y~fWPzEcNF+;$DoC%6b zG$(K>Bdv3cKek7;tRq*qOKhIYAkDrwX%aueC=9U=2IUN7l+e@)fp4ImlCK{q6Fm4f zVhXcLpjytUTZnJ&5(~9(%U2*^9rE>MHragn2}rA#bBhtwmX>K0B{3L0z6KtfT6^38 zjd^~K@NCUTQ+m$#Z-fgG^n^I#fXqi)-Uc?gnu#8WKGwV1*$$h@{N%}E{IXJI@-^qFQJH&d;w%(qhLw>1V(NX{V3wOxS)a@x!49$JPY zv7y&tSqo)4Sm=uY4&ch9^*-SZfvcka6$xeie;}cPq7w45vj3HY{_w$nr3d_nuHheg zKqeN(|4$s0<43>uA2mPU0Gw-qYbmo25`&#w1w|7-Wg6y`0!YrOOxVmsbO#lL64NGoC zK>;D8UvIvUehmaBc?ly>M9_B;**;6Kr#^yt;={Lt!jqqHty>lpO2qTLU;%)vJP80I zC;`%3tk#@90|5}2^ylTDr&utRTwMrH0da^Kk%AozCOMOaj2Q5~S;z?b`)9-*|63pg z%2F+$?tVZ~^%ig-Fi}7*g$m>iR6Rs6Q6MpM44~-8S9K^n4RV?#S+4z&XW@uK zo*ZMhPykyH70CJ!!#%tmJ5N3IJ$`fxs9)e|2$%3+`Y zClDM23C@i2JX+sg4G;i|$@e&7_(1OMtpYs-5M*ON_s10u)L%+000o|&?i~YtJP39g zF^E8cuK5ExPHC%n46r@w%nO5itcU@aFDUBU33Uf zd3FP2l)g>ms=T`tXkF2#m?^|)(1G6gW)V_Rz!q+R;oi(3-y-%W`@nBDA)nG8viZ3& zW8(*m2eN^`3o!g0_iB)E)p(t&k#BR&Mb z4eSqm6>z%|2(Y8q{he8H`%oud5X<-7@||5>Qx_H=5|8waKk!{kNttKwmy`PkgMfkv z4vYW+0;46E|K*!|(wA<>_NKe>O<_Q9(*Jw(ufKx;@C!}1;EwIJErG7@ZNPDL)-LFm zju3hjIWx}AYv{Y0zC8oXxBrK)ZO?V=H}}uy$F$ShP%)DH$3wKs{h05 zIN-F2JdF>%)6C1Iz-Mzg=EpSMdCw(ccGb7_Vvo@6d)^<10Y_~FA~F!P_X2VK1q6ANwSXb%Zsp&$56ID{NT7YY1>;H9%Mbl(RV4*^Xmul5B2AZ8WcPQWwv6RW-u zgTU%T`cW(3j~}4HhV8AMs(v;e-V2*g0`PX<_T4o)0Nik|fiXVW3_}{jaeB>AzojUd zZSUc8oruZzLp(Xwrp(WeYWSi7gD5qmWyN`4uyWY#6 zOXw{XE$0r4XS+SG@4gk{ZeY_V$T4-0SJP6din$^@T#z>!Mitt^yQgSevCPEh*56yQ zymv=!YQ-+n%pHo&rA2Kt(izbjV-M%~ginn+&9^`59I&em(dD3-=~^}TIVa|oM&pd= zk@$}CzenvJ?Ph=1H8hO^SUZK1yB$UJOI1zU(o_fjl*^bwQOG$;cd{{=e_SkBB%MY& z-L1l4jlpYGnrM7$H7aquAl3r6?0*RaGLPE8LMwOP#J%o3PacM@+ zU2cl8@ZiBz=Nk0213c?>jTGNu^4Fgn+G+dLVpUFGASYij($Rx-LP=qS2A)qaV_UBO z7#27Ize6pwaCFasE8Jx+qpwId(+_xb9gG}l&4Qcn`B!J!I32kH6qCDUON9cp$6?cu z`w-?J9Si}{9qGe(s-#SoVQRH+^oOEc|C|0Ea{)`r8Od`Hk-SCWfm51Zl8uw0z;F`d zUZ+{ba-oeOh0XS8t(pCEy_QPLYuXSIMM^II0bq`Ap;Ww`TSDM8IxF4FgHC^9C;=*z z3Q-9+W_ITr0P^4`ZED1bwnMXjuwVM_@Tqv;S-STu`|GJibx=meHLrTH4~55hC}n&n zySc~Z?pGYH;wwidopz3>V7dPaO0p3KS?L}LrD~UboqFu?(K{!-uqU-LE%%Iv7iDMd z>?2*m;Hl5o+3XASx$7u+&y`QZWpu)6rzGr1@zK}ZYES4L65pyzvo=5dYaq4S1nk+Q z#Zu_+-x>~70F=Zoej9}#5026fetasq4sRe|P5P=j2s>GR6gd(8YDH+n=ZQdbV+rc2 zhAbBnK36(Tq$vo0x@nn_1JN+%Hs@zX9em6^&rHI}ejQyDyNuCavI%Gd=$eIRj88cy z^NaEUnVB;OhcqTUT`G5{txL5vNsvIxdU)s4XT9zX$PtFlpo;W(OMJV#4jJ5tPB6Q? z%w=<6U&96Xvpt3sJ1w~?+QOA_Chr?U$rz7~jlH2mO}&c>@;ij+@!`=Q^K_?|iVx~O zF0L=MgH^n~m^Gn>T{<;d?gJ@rvWI5X$Vquy&ao;~11@zIZ7IWn9UY$pA4=IqNBF;q z!oFq!(Y z#=mI6n$sCV1cbM}8PUw&&r^|?%Kom$C&&{}x}#|k(gR%KVjcuh{27!z?~R&>=x4u} zZGcAtKt$_S`;>bP!%QjIs&7eA(agRi%M6-d9tXl6K(zu-%02bc5;5{2lZ=8)%VP=9 zsWydNgeIaQs9ckQACT2t==n`fY~XOt74o1?C!+)>=ytj32$u^~mq5r4tE?=xmMBFF z#J_U1TzItDjmI4{f|AO2%GmBRVP^d$@^w)50SL+MpL|&UcLoB;3=~-MO5sHt*k!h3 z*W~7mdKHr^ytIHFo05)N#pj(DLr}VJ!%N-u*)GNf7HfHx(G{qo28D%P=vi~ZL_GBn zZ8KG~P?$7g%-eXi?MXPIK#lYmc-U-scQLK#>$$8e)N88DWiNO7*Y1b}L)Sc^L_h8O z)U4X%hWeWGY3}zFrSH9jNWlD*7#7`>R=| zaLnol&KPijdxvf6%ehmCWM=#f)utB=Sti}e#z|`V5tYF6sS35fDr5)bNzUHYz&g{< zq06#-M}&Wv-dXRZIi4O4-V6p4Ujn2=@@{?;m)rs2V(SI>zTp6}^X`digXu2Az|esE zs0}I}6(LezpB^dgx8<{?YBR<1Yy6JuV)GGqpDXq>RHr7h_c>}qQ-&d~z&Wg${{X+~ z3!^2x$=heIi6&U9sv68BGib7khK$wc7+|?!Cb%Fzf0i=ibh%4);yGSajcx-Z z+)NVG{98MjQ)z^VmI1hv`_XyM*uzW?bZ*yyFQ+7aXSeeG`F6c75CstW1vZ+k){*mW z3l=P{+E&h?gMRgyQrM9utVbAU=I!H7^aXzvJ%${vGmWy8sQXXAwj+Iz1O(JG;BQ|w)IUsE5spJ`HNWXl^kqvMiRM_i24A17l- zO*2A9eHnGag3%M|1RBh9t1v!pu-ZuWS559zk#f--b-XIdL5s?LY`Ym-Q~}9?((!4`W~UFDg11}oDF_@DVHo_$_pU!5YPu4R+a+As!tKKZ*|5hbT2 za19Bh$NO0KrbG$9zwYp^CJ#3%Q;qXOH7fWeyzYp!qtDW(hPCZn#caaXhOA_GF?=n6 zrzfFxJir>9-wF4GuB%#!PT{{8Kz`Rt#W%VUe{ z>3VwTK{TUYUso7?jNAZC2^`u(+3r4zKs9 zXL0f|Cj<}#@5Aqwf$vFc))*(7Q)z*K2@d#P+Gx1kI=LL-fP~#;j@VRwrk$CHqw#C# zO7=nYHWTRp>(7=`Ee$cbY)tyN_B8s>X1dUd)GTbB!z+rIfk#}pQKv<|mtsT^6bCvW zXy1EFauMckM-6;`L1$?~hX-<9_^x&2!V$mBu&fciWT-enW!CyYYzQ68aAJ%8b10{% z+HW%ziLX%w-r^x6_eSFgG@-w%JES@4(Y@y4+-0d3w+J;$FAou3m`x!(i%iNu2>4BM~{l_uEs zn+XCFVgvaNO|q?j4dfWPs3KL0z~EMxnI;6OJEmXsHE!ulYdVy2d?CI8qhNl;hg=*0 zJ(=hE{x#AB1JP{PdW;`oLzOdMK*8sFsSLK;fq5&Kb^g5#-+f-8e zuFyI5Hj)(h`K8UqT$FhvDH=dZKOP1x&o|dF(v-95v68nEXDqv35JvaR1vdK_@7l)3JrEcboJZT*X7U zBb6H_OC2U;<0P5>yMfcZTD)_)%7mC=s@cr^(Ii3NGfy*lGvHu0L|RWjxhx4l7(02mQMy z(`CtuB*Bo|4)$;cw6s4OxR^QcROXy59hAu0cnV@JDEWLCivlmZH_0mPh9dICF-cAc z9Q=8jN(h+}9JUk8P!=T?@iaGPX7HYJO#KsTof6U~Y}fb2p6jG)J0)usQ}*`rf#)I8 z=^_V-q98Nwdcvs*birCZMB>%pUQz5y(x3{$K!&iyUN9J4!kc0D=47tVDPK}{>23{q zGxl=pH0%jmw^)w^*-NCg4v;9H!E$-Y?qcRMaMpDYYVA8oAHN?c(qQPMR5c#N<0W3& zgBd=#vFO;4hGL?5Sf$H@`Gt17zGafJk^~BZf&reaZx`+8QX4(ivhISzO$CFP)M`RK ztpNLpjw^0VFI7AJdToE-m*MSiOPO4$2r=Y+2{r%^t;{-F8J({@*M&L&<|-LeUvKz_ zHwgB0Pa`?A6UTYtJcYD3@eja4I`zL^WnL+dYun0Q-zSeaADDY~#+-D2*^JBit5rX8 z#kHUnAa)rn+AF>^6Rg?9j}6BKH^!2P!j;}$=Xm9>*spcQ<>_d+ku*E>(KPQbC>L6H z2MsZ`?iyF}a-^S)i`iv5pJqb+6b!7zbPtW!S#lXN;*fO?bsuO|Bk|_BpWPM+9^Kp} zddo|xL;9nvFEBe5|B$@7kp$ld|KWK^xc|E|0A%3TpnSI5(KAjt5 zL=!PU85Aiti*~PapD5>(z_}ZkImz83a;{J zRE&DEap<^~-k$~LQjAFvWH6_)PW;7gg48wtIjH!Bn2x6t_v-e(qjl%ec)&MgR?r&l zxjdIHg{Z#%GagoZHBtD*BradTyrqy_M-3(%gt940&M!6+9>`OSn zte)vs^Rf!Vcj9p6w^*{^)%NBUtU42#4}7#(naUJ-3=dcYB$mgtou6{yw0ZH;dR5E^ z2<)4WZ4{cm!ZO|r8R0D%AMWV%OkLUxZa6=E^Saz_maW_`RtfQvhw$Z(7b~PxZ))Si zdrnn7l>&2|5A>c|8_8ng z@%K~|Vfs+Y`7@+b5GPx^Zj?XrVRIZ^m$IUW6U-qP0mB=GIkL*uGHRZ(6?IJGjaq?_ zA1K*PgI=T6iKA7V4|Vn%U~R{+n`5PkAq(0yw#VH#qvtKTf1NDTblxo{Zka3pEs^vH zQ(+0r-8(YY18W~B?sxE!z+F3kqWEK~DVb*Ah{RMz7TE~@7r5I|%9d_6%9u$86)q}G zFLA8^twHW)zm8Yaf1{@T@Om6o5fG`~rNzGTID|u)_wD z7$biFCiF>s094W)RMh_0Ru=ScVFbHvL`>cx1Zo8;Yr3|z_!%BA>89oPkhZEym4*s# zz!#RaV=4J)qYpy>D(*ZA@p+RdPK8DBO9 z2?gO}=38I`F8HM+iY32?)h=V-$S8dQvP}jvX~+hL-x4XypFTI1K2#W3gUT^V$7Tj_ zjO&uFDzfijY6~Na#%bla4J+Wcr0X^kMhjbco+76bcb>{uLC90mZ!W|khX&F^-;cOh zyeQ*8+3>yC^>2plSy=mb%Q_B2DAm(f=Sb+B-IlG7L+Nd{jmL11Ws7{qCuw`5Pc0mD zpiO35T(M#HopAbaL%F<4{1KdR$l!Gf(!Y;S&))IKq4+^qzE>$y-T1DC zmF$8G&h)FVt81Z}5U9Q?#v!YZ3O4UZn~~G_TekzrMEuSIW7J6=#i|%q73fgd-jXga zT8)EcgcgXPEMPIR<{P7i8spDZrDi-zhWge#-CXx0DskN38MC^lrSBBZW2k1;hy6nH^%!i-Uo2RHBg6Mv#j$qsns&lGl3lZ=U+0!uP4RVoJtv(#5*|YHm%)wDj_kvP?a+I#4?T59u;Ce={n`i!iRR|0^5RB@#AoOr zmZt|fXb(;~2+(|WE?qmBk2c$Nc;gPngTZ%YZR7ODV2ehfL*x;JR8v7$Z=%Nv=_93cT*?ZRkdvo>J&g=_U&G8Z%II7Z6WWJlF*u_Jjl8501<2^lw!~op9vg%|^ zb#uO+ZI^Q_pSyz0aSwcU-utaLZauxx0yDUdhhZVN0)Tm)GIYl4Q<%zL?Iy=0hCVQ@ zGb#0!sne4oJf8;RPL-?TagJT&vEtZi|6>|a)qm}jo`2^nU-Rj_xtha;9{Lq5Os?V) z&a&-tIu>CL3j7+GIFs^L216w%)~=??I4r;9zgpT+w6S+qLv^SbvcGwwgG&w^DBeoU zk=5HUOr@*5^t%?;J>h*giI@}>I{nbAItm?Hfcc`GSPnm}kGvVtv}v!QGe+5lL7)*V za(vA8!a*j02$Dz-8nMzBIDmV;D?v*;2&vTv(!(|5W;eG#dX?yJRy3Od?E2}%VFb)_ zD!aP=fGL=(mj|m}3XU6bOZv6j`MQ>nO{*uKb>C414W0dOax?K zvzElr?gsrDTFiYoh{N0_>E7<#fz#f|YeG){+xAw|qq1GmhKC)AS0__MEt%0bb=ny* zPL3!U>}{_a=J0}p*07c2xX^~VpyZb6)KzoO-5*+sx)*nL;pC)^$M{+A63ZDV<6o8h zQ&h*aJ+YC55k1Reu+xweGhm*{%>ux|h)Q?RaO$SOnL~mTy<_T0G0| zMu}o87?lDa$vvNeD(|L(9l#ywhWVF-hu5l@oXI#HX}(7JL0b{pF%3y_YgF|~7usyI z+1b}S={ngcgprdJ*#-EH;fWq)6KYesJKK&7szlN>W=gNqpdFjuo!T8OxKfGfKEulZ zXt;zA^7PCG#Zq>pc!L!63-L2dgbqGbRAA~gP{rWV-~+sz99Z4he!S638;WSw3(@ma zHkkQK(X)S8BrcaY#|iAA&b`FmojPb3Co^X`sD%>68<2DuF%e;}D7_M8*OVIWLz+^r zdRZC=9k13cK*OTxMT;?jEc8mIEK@B)@6rdnI&v7SZixl5*TZ6*GV(W|Ph1J*4k<3i zrrjJDUNI2oj1{esJxV1KYXcJ=G`W=`i)|t}R~>%sGF75~XnR!?8<8KMax!(xrLsTW z?w3p1FzpI68fZQMMRu}0gpYel$^3W2b2IW)3BFCEZmAde#C16Ll zu4*sv!1`zN1D-J0J7Rudv;NUaFnl&PL;t!VZNNbMfENO3xBpakArg>+Q2@5 zI7%hj3xwgBEQLM}gpTvH^z}%+=hBe#r+(tB1+%M7mykH$Ir`w}1Bz|B3{v3mM3Z0> z3EJqz&v7EBi2Eu*rs+JAuHadEgT*czpXGY}^DIyBKEwV?p=Lm8X@e7WJ z=G5+5*Hy>ux8w8^_0J;59_z#ClOYv}lg(N#mDbGEd?`aYJU<6FLkJ)#;NGVwRCI33LFzv8s)|Bhw;-^BXDszQ=NLjRT1 za{Nn9OUv}%cib2m8U8-Ie`o0?!FVF49Hw9@4pzJV^pwqJ}pb(T- zRnY(e0KK;Q3-D>1n(9!@;oYTRrD)&>*oE{N+>|a|odjfI9?h0xh%xQrTe)V5VrGU7h&*X|5AoSG~SN=!4b+ zx`~PearlM;7vd5?P+))n{|$^~LkMlh?j`W_gTsLdCgA-_3Q(N@3v)s_+_iUf+y~?2 zaO_81LbA#PV5gV^yMft*5o{5n0qh0^{Gd&>G6qEDk z=nzuqVtBk5i({bqG%qO=Sx_(dS*#$C2p~|;-`4chxo_>zUK zdnew3#Rqf-#{j-*9f1b;e*Zc#_7J0&;+Wh%_)iS=$eoOqx+1Ud?msb9CMJ7VKXUXO z2)_t91c+TwC`h1x*KpfEvJW|6pRnI8s?Z=`6&$<#m`Mhzw;epbe>RO2s)^iOao$uf7sG5+R+VU3~EW6^I?4$02eJ|;h zHUKT+8kT{I1lW8toZV<_ZW+J_2{i6b&+5rd>!2XK>NR&X0dH*aQct`7Mp1z{cdiKT zU+jIyVmoL*TygIi7&h-$xb7kO0R0dkV!^L*39m^6{K#*%wlxJeeUb5c2VetT;@tc{0q`z-g>?}DVmA1R@DX|szI%jq0b)je zx4EDJItZcMAU*ERYG1$G+!0_PhY&vpGqSzi68~mYe^@h6ka&|=0wL;mz`3yeCyK~YP_g;>cBPQC*$W4e52s9QXpQcGSV{RnQ6(u2 zpL8tHsL=22b7tc%k(le?-Mhe%v8M4;#&)xP6!F`K7ajGV(HI2r>WP8;-2jd2xMk~pg z>%};Qk6d6+dN~=!XBA0RW4+47KhkS47ztzhE43m_uG@X45*;*pFN)qEY4*?2hl%6yXE_4BN;R_~R$q&?F09a!l0WkU)kR@&X3T$Na=-HuWx>QW2rIEU@UcHet14h@Izmc z1Co^*R*1;gYzV>YNJ4S;OchM&)U|YqqlZr>XyFe^)6V}+-CSejI+o|6 ziGTF>v%F3&Nb>6``cFy4>60abBjub%X^ou*()^MX17ic!Gh^`U3H(r(@Cp+!Ky69z zv@ovDofPxOo1H7@x3QkFCq3}NhSei8?F}@(gB;LSHO-Sa`%uym$>bjaZhTgOhVGk= z8{ieJylB#9%ZCqt%Tdeb|NVL2+LXhYAm;`0b|x*lE+E32-MrOIu!%$J8xb5v`uci^O%a4{5=} zVmij?We7`<%{r%eNh=8CSq$)b6^+<--oNP-_DLo5B>`2BI}4<+b;KO_g?h++Vh0Bv zUTeJ}hH#?V1&|$xSuh+q)i+lLWDos~y7#h7vIcrDe_e|k|7%pWv;;$QbMcbm|8obb9aqxnbjIgyeL3@O# z@98tGyk;uSu@NYbJq59dI%B(ht*2A-n#r9xid&cenYS&U8ybqL6$(+*l0*QZZ&gqh zgo2QOX}k{uCxroK28(n2=XM0T(EF!g$=E}g&|7k8G;iD1z%PG^c`zlP;@WxJe{Tq5 z6Wo;ECdGN)2E*f5&dQWE<6Ie}({62H^HOz!e)w^PM#@yLU8qe$Y$Pw!AFkKGGTW-D z++kZz?AuQ!=?;a;mFSEF=6qvxDJSB?g5yQ5e2Ht`j0$&0+{yV@!}K~fQkDv+L7J`e z^z6`hEKD@$+PyLxDFL4^#Sj%?hljO`-v6u*m$+CRUOvzpwY2l;ZL>?@FO}CAt!=RH z9`8j~MY-1l;R0hqc9qH;e8tFoX_9KYD-v_e9{A{xnS@N<^mALz+&mkP%tw>{5>GZ? z7wi-|c^8CWRiR)b`}pJ3hOs=b=}FyIN}J1piKfDvn$jUji$DYJk--9&Z;W^A^KecEM>`e}Ly{Vwe)OL;!Oj(r%AU*0g!2 z_FHCyM=;0ov*hlnfQ`NY6U`- zIT4|ESJPJiwro1}MII;gXzI}-CN^Y15XrwN6PRxVj6E<%-KYXnexgnH(>ek>h;{LQO4IcVXe9pEp#OSdsl zs!2`zG*5Tm%TQgGWP>-B`3c<=d202dS94OqzT)w0smT?Pk_tGQSfj&@!xT)GF7qx` z1qlw-)L*3jUJ)Qb#Uyh`qs9DG*Xn9nTlC?4IJU+z;D#Gsi75yMop76(&c-Ty;j7JM z#T(~mg^n;2JQX-v=XAA%(N8NX6tZtAWR^W>T{2yNBem(EAp}z?s))bt-XT!7h)>}@ zthE3Xgy7Fsl0<%)(;!OwxAcq45`9nCt$~Eq<2;u{`58a=Kx}SbE>@Sv89L-ho$I%4 zkJ0*p+mAXFXFKV=bmBl{K^7MmvXs*hav7Db8*?|BYQRI#koJU=s&ulTt!GFLPvhJq zR8rpi2h^|k*7M@)kOt12Z|3*fvpx)XgqlfDlR}%(AYXm8 z_e$~jr{gTzHOPlN8%_&naCM<5)?H#Lj1SJZr+O!e6Ej&-cXZ3u^Bs=h%CQywLf+wv zJy19A0bCYUndBViLV_~H?(q;6RMq7Z{0TX-*n*$qlU`wZjrgh=*3~e9stpu6qS|?m ziqCL-3{Hj?d3&`;H~83(kCIH5CU6*D1)2VJ2;hNKwF{I(Jj}@am+s!`1lcf}C);z2 z${jJ~XcI-tAseI3BIOUD^tu?mib!2E9t#?;k6A?V4s4yKS-3R-w$qB326h1dbm=vw za?FX`9Hb9g^b+CQVF%kj8JIqaL^jKPnhLDk=^gXYZWo4upA;51CQMT(Qp z#p9*c#q`sliQmDkWaxr^A_Y8Ih~lQ)z8%!pBq5u-^PXHXR$^p3H-2r#KFq3wHYqEk z24yyZa$4;?7GHC$NHPN$!#j9bnCyv8>64Uidw!-P6k!P^vQ#Or0*;>D()N=19G93s zB>b54h!-79$Ne1hea|&a(|zY|HM>GK%xLwY&m~UK99OIeoBY52C?yne`rwurT$Cd! zIldplRn#VjfyeGGFW(80e!X!9CWHl5yVIt7b5+4m&la*>#7?5suJc{U}RxP-9~|fM-eF0_$7kI|k5jv?QV=P>rk6X2AJ| zVFwoA&OYXI9Wv~?E%4c`k!eRI!6*|)VM&sl-OSo`#3pn1ZbXkJQ4NbjifS5m=I38h zNh_2wBV4qCRo2V&VzVg|W5z`xmGKUj@JXMGcZQhRx@pOWEb$X)^N@e@W}F+dnq0|m zfu4K9KFIyh)ACD_rcN*1B;V%D+jov8NRHpDsk{HI*dx}=+WMv|mKmAZClOFSrm4$p z?;+pgrJdG2>tfFV%%?6f=A=(L` zvmJ&Xxyw`ewtO$dn}8#%Jy3wFU5yf|KMa=%wR>G#Es&85ZHNG~#3X%_M$RUdF;YWo zBoeZ~4xAV&D9L-fybn0q&34C*-uAvscLxvvRtvw^C4m1z5HoaKMFxMY(+v z3b}d0a0g6MTUrKxgJa6_V$(|~V;?s@m|TMZj^4OzPDJi<&1^^eG;<9nExR19*RC`N z7)Eg*8#!_>4@jz|0z%4ke!o8n6eLN-Y(%EYbuga&(|IVDr6ymO`P2Zn_zng}iyEyC zSjHS--UY4M=vC7l^UYfZ3J6)roZt+=_aP+oR6~-k?a*snxdHx9*}$bek&K(JyM!GC zsXJdH@6G10eDeNebr$sKi(S}JGNcUOOc|^}EK2rixuqvpF0;$%Ca`l9mVemXBL4EP zK8sB;;u$m<-UrI~3Nr=WR&L2dGpZ8M1)pX_2Wo2Oe1~Q`NKg?K%<&~p-MvefjP{sC z-I7lPiAFl+To&UZ%(mK-Z9$&8NYMkLr@xi%&kwB};R-?5sQm30 zEZT#pI0@;G(rC~khh-k9elxuh*UINw5#d{jw?|{HU7LSp=e8la4kJ(mql-tY*}c=7 zjElt`!3-yKA@ICS%Sr(Eg~7tVxoK(c_^8PjGce-2QMw>TIGYEC4!xMmS9>^-2DHS- z>T&owujE=yuSwsn7Z%<+-WWVNfd*A~|38K&d`G3}Mz`lEm+y!f5p6lyeXa!j z09oIX^2R?+G8>%V=jm*8rc93i2H$c&N}=>}t2Lkc6)Z4$%zZ5N9$_`T1!Qvu%V-`< ztV~lJLWCBM6Jn^8p_l^;B?pF~m}HUN?1{AlD;}N_#zyOxAs@YeMJQzJj~}E~ErzV1 zUM=`@NgLyd%UQ8`sl|JDH%DVT^gQ}(689~W`tS3Zsl$^~mp6*Jz@+(9`JSc3G3!6f z-c$$_V5))>QQd@_eo}g#T;Ri*L{6P1_RQUiXhc^oR}io4QOS>^P>IOO`cRRWHazb1*oPA_Uzh8j{Z!T;P+#vvOC%1;+`(lN z^G8DAuotFADy6RIbovj`z%O`$;dQQQYW|kpr!az!U*iYQtvnb%y07`Y zh{v|X({r#^dFrW@*OT(aUmtqWi}Z`AJKLRp?Oyp*VLrfZgr(PJFOCZ%W^AhMr+Hd6 z=yB;x$-?c_p-_!`KbP*0UZnLHNxt8T^f9=8;Hf&lTV#D_*X9;j13b9`_n z2yD3_tYDM{z!1M+7_P5WxN6pu`Myl|V5)*PXp^mRhIF2lrICS87n-A(Z>2=CsOjK(^yEx- z?!*>sDSpvIhF1rm1EhAIhxF`z$*YEIi}vL9un0YBm-Mp@w5@V8^s~+DI(~H)($m5C z6uHV3Ef4aqrOrr9$T2P+7PpeZ@E7N zvnoujZzhRxfj8{ePxbYzh_9nQ5l0GAun)&WyzQd>8&7t6*gjCrJp*bPZwRexW`5nY zC&wB|+t1ex={F!6S=i%$(;;3=gCc#pBvwLcG&!JmB=xz@iTBS}ux?;POeDFE^GIpY z(f6zSpNCWyvYgT*bL!vg=aG}TR6mW1hU?~)LY<02ovrxTn?%l;*<$&)x%Q0yWop=y z=(!&zn5_R@gc*vdLFJ4?az`qk>;8VVKL1d?!edJ?+jZI4m>eM@BxSM_GlkZcdSxha zy^4g+dg8rcZJ7l^q1J0g%L=NP9BHP0O-H26OT;YC;~nxaJ_eT6az>!Q-ac`wi2{bn zl5kwVTYyo-f7q-|xK#PI#i>|cZDfpFHuPeZ)Z1V;%CM?wJM(vvZ~5(%>D|-#Nk`q@ zj-!@JdxHq`LMWsrg=&5kGYU=Z%Cz<{7CiNGCscf!nTW}SWEX2W88FPL+`MF?RJT26 z?sb0!HWwvg?(6*A=9n@|Nu`qKEIvDDlg`ORzL*Y0ysdzkcK6+M?;8LNzBC+%v64|C zrik0_pf$|4<)Ttv93B&7!zX!rt($%?ehs_!D}ZUGGG60$cPXPXDjov;2G~Y=36^nE zJz;$i=#J(CEO|rKN4#YjbO?HIOjyx?eCzJt$}Rs?iH_sjDW9Z8K0E60P*&H5aO-g2 zTWamQXmE-W5fx-(qME-H5QjzOvssDbuie1gnUpqLYwBP9CH7VW;Ef{nT#q7QlHsO0 z+%SnDc^1kqJ`SMf2q4}&C}3=9X9J5_g8Dc`?wa7dRsvgww!S{8^-L}VU#YYn&&9ST zAHK6Q!YaU2HnLL9>a4Hb9$2bKWtMS5jWsFwh#uknJE^=~aJF^~D=jRY;;K1lOn*Fx z^wL=xizn%7D4&|`ME>R1nG#5wDcTi5AO|gDm#;s(kcd-v$m9UMCaXolY2SR-+9CyZ zm6|zrH_19uU8X{RdLIwnyg=S!hI2eAdxOk=`-7334J!`E@Sm-!mg5); z%V(;&NGfBQFJ&7Y8JvjuphKyIa49cREq+jJ7&<|@xnG%89-@evfUe`4Ml&lmx)5pr|*pi1!RPyc(8EtL^AwXr0=qrb^yk+y?S>U zv;{|Q4u8(QT|+W{KdNAQ65bbX<8PdY^2tBQL>sx;5d9lpVC|9}xnnRDno1xjs5d;? z%r6$11%hk6%*ZKZh47lNnui#Tfhq4e9)?$xl5dmkKIW^lYHDB~{M|oU37~n(5Hbvu z?R)I76fDnqmP#_i${?O{T4x(2Bj1DHN&#?mI!#)9-!;-(uCK*t#{`>9b*c%x5G^D_;DT;rgdxiwmgT`MXSNlXVIg~zG6R!k0c1)=Rq~WJx4%rqytU#n zim4r&qQG4p6bA%lB#SPrp3V+{1NaebY_1zh?}{Uo9w(q1>XpQ=GsG(AR{fB3`ro1l1QTag?|!uVRC1+6&y>OOYWi> z`>oBch{1KatVd^+0_c*`6=_0#Cu6+PzqK!G?8OGt9Y?JajOP<}<5E#gJM#Kyh17y5 zl#T>jbYUsQnqucd)7%o5(uA?{NE^nl3CD{&TD7JwTc_iI2_ps9<1@WuMry~5=k^Q- z4m!5c{=)Kwhgu1bjMJctPw`pDNedaJ_AO=rbwTU_+Joj4;40lX!u{3}tH5L#naquz zhm)wOOjq=18o(&qSbH9SbCd>eoCK=(SVp(bx{TbQ5B8d@aAurmnO><3WMZ^R%O@z;M%ayUc%KS4WrKEecH!%^i{A&3-ZvopFwtw zAgDC|VKVS#eo|Z`PMC5?XgvuGw#Fxu3_-)wWEQF;vfDzBZM3<37;qMw^ipCR>d&m| zH=&r{EN(|luMSBI9k3bne(od>!ugx zyaL4)!=&0^^#Ef+eG2N>C?N!bqI}3h0DF7;ItP3E{P{VH4Ix|s-wK5@CxL3)XN1~a zUk>rM0GeESE(_?>h#V*o7yL!#RN*5%CuHeOwBea~A7Sm$P=RTK0^^v`WWfw*{v*@J5ZY6H@T05_r}0$NTJ-0Dq_ z`*PL-d|$%?jQ&cqw|3@yN$SCWFs%(tKpp-z19)x(+5oaWM-%v^S2AHQLXQL00%-m0 zneUx~xrepf*4DZ<)_OU-HvEP5tNaJnyAQg%bGuooeU+7GYi;`+?fb|0hj>aV#iVyx z5rLc>0pmRQUCev_xtgFNrP;ILhjpz*Ka_m+#jbA{&)Vhz9Ky=g%muf$D}q~G;N30- z9re7&xtV~%FC;K9P|gn;;4h$GXXWMUk9f`170mkr#HY|#K<~~9<~~fVJ0ReFOABDv zXYPBuhMOONyqarl&y6qEx0WC%5a9B&s=OcR=rUg9`^_c2W$cvR{lu-#RTqFL4*e!D z5XblH=Y#RRAiWjD>fFc9weNI_j*g0yq+<9R{ov0k2`Qm2fS#%?8~`;rJUGBB_}Hs1 z-sf*HpC9%W{guDz9PQZ`{RJNrwU-USuU8L4H~obk2hVpQVDBc$0Oa!pvOE@@E)W3b zr?{ID96n@e0{!;K9q=3G?dRYNU*p?u@n&L|{ub%tS zgjSh=egg1YPmOn0uc8vDzS-6FU9SRYao>cOq_;Wxr*UpuW_cUhxXKp3ss1BE=qJ5j z%0tYPK^%AA^k>8bSl=6S^=DNVZTj~H2-<&Us^FK&P4RxeAvWn%MY!Nci%AGU*WWw0 z+>3f=dPfff--Y&Cledap$yo%eZSW_YO+n~|=JEA|9YlSK3A?`sTrK*R|DwEm09tka zi352ByiEQP=g|gm!TvyB{*eMa+y$)N_z8L4zkbEf2k_fE+u4U!SnK-<-J~B*$++LS zk63y;@&Muvu+IHi2Krh47RmQrq)+1DZtwUKyHAn)R`T+{vwKNdt`p)V{4wz9yZpYf zrZ@TU)BdUdQM0Ss)X|#`{vP{I8UB&_eh3Ek@BE`$3f+J}oyQOoTpOJcgH)JZxnV@4 z|8Cls4U9Goy!w{>8c~LL4tX)H*7}8#s%x;3=6G5-Y_m0=hN+jYVyKLU`;>jSj zn7L{zmW5A#`lH}QaaR_D6BMbUt&vfu=o%*iag7%H#&*O)AmnSSzYM@@;toj;or6**1e zE5@)*(hGKl^T5{3OSQa-bBim?A`CWcbkFx7Qo8dlX;VsxB=domUgJ9F#S)n=Z&Jui zLeF%_aN}UIykR90tmSdhGm^#&)b^+ZsQ*;r!=WYqf?D%-QoC&F_F{c1-y!cw+fLxn z^H)o(##QaqVU06Ch6YN;&kI~U2YU$@sM+ClgRP?)-2Kv^D^}>+jcNJTy>?WiMz%~Y zYI*@_9AC#AuBnSONhIg10*M=Ru?S4LYfwkyQFzbaSr38!49l6)NepO<;%JX?-*fJd zOUS)9_QD6L|P3LI_nLT_tAs=!5h8#vxmi#P37&XHsJ+pauO15-6 zNLE#26y<>FYDfJil$;ECoAC~IY14EzWP%kjIJJ~KqjXsXS1xQ=r2f6~%x89eZWkhe z1a=;s4vuH8j@bQ=1E}|N`Cmxp?FZ|>)dRtD(XY5BUKQe184d$f+je`mREP(%!0PL) z7Im&%;1mbk@SSDu3A%qlv3C8b=HV3vwVs`w8YtV89g$1NGa3FpiMHX_`r0IeFewhL z{<{bv(7G}ZBOb7ZnwdR-Wg9HXvf3|q97B;0s)JfKS}>~NkCM`-FkG(d(mb_^Rm2HY z_@~<6d3JXsB)wZDRs^|>dxLqylbM#3LnzZ7X`ibIpm7 zPsr2Eog5v^W`H+KlPLsvSb8fo?S*E$Q};yPeWSs*x=$#HF6YUM4Bte>n#s8=Iy4joP5KUyV@>&4)bDVO-eE%~gLh~0kC%%B!B6qO4QrL-M zaCJzK;zeg{Wj`x1uTc9MT^Z`{4JlY81?hVzo-AuL<<_I7E~vAn=E%oa$GPgValdnc zZ2o}7?5X_Y6aXYs-Tde#wk+2M$^=)=sMQeSzBHPvxSu4e8GYPLxu>G3&mjx_LWoPT z;$ye%V|kdFzn#&Mm0_2NBqfMyr0@WLwJ%oA+OdGucBqQ=@Ym^=GrZ^`-{WU|=Yl|n zU6m!xQo0IHbEymKZ*#eD%tFN9n4KWWHII6i1eCuRwV;b8F_?)ch&4aXuF^wsize~_ zcWp(y-MBq?5cwBXZ)}YJZr&W9$V(s#>&;;0t)3~0_1S-;+G+%6PDByn6ssVEf3oEo zM5{3#kGtT`w6#HFC-PH55Ge!Q8|ipgaZ}ryLlU%wn3spI}?9Wl{<}$)c38|_bG@A<#)JNThoXo!W z5XxEz+-cLcj$P%V574=sF{gn9pmZQbX(ddaarYzxknuJp%e2Gtn=Wv~@-%n$WLdz{ zXCB^bdh0_a7Dwk8Fc}O!yVD;JFxB=0D8hjUUHg9GN-VE${ZJ?7Ke{-wrc0>9fTux zDm^`z<=`{c`-f6+L?^YVEN+G8Hxc}E*BNu;m0S>r9u&}#SuOx#L zpc?S|TG!VB-zMoTI<7uR9Ag}ZV>ghub|f z+M(3!)Iy2(DYvmAL@1%x^z-PS;h+#6b|`WNAZZu$iPV-iRY zw@;SlTnSkvf%~YON2M(B(HGOTTNM{cbkk@m zhBhEgyb^kvGi>63gv`IeLmcz3NQe%ybIGuUX+FU^Lm$?EL>p-l+Hper3qlQ;9eT%K zyHT)8FWp|CejM*4m3RLewiO>unLKpp%lBx|!8r14vZ?&zk95tN#95O?>Qjs9fNnA6 zsOeG6paqzVIz(PhfJDU2bQTwk+Q@evufyd2O9?JxQJcz37^fFK9;N&nFax>{J^2 z+}`9x|0)m-(}HlhCSZuen_IaO^Xrp&Wc9mBP%^YmNU46gDHgd5!?8rh$^poKWHO71 zpnJr*4;`GWchN zW;~+5#tkOi_=d4GQL3n(_mo4rEVs1vGEytSst#`@jjPcARRmg=;oWM`nsjTMRRq*8 z^Y`vlk?DA^{UgZbLND0k?3Oit#8`^pT+f4@tX2rvf*QG7Ue4aZS-S#y5)ubpV@F5KPR;U8MoGx^etq}QGE=wy0YgP3SFsRn!?SkH%j46OE_Z``K`;~J^_ zniE)}r5m5T=&}CuQ4~BKzM)JR${?3%{qd1mc9yVyEX&Xs11g$Ip|kMj?1g&nsBz3U zj~y@X(H3mrlg?`LZT8$8-TG78R5CohI>J`*90(uRU3zXjGr#HUNfxA@>6co;-kh&>!bJjL9xhLC<=GTGbr47 z#k3+wYaVp+gn2|ew>A^`7@?k4X&{*)Cw(T%n_Pk93KR=}c}h8KUo`WLl>~Kb zDz~zfM=Lcjx}fXY6khh>;^AjTUbz3vdzzzY#uuax4KVc<9mjtTHQ2w^IzA|Er+So+ zL)?L-vL(A)4;6S2%b(GVkCm*_y}7L&4#W8(Em=?8R`f&b1%d)oSt@t*@u$-R^z9B*YMxY8DQBReFH%ytXCBh1 zII3dv-q4^+man!CfTncwnc&4ZFQoyMUcLdnjf^iWXeXI|YL`w1iLeog`2Z+tOywR6 zU-ah%M9C%Opq*A=siqoYNgBE_D2s+UQIcsKMadBm!rHi$oi68*^s4oU$)(^Q&MtaW ziJ*9EOm`k=F5|L&QOEtU^X}^4?HNbBa{@qC9xQC_Hp8eIU}I8t&Slyve` zC1rB15<_{>Ac}`3h9WBz&2lG_&T8L?n)aFzJv4UjF^Oqg^4lgU0gQgikZ zCu`soAn9{u!JPHY>@aVRL$YDx*gUUmG`KFJcMx_+H3ld$SU?RpXeEv(4#hr3I_cyw3>m|ghlGu z@jxF~FND;Qj$e!e{$BH8<`F9TEyn-iNqHj*9<--qv7-n7tr&%9e9w$-O>EO{{TAE@awtw!_|zHvV)w4JVDdCM?`Xq|F&6(3JyCOC0_8rQw;x>8hRZ?|S1baQ4m zZ)x0xjN09@jAGtoF`ynDa%7b9pA5#-?b-=cuA-Jr=@9cZzXqJ^;K+G~3bBEfe>ZPd ze?O);-S3Y6>1W{Q#n@@FuE90<@O#XH!*bN^&Bj>TxJb3c&~SM0%Ol;9BBOM(z4B5& zl@-re^o%vO$xdgDNYg=|6q@X>yiW+a% zl{KQ)7LfK(-vqKE@~gD5=CEg3Cn&We?UxDCJmYX!i>)f!J98#coYcobXfXFSyVk&+ z>#m)*y)rp?u!I@yhBwL4eSJtW@VU&T14%T1_<+XJ01o+hk7}m%28^`ct>xFdoi=O@ z!vhwaF};`>SLqM|7Ln{TTk+9hx@D7r=7Vm@B6E&l1^zfCe|7z=6}? z9o0()$ySj0@^gpFt_$Oz!D?sWZ$V~Xfz?gw;Z?wbj>x)t`l7s;0QcyyaDvhKaY=yd zPi@%^?umaQl*drqnWgMpvHF~{>l~8u8q7Rpx3afzQ1?>e3db;&V@LEe<$Q7xC1@>P zNz6Z;j|K!hI{VK=e+AWxU=T+447|j22<^X!C~SOt`|GB1mv~Io#4@$?#o0Pw;^>pX z=tXjgF%CfGOq?#>aLnabb$pH_PFId2+kr(~@5v=iiU1x*9XV|sTLh6)?*wmB4e@!x zw7g_s@pqa@_UCvnzJ51oFU^x>x|bbXSgO%B9$d=xz3d)mm$ovw@lzP644|MS5Q`Q~b*g?~o6B7?7Bu~0LnPkb1 zKiQx4R(24bZSV9Kje;8oo2ly7#U> zS8pU4n<}oXtr@Emhep_jAruG07P@K)60t_pv^?;K)X8(UeXW%UXc6Zbe?7E6!YK|s zRHEpDpx@5s^bQiU4A%oj_8;m?{&kekn2T$^>rmr7^)E$UxmKFXsgty?b&DOUBYy+%Yj;<3$ap3%-1Z-J}^d!2I>{INw^{RiE4i(*4{%ld<4g z@t53k!|Tjio23R`DHeUsR^aLJ&Fv`mr)ckxF73Eg&lvpO!!UFIusXn0tvo&zNVc#@iIx8g*V{0A~CjTq>}vV zi4nuM_+{-CkdSMonD81{22r9D75!W~?*YaTgb`APs*`F?7f%!;CF@82=txpnoUc|=X99TFI#z^LnxW~xq;%xx;f zVwNS9$LB(xksj%G5Ph(6aN;Gc8@|yyf~6 z3zO~DAgf$7%0)uq+Ig6;x2L}?#Uk2NYIf#B4-*bIT<=(9J)|y!&vSrQ9@S|?!X>T) zFB?jmnl8_AUO5bni+MJY) z+IeveL=8AN^({4&ACX)UKXaK?LY8PkP?Vr-qqsv61(--WRBP~@ljH<7F-US+9z!db z0^A^}Z;QMJ6wHL&W`&iTuzZ~XYsB{ee(T4cL@i#PSN6;(5x=EtPP8Cb5wVpF7t1ij zhwPKn9mN`DD76Q3;k@5kHc^~WA6O!RP!mh- zN5t}^i+TlRe}F5*rz};y%W_*c0rgFc?(cRLzRfftsPelA*Wqtv5HRqpHN75(pvkZp zosqLP5~d%+CjnRoj|TR$IarD3wo1q=*p1G4z;e%|tc~YMB+D`uU%%=!-2)V(HpRo%aO2yD$OkEN!)vF#t8UVO6uMX9fIim8C-C|~}gI%ei@FNW~xbRKoI)iwn4R9C*T9$2e{G*<`K~RT>$~r6oGh58BuCbzB z*z4^tq*01vg(*R4UqExU;sDVKKYMRcbVBXNd9&L)cYwu7en=K3riP+4C)bwKbHR#) z-ONDiz z=f?>JQGn_@aTJd8NE??Psw>@sd5nJ1X7!FDKx>fOm{Q{xzqD+5410tqsD$3|3I(we zFXVGruqeRc!X0&_rc|l9srxTfR*K^|zr%#=*wmYB$H?mO{oW*)Et*e>P%Wxk@7k=( zI8?|IBJnk&vyq^^QmQau^h{Ry?dM<0d)8VqV}by9t)mt z1gjeU`Vg`jmZck&zNm`d+04 z(Dp(ictU>h>rrLHt!fiuJq@3*m)5f>09vEUtix~-E_ zC{qY4;uL-Jk!o;Y4DZ@~imXcB^uC3}x{#>kV%TZIBU)?jnc=`xQc?{yv;-#-TYWvR zmW?YMh59c%RdTae_C+~-%r?LNO5Hg|-HzrSs3L%`lK<~x*?KO_50yr6mH%z8_B^|R z7YlFiX5>mzyuQS(KQUBOs;MR)bsMQp-1a15_28K`7dP#@eJdDZF2QKZP#ObEyFn{5 z)h3N(P=cd+IqI0iPoi4?Rd}If@_R+=(0;$T01RZ9(KmU_Xvos{%K)oY%?i}{(h>$8 zTWr{Xm{W3!Mz;nupV zoQ%%idq9=xb*dUHD@rGmnd7+z6;KhxE_YdBVh6q_%u@1>O@L3{(dilyySng1DSIoJ z@V~?)%@Pk60>W4_2%Y8dGp2F#%1v=_hEhFZpXXgeK*aK(jryQR>|88PBEieadIbkz zi0KYgq#f84WAm`|hNfJ)wiTGf$%fpQ8mAd?ANh=wW7A1|V|Hj%o25Az8YntUQ+h&(-+je!?wr$(hW!tuG z+xAzsw$Dz??3tJ|F&nY_@6A6Mk(m*h`99YTd@QqYq}&gW(+EfLkHSZS-QgOsRuZ8X z^{FUrbAZl}=pC6ebME=JBMMVgWZSH)<_$n!C( zI?srhGa7w-tX%=6Y&JzZ`oje%Q$ik%|9Voi3{|2|clI8$<=WpcP)!olri*6N0inl5 zfH!qg_-o?3BVgwhAr_@y*jQYq(q}p{3$lPF0?D7K4RAnMFW@5!P4#hS9NXA-vzamH zx{60T!DaTNz%y%4fBD7;6J7%~S$h@2*!NWJ27&9hqTP%^&eI+^6l*Rc*cFY?0WB*X z;->w$(l}*_2U_Fk<00FJk2aXzAR}kOfR8qH!jUBvw*j0Nx3sOLZd3pZUTJw87&e+I z4T;d)h4yk8glakkY@nmVhjxfG-tew0m&SR`>jq?W92$zPa_oR~nPfscYc{=~XvCOL zS8+opzOWBfzImE|G+f$j9`^*p{jzduL}u$mnBkguBsEnF`)`>_fM|tf?Y$w#jm~=d zFRG(N3yMQcyoGWXWCZzYpjwR+cPnq#rb+12B>1CS6edS?6~G6Gq$216(R6n{Y!!DK zjzihgsL{%pWhb7c*vZCKZb$_m0@NRs+ufMI_TEWL{TlYtw;V_D4{40gy?If_h|~aP zZbPvmS(ZMYLXJ)_@)6VM5|+jEb`Ddg$}o+Pay~no5w_BPR3ah@ao>$;baPz%9vSP1 z{4t^`pD~gA1cfp145!=1@1;wVzUaaHyuX#gpX0vxDQjC#o3*;PD|`=;!+-1XM$WJD zvaTenrKKL`=ts=FruQ>HG9eld>CWx7_KwH_0x=apv{Y#M99XjN%4!B5EKO#6JvKEz zwCnw_Nitm-tH*r6AniC4{sTFyS`rDdQ(cb%rdj(gu%y4=fkB@Wi2JxO*5~kr7FuLw;un|H3G`6s4Mg8~&Eakj$86`?&{KDNS zKzix?)P2~9w6YGL^}R(Brp|>L#jjE&3&=IXnZYt{<*{ppI&$~0S-1;d_R3B$wDz1 z<4CN@wewM+)3mA|M+Wb)F{uO9F+nrFtq}u8g}eTE73|O8p-en_*e6i;%rMM!{C3pe zAbn||zwYv;{OZc;1JB~7U6xllu6iWjU7*%7wNmHr1t?lDGg<9M*{Wua%ZU44m%Bpz z^9`d73&x9p(dASrk-cpEZDpvxHhb9Tq-HvHoP)OussyNe%2vlquW!YAIc70W0k2!S z>;qfSW<~W_WB{{Ve2}@6mx8;@(JUPStQXN41Ue|CgMl!2O5x6KFfz}&j&9^@jOf*A z!3&^717Ng2$HyC;3Gh-;7_QJ;$EU-0IC>Z@o#ETxYyZn}8+NKdRYHgflK2cPc zE0E~`n7J9GKeyVLWGpxRhe6T14!;v%dP|RExy5QZgS<6{VA?)?fiZ3nH#^mevV@t! z7aINBagZVA{|>CpypukzJLdg#@5f%U@rH#^r1V&#ebmZ7f`ax|QE^3`LFi zRbvWTPV*S&bCtc*QnD0af)F7p#8m3_i;5<0rQ=0`F6vk3zVU%4w>My2%;7*}u*`nz za$SuxG8SChNow9Wew(t4mT1_^@vqJ^t`wi89Z5GaaPs-02VgG=*52sk%L;raI z3x&5Pt$RrOnqyHj?yKtvzWfKYc_vONVxGbXodv`thdMH>p;TNZ7TBhwJfn+RdDWSHr(QB|Zz_XHAEy-UGH>M~n^)GFzyi}zt_ z1CRdClQ6NeH}9ZKq}mxMfTX{6r~MC+mFS<`FKww)e51d@Etjh_GMN-h5`{1egSlcP z5oR>V%5SclO$N916Z;Q^uB*~bvEz_D1K|mpQ?PKfO>KG(zcug*5f~kHX5sInj-L`d zV!BeWYbb0OQ0C-9)VomcSqY?^`#`zVGa*VhI--RhJmjqqxl7bXg$fT)e!m{E#cd?6 z>g|)kU5!*#b#`7CWbDBeGU9n*B%??UCnIRP;q=;)5k^pcNFH1+#AfQEIqVy(>xAwt zMo6a{y!wwRQia_QaZ+*X*D*1AQ8pd-^vP;klFF`rnwT1<3O&RaVydPnX7>o^JM_h< zDJ%k3&b@MVL)n-lg>$|OA{k#tHSB;VWe1C~*Di{uKpG#44KN>4JyxmNvAvVArn)^5 zW+iL(*bQ70+fr#}EOyaodyu_$lkiGRi@NC14gm2A+4mABHU{suu9;vg2ny%V!8wF_ z@e-rgpA06wh?G=RBYO z&2d9cf^dQSGQM}p?&~5yPE0Ql&PMKtjirO0{WWoJ^V1)N#REB_24V_Dl#}1S+xJUO zN~yK#o3g%xSjk_=YZd?Afvy7dlJgGD2Vh3M^WA{ak^qwdavu(}K01*8&p!6&e8jM! zywBew_nJ)=GX#2Px`zd%Y&~Q#tuS%{OFrf`>iUJjeQyAm^?qfeJ0IyULcMx3QA*Pl zE1h2qO<(}gkDx~%WDs7o-4+puHxFGy@hByq_vx%V*&6B%)&^fB>VdroXD!sLSTOOO zk%)?m=x^gU{G5LBo2e$oWvgzEm2Up|3X-Ty?(Ql5`}$eOkBX*3Bc`^&Mc`O+Cm`!N zbesuwTR7^Cc{C>ys%FB*j=Sal_3)`HF^lG;I(%q{BKAHHf+_0Le@$}XTBcvyzaJ~ z>-CF)Qv7Im_o5#~WI+mUB7mX7vgNrQ*N_oXLm3hO*$-}x-a4#YB^L}e;0qX!CrLfp zCg}K_X>AaOt!bHyAo>$<^30HDc_S zIID5`21cYpoC#0cDdPpyERq1VT8PHg#lWR(X1!c1xUT!LwDH~gD2dNA5FJao8N>3q zyaGcxJwet4r8OioXw(h?&<~trCzVjz)0G^mp5-kR@~P%zII=wSOY1-%gsS+0%ElHX zIu=o>i>~~3!@rv;ZmAFZNk&CR<{0Ua9v-~P(w7Z&Np)dIcfQDudI>S#Z`7+kO3^3E z$yoKbjQf&Co!m(T2?8jIjI`LJG$L++bk?cybRA<;&U$;}FF4=j)WlCiy5jk26eI~6 zG4ft8N3HJ1wNY;`Ws*mn8szDBrqvY6IOw~NBicJ~y~?!-;(K?+oL~@XUL-E;n>dc1 zK0Domvi;fG(bUp(zCH*KfRivM>tuw`_~P;3{AWhjaz)~CX!Jj`TP%e_z?3L~f%Nm2 zh1A-gO^w=a*N}9a@5n4ls`3v>O+gRKp=fAD5@Rgltr+%f$|k?W%SJhRZn9BcBA+P( zfB~DERDZ*UF(384otwD1+YklKr0GpqZTle^lkv&NoYi;f>6tPxcb!ti< z+FsY3s7+Jl0uz^GOw~w@cA5*%l`5GM61J7_cW1)ud8lkb9XZShKo5{JtYlt__gU|a zD%h3}Y2~j#=0{Wt4WgB3P%Z|#*{Kc5UcBl+CW6gN6_3tocq?6;WJ#Vu`6Cq27ZQay z$R8}{W1Mf5*b*04)WeC`(qwg#x#AE4kBsBs0d^kPZjAO=!F(O70wM6S7_vMip_A_| z9QpasqC8Y*POZ$94y{=F#n;T&JOOqKd{Xc?#Ee#UL&>Jwxzh^z>{>>d@4eyO)m^k{ zSFWl74*45MhuDP~`SRz9s%fQA0aT>WKr<2O|(tQB%{ta^vP*0E-R~ z>T~n~MLULg>e~kUZv&e`Lc&Jg|ENRjf~%uWD9ecq&CbeWUhUIH3v^K2L4kbgQ>gn> zF5yHzhHwG<_Jd;v^5*phKqUbIpVTni@GqG{nk5rpLV@d}0vI4s0Wnaw0o;NKKvUa5 z%y>Tj3FN5XVU6De@PYq=&p;8;(7(91bLV@J`}cZ-`Vk=q22o&N!uoZ9W*FQk`Xr?F zFhj(kK>F-U^23Fa;*;o-@%Pi7yleP_{^pa5HR@k`h>atR{&+zar_$~LekKh;Cb^5zkx*<+w5 zD2pA*#m7V&=jXzpfF^_j2`Dl#23DX4LWOfcdrR5c+C_QaqyL)nM29})0} z7|hE5OOPmFS4WTPFZ3=D1p2dhYZoD+g1QG5lm`^6fPtBHlzWBAy7Y#C#q2=}3s(nh z5Kaya^!5Jf(=cd12?gx-@-zDNVlUbhqeANf3+@a0y;)QeDgX)+G9&;*#3+d<)y7@iO)vRw`mc$4P?(h{P;5QAF zw1Wo`hE39C(3^whA5Q`KsK+){Be=yNAHi;_)GMnnMfDG8%W{D2KU$p*kro5#lOkWq z2V(JvC4zxP8m2BnMSf3P`G+&$1`GrPG28|M&p?un*Lp-6zETFh7Jn$Cf`+?)hf#nd z3VzW_jRA>(IpxBQg;{(=|CH>U_THh>3Ci0jxzU4APRd`iuo z8~J;{Vn296l&i1@a$h{l$!UPD=i@s>b)RXuvR9cYeVNf!N_DeN2kN$&2}R&+{I}~B z%h@2;l&k$N@Ms%MXV?9_=AyBcW@t+2gep@oO;<2=-?r^~ZM&n7n4SR3@euifz}K#6 zes)KVHg;&r=CAdN^m&4=iYye_AJUCb^(mkzJQ!0f4oC$d8j(*Gar4OZMY~0nki%8$ z4hs;{elN)blYkW~!*R1l;7QgK!yVpe?dTO)nzm9ElBBHwORe>e$A$PT+Z2y4uYZvk7s_E9+8v_lhP#Qx%WNeS)iwrqf6e~uiXqJ2|QXXMHo@iyR$ z);t-$lg%;BcAzqy&TQAY$bc`ev$eB>bDigRQ(?IXoo+zl>Tem9wRkuFR4>`j!l^Nu zOVjaR%)TVYs}0$rhm|k{D~@v5WzhfJI9e%92^cYUh`7yV_NFfM>Flto z_7=HV%hEu{G`7tlu{praWi(%aa~s@#zPNTrP{!}fuy2f9bz-ub z-kE>%^Y;gDLo`234D|P|%QGtRg`m`6V1$LuU`V63e2{e>C<`>$!P>>@kIM*3f(+#yC9r;~{ln^k^aS_7J=crAaM=L7^ z1EB7wB4RUfPo;Jz5pU+Ke;9RK+AuQuh$llfjlM!WSH^c|@P;#@yZ(rjYmCLGu@@yv z$QEKi;HHD@qWV~P^+gqEl%lK{!%5U1#2iO6FyKmBC3q4H@YhoEuln%j?~H0FA@q>H zZ|gM}wr7quZ||lT&1c@9cp0SM-a(9a;6p|$WlB4)fjgI(0enL)Js4{n@{C8_uRk4t zM=dX$mI|6ABU_GbPc-4W9!v zdLiq^>cN}0Kp@bB?1!F}g*4?c?$m{rWe`4wv%naVUfue;aA_PLi+1TqSElOs2@kPQ z@`U)L7#m)cn-YFF)3W*X`EAg>c-E}8mRLFp&uWkfuF4x?r8V!YY(P(vrk8HhU4xPz zEfDu7p~O&hHoMKr{j$yk+ul>rqr$gF!D~#6nCY&0gk$&MTLoHB^H#1%Xu+w6H}BM? z0%8v4oGs!N*(EG3ld!t77d#L{KC{B!u4IrxNmu$;Yg5~@3hztfPCH`k!}-_DVo+AG zKjQ#K^>7kOm9+oob~nuGlZaga>o@Gb6xGjv>5R~u>}g$7-I3UAa^6%J)B-#zYZhz- zr;8zv96=$ts>95Z!ZoF^1;06Mn^9|)GwsR(|6U5~-Ty%lfKM|&J&cNoG*HkkC{J#1gFF`DR;OWKTX;`O*A@h(n1 z&k>d#^dC_8qS-oRk+k?MxxkEBQ(IDKHIVRWYCr0|$#+-3EGf%`G=%9Ew;N#v10?iZ5Y=5N1r*H?_2C}wY(WZrH``Lf?J zE+*rbJ%=vA)U-E5P6sb(8nGX@7Jk!z)*6u&aF?Oo_R`kk!j*baR#-U!$DTEAs$`*i z;@oKo_rO;~W{ioHL4#M1a7J>0EwSy4g0PgD(x>WaZ0^t?0mSjub||3VmTtDQC-1f# z!ggks_}SUha5(dTJI*U|&DbVel~D*y>dIdk!`>rr((14LJ=n$%-IJNbN9TVGonaQkc)iZ#i%-xswZpa&DDo(6 zW#%YgvI{Ot!A!+&{5s?9@EJAHPmWi<#q#V^oj$`gplc3qfomk!IeG^%(pr_E*-v7|)AN@mXh8>&c>*A1qXka*> zXEhmA?4e)iqJv*f45K`qG9%#ZSHIc*KKz|8BODx=D9KQ1)TCAqw*&vQI^kc-lOwui zN?-pM~!Eci*|8IcibJ`y@S{8rf=} zxpk-tphxFUqjl477AIJQ)msww9_dIB?@{66bWP=wSHCp0o`#3#a8A60Wb+vphUt!g zTIdFNo}fhIZ0blu=o~^2#q5k4gc%4EZdwv<)Jl4$3O=tX+>`idcHy#Wi2&E&{wqYySOS#hlke)!XDl=w26OE$n)9Jww` zOg}bv)h-dyRUiMZe@#-ig<5bF4cT8r>9n99aZ$zCkmnPg+U^{bfBr8n`l)u8Q~mhYa~I zBhrf?+;+{$b~n3KdC@I}xrwBleiWqmH_cret*%Wg%1;`8aDz+N(qzQQ?LUtl@bdl_ zlDia1$$IIUFf!e%i)Tm{BxoTk3U;wXnuE4Y3IQqKDL{8RR&(5s8g!F=@H?P5m+|f4 zQ<3uXI_)_V{5@PPQsX6|l|HMURAYJBG;n-*H_fDN+^xyqP8h>7&(Q48nSy2XB9hTF zkq_nWaAyy63;vbpGTyQ!!l(Nm<_DAQ^KuxY%7Vxj5}Z54dGEHP69&b=RjSAKOV3Sx zB?)`M#^)@Q@F}d#VwG(v#s>DVt%{AMc!-lNqq4;60UtanE4j!;%XJNTSnX0-f~^LO zRPSJB4xUZMlJzo$s^c1SFSoK)e$YS`;mWRuub}6nhh|y{K#QA0Y@cplPFw;wb>EtZ zYe+x$srAmsc|Y3fS*7%qS|M*A2_8<$z0DdB?C zb6(hMNK94o6?R0=j;(xPbUkP5w%Zd3zlqPDgJ3kV2+-!2z02mIKwdTM<^}-=2By{(W2_Q^gD@L9v_t`0&;p@M|ryY?=K_ z`YLkJB`qVV(5+(rZK+T-tZb)?DM)j1EpbJ}<0Oh&d}~SNQx@8<7yRe44m}j^;dhSO zJT7CZy{^N3JE+0TUIr9{yQJvXY(|-GEJcIXO2f4ymGvDm1;3cvHvsk&g$~ac0Q^bY{ry$dc~WQx(>(# zN*|u=-zTdfp#3t!TZ%5auDOR9Lg88)CJNp+S}#U&tb&Xo07a*_!eXhMZQA%my3c!2 zH=q%pppH_G!XH7AlEEF!`ugK@3TMnRev;U6^(n(I#C|qAb*4%M%T~;3(sueBJV8AZ z`8l|MYG+JPot0%GBiX`cF3y@!J2e9<_9qlMMNV=^X^x@6$8@CQY%}>z^z-P$py3M zE<6q&W^BUvf@G_`8mkX1)&;W!2k*2Vliih~tr|?;7n201wUN+cwfbr* zPw=_PK-c09-08j5pkU=QnAk~3V;t1YmE1U2o#mnUcH16PizY?Lzb!70ZkCGk3fN3C zHY4M2FD{E@TCXfH*gf@`?)r~8Ih@5u?;2SCywd>P5+Hodu$6_Fp}0Clz|l}%P~Di3 zqpsm=!9|S;hS}ZvXlzTDYfw}oN#{Mm=NH+7yzwff(Vc=BY+{x~+zWvR%W3`*WKDfn zVr11ZWdIOXTX+G}=l2nF=x9<`bMS**s0aA@{Y1>b@TWv8T2W;4UOchlGu-mCzg8+r zN$WrAbavFU=CMku4_FDxORM&3qY$s>GB@!;zs#iaMj7RoQB7oXYP?CA#GoSN)E<3Z+aWgQ5#ubTkBq@~Ho%DVd$zH_O+U0sqV8Lu1iW>rA2dMx<-Q_`!^+wArm=(wgOK%|-2PFfLETvT&E2FuoCAAQ6-s7Kxd-s?{_TsB z_SGs_*ucRy5wW5VK1-cdFL>usgBi zX3BBZ6SFUF@g35(Q@br5iGi5`+UE&GU<+Wxq=e}OnRsHRqn5N+auvZMN}bKFY65Ba zW1$}NX`d+rsZ!)!R%AgM^*hgAp)bM+V_r6}W~vR5uhqGJM(fF^&MrC&N#9eHzx8T+ zwv>?X8Wp3bYGOA}w*7XWC-2~#DmKYyZvs_fF$a-0TWZT~rZjwF^gO4I) zehhZ&X#P;*@!`Q6(mgk^HxkRw=1e+g6EAqgNPo(@d1g|Q&`#xW#4A(OWzX0BVj96P zPm_NX;sz%sX7^Yo$$2Yd>$)E>%Cg^O3VU5MPWm3};4l4KkS=b|qcukHEUW{<@!8DT zR1%;j(+6eYIL9ceE<{4So2i!k&Ua0t@%56ckTRENWh=3?2^b`u&*cK;m=f#9TT3K> zZyP6GLyL!a#)2CKTqME7@hJy0!W}Hm;3(OrzLfsvPa>RExkp1~(BMShe%m@c$1>~H z&FxZ$;R?hG(}^)P!TT-dyn@RwVdF%3*?=A+n*b99zaD&7(n&s2OWonI9B^qB8|)=Q z$#>kVwV#l5nyFQvq|c4Kl~V8`D9m?BU&aI~bWFtqYnAg!I5?phKUoZ@T%{kji0MG5M}WD~N=!s^9W5wfeFh7suBlho zwow0jkTLY9JdC&ujnBF-*e&+cmU*02CeFbHIl|&Lv{g5iT5T0yMZWQZ$P#+14H}}1 zs^jhW5SCnw87S+Yz+?-IMJ8pJv(%Swv%t77MS}RBHbX#@8esv!(f2qQHy2$IFOJ_3 z2grIah@EW_g||11)cq(MtcZ7a@zBO_E;t9sC<|kX?K5k}JIK+w6MDc-MTo#yK@XE? zNiPIX7cx*rp`3xHW@xV+GL{fNja@9x`9eYjn}Fho%>rBfu5r57(GH@`mM`CYdhu*2 zMyCW#?u!i-%D{Nxtd;Lu0(sfj2CkE{W%1RA^|0D%XOL}J1QhwoU*e;6fm%5L8T(T7JG@Y=WrlaZO`xs@nvnwX~X`MQ?Kp*q^ z7i_1a#ORmk5?O9E30}&sQL)4iuChk~4WbQYI>RJakJqJ+jtygkreTxH=v=GM(Dv%6 zZoVC0S;|z?3q&&^P}=hR@r7?FHxbWPQLk90UWD*J(4mYPvDsNfmd`F#ngMSWHPxGWTE7}OBj+VwOOHW(y4AfeU z52d%U6r8Wb5HnapZiy=9(0XFD4DV@4c;czXUPvzG&;U=15|=t3WSuk=EQG+oTfd`@X%u~W!?E7`H9PHLxq0NHKk#xqrFo>9u&VKF8g zIY=;-AGdSZ=KnBWsF5lVk-qFHGPLJtC&b|2kqqK-+HLY1#4{v_hs+mV)oMZFg}B6H zy7SWB2h7RWF`-EFt5+N$;C6^$(b_a-<0eO{&-!)re!II`=Y{I|GUHWUTXRiV-S}o1 zp^KGl2{h!kZtG@VSy+{Q`!hP&qv8$2QW*V#Yh`o0-q)bpGoqs=YF6nN|2?a4S_-S=Vq< zbv_s9LtG&|{>4`RG^FM^0T!$7V&u}~EH5ObcYI`eLLW+P(HG5MsI3c+Gv@Ocv0ug1 z2VgeVC#W-0Xg9+7Qp7H?51%WFOwQ$b$#HF8oEDuo9`(CK{65~Hb?wFT6qv&F+3!X@ z9O4Q%GfLmTPMD48I(pumZG1!{P);oI6H?b8eZcBvYi1AUJ)uV2#EhlLO2gO0`}K$>BSXPVCSI1KLQRE5L}@M+YJcp&8`Thdg)WFhF8S#Jpe83HU>Pm3)ssR0GBu#=-4dz7iWbI0KgRFYn`x zcyJq~a93YT2VzmoAOYBW<*%|w1xVN`7`LELO=ck7JpVqwHHAjg!(dG^+p>RuIsuA> zk2lmQ`fT=_dd%b$#Lz%Qh=g`LDu;@RkbM~8*m7ERt9H7euW$PHq*P%3fu{&{K_s`n zPs%E=eYLmJPgcm>$pnwIRbCC=hi=CEh0PRx7V*C0s7HP-NZ43A%O2bsI} z5)R1iSB-hMgmWZFpMQwlyQoGSYPhDJZ@hT_(tb-LmQ+M|0;s zrqeT{I$IU`2v|uChC9fxF-)9L_r57*dv3J0=_4`5b4f1qv|W9IKyDx1{#jk&7q-UJ zXsCymwx3(LHBu-O9i?F_`^|~LNNxaScI~IC_o&2;SlQ}&I4>Evbs;cZ5njcGa4lY` z$J!YoWn1LEAPYAkRb5W~BA)26eA`s+Q6>)Ml96X}<4xDx$JN)F{M~`0pfs5*_C_o1 z0uG#_GMs|BcPq7Yyn5Z~?NFI6<~PTTX=PtB0x<0s*!|0nhxk`2?znU_az9b1*rrhU z&r6NAZQa@HYqxi?;)~@kn9_V@*hK_sShg9vj=Nt%|7m#L5}-+_o~4 z9$uwsYf~r!{pDDjWbZLsAC9QPKv8_Fjf90%>usY>5p$?@4+Y)UUHfF9e9#1cdEK^S z?<;K$c*T=osn^}kYD7)u5$PdP}!kgGh*6wRAOL) zWqrm~KIo3q1lB({bPVKRfvLi55xG~Njz#u6i7YnG2lIBy%O-xr!A;5svo{^ZAIY4Q ztOUMaA3EY^MfY)9Hz6u>p{?HSTRUt6v~Vkg+L8@bwU@A797sD9!{w?w=-4PNR3T2I z9(T6Z^+$cJX%VoJL&x7-EdnsgK}3;uFIg_aR}dl8zNKvipW8oJTSu~fo%yS#M*$E;b(0Vg>iyqRqL%~Np+^Data2P>3z78aXM zn0eyWKm#VfIc@+fV-jrRmI(+)*ArIsspUOtx zv3qidhBjaRUK25Ia>I}B^0ySFNN)XXv0IX3s-|uKC|^C2-uuR{0*sobV@*#(+fEKk zW5L;c3JIll@!8{9Ewnq}uZX?^dcMBW5+h~lKh7J)CBRTP zm)eEj5xz{tHXT%$lA_qi-I#loX*eTh)nr2ya09!Y&L#fIExm@@J>089crJ%?NwXrh z?`AW0azGIi0KPBj+B21AWz=n0xPH1azaU`6lsyQe> zanP7og5@CgzJZLnPWpwK-x9a-VGaZXOUI%Noeq34%thpapd7#?^q8sO#s_Nyc`;UyO+maRBDHpBir$bZE#_EAydc4qyV$=!?8+Re+DTl;g z-=&O4`FEsC;{f|%x%qBpmArZElV6qth1lq#YI6(4Y#$N~KB4{(UNfqLn{G?h;H)~p zeDk`D1=S$|GvoOxYa`?nVv6)~sL9S(*e|R`T?T(~q2hcsa25tJ zc{`sL+?Me=gBZA$e#cqqG_(=WFk5x^tOY@^Qgz;O;}NG!-{2mTO`F(%(wVgqf9DUM zO}wAUveK;&a)+ilwW!9j3`}W>$->pH^r?=9Qz*wlDdX2E?rW^+U;*SpEU@|RNwu@8q~GaiItshW-Qi9liC?;cqx=FmCGAlx3ItgIKkEg zSY+LvaE%XrUVS9+hKt%3DYX0P;hbAryDMuLdJFB zcfHq5+Wg|xe2|hV@@XVm(Ix5@f?+}Q5$TP~>zXS-cmal_r-jzoLM}Oh!!8Y>LZy53 zGa=r!9YrgG8@jTsbL>QOP^W3^(og%NGt})0)~S?jW7w*Pi(!DQ!sZaKe8`d;M?QN- z*}hrt>9cWUZ`v;?o;G?~C)SqHw$M?i1)EaAwDB_KTrhvs8GcN9nkwD3nlqnN*d%JV z0hgJ@BKd~(DLfl780UDDv}}2G>$EPHfKnI~o+Iyv@##EruqRt=ef)=s+`KqPKjb+d(9 z)2swDPQ>kgtMMDj9BV2)RynkGZZ%esfqng@o`e|+xMb5KQObPvXOK&@yT!A4kf}t? zVhT#JU(FDslw*32ZM09%Tn>t80Z1Hh?g8bnEcN{u?;0>HK~Dz9?hct)b4g*8Ysjmz zIF}-1tY-YHI#fv(^zr^!obzXuyhm2KR3*_mHz^K;G_|cjlS;Mt++hD(OmG*>V#@fc ziUzlu#8Z`$)M`$XtMyai6+3;_me+B2CBP|7r3btMU>?|`<+lbx-zABwkobATw*5KAMUgv%uVitTi-V3;||UQi+RjxC(6K`AnKHO@T@ zp*KudUmFvBa83Srbs-3|UP^MA_7WgIC@`uLp@{jySRzF?>%7V!4}Hw#LAZ1+R%Y>? z-mp=ff1%VxC49C>+LYuRHkVE zlFwaPRPTH}(GbTjLvePT2+CGT zwy2a|&42cCaysvpj2!|iTJIXSt{vxyXlfT-+N)^4vnTrEyz32em`*FWE2Ts?T?!83 zltyYJhgAm8j+DqPGWrX}k9#UfZX69wqDMZOAKbN_rtf6#m zbS|R0ShV+;y&XLQj5tZ^-E=*H^(Q{Oq%J^RKZ(!Y14Y4Nv0!*bSWy_(xhIBD&MmEz zTYTXtx5`3HZLn5W^K_;XOo0Bn5cA6Iz6ues%Hlln1lQ4&5#cGEa81NX-X~C52uhf8 z^>Fj%q2V}1X7S|i(B?B$GVc)1?NTU5bDt-k9WbmJVV>@5zIH9%ueS21dudtd`t3Zu zfJj88Bg$io^&4QqH`2QT==^ zsJQ-=Ig_SpRoBhX<|lB}4REPZiVg|XnKgo-I=K}VUHLrwQ!BLV%+mdGcPp=Ca-%u&(_aWeZM$>+-xvuEIg zee8;;ASZR34URUanrZ?}&o@&FkG+=pl-c|O7~MI1tM;;sABqi5hpHK?JXkv;R54AI z2^9xer12dIQ!P?W>hflSeYz3_#G@TikG7;I7j6cS&-@IQm!=6^ zL&ilru?X~{?ttEMvxsHQ$W2vw?(~Zs%)$fLzs)u7&~pz=j;~*r_5V;fA^b55gDQTV zTwQ-UV^q(N)f*UOA}NbpYwvr9zw8>S_kO{ph$J(@t80SZ+t!<~raFiSlke!FXAZWcTYF9qVZ4=NBndta2H{LkxG*40gWpp| zc4QKFbz)PsHKIyE-c<1N)Z5~&V+&QK8>O($LG(f-wck>j*L}O+M+OT}Gkh57(Ai9z z^78Ymm>L>2T7L2SsLs4VADZL{WlHM0CEJG%Ni@891Y01@v*_nGyBKHY8lzxg?ok{g zSq!{nv%S@jaEUiJo*S(j=N2SIV-<~t69hfH$64uqSHWK5;l-9nRm;|oPeEpdv6vmc z^g+fJ%xTSOWxQx$w#V8RG;ubBanVULEaU)+o#G8yQ=>V1yo(T1ppTT!r0I24 zNG7HF^6SKOi3jj*){6KXY&bnBNgI8T;dzmhSg^9}Q3B}{ZZnZy5z2YT zi0yC7=DKun8)0RF6mP5D!rp4*q?=EfQ1%SiGSD3F1Wu{Cyt-X@1?Jne{UQ~rVN@G- z)Xd4hNFCj@GG^}BzTSTfiPfM_CWELrMY%cy9At2Q-TGkP7yVdv7-Yxmq7Jd)%E~sI zgmvBNE0!$yybi_@N8k*S3vjoY#A<2sF(^evJ}xZ+AU_@x#*Xi0-J>ZE4K4DvtUEG1 zS-iUFYjK+{0)mbZPCt%4U0y`~THAo1ZH2T+|1Cka4wR0S9gPqxB>(iUzRyNa#2IRy zEWia}>M{~nBCaGg2N$aFPsd7day8!eiKXILG`%dMMG({W? z!we%V_^4s7b9^T-Kk2pmD+)1DAJ}~$5*vM>jVnRy5KL7Qyrdgk2{>zY$Zk4|`W*0K zA4Qk@!t4Z#(6gPw;CggFNHg%97vc5tFL7fq7rvzD3ynbU)#$cW*ehs|Uv&K&e1UO7 z$MzDk$CaAZ*i`e_bZ}Y@EW@-H7cB>*ii%XZX`WV|KdQyYO*#2GfN*m`jYZ50`o)L8 z-OKZi5*SEGj)a={E~jK%n1`LD5{NcpTIXm$k65~gddXx>N>&8v0H?hR6UC%~J8uRkH()E82Z35@d{H1$mrx3{fn z*(>Snc9PLOnoPgj_k1+y|8`kf&TQU3 zs&d_SrFPh@o(+2r`q(Kdi*S$+e>hgE62Or^`)Xh02WaVNQ@lVvCm2ClIl0~3FC9Oc z{u*%k`oCB^#~@kSZcVps+qSvewrz8_ZQFMDZrir8+qP|6)9*R)&76t(20tc$RpqlH zqcW6Rh7}Z+puDp=yY!tew-0?`{ur=R^08E62*K0TmE7LFnzpvp;jcBHX zfpQ+y$f$NMZOQ&h)%`%%z{gJFu~&e;jb77-xXYebK3?$xf98$JYme!bZP}lhU-}(aVSja2ve54zsxa*YdmG}T(Oy5s}Wh%Ka*(Jk5F_x zwb*H6+OqD_&7S0pL&U@? zUY!VrygA+ZKFqp8LH%mE*&PdU34``FtmtcrBBm$`>w4_IFs`6x9`Quh-S5jjHt3Yu zy4lnbxB(Kn)Pb9YQ|&z`=6a87Bw;^gMuSUr?kdht#6k1!YOW#zR?Aa6;3u4Jq0Q6L z3rhdnfCf#^R@{d&$6vBsgC(3)9kB{o?X{PbtwcXZ^OyL!hYQ=~1&+^A92m?cLzJ|8 z@1$Ezz~wSNe8HligZy^bf+RJBO^5?Qwqv{66PqDkO1}N|i&fcy^v$W;>%WZ8&-n24 z<5)vDtS!V>Ie|@_=y4*axzSQ!;Nmg$TC-l5RjEd??D~sQ8vC14^kBSGjIXnF)V1g8 zdRlN5_z4}qC|=#Vh!6=eWX|AS3;q@eTL(Y-*W50bL2(5)2NGk|ulNieY*)$NuasRC zQbhGqLm^^Tm+H}Zt53|AYx`~5MR*-@rZk2Ey6I`%7ILbDnE3jYLcv@|?s9gojRMfm zG6)LK1L!=`4TDI5>4I;1z8_?!tZz#eZVdpg zjXkKrR(EBb=v5!#LB-QAt`X9yf3fMZw3%zCRpPXI65nzf>qQ6RH$>MV`)TBwRDzrR z@xzK8Y(%#(g3N~JCT8y=p(n;rT%+lSG4R%VUr~?c9G5&{sh+Zmu1jq)If@C!alFy6{T;?Azz>|8lzPR2Z3|rkQcyt6JKyxKn=f#7e*O{ooZup zw=0}?KByW*W}6}9y~rHh(cpAKwGX@PA1Pzecv{E^_x6+-EhiFZy5#b-jq*m zrp(h|Bw*p*t{N(GfPdiaR~(@ZY-;eM6^}07pH;)r>XT>EA6%mywHxg7I~k~JI->hD zve>7GduhvMhO8)kg-6Qu@h_x3<%`qg-JI2QPoN>{3HuYDHH4rwnq5Vv`6P0u;FTlH zJA$oZBIq@B6SO<%^z7=$6{6wYW}n5*Q{FL^ZisXR)X>e0vD^{;N3kMH)SO8v@&L{V zT%ApZhAnm8)jUCOK3U zoc${^;?;kf+1})Nx)TiAD`i z+uNnzRWWwHN5HmQ@xnp0zQlVK=pdpKXvnz2Sv`6pPqsJX<#a`@&Bpe*Ij3~Aim)wC zF>wdFsKZ1yn*jLl!%y9@(U)D!5w|vF0ba&D@=Ol0B40Z(s?`N&Mk@!i`MH=U*fMaT zdyL5(ta+2KKg-iso_%vpu}*3PjT-^hxO~#!(LLAx5VpW(L4tu*$tBT|0W6AcfA2wC zSC03WB&Nh?bCcDJybsERfW1aze`Z_(1X$+bRvH*K<4mw;pM**pX+8+D05iJBkS;5q zwm6*PqxJNBJH+Oqa3!cqeAR&*An&4dW#eoKFbT`jebMo!Y0BQRQ2Er>d;zc0fn=t| zq~un2ezxZxLjRcyOz;w#wvioYZA3j=%5B z8UkAHnnNAtyb&zakW?rMQij>3iQZ{@+>Y>7+;Ry0+_g$M$?&B57#n?t(u`g0N*7M0 za$z`#xh7cgh8y#_-l39w{N|uD=7bjm@8MXbtX`o=y3KrH!<3cU64IHYzVy|ck=I-S zVyfDsouA=RJ>YoVJ3xN_NIc5M(X~vR`x)eTML^#lkf-oHfRME3W2*HKu7O85j|Oj4 zS-_Qe#iLEh5DzOza<|&;EutBy7hww$B(-IfXs~+C;4tzPV4mmioNcQ}bVFD0kS69C zFTsTmIE*Aj$TsW?XgokQ^zSG>>wiJq|2K-SDkq_#sQC}Y=lJ&&pPB7nsy92s{}+nS z{?jh-e^9;u)9(Jq-~L}|{y*&gf2R3t|K(Qy2hC^u@BIG9-ezI`_x3i+Pk+LH9RCmY zw#q;Dc1MaVpv72x%+|?O+*Jw&!*Cevu%80apE+@ASVba5B0|dOq@;~`c`{8Ha?f1@YH;yRjU}fz%S$P=}AX*SKurZ*82N~lZdpqsN-j@73 zU<4-SDfrDV;ZBoBp~rzl_`ZE%NkIV;J+we*UYW^@1UPeh58^ijpf90On?wTvf&l7o z{N*5=Zwz>b;M)q#uZNKrD9rCI;l2>J-RZGq#^b4?9+>8SS_oW7f-<_RhO-ogngn)n_WABhUO1KZ@6$B8_t`WNz z0^rHo zudErbcLqD+WkBN^9$cU|R}B~dI`CWe+3cZ4*lzGzKdgayZX7!RB8XTYK&_P=MZdI+ zJZd-(6c8b3oL(%fgdPbS{x-Cihfr4i2j~j{WKazQK%{KvUU+3I*x5GL)Y5O&d&jhfF@Ena z0!@qG550ng-}(#`SOkDS_O`JwpgcYR%Kin}9d(;V9{WQJ;s^Bb5N^aEI{Atk@i zZngXcyhSbjAU+g-!AIVoz8|1}jZ29EW9QFZ04OVufg|uH=RyPH{Am<>`3oura3!F& z9~hXwhu62}qIS(efan+SxBd5~HX@G>wGb+;|8~$fTUj{~qn|z@RvK+50%ZJ^=hxNIWB&482D$UY^TA)9A;H8eWBvf_ z@YVMKCjf97_4Iz*-hRWqZnJz-kAD-se^-jlPtV`CpuYUW^AYG<&31BKDkDB;R>Eh* z43B|sbE{Kket16q8PN0nn_LAORzNlkD#*nBwN%i%Wj~`lIx)xE>Lonj=OVDRha3lx zWza+Lw}&Z!pgzJ0pY@7{<5Mp$Y4^$x&ljls;rYa@2vg#zKRlm`5YjJCK8|0}dcTev zlAi&CJBv*#9P| zJ^x#v&o|%K>E2cy2HNxO^$S=WSU4b$;=p!CFPZE8Pwno>wq*a@i`DmgnV%q|yxCma zv$$Cs#dCY<(mWRG5x}2Egw2TdLDQ9c5@MtX||p z_ov)G?#V}Cc)b#=maI^14wB5MnwGe!?t*J<>MaHL)p5ywBIDvt#JhR&L81-d8q5-* z(30K}xs3kOup^c{G3fjHmc4hlf5=>6WS;5M| zj|Fgyzh#NGi3_hrY8PB%K!txgAPq_T*r@Zv&E^FnlTGuxv)S8h*BI*evgP4p@4+f; zOivglKvGj_9wrSl4y9J^YoJZ(AQT{NBTUr>WcCoEH=Di&94~j|Ku`TjwI;k-auuy| zS?9R&IABl9wQ%;#XPON0k#OvrR~0gH<`6s>BGhd`oeG{;;L zB2j-rNI|?XDYvA2DyyWfyFIQv=I;V_OW5XrCQL-|}np#<6Di=sWdULCvY}4bz2eD#|&|A8&lz64!Ojb0Q#KQdcPW`=-A#2#`KCexA3Ou$SCEvyYqx0CS~{iv=JYB?FWYM-WbMu z#P9eFJTSCGuCu5+!u-ub6LbbBWCpHPMikpVKVqarl`FaXT9h84i~HU}^D}WbVLN&Y zLf993&Ux3Xg-o*rZ0m%)j1mH0Ec>FD(lPEaANqhox|z(3wRBPn$3MK;9cmNyX~-)%FTgq#pXkep0oxP7D%~GB8Oc68mO_@1 z@AW>PH+6sNzubqEinv#Wg7{5&)-XO|r;!@M0^ROzOVXWSo#+&CJ#*0Ig1TFhtf|f@ z^_2-_84QaPSXLsYkD`(ttSxlJA2Znqye->pi$0R^c~^oP<>-%7I3jG~B|II&2PXE2F&(;iC~Xy=kyJ@k$+{ zJI17*Q22#Xk=EAbWnS>-lEi+?98c|rwT0FTjmfce0B;N^r*W4`D&hE-tQ?RV0Vz1 zIM5OETKi`#yHyQ~u0JJrnzR=v0=v2*-qA&)kB}GWX3b{vI0ugw%z{Kne~$Jt;X2=UpnHW)hWc6dwoc2LuA{rtWNoB9@t$DE2z&DLHL%Kd!bHlm%IdUK&|Gew?XWi?nWaGeT z-n5bhdP*#r(k|A4@v@38XYo#_$*L#zca&%?@A-CLKvvMW%dA~b ziWDf=`I6V|IxB)DfW!4j+cGDb5?j!w#{^#&(5kk-g^bBQ%RO>prNMr;0dE6h_fdR>7#?_p|3)G zorM*kX-U`p%B%|p+dY6mxh_(-D~aetwblN%49`CWKyHH7C1!?L%1lHpRk--la3Jwp z=1GXRpChr#;dqD+vmLoSkMmk3^6+`0vkB);+u*2?6sLKRcvE@;WmeQw;v?i1_4)#~ z9MSJnGvJR5aiz_LUP+Y#J^noBZZBBj1S#HHUrELTe&(n`fZx^mwHR+uZDvAB1U3nMw50hWP6|9;9~VH9&d9~iZ6MF$;inE8PAOeON7#z z&4Z(AIBuN@zT@YMu7aBaMTs!z=ysRJ*+cgW)QOFbq!K?i?OtvPnPjTSXPPyRka>$xv(uHt=@>Y}SI1*yDLcs4riK$iu*joCM$b zxLVD8kq_Q0(XJ>rXSiPPZyDB}2D5ggYSut($QxFkp7BCiB}G!Cv7-4_gqrQhF~pNY z9g{LU#tw4rw2PGW)Ds1qLE&zUnRyy{ey$8zNkSo%UXt6vj>7^&@gRQ-=9-~~irl+N zYfFxf{-Q$>YmN2fDve!(4p=mabc8E7`i2qD~XMo-V%)wHt%f;N^Ie4m}~v zYZ5{ANTerV@K9mmPgMWlDR0Q&EF|Jn#5X}Z*(a$)!BRBtl5`=Jo(}JCmS7ZIu?UNUC*{+V!+PQb z?Qrp=o$h-`WB~*@~xe9To3c zw|c`*nI-QXu;+0M`f|{w_XTTA*7Q}u^1l|sU?oMzA|I?xK#Dp)eJbufh~?6n_F@$x z(SQ$Z+`g@~7wXKmi9qW-a{_RVq&`fhBlj;_bPSWuy@DKZG{sKZQ#90YJ2IdB2gz+k z0?}V~DC`0n#Y3cGoUi>@)j`Q@eb^G&E}BhzFg-d$EG>H*(C3~J!f2)bnGcdEeE~geMWEd zpCs$HOI}?Hb8Q!;S7;gAs=vC##wdl{$*{r93HIWNC`rvgL0`2L$%Ot^EXOQRrQ45U zW0dsKV=c#$*Vn`PbA?CBj5wbN5LG>t`ml#JBqDs6gOlfNDgUGx(?ORGF0P2y4zMb^ z+j+=X9t;3uJzB5}2vp;cWknS){_RWGp$>-E!%W`KR@z^!xQb0EilBa_@QK)8(MkQ= zU1Z86s!RUfn|TR$15sq6P!aw8l$^ODZmhvd%CSl45L0)P^swtRV!UwcXCGCQ=nGAm z!RgW2(G;r1Xs2f&c49PoydwDs_Y}NdK25I&-@pnN9_Hk&sU1t;7wy@_H=xFJX)yDP z*|>PlEif+QLT8OtPd18GZqp@OizdTjF)z<6^!2sBqOhprv+pBmAQ2qIK2^lG_~Oa7IxA@^uSG+QS16oqFH9@7N-*JLV*nWtsUY?h zJ5Y%kel~3wP?Eg;*_P~=y^=faRw@98N3>MS9(>?g%n2&zOOC#^V-6jyL1$itmns1RgE^{=&Onox&M3Uo}b)8UwH-m;i$<$q!?YLR;!pJ~L%w_p>w@FoErR$8DPT7+cwUhD_AMHhYFv8aeUn3<$HDJ;G+FmXFA-(U25;SBDvZs7^X*y?!7dZ z-!%8cjcNsn$qi5!t5Ih66GgQ=?uJHpQAl4$h1pC$`|SIWVIYA8<>kR4I-Af8(XqRX z!IJ&NfedPI_QRGLc#;7y51>XWv6er%09ck`S^QWq5W+eAT2>ZGGvoBcI`CjqyD6S2 zfS8)vz3!AMb57WP`>0m)?!bB1B_y7>HvgvA6eR ztAmU9liHU#lqRw!VCtl7pWj2kS1g)|F6g6#t5&S?Fn!6(ldMo9ALvn15UVL8HFF#q zPrKr-#3&Hq#-BlW>;vSXh4f1bYKpXd6m@6#Vk&FFSLNMvZU61;TW2@dU#g#5w(lW2 z{id{#Xz480t1{}CKsTj_#V-+Z9#_{55+Vt`%N<_V@MGzl zDWWs9w;o%6%b)(zw}=!6>RqP9bOJj{u8QZHfFBs&mmkERRh`aC}f2O3J7Jq^C-?gLqpKVdQakiqDNY_15{8WA@vM3mVVdAY|z@Nj0707v3vX zzTLUR=oZx)_cpe#iw&!25@t^DH>HkYRrjQS>Xub0a#OJ-pk+SMCePX2fH9it!ve+o zOpeDHr{0m!9F3a03+@li-(~&8HE&$T73}YZBx!XTo6|PZ+=#3nSJY~sHitc6jIJ`t zZFw)+Fy0ev8$E;@uC`nmP{UxN1|-TTyL?MAevNzeR_h8@P=_p24xbeZ=V zlf$K$p|t2!Jt_}he?5eMeB=N&J`1d{QY)a???s_RRRqvVDi?sY;jwr_uSVRJgGtaJ z!dA%#{*%s%1^M7{wy0@T{NeQ%Y>pAh z%hDSkqyZCHR#s2OIGnmsM#A9?{15W|1#jue&FX2<5kh|d-fI&g=Hjd6Q*Jb8<9g{h z#z{1-qJt$|&S3S(`ht!;_ejK)93NAOhx{*EcFD@0`Pu@1PMu0Qb+U74ym5y8Vr&2U zCYMcS1k~h%*T(Wm99>6@#t1^$nryrpwD-J4TX@6qjcKmivd7K-eGW!~#aw6Lh;3@v zKha6Bu0s<@mU=Y9&$=@Lw!u{g?Sl`>xh~OH!9QZ<>y+7t%5afl-4BNI z^#<{EPbRc97EOVnQC=X|n1)sJuyTBW{sC`L>Fnr!$xDssLxGCg*P8tqxdarSOCG zH@QfYQ0b+QVZ&Vq6L${8(wx8Ngm$~4{Y9J7Iv*Rj^hToNFJYB>)Ma-KqRVqMcH0b) zXzJFju+_gi+`(-XG{sx}znm0V9pYUu2y*B+}(a8<3Hqy^~17p`T%&gRZB6%k!jPYxGDi0NsOdgL}NY zVy>h~osECtKtxWhf2igL0n~H=QXmTK$&c4dl<(=$Z8wH^fE~1rNwHK!Ac_B)LqM6Ej?acR(@JD_0FB)d(|3ba29P*zJ+KGNiI*sH(kM*(4lU5);Vn;+zR*D?BWS1qn)wQORf#(P`l$ zsIe!#9Wy=5&QM3;faY~puxELayv@G0S==$svFO-s9GTfNWRkS04 za}|!9a%N>4bbP$J<^^8l6b}7)eEV2+%G)g(@u9sYDeJwM8Lauxa0Q3E>>b3{!Pmqs&-6E5tF`^l{t<>z*!c z&DPs`PR>E8YyAv2SJl^A>nyv#DG|7rsq|}jaaG4t&V=J`JxVq$cNk74hi`fVftxl2 z1nOD8xdfZhc;|1HO%B#?Q+PtICAIr8+bqrO$ilSXoz97abM(u()#g+sFH4BfZanFND&3OHsc8eVgLMyW;iu+0xARN#%MX@AuSmqBZV3!Np~_A*6L zq}3_N`6ItrVd-?33<}-l0C=W3DXX_@ zy11$$XFsjFxd+n26MpU$Jg4fron~9Vt@P{ zo>LC~a)%WSZR_-H*L@;=$M_yz#}Ea?N-TkP6l`^MK)vhK zpA=Zg!jMRxh4MbKFmOh@SvzoP?DHO`N3@wyECI|V$Eef1?#uo=S7zfudf?bT% zfu$YL0S6b@!R^0uMPeQR3Xia{`Evwpja_wTUOa!RJfo>F$hqcTm0V`|M`%j~OAMkI z!z6*Max&L3HrxRZ9;hg8H2GGq1?w8H2~!*8$er1FW>ZuDZQwXaHVRR(gFigK+*_ELxjZ2JmhI05cAE1~Oa{ z#`t>I+`?uTCg#2;7C;l33jiA*AAVnN1dyniUrY*_nA@*2z5#Rw4QF<66f6&jsSbq8 z^J4_GDlfR9frk$|GBXpqA-)Qkd307gECzAM^wb*A4c-Zes~t!NutyP$0%H~ETOt}W z94gP!;PjzI5Y+hS!t?+F#1E7$g^Zt@{00%7TPcqi00%dZh!$MF5q$0QH_dYkAn{J_ z9>7Z4>X-BL^r>D9&E*%DwXq>keG_~AeQhH%c$&r<0ANId!^G6pR1^R)_q<++D4Q(7 zjXSX#u@pA3QEi{zLNq`E(O&>!yO8gLW8*z@i|dQQ3uB9WYOxeOo1cI3T4q$>)it2Y ztn4_STjUlekPN@`tG+uq$Er(y8yDSgA=4C>V$+^E2Io36g@y(vJ3z_EZzEtd!q1d+ z;A}wc%F4>lN*sVZV1N@F!@fIezw%I?8+y`pdPWX#e0t9~o?e(Nu$hrL7>KXHgG1v3 zC=d?rb^!0rFXaz(!n!&@XUpg7z<&8Yh&HFN;eD(7jjRq~c4FNT z+ytzA>M6nQY`@dMvotx?efDTtm=WJZgsr5ne`twIkxNLq=9MKBHG~gsD?Rk^`faYO zuK_0W%ck_$-~b?FQ=fm&`ln6}VtG|?_;);}LP2bmeTO8~G6SZ6Y4Wi8w6y~0TJO-Zg0_FNZUCT}a>p^hKmcUr!1ux&ggsQ0Y-j_Z#p~twAhP?3Jh1Np z)`oqGb^@T?Zim7565Z188Gyc_uE_i7va5;LH; zZ9`0me6a&LD!lxhLirZy)Tfi|K}?IhvjsW2`;UcxYL)+~ZThG7^QU(9pIVlGPF49L z;;+n|=nX=~*c^c5&`Ob?Ze3dir#Ncpf!!F~k);WQ3n;rc_0g7?0ddE+XXnHJJA8Z?&IP8C zmDQpCMF`9kGG~U*1gA&%ii}OP+4lu(x$lA*O6AKmFwCi*h9 z_o(G7m2-6HHr8Ap_@0ko<=ggW3>}-6+lm&zYexLSSOucNG|S132Hl%Xd1AY_o6ScQ&*v zgO%q^p}&u72C_DUCw3}d#z%z=PF%=aC5>h#zVAMgm+)SavP&3pfz z^)AGRkxd_|qYLn-J;24lAw0xY&N)89#KdLn7;vu3H*mnF=LcZl;oXM}+{GC3$%||0 z_r?qvUChoE$M<7IK)OZyfQV#Olv z)S)y_=D7(Wcl}`g z9aJNzoj_PVT#;qW^MxMU2a%cDLMT9pbbaDTve&VVj?A2vp2*Vna$bi|%8e%o0jH)o z6*JJ1KMaj%uHhAwT6iv~YZKPwbL-S6Q(X214Nh9xbW;mo;u5vF4Xoey7+PsFmUY~J^g7EV<>k85FJ9vh;Tc@SsA;VGzPwiT9jz~CGB-BQUZSh1Dr{B)mkzjR z)^;HdpmCyFgz))N3T8@?YKD~J!dH|QaTEF+6>N;IF!7B>mcqXn+qfqinO$P}er*Mn zt!_Y-eax48a+g3Zb+>;jb5zEDhKm#7CKC$ragq9oix~yhyH2)3(h`-usY3-<+xq2JbW?5K?Ur+G3h_g_LT{mh8LU zRs?%Cs}v;_5>~|YS%WW|p3PNl!TyqmM7%>|=bY>3=5P|h4SA~_8=To|X6&gwR*YW% zT`qLhfR<-X?)$||xJ$7VT%!SyUyGJcc_QWAnk;QUne%vy{suG;;3JD_m8n@0ZjH|; zJJ{dsDQwu$J045#KUfVMnXvGFCZ*X~Q#m)|`D-(%CX)}p_ASfhg;qy_bDx~Puapb~ z{FhP@bm2+^b)@+y828PF-Ts35VHzSGM5I~&yqbgOuoJ*}we`GQKrjLb(qAE^mhk(- z%0hVChl#&j4B)Vjk%_O#k;P&2rLl}b)hNmV;RUyUc$MW&Onc@P=~oHn34nF?Ukv=zq`++*)us@ZmBzv)PnJ4NTo+f0QeG-o*4L|H+y)*mja zs7~w9Up`zzelXC?EKCi?fTRaUS7hJOspX7 zF2iwc3x1Pyv9NpoN;*tPwB@T;(Y9NmU3uPbp)H9IATF9&=+ZLY{F(F>y9`946UoU1VW1nJ0}s zLqAv?Z_^J!%@d9I>u`E!X?jw^vUYTtDpST3ln2{bdLEs3NCH_PH`9-oFOZ`MFRY>G zBY@Uz+}u%7k=;V0FU{efl?N9Tl`Vq{*SChidejb6(WO7LkZF<4~AQ}l0&M$b4KmgEdK5V!8huEW|07Oy;nlo8im+OwTu@I zB+7y@bqF1#U;4O^j1BvJ1RD5EJIEp)(mNaxZrx&ZE*Ppo%}Be8@wtX8m0t~?K@|Q_ zJ1)EG6tqOwf7YG=L?+oYbI zp(<}C#!=q#lLt_UA{dwPdrgy3;H62_=|{TuPPwJrRtq)6l?(ztwwb(o!8^XT+hs| zlox*H2kc_2+VA9prn!>#StRyQIPrBYfv%gu$V#b$d?$Ixe8P%D4g%M^81WFrVW@IM zj)Oq&^_+ucC{2uBC+I5}zE1g1(xb>fdqLvczz;F&=74N=qjhJ3U}k3b3W9hjq=hDslZ!jd-orKWGXVn$U(N4)1)sK@7v@9X>V!hs zZc?hUn(4rI?0iV*&Up}A^E1qX0$t(zX^NF#+WtZ1LIID|_5spAMvNvkF=9^ZaR9GJ zZjP(@;aYC#DPT@j##w@pJ%&4om9IbN$_FOanP>@Z`7J<`nNqQhPkdE}HO`j_oilK) zS#cWLO=!E#eFWt#nXZrDpr*xECVp6wsCf}ahwvVNu1fxSUNiuHMBZIsTUnvR(o?%l zYo_zh=^X1HsbqBFGNWM8zlFTmfe<{G7+}zw8DRA~Ek~`lSy?lO&GlmF!*U@|Jea@3 z_ofK96duvymh34M%vi8NvYb0i)9LSSd7{;w1u>tKOFSQ)Z%9+RMp_T*PnqRpN5$@a zA_e3~&Wgrx+iK8r11YB%@!JVbG22WS+b<`Lg2_=sUJ4p&&m0+r{izcY#TW1(+37Os zv}Gj8SXx2eK~G!|iK%6DP2Sijj~>k#6syH+umxFuPuw(93m@Hzk+jmp(!D=J`u;@y z3o^YJgTH&9&=9x3l}4PM!+^|)b?3e>8WV-8S_Yq2zyrbSL}Rv~T)r^QVohc=8K5ir zlXA`_M!7Q!Hi`|mT)eQz>sYXY6?O2A2sZ)!VoDIt1qrCJ&2B}5y2(w6(!rH>J8qU} zKuLlw%zvhl1j^X20QOH`5+KBkdM}!PyI`ZjOYGG?`l>#7`pkzusJ@@*F2k*Q9uV4l z&C0|6O25v`FxRvD?9L3fxa3xk7EgMGAiz|0ioDx#^9)p-(F*U0P?{zHrqp-eg5mc{ z9l^c3?W>|u!jReF{XQ`IjrssH&(yTiD7us13yzV1q4;zUWcN$+RlIaY4C6=c{#Oes7(buTqa zOI*{!d3@Ow?ev3L1Nrg|<`)R_iLb$`?Efq{iiIkD;IG_DXBm(VV}!Z4dF)^Xk?O=u6R zxO;Pfs&#j%Hp}XGRhu}_y2H3}N``Wu&Nu-E70#*6mjqQ(=-aLiy&Z0J9}KJ^J1DpW z6|8Nt`Q=MT-jjOcr^xj&UUoQ>33}#IQrBRO*}Y>bv&B+jAra2()8QjBkXN00~ggD`34a*ua=3d5E}kPTc`pr0yoCQn5?|6=5!Z zB97e%5O5*2D{6IwuLlhNp!`9j?;FY!*oxDjr&9P>vj%7TZ0XZnoT0q$r9U{SlM7#|C_26@A?DS`;#oTZE|7}fJ&5a1qRxipNwjhN6^ zIXhJ3@nOW1!mvW8tl-5!kL*CW(qLPYp_AvFy$mRatQy4#0mbDSDA@OQq!=Uok!+|Z zM0ih$L%n)Bed8{q(r{2xt*njbJr*Ejc!>tAbd)K0L@icEU;_1Au^4XOHsu$x^n&2l zelfSnZv>~wq*&LN+AyaAkWP0#Z4?0mR){*&Wi;!z!N+_NfdPS?6%5(uuu6q71A(xO z#@K3=)#Yf9hZVb)DLLf4Q~8hCmHGV%V`<53Hc^kQIsm8*>2 zt6U`#;l)u-Ci37~KIGxihu|TNQiT;!dUd2~JxIG$`sG;9p-n@{NVaY;^sa1=L95a4 zt5nqooWL{trN3kuGI1Fp220~A14Kkx)3zr`HVzUgurFjk5%JD#L<{}%g={5jk|x<)qU*r$$Xs`Ubx0HmLQLLNW7&ULX2d*AGBXE6ds&Fh3Fph~Iv`q%l{;Ra zrCcS{eM3rxVi~XWti8%>HM-9dWVgujbuM$e!$!ayj6&^M0TMnu= zEwws<#VLddyzAWC1tpiACVln=(bQ()@4B>$KbBdo9w6ZnNEG>+v^WFiNy}ji)W(oC zNe9nc6przrX+#VvQ5|i~3EwDNPy)L|no9Ew=p4U489Z)#TT2`IHyAfboYE9CEOJOE z(@;n?rUh&8dU>I}$dGI2Le#Uj(AM)E&^zOgatG|aMdRdTE2DuLowZWCF5P_1j^HN} z>=mpTMR?}UxPFDMw$|2m*HR|?<w600OEhBxcew=WE?tbU zCuN=^JiZ_}4@wCScK+xMb0Yp4LjiWvwm=jyYn8V(K-1vRaNvwP?L+dyyR>KvM;=nL zmm{qAah5Y4-hb~7(%hzXawar%{zDl=48SLC*cSD(6EO04=9n|{ejDUzJ9UaQ1CCtT z0Y0JM!oBTHDQ28rS<9dHUd^gKq~Y^4X`L-CriTyL0~zX?>Bf^dEIi1EVA^?YKOcRQU zpDuybY7{20@r+=`@Q(M%WrGYpiQqvQR8!Cs`Q9WGmP*#@yAo2uiZs%2)+DdpC2o2t zCzXCQuf2j2p6AiFR-u|l^|kQO-W)}alyHP(A1aY<^JZZG+qpVuveb>SOhJ63E{)a( zd|Z`GI%f|l;89B-F?wfi&r1?X(LK>R+Jx20-7$D=hC@` z&BQ4b@qE1MtN_bqRUIvBM+Xzf7AO{c+1rgrjg0-hWl{z*?KrU{PLQF3sA*dLP9@k| zoVrxtTECiHjiM_B6?R`xPvkmBFrBt{!LS-;SGMrb`}6J6UIWd{K(V>{KEyzX&$T^ zv*ck83RwMI?bB(I6fQcs9_7w}u;JWnq6RMev%(YGLaK3oPt?SqOC}_K6*=!1eWp^% zcLW}xpUxD{=owbU(MS(Owb#Rof#n$v(9dpKRYzlcMlqU=PTBbBz@Mx)G4555qTnuq%i;WTHzs^mmhyKAa2 zfW0rMw-px5p>vfqQhD~S%pLcqOD$P{Q;7OF&AA*R$lDiooxx{%3T+BXq%Zxk&N#h^ z%Uu=p7gc6W^{fZAtfYx4kc#`Gno~d|&lP)cx`dN_{}I-?@Vr3cn#)&)JARu(hd;+7Zg&{cqlU!u_viW0 z3G^LWm0JBtWw5m|yxE{cQf|5RVxC>ve89g)Wd#C4Fr)vx&;Gl1gON)z?X`MWj;~#^ z0Oc67O?^?vfMENR<(t+9%;qWY0p|;#r-XlcHcCM}YADm|8`oVFvH*N8!VMuJO{j6^ zVucc{5A3(7-CvEfmS*ztXTsfzEK*mH1$HT++5$GZukbe!4#t;xmjA}sI|ug?v<=!Z zPVD5wc7CyK+qP}nww;_LC$??dwryw6^S-rP`&I4Mw^dy|-G6k=-CZ+PQ`3E2_qTKL z0o7`Msf{r}QJ!wry#=0L&RvBA_m~p&cPEMroRQ_$>Sdc4 z9{du#tpc;Zz@pgk2( zkJ9oMHhQ1;30!X5xcn{KG;`2m3ym*>hb}vMJC+`o_e1k$3Ez_XW~@Q#TjQH6YznV4 zc05il%U|vbmD_mp7P+abtqTN6rJ^paL*QLm!^}sgeYvZk3~3x?Rz>@GkpF(5+M^@dXaFzKgXdU1rQaPg!>m_ z_f>1EiuqGbveQ(17Mcd+HXlaexxUC;37}c!07)90y08-{K%9+<%1#`snLrp4Qsgj@ zO;ZMDy4BmZW9jzZ<`Ip;^K51t-5vf+SgJEBb+(Aj`izi40shX}@7Dv>bKjlc?Bh-a zp^-Ti-W1w*8t6>mlOPZb!XkC>hIhPDjVLM z<^QI~>YJRPw^~%~by@6Ru`h^|&{wYT(@X^Y%4Yx`{~}nk)BQ;uf5Wt|Up069r`h*? z^p7^a)|WvT!{HUGBVWXO8Xt& z5Ym1arG!JZJSO(;HX)%G!>Iis<=m{9cA)VAM^3)X{zddwlC4-Oy6rGmO#BP4RLq87d=9APNDtaVc$JwF)X_d%{u5S5nG=d5yYZMs!-uko5)0DvI1NuK8S zh@U2#;9_|edtpvi;DHMe>2Ujn!YV_i)8$U~fhwDPM{`H$FI+@v3<9zcaX9Bc5exL zM&Rzrd@Gqh4wKv~e;Pq>Hw&C&TYm^JMnYLV8sX(Tm@L|<-w~WM&Me*+y(Dqb+-T+5 zJ(At5C4oR%#`B${pPH7E5bpwt(aK*{2!+HTIKi+x!&%qNoSVo!OF7Ls8YT>1D=$1{ zE3*MA9d43TXYHq^E8lRFcaT-rQYweeSE=?sYzxURn8_N46xZEvosgT2FFevJk}9Ep_D3 zltH)a@%s=fK_xJq95Mg*w{v7A5*`53FO(O}qzx?!g_jp5JzQ0XkB~gBpk%zcG~_bT zrTtIn=FZIzmR6jhS5CRj_k!VtO_ld1*8_rm#GM^8zEQW4cnI&frFWB$aS;CeG_@Uw z^SL?or*mCtDTdCF`u5RAGkLGzaY)pl?nwoxp77RL$?izbnhKn%p1|M+Txtf~=T!WP zga|+6m>)_d#jPw{E!IiYDIP-Kles@gP8<#aOPUyQ4bcymw^53CDEe&04j z`P3abwG-45VqQmS1e0dip#Y{6MH!hQ@3ZI_n7a zY1(hdwJMI7K&~hnh5h=JLybvauUV9}5k)XUoaI&IxBbO~jmYSWqTq;OKc?lpwHL!g zXrlXy6SKPi6Mb$3^~mtze`@L~W}rq{m5Ux1i#G2-*f*nYmpJGf}Nr!kra3Vjg?g;sb+a%6%R_x zz3S6cFiMI(YQH1hqkn@f2HNm(E`)L%VJ8<2?>6*;-@^IwO-As%Qx@*o*9t%vjJQ_>!n#_3%we%Ocs#_yqQT9L(V&^88N zlfpMbZlv|Mg@;?~J}(8-ggz0=Glt8MMf%BC1`Ke~cnOriXDL{gK**-+|jD<#jNDH8>(OYbwG4k)ieu}|psT`c_kL}SHm`^rrD#*y=PCLfOn4yF#oz)g@M|rWQz(gyn zds~9lNH1TCUq!<4`So4AxGI-D#DQ1a?ky3=2}&ey!x76y;mbs!MFVJBx~UZB$21Z= zo(yH@y9-?)#>zclrJGvoZaSHIx;5ZqhqGGMa-Cch=A^ue3_g68R#m(~sw!;@MSOB2 zVWzapEz*1CLC@)6`qlp1r9;`fW8&U=_)Rk#xl`Ugx%XqohccEq2q_7wqGvov%p)N%ksDmJrJMAm-H2Dhlq1_CI{wlz)5*?2Zi-| zibYS#hHNzYgt@$WV3K`472Zq}i%+mOhshzwP{i)3qJt3i%(?&mz50z`e%cky%g{uQXRzJiJvPm#M44E^D{jVp z5rEzcaJ%8B7HvdS92Qz&x(nYdj!e~Pe)u35@w!+Pw?fO`dXUqMoRfKeFhDx7xJk6VG%ee_PXubXw$ z5!FB*&1c#vh48pq<;gwlF3j(|%c}Ei%HJamd!Svp44?ay1qAfe990ja8XN#zM7ebq z>_;0=IYRmq_(s5$E$&>~C4)IweDV46hrR!5-%$Q@~sbX67DZlP}RvhhP3)?iJ<8Eyv=2ZnaehnuWi*Xpj6 zlmL^TK$L9jhR4+-6@M_hT%fQ=5$$9Pu(2!rOPq%sOgZSR#Js6ox6hpwm4)>U>~v9u z#mYJ)Icgp(cALfP$`p;il|?1WBkiqCQE9q)%sy#uDfX~{_$3O0W#`$1@8;@lw{4P$ zoh;ASN`+a8u%JFgK~KVDBm#hkWA|0aaOWXkx%84L!^icbmWDqWN$j=9;69H%>sP4A zXi}VLs%Km4?`x#t8_pISn6WpqIk(IZ+>LT^(&V(FN*?)JaoK!*#YIqA$5&e%`n$() zXTL>VrTS;#=6SvZ=r#4GK80!~khXr%wpQAPBSnd>3T6#q{BgHPjqr~$F~_M+ zCXi7cgz3`er^i}9Jjcl{21}KiaOg_bljz&AYv%4zxE@o*UB%UH)vD*ddrHDstBEoxc8^T@HYNH1@*y+*VvDH;;Wq<|@znkEdXB(P`zwD(MfgmcVMc-Ca5flK5PYffTn0z!%BtA?#rT}u8(rGtlO9stRRgjUMtA(d z<%4kQ{o@l7t)c?qJWB<(*(Q$3L9L&1Kb8f3*-ldcu&U?rUPK|7Z-VF9FQ3JxTnEp8J_8w!+g zWp`U2+C1knF>{w%qL20Ue2Vlc#1tkgTaCz|Q-8@|M&snTvqQA46%v^<()ja)YC#?Z z&GXowoffw)+&`?->*E>q*SwzjiAfnaK`(VpM9987>?rw1d$YUuTkgW?TKP`^0n6Qs zt&hb_!3JrVZagY9xU4y!mt|aVr?!%0Cm2}9T9CuJP1+!`2Xh$>noJ7YnG^G&a0AaN znq!7jf^YfHV|#$vO=J;@HJF`-dL1h~TDGrA&g9l3`BG}tq6tRbt>iIEa%!o^6nnj0 zd@vHq)B%G!Un;dIRR5EB&LX&$!sioW@CUn>o+K{YS&cz=ZQim^{>Xwa66XDa-Tf8K zFv7C>A6g`RC-d!Z4aSN|;~#~0F9&1ec;v85J>;+M8SBFW-4+Y&q`v}((e3xN z8_&3la%SlBlsypAArGNq z!ZU)p(lRU1i_E9ziAYq6E0EN}!Y?G}-U~y;{nya#?kjwJ2d(1uZ3o)t$j;)m#_Qa- zSoI{8o<_G~m0sN3E-g2Z-zmY-I<{JhuIHwcGmkQ1#H|f%csni9DHZWYc!m}<$J%OP z#QlX9D;fms9+=13P3EIIC4Q?bg2(?Xq}yGvg`@Q|j<3J2t4}=2U}V*^^};_d6-7V-JcTMild=sb%W~;|A3ol{=CX*2xKGgxG6yOctfRdqS&Cz6Gtr zch6{KtvgsXAuLob zymwAHe7fe%JIJK#3g8`;#lz4$diFd*{I*Id7rGr9Gid#Q+-h(3@LBU$*pco4lo;SkVBY$HVbxSjie4)vx`OUDvM8%uj%#b|1`7A)> zPsE5L52EcLXb)t~2kcV?dIai=n=eH0eX0&*)p6#vk(nBuJkC+r`jPY)p=bL^tao}@ zkuurd8p|qB0y(uGPJ{N#?Rq}-KuM{}U;Kz+>%@S-Q}=T*EQVx42xwp6yd|u7XH%sl zs#{xAH>oSTkli;;Gwy^Q7qfKXEHAnb>-Z)I-iiFv-be@B?z(^u-^iEwt-bg$<%bH+ z_TOdpTs^=2^RkMY(&~aUF$?8Helj}4yJs$wADYISM*ZHFxHX$4Kd4<~13TFuO1&od zt{7GLmc+;-J{V3Y3)q`Qw@#%>p5bc+?V}3ykm{Cyyvc-m`VYVBxF*d8tR7U7`i*vK z2IwbJ^G`UQHkQe3SYRM|rFUeM)KtEq>Jlc$hGWM)wg!t0@V|P62CSFSA!$F}55bUZF zxj$&cL*`-5k_rRm;zgcOf52!Yxi3yISG6o~Q9In4JF8*QQgLJ?m(I)HyfA6*XYG=n zNSer+PS`zy6SEsxb$n#i*TX&NH4S9}E(B`%VmY*1Kcs--UP%-<#75$Ul=`MToXQvq z8!Ac1e6p-;{KP0h0I9oSQP?Ja!V`*fJ=a<3=eSqFo)csmQLuH+Kb1R@ z2f1eLYvMB;=FeG>Lid3~y5X=~`_ zH8#0Ha@?j`tdK2aGNgMnL?_O4(D-I4DSH9aVV&w4&A2KpLAdJb_rg>p3cCW)DH(W) zj*Qz*6VzQu61#ob#{IOf>C@GOh1l=%5$8DEL1T6s7)n3`-td_$?&<}DEE&oc`j6`9 z*d-gG@TYdfMUx3))GHNw;IO)rp04Oo0a(YsT+pE;yU(8s;@9v#cfB7g#%O6ZKDI6B z;+-4%WQFkguZW*w*AKXyzT2AYqMIEiumI(zgBCH-Fj=&{UA|@?s}ZsDq2+9y;^aQU z8oEg~vz7{l6HAvb&%gY|mW_Q0TP6j%A-jaIZZH8X8~kE3T^&#---HymHs?>(t8wm! zGXq2Ezn46alyWO)F3+zrJq$IMltT{Nh z(UO&G5na( z**@DQQ^-XPud;H=wbHhL5J&$;IByM!ztVYwSY*_7doxFSVd}vCaq8QoWKL+#P$=UK zX5q>RSR_K_%~nu$cV&Q!edp=(;O2U?#qH`<=gWc&h5f1qg$v84Qc#MDTK|YcZOc@U zo=T>LCFw?A$iac+el)(gZn4W9_EL6A<0bhZ&7o+BVBuwTgT&D?ZuUcx;fM;) zJ=m?lc35oeBRdp5$42V*MpEt~kS_D8@TZ;7x*@E#p%r%>v`-Sk_Qz4V6R)l&8MocfEY z@6N2vGKwYSpiNVSYh|P2CUVIcby)qV6vT(x0?oI;LF`-eZ-Wm=6SG7Ebo0+Zeuwir zkqD6BiRCxQkZIR-A5BCB85=evOnb5^LhbYXah?*|&UzZ%cW$0Pj@3bj_{x}zwMnSh zx4sy5s-`q&LRcjjkJ*1cf~GwWp6D}YK-kHukc4! zTBh6|$l~2*b*K-_B_HZv6hx$4*-3O8Vjn00Pr`$9#*@e*+wP4Wn_ z69}IOYQz(Bn|_2SGFi246ge!98Z#L_O>|n3%|}3xISWw?YTyoNYTLE+IN%867)F@6 zW&Ti?RA?tA0eyd5a3oq%OS+SSs=zn-rly)$DwPs6f^y>&I==7?c?)qEVa+pxrZ9$5 z^y&7Ah_J26rx4Eb=@%HZiIu`#`1PTd72n_wLSw-hIRJ4p#TizlhR|stxj9C@ewOpK=&TVg5 ziRQbWOcn6qVd%W_s(;noxsNhLjlw*ruGNK#9jV-L`*(_3L?6yKV+PgHCif|{9YoGp zI(h{A+J*wEl>B!vQ3leICp9y)Lzrq!P%jCNj1wEf8L1rOfWq!5zIow0Gl3cH(M|Yy zM%L?d1)jny5&8JE>j zZfST7y(IPt^DBtU)h4{lo8pH$GA{{WxNp8oB?kY7mO`v6qddUDd?b$=kp$g?ZesFn znK%ta12JEKVsK#T0t zM8=ClfI+IgRuAlg8QtFvUyBl9&B|DN!LBLG7#BU4z zlZU=WNsX9J?RD_$a}59)XX0y4NS%qfCe@`)!N(72lSq-|Tv^@+ZJbf%p>O1lKTZtz z3*VsGEJ96G&lv#P^7qR$2Z;!Ok#SKr>1mx`;>j{Iy8h**xg+humGFt7y@mc6XJ+nn zafJ~PStZK=yC`pJZW-CB`h52?l#;!O!GsJ%68Z(LZD%elEY*doCN?3(vxJ+GTv1Jo zLBuv}ky1X(YFR^UyviK<#~F}9kc9a1hFz{dA39@`L4Hn=(7E+Kz6T+ly=S3H7kQZ1 z40j&QEbs3##9J{E@-#gn>YNa6$D3Xx&NTxw?Y_X=I%lM*51ceEQFf;uWagP| z)nbX-(eD;jdqd)>T}_e9eMrw+EOlNiwpxzHAg7A3th#QUD*OeHv!Sf&Q(!vEP_vd@ z0AwuTZh?agnndKjInTX}fT(SU#4U_wAW|uT2F)+sDcA7#1<4e6!+kBMz!_x7TKp^U z+%aQD7#$-VYi5Z==6}kCMtILXp4_XCV%ycu^o~0=g7^yG2Jv9YCnGRn zy1?GJr$er!K?hNu?hrHLQNi3Ahp95X#a-RY>Y-FjR;2fM-ZBe$bi=%YB!s~57x5ytw#R48eRi?~F)$Pfwo|!wl*FL3^Ru~sR9l7%I8ot!;9Ntnjx1ww3q*!N$wCf%-GJ)?$c}j`2z&PYW?zm!ty!(H!}VI56c%76&4Xv z{)go&Dg7tc`Tq&bXJzc%V+*KM#$X2QOU%a zfC3-@5CjMTgaIM|QGggg93TOZ1V{m-0WtttfE+*`pa4(=C;^lKDgaf08bBSO0Wbg< zI60d*S~yt&3;~9Y21ZsU&ekTT&i}LR_#b5ezzASuXKiQuuePx<02l*|EleCuoGhFG zCV>BP3II%Oj18R30VcNpeQ`IkHn0Jh0!;r?ECByiTulI`)&NsG7e{~@z#L%iVQ+3? z3$OrK0;~Ym02_cUz}CXn1YifS`&ZllU*rP+BDFIH*ju|e0UQ7hE_Ti)#)j7a74QG- z{CB|r)%)+JBftsZWMX6S-!pJBas78!CkuCgll6Zhb_O_`JDQjP{-eov0k{I(0PX+} zfam`~ng1VO!T-l#@Xz8;Phe+gNx;qhKg|RT1PpBK|I1UrNWjj<^uK!lyTE{hotg3f zS()DguAFRzO$UoC$(G3IJODIL_|H}V3d_(7MmZ0a2tq|LPmmKhzcsHjPdYCtp5u__ z<@eLG%we^h=~2U#cM*G{Gay}4H9~82V+*6`9M;?R=I(C@!~w^{!|Mx#NYM)lc5lSQ zbP=>yo!@h`IvGkp0ecCL^pO^VgK7*aHhyTcD=q}*2E~uI_iGmg=oUKS4mt`r0LYg> z{?SgztqhZYdl<$VVRjd|tX+to-rAJI4MC4$bq+dq^5KQpe<~KYmz;`f@+pjqe;5u7 zd}ECt=r^l9c|0~_QBDjs|I8LVY~aT?IapRO3eGj*@WjQ{KUU`e;=mz{Q?kwpxUTwfycbion5s1z8D6?5FrpG zeht`@>Kup`0r61I=!p-m703?_vUgO-iWu7Y-MFF+AXF1)AXf2Ezq_C{fj&HYOa$1= z_bB3<8v0R2YW~Zk&8+ViJmKE^*Yq+}~Yz}|IXZRlTRbp;; zI0Ah+FmaJ@0Cq9dN6RD<7$g)(06)^M5zr_K(0!fL{#OeB&I;&bSmI3@<``k`&cGJv zu75G`FCZ@ec)rzddTan95WI*#$mdVhE1>`Q0CY9zY8OZ=o)|Omi;Ghc*6|gE_yYm_ z18CBJ^zHx@$j|57qn=+jy^Cvb>80fjpY}LqK`DVD@#Hh=o=;Lk!wuh`uLY6MKT9tj zfq;qz1Q8t-80?d6k`Mef>l0tm2K!bo4D=hm48*}6GW>fCSfjJY!~Kf|)7sAlj%&9E zi+L;I02ZY7E7#X4pI{dLZRq8v6V$Ku^C#xJhT>=C>}Lmsl1N+UXSU(X;`V25qcuRs z=ck@OmI)+Q8xGFxFp&RyWfAJ}gxAXdvJa}|XQ{l`CZ3uI)WP|yG+sZQXcf}91}=1i z^e8g8i&cpe&HUc{|%z7=qGXBw=cRNY&@SKjXnxg{@ zRFGBv0@m(T{=?uqm|q~DZ}D1|2={MBt-zh!h;Hoj;QqxJK=$@whCk`+>E-u2M-ntm`2L2m=U!4u$Re*(qncKrm9fNCy!2pH2g>_)?)Vc#%>MO}X| zgcWaJedvufxZ@YjziWza37v#~z!TaG{*6I+?IB2H+1Eq#K)umF_!H!z-h zw^BzOBwv&!S?5>9u+-jl*sW-mG4pp$?N%ZE4sYt467Xgls&+_wP}FRs`JR%{k#Xb3 z%dIHZ0yE7Jg!FWjVI-j`MZ|Y12x7LE!aj$SdKre~wC)R2hrggwQa)!qTXtZwj*Fbs z!Q({Y6cS&`XG{<%UX)|HB^AEG1+}BUa>vj}h0$B4gp1Oq`DvYHIA9T|`lm`jdN>+9 zw??+GlRXT*PYi;L9>dpBd&;?0f@TJl>04r8n01)XrsgWa!n^dX5w7w5b&$(#D$qFh zWYY$b;ypp*sxb|XQHEB_!M=p})=;~eNlA$lWZ$x1RjVP%8e6HPvKXZfWN{(3Des%I zB=}5Z@l_YbAIP>$^}Th?Zw(+-UeD;VX7k7Yh6vpwpekL!nB@N2dJfHD9FQEFaVN|n zdk}S1KWW!`_U5>NL%NPL#PeOPxHHt)dHy-xnEUsRS1X{NACyp7<_ojzk$=zArWrwN z{o$RcFjna(I;Y(nQ3;Fx^bQ_nFirI`)RbCPA2P1ai?<_M&(O(`O&>qn0Bn6fR*tGtUic$c9(|McD@M<5Q*fAx~UdtH6hUiu}O8$tq{wbAMNf1SYs|0+7S$2b^9$n>dZXOwNsD00rt=2 zfr_3B`?KR8Xo1za6A_*fCm*G8B7!WD#Kap>0cjJ#7b9_(=5_ifpGBsNP-EtTlCY;8 z#vSK>Yckj6nNWcr^-+Sof(hx!?uq@2d$$s2r@Md_BR+0^K~1HoF1+GN7Hdn*NPP73 z{K2NciZ#muuZWjL!IhH;6YY2I5{zhR!9$AKZI`B5kc0`EKTG!SLj4Sw2s=&txFEyp zJhoiii=l1a*-NXBVPc<=Wxr_mF%S#7ZOj z(<~&y>zI1aGP&9!Q^Ti$8zW(YHUIgU%d1O@;ak=RfNIPp04t~4vBWv!dZxSANRo4a z&!zwTV$JHFfg4o7P^1WQ?L>-vhCE=Ez3h-Vj58Tsdss>hbcNY`Cuw#fR=tQwNj-MO zo;N9!fS=ss_zgJE#?k}qQg^pKGgF!J(moV(4i8eG9ctb6lG#bc=dVP144y)6>V5VW z=f6$kmh79V%M-GPV7t_wXW}82t&RgkO`2$XVXQ|eEWp}rxO^Hwj|UqjlL(|-tXIrK zDtu>0&dR5Ylc4SszCdiI^}s}pWoXdQ)4at@7NPn9Q~`;%(4*P^U-J4hRTmkw&w$LF zWtFAZaSGB0&YL@L^(iU1^?a(HO>d>RVOF&i(h7gl#tli>EAgP$%Rz5+#hWtJBBZ3% zxOuKk^Hc+31S|h>;*ZTBFI@a7$mi~57mNjepK412r#fiK7s0BRquM%{`FH69At4$V zWz~wSiYm%41}9~UlimTy3PH6~+uX$TUdtiV3}DuZk7c40498@W7z;%_Z`AuFTpW+c z3(!a38(YK>%D=h%sV$c#<@hH!tFSGdHLVk7*J9zZw@=n6LGyEEKmc_CtyQE&Ur-i&d-^%G|$g9ii<@(&PH?pzu@O;(-|Dg$J6>2h8PysS{~? zxXM&?Zj*Cq^nf0Mki8`9eon>tNl<(S(Hv^mghHnXZt1Sp`uO?l&7%ka1#DayOH?Pd zVIhuq^fie4S?Gjz%?`)Rd>7H+hvW!;p(45}UMkcoV}de2%YyrRK0^lITW7b;N| zo3ji2G23cul6B#l;PFxt`^pDL?M-U&Wrh#GuxFQ1)dXtAb#4~+ zuO(@p8PMX>61_nM8+=k4w1-NRgXF-@rQ_{31!fFHUZ^L)?X1}`!(;|_o z>~ssR2MojKj{Ovk?v~3-%J`a4k^MC_7%c=j{L^E)VRy&8zOjWZ{_AiSonJkWrj-fO zv3V?1Mkxr{N}gpMw1jHOM0`6+U=BpND-|P2o;R#?xmEU>oZFF8Q@lr|8CLzc$mKVd z^}dIUe?FcTEPEbnF$XNdSYw10-@^_{JD|dfXokEFIB+lrgmxb0sY}3HV|Y~M{zg_2 z5rOd7*kcH?=|3H?Yq%>QF%>(!ewZVn*I*GXI#cf;)i~<`wvvqVs0t{*GSuB608sfS?hx*vm2+55<-un(4$bD*dB8rlyy*qC`tC)G-a%N@U5ud4) z)emyPF1o5;6)n9S4%iNuV1npP?e;6Pg1VAv-W?(f05NTmGb<#?Yo>HtWvRZ`d=oX# zM<)(Ut%|O>JhYqD*LS2$i|fuKGLO@a1~ z($h%m9EA+Kz~_~99`y11jvZp)4eUXV(?$gH%mgw%nn%q*6-5#dUA#)1+vGnAH;*J568{YM zwo0c?BNMtx-I6>ris-Th=u&e#y?5G$3?M!hL>vCy#F(&AJS)uTA?JOVN+69q*|Z%3 zZuq$v!yNDEZE_+&rsg4ODijiTR}PUwnFV&eu$vpXwV_d{kQQ*NU*_fh>!KvjIIweGnxUK? zYva6;ygDgJ;#2)fEQ)imWpJVe5&OWS!6t0N416lFOkbT+2T*OE=gm`Sv0gl1XFOKe z+%=M@=wOMf(lPj_gR26G zKq$34rO{di3O++{*8C#=-0lqi$=Zz4iK zyBgTs*n1&+f_4ld^1{J{?u{ZL9lUU~`mY3Xpyh_=hw)e5H)9v$Oq?CF*{FMEEpYM% zw!|~kUyMYd0!O$t*4Hy?+n~A;&BfBN!b9EOrr_b+4mPuqti+5BX9Xd!xpiKW-L_C#qmY&>_gwc8iipUs9QW zEx41?#+|+#q>?{1lfbLh(n$;h4Akp^8-pCMR|LDV1}aXWE!)}U2x5IrBh1F8WVE~g z0&sKpS}InwQXwltD|}W?hF;|fWt`Ag+knSrG*S0c*q^KKU8woP(F$#tVgxMG${-yg z!tm281xK8CIQwS9VLD+GG1xR9%VaSzB&T{A)=$gC-n)F8l;xzRb;=j%$4Eee&R7$x zmvZqo^yMiBX}!R;Eh!-vqmFwWj7_u4+pW(Wmd@CROty^UMTYJN8ymEQ>dVJJ&Y@@*_-NS-eC5=5wCM>E^;5#{z` z7SN{TZK1sMTNK0o`!wp-XAq_wHG37h))M`P{BH-HZso+0d1g$!pJTm2oIq@Jc{!?C zu93OK02tfeVU_>TP@MmD@lf+F^?a$eRzsWVF)+c9NlUIp|FGsKk>5aO9Otmo6-`2TJV@X@l1t-__c|F=I>js}&E($3*t_0rk z@S<$k*5zBQ!yM=8vX~rU&I7&-brFed-ShHSy7QL?1S@kQCh(kODCdPtXhjZ=GzYVq zxJA|p-gJyS6n+~HKBBP7?v19?!{g?V@PVTSBS#fO{y8&S#OP0?noHQyu$F=UsBt=i zZ)UNEw>(Z}&v{ySAyVvFIXyM2x?&RMUKp2u+V@i4^7G*9CS+%(1LSNK^mXHslqN(C z#l0c16q1hqCXZxYdckpD$g*bO(TWM#I4~d{OT=1vbplAA36h+EHzKIV%}cO(t{JUYTPt)kuN`ncIe001d++Qb%3V}k8b@LM zC1DO`b!%q1Ki0kQI z+9v#<5~1Y#vHWdFEBKRsk3{s|5jU5sV>A!^i8mN3Nx+{jR_kqGnf*r|ZQo zGLt0nvV-d%?QANdu><XQaCm%@}iT1lKX}W84ngd%CvQbyc6VOwh z{Z`mbb_h~JimWgHw(?Pk!AzjbbJsVO;Tj4YMY1K3)n=D@@P;DZlE>e&75G*= z)*=dS`*1;3LdB2v^*{dNJa62;l@-i)9k0#2RRl2S%z!oE83<#fwOXT0Bup!HAJcr4 zwb5efJsnmSUSH3rnE-7~HuJV)5~_M!Jy5#upXdy)UrnU9h76pz1{n7~snj(GckJGf z#6v2T(sL}+wiPgWE}t;2`Fd?3dV1!K26nIeXwXL|+IvmWTNHaZ%BA4r%oG<_(-Wgb z8)4sOI~wT_e=nZY)4fMBSB>a>CiFq$sp@-yd(UqvC)bJHH@o=f_J(lGo<9~p-qlKX zc$Bx~lq7-$5p-~fp47u2Re+iXH)h}xg?T$U z#MCC+?EY?Nky!ODR{6Z=&YD>Jwy+@T`Ce~67a8qW{y7gKa%?QVCNvZ}dEhM>sM$hv zi}s{j^&&61{t63}f#X@ER8pU8-8&yyZ++|({f)YCPm|{ixW+-h$cu)ODQLnXD~ju8U7NO57hq32%h8$Ls(OUzYbsF!vL&HjkEfhGPC@l* z`9QGSaV;k_)X>7!4Kfo6O>=*^9~TU(!7?;9VBwB`>A7|I>a+6Z-5N)9xy{ivZ|k!t z{I{kKeTmUKJrs*wsDckr0?rk9d+umT=)7tpk#_(27ds+CEnHsGYNnFRUZ5oI<_S0k z(7i?V(^x&B6MZV#L{2Io<9hp!PEkoPrC!*=<)%NCy!>l(oIs#A%_sTWqSfgPZM_4Sc$C@9j3@H-UUvO8BmE-}l%; ziVU#ddi(XK!|;^hbOr@&hsUF7ZG)lj1N=GVQ{NoPgv(>q+f2#Z_?CT=TKb=tC>I%T z$|D0AMoYSsxE2VYW1c1W!^pwPVJ^95U|2uj1~h*Y5Ipe;M5 z+Bw70w}}i|t!KKV&y_vfAzlyuBIp(S9h5gd?XrAFqfEr0tq%Uqq_D3|S*>IH+O%)P6%12U3zf7<0QW+uPT8GayZ%vMeh?~E zIq))T59*XRJSn`AUy@`zMGVK86C*Zg^vUvD7qSP#^~o%C{CH_#g<{xJf`4I{Bt0O3E+dX!lOLHgeD zl)pIK=7tyoZ*jx*9f_oiI-TG4(n2yTO9l{z&}pR?zn%;+e4z`}b=+!Ii@%OWxPP|T zNPkV)OX($z@mnE*Ep$u`bUAF?8ki#(2QDX7DAHNW|q#Dj}hr2uEj6bn6_1O4^C$Y_{;; zcrT6)gUc=Miifb92v@YCVuo20)suRPFs(mRsmhnhCWdQI+6ZW0e#&M!g8 z@SkKGDvw6Jh`~4lv~eG6wcN~L9$}CuIO=fATO=mT+b*q1F(zB1v~2jJv(%d#uchoR#kWgg9utY{OJGVHGjSV-9^mYKy3R; zlEM*WD?&GbwenTRbjmS9toMu69~A4Vfl>j7nY`r@)JCLiByPQUei|<}WdjN^ykJ$&0edAd&d|`-5bT@Mz$JpEC;#FW{@;28OV_;NV%v3zqM*ixCO~Gu~wgh`{PMSjC`eBB(jB;i~^Z z+BwFE5-sSqZQHhO+qP}nJZ+sePMfD~+qP}n?tXpmeKWa}%*#yj{?$$@mD*L6RI1k6 z-$w`-95riJf>T)LULOXc1->zip1=6&OtHPkb0b5E)fgG-bbA&%PCwS4g#E4zE<3}o z88OwdWkNnnS%PVwa?iwrkgJT{oNDURBqk&5C6g^%NTWpTAfYm=o$|~Cv1|E6Hf<*| zmKWr0)WEo9slsMxXoY|OC*?3IwNsO>q&yZo%`srnme0?QrNS)}C~Wk4wiW6?t`(X_ zk%Gp2;KQzUpEtifB_Drh5gzpb|0lKz?`fNR>y@bF@vL)y|E}sdMm0}wUmVTOka>f5 zJI#e_^mI+U5zboN?#*@4kh-< z^u=k&m(TrcwaBP(V;tByX2v}!hX?P(WR*IjtdFD9lMijnf8-YjU+t`!Z7DohL)06? zIpra5f!k(}j7mb?zA&>`2v5J)=E&;%ujA7+v)WCfEaM;$;Ax~d;j;k~?UGgz4&v#$ zZ`19WSarrfht0kv81bbEzYS%aa4tSp*dO@VG1MEP={}Gf@XXp_jd)ixu>aUvt0`rM zZbH6ScTq%@BBEpzq3k(xVK<;r6>3OMbgdPfxg8O@?lfIlF?`B(L~E5#{(dE#ip2jg zo_XgyL7fRX#1^Ns(bn~cf%G~9Y&Rgf&@rO2-X!%{| zkvbn%rx{FY^ct~VK|}sowW$IRg;<0Tq^!^m?}1oki@0Vu)GM~ujDKMgzz-eGGiD#P z^@N>v_(7mqOgCf7kR;{WB%hlw^7|uOq+CgY6B`AO;HP^n7Q272)w{xTZ z5%v&-DQkq!$rpIps?y07>Jk8mrL0AEOksG7a#8P6rk|1Rm~!UC97H+vi!T z5rrKsN6~io|p-k&&Qi2AzFgRBY^N*>PJuMop+Pmxn> zTv>QAY0{DhQZ37P-sckypcD;Pd%+%f*Hv)i;vNsyxHWAUrv;5HF5)lEKTiP&xq6hB z!H)pd5Jo^oliuL$#3`^o@>cZ~3`K7}o_#abfnod_>0`#kK#aurdbt885uSx9M5??w z(L{UCl{5IGAp1By=QG-jIc|^!gDPfzEnawkzXyVx`k$u&4?CqJuBi{#5#{8g)AHE$ zrdNI1L_nm-MvC9nm)CEyX|mU@tF!o8h79R_`fg(6A|RCvBvemRJ6P3nahsuZsQo)<@kB!@33(DANZJUm8KWA;4H6t@%A4TsKvMaJT)o`_=BD0B{oLDLzo z+^5mHu358P@Z*LQso4jYE|_K-AC0Ix{t&kI)>!velfk#z`BlfHSJsen(=FSgVa;vo zbgm<3(-|+o7OAiLp0Q8Z<+=9cTJ`^^lTU0fwRq0gDO+LI8d_Ii@bL+P;e?USg{h|r za_TS0bvMJA_F&X}%WQ9*66`)TX?WrB?(oUZ&YvmD%D{xugC;8FA7!QN7JzoZq_>#( z456Ul&)S+2qCVTsE=*^UD|WEG>l09k<7Eczvo`VCFTEIEkJ)64DO^u32Zxnnx5T~~ z(0mwV3v6}`Ut-O7(&^cU#*0K(Y*7+VGTIA4W695KG?`!9?^JzppDh5oee%i#g7+18 znr$h;oro1A;lp+OGYf}G8lvNRn%stu$Gy;JSW%GK8S=mlG(0F{QuJ}A8l12w+SSy` ze?BWJ#1NFK_(;dyCAq{E=hC-zf!f?4uVJ~n5f5fap$N1By#QIr!tQS8vd8BE2@+8HJFA?zxLgR zGMa9~_Jde24Yy3d*+K&@_mjd0cMe?HJPH715{9W`tq51 znY*GiXTd&B>tN}IgO_XKlrBuGY!KgvhZm-wqcgyzuI)z3SelK)J-yw$&6{t+^Q$RO z*kcGXLRpa>NmY}0XXt4KXgJ)jI7(F2I{aynd!AyH3}P)jtvn!GuMl0Sw1==V&Wt8N zr0Sh@<6s4QjD=!(DtN2LNjr zpdD_?Y^H(VtJmd*Ix|WxzZLJHYt!`mmCMu(db(l~8*r5J@ExfO71jBo8KdBnP}&Bh zc>}gmh{pAj^;3I@0#`_xLro;UzkZz{x)~Z8c2C8~6%**O5P8$Zmi3kzte-o#{bZ{i zY_u>8F73ov$yy(oGz`9J3e8kR18tsTVq{yaMsN2`xNlgbI65qi2k7{=3?*WnYeef{ z8BdhqY*Q}DTo6%=dKKQTw~W!xWy`M#M*f9)IwNd*-4F3lwRi`KOqrc?WLLkmZJ~0I zFKb`Y!a>>N?-JY`d{!eE28}6?y(Jqq&$88Qp1*GdIcoyMv)|E!vlR%BZt$~+frnoF zYp%phoYU^;>MHX9_ST~#+Z!PF8WOBy-kQi-R`uo-G(D0CgoYRk1(b?+)@k|`T>BqB zscd5pG==hn*3z-Vb2}*r^J(;!sOuqb|eY?l_azMbNX$sf}kM;fi~6eisPpZ zMC*9pB#boBi`ipW#v%}Kz<2yk4vLtX5xX4q*EN>G>Ps^CoEtp1r8vv4390i!^)zXH z*NAeT2DCr_hvlMOgG%dk^gA6G+f6Hpu;!vZ| z8`M-C8arXXi2)riNg=ajyotS_g7*;D5Km<-QIPC91)1T4Pt}DV@rGKcz4*uz3EMp2 zd%-J^xfpB0)FJS*-7IscVfNN!Xgm%de66cp+hIaIx9dr1XfBRumNc9eqB-Ty_^`wPr z7R|o!9$FE*QYkvrG#qA+rpEBGjXU238qp@3kItJsUTbS5h{%_)-ndqT<_9Bdzl2W5 zJiRxoE9we$SDb9^u{I{r!>6+mWvlXZ6n1R~X!m13>v{Erz~M+X2VkRTQ}}O;NOs15Gu{3tBT`sdQczvwUq<9ld(VGs zL^A!uh-4(-Was!XB02v5jYzit!H5+5aUrGt={_3%(`EdZ#c2AYAzJ=l_t5?y%HhB4 z!hZ;ZE&-vTixrkZ*^dfQm)A#$Y1|ZYFU6=ppFk)n3{h9W^Moa{3%>S@D z|26t|1CX8h=Wzeq3L|$=6&2fMw#uYm0W4uxI6^{&(rt(!U}gbvbrvMcIzJLw}05b}}Ljn{{ye%W{1X5s7XNS2; z>*fOlG#3<5($kYWXy(p6gB0z}?1kt7h;|J2+LLnu>jz{mWQK`^d{Ku0BxQ#gk`~n2 zn4Xr0xrjg$&eur>6$RkO7=mR8$cq(Sm^u{?4cPqK2s&%YX>ynwv+C?8zPVJ1hYd7R+)qg-7@}On`A7@&KgcK$6?bfKG8G8Y&v>n+E`P2n;*)RkF8@lwL>z5Xfl^K>n8+M(|1A z1qa6URd|RMAM_sFhSZ^+98%)L>+7p67@Hmf2@w8e_`}_QaFVt1v9dAb+u);FP8RkQ z-aypU6hM&@6H-7)NDbN+Mt7%^WAX^ zKi`^!-DvVsVrT#b3OfKyI_HiFFagN}wiF;|-`)*Bbsiu{!OnmV4?%$FB#{^D;?>fC zd&S+k+X*moPJ(Z_UtooYfQ}n6PjP`H1hJ07g5SXLJ%oNE+jree&QF4Q4%F}7ZVr~; zq~BfmxeES&nOEN_3+s&vy>(5_9V@A#a!$?|Mu+7upA&7oj7=DP=HqJY-csuthdUQ> z2p6M;F^8BBpNEQrG=90oiho>kIrsAwo}(Dtuz05~K8Zks%XPW739S-Jm@PLuVLqo? zy5VQkC~~eLt=^Sr$YzO-x&|&;FX81h7cAS4`-AZWl7}s1p32EZ5&yf6-jGk0Q*zsjaJ0ONIFD&-U|N%EwJFIjC_rVzN|EW#08^ z?GEZ1Y2b#|W8zXy_-M@fsJl(I&_!*JOn;Y9&KK|~*TNLw#pPb?*udY82&$7kDU^J1 zp!mFr4M?^;3NfJe?FaibuU~hhDl8)HzXGmJ-|CbG$95J(B+P?ThoeEHtouD)KE1Xp z&o)rVHjMXyu2C{l@1DEG-RhNrf00zWmLi_pbgKqt2Sf@@9=ciX=Z|QY+98Y|yxyzs zJ>rDT9#IvG3_rGmFR1@PH^6vb`{%T z^F@p2;b_D)jgVI$c)Y9&_x%Q1T8(O4I zC8S@p@YY;Q$F^P>5-BHEt{qHKp~xRxfL1@Cp|qv1HOWJ5?2Q%i1)F(&vy~`0{^g~y z>ld(a8zV&zQ<2pH>|Dt`VoT@D&Y+DiiOj*b3-cGjre2$@?PBq__YKiHTKxEuYZkI) z-lbbI`?yr(ZP!c^?}mOg+jf|ZOtd;20)nImHJgduY8#RN$bt7civ!zaN2H>#GV6dTWZxRHU2%w?Aw?& z;`}-2w(v8LYy)=)7PhL)Lr)X68PUFIlvq}FM3%*z9(J?&8A38PeehjpnM_HaGEfl? z=1JuIP?+kXTBh`$wXG zZQ^cjFTdL<2EfaI>~(eCpkn2bJHeKCmeA_Ojpbw2Zy>b)=?0?qCFeMv<6(y{sy29! z*D24ENg-iELAD?Pl()Bf$<`cfx<-kutZq!)KUh1oS6_SgmFc0SXMi##zU?XnlRy%m>e)CG2 z2kj>o^$DkObd`H4rnwAV5UrtJu1X&*f*Y@3HQTzzM#$uewc0LgWrNY8P}e&bLbrug zX1|CBVvbO4p_P5ilHS*}$QDSG#c-y}lk$8}EdI}&T4FP*uyW++;P~$h(1FbGrGQpD zO}k9y6Bnt%Mo^@RJAvq<2Lg9bCi7t|`|ia-g*qXRy4k?2(HFZjK;}TrhRbZF>WrjN zUqo7&@$3)E5UJ>9iv-q)WR55mB`}#?MD2=r*h>6nPuk_j#Lkn;X}frx=)TGQf-^Ls zM6xs41HUazTHIYDVp(+!nH3cdrmR-T2EK>4G#Awcf~IMoUMhhucBbRkC|2Ebv3qi zh^q=}iMHEWDxypGR!uv!(q*z!oC{1!?(&3m=;V!{Es*L2F&*cQ?K!n8y9qQ)Bom5n zV&~lHL<`)LEXmpu=r!ZPiA`f&+(z@?UH<70vRr1hlc|(?&Rge^hnYG2r2d+=?V?J@ zq*b2!O|$~te~%7rQu1Y!Ta0e5=$b&-?q9;xRp;5gl@K=kbN2SNw6z`yt()|nk6F^Z zYwo-`%e830$%ew2=xF!2p@p<-Ip9=Rz}wEXFtxJ%y|CP)*w-(Lc_orL^}RN`*=BEK z(mV8cyfk3nx%Lr?jhi5A(|o>p>@xIsNQ`7@RKBok#9hc_B(t7Ikfki7jvePFi)7{2 zx9Br>4$oZ)s`z)SpF}LwW9t)phyQxv)njEy)ac|Kn$igowVsw-<(PE3Q|JKw2Pio4!MQ2NQ1i{1gRZYbz?wtLz7vYouXhrU3;bpp-uT&ki3?#UP`BR#*2DRE$$BU{G9Zq z6{6kaboN5`CyO*oS!9AIf{$3}r6Z}gZ__zGDWmL;%yjof3&n85ms?T1rl(hCT1DqZ z>!??^rXL!f+m)vk!4>t$hjM1TsMLHfUlNDuLnC{bgpOu~ zN)-R3Q%>9|xs2hx`?1YKlyimCVfORUOq`h+H>(-$etzg}F)HHxeMcE9%QNgxtRU{` zl?mO8*DA0t+a8Rg$GoDjYdQWD&E#g>I?kL0{Q9gZWEI0r2*|L>kOrJ>w3&hubTQSxE*At|O^8Y&;@$m>@Cy|8eEI!#EldVq3wse8)r3f_X> zN}en<_Fg@<)Ejy1*fMqsYFa*b0QP8jP~?BN&xf^C%%|O={g|}(QA?W7_efB5WXJB- zy4b(^WVgmHSu zpTgFX8cx{eQR$lpqPs!;W9NnAN?2og3e~FUs3jV+geLVejfV}b!^J&5I%X}KLHsQ( z;tIMqFo9AD^HJ3vf$ixlP4SlpwRbDe>?NA51(kE2Z|Yq8ES&hLM_%1#3DL21d-9tB zsOPHVoB=Ob3j9Gij}cT9?SZX5Mh@fkY7p)Rhfx{+1L8^)^*}>+80o5Q)j{=3FP}3d zw-aR7>1bF-dO*c}&QN6Z{d*A%*!f#2=vL1|DXZNv+z3}SYi&or%S_@^b5WN0qsbA0 z6$*<6;PZXU3YO;DwJWn+;)Xn9>iaYrT9~AMM0AIv{Xjh)V9{W#mWjH}tdn^&Xk!k7 zH3UU-%uRLzn;Y;8SSc$a9+%~BbUCW|Qn4JpcQQNuWhiBxSq*r~QxZ z>Skvt%d!x3mYJ~G>xNIW>eBJ1SdmwoeDodto_$0^Pt&!H|9Beb85TOJe|$|Dx-4*a za%-5(Go;h&gQ??Ad!bJ1#63VevutM}UbIGvMq?lbBU8>;{2^KUdyL>z{e)@Ue!I>c zI=OnC5HSa)L$SwPR?rZuOV5e-WQrB_+-WP2R!gU=!8X2g-6FF?P2;$saU9@(?q>pk z!o+IFP|WDJ;~=XWQ9Rj3y5K`!q1~P>?I2WS?9M zCvjpyPE99}64JVOBYVCmE5*b-HFbI|nF(Tj+{n4jZ5N6VMtcDm(S?Q+m7u5&wp}5W zeup8ITMbpxg>`7a$6H@Xkei>~$*V1`ut}(z-9hg4E&yiLWvj13_;=G_R*YZXr9ad8 zqz|^b0r-6;+!JnLa6j{AvE=U0_ptWZX8+%#v;v2OL~hn%I&ZL}v#Oi6Na$7pfuX$* zReC-5`1qk?A2G~6F!Yka+Bd6e=^iprpK~3oZm(%Z{H$}r@15~ECiTGcKP6h*5Ui$% zaf34l zLeU>S*5Cri71C{$s`?u?V!Mwl_4tqGX-HO%Z^s>)z@F#ydM%;A>?nQw_|b;sNb3AktpcN|NHakl zh3S$U44>gDQFM_*Q**>Maa|T*Fa32jIq(ID1SAsqbwgTcgl85RQ+WEWhE@3U^PcCs z&+p;AW?`a`nnMe9+eDR$$1Yq{feKVHgnt9Or+ZJA7G;m zzdHOfTWAZjd|M0YoJGteKy3iqw5*riut@%DNq)>fZcEW0xGKQ_v5p`)7xkbPijN?g zCtPk@@yQYC)=fTN`FTqucDd&T`<4j!t+ZxC+-O9ID>ZcDBZLWMg%>7mh2H9);*HWr zcfDjgJ4{1PNm{<(vHVGYmV~^cd~;CVuB=}Qn%@lRYU-3Hqv_$DYY+$+6-7L~JgZ|z z1vtq^xxnE%_Y#+p%*&_Od74g3g2ot>y?)u%qc1H2GwGllfu-#^2ya12Y zhhk2?jjxhtMWUii`%xIOur3A)SDD|?N#CbvzwR=jwv^(^dGM0WMHB zb}Di<7n718bXoFIo>{|8IiHnKAn3EWvC;ucyp~cqkyLp_T*8edren`Pay&v=$blg2 zZtos)QL&`~t6vgLtDJv)U{BMF?vu)AZhHUXAk|}zYt5oa&TII7(MbPZp(GAsI+)tD zl0%Lf(!bWrRcrfeHS(dkRQVy;SqGQ>Z}@TaTxn4k+?H9Qv+}URKv-HeZ&@xH*|pLc zzT$kOsahpyBh!0B=x@1ZhRL+92rpcBB}Rj`Ury*unLc}Myn%PrGyUN4aZIlBY!=^{ zUsmn_MHLcy+Pgwc-G#WghUiV(*hKbr5;cFUU42Zx&1!ZI2TI5%m9=P=?!jNL>U6UO zyXfsqN9JW8J{7v=Z<>;ZcptJ67biR_EP88ZQD3~=!8-9&O8qKyolgwqcdv*s!Re^+ zL(4nO4dWyA8+bx-=Y{VQ@uo*Jn&O(?{xA@?S}=QcBp`^FVg+GLn!!FQcU;mCa%OXr=` zz1%5oC$)7xk68@Oj^X)(at)cFQgI>7uYCQi9l?s~Q(a$&T$P+}Ud9%;;J>5GLeEtN z-j8BE? zn(cHo`K!#BJUgX(ov$9+dj!X)Fb(T=FZ*OezO99wdTkXu;`yOJ`yPEl@D9HuB8PqQ zVL6gzz596HnC~P`obFk%y8R6^kQi7~hc(O;!x~$~)uu9NbovE~H3(vJg9F`D0FdOJ zE6!TI>Oh|wblxukCz7l-e^Y+x3uvwuy`@16H?@Y~3IR#brAP&)u!=TE)V`LyjG5Be zckJp+{FZ$2S<)bg?9B0H$P23Lk8Cp58@t65^6a#(9u&_CaYz$j9*QT-@t1ejHZVhQPEy2Ke%gQ88G;@$NZ`kFwFNJ1ysrMTe!1g)rmr zWW40XzmasG<@Mc8FIYlYnJU(mQhKHfmD1%1cHti?$siC`N=YLDWkdz~^QM8T6&!fB zVZO%tck6LLk*&u$7dbN`N@k!!tKUe_)>3;(<3m9AZLkU2SUO!DjNcx2tS2k4}eN*R6TI-u*h- zMvn9myk7V;8XwB3xmdkca|j=vX}lu;`|I3q$xpD`16a}-_x`(2zq37!+VOE|+_qwk zDYcc9<~L7%eX`8scn@pt(_l-2!wr4b=W^wtY=b`YXIEE!3DI8C`*t#xt@c$U=J)on zWz3|zFmUgX*x^hfx$M)%3ng1*X#F=Mj2&B2bC0b2xNy?nqko{Wkr-Bd&qPQsir+f>kKvdTBAPwDBlyMhMT>jf0-Dg{c{ zRb6t7pwnsj0|c)Y0E^8W7mTZ{Q(hu1S|0@p^Nl{P^stI8J>ao&(vgAK(vNFxuQq?T zXi?KCQA|-a|1&E{<3>r>!Br%H#}%Kdz0ZczJ&wuBZjq57p4tkm8!FW|!vV0T2HhJL}ehH z*xJZ-)Z3zXg2C|s%Dok)1pF3YIug7dt$o3#5_#Ypn7N>@UPWvIht@rTm*>?%&|<$s zq{+9>_7>t&UY3uSvHQgg(bNo+AhszC@xv z>{&ilf9|eD^w_^Vje@xI!DGpmRgXIvVuzQ z@*4osh*I~zBg;Qb^glCH{wK1mBB~*yA^uOY{1bum--2b6?8vt^AgmQj_aBu+V z;9)!dFoaV=0Ft@fD?qseV86pS0(2Bke-NAAlmWH1x<$q}4-m#=IzVPn&CQB8Xyb7k-_isW&aQZlv+1eR}>@j=bIY?;I;M|!OTiM###WL zo~k7P*Wb`1tGFhBKd3ktrUCqOG8#4+F4q#)?Nz%9u-4@ffGZe4ArN;3=U@lu(ZRU} zfD<@(6cEcP5&%{FcmMWKq(62Iz*i}3Kw`}Ow!^o_Hx!85%Q&Wm9bBzD2$x47ZUsP! z0XKqxs8;;s;(RhFfJ@DbDMW*FpulI~l|T*d42;#y@@OD{B_k^Ug47MZ7v0g6fw($4 z8+y$qedI-VpFlayp#dRaZ8JD$OIz+2R}RSvrU@KvJNo-}R-Vi0(Ag-aPTkyaCCqJ5CG2%?fP%1>eEArH|fz=X&BR; z<9!H65Dg*8fRCOOf)n_%IOrK%5C>N`;MdoW(ii(*W22BY0DsznCIr+Bz!$b>^NfBU zZey(ZnAec^1ORh+X9C3P=lJJD=kA*VI@a93*?y_}ucDeJH5?Y|e@wpUXSHw)An){# z4Z|87?i~U+I62$`zr1n)`2AqxZJ>{^4}B$7f|sB2&W~7%V*^M)h_6XNt&Z;-hi`Kl zjBia$vL1hPg-`)=Ob~+)-nUSk4xFPI`l)|#$$*C)P)_wiA z?>H z3&=VJ(Dn@NZ(iZ=Qy`WO+!eq=C`Z8WHXDG7OdOo=f?&GLR@w(4$H1pEdQ^xu`R^>H zv0fabTkG2vk5>QzbMstus)k2}0qC3EUv_^%NA9ak4Vpw#yJ4D7WXaT;o&EFap_O~u}I+-#ZSOOdIAqonRICX0v+f-{0&NIH|3uu z3~%-b{;RnDD+^~0-qw>tcte4lw* z=VD}nU#gszC_m3qjPL@E@2GmX_vBlO9I-bo&Ki)VEsGGJS4AJ|FFEoVO^dT1=7sgH z3s##man>~~1Y;YJ*SzQ7)P2whq@W=vR73taRmA2Xm$aI$m4QWo!Pq*P;Qe*`>~y_g zgZ_EpvO0^-1F!-tRaIL$H=?sY;KT*LWAyOXVp&)G0j74}F$MDwp&QZ} zja6{4*seZS{E=^+I}&|k4xx4NzSBptl?tVtqQ8v{;NA8ewf9YA9o8(v>@d+k9ov{p zKSheooO#>D?0H(VNe~=ywo)_@(a6m%8}tTx$CRV-6NmgWw`z08NEAqeSsl~8MKt2(I(26WI z_uoCGw}J>OkDBU0hypLK4g;H-oi35$JRIly{if%lU_|;QCp{OIcM1L~nzOwMBp^?K z4$J>oV@dcmD}Ylje7;4rny+9c8A|69agZs$I=Ej2{4^R9K?Tyla)5o!v}U@-->_1} zZEtktGYbj0^4gg%IWks8wO^M7+OEbBOZilGr!WqHe9VbE93wVscFWD6VQfAM zGVE5dN@^2=2{L*;C&WX z5CrUJ^=i$0UR;fhH=50bur-N9^Wfja=~87NYW1o?Da1~g?H|I@XH3W@Y)k+Pr%0qx z>P$FXsF4!xGr`8hchyylo0cf?Arca#YoW5cdN%teapj)fsNMO;G`(-Axd8SkHH>IE_JQ<^A1UIamL;J%`nwC)<6kmv|B@8E7pK-t%Z z5zawy2n1ur`mUv1ufx@$6?cnD<_ZX4#|DH=$xUUeT#B_u8KG?YErfSNd$KX}8ncXB z?5=Hoj!29#6uA}sgK$-9J7;_#baiQSSE5#C-FV0B38RZw@ZK{>y~5GH{)SWTH4~=> zSjl_Gx8cn#sJ+Ynopp5Q^L~zj8aBNn(ajZOB9s$of#@#KD8Iq&=>$nVpL_~h<{=v~ z`Ijc2uOvpzGK#p1v;VJs9rxLqn&<-gbUGH0)U5OCUUcXTZL!jN-(ccImYOZwn9bEL_p*B?Ah$zg z+)?7ATTv*UGN{;gx@q#{6Pd4TOs9Drb8vO!*W0B19q?={S1Pitm{+)4o5r)6DS z%VGFMzYFtyZ5P6b1THI?`?aWF9U(773bZm3F3Vnv`jWWa@p@MWH@PS`VeuV*snbQx zw&D0ne@wgOp5V|}IDZq%g6F)|GroJxl>prcN* zoE^NY>Sd7ZuHs>ie6Gtu98A!7#7o(GASPkgalER@AY@ao<-InI&G8+~_S{znmg57x z6OiuDUZh@CxnzSoEr}lb`z0`= zv7b$gg5)*-LI@-ay-QET^F^1(ExboKoSKF%NkH2l^m>x=U;j&DSDs|@EZIyv z;uCrjRw_cq_kAM$J^kD-rm(+GGnkA5LRcx{pn_0 zQ%VemkSraqmU}RnN;BhEN7q1G#pa-2VjCFt;nxY;y-n#)Gz&U7-7o+A!l1L^W3GYx zr{N2XdX^?O`@%X;dtPxLtxgd(Yi>YY-=jLebTVmgN3!lc5@(GL1B{J%&VfT1HzuX4 z+sNESKS;wS_qJt-1@~YlQU5ellA=l9>^==AHPu1f%yrE(qSM0KDT1UC?F&*YX%3Z} zM`Fz2v$Dh#*N+!zlF=CePW<}pw+7%C5H|C`PLsET=elRctI@V-70vKt)KH_Ptn6(- z$h7HSQvB5Q&z{tlS#P>l-RVKJ39E?{8bHyuVT!l2Fdat<5PCY#T-wasguzU zbxuSFjEfsb6C5h>kJi1=F~{o!4B^;@Ugu{M_~|%Y9;S&TN)=036ukzLf|=GcDjV5A z@?3p=@zRGeb~$D5ze$u$e_AeHcono0qg~}Mh14@=jOY)Q)e{^1%$C>nR)UI`6)jVq zrqER(JB_LhVMNOlW;Po16x{Hyo2p*Xsw<^U2z}qXdLO%Z&vcZ}d1X<|RvH4f&a&!; zoXys%pPN54HzsHhY1GN3fES6%8W-&ml#ntT%61pUQ{Gv`X3fLRyD7l%E9wbIoUxmG z?NRL95M_0JTIt;)UpSDHFE9USmaq*LA*faj9aLu4yc>nO43x7Irf0rRYOfYhj}BkT ztf{AQo6pq)Ea-iMzTk&87SwUh;dk5Y{nBd-102>j6(JvXO-cW?$^v1#J)-hLrqrST z@F6FTI=UuHCd6P`@$?Ba=uC;vD34MQ-&VRgrVkt67$xN$sgy9?6)>eqO}nBzzs)CA zek?-3+gg)mbYZo4@MK0oF3_Jb6Y=LW;cyg zdc_)5rKR)LX*qH`Gf8H%w<{h)7|T_(($^{O67kn zN+=8`oDY$G)Et))4H2#ZbYk!iE~DN0(@0&BvsvjuVqtG2N+HEonBRTbC4DhmCMOw= zTh0lK4V0o2Y$WFMYW3dCogMWmDQ)5WY_8L)@knGiJ;;CvxdHez6576ni{c=%F*vxH zX})Z&yKc!@jpu!<#QjRO-(C1UbVjc;Q6@1JRy%(4+wb0~*~cjdy7q{4 zvq?In5f^sr7u{N5>P;30)J<2Krim$fKn?mEF5zcT^M|;(&T;J~b`*h0m1~EnV|nyQ zWklEOW`K}(DET|*8!XoT3GWkY%Q_VjHzLFu?o}z0StX!SZHcHfnAW}D>LM3$+?06@ zE>|TqGHj~^limEZ#;w|?lR!7$>JcM2tRxG-Z4$<;AO>b$;T6bY?5V@bbNl7;!=Zz> zoy#Yi&~=~F;jPcGbCqYUxN20UJ=^^*m_%|On#oD+>@GwlY5U$NE+A%?w`~$Q?n!8^ zy4YX28ZWA;-c8O+=DAU_&d~)PM?c+!Od_5n*SHXp;$`9ZWDcXOVOI{EF`U`mkwB~| zXREapdcTM^&auQA$fslwgE3t1&4ZO&8F3Oz+#Ja48%=}W za%;*H#7l{LIh$ppf%y63ciXbbS(zM|M%;wV1F`KMrXUSorw73v9peBj$^!H47ti95 z$rs2Xnz&{ZN(CAZ^Js?3a}1u=q$nrr6C*vO+d_IJ(c{;4-awx#PjRAB&Sz4_C2^Q!Ey4{C&4qpu$Lv;yTHB` zG=#2HSgww*U*_jF(WRHwH^md1$w$CI%>G{L`|%z(+j=@+y8>GiMRi>n(uK!*(8-Xm z1p9gK(=7LW<)mJfPPqFg5?hl+%j4l*nM4&L#`@RJiGoCiQt|5AY#|JiwahOkY-=B{ z9vje`@NF8oTWJfBHV}~#^w>$@)0?tUw6A+t*f^)=KzC>TR+vccwI%r}hzjplyu?`H zqC9>b?W%UnEv6?Wkz=}dJ=f5gvkqx}?)T@6GHk_* z4CQzeLhC+!Gw{L7rq#Kvp6;TI^XOa4jM3dq$4?rfS7&rM3Cp<=#MW% zz3Pz89B9VK$mZ+H6*FOnZ0zi;c6KL<+F9WWHaEk<&Rn870NUqLL_E%$SGX zg4;Fu`wH`!x4i=4RBCO%0un-Wwlrw<+`y;7k@edCg;u^{9BC&`K4wKL7Er_B_ehfq z@(agy+A^B^fOY|W5Lx-!I}h)}u?PhgSpHwZ9fdoKUq>X5T&}9?Pw^^_d!Khp4A;w& zMa#;#U1jFibln*)@v~$l5^N9gNYbjLec|5{U3)}6r}$M&%z?PIIFiEVc8=%08VZ=~ zYM)O!Ak_m*i2iU$rH>jaL+3mp(C@;X;Z4IIA7a?1LkKM$u?wd8M#En{zw~x%xwEC- zXG3{qeP~?zz_TM7nTwGKk!ka#5{+c;01l`6sLN8Fm{=ZN{mYLltxOC_8|&!^KM`C*yg zBD70HMc7UPVdL*wd9mq{jd`=b;Z^4N6B^c6x>q2c9ldz+CtG(U+PG}M#*_>s);;vF zpZ3>TvY>bNbN>S3^Rk4}?cbqT} zro>HC3 z`-AzSTJmhztCX=!dnOdnQ~AR-7RY0*))sNh%{%Xxu@q#<@oH4mICdwI;_09*@YL>y zfkPF|U8VBVAjB7WBBVuS^rIWmB(oUf($D7C{F?cpQjmIBH-4;~*(^|#%n6wkJ~9j2 z(;#e-}gNmqc>~D#QTK%}-zonzW8Xm`%LZ&kWq*GV2$2*=> z#`a_99z={9JB9ifV^PXyx%9te_K}~E^MJF~r*IXoOgJV7a#p~#CO2hDjPDF+Wt5WQ ziPFJ88$Va=wOFVfiL{hbp-#UmVIoqsm?F?t7l6PSpw8AG2=y{T48!4il-&m8k_lx*JJu(f+B&)poeTp7 zmF8-t@kulGC2y$!?3R~Uty)}csaCw}JP6H}{%ri-VSQ$|0JR$w6K{;5qRw!w4inTb z3YZQmpDtauATVNBPAHkk_N42EZy^0l>d7LKdx&h<6@a-KME@b|C>a<{-#klvm4pW# zTQfpJrZEi`R5Ol>Qn)rojVI|G+rDkZh#dA#GPADPI026_hU|%}nM5Q*ZinjO$pGF$ zPvEsx&pX+nwJlY_35dzAh;#6L$Sn0y^zQbiLeDAE|2_~HB(gd)%bu#1Op@B%5~_s7 zC79Wy2HdVh{i~_EOm$}l?}xl?WV9;d!s~?%Ol1Px086+qx^;}iR+>@DqG#p}5|U_9 z8TXlcRE}e(pjwMihge8tS87ETFQ|`wr8J*)3g8KY#iAG5N@cehO$MZQhBo0Nnb4~` z@8@Ay8v0h8uDjl#OsYmw=wy`R9z5aFejRNn_A@fO;yPF+aCgct%=8ldz;vkNk(ZmU z_(KcP-6<2$-;WK-!~6Jk__ImWg|2vp_N4bT3k)%KOXH#?SQ>##%z(8GJ@9flHF=Ol z5&Aj9C<8}#E5`9x9X0NXXv=t1v@9TmZ{U1{QJA+sL@o76b1+?&dEKZP6i;i6jEyFt z$II#Fk33m}7xE0AFH+Udos6OHvW}bFS++pWFx)LKpMAp7rai3bQI7n9A(ay8!z3s~ z;1r3MV?+b_CT*OrNc0;Pxj_DnS=>Lnnync~<+Xb%q4NC2y&A9VBdhX7yR8(K7R5#K zG7)hloQ7K%6E!#p)pG2IPswOs?VY$@JZl4Kt2z@(CzBP)zvE%&TYq7Xd&%Uw6p&jM zI8pPxkluPz7Fj)rNN?P_(th2l9kYbHhId;26Cl+LV0d^2pKUpKYX&m;p?}znJriYb zCNi?PwAJTA)7u2b4IJKz##9-Hi3y9tQT@lPZ$dZbwDvJPDVLU!#6*5W6W zkpJ~Vd_1qKUnFNtA}LW}&Uf+6pYR2FcKgIOTPy~Hu11hh?9|z!iAsueLDqO37r#3b zG6i@t8|W}1mP^=c_1i%WU8Sp0YY9}!sN6xNW4DIEv}^`z7xA_{-MQ` z`J1@}ksf==bf%_2*`4jH{v#>=`Ihjirm$?>a-1qF)|3dQEyZ(w}{!7{Bqewu5?!J6FFnEg3-uv84T-h~B z<_hVo;xX1ecCZ{X%vIUCMPg3twtSaD#*&flE$KILf2j}cNI3*Cd3`0Cc5@3WqUa^k zPhx^8IfM3rZb{uG*33RR&>EGjjL{yo<1Q>WUMqZiVg#p^Y|;FOgk5l%`QDSO%yjcx zd?MA@r;bSmVT$`SY~)QRxz#U@Mi1l5FWkR{wu8Lv21J0fmQ$RIZSv6dENKskgiw5H zG`c4pc_(J^4ty1TJ1tNoU}Z0z!!Wk-o6axfHk%yBk(FC>nzWQ1!@ z5%)Z-a7*fa$dp;hg&x0Q1RV(tC3gvx<9&y+%h=bKGBVsA^QG~blbT6>rPG=b+ zaDCb>W@a&YAHa|$EK$+fKjvZ*C}24dxa?|?6?@&M(C=x4%`-@3WC`(Uy8;P%e=kR* z7DE8I6hj|n^)#bQ%R8f_*Qb{zWvEP@OxqIb#7|xWssRlv*ArV)U3O~H z`$$eHf*A*5UW1F!|54&ctCQZGl!)K87OqOq3UFr+rmA)I?vv3%sW>SoA!K~|ZV*Z_ z$)Wmy*H1>p=wD19#>dQm^Jq#)V_G@u$nI0xENzwXVEW>Q0_c%Y%Z&uw@$$io&$!!@ z$Qk;Y+m%7oi-Q6?W-Qlz5`++J_>tSnVzy#ZwByy~ZTBE^?0t79uey31kS;xpN?0!u zcxc-j3D+nA?21|3^Ng4G$88EPjd!lV{oa_lkjrw4h=^uCRvwwY$}uFK|$0JA2sJ>Z_* zJF(z^<|L7Q67hB2mSLW889!e<|AKqNmYz>4J))Ol{fJ2{`xryQ^j%!w=3$v( zm>|lfs*xW=58;06X{2mkln%s6q2!cw{QFcb0N0{!Hc}&uO%+y5g_GCBb(HZu267IT z3&|?#V|)KGG8wMDi7(0wE|lr44whn>*C&g2<_~s?RS0pc%RQyBf(x;rY{6XH{^;!G zOc78jzk_|HVd&`L)+bx428V^Ib!A9qI+=5^9Bza|u!lR8uo-+UB)u-`ww&YcpME3i zxi0L7Zm=A}e6?;H&y>_R_ME8D4O^?RuLDfm#+9=PSw2pdobzfRKsMKhKfM=4KraQC z%k5Ob3QxxzdqkDV6IuO+Ccn^h){Bd8uPYS2Fo&NGb|}p}tuIa+q`l0I(p<1H5VDi0 ztK&(#A@U)InwKM*(`{&o=C=jE9jKZ>E;?h}BwI=z?MQeQB5{tcrp(0H?oh=O2oWX> zMZFpyl#neF(sH@QQy8~a3|x~> z1d0b0AbjvQNi(dsdtz{1FmgUTgW148gU{RCL7E=0L zF=#ehQ+!UYx4Al>1gjpwf7oD)fWkxyQx()*_Ndo?g!-v12k}9lQ=M5*dH5(ijXRG&*%RW8?8 zd_>D<8?|JPcO?2hJw9RL@SR5E7wWkDXL|E-yDdY~xeq=%D#TlOE4w;z(I}c9)wZ z7eD`)62=MM-w1~#*Up0)S0PUe{jZ&~wjcqd z#vfI|>3pH_yU4luSMBwO-dgTkoz>1_c|%OnlfjH+#%e6+nZ<=Ss?jm_e1NeZr-oZi zIyX#--CSLSOiMS{T}Vf=h<;#3ER00&1eK{n1A93N41~d!6BN{do?zaoQcGw;6M0-a z>J3XGkr9+d^pL!rKG(Bc1I>)kB?N zplmj894sVxPv-^XO)XXDoq;7Qi(HDo<9^i6$<$CWuhS+Y&1K-Yx;FW5-e1;Qyn9la z`L?eq-`I3y?$?5UPFc%IuMRN?^eS)roVHCKI~yCu?~?h?;ciycr|Ijr_s zHEc1GPQC3?CN8~fWXcmOTHj|UBOzo=`0rPNa&<68AA#G6upCUbn*sNZn0w-BxticW zrav!a?46}Ol@tbNee-|JG5E@gY^`WW3E4NpFpoCJdU%GH^>~sr6&Xg6FxdZQ8f+x& zWBdK-@MDvRT!9fQY9r&S&X87cLK4QY7vi4y*}r-4Nw`H#((W}K-t2eyp9ZNu;Sd7_FhXb4l!fTuQ-cd>hbcK@2*o6cQJD z!gDP8&$!Oe{CZB%pP`%N4ke!yAM;9iU_6`?+@&voU)d&INB{+u zemz-VUV%Kliau({*Qs~vn8U*rM2nfkQTISxTxjFSBYnOwXDnN)B7p6K2dwGKo6}O# zUeTa)8qMLyf;qMv7 zWI2(W*Er)x!BABvZ~vJLL$(sAJz2?Ehu#*7fCUZV?Zu@E3-n^3piukv1sinQzxu&w!KOb|-sejyfrbVk zaau4*E|XN*lw4282FqrIXzW|cOH*`_5BtyqYq`$8%_P-o+Oh8}x#K&<#st8Z(_39q ze?lbNCIeD&8cVVbfqne>z}o&$!0ys-@Q43XrGb+tp-GR$pa;30L$j%ku52V#n(qOy z7OqpbGAYWqL}(PX*cwR?Z4Pcv4^Sy&wurRE7ZP zhr-`3b|9V{jGu~0ABSt@65$JtPCR+bVSeL{qOY^7E?!nXB`iMO>=+y=gc+BA6oDaN z^i6mHNRA93PzUXagzjKQef>5@%IInZ7SI#I;~ez8Wbw%q8~yeEbyxH>$3&#lRC27to>MzyUP zjVJP%{GPF!R_+V59!{_<)_TUxdnqMsotX#M zbrEb1x=uT_oI|B}^v2b3>NJ#*I*?r1?>UUz!c3&9`=h(;BU#K4ojVla^|BLe8O6Pb zL?dT`?IvAKRMgQV)znI4Z-yIrFB^6lCf? z(Pb1G*jc+3k+2V)WL)2N+zHyjPq8pnE$QC0Xoej}01Tf9dz$|69i)Hni8btv z!Ah+7bf&UDg1)qVJzVo=RPi=;OxraVOa=gJMieqQhQHo`%zn=;Z16P`5UPPD$hs7P z0eR_JI$rYeEk1mNQxnx|v0&@#d_0_1Mj(w?`Q*In%;xb)A2GUnb5S9QD2=Q`)m{xL;+%LR?2 zC)4QKIix7LWZaE7=f4g|qzgoKac5I4L?fgJd0lTP!vNLi`^nh^KibM>nU}ArYxZb5 z9)am+>(s1)SJGx15skRRBKIj~6bGt|3bLWGQUWe9Ca9E$Zj2gjw%L6WnHI0-eJD*6 zN^oGy2|f~fhtBnaH4zh%|+*Nc}>EkBU(|>3|Nw9h+dH zxZX<^OijDVn@x5xG5r^>J1q>sE4(CaUDc-4?qLxwZW{R*RJrsc-VULv9DHvT zCV|Q*S|V>O3F;z(H1qR*aa0fUvw$-7CNtb1$*7>X84bm~_F_xQy@vT>@&Gk=SyUU; ztq~*y`hNcO$2@u3&vl=7LdIBk`jfEaXYF3II00>MdeBRyGPz#&(u`d3&%PfK4*3BV z*_N`>n}^TZmt}70fE~)ti?$Z-Cs^FZw)`lW;9uF*5=`z zqQi0D=^C*(S#du9H}R)mfQ>*pi2pafg5`f94*pMkg|wKAs)Xo&=PNk=H+%)tfASTK zZ2$O*KmY&v3a0-pUm@_%Wc)uI#{a`#{2%t>|8N(p{c{!@{->V!|EwzhXC40U{^9=* z@9_VPa`^u#6#h?n@PE|?|5yIwKWLBt%73u_FJI$-@*m7h|K9fhZX_j^Ex5E70rk25XD3jrrz=u76u6hzkVb22DG#Qz(9q)2Ajo z`*Zp$ec8(8RjIlArN*rrr6`gLW`N99lmL=T%M6Twm~`PW!1M;@YU+?s{*eAUZTFb8@D>G|LV?A5b zb6p(^aJr^?5C9ZXL-fqe%oBi+R#GnrY<136-$!UoDB4P>sD6MSs2xN+f+`S3pwpLJ zsO(5A+RKb=v@F_+pUL=B8m4{0u#JrHwY4>W%Zx09-!Qr9J_I9}+D_2}ze{vJ>w+GiY!JLLXsCgvDs-^|q1)bJD_00#j7&B%$gABVzo z9r(8u^4lsSJ3KzU7nhemB|B<-TnHt^SJ2+E@fj2lJ6DIlch^t*eQz)T2#_>QbPk{> z0TZ-VFyBi5B*CH|QyVl6?H1t1)E*fKQ2Ou3*S8${mKm9A%L<;~(67s!^uYntg=D0& zANludOL%w=S6@^BGK9Xqff*P;MteJ8w)PZ2-f#1h8|+WkZ?7sUEbR~SE+38LX66Q9 z+iwn7oA0m8@H5}Hz<1t#0pM3HxCfWLUJ$^N-w1zLM$S6M7wFe756rLP`)_7IZ`Ic? zM$j*IQgBrBb1zBRFZIK3;-9Aax|g>&n6^fp?0zL8Gw@v0&0p#Yz>in^s5OnOuU#Gs zGoiaGh|NrmUmZzka!6>m_=v)g#`^bOt@B=TKvr8D18Bu2r-rx72f#l785zH`c4}?^aM6Ya9Tfv9Y0e5POH<$XtEU5O`|H@t?h%IDJFr zR;Mtkfc{C3fax0?L|-lyI9C8<`@N|@GB^Na34BA4`bghG+5lwrd_%CdBfSwxn0+Mo zVg3MQ<9tIv`iUPxRRCn?d>}7$k70c~Ccg-4om==oUTMEV`nOPi$ZgXZDF3lr__tI0 z`M0C;3y1A1`UvZ*FZ(96r@8Qhz=;~c2O2GW|F<&#mf6ym7~}&UuP-^%A-hWW?+tBP z{u^WcZ+fj|1>wW{k@Q)i{qoxfr~VrUs{h8x%D-{J`Wud${eeGurLUr8-}-BWpPjv( zr{6c>`r8OAJMuHjx|YuK#$jd!%lNHC$GYdIiu+p{X}wo=-LDq6oj1`K0BvA*eeeYT zxrZ9on}B+?(?1O7P5gE10nm^7DaI49_wZHU|AQW&{j0#|TGxjBHt_ow0PZ-BBV)(b2W>GYqIrmhRsZMd-@;O99|nn)D}GT;{oY&oArCwlk-Lx!!?esYtlEH!nW4H-}2R?mfjnwW9tWZ%5|+B zANZqC^t$80?=9*_EkMd;rBR}7SdLFoV75+5e_)^2*z>k&)f!MVA9S4>Abcn?!Y2#5-WVps9elNVu|oL-ESohP_) z%++Zn)o5G~*}g2-nv$ax6RPsMR_jpi*lJ@Kq4?)$N!)BKB-QcDF)s%}>nh2q(Hy5NLr}SbcR^hg7uDCh`*~lL*iR1hvm{B4K zde&X5McxaHO~%CZpQt&dFWuBx2{ugPV!1?^hd40P9WuHe40uGD7Du!$VX%Wa&!R-0 zYRsQhk$E>3CHX)s>4dKXdKC*dQ2_;7J{(<3PF99v8_m)B};{K1(NfBZpy@r6VY;?a7N)Xr~sx0UD5IX<7Le^ve;xQ~_QU z%u8xe?~ww29BS1j@4DW-T)*3}q0A@*U2GLHmiZgXx0G34+C%KkC4$}1o!1@tPMNB{ z@hZy`cvR5N=k9O`Zj1CA%qcVl<8X(+<@@lj_CM7eX{RZt<@T@VDglZpJ?BW!-I`ji z0dfnF%qZFIy+p1O%-@jgHbB1-|S_ zyBXsU?Ixm9@@*Ri1XS2B&0l4jJ!>l1gnB}Rq~J-*u>_cS_Esq~Ds_xq(2FFne5R&mr&=KozncpV8mM+N8$(PTC=PgaCO48 zWHEV;$wE7>Z4RDEG7jb)vBkm&hS)4(*hth`{2XXD^YReuj2ipzBx|?4Z;;t=9GhB4 zIoF~v4?-#hvO58B_dMv-Y~>u^${WAub_kQWdX&nSu3v?hGqQBh!}*ePh#Hqt+@!f@ z44uj&4V)B{nT~Uvvdh`aU%(5IHij>Hr4+~xxAv0guA}Eey~-w@YJ&t~&QA|sfpp+kS zUe9dzeJ9`Vgn$MaDT1%nG==r8gPo9`J4h@R?ug`)_1;FUmmUBibXDU9EApMv5B$T> z3Q~Pm^7pidv)#azpzJV*d{7UQfq2kdBIQ8??ul41aJ^B>N3Qu{^giI>!8&YXO*Su* zp)E6D?-Qs^9>Vkd*HgxyTk6v+@&2V9$>Y|hK=BkjV^Vy=q*I zXknO;#4@0EgfiV_x(6?+PkhK9k=+*C2-|mgoN-RivVd1>mEdY8cDjhr64bSb4``LB zoU8h}cdh#enM&ez%VV1(o#A)L1bFFYX@G) zbu=K4rhU;rou88`aOf1TtFN%0Dd`t!|PzG~Uwl<<}4)DiXUYkieUO()ywHIpc<@}qap z@*D2*!W$*WF$-hE(2UZH*A{zoV+8ECW}tW27}b3f=O!1zF|Xkbv1zH~P@FrtHfn8u znkxsd5H%KL{y0dVVl2+qMHaGtGl23LbVZ^+2uMp4@Oz)}5`VtwIRsdqG zm6O$fk(`+3x)pmM$s9d*4sH{3^foRS&-O)I6Te8bycJ_Dez+B&m^PTv<%zybuL2k9 zrc2ds zvY5TRJM9n1;1^1TVB~D}ARhe{y`{SswJI4iBJCx~awP@vno^#x{ez}968bgRT~^>L z*3oBUq(NnX14VXn`lbiH!Z+U)t9V_dL%_g^{l!9s?QOag>;2Q^NCV zXjV5gr0@NEzkLVsR}uD=Cj|u!7VBKbrMa<5e}_foU^`=-{x1lKz9|z?r`s{d#ghsk z6ZS!9>9=dF7GMHs_5yZQ?Cf zKj#YRWr>p3Ze&aku_w3o8O>1Xc_1fbNY};GT|$H1hiOKe=!h@LBYCEY6BFGFj$$7| z2O1@%jG~7}A{b(fRyU$bTqu6jbwGnj31ls2M2wbWQqk_*!SL)8NEPOdjkC$n?nubg z3`eTCxNYxMJ*&CJIZ9}f zkJOF{e?>M^di;M+9&=&aTPrV*FHI~O;B7MfigiPgWF(H0wrH?FI~+ueKR~8l5RJ!E zd`1eqA9JunZ5k3{-SE6-hm9ZRmG0=Fy!9@nvBL#jLRW@{`*h093lULeecf>~<2c%< z_*FJj8p7-qG~j9uj%KzvK}^)?6HBZuI;3Bdrd*qye*wiP+dJ49Mens8Cz!aQwTE2H zr^J-?jcyo%2e3h{^A^3)b#m_LocMjlVor)@8*?Svr$H^ z#q6A!QM=v8kL#qTrD5ZHW#@fJH7E14U1UabdY(IvOJw@(3EM&z#06GRZozYPBEi(X zvQ=M7)i^<$ZGR@&EaT*ZI~6=1t}ibvP4{KFYPXyj0xsiTtHZ_DpqPl3KqMT`a*8346lG{ z_-ua+^+$HfGR94(zfXO7mY4rKu_qOg!Zj;>GB8(9zU;jfW{$es8jhl$fle}Sy|5>!Qu4=P~p<}>VCR#3_L3PBdR@( zQWh6@r|wk&kyoaD)r8ib@5s|a4(Wp{gb!p++|o3OSg<;=V?W!4TnVXvwPy^;>h$gF z^02W{qdppDIW9&MNH8CEnM@TR9_>~|D>tK$34XFP{)jcQqjDmjC`tvIo|aZ9hV}d{ z<%3i4;}hnx{%l(;qjC+Z>HW;Tc7OL{t^s586ni6N+wvCV$-vXD5RU(>uOuw`NExeV zdq)Gw2E)Uf+=ep`u;gJXZgPfkxY5Q3F#GVUn?^p;o9}W@ptM?`UF|q?b;>G zR<|;pmFEFFmvARsvM20rwY6>(+qZGhpbHBX5sEVD5+wV-MGBp@a+sKjVlbtGrx z6pI6+a|+4PwUUh@7=V92^X?f*7i%K-_7S1bv(?aU3)hoQj^vn&uPeo@BvM~XpYheZ z=|0}5<7-DwnP8RE$Oq}1;$d#V6~CaYe}H8{!&V?J6$?eW>g3Dhs%xcgQ%dTz9>9(} z(5q&pnBY8j_%ygkv{Zjt75ah!_2+;Km=>cRxdB>N_~YC52>pkRvIQLk&dFF+pWY{# z()>K9crL0HM~UJp&8r+aNYlAwGBSej7LsdqkJAa_6s9XA^) z(Cv$SfhACeBEZr+DmPFPLhn;Fnui1hJwk?>3Vn(fK8EW{QLRpW&cy!VQxL2fIN2YG zQy%?=F;8}4hHs~tkC`ctQ=G#yqK4Jn_il4@Y`nyek?qg*orQsG#`g^e=F77qUBMVS z9~dlkAro0?h$O(B56IxyWOn1CK!7b2@HiE3OTi7bH1z%}TV!W6O8IHa%#Eb6(nexph>g zJxY-%4SwypmE?jkANMHnJ5b96w%)aAmBQkE`dHmH>)S4+!?!OAWcr;$Y$cD0FH$@f z!}*j!B+Aa=n+>;C-P;Q4gjKO;?_qM?+KTidPdqbqch6LOo7^v+$>ts)9to4xB`@tvwGb)FoC2fZ z#sHDxS(D{vxS~_NqANiS7LT|*jL=^28xcsCZKmpJ{MaR&0kC}K!al=}Xz*btd@HpS zF78|1)8--jL^O6HN;jK7g^zIwQ(nh0A)Fv#j9&;Drln@kXhrcqBet}nn}sZiv6d=^ z-cL9mIl%&Shp-u{=BEjFjek*y!Q#4uT8B=rxPTe4RCfpUI5uL5cN0PVib`vE>r`wW z+74i^G3@T35yN+Di>fy7#GH&NwNKDxeyF&=wY$=dhmZQEXI+Lf6snIb!4#BWd5}*~ zc6`@FLh1tZo)wIZa~?g`v2;G8@h}lt803hLVg6z6_+nbwcOclMOG;pXDQBp(%1Z$l zlz~PADFm>z)dI;?%2kW)>m)uuNm}m#4bks3k8&VK1@( z&!x^*9HrFObR{It5>U?~Q~3c3Aa#0E!A;Cfbq`xpQo7|^(-id8fr{&P_{D{O2PZ9Q zZr~SGl%-8xLKrH#af{8x?7{bYpWGA9k779@e%ukdb3X0Z+1nr?)ql%(ANKz6+B+Y1 z(pbk&7J|UJ0fXp6N@Yi6k=7mranvbWrnVT`dG@f$V_lSxEs}7Q|Jnyly3$NL;o-Ah z6S)zf&5O;kjgo@jbR;n94l-!=48iUcr-4e^Fk?vWfJ7tUJeJ71teOxE?#V{eFXYWO^6sR#eY^Z74MH8hRlT&+(GGouB( z?)RJh?Fq{^dnI203;3=GCF+-e|56uis!P4vB-iI`m9!Hj1gUG{@bNf(lYJnrf;cw| zd7Wiqhm+@XGEdCc5B*b1;%b7ex*NJOlEm3L4!W*mxKJ?&;A*F=NSfg`i1FRw8^dPd z@(Pj6C7=E#oO^D0Z2%;o_R;kjAtl#)mgW^EX?AL}W*pmxO0ioIu?a}l%m!g^$zyVE@ng_9yKTEvkNftCi_ zmdR4YXA?Q3D6e@rH%hA}x=hd9)IpQ$eB667agFzHL**4fPt0(4VPdmn@oo`pH)qaxT8QNV3%hlea*-$RwADz z&96kQ6~rhhgW1=k8C-3ZeEca=$1yu$IzP|DTRtX& z5EpNGf^l?xB`RnGkG}Tit;AI2n;XHkcauf&H$vG0F^zeH4}w&~x9pMzh7gr1j@3r+ zRKk&NKCe)aAYta-TYWd~H?@GkO}7=6YDvc>nIQh0KaDgu@h#Ew{n_39c>ze==t7FV zjdkK7WnKJgQ*lZ6Cdzx|()76(v`HVFWI=r;tK21|wO>Y6Ez}mn3UnnRSZrRl4E54K z8S?d@*KZhVs~1Ura%z;zH^sS#aua{6g2PClp#MVWOiI6y<8qnZ2XM1U<G!8?!@D^ zA@VGM^OTfWN$Py8yVw$%%IDlt--fkKuj>jGct~4FCUn>YPFa}cn?QY1$TNjaYL@ey zX~e~cgdE0_MAf7F%x8#?n+cl#iCDHEJ*1T`C zFrhi76;ACiog*%cA!p5n7M&*Gxd744nZFAY)4|!E!ZZtfCqg0Bn#DdXG=eKNJ}Y6r zi1Cz#1lIH`YrzXtwsPdUolQ|G7sP;mG!)P@FV%Kgw7_iBp$fwDz zzFNx1W+R+LYDr1HCi1`Bjrby;$p$*Z+q5ilJ3pvRUic$;rp~51v#9bKYfj@nXZu1q z0u(lq!+*`7ML6k%>xI&Q1h$W278kzqY=9tgy@3$SaxU;A7O(^c|H)ltG-T_5*L6!F zsws14Y-xO(iD{1ou|845T%hFh;Z-l>Sz_x?OAa?7@gS3J-@YBE>>rxTtB9XM#ORVE zM(epubOF!{4#^^Tla!Ed0yX}88-yNdBdb*8!+}uDsi!$t$_kZ^9*;z;x-_Rh0#fuE zgf?L5pP4nnVt!t&6wA1$ChIMw$~m?}*M3OJ56a+_AeK~{s5cJR+#XN&*8TV|A}H1R z9VFc3tVs+X9IO6Vhg_@yReBi7q!QM|G)|p*fcAY8xE-g}GRib`)jHAL-FbOXuM;ZX zvsaGMVUAaGyQ%cIEv&?{K}B~kY*(80EfRGLlv}H!!J|Ix(GX|nJ5@ez!2x%+Whz@oZIe3rdaBJpBT;7W6Y9^jsdFA0<4$I$o4oiw| z7O@M488}=rLxAS&GHR_8TNa^igu68&qRHAJdql^j7P4nlm`*8(9wFC-J0}(|7`hwb z1?`1&=lRu3aJpNkuC}0^TCbpvOg=9gue~|Qrq?)&_(LdYTxpNQ(_}X*XLe^Rl`2NL z5=EF{^R$l^jJw>-FcmB7k4}d5tw9xCwTMs{Ob@`@=_k@lQ0QXTeTzALn$BK6cRZMv zD05AF0wppx;T7X|l2}vu3uiDI4Dfq-J1Ed8IQ(2A-7MWvHDtJ(G4z_LAZ80>d)~q{ ztt+iw{sd_tG9|-7r!t^Dnm@ggKO=#l#l4xL1Yz@ajcW^f@ox=$vFwIrFi>f=G(#P( z8%hd3V}9rO^Ql=^+5GFgLU2FR250dmC0AN`R$;Z-O|0Z6x#0%=$FslvfA6|@-jMB% zUy7F4JV9DVCPI_WA$d2Ea;8RWp&9LSMZlnX{TyDtPV#u#pakDaX zIiU=eyzPtF90QQ*H$GIdO)3axf{X36I{26a_EP*1KYu4{Z;QjDu9^@v<1E#S>qq$r zbGgY4mC)6uhXp&E7-A9f;=$#a8Ll5R(-`^BYZEZG1O^KSBBG>Gubx-EFo=D&?vXiv z>hXHczEvmdPJ+sgC)DW3$xTaV>as}j%{_@cj@3O_x4~)i2n;1q$j}zNqBBUO%Y7f> zboG$utWoQpyqIM?yq=13sd#W3b31f_!ZbOYE%7F(D>>5DlLV8ZLL#fN-ja}?w{m&X z$Gl}#NJ1i~4uI4OFVwwgx>b2xdNL{4;?bH3a^SzWuNP*eKUS5|W4949_?e5<+;@KK zb0z)8SB3^==R0XA_901UUK6H`iS|^%cVZ)mbu6{?)OM43*v+JCI??5G#!&UChQRLf znUZ=j$l*P|AbU8KsCzB-#L8=C(*V0}WT7(6x(NSrfqw7rRCtl9*p1}#e4m*Vop7ls zY%KzT5++KA0Y+UWMWy{^`6{}SEr9aUWk;mP&U)gw%C=hx$}C&OkvR`tzSi5fzE5MS z$)g40{Fv^z)J0qLqRbBtI`k`_Kq~oi{y-`4n{_*!!|oB{z;1%;y%M^zsyJ?~812!d zW>Mp#N4&DMx&oEU9MLycV-J=h;r5*I(oqw!z!DgW^{hokx4ZBOodV>j4O>aFjgG@N z^D1ku@Oa}5cGSSK2UgUdnV^A>1CCs}Smz&SJQCwvfPwBt3_rPul{ixNu9=iysFMM%h3p>N zNgRw3ym&HUO1mdz&65AY^KN&9W#s%NN^%LP&UV>MmRn`Jw9$}vv)x@+@#Yy&2qm=xi!R4m@2;GXU0=AF#^;|scF@U!uQK7r0 z*AR3`f4Li5_8GKef&rZVJd{q0UdGSkNkmOFV?T6syipXUw-v+UqkB2Duqn0P;~bs$ z{*9DDQ{%eMTTH^y?5m;MX4;Qz`dr|_(lg+189P$Dl1q`;$(*`Ie4OmuN3Z*$UR7r~ zT&tyMA(a4Ib{^9P#yy~0R}L}2h0sMR4N*GbmAdSjcj;g)V@hcCqQDE22y>XP+S!nn zRDS~E6nRKAOl%{cD>;wJD~}f!l40QIVOQEaT^IVmAT47}29SpB%4``SeN&l;?pQ3~ zspw)Oya;N*NpPvO>f{-HsfuSAXMaJ1=d>F3>79`t*cEnPc`f4nD4(^0pT2%iF7d8@ zJ2RyQ%hJ-lxcXSmhOh^jfES-urw|vD-oRwgFwB@;=}@ESka1xSW#41}dHQm_hpF4H zKB&%yajZ=Yw^U3sR8Q_;p;_H)HJXBR0&5W;QJcNG^@_>2TsRy~s)?LMU$qXs){?^`0GwQyF;5Gia{E6n+zVC|Vs|NiN3OOE~z}1P59c$o?q??NwZ|;s4_dx4- zUjMNmlj?V5oJ2)a9Q2I^{^)dX2M;u`SB|8=o8VPd+_;b#kL%6+Ys zOG{7Cat)S_;{(k=B`F-MHv}hDd0g47wy#%oXR z;Mm~JRp_Qb#Q7Dmu@PW)RL8JFUZjSkZ+hyhNEqb}TbR0cJ+{lvw=AzEH;sH(sg|;G z?r^v7nh{e%7zxhjIr%B+i5Nu+4WSMtY)i9Y7rT7_sTG77#S!HD^UN1kBCT!W zAOAR0szD2>{mX4|6sgmppre9+r6i)M`5X8v77U5V#Qq{{g?jTKmmuqhslsF`Afe5n zU&U@wv&bM(Y9GD!kXKS|DXpSn1jcbu)t29}Jm}FF$@=!^7AUuaNPaoDy<2~+ajNuK zSU~~~qF64owpCO+#01Z(ppm0_NuyVfk3R&yJ!b*gmosG9SMSYK zZ03frNU9|U-0Ox9rFZx0X)GCR+ePnig(!kY)>tfa_T(DLTVk(v&*s%^o*k}hBBa;u zO{Z!H5Sx0k!+1#=Yq_-Qo2H|yNRrOV5Cdr6F1+X*gNW+qGRbwxjHI_Ro_TG^!)ZRb zesA$QHx6|yf9Xm!j8Xm@Y4;Q)S`a39zHHmJZQHhO+qP}nuDWI0uDWI0cJ1w+o!#z@ ziQS3V$McZqC0{bm$?x}qv?hiUWZUIv-YhL) zR13WqQ{}7D%1DQB)H$qAU$)ZS0&4$$wbc)t;6LHm%z;|VI-Pt%L}ft zOQ+-GvgGwmVjJUYYhjph=GIH#B+pN;BSHTJ9WX3_C;qkd(m;}no|$PnsSysxzQo-Y zm;2Ed!a`?ny$4tQ791Rqq~4EF^A9)|EHiN$51%PYi35wP_t2=ZM1?i46!|8e=xoTBV_9mU+7UB znAL|!r+(1bdo$%)faT%PYgv4%C6i#JdmA0GHJx zBD)EvdoSC|sx`VZJtJL2Ih3J(2o%Q=jUuH<;{ejs2z>>a)EZ?0Vc1d&jOBey&$1Ys zqmGqqgF`c(LF;Y#qqhZdPW!?g2ewkfwUcU$xN3JIRb3Z#B9(^qvmag4adcjd1^rgk zzGI*G>jmwdK(8@yqy1lOfHJpv3%E@@5QcplzV&mgv&g}|_NA!sXPb?DXHi(tV2Neiz2Z>9n44Cfj}pmx&|FV{?KjfYLs7 zK0A?l4JL)yZ)o#AA@k!h*l*nhz28bh1fL6xmFp=OnSuHPEwGSwI6dT|)1=ox`z4Rt zr=%7=vU$?f6MTrBTK;oASb}R~y@qk#}Cq=;7ve)WNL!SU^c_q!g05VX1N-tqb z!N{$DVRbK17it3DT~|$yUs2-rqS=>`oi9Y#M50zPt&a=Lvn|;N5v0s|)U&aRv`m+F z!<9mS5rUAsMQhK81Kru`p=tkOY9We3H%fy(=`L|B|5&|Sc#r-ZGYV7ucnYk>{XC`H z-W`JKJGvE}E1A(Os2r3ee}%|dKJrdUpd<%p7y$s4B*`7na(%arG3A9Y;aW% zdH`tRA8C=9zKTJdWwWjE93(z><;2GsoldR)USE0PRW_+L3Ze@cB)I`A+nmPaE{o7@ zR^YIZ$cz_bO#9%mbA-Zsm+7N_**~($PyK3GYE77Wbv&dZ#OVN<9j;`lU!<$H>gH|@ z*yA^wJsjFx)R)`Zv$qGO2}f=J%2;+od-J+Xj$>*3$@N5iS@c%Q?JcxTJi z1d0pFJmL=7h&ee#*;=LCyErKR&*J$@-U!9~>3gC?&biNx!ske*ev#{nQ*&!YRFfzd z{CDN#3Zp*#B=!k87-^QL(r3G%13pU1N~c)h82w0D*3*s3sJ*HKsb%laOI0q-IZ<%b zU9#d~%*O!9#gHDBGJJ)0^5%1?u_@H%ca7DeUJvOLIRZ2XiUW*GO8eq1vUK)@3oHqZ zBq}Sdoy^g(Z?fGD&NCKM2kQh3Y>uDFq)~$Hn46`Up1+{SsVx^P-tO6G6qPsu-9*So ze;Q=|K&gkR1S-!&Hi71@?`wDM9hY4u&!nJgIxqQ~CV3v`eJ8$m=cAR^wj4=~rhB?m z|Bm$HlIo=6(YCAATmZeV$+ToLdjU-LJZ>~xg+wKbe!Z@#ebPxnnqL7UkSKBLCH;(v z>4$KT^1A`d0^ofqe>(uhHGKM<*#;8jTvJF_-j;Wm3l)c{O3XS|&WTyR=numepK*Mr z3(#nK{P>b+*-^7`@UXH86cS%F;KdyW`%$Qey!xEVNEcX8*M4u&q-B=MoKz}Lp%*A9 z*E0k-=8?Tc1A!rYreQtx&`7-%wlWl=Qs3BqylA^^@Iil}j2yhli7rgu~brKh0^oGiU0(Q`z|( zk0?OJ`RkM+Ufbs{Sl4;d&FG1aJi)nBvjUFTWYS%LS)Y}bAR}B?{TyPi7Zr!6LJxax zWghCz#tpF!x04ai0dncuz6)uBay}kr^$LZ&^AuC>^g2lu=SqM_5BnXwJ_vsujzSXu zgQ-Dox=_n_y+WNo;qIfwWh!{OkaD|q(dLeYai^Rk28E)6FSS(;uG*yZxR36lxY zX8xt_76D{-VMUkIQIc z@kFLwp~~5>lY}c8qdOxVvqq%^7i4ObnzrmziW8-ttUBm%lxSn;bC6?0hvLp5J>$xGL2)EQCPCXwQ|b8T|lSA zm==oXMnrK*En`iS!$;W`G4YGLsJZJNwvzXqB7Ihwmp)DGd%QoBhJIu)-}jkVyXz`KI#}*++qGrGn4IA0 zPax?mMEgD5=823Pa$FmZ4|d_ZO(RY30XgN^;12jQ`>P@dU-Kj@uPBqDg=D)-gvXnw z^D!Kv=V&&l3$>H*8)676C)W3>MJ`w)u=va0j?8>MMA6ZK&>k#)>cNZXrS%bX0}U=W zyjEnU!R>6nAH{OcwYuUCZhh2fepj`eVISvbF@|rh8ZOj#HqWE0UOs1kZ^;SitRJHX z$eaeCt}UWNfKg~gCIN5?BH%$ApD0hNde_Rrw;-e`OI8PK7A=XWXsttF!ua$Egj+6; zE|=sJfKE~)-6>3qH4BcJmp}+<9Q{*m&ucGp;nCwO(l1c>!?;o8oMhzEeVCbDY&PSn zaev%JTvO_e)D$rlw~bd(JU84VW3SZ6oF~t~R+795Z7Z0$XRk?o-SwmAX_QZdBf?4U z|KV)Lgh87Jm2=Ej(Mo!p*heH7{#99aZz0Y!vo0vgQt8uCCEPtN;79Q5i5M_o77H07 zDPI2BeBW}{CW}@q?t`ab5x)JKnO1;;etG(E(6jA->cMCe7yC=9(ZI4)Q~bn~=F$n+ zPHyi$4C1cdjOmvLa{@T3o-!mamCeh>!~YfoYw60_SYBWb3jvc^egs!Js)c!fowGTT(X@% zmk%mEnoK>~TQ;L`8`&j}>s>?2zR^9w&93T$EwrnNP|n<+_>^bDK)NswE`#zx+2&!B z4(o8oD#$j#Xm)W%b0$w-VAAVucFTy=r}X;yN@B|szI7AO27-z8U^rO#K4{+HNMFRR ztCrSLZ0^Z_EX9wAHVsL(O<@0{1akNTZK$sNx_5GvNw0<@7`3WvOiw6-sIzl^4$?Nv zc*JI5>;NsWA05dDN5o8SoQ@%zgVh`d6aRhrz%xsW!+;>Vn%_p`ro1F6HvFat{BJcv z;VW#p@*S}MU-HuOWUb~XDl*M`(^+F?Vo=%ON2F?V4T$D^zu1;@SPS?iC@-;XRXBj$ci$0`<)@l)8vn`(>Zn?mSz*eQ2Bbk7qN9DodMG4 zG0Kq29{!~WpqHhp$*wF02v)O_YHwZVu7;PHzhcfqv z6gynzXSz754lU;fYyOQE47ScJ;f0%owda`I&B$DHAKU?@_jtva)8a)2bCf`ruk@uQ z2sv%GD|xo{h1W_!nDu{d8KhVsyT~yG-Aak#XJ;&W_`9swFqjWSAw@w64gTW~N4Y1J zNsnS9Tf{gf_r$HtaM{{MdA7P!_5g_9p$W%k;EL`;v4xrP;PvT^Pu$eujKz)=50%-- zqD?-`d%Ze^$>Ju_%9KcL(w`4}bae`Giv`eQ2*cheClZRoJm^)vlc=a5lov}7Fra8{ z7S)D(CNAIlqa2aq3QF)4_NzaZQ<(e^9OlUxQQOGKz7jI5;PK4Lx<5R5T-hef*oqM; zW9q#|tV0-L>AW}QYsqi?6_kxhxi_b*SP(G<} zygV_i4q6=WEZqaEUB>N+{ua)PmH^Uv#m|AapSGhC0Sk3(-Kc6T_d&$x0nMrPzFx~* zBHuJ--wcki%C;H!3!&9k43L?`p@1?ZI*lWEB9!_;s%oEFrMJIHY6pq97v8zbY|QmN zG5)%)|N4F=FUqj{27WWW*(vh2zn8WNce+138sGQ3d2&+dD}4dqhd$gvnuU^#zPmbZ z1K!*w*xk_gZs46%h)QCYA7Pdzxywojjb;Q4B-qc2@mxzu&{=tcJ3Zgp&#fhrk|<0O zH?BU?PX(Gx15V;M@(-$cH)^d_X^6c1QQ2?}r9$wOhg)<;Ou?^8`1=dv-hfj|?d%Vm z=bBoy_l_v&@8qS`>E4t3<7^QR(P~MSOdMJgp<%Z%?tWUdaV%lNS&a$}#j<8-FpuDw zpHWX0u!ix|un?w!&5zFdG14Wzg4@Noh|tv8k=^}p)V*oC)h|)8(9)>4n-6WvRI+e+ z65(CrDx4-uC=y|A3UH>_RlHDu{I#StIXIjZw191z*8Vc3N+n{OP z&M6Nj#3X_ANxn1~|3WL=q2{=B?G}T0W53v!P3s)g#>_(6<fL^o&apk%9h z%WZq898G(09YYPV$(_B477dZT8L`TeUA!M{=O;7KXnLyLn^hwvA=S#%jUQXbcI~xj zE{bXxd;YB^BhHegmo3e|}4TkSL;1W)mx$B+`L?|SouGgwlu+E#{{Xv=qpJc^O4cpf!5H^!))B+5Y>pd~wvV?DRX4Hs&oY zO}a#mcRjn?)JGHF+#v&THidQ&v$I#4NQ0Yql{pX^nH8>Gg>9y~y7~DvT8z0dljNoa z?7tf`Z++YSoPs8N{V8-Ax^Bwg3zADX$+(c1Zyrie3IuXP^6Vz6b`_avFjCY>O)of4 z7V8@6do(2ZAc2s(E*JPpXOHh9th4A_LnP%KkcXlOWb0B%ZVc7o2%eN~i26ZNM+jn; zYMEbY1XGU?z&cw#7o|o7`-#ndF@x`(MdD{Rt(T~gyx^eGSL1UR(u%MqWghk5<~aK1 zhd!SI$zILJgC^!j)#2*I!rmi+mr+cw0K1#C15VgFXfo`&P5+>Md}GL^NIvG1H*CUM zcCUpm&q|$=n$_xMho*kFfb_PRWqHIP40a0e#THcJ1w~kMf3J${$%j>aTkT$ydOv4M zvq4#YNno0J2=v;pp`f!4r`W#vRQm7aOfQ(-0%5U)gU+>%2@KNgLDgu2o-s#DNH@Xx z42=pT2RcEel|#sdTj$JgAyIswiUCZxj~;3(_L#Ag*O`0;yc?Cm=tB>as{wj;J361I zn7kT%EBz)m!)3Q8iq^p*;^aqz$9-Jy1E_Ba)^`Ao#Q$6ZmUHQuc%P`6L_wXRuAZKT z!DB8~F6Lc*R?s_D%+b)fo~~7l+afwt8~Z|*m@6Z9i)mRe?+O)fTp|`)tWI#s^AZYmP|a#m7ZFv*QVDn}^R2j?F!PX#gi=c}#u0Zlhl}zkd6vBC6$t?UR@(vI}%u<DmEM+sQleY@49lmdlQCURDRJ+)yqT7iZ9#5`0w8p z$Vc*Qy66`7${y;>GF4g`!wyIjvk2!D-0Igpm@f%!dis~zuGk$ ziP@>Wv3rc6`j~TH91032MfLEeDW2$RokZqKMEz%Kf4 z{ScutB16xU#_uLHs;S>Ena>IyrmdMW)^i%s&2?!o}M3Vvqm=d$lxsR+KLDC!H< zQGyifkl|#)8_Za%@jj=^6t$NlUY=|0%U(GC3FW3TucD{g2U&g$e-28@nPm!1echd2 zB1fPeRfZ71$<{lf*ajD&E&XR#L{tpM1XcU`>68jc)**3-xT4bCVhol~kKunY$ga2YSQ9z-_4g4g@Qrc~8xtr6L)nl-&%nxAs{%Z&zL_ zO!LcXytH(Z`l)@}&rB4{{q|-}P%FQ%J3)}4S9YFrcE{Y-sHdYsO8n);1u1#l#f=|o zY%`{dfD=}jgDUB%rK)xJzJl0q9`Bm?W$`G=Ix(>hG6j*1C(~==4+fGZYur^MHKEL% zmfSvVJeTsi<=Y+xg{G0&Klvb_8r^m{r^u^KDkV zp-O_RQ<+)YYe94LD3jd`2)9=$%30XcQ|W?$w8O7b5>9{E+33o@N(2gT@nQ z)o;6C3Ljs`kNc>mz?*y8GAj9TXnZW*=DFCe=I!jN?>&lm{sMg=nJcr*<{6EVbK!%x znv+Iw^aC|388EICbA{)|3Jv~e@bH8?qdL`L;l$Q)P(VbZSB90|!w^jwAp}WULZtbT z`I0mSJmk-)Jp=|k8QVBKG&hiR5gqxWs-NKZ!7AbY*6F%mnTqui)~Mf=vN`!y9xUBMs> z{m~^CplO7jr4lq-ykyFZsY))=!L|#`czXR!E>Gq`UuTNaU;Hg&nCt%)$-(|#5QzUT zl0#HfUQJQqKS>TD4Mv9lwaUTH_&-$+PELYDB&09UAnS|A}=N)0@zn(wkbE zTe$p(#_>Nu4okOxG{^so%3){uudMpNLvuLTxH{82(*Hk&4pTQ%J9=kJ4|B>Ez(lPvMdr3Y;VtC z`j`H`ey(zvH=<3qdhfpO%rVa^QdT!cWDCmWq5=Q` z;s_A@_Jt{s0|t~tVh`gK^g|^CZv^Kuo(U*`%accxrb5#!^x*@-n9&1XeSLLL|3|X* zx?c`~8QD7^C^8y#9WHHQdKj$$j5Rnwm*4=oM zANRlrQ~{JbICrc6BtTyl7)AD~|Mz7yN)TM(PY}m%tzxiNdwVuVARt2^?J$hZEzF~1 zD?2zhpustyRZ~5n6r90lU#$MGZ9mN0sSChW&DC${=h&w@LBzNIESZ^^0yj9aw|qno zX+Mw=G#G_spPB2ugCSVPdiF09OQUPp;Fs){48cETgCV%jiXBiQx*9;nfc9sppg9wH zcwi)R1=HxWTCz>w(BPED)E+Kq<8R=#ZVsd03OS@BQ1$@aPV)8cXKQ14=ce~>I2wYt zbF_YJMi*Cu<+?DA?m$!0FUEifMxSY#0XhIX0>n|UXCN-10X#Exn?B_-FK)j-9|E!LISvZF9j1B;qfiwi~nB4_K zqlS@P7;HfD2yg*-h-?8jfV;Ih|9lt&VKcbaKhIybKWntjl~L5v6;jOKn~(llkdPJN z{n?@U=>3BOupkYEK_Ku~+XUC`_I-{A3MeQD;K-wsd-qPz0 z%?-|9v>_bQ!aV&alL+X{)qUpYyIldK4WaA7sfDu%`tf)f&n z=}<76wZF1druJa0zpWuSTRZ^BLF=AM680 zR9|EoG9$Yn(Unj5_ke&llYNo6{bdi?90p6j*#>`C{E%zFV}BvqKy1kRAk*fa*asdm zzs0v0axs_D+@5}=+S~u7TCe;*e>;)c9{CZ}P~Z5ELRJ8|b+nPY_-X#7YQ9GGLEeR- z9~-`a4IyiP1T@I~v4*r7-+>LEH+}*e%znn9wawW+|1G6>f)82Qzw46Es0F^7F|dbj zb9kpU{T2UsJ^6VFUAcM#AGC7&05)Xh{taxH`dva_4Z6gKupYRE4{6=|8Pgn?e0cl! zR*#?1U*-q1I=Kcc-5)QOftP*#pG#5@Fz|eS1bD-08=3KUR0S z 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

kTc>TvK1JW>YuTEzRR6}T7?}qn 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 A#{d8T literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example1.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example1.cpp new file mode 100644 index 00000000000..1e4b7d0ec35 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example1.cpp @@ -0,0 +1,97 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example1.cpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + * + * Very simple example for testing qpOASES using the QProblem class. + */ + + + +#include + + +/** Example for qpOASES main function using the QProblem class. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + /* Setup data of first QP. */ + real_t H[2*2] = { 1.0, 0.0, 0.0, 0.5 }; + real_t A[1*2] = { 1.0, 1.0 }; + real_t g[2] = { 1.5, 1.0 }; + real_t lb[2] = { 0.5, -2.0 }; + real_t ub[2] = { 5.0, 2.0 }; + real_t lbA[1] = { -1.0 }; + real_t ubA[1] = { 2.0 }; + + /* Setup data of second QP. */ + real_t g_new[2] = { 1.0, 1.5 }; + real_t lb_new[2] = { 0.0, -1.0 }; + real_t ub_new[2] = { 5.0, -0.5 }; + real_t lbA_new[1] = { -2.0 }; + real_t ubA_new[1] = { 1.0 }; + + + /* Setting up QProblem object. */ + QProblem example( 2,1 ); + + Options options; + example.setOptions( options ); + + /* Solve first QP. */ + int nWSR = 10; + example.init( H,g,A,lb,ub,lbA,ubA, nWSR ); + + /* Get and print solution of second QP. */ + real_t xOpt[2]; + real_t yOpt[2+1]; + example.getPrimalSolution( xOpt ); + example.getDualSolution( yOpt ); + printf( "\nxOpt = [ %e, %e ]; yOpt = [ %e, %e, %e ]; objVal = %e\n\n", + xOpt[0],xOpt[1],yOpt[0],yOpt[1],yOpt[2],example.getObjVal() ); + + /* Solve second QP. */ + nWSR = 10; + example.hotstart( g_new,lb_new,ub_new,lbA_new,ubA_new, nWSR ); + + /* Get and print solution of second QP. */ + example.getPrimalSolution( xOpt ); + example.getDualSolution( yOpt ); + printf( "\nxOpt = [ %e, %e ]; yOpt = [ %e, %e, %e ]; objVal = %e\n\n", + xOpt[0],xOpt[1],yOpt[0],yOpt[1],yOpt[2],example.getObjVal() ); + + example.printOptions(); + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example1a.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example1a.cpp new file mode 100644 index 00000000000..57a28757cc2 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example1a.cpp @@ -0,0 +1,85 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example1a.cpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + * + * Very simple example for testing qpOASES using the SQProblem class. + */ + + + +#include + + +/** Example for qpOASES main function using the SQProblem class. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + /* Setup data of first QP. */ + real_t H[2*2] = { 1.0, 0.0, 0.0, 0.5 }; + real_t A[1*2] = { 1.0, 1.0 }; + real_t g[2] = { 1.5, 1.0 }; + real_t lb[2] = { 0.5, -2.0 }; + real_t ub[2] = { 5.0, 2.0 }; + real_t lbA[1] = { -1.0 }; + real_t ubA[1] = { 2.0 }; + + /* Setup data of second QP. */ + real_t H_new[2*2] = { 1.0, 0.5, 0.5, 0.5 }; + real_t A_new[1*2] = { 1.0, 5.0 }; + real_t g_new[2] = { 1.0, 1.5 }; + real_t lb_new[2] = { 0.0, -1.0 }; + real_t ub_new[2] = { 5.0, -0.5 }; + real_t lbA_new[1] = { -2.0 }; + real_t ubA_new[1] = { 1.0 }; + + + /* Setting up SQProblem object. */ + SQProblem example( 2,1 ); + + /* Solve first QP. */ + int nWSR = 10; + example.init( H,g,A,lb,ub,lbA,ubA, nWSR,0 ); + + /* Solve second QP. */ + nWSR = 10; + example.hotstart( H_new,g_new,A_new,lb_new,ub_new,lbA_new,ubA_new, nWSR,0 ); + + /* Get and print solution of second QP. */ + real_t xOpt[2]; + example.getPrimalSolution( xOpt ); + printf( "\nxOpt = [ %e, %e ]; objVal = %e\n\n", xOpt[0],xOpt[1],example.getObjVal() ); + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example1b.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example1b.cpp new file mode 100644 index 00000000000..102155a666c --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example1b.cpp @@ -0,0 +1,86 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example1b.cpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + * + * Very simple example for testing qpOASES using the QProblemB class. + */ + + +#include + + +/** Example for qpOASES main function using the QProblemB class. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + /* Setup data of first QP. */ + real_t H[2*2] = { 1.0, 0.0, 0.0, 0.5 }; + real_t g[2] = { 1.5, 1.0 }; + real_t lb[2] = { 0.5, -2.0 }; + real_t ub[2] = { 5.0, 2.0 }; + + /* Setup data of second QP. */ + real_t g_new[2] = { 1.0, 1.5 }; + real_t lb_new[2] = { 0.0, -1.0 }; + real_t ub_new[2] = { 5.0, -0.5 }; + + + /* Setting up QProblemB object. */ + QProblemB example( 2 ); + + Options options; + //options.enableFlippingBounds = BT_FALSE; + options.initialStatusBounds = ST_INACTIVE; + options.numRefinementSteps = 1; + options.enableCholeskyRefactorisation = 1; + example.setOptions( options ); + + /* Solve first QP. */ + int nWSR = 10; + example.init( H,g,lb,ub, nWSR,0 ); +// printf( "\nnWSR = %d\n\n", nWSR ); + + /* Solve second QP. */ + nWSR = 10; + example.hotstart( g_new,lb_new,ub_new, nWSR,0 ); +// printf( "\nnWSR = %d\n\n", nWSR ); + + /* Get and print solution of second QP. */ + real_t xOpt[2]; + example.getPrimalSolution( xOpt ); + printf( "\nxOpt = [ %e, %e ]; objVal = %e\n\n", xOpt[0],xOpt[1],example.getObjVal() ); + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example2.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example2.cpp new file mode 100644 index 00000000000..a770dc70efe --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example2.cpp @@ -0,0 +1,124 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example2.cpp + * \author Hans Joachim Ferreau (thanks to Boris Houska) + * \version 3.0 + * \date 2008-2014 + * + * Very simple example for testing qpOASES in combination + * with the SolutionAnalysis class. + */ + + + +#include + + +/** Example for qpOASES main function using the SolutionAnalysis class. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + /* Setup data of first QP. */ + real_t H[2*2] = { 1.0, 0.0, 0.0, 0.5 }; + real_t A[1*2] = { 1.0, 1.0 }; + real_t g[2] = { 1.5, 1.0 }; + real_t lb[2] = { 0.5, -2.0 }; + real_t ub[2] = { 5.0, 2.0 }; + real_t lbA[1] = { -1.0 }; + real_t ubA[1] = { 2.0 }; + + /* Setup data of second QP. */ + real_t H_new[2*2] = { 1.0, 0.5, 0.5, 0.5 }; + real_t A_new[1*2] = { 1.0, 5.0 }; + real_t g_new[2] = { 1.0, 1.5 }; + real_t lb_new[2] = { 0.0, -1.0 }; + real_t ub_new[2] = { 5.0, -0.5 }; + real_t lbA_new[1] = { -2.0 }; + real_t ubA_new[1] = { 1.0 }; + + + /* Setting up SQProblem object and solution analyser. */ + SQProblem example( 2,1 ); + SolutionAnalysis analyser; + + /* Solve first QP ... */ + int nWSR = 10; + example.init( H,g,A,lb,ub,lbA,ubA, nWSR,0 ); + + /* ... and analyse it. */ + real_t maxKKTviolation; + analyser.getMaxKKTviolation( &example, maxKKTviolation ); + printf( "maxKKTviolation: %e\n", maxKKTviolation ); + + /* Solve second QP ... */ + nWSR = 10; + example.hotstart( H_new,g_new,A_new,lb_new,ub_new,lbA_new,ubA_new, nWSR,0 ); + + /* ... and analyse it. */ + analyser.getMaxKKTviolation( &example, maxKKTviolation ); + printf( "maxKKTviolation: %e\n", maxKKTviolation ); + + +// ------------ VARIANCE-COVARIANCE EVALUATION -------------------- + + real_t *Var = new real_t[5*5]; + real_t *Primal_Dual_Var = new real_t[5*5]; + + int run1, run2; + for( run1 = 0; run1 < 5*5; run1++ ) + Var[run1] = 0.0; + + Var[0] = 1.0; + Var[6] = 1.0; + +// ( 1 0 0 0 0 ) +// ( 0 1 0 0 0 ) +// Var = ( 0 0 0 0 0 ) +// ( 0 0 0 0 0 ) +// ( 0 0 0 0 0 ) + + + analyser.getVarianceCovariance( &example, Var,Primal_Dual_Var ); + + printf("\nPrimal_Dual_VAR = \n"); + for( run1 = 0; run1 < 5; run1++ ){ + for( run2 = 0; run2 < 5; run2++ ){ + printf(" %10f", Primal_Dual_Var[run1*5+run2]); + } + printf("\n"); + } + + delete[] Primal_Dual_Var; + delete[] Var; + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example3.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example3.cpp new file mode 100644 index 00000000000..8fb1cea8336 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example3.cpp @@ -0,0 +1,88 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example3.cpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2008-2014 + * + * Example demonstrating usage of qpOASES for solving a QP sequence of the + * Online QP Benchmark Collection. In order to run it, you have to download + * "Example 02" from from http://www.qpOASES.org/onlineQP/ and store it into + * the directory bin/chain80w/. + */ + + + +#include + + +/** Example for qpOASES main function using the OQP interface. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + /* 1) Define benchmark arguments. */ + BooleanType isSparse = BT_FALSE; + Options options; + options.setToMPC(); + options.printLevel = PL_NONE; + + int nWSR = 600; + real_t maxCPUtime = 10.0; /* seconds */ + real_t maxStationarity, maxFeasibility, maxComplementarity; + + /* 2) Run benchmark. */ + if ( runOQPbenchmark( "./chain80w/", + isSparse, + options, + nWSR, + maxCPUtime, + maxStationarity, + maxFeasibility, + maxComplementarity + ) != SUCCESSFUL_RETURN ) + { + myPrintf( "In order to run this example, you need to download example no. 02\nfrom the Online QP Benchmark Collection website first!\n" ); + return -1; + } + + /* 3) Print results. */ + printf( "\n\n" ); + printf( "OQP Benchmark Results:\n" ); + printf( "======================\n\n" ); + printf( "maximum violation stationarity: %.3e\n",maxStationarity ); + printf( "maximum violation feasibility: %.3e\n",maxFeasibility ); + printf( "maximum violation complementarity: %.3e\n",maxComplementarity ); + printf( "\n" ); + printf( "maximum CPU time: %.3f milliseconds\n\n",1000.0*maxCPUtime ); + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example3b.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example3b.cpp new file mode 100644 index 00000000000..58d102250dd --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example3b.cpp @@ -0,0 +1,88 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example3b.cpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2008-2014 + * + * Example demonstrating usage of qpOASES for solving a QP sequence of the + * Online QP Benchmark Collection. In order to run it, you have to download + * "Example 02" from http://www.qpOASES.org/onlineQP/ and store it into + * the directory bin/chain80/. + */ + + + +#include + + +/** Example for qpOASES main function using the OQP interface. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + /* 1) Define benchmark arguments. */ + BooleanType isSparse = BT_FALSE; + Options options; + options.setToMPC(); + options.printLevel = PL_NONE; + + int nWSR = 300; + real_t maxCPUtime = 10.0; /* seconds */ + real_t maxStationarity, maxFeasibility, maxComplementarity; + + /* 2) Run benchmark. */ + if ( runOQPbenchmark( "./chain80/", + isSparse, + options, + nWSR, + maxCPUtime, + maxStationarity, + maxFeasibility, + maxComplementarity + ) != SUCCESSFUL_RETURN ) + { + myPrintf( "In order to run this example, you need to download example no. 02\nfrom the Online QP Benchmark Collection website first!\n" ); + return -1; + } + + /* 3) Print results. */ + printf( "\n\n" ); + printf( "OQP Benchmark Results:\n" ); + printf( "======================\n\n" ); + printf( "maximum violation stationarity: %.3e\n",maxStationarity ); + printf( "maximum violation feasibility: %.3e\n",maxFeasibility ); + printf( "maximum violation complementarity: %.3e\n",maxComplementarity ); + printf( "\n" ); + printf( "maximum CPU time: %.3f milliseconds\n\n",1000.0*maxCPUtime ); + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example4.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example4.cpp new file mode 100644 index 00000000000..ac716ad48dd --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example4.cpp @@ -0,0 +1,172 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example4.cpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2009-2014 + * + * Very simple example for testing qpOASES (using the possibility to specify + * user-defined constraint product function). + */ + + + +#include + +#include +#include "example4CP.cpp" + + +/** Example for qpOASES main function using the possibility to specify + * user-defined constraint product function. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + int i,j; + + /* Setup data of first QP... */ + real_t H[7*7]; + real_t A[50*7]; + real_t g[7]; + real_t lbA[50]; + + /* ( 1.0 0.5 | ) + * ( 0.5 2.0 | ) + * ( --------+------------------- ) + * H = ( | 1e-6 ) + * ( | 1e-6 ) + * ( | ... ) + * ( | 1e-6 ) */ + for( i=0; i<7*7; ++i ) + H[i] = 0.0; + for( i=2; i<7; ++i ) + H[i*7+i] = 1.0e-6; + H[0] = 1.0; + H[1] = 0.5; + H[7] = 0.5; + H[8] = 2.0; + + /* ( x.x x.x | 1.0 ) + * ( x.x x.x | ... ) + * ( x.x x.x | 1.0 ) + * ( x.x x.x | 1.0 ) + * A = ( x.x x.x | ... ) + * ( x.x x.x | 1.0 ) + * ( x.x x.x | ... ) + * ( x.x x.x | 1.0 ) + * ( x.x x.x | ... ) + * ( x.x x.x | 1.0 ) */ + for( i=0; i<50*7; ++i ) + A[i] = 0.0; + for( i=0; i<50; ++i ) + { + for( j=0; j<2; ++j ) + A[i*7+j] = (real_t)rand() / (real_t)RAND_MAX; + + A[i*7 + (i/10)+2] = 1.0; + } + + /* ( -1.0 ) + * ( -0.5 ) + * ( ---- ) + * g = ( ) + * ( ) + * ( ) + * ( ) */ + for( i=0; i<7; ++i ) + g[i] = 0.0; + g[0] = -1.0; + g[1] = -0.5; + + for( i=0; i<50; ++i ) + lbA[i] = 1.0; + + /* ... and setting up user-defined constraint product function. */ + MyConstraintProduct myCP( 7,50,A ); + + + /* Setting up QProblem object and set construct product function. */ + QProblem exampleCP( 7,50 ); + exampleCP.setPrintLevel( PL_NONE ); + + exampleCP.setConstraintProduct( &myCP ); + + + /* Solve first QP. */ + real_t cputime = 1.0; + int nWSR = 100; + exampleCP.init( H,g,A,0,0,lbA,0, nWSR,&cputime ); + + + /* Solve second QP using a modified gradient. */ + g[0] = -2.0; + g[1] = 0.5; + + cputime = 1.0; + nWSR = 100; + exampleCP.hotstart( g,0,0,lbA,0, nWSR,&cputime ); + + /* Get and print solution of second QP. */ + real_t xOpt[7]; + exampleCP.getPrimalSolution( xOpt ); + printf( "\nxOpt = [ %e, %e, %e ... ]; objVal = %e\n", xOpt[0],xOpt[1],xOpt[2],exampleCP.getObjVal() ); + printf( "CPU time: %.3f microseconds\n\n", cputime*1.0e6 ); + + + + /* Do the same without specifying constraint product. */ + QProblem example( 7,50 ); + example.setPrintLevel( PL_NONE ); + + /* Solve first QP. */ + g[0] = -1.0; + g[1] = -0.5; + + cputime = 1.0; + nWSR = 100; + example.init( H,g,A,0,0,lbA,0, nWSR,&cputime ); + + /* Solve second QP using a modified gradient. */ + g[0] = -2.0; + g[1] = 0.5; + + cputime = 1.0; + nWSR = 100; + example.hotstart( g,0,0,lbA,0, nWSR,&cputime ); + + /* Get and print solution of second QP. */ + example.getPrimalSolution( xOpt ); + printf( "\nxOpt = [ %e, %e, %e ... ]; objVal = %e\n", xOpt[0],xOpt[1],xOpt[2],example.getObjVal() ); + printf( "CPU time: %.3f microseconds\n\n", cputime*1.0e6 ); + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example4CP.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example4CP.cpp new file mode 100644 index 00000000000..976e4e99381 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example4CP.cpp @@ -0,0 +1,111 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example4CP.cpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2009-2014 + * + * Sample implementation of the ConstraintProduct class tailored for Example4. + */ + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Example illustrating the use of the \a ConstraintProduct class. + * + * Example illustrating the use of the \a ConstraintProduct class. + * + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + */ +class MyConstraintProduct : public ConstraintProduct +{ + public: + /** Default constructor. */ + MyConstraintProduct( ) {}; + + /** Constructor. */ + MyConstraintProduct( int _nV, + int _nC, + real_t* _A + ) + { + nV = _nV; + nC = _nC; + A = _A; + }; + + /** Copy constructor (flat copy). */ + MyConstraintProduct( const MyConstraintProduct& rhs + ) + { + nV = rhs.nV; + nC = rhs.nC; + A = rhs.A; + }; + + /** Destructor. */ + virtual ~MyConstraintProduct( ) {}; + + /** Assignment operator (flat copy). */ + MyConstraintProduct& operator=( const MyConstraintProduct& rhs + ) + { + if ( this != &rhs ) + { + nV = rhs.nV; + nC = rhs.nC; + A = rhs.A; + } + else + return *this; + }; + + virtual int operator() ( int constrIndex, + const real_t* const x, + real_t* const constrValue + ) const + { + constrValue[0] = 1.0 * x[(constrIndex/10)+2]; + + for( int i=0; i<2; ++i ) + constrValue[0] += A[constrIndex*nV + i] * x[i]; + + return 0; + }; + + protected: + int nV; /**< Number of variables. */ + int nC; /**< Number of constraints. */ + real_t* A; /**< Pointer to full constraint matrix (typically not needed!). */ +}; + + +END_NAMESPACE_QPOASES + diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/example5.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/example5.cpp new file mode 100644 index 00000000000..f5f611f67c3 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/example5.cpp @@ -0,0 +1,200 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/example5.cpp + * \author Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2011-2014 + * + * Very simple example for testing qpOASES (using the possibility to + * compute the local linear feedback law) + */ + + + +#include + +#include +#include "example4CP.cpp" + + +/** Example for qpOASES main function using the possibility to specify + * user-defined constraint product function. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + int i,j,jj; + real_t d = 0.0; + + /* Setup data of first QP... */ + real_t H[7*7]; + real_t A[50*7]; + real_t g[7]; + real_t lbA[50]; + + /* ( 1.0 0.5 | ) + * ( 0.5 2.0 | ) + * ( --------+------------------- ) + * H = ( | 1e-6 ) + * ( | 1e-6 ) + * ( | ... ) + * ( | 1e-6 ) */ + for( i=0; i<7*7; ++i ) + H[i] = 0.0; + for( i=2; i<7; ++i ) + H[i*7+i] = 1.0e-6; + H[0] = 1.0; + H[1] = 0.5; + H[7] = 0.5; + H[8] = 2.0; + + /* ( x.x x.x | 1.0 ) + * ( x.x x.x | ... ) + * ( x.x x.x | 1.0 ) + * ( x.x x.x | 1.0 ) + * A = ( x.x x.x | ... ) + * ( x.x x.x | 1.0 ) + * ( x.x x.x | ... ) + * ( x.x x.x | 1.0 ) + * ( x.x x.x | ... ) + * ( x.x x.x | 1.0 ) */ + for( i=0; i<50*7; ++i ) + A[i] = 0.0; + for( i=0; i<50; ++i ) + { + for( j=0; j<2; ++j ) + A[i*7+j] = (real_t)rand() / (real_t)RAND_MAX; + + A[i*7 + (i/10)+2] = 1.0; + } + + /* ( -1.0 ) + * ( -0.5 ) + * ( ---- ) + * g = ( ) + * ( ) + * ( ) + * ( ) */ + for( i=0; i<7; ++i ) + g[i] = 0.0; + g[0] = -1.0; + g[1] = -0.5; + + for( i=0; i<50; ++i ) + lbA[i] = 1.0; + + /* ... and setting up user-defined constraint product function. */ + MyConstraintProduct myCP( 7,50,A ); + + + /* Setting up QProblem object and set construct product function. */ + QProblem example( 7,50 ); + example.setConstraintProduct( &myCP ); + + + /* Solve first QP. */ + real_t cputime = 1.0; + int nWSR = 100; + example.init( H,g,A,0,0,lbA,0, nWSR,&cputime ); + + /* Get and print solution of QP. */ + real_t xOpt[7], yOpt[7+50]; + example.getPrimalSolution( xOpt ); + example.getDualSolution( yOpt ); + + + /* Compute local linear feedback law */ + const int n_rhs = 7+7+50; + real_t g_in[7*n_rhs]; + real_t b_in[7*n_rhs]; + real_t bA_in[50*n_rhs]; + real_t x_out[7*n_rhs]; + real_t y_out[(7+50)*n_rhs]; + + int ii; + memset (g_in, 0, sizeof (g_in)); + memset (b_in, 0, sizeof (b_in)); + memset (bA_in, 0, sizeof (bA_in)); + + for ( ii = 0; ii < 7; ++ii ) + g_in[ii*7 + ii] = 1.0; + for ( ii = 0; ii < 7; ++ii ) + b_in[(ii+7)*7 + ii] = 1.0; + for ( ii = 0; ii < 50; ++ii ) + bA_in[(ii+14)*50 + ii] = 1.0; + + example.solveCurrentEQP ( n_rhs, g_in, b_in, b_in, bA_in, bA_in, x_out, y_out ); + + /* Verify validity of local feedback law by perturbation and hot starts */ + real_t perturb = 1.0e-6; + real_t nrm = 0.0; + for ( ii = 0; ii < n_rhs; ++ii ) + { + for ( jj = 0; jj < 7; ++jj ) + g_in[ii*7 + jj] = g[jj] + g_in[ii*7+jj]*perturb; + for ( jj = 0; jj < 50; ++jj ) + bA_in[ii*50 + jj] = lbA[jj] + bA_in[ii*50+jj]*perturb; + + nWSR = 100; + example.hotstart( &g_in[ii*7],0,0,&bA_in[ii*50],0, nWSR, 0 ); + + real_t xPer[7], yPer[7+50]; + example.getPrimalSolution( xPer ); + example.getDualSolution( yPer ); + + for ( jj = 0; jj < 7; ++jj ) + { + d = getAbs (x_out[ii*7+jj]*perturb - (xPer[jj]-xOpt[jj]) ); + if (nrm < d) nrm=d; + } + for ( jj = 0; jj < 7+50; ++jj ) + { + d = getAbs (y_out[ii*(7+50)+jj]*perturb - (yPer[jj]-yOpt[jj]) ); + if (nrm < d) nrm=d; + } + } + printf ("Maximum perturbation over all directions: %e\n", nrm); + + /* // print feedback matrix + for (ii = 0; ii < n_rhs; ++ii) + { + printf ("x: "); + for (jj = 0; jj < 7; ++jj ) + printf ("%8.2e ", x_out[ii*7+jj]); + printf (" y: "); + for (jj = 0; jj < 7+50; ++jj ) + printf ("%8.2e ", y_out[ii*(7+50)+jj]); + printf("\n"); + } +*/ + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/exampleLP.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/exampleLP.cpp new file mode 100644 index 00000000000..b7e2f3a3c63 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/exampleLP.cpp @@ -0,0 +1,87 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/exampleLP.cpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2008-2014 + * + * Very simple example for solving a LP sequence using qpOASES. + */ + + + +#include + + +/** Example for qpOASES main function solving LPs. */ +int main( ) +{ + USING_NAMESPACE_QPOASES + + /* Setup data of first LP. */ + real_t A[1*2] = { 1.0, 1.0 }; + real_t g[2] = { 1.5, 1.0 }; + real_t lb[2] = { 0.5, -2.0 }; + real_t ub[2] = { 5.0, 2.0 }; + real_t lbA[1] = { -1.0 }; + real_t ubA[1] = { 2.0 }; + + /* Setup data of second LP. */ + real_t g_new[2] = { 1.0, 1.5 }; + real_t lb_new[2] = { 0.0, -1.0 }; + real_t ub_new[2] = { 5.0, -0.5 }; + real_t lbA_new[1] = { -2.0 }; + real_t ubA_new[1] = { 1.0 }; + + + /* Setting up QProblem object with zero Hessian matrix. */ + QProblem example( 2,1,HST_ZERO ); + + Options options; + //options.setToMPC(); + example.setOptions( options ); + + /* Solve first LP. */ + int nWSR = 10; + example.init( 0,g,A,lb,ub,lbA,ubA, nWSR,0 ); + + /* Solve second LP. */ + nWSR = 10; + example.hotstart( g_new,lb_new,ub_new,lbA_new,ubA_new, nWSR,0 ); + + + /* Get and print solution of second LP. */ + real_t xOpt[2]; + example.getPrimalSolution( xOpt ); + printf( "\nxOpt = [ %e, %e ]; objVal = %e\n\n", xOpt[0],xOpt[1],example.getObjVal() ); + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/index.html b/3rdparty/qpOASES/qpOASES-3.0/examples/index.html new file mode 100644 index 00000000000..9b354532ede --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/index.html @@ -0,0 +1,19 @@ +qpOASES - Revision 198: /stable/3.0/examples + +

qpOASES - Revision 198: /stable/3.0/examples

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/examples/qrecipe.cpp b/3rdparty/qpOASES/qpOASES-3.0/examples/qrecipe.cpp new file mode 100644 index 00000000000..1304ac739ce --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/examples/qrecipe.cpp @@ -0,0 +1,495 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file examples/qrecipe.cpp + * \author Andreas Potschka + * \version 3.0 + * \date 2007-2014 + * + * QRECIPE example from the CUTEr test set with sparse matrices. + */ + + + +#include + +USING_NAMESPACE_QPOASES + + +/** Infinity constant for qrecipe example. */ +const real_t Inf = INFTY; + +/** Sparse Hessian matrix data for qrecipe example. */ +sparse_int_t H_jc[] = { 0, 4, 8, 12, 16, 20, 20, 20, 20, 20, 20, + 24, 28, 32, 36, 40, 40, 40, 40, 40, 40, + 44, 48, 52, 56, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 64, 68, 72, 76, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80 }; + +/** Sparse Hessian matrix data for qrecipe example. */ +sparse_int_t H_ir[] = { + 0, 10, 20, 34, 1, 11, 21, 35, 2, 12, 22, 36, 3, 13, 23, 37, 4, 14, 24, 38, + 0, 10, 20, 34, 1, 11, 21, 35, 2, 12, 22, 36, 3, 13, 23, 37, 4, 14, 24, 38, + 0, 10, 20, 34, 1, 11, 21, 35, 2, 12, 22, 36, 3, 13, 23, 37, 4, 14, 24, 38, + 0, 10, 20, 34, 1, 11, 21, 35, 2, 12, 22, 36, 3, 13, 23, 37, 4, 14, 24, 38}; + +/** Sparse Hessian matrix data for qrecipe example. */ +real_t H_val[] = {10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, + 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 1, + 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 1, 10, 1, + 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10, 1, 1, 1, 10}; + +/** Sparse constraint matrix data for qrecipe example. */ +sparse_int_t A_jc[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, + 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, + 280, 290, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 331, + 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, + 363, 365, 367, 369, 371, 373, 383, 393, 403, 405, 408, 410, 413, 415, 418, + 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, + 450, 452, 454, 456, 458, 460, 462, 472, 482, 492, 494, 497, 499, 502, 504, + 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, + 537, 539, 541, 543, 545, 547, 549, 551, 561, 571, 581, 583, 586, 588, 591, + 593, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, + 610, 611, 612, 613, 614, 615, 616, 617, 618, 628, 638, 648, 650, 653, 655, + 658, 660, 663}; + +/** Sparse constraint matrix data for qrecipe example. */ +sparse_int_t A_ir[] = {0, 14, 35, 36, 71, 72, 85, 86, 87, 88, 1, 14, 35, 36, 71, 72, 85, + 86, 87, 88, 2, 14, 35, 36, 71, 72, 85, 86, 87, 88, 3, 14, 35, 36, 71, 72, + 85, 86, 87, 88, 4, 14, 35, 36, 71, 72, 85, 86, 87, 88, 5, 14, 35, 36, 71, + 72, 85, 86, 87, 88, 6, 14, 35, 36, 71, 72, 85, 86, 87, 88, 7, 14, 35, 36, + 71, 72, 85, 86, 87, 88, 8, 14, 35, 36, 71, 72, 85, 86, 87, 88, 9, 14, 35, + 36, 71, 72, 85, 86, 87, 88, 0, 15, 37, 38, 69, 70, 79, 80, 81, 82, 1, 15, + 37, 38, 69, 70, 79, 80, 81, 82, 2, 15, 37, 38, 69, 70, 79, 80, 81, 82, 3, + 15, 37, 38, 69, 70, 79, 80, 81, 82, 4, 15, 37, 38, 69, 70, 79, 80, 81, 82, + 5, 15, 37, 38, 69, 70, 79, 80, 81, 82, 6, 15, 37, 38, 69, 70, 79, 80, 81, + 82, 7, 15, 37, 38, 69, 70, 79, 80, 81, 82, 8, 15, 37, 38, 69, 70, 79, 80, + 81, 82, 9, 15, 37, 38, 69, 70, 79, 80, 81, 82, 0, 16, 39, 40, 67, 68, 73, + 74, 75, 76, 1, 16, 39, 40, 67, 68, 73, 74, 75, 76, 2, 16, 39, 40, 67, 68, + 73, 74, 75, 76, 3, 16, 39, 40, 67, 68, 73, 74, 75, 76, 4, 16, 39, 40, 67, + 68, 73, 74, 75, 76, 5, 16, 39, 40, 67, 68, 73, 74, 75, 76, 6, 16, 39, 40, + 67, 68, 73, 74, 75, 76, 7, 16, 39, 40, 67, 68, 73, 74, 75, 76, 8, 16, 39, + 40, 67, 68, 73, 74, 75, 76, 9, 16, 39, 40, 67, 68, 73, 74, 75, 76, 10, 11, + 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 47, 58, 48, 59, 49, 60, 50, 61, 51, 62, 52, 63, 53, + 64, 54, 65, 55, 66, 46, 56, 45, 57, 47, 58, 48, 59, 49, 60, 50, 61, 51, 62, + 52, 63, 53, 64, 54, 65, 55, 66, 46, 56, 45, 57, 10, 14, 71, 72, 85, 86, 87, + 88, 89, 90, 11, 15, 69, 70, 79, 80, 81, 82, 83, 84, 12, 16, 67, 68, 73, 74, + 75, 76, 77, 78, 35, 90, 36, 89, 90, 37, 84, 38, 83, 84, 39, 78, 40, 77, 78, + 44, 58, 43, 59, 42, 60, 41, 61, 34, 62, 33, 63, 32, 64, 31, 65, 30, 66, 29, + 46, 28, 45, 44, 58, 43, 59, 42, 60, 41, 61, 34, 62, 33, 63, 32, 64, 31, 65, + 30, 66, 29, 46, 28, 45, 10, 14, 71, 72, 85, 86, 87, 88, 89, 90, 11, 15, 69, + 70, 79, 80, 81, 82, 83, 84, 12, 16, 67, 68, 73, 74, 75, 76, 77, 78, 35, 90, + 36, 89, 90, 37, 84, 38, 83, 84, 39, 78, 40, 77, 78, 27, 44, 26, 43, 25, 42, + 24, 41, 23, 34, 22, 33, 21, 32, 20, 31, 19, 30, 18, 29, 17, 28, 27, 44, 26, + 43, 25, 42, 24, 41, 23, 34, 22, 33, 21, 32, 20, 31, 19, 30, 18, 29, 17, 28, + 10, 14, 71, 72, 85, 86, 87, 88, 89, 90, 11, 15, 69, 70, 79, 80, 81, 82, 83, + 84, 12, 16, 67, 68, 73, 74, 75, 76, 77, 78, 35, 90, 36, 89, 90, 37, 84, 38, + 83, 84, 39, 78, 40, 77, 78, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 27, + 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 10, 14, 71, 72, 85, 86, 87, 88, 89, + 90, 11, 15, 69, 70, 79, 80, 81, 82, 83, 84, 12, 16, 67, 68, 73, 74, 75, 76, + 77, 78, 35, 90, 36, 89, 90, 37, 84, 38, 83, 84, 39, 78, 40, 77, 78}; + +/** Sparse constraint matrix data for qrecipe example. */ +real_t A_val[] = { +-1.0000000000000000e+00, 1.0000000000000000e+00, 8.8678200000000004e+01, + 9.3617050000000006e+01, 1.6000000000000000e+01, 8.1999999999999993e+00, + 9.9000000000000000e+01, 8.0000000000000000e+01, 1.2000000000000000e+01, + 9.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, + 8.0062830000000005e+01, 9.9224010000000007e+01, 1.0000000000000000e+02, + 2.1100000000000001e+01, 1.0000000000000000e+02, 1.0000000000000000e+02, + 1.1400000000000000e+02, 1.1680000000000000e+02, -1.0000000000000000e+00, + 1.0000000000000000e+00, 7.4697360000000003e+01, 8.3801220000000001e+01, +-8.1999999999999993e+00, 2.0000000000000000e+00, 9.0000000000000000e+01, + 2.3999999999999999e+00, -1.2000000000000000e+01, -1.4800000000000001e+01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 7.9194209999999998e+01, + 9.0175110000000004e+01, 4.3000000000000000e+01, 8.0000000000000000e+00, + 1.0000000000000000e+02, 9.5000000000000000e+01, 9.0000000000000000e+00, + 2.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, + 7.8568219999999997e+01, 8.5996200000000002e+01, -1.2500000000000000e+01, + 1.0000000000000000e+00, 9.6500000000000000e+01, 4.0000000000000000e+00, +-1.8000000000000000e+01, -2.1899999999999999e+01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 8.2922240000000002e+01, 8.6963380000000001e+01, + 6.5000000000000000e+01, 1.2500000000000000e+01, 1.0000000000000000e+02, + 9.8000000000000000e+01, 4.9000000000000000e+01, 3.7000000000000000e+01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 8.2592740000000006e+01, + 9.3147599999999997e+01, -1.2000000000000000e+01, 1.0000000000000000e+00, + 9.6500000000000000e+01, 4.0000000000000000e+00, -1.8000000000000000e+01, +-2.1899999999999999e+01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 7.6506460000000004e+01, 7.8210250000000002e+01, 7.9000000000000000e+01, + 1.2000000000000000e+01, 1.0000000000000000e+02, 9.5000000000000000e+01, + 6.8000000000000000e+01, 6.1000000000000000e+01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 8.8357460000000003e+01, 9.4257840000000002e+01, + 1.2500000000000000e+02, 6.1299999999999997e+01, 1.0000000000000000e+02, + 1.0000000000000000e+02, 1.4500000000000000e+02, 1.4500000000000000e+02, +-1.0000000000000000e+00, 1.0000000000000000e+00, 9.0590469999999996e+01, + 1.0582863000000000e+02, 6.2000000000000002e+00, 6.0000000000000000e+00, + 9.7000000000000000e+01, 2.8500000000000000e+01, 4.0000000000000000e+00, + 3.6000000000000001e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, + 8.8678200000000004e+01, 9.3617050000000006e+01, 1.6000000000000000e+01, + 8.1999999999999993e+00, 9.9000000000000000e+01, 8.0000000000000000e+01, + 1.2000000000000000e+01, 9.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, 8.0062830000000005e+01, 9.9224010000000007e+01, + 1.0000000000000000e+02, 2.1100000000000001e+01, 1.0000000000000000e+02, + 1.0000000000000000e+02, 1.1400000000000000e+02, 1.1680000000000000e+02, +-1.0000000000000000e+00, 1.0000000000000000e+00, 7.4697360000000003e+01, + 8.3801220000000001e+01, -8.1999999999999993e+00, 2.0000000000000000e+00, + 9.0000000000000000e+01, 2.3999999999999999e+00, -1.2000000000000000e+01, +-1.4800000000000001e+01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 7.9194209999999998e+01, 9.0175110000000004e+01, 4.3000000000000000e+01, + 8.0000000000000000e+00, 1.0000000000000000e+02, 9.5000000000000000e+01, + 9.0000000000000000e+00, 2.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, 7.8568219999999997e+01, 8.5996200000000002e+01, +-1.2500000000000000e+01, 1.0000000000000000e+00, 9.6500000000000000e+01, + 4.0000000000000000e+00, -1.8000000000000000e+01, -2.1899999999999999e+01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 8.2922240000000002e+01, + 8.6963380000000001e+01, 6.5000000000000000e+01, 1.2500000000000000e+01, + 1.0000000000000000e+02, 9.8000000000000000e+01, 4.9000000000000000e+01, + 3.7000000000000000e+01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 8.2592740000000006e+01, 9.3147599999999997e+01, -1.2000000000000000e+01, + 1.0000000000000000e+00, 9.6500000000000000e+01, 4.0000000000000000e+00, +-1.8000000000000000e+01, -2.1899999999999999e+01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 7.6506460000000004e+01, 7.8210250000000002e+01, + 7.9000000000000000e+01, 1.2000000000000000e+01, 1.0000000000000000e+02, + 9.5000000000000000e+01, 6.8000000000000000e+01, 6.1000000000000000e+01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 8.8357460000000003e+01, + 9.4257840000000002e+01, 1.2500000000000000e+02, 6.1299999999999997e+01, + 1.0000000000000000e+02, 1.0000000000000000e+02, 1.4500000000000000e+02, + 1.4500000000000000e+02, -1.0000000000000000e+00, 1.0000000000000000e+00, + 9.0590469999999996e+01, 1.0582863000000000e+02, 6.2000000000000002e+00, + 6.0000000000000000e+00, 9.7000000000000000e+01, 2.8500000000000000e+01, + 4.0000000000000000e+00, 3.6000000000000001e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, 8.8678200000000004e+01, 9.3617050000000006e+01, + 1.6000000000000000e+01, 8.1999999999999993e+00, 9.9000000000000000e+01, + 8.0000000000000000e+01, 1.2000000000000000e+01, 9.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, 8.0062830000000005e+01, + 9.9224010000000007e+01, 1.0000000000000000e+02, 2.1100000000000001e+01, + 1.0000000000000000e+02, 1.0000000000000000e+02, 1.1400000000000000e+02, + 1.1680000000000000e+02, -1.0000000000000000e+00, 1.0000000000000000e+00, + 7.4697360000000003e+01, 8.3801220000000001e+01, -8.1999999999999993e+00, + 2.0000000000000000e+00, 9.0000000000000000e+01, 2.3999999999999999e+00, +-1.2000000000000000e+01, -1.4800000000000001e+01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 7.9194209999999998e+01, 9.0175110000000004e+01, + 4.3000000000000000e+01, 8.0000000000000000e+00, 1.0000000000000000e+02, + 9.5000000000000000e+01, 9.0000000000000000e+00, 2.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, 7.8568219999999997e+01, + 8.5996200000000002e+01, -1.2500000000000000e+01, 1.0000000000000000e+00, + 9.6500000000000000e+01, 4.0000000000000000e+00, -1.8000000000000000e+01, +-2.1899999999999999e+01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 8.2922240000000002e+01, 8.6963380000000001e+01, 6.5000000000000000e+01, + 1.2500000000000000e+01, 1.0000000000000000e+02, 9.8000000000000000e+01, + 4.9000000000000000e+01, 3.7000000000000000e+01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 8.2592740000000006e+01, 9.3147599999999997e+01, +-1.2000000000000000e+01, 1.0000000000000000e+00, 9.6500000000000000e+01, + 4.0000000000000000e+00, -1.8000000000000000e+01, -2.1899999999999999e+01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 7.6506460000000004e+01, + 7.8210250000000002e+01, 7.9000000000000000e+01, 1.2000000000000000e+01, + 1.0000000000000000e+02, 9.5000000000000000e+01, 6.8000000000000000e+01, + 6.1000000000000000e+01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 8.8357460000000003e+01, 9.4257840000000002e+01, 1.2500000000000000e+02, + 6.1299999999999997e+01, 1.0000000000000000e+02, 1.0000000000000000e+02, + 1.4500000000000000e+02, 1.4500000000000000e+02, -1.0000000000000000e+00, + 1.0000000000000000e+00, 9.0590469999999996e+01, 1.0582863000000000e+02, + 6.2000000000000002e+00, 6.0000000000000000e+00, 9.7000000000000000e+01, + 2.8500000000000000e+01, 4.0000000000000000e+00, 3.6000000000000001e+00, +-1.0000000000000000e+00, -1.0000000000000000e+00, -1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, 1.0000000000000000e+00, + 1.0000000000000000e+00, 1.0000000000000000e+00, 1.0000000000000000e+00, + 1.0000000000000000e+00, 1.0000000000000000e+00, 1.0000000000000000e+00, + 1.0000000000000000e+00, 1.0000000000000000e+00, -1.2000000000000000e-01, +-3.8000000000000000e-01, -5.0000000000000000e-01, 1.0000000000000000e+00, + 1.0000000000000000e+00, 1.0000000000000000e+00, 1.0000000000000000e+00, + 1.0000000000000000e+00, 1.0000000000000000e+00, 1.0000000000000000e+00, + 1.0000000000000000e+00, 1.0000000000000000e+00, 1.0000000000000000e+00, + 1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, +-4.7000000000000000e+01, -8.6999999999999993e+00, -9.0000000000000000e+01, +-5.0000000000000000e+01, -1.0000000000000000e+01, -1.0000000000000000e+01, +-9.3000000000000000e+01, -8.9000000000000000e+01, 1.0000000000000000e+00, +-1.0000000000000000e+00, -4.7000000000000000e+01, -8.6999999999999993e+00, +-9.0000000000000000e+01, -5.0000000000000000e+01, -1.0000000000000000e+01, +-1.0000000000000000e+01, -8.9000000000000000e+01, -8.5000000000000000e+01, + 1.0000000000000000e+00, -1.0000000000000000e+00, -4.7000000000000000e+01, +-8.6999999999999993e+00, -9.0000000000000000e+01, -5.0000000000000000e+01, +-1.0000000000000000e+01, -1.0000000000000000e+01, -9.1000000000000000e+01, +-8.8000000000000000e+01, -1.0000000000000000e+00, 5.0000000000000000e-01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 5.0000000000000000e-01, +-1.0000000000000000e+00, 5.0000000000000000e-01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 5.0000000000000000e-01, -1.0000000000000000e+00, + 5.0000000000000000e-01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 5.0000000000000000e-01, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, -4.7000000000000000e+01, +-8.6999999999999993e+00, -9.0000000000000000e+01, -5.0000000000000000e+01, +-1.0000000000000000e+01, -1.0000000000000000e+01, -9.3000000000000000e+01, +-8.9000000000000000e+01, 1.0000000000000000e+00, -1.0000000000000000e+00, +-4.7000000000000000e+01, -8.6999999999999993e+00, -9.0000000000000000e+01, +-5.0000000000000000e+01, -1.0000000000000000e+01, -1.0000000000000000e+01, +-8.9000000000000000e+01, -8.5000000000000000e+01, 1.0000000000000000e+00, +-1.0000000000000000e+00, -4.7000000000000000e+01, -8.6999999999999993e+00, +-9.0000000000000000e+01, -5.0000000000000000e+01, -1.0000000000000000e+01, +-1.0000000000000000e+01, -9.1000000000000000e+01, -8.8000000000000000e+01, +-1.0000000000000000e+00, 5.0000000000000000e-01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 5.0000000000000000e-01, -1.0000000000000000e+00, + 5.0000000000000000e-01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 5.0000000000000000e-01, -1.0000000000000000e+00, 5.0000000000000000e-01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 5.0000000000000000e-01, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, 1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, 1.0000000000000000e+00, +-1.0000000000000000e+00, -4.7000000000000000e+01, -8.6999999999999993e+00, +-9.0000000000000000e+01, -5.0000000000000000e+01, -1.0000000000000000e+01, +-1.0000000000000000e+01, -9.3000000000000000e+01, -8.9000000000000000e+01, + 1.0000000000000000e+00, -1.0000000000000000e+00, -4.7000000000000000e+01, +-8.6999999999999993e+00, -9.0000000000000000e+01, -5.0000000000000000e+01, +-1.0000000000000000e+01, -1.0000000000000000e+01, -8.9000000000000000e+01, +-8.5000000000000000e+01, 1.0000000000000000e+00, -1.0000000000000000e+00, +-4.7000000000000000e+01, -8.6999999999999993e+00, -9.0000000000000000e+01, +-5.0000000000000000e+01, -1.0000000000000000e+01, -1.0000000000000000e+01, +-9.1000000000000000e+01, -8.8000000000000000e+01, -1.0000000000000000e+00, + 5.0000000000000000e-01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 5.0000000000000000e-01, -1.0000000000000000e+00, 5.0000000000000000e-01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 5.0000000000000000e-01, +-1.0000000000000000e+00, 5.0000000000000000e-01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 5.0000000000000000e-01, -1.0000000000000000e+00, +-1.0000000000000000e+00, -1.0000000000000000e+00, -1.0000000000000000e+00, +-1.0000000000000000e+00, -1.0000000000000000e+00, -1.0000000000000000e+00, +-1.0000000000000000e+00, -1.0000000000000000e+00, -1.0000000000000000e+00, +-1.0000000000000000e+00, -1.0000000000000000e+00, -1.0000000000000000e+00, +-1.0000000000000000e+00, -1.0000000000000000e+00, -1.0000000000000000e+00, +-1.0000000000000000e+00, -1.0000000000000000e+00, -1.0000000000000000e+00, +-1.0000000000000000e+00, -1.0000000000000000e+00, -1.0000000000000000e+00, + 1.0000000000000000e+00, -1.0000000000000000e+00, -4.7000000000000000e+01, +-8.6999999999999993e+00, -9.0000000000000000e+01, -5.0000000000000000e+01, +-1.0000000000000000e+01, -1.0000000000000000e+01, -9.3000000000000000e+01, +-8.9000000000000000e+01, 1.0000000000000000e+00, -1.0000000000000000e+00, +-4.7000000000000000e+01, -8.6999999999999993e+00, -9.0000000000000000e+01, +-5.0000000000000000e+01, -1.0000000000000000e+01, -1.0000000000000000e+01, +-8.9000000000000000e+01, -8.5000000000000000e+01, 1.0000000000000000e+00, +-1.0000000000000000e+00, -4.7000000000000000e+01, -8.6999999999999993e+00, +-9.0000000000000000e+01, -5.0000000000000000e+01, -1.0000000000000000e+01, +-1.0000000000000000e+01, -9.1000000000000000e+01, -8.8000000000000000e+01, +-1.0000000000000000e+00, 5.0000000000000000e-01, -1.0000000000000000e+00, + 1.0000000000000000e+00, 5.0000000000000000e-01, -1.0000000000000000e+00, + 5.0000000000000000e-01, -1.0000000000000000e+00, 1.0000000000000000e+00, + 5.0000000000000000e-01, -1.0000000000000000e+00, 5.0000000000000000e-01, +-1.0000000000000000e+00, 1.0000000000000000e+00, 5.0000000000000000e-01}; + +/** Gradient vector for qrecipe example. */ +real_t g[] = {+0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, + +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, + +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, + +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, + +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, + +0e+00, +0e+00, -2e+00, -2e+00, -2e+00, -2e+00, -2e+00, -2e+00, -2e+00, + -2e+00, +0e+00, -2e+00, +0e+00, +2e-03, +2e-03, +2e-03, +2e-03, +2e-03, + +2e-03, +1e-03, +2e-03, +2e-03, +2e-03, +0e+00, -2e-03, -2e-03, -2e-03, + -2e-03, -2e-03, -2e-03, -1e-03, -2e-03, -2e-03, -2e-03, +0e+00, +0e+00, + +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +2e-03, + +2e-03, +2e-03, +2e-03, +2e-03, +2e-03, +1e-03, +2e-03, +2e-03, +2e-03, + +0e+00, -2e-03, -2e-03, -2e-03, -2e-03, -2e-03, -2e-03, -1e-03, -2e-03, + -2e-03, -2e-03, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, + +0e+00, +0e+00, +0e+00, +2e-03, +2e-03, +2e-03, +2e-03, +2e-03, +2e-03, + +1e-03, +2e-03, +2e-03, +2e-03, +0e+00, -2e-03, -2e-03, -2e-03, -2e-03, + -2e-03, -2e-03, -1e-03, -2e-03, -2e-03, -2e-03, +0e+00, +0e+00, +0e+00, + +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +1e-01, +1e-01, + +1e-01, +1e-01, +1e-01, +1e-01, +1e-01, +1e-01, +1e-01, +1e-01, +0e+00, + -1e-01, -1e-01, -1e-01, -1e-01, -1e-01, -1e-01, -1e-01, -1e-01, -1e-01, + -1e-01, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, +0e+00, + +0e+00}; + +/** Lower bound vector for qrecipe example. */ +real_t lb[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -Inf, 0, -Inf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, + 10, 5, 0, 10, 0, 2, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 5, 10, 5, 0, 10, 0, 5, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 10, 5, 0, 10, 0, 5, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +/** Upper bound vector for qrecipe example. */ +real_t ub[] = {Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, + Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, + Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, + Inf, Inf, 0, 92, 39, 87, 29, 0, 20, 0, 28, 20, 71, Inf, 130, 45, 53, 55, 75, + 112, 0, 73, 480, 154, 121, 50, 30, 77, 20, 0, 18, 0, 5, 20, 71, Inf, Inf, + Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, 130, 55, 93, 60, 75, 115, 0, 67, + 480, 154, 121, 50, 20, 37, 15, 0, 15, 0, 8, 20, 71, Inf, Inf, Inf, Inf, Inf, + Inf, Inf, Inf, Inf, Inf, 130, 55, 93, 60, 75, 105, 0, 67, 4980, 154, 110, + 50, 20, 37, 15, 0, 25, 0, 8, 20, 71, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, + Inf, Inf, 20, 20, 20, 20, 0, 20, 0, 20, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf}; + +/** Lower constraint bound vector for qrecipe example. */ +real_t lbA[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -Inf, -Inf, + -Inf, -Inf, -Inf, -Inf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0}; + +/** Upper constraint bound vector for qrecipe example. */ +real_t ubA[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, + Inf, Inf, Inf, Inf}; + +/** Number of non-zeros in Hessian matrix for qrecipe example. */ +long H_nnz = sizeof(H_val) / sizeof(real_t); + +/** Number of non-zeros in constraint matrix for qrecipe example. */ +long A_nnz = sizeof(A_val) / sizeof(real_t); + + +/** Example for calling qpOASES with sparse matrices. */ +int main( ) +{ + long i; + int nWSR; + real_t err, tic, toc; + real_t *x1 = new real_t[180]; + real_t *y1 = new real_t[271]; + real_t *x2 = new real_t[180]; + real_t *y2 = new real_t[271]; + + /* create sparse matrices */ + SymSparseMat *H = new SymSparseMat(180, 180, H_ir, H_jc, H_val); + SparseMatrix *A = new SparseMatrix(91, 180, A_ir, A_jc, A_val); + + H->createDiagInfo(); + + real_t* H_full = H->full(); + real_t* A_full = A->full(); + + SymDenseMat *Hd = new SymDenseMat(180,180,180,H_full); + DenseMatrix *Ad = new DenseMatrix(91,180,180,A_full); + + /* solve with dense matrices */ + nWSR = 1000; + QProblem qrecipeD(180, 91); + tic = getCPUtime(); + qrecipeD.init(Hd, g, Ad, lb, ub, lbA, ubA, nWSR, 0); + toc = getCPUtime(); + qrecipeD.getPrimalSolution(x1); + qrecipeD.getDualSolution(y1); + + fprintf(stdFile, "Solved dense problem in %d iterations, %.3f seconds.\n", nWSR, toc-tic); + + /* solve with sparse matrices */ + nWSR = 1000; + QProblem qrecipeS(180, 91); + tic = getCPUtime(); + qrecipeS.init(H, g, A, lb, ub, lbA, ubA, nWSR, 0); + toc = getCPUtime(); + qrecipeS.getPrimalSolution(x2); + qrecipeS.getDualSolution(y2); + + fprintf(stdFile, "Solved sparse problem in %d iterations, %.3f seconds.\n", nWSR, toc-tic); + + /* check distance of solutions */ + err = 0.0; + for (i = 0; i < 180; i++) + if (getAbs(x1[i] - x2[i]) > err) + err = getAbs(x1[i] - x2[i]); + fprintf(stdFile, "Primal error: %9.2e\n", err); + err = 0.0; + for (i = 0; i < 271; i++) + if (getAbs(y1[i] - y2[i]) > err) + err = getAbs(y1[i] - y2[i]); + fprintf(stdFile, "Dual error: %9.2e (might not be unique)\n", err); + + delete H; + delete A; + delete[] H_full; + delete[] A_full; + delete Hd; + delete Ad; + + delete[] y2; + delete[] x2; + delete[] y1; + delete[] x1; + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/index.html b/3rdparty/qpOASES/qpOASES-3.0/include/index.html new file mode 100644 index 00000000000..77dd423600b --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/index.html @@ -0,0 +1,9 @@ +qpOASES - Revision 198: /stable/3.0/include + +

qpOASES - Revision 198: /stable/3.0/include

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES.hpp new file mode 100644 index 00000000000..4570d6031c1 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES.hpp @@ -0,0 +1,59 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + */ + +#ifndef __SINGLE_OBJECT__ + +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Bounds.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Bounds.hpp new file mode 100644 index 00000000000..c1ea151e804 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Bounds.hpp @@ -0,0 +1,256 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Bounds.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the Bounds class designed to manage working sets of + * bounds within a QProblem. + */ + + +#ifndef QPOASES_BOUNDS_HPP +#define QPOASES_BOUNDS_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Manages working sets of bounds (= box constraints). + * + * This class manages working sets of bounds (= box constraints) + * by storing index sets and other status information. + * + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + */ +class Bounds : public SubjectTo +{ + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + Bounds( ); + + /** Constructor which takes the number of bounds. */ + Bounds( int _n /**< Number of bounds. */ + ); + + /** Copy constructor (deep copy). */ + Bounds( const Bounds& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + virtual ~Bounds( ); + + /** Assignment operator (deep copy). */ + Bounds& operator=( const Bounds& rhs /**< Rhs object. */ + ); + + + /** Initialises object with given number of bounds. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ + returnValue init( int _n = 0 /**< Number of bounds. */ + ); + + + /** Initially adds number of a new (i.e. not yet in the list) bound to + * given index set. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS */ + returnValue setupBound( int number, /**< Number of new bound. */ + SubjectToStatus _status /**< Status of new bound. */ + ); + + /** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set of free bounds; the order depends on the SujectToType + * of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED */ + returnValue setupAllFree( ); + + /** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set of fixed bounds (on their lower bounds); + * the order depends on the SujectToType of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED */ + returnValue setupAllLower( ); + + /** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set of fixed bounds (on their upper bounds); + * the order depends on the SujectToType of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED */ + returnValue setupAllUpper( ); + + + /** Moves index of a bound from index list of fixed to that of free bounds. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_BOUND_FAILED \n + RET_INDEX_OUT_OF_BOUNDS */ + returnValue moveFixedToFree( int number /**< Number of bound to be freed. */ + ); + + /** Moves index of a bound from index list of free to that of fixed bounds. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_BOUND_FAILED \n + RET_INDEX_OUT_OF_BOUNDS */ + returnValue moveFreeToFixed( int number, /**< Number of bound to be fixed. */ + SubjectToStatus _status /**< Status of bound to be fixed. */ + ); + + /** Flip fixed bound. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_BOUND_FAILED \n + RET_INDEX_OUT_OF_BOUNDS */ + returnValue flipFixed( int number ); + + /** Swaps the indices of two free bounds within the index set. + * \return SUCCESSFUL_RETURN \n + RET_SWAPINDEX_FAILED */ + returnValue swapFree( int number1, /**< Number of first constraint or bound. */ + int number2 /**< Number of second constraint or bound. */ + ); + + + /** Returns number of variables. + * \return Number of variables. */ + inline int getNV( ) const; + + /** Returns number of implicitly fixed variables. + * \return Number of implicitly fixed variables. */ + inline int getNFV( ) const; + + /** Returns number of bounded (but possibly free) variables. + * \return Number of bounded (but possibly free) variables. */ + inline int getNBV( ) const; + + /** Returns number of unbounded variables. + * \return Number of unbounded variables. */ + inline int getNUV( ) const; + + /** Returns number of free variables. + * \return Number of free variables. */ + inline int getNFR( ) const; + + /** Returns number of fixed variables. + * \return Number of fixed variables. */ + inline int getNFX( ) const; + + + /** Returns a pointer to free variables index list. + * \return Pointer to free variables index list. */ + inline Indexlist* getFree( ); + + /** Returns a pointer to fixed variables index list. + * \return Pointer to fixed variables index list. */ + inline Indexlist* getFixed( ); + + + /** Shifts forward type and status of all bounds by a given + * offset. This offset has to lie within the range [0,n/2] and has to + * be an integer divisor of the total number of bounds n. + * Type and status of the first \ bounds is thrown away, + * type and status of the last \ bounds is doubled, + * e.g. for offset = 2: \n + * shift( {b1,b2,b3,b4,b5,b6} ) = {b3,b4,b5,b6,b5,b6} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS \n + RET_SHIFTING_FAILED */ + virtual returnValue shift( int offset /**< Shift offset within the range [0,n/2] and integer divisor of n. */ + ); + + /** Rotates forward type and status of all bounds by a given + * offset. This offset has to lie within the range [0,n]. + * Example for offset = 2: \n + * rotate( {b1,b2,b3,b4,b5,b6} ) = {b3,b4,b5,b6,b1,b2} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_ROTATING_FAILED */ + virtual returnValue rotate( int offset /**< Rotation offset within the range [0,n]. */ + ); + + + /** Prints information on bounds object + * (in particular, lists of free and fixed bounds. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ + returnValue print( ); + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Frees all allocated memory. + * \return SUCCESSFUL_RETURN */ + returnValue clear( ); + + /** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ + returnValue copy( const Bounds& rhs /**< Rhs object. */ + ); + + + /** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set corresponding to the desired status; + * the order depends on the SujectToType of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED */ + returnValue setupAll( SubjectToStatus _status /**< Desired initial status for all bounds. */ + ); + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + Indexlist freee; /**< Index list of free variables. */ + Indexlist fixed; /**< Index list of fixed variables. */ +}; + + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_BOUNDS_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Bounds.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Bounds.ipp new file mode 100644 index 00000000000..0efdccf73a9 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Bounds.ipp @@ -0,0 +1,120 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Bounds.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Implementation of inlined member functions of the Bounds class designed + * to manage working sets of bounds within a QProblem. + */ + + +BEGIN_NAMESPACE_QPOASES + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + +/* + * g e t N V + */ +inline int Bounds::getNV( ) const +{ + return n; +} + + +/* + * g e t N F V + */ +inline int Bounds::getNFV( ) const +{ + return getNumberOfType( ST_EQUALITY ); +} + + +/* + * g e t N B V + */ +inline int Bounds::getNBV( ) const +{ + return getNumberOfType( ST_BOUNDED ); +} + + +/* + * g e t N U V + */ +inline int Bounds::getNUV( ) const +{ + return getNumberOfType( ST_UNBOUNDED ); +} + + +/* + * g e t N F R + */ +inline int Bounds::getNFR( ) const +{ + return freee.getLength( ); +} + + +/* + * g e t N F X + */ +inline int Bounds::getNFX( ) const +{ + return fixed.getLength( ); +} + + +/* + * g e t F r e e + */ +inline Indexlist* Bounds::getFree( ) +{ + return &freee; +} + + +/* + * g e t F i x e d + */ +inline Indexlist* Bounds::getFixed( ) +{ + return &fixed; +} + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constants.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constants.hpp new file mode 100644 index 00000000000..e2ba4e7edca --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constants.hpp @@ -0,0 +1,77 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Constants.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Definition of all global constants. + */ + + +#ifndef QPOASES_CONSTANTS_HPP +#define QPOASES_CONSTANTS_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** Numerical value of machine precision (min eps, s.t. 1+eps > 1). + * Note: this value has to be positive! */ +#ifdef __USE_SINGLE_PRECISION__ +const real_t EPS = 1.193e-07; +#else +const real_t EPS = 2.221e-16; +#endif /* __USE_SINGLE_PRECISION__ */ + + +/** Numerical value of zero (for situations in which it would be + * unreasonable to compare with 0.0). + * Note: this value has to be positive! */ +const real_t ZERO = 1.0e-25; + +/** Numerical value of infinity (e.g. for non-existing bounds). + Note: this value has to be positive! */ +const real_t INFTY = 1.0e20; + + +/** Maximum number of characters within a string. + * Note: this value should be at least 41! */ +const unsigned int MAX_STRING_LENGTH = 160; + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_CONSTANTS_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/ConstraintProduct.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/ConstraintProduct.hpp new file mode 100644 index 00000000000..929f6c91556 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/ConstraintProduct.hpp @@ -0,0 +1,91 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/ConstraintProduct.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2009-2014 + * + * Declaration of the ConstraintProduct class which allows to specify a + * user-defined function for evaluating the constraint product at the + * current iterate to speed-up QP solution in case of a specially structured + * constraint matrix. + */ + + + +#ifndef QPOASES_CONSTRAINT_PRODUCT_HPP +#define QPOASES_CONSTRAINT_PRODUCT_HPP + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Interface for specifying user-defined evaluations of constraint products. + * + * A class which allows to specify a user-defined function for evaluating the + * constraint product at the current iterate to speed-up QP solution in case + * of a specially structured constraint matrix. + * + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2009-2014 + */ +class ConstraintProduct +{ + public: + /** Default constructor. */ + ConstraintProduct( ) {}; + + /** Copy constructor. */ + ConstraintProduct( const ConstraintProduct &toCopy /**< Rhs object. */ + ) {}; + + /** Destructor. */ + virtual ~ConstraintProduct( ) {}; + + /** Assignment operator. */ + ConstraintProduct &operator=( const ConstraintProduct &toCopy /**< Rhs object. */ + ) + { + return *this; + } + + /** Evaluates the product of a given constraint with the current iterate. + * This function needs to be implemented in a derived class for the + * user-defined constraint product function. + * \return 0: successful \n + otherwise: not successful */ + virtual int operator() ( int constrIndex, /**< Number of constraint to be evaluated. */ + const real_t* const x, /**< Array containing current primal iterate. */ + real_t* const constrValue /**< Output: Scalar value of the evaluated constraint. */ + ) const = 0; +}; + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_CONSTRAINT_PRODUCT_HPP */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constraints.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constraints.hpp new file mode 100644 index 00000000000..8d4556ac720 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constraints.hpp @@ -0,0 +1,246 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Constraints.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the Constraints class designed to manage working sets of + * constraints within a QProblem. + */ + + +#ifndef QPOASES_CONSTRAINTS_HPP +#define QPOASES_CONSTRAINTS_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Manages working sets of constraints. + * + * This class manages working sets of constraints by storing + * index sets and other status information. + * + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + */ +class Constraints : public SubjectTo +{ + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + Constraints( ); + + /** Constructor which takes the number of constraints. */ + Constraints( int _n /**< Number of constraints. */ + ); + + /** Copy constructor (deep copy). */ + Constraints( const Constraints& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + virtual ~Constraints( ); + + /** Assignment operator (deep copy). */ + Constraints& operator=( const Constraints& rhs /**< Rhs object. */ + ); + + + /** Initialises object with given number of constraints. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ + returnValue init( int _n = 0 /**< Number of constraints. */ + ); + + + /** Initially adds number of a new (i.e. not yet in the list) constraint to + * a given index set. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS */ + returnValue setupConstraint( int number, /**< Number of new constraint. */ + SubjectToStatus _status /**< Status of new constraint. */ + ); + + /** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to + * to the index set of inactive constraints; the order depends on the SujectToType + * of each index. Only disabled constraints are added to index set of disabled constraints! + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED */ + returnValue setupAllInactive( ); + + /** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to + * to the index set of active constraints (on their lower bounds); the order depends on the SujectToType + * of each index. Only disabled constraints are added to index set of disabled constraints! + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED */ + returnValue setupAllLower( ); + + /** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to + * to the index set of active constraints (on their upper bounds); the order depends on the SujectToType + * of each index. Only disabled constraints are added to index set of disabled constraints! + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED */ + returnValue setupAllUpper( ); + + + /** Moves index of a constraint from index list of active to that of inactive constraints. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_CONSTRAINT_FAILED */ + returnValue moveActiveToInactive( int number /**< Number of constraint to become inactive. */ + ); + + /** Moves index of a constraint from index list of inactive to that of active constraints. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_CONSTRAINT_FAILED */ + returnValue moveInactiveToActive( int number, /**< Number of constraint to become active. */ + SubjectToStatus _status /**< Status of constraint to become active. */ + ); + + /** Flip fixed constraint. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_CONSTRAINT_FAILED \n + RET_INDEX_OUT_OF_BOUNDS */ + returnValue flipFixed( int number ); + + + /** Returns the number of constraints. + * \return Number of constraints. */ + inline int getNC( ) const; + + /** Returns the number of implicit equality constraints. + * \return Number of implicit equality constraints. */ + inline int getNEC( ) const; + + /** Returns the number of "real" inequality constraints. + * \return Number of "real" inequality constraints. */ + inline int getNIC( ) const; + + /** Returns the number of unbounded constraints (i.e. without any bounds). + * \return Number of unbounded constraints (i.e. without any bounds). */ + inline int getNUC( ) const; + + /** Returns the number of active constraints. + * \return Number of active constraints. */ + inline int getNAC( ) const; + + /** Returns the number of inactive constraints. + * \return Number of inactive constraints. */ + inline int getNIAC( ) const; + + + /** Returns a pointer to active constraints index list. + * \return Pointer to active constraints index list. */ + inline Indexlist* getActive( ); + + /** Returns a pointer to inactive constraints index list. + * \return Pointer to inactive constraints index list. */ + inline Indexlist* getInactive( ); + + + /** Shifts forward type and status of all constraints by a given + * offset. This offset has to lie within the range [0,n/2] and has to + * be an integer divisor of the total number of constraints n. + * Type and status of the first \ constraints is thrown away, + * type and status of the last \ constraints is doubled, + * e.g. for offset = 2: \n + * shift( {c1,c2,c3,c4,c5,c6} ) = {c3,c4,c5,c6,c5,c6} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS \n + RET_SHIFTING_FAILED */ + virtual returnValue shift( int offset /**< Shift offset within the range [0,n/2] and integer divisor of n. */ + ); + + /** Rotates forward type and status of all constraints by a given + * offset. This offset has to lie within the range [0,n]. + * Example for offset = 2: \n + * rotate( {c1,c2,c3,c4,c5,c6} ) = {c3,c4,c5,c6,c1,c2} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_ROTATING_FAILED */ + virtual returnValue rotate( int offset /**< Rotation offset within the range [0,n]. */ + ); + + + /** Prints information on constraints object + * (in particular, lists of inactive and active constraints. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ + returnValue print( ); + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Frees all allocated memory. + * \return SUCCESSFUL_RETURN */ + returnValue clear( ); + + /** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ + returnValue copy( const Constraints& rhs /**< Rhs object. */ + ); + + + /** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set corresponding to the desired status; + * the order depends on the SujectToType of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED */ + returnValue setupAll( SubjectToStatus _status /**< Desired initial status for all bounds. */ + ); + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + Indexlist active; /**< Index list of active constraints. */ + Indexlist inactive; /**< Index list of inactive constraints. */ +}; + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_CONSTRAINTS_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constraints.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constraints.ipp new file mode 100644 index 00000000000..b58e02b2516 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Constraints.ipp @@ -0,0 +1,122 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Constraints.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of inlined member functions of the Constraints class designed + * to manage working sets of constraints within a QProblem. + */ + + +BEGIN_NAMESPACE_QPOASES + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + + +/* + * g e t N C + */ +inline int Constraints::getNC( ) const +{ + return n; +} + + +/* + * g e t N E C + */ +inline int Constraints::getNEC( ) const +{ + return getNumberOfType( ST_EQUALITY ); +} + + +/* + * g e t N I C + */ +inline int Constraints::getNIC( ) const +{ + return getNumberOfType( ST_BOUNDED ); +} + + +/* + * g e t N U C + */ +inline int Constraints::getNUC( ) const +{ + return getNumberOfType( ST_UNBOUNDED ); +} + + +/* + * g e t N A C + */ +inline int Constraints::getNAC( ) const +{ + return active.getLength( ); +} + + +/* + * g e t N I A C + */ +inline int Constraints::getNIAC( ) const +{ + return inactive.getLength( ); +} + + + +/* + * g e t A c t i v e + */ +inline Indexlist* Constraints::getActive( ) +{ + return &active; +} + + +/* + * g e t I n a c t i v e + */ +inline Indexlist* Constraints::getInactive( ) +{ + return &inactive; +} + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Flipper.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Flipper.hpp new file mode 100644 index 00000000000..4e6f215d681 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Flipper.hpp @@ -0,0 +1,155 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Flipper.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the Options class designed to manage user-specified + * options for solving a QProblem. + */ + + +#ifndef QPOASES_FLIPPER_HPP +#define QPOASES_FLIPPER_HPP + + +#include +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Auxiliary class for storing a copy of the current matrix factorisations. + * + * This auxiliary class stores a copy of the current matrix factorisations. It + * is used by the classe QProblemB and QProblem in case flipping bounds are enabled. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + */ +class Flipper +{ + friend class QProblemB; + friend class QProblem; + + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + Flipper( ); + + /** Constructor which takes the number of bounds and constraints. */ + Flipper( unsigned int _nV, /**< Number of bounds. */ + unsigned int _nC = 0 /**< Number of constraints. */ + ); + + /** Copy constructor (deep copy). */ + Flipper( const Flipper& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + ~Flipper( ); + + /** Assignment operator (deep copy). */ + Flipper& operator=( const Flipper& rhs /**< Rhs object. */ + ); + + + /** Initialises object with given number of bounds and constraints. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ + returnValue init( unsigned int _nV = 0, /**< Number of bounds. */ + unsigned int _nC = 0 /**< Number of constraints. */ + ); + + + /** Copies current values to non-null arguments (assumed to be allocated with consistent size). + * \return SUCCESSFUL_RETURN */ + returnValue get( Bounds* const _bounds, /**< Pointer to new bounds. */ + real_t* const R, /**< New matrix R. */ + Constraints* const _constraints = 0, /**< Pointer to new constraints. */ + real_t* const _Q = 0, /**< New matrix Q. */ + real_t* const _T = 0 /**< New matrix T. */ + ) const; + + /** Assigns new values to non-null arguments. + * \return SUCCESSFUL_RETURN */ + returnValue set( const Bounds* const _bounds, /**< Pointer to new bounds. */ + const real_t* const _R, /**< New matrix R. */ + const Constraints* const _constraints = 0, /**< Pointer to new constraints. */ + const real_t* const _Q = 0, /**< New matrix Q. */ + const real_t* const _T = 0 /**< New matrix T. */ + ); + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Frees all allocated memory. + * \return SUCCESSFUL_RETURN */ + returnValue clear( ); + + /** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ + returnValue copy( const Flipper& rhs /**< Rhs object. */ + ); + + /** Returns dimension of matrix T. + * \return Dimension of matrix T. */ + unsigned int getDimT( ) const; + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + unsigned int nV; /**< Number of variables. */ + unsigned int nC; /**< Number of constraints. */ + + Bounds bounds; /**< Data structure for problem's bounds. */ + Constraints constraints; /**< Data structure for problem's constraints. */ + + real_t* R; /**< Cholesky factor of H (i.e. H = R^T*R). */ + real_t* Q; /**< Orthonormal quadratic matrix, A = [0 T]*Q'. */ + real_t* T; /**< Reverse triangular matrix, A = [0 T]*Q'. */ +}; + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_FLIPPER_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Indexlist.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Indexlist.hpp new file mode 100644 index 00000000000..4a0e40d7fd5 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Indexlist.hpp @@ -0,0 +1,199 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Indexlist.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the Indexlist class designed to manage index lists of + * constraints and bounds within a SubjectTo object. + */ + + +#ifndef QPOASES_INDEXLIST_HPP +#define QPOASES_INDEXLIST_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Stores and manages index lists. + * + * This class manages index lists of active/inactive bounds/constraints. + * + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + */ +class Indexlist +{ + /* + * FRIENDS + */ + friend class DenseMatrix; + friend class SymDenseMat; + friend class SparseMatrix; + friend class SparseMatrixRow; + friend class SymSparseMat; + + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + Indexlist( ); + + /** Constructor which takes the desired physical length of the index list. */ + Indexlist( int n /**< Physical length of index list. */ + ); + + /** Copy constructor (deep copy). */ + Indexlist( const Indexlist& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + ~Indexlist( ); + + /** Assingment operator (deep copy). */ + Indexlist& operator=( const Indexlist& rhs /**< Rhs object. */ + ); + + + /** Initialises index list of desired physical length. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ + returnValue init( int n = 0 /**< Physical length of index list. */ + ); + + + /** Creates an array of all numbers within the index set in correct order. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ + returnValue getNumberArray( int** const numberarray /**< Output: Array of numbers (NULL on error). */ + ) const; + + /** Creates an array of all numbers within the index set in correct order. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ + returnValue getISortArray( int** const iSortArray /**< Output: iSort Array. */ + ) const; + + + /** Determines the index within the index list at which a given number is stored. + * \return >= 0: Index of given number. \n + -1: Number not found. */ + int getIndex( int givennumber /**< Number whose index shall be determined. */ + ) const; + + /** Returns the number stored at a given physical index. + * \return >= 0: Number stored at given physical index. \n + -RET_INDEXLIST_OUTOFBOUNDS */ + int getNumber( int physicalindex /**< Physical index of the number to be returned. */ + ) const; + + + /** Returns the current length of the index list. + * \return Current length of the index list. */ + inline int getLength( ) const; + + /** Returns last number within the index list. + * \return Last number within the index list. */ + inline int getLastNumber( ) const; + + + /** Adds number to index list. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_MUST_BE_REORDERD \n + RET_INDEXLIST_EXCEEDS_MAX_LENGTH */ + returnValue addNumber( int addnumber /**< Number to be added. */ + ); + + /** Removes number from index list. + * \return SUCCESSFUL_RETURN */ + returnValue removeNumber( int removenumber /**< Number to be removed. */ + ); + + /** Swaps two numbers within index list. + * \return SUCCESSFUL_RETURN */ + returnValue swapNumbers( int number1, /**< First number for swapping. */ + int number2 /**< Second number for swapping. */ + ); + + /** Determines if a given number is contained in the index set. + * \return BT_TRUE iff number is contain in the index set */ + inline BooleanType isMember( int _number /**< Number to be tested for membership. */ + ) const; + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Frees all allocated memory. + * \return SUCCESSFUL_RETURN */ + returnValue clear( ); + + /** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ + returnValue copy( const Indexlist& rhs /**< Rhs object. */ + ); + + /** Find first index j between -1 and length in sorted list of indices + * iSort such that numbers[iSort[j]] <= i < numbers[iSort[j+1]]. Uses + * bisection. + * \return j. */ + int findInsert( int i + ) const; + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + int* number; /**< Array to store numbers of constraints or bounds. */ + int* iSort; /**< Index list to sort vector \a number */ + + int length; /**< Length of index list. */ + int first; /**< Physical index of first element. */ + int last; /**< Physical index of last element. */ + int lastusedindex; /**< Physical index of last entry in index list. */ + int physicallength; /**< Physical length of index list. */ +}; + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_INDEXLIST_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Indexlist.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Indexlist.ipp new file mode 100644 index 00000000000..338c8a33bf1 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Indexlist.ipp @@ -0,0 +1,92 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Indexlist.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Implementation of inlined member functions of the Indexlist class designed + * to manage index lists of constraints and bounds within a QProblem_SubjectTo. + */ + + +BEGIN_NAMESPACE_QPOASES + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + + +/* + * g e t N u m b e r + */ +inline int Indexlist::getNumber( int physicalindex ) const +{ + /* consistency check */ + if ( ( physicalindex < 0 ) || ( physicalindex > length ) ) + return -RET_INDEXLIST_OUTOFBOUNDS; + + return number[physicalindex]; +} + + +/* + * g e t L e n g t h + */ +inline int Indexlist::getLength( ) const +{ + return length; +} + + +/* + * g e t L a s t N u m b e r + */ +inline int Indexlist::getLastNumber( ) const +{ + return number[length-1]; +} + + +/* + * g e t L a s t N u m b e r + */ +inline BooleanType Indexlist::isMember( int _number ) const +{ + if ( getIndex( _number ) >= 0 ) + return BT_TRUE; + else + return BT_FALSE; +} + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Matrices.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Matrices.hpp new file mode 100644 index 00000000000..d03ad5f6a91 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Matrices.hpp @@ -0,0 +1,867 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Matrices.hpp + * \author Andreas Potschka, Hans Joachim Ferreau, Christian Kirches + * \version 3.0 + * \date 2009-2014 + * + * Various matrix classes: Abstract base matrix class, dense and sparse matrices, + * including symmetry exploiting specializations. + */ + + + +#ifndef QPOASES_MATRICES_HPP +#define QPOASES_MATRICES_HPP + + +#include +#include + + +#ifdef __USE_SINGLE_PRECISION__ + + /** Macro for calling level 3 BLAS operation in single precision. */ + #define GEMM sgemm_ + /** Macro for calling level 3 BLAS operation in single precision. */ + #define SYR ssyr_ + /** Macro for calling level 3 BLAS operation in single precision. */ + #define SYR2 ssyr2_ + /** Macro for calling level 3 BLAS operation in single precision. */ + #define POTRF spotrf_ + +#else + + /** Macro for calling level 3 BLAS operation in double precision. */ + #define GEMM dgemm_ + /** Macro for calling level 3 BLAS operation in double precision. */ + #define SYR dsyr_ + /** Macro for calling level 3 BLAS operation in double precision. */ + #define SYR2 dsyr2_ + /** Macro for calling level 3 BLAS operation in double precision. */ + #define POTRF dpotrf_ + +#endif /* __USE_SINGLE_PRECISION__ */ + + +extern "C" +{ + /** Performs one of the matrix-matrix operation in double precision. */ + void dgemm_ ( const char*, const char*, const unsigned long*, const unsigned long*, const unsigned long*, + const double*, const double*, const unsigned long*, const double*, const unsigned long*, + const double*, double*, const unsigned long* ); + /** Performs one of the matrix-matrix operation in single precision. */ + void sgemm_ ( const char*, const char*, const unsigned long*, const unsigned long*, const unsigned long*, + const float*, const float*, const unsigned long*, const float*, const unsigned long*, + const float*, float*, const unsigned long* ); + + /** Performs a symmetric rank 1 operation in double precision. */ + void dsyr_ ( const char *, const unsigned long *, const double *, const double *, + const unsigned long *, double *, const unsigned long *); + /** Performs a symmetric rank 1 operation in single precision. */ + void ssyr_ ( const char *, const unsigned long *, const float *, const float *, + const unsigned long *, float *, const unsigned long *); + + /** Performs a symmetric rank 2 operation in double precision. */ + void dsyr2_ ( const char *, const unsigned long *, const double *, const double *, + const unsigned long *, const double *, const unsigned long *, double *, const unsigned long *); + /** Performs a symmetric rank 2 operation in single precision. */ + void ssyr2_ ( const char *, const unsigned long *, const float *, const float *, + const unsigned long *, const float *, const unsigned long *, float *, const unsigned long *); + + /** Calculates the Cholesky factorization of a real symmetric positive definite matrix in double precision. */ + void dpotrf_ ( const char *, const unsigned long *, double *, const unsigned long *, long * ); + /** Calculates the Cholesky factorization of a real symmetric positive definite matrix in single precision. */ + void spotrf_ ( const char *, const unsigned long *, float *, const unsigned long *, long * ); +} + + +BEGIN_NAMESPACE_QPOASES + +/** + * Integer type for sparse matrix row/column entries. Make this "int" + * for 32 bit entries, and "long" for 64-bit entries on x86_64 platform. + * + * Most sparse codes still assume 32-bit entries here (HSL, BQPD, ...) + */ +typedef int sparse_int_t; + + +/** + * \brief Abstract base class for interfacing tailored matrix-vector operations. + * + * Abstract base matrix class. Supplies interface to matrix vector + * products, including products with submatrices given by (ordered) working set + * index lists (see \a SubjectTo). + * + * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau + * \version 3.0 + * \date 2011-2014 + */ +class Matrix +{ + public: + /** Default constructor. */ + Matrix( ) { doNotFreeMemory(); }; + + /** Destructor. */ + virtual ~Matrix( ) { }; + + /** Frees all internal memory. */ + virtual void free( ) = 0; + + /** Returns a deep-copy of the Matrix object. + * \return Deep-copy of Matrix object */ + virtual Matrix* duplicate( ) const = 0; + + /** Returns i-th diagonal entry. + * \return i-th diagonal entry */ + virtual real_t diag( int i /**< Index. */ + ) const = 0; + + /** Checks whether matrix is square and diagonal. + * \return BT_TRUE iff matrix is square and diagonal; \n + * BT_FALSE otherwise. */ + virtual BooleanType isDiag( ) const = 0; + + /** Get the N-norm of the matrix + * \return N-norm of the matrix + */ + virtual real_t getNorm( int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ) const = 0; + + /** Get the N-norm of a row + * \return N-norm of row \a rNum + */ + virtual real_t getRowNorm( int rNum, /**< Row number. */ + int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ) const = 0; + + /** Retrieve indexed entries of matrix row multiplied by alpha. + * \return SUCCESSFUL_RETURN */ + virtual returnValue getRow( int rNum, /**< Row number. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + real_t alpha, /**< Scalar factor. */ + real_t *row /**< Output row vector. */ + ) const = 0; + + /** Retrieve indexed entries of matrix column multiplied by alpha. + * \return SUCCESSFUL_RETURN */ + virtual returnValue getCol( int cNum, /**< Column number. */ + const Indexlist* const irows, /**< Index list specifying rows. */ + real_t alpha, /**< Scalar factor. */ + real_t *col /**< Output column vector. */ + ) const = 0; + + /** Evaluate Y=alpha*A*X + beta*Y. + * \return SUCCESSFUL_RETURN */ + virtual returnValue times ( int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const = 0; + + /** Evaluate Y=alpha*A'*X + beta*Y. + * \return SUCCESSFUL_RETURN */ + virtual returnValue transTimes ( int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const = 0; + + /** Evaluate matrix vector product with submatrix given by Indexlist. + * \return SUCCESSFUL_RETURN */ + virtual returnValue times ( const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD, /**< Leading dimension of output y. */ + BooleanType yCompr = BT_TRUE /**< Compressed storage for y. */ + ) const = 0; + + /** Evaluate matrix transpose vector product. + * \return SUCCESSFUL_RETURN */ + virtual returnValue transTimes ( const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const = 0; + + /** Adds given offset to diagonal of matrix. + * \return SUCCESSFUL_RETURN \n + RET_NO_DIAGONAL_AVAILABLE */ + virtual returnValue addToDiag( real_t alpha /**< Diagonal offset. */ + ) = 0; + + /** Allocates and creates dense matrix array in row major format. + * + * Note: Calling function has to free allocated memory! + * + * \return Pointer to matrix array. + */ + virtual real_t* full() const = 0; + + + /** Prints matrix to screen. + * \return SUCCESSFUL_RETURN */ + virtual returnValue print( const char* name = 0 /** Name of matrix. */ + ) const = 0; + + + /** Returns whether internal memory needs to be de-allocated. + * \return BT_TRUE iff internal memory needs to be de-allocated, \n + BT_FALSE otherwise */ + BooleanType needToFreeMemory( ) const { return freeMemory; }; + + /** Enables de-allocation of internal memory. */ + void doFreeMemory( ) { freeMemory = BT_TRUE; }; + + /** Disables de-allocation of internal memory. */ + void doNotFreeMemory( ) { freeMemory = BT_FALSE; }; + + + protected: + BooleanType freeMemory; /**< Indicating whether internal memory needs to be de-allocated. */ + +}; + + +/** + * \brief Abstract base class for interfacing matrix-vector operations tailored to symmetric matrices. + * + * Abstract base class for symmetric matrices. Extends Matrix interface with + * bilinear form evaluation. + * + * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau + * \version 3.0 + * \date 2011-2014 + */ +class SymmetricMatrix : public virtual Matrix +{ + public: + + /** Returns a deep-copy of the SymmetricMatrix object. + * \return Deep-copy of SymmetricMatrix object */ + virtual SymmetricMatrix* duplicateSym( ) const = 0; + + + /** Compute bilinear form y = x'*H*x using submatrix given by index list. + * \return SUCCESSFUL_RETURN */ + virtual returnValue bilinear( const Indexlist* const icols, /**< Index list specifying columns of x. */ + int xN, /**< Number of vectors to multiply. */ + const real_t *x, /**< Input vector to be multiplied (uncompressed). */ + int xLD, /**< Leading dimension of input x. */ + real_t *y, /**< Output vector of results (compressed). */ + int yLD /**< Leading dimension of output y. */ + ) const = 0; + +}; + + +/** + * \brief Interfaces matrix-vector operations tailored to general dense matrices. + * + * Dense matrix class (row major format). + * + * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau + * \version 3.0 + * \date 2011-2014 + */ +class DenseMatrix : public virtual Matrix +{ + public: + /** Default constructor. */ + DenseMatrix( ) : nRows(0), nCols(0), leaDim(0), val(0) {}; + + /** Constructor from vector of values. + * Caution: Data pointer must be valid throughout lifetime + */ + DenseMatrix( int m, /**< Number of rows. */ + int n, /**< Number of columns. */ + int lD, /**< Leading dimension. */ + real_t *v /**< Values. */ + ) : nRows(m), nCols(n), leaDim(lD), val(v) {} + + + /** Destructor. */ + virtual ~DenseMatrix(); + + /** Frees all internal memory. */ + virtual void free( ); + + /** Returns a deep-copy of the Matrix object. + * \return Deep-copy of Matrix object */ + virtual Matrix *duplicate( ) const; + + /** Returns i-th diagonal entry. + * \return i-th diagonal entry */ + virtual real_t diag( int i /**< Index. */ + ) const; + + /** Checks whether matrix is square and diagonal. + * \return BT_TRUE iff matrix is square and diagonal; \n + * BT_FALSE otherwise. */ + virtual BooleanType isDiag( ) const; + + /** Get the N-norm of the matrix + * \return N-norm of the matrix + */ + virtual real_t getNorm( int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ) const; + + /** Get the N-norm of a row + * \return N-norm of row \a rNum + */ + virtual real_t getRowNorm( int rNum, /**< Row number. */ + int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ) const; + + /** Retrieve indexed entries of matrix row multiplied by alpha. + * \return SUCCESSFUL_RETURN */ + virtual returnValue getRow( + int rNum, /**< Row number. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + real_t alpha, /**< Scalar factor. */ + real_t *row /**< Output row vector. */ + ) const; + + /** Retrieve indexed entries of matrix column multiplied by alpha. + * \return SUCCESSFUL_RETURN */ + virtual returnValue getCol( + int cNum, /**< Column number. */ + const Indexlist* const irows, /**< Index list specifying rows. */ + real_t alpha, /**< Scalar factor. */ + real_t *col /**< Output column vector. */ + ) const; + + /** Evaluate Y=alpha*A*X + beta*Y. + * \return SUCCESSFUL_RETURN. */ + returnValue times ( int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Evaluate Y=alpha*A'*X + beta*Y. + * \return SUCCESSFUL_RETURN. */ + returnValue transTimes ( int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Evaluate matrix vector product with submatrix given by Indexlist. + * \return SUCCESSFUL_RETURN */ + virtual returnValue times ( const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD, /**< Leading dimension of output y. */ + BooleanType yCompr = BT_TRUE /**< Compressed storage for y. */ + ) const; + + /** Evaluate matrix transpose vector product. + * \return SUCCESSFUL_RETURN */ + virtual returnValue transTimes ( const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Adds given offset to diagonal of matrix. + * \return SUCCESSFUL_RETURN \n + RET_NO_DIAGONAL_AVAILABLE */ + virtual returnValue addToDiag( real_t alpha /**< Diagonal offset. */ + ); + + + /** Allocates and creates dense matrix array in row major format. + * + * Note: Calling function has to free allocated memory! + * + * \return Pointer to matrix array. + */ + virtual real_t* full() const; + + + /** Prints matrix to screen. + * \return SUCCESSFUL_RETURN */ + virtual returnValue print( const char* name = 0 /** Name of matrix. */ + ) const; + + + protected: + int nRows; /**< Number of rows. */ + int nCols; /**< Number of columns. */ + int leaDim; /**< Leading dimension. */ + real_t *val; /**< Vector of entries. */ +}; + + +/** + * \brief Interfaces matrix-vector operations tailored to symmetric dense matrices. + * + * Symmetric dense matrix class. + * + * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau + * \version 3.0 + * \date 2011-2014 + */ +class SymDenseMat : public DenseMatrix, public SymmetricMatrix +{ + public: + /** Default constructor. */ + SymDenseMat() : DenseMatrix() {} + + /** Constructor from vector of values. */ + SymDenseMat( int m, /**< Number of rows. */ + int n, /**< Number of columns. */ + int lD, /**< Leading dimension. */ + real_t *v /**< Values. */ + ) : DenseMatrix(m, n, lD, v) {} + + /** Returns a deep-copy of the Matrix object. + * \return Deep-copy of Matrix object */ + virtual Matrix *duplicate( ) const; + + /** Returns a deep-copy of the SymmetricMatrix object. + * \return Deep-copy of SymmetricMatrix object */ + virtual SymmetricMatrix* duplicateSym( ) const; + + + /** Compute bilinear form y = x'*H*x using submatrix given by index list. + * \return SUCCESSFUL_RETURN */ + virtual returnValue bilinear( const Indexlist* const icols, /**< Index list specifying columns of x. */ + int xN, /**< Number of vectors to multiply. */ + const real_t *x, /**< Input vector to be multiplied (uncompressed). */ + int xLD, /**< Leading dimension of input x. */ + real_t *y, /**< Output vector of results (compressed). */ + int yLD /**< Leading dimension of output y. */ + ) const; +}; + + +/** + * \brief Interfaces matrix-vector operations tailored to general sparse matrices. + * + * Sparse matrix class (col compressed format). + * + * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau + * \version 3.0 + * \date 2011-2014 + */ +class SparseMatrix : public virtual Matrix +{ + public: + /** Default constructor. */ + SparseMatrix(); + + /** Constructor with arguments. */ + SparseMatrix( int nr, /**< Number of rows. */ + int nc, /**< Number of columns. */ + sparse_int_t *r, /**< Row indices (length). */ + sparse_int_t *c, /**< Indices to first entry of columns (nCols+1). */ + real_t *v /**< Vector of entries (length). */ + ); + + /** Constructor from dense matrix. */ + SparseMatrix( int nr, /**< Number of rows. */ + int nc, /**< Number of columns. */ + int ld, /**< Leading dimension. */ + const real_t * const v /**< Row major stored matrix elements. */ + ); + + /** Destructor. */ + virtual ~SparseMatrix(); + + /** Frees all internal memory. */ + virtual void free( ); + + /** Returns a deep-copy of the Matrix object. + * \return Deep-copy of Matrix object */ + virtual Matrix *duplicate( ) const; + + /** Returns i-th diagonal entry. + * \return i-th diagonal entry (or INFTY if diagonal does not exist)*/ + virtual real_t diag( int i /**< Index. */ + ) const; + + /** Checks whether matrix is square and diagonal. + * \return BT_TRUE iff matrix is square and diagonal; \n + * BT_FALSE otherwise. */ + virtual BooleanType isDiag( ) const; + + + /** Get the N-norm of the matrix + * \return N-norm of the matrix + */ + virtual real_t getNorm( int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ) const; + + /** Get the N-norm of a row + * \return N-norm of row \a rNum + */ + virtual real_t getRowNorm( int rNum, /**< Row number. */ + int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ) const; + + /** Retrieve indexed entries of matrix row multiplied by alpha. */ + virtual returnValue getRow( int rNum, /**< Row number. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + real_t alpha, /**< Scalar factor. */ + real_t *row /**< Output row vector. */ + ) const; + + /** Retrieve indexed entries of matrix column multiplied by alpha. */ + virtual returnValue getCol( int cNum, /**< Column number. */ + const Indexlist* const irows, /**< Index list specifying rows. */ + real_t alpha, /**< Scalar factor. */ + real_t *col /**< Output column vector. */ + ) const; + + /** Evaluate Y=alpha*A*X + beta*Y. */ + virtual returnValue times ( int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Evaluate Y=alpha*A'*X + beta*Y. */ + virtual returnValue transTimes ( int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Evaluate matrix vector product with submatrix given by Indexlist. */ + virtual returnValue times ( const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD, /**< Leading dimension of output y. */ + BooleanType yCompr = BT_TRUE /**< Compressed storage for y. */ + ) const; + + /** Evaluate matrix transpose vector product. */ + virtual returnValue transTimes ( const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Adds given offset to diagonal of matrix. + * \return SUCCESSFUL_RETURN \n + RET_NO_DIAGONAL_AVAILABLE */ + virtual returnValue addToDiag( real_t alpha /**< Diagonal offset. */ + ); + + /** Create jd field from ir and jc. + * \return Pointer to jd. */ + sparse_int_t *createDiagInfo(); + + /** Allocates and creates dense matrix array in row major format. + * + * Note: Calling function has to free allocated memory! + * + * \return Pointer to matrix array. + */ + virtual real_t* full() const; + + /** Prints matrix to screen. + * \return SUCCESSFUL_RETURN */ + virtual returnValue print( const char* name = 0 /** Name of matrix. */ + ) const; + + + protected: + int nRows; /**< Number of rows. */ + int nCols; /**< Number of columns. */ + sparse_int_t *ir; /**< Row indices (length). */ + sparse_int_t *jc; /**< Indices to first entry of columns (nCols+1). */ + sparse_int_t *jd; /**< Indices to first entry of lower triangle (including diagonal) (nCols). */ + real_t *val; /**< Vector of entries (length). */ +}; + + +/** + * \brief Interfaces matrix-vector operations tailored to general sparse matrices. + * + * Sparse matrix class (row compressed format). + * + * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau + * \version 3.0 + * \date 2011-2014 + */ +class SparseMatrixRow : public virtual Matrix +{ + public: + /** Default constructor. */ + SparseMatrixRow(); + + /** Constructor with arguments. */ + SparseMatrixRow( int nr, /**< Number of rows. */ + int nc, /**< Number of columns. */ + sparse_int_t *r, /**< Indices to first entry of rows (nRows+1). */ + sparse_int_t *c, /**< Column indices (length). */ + real_t *v /**< Vector of entries (length). */ + ); + + /** Constructor from dense matrix. */ + SparseMatrixRow( int nr, /**< Number of rows. */ + int nc, /**< Number of columns. */ + int ld, /**< Leading dimension. */ + const real_t * const v /**< Row major stored matrix elements. */ + ); + + /** Destructor. */ + virtual ~SparseMatrixRow(); + + /** Frees all internal memory. */ + virtual void free( ); + + /** Returns a deep-copy of the Matrix object. + * \return Deep-copy of Matrix object */ + virtual Matrix *duplicate( ) const; + + /** Returns i-th diagonal entry. + * \return i-th diagonal entry (or INFTY if diagonal does not exist)*/ + virtual real_t diag( int i /**< Index. */ + ) const; + + /** Checks whether matrix is square and diagonal. + * \return BT_TRUE iff matrix is square and diagonal; \n + * BT_FALSE otherwise. */ + virtual BooleanType isDiag( ) const; + + + /** Get the N-norm of the matrix + * \return N-norm of the matrix + */ + virtual real_t getNorm( int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ) const; + + /** Get the N-norm of a row + * \return N-norm of row \a rNum + */ + virtual real_t getRowNorm( int rNum, /**< Row number. */ + int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ) const; + + /** Retrieve indexed entries of matrix row multiplied by alpha. */ + virtual returnValue getRow ( + int rNum, /**< Row number. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + real_t alpha, /**< Scalar factor. */ + real_t *row /**< Output row vector. */ + ) const; + + /** Retrieve indexed entries of matrix column multiplied by alpha. */ + virtual returnValue getCol ( + int cNum, /**< Column number. */ + const Indexlist* const irows, /**< Index list specifying rows. */ + real_t alpha, /**< Scalar factor. */ + real_t *col /**< Output column vector. */ + ) const; + + /** Evaluate Y=alpha*A*X + beta*Y. */ + virtual returnValue times ( int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Evaluate Y=alpha*A'*X + beta*Y. */ + virtual returnValue transTimes ( int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Evaluate matrix vector product with submatrix given by Indexlist. */ + virtual returnValue times ( const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD, /**< Leading dimension of output y. */ + BooleanType yCompr = BT_TRUE /**< Compressed storage for y. */ + ) const; + + /** Evaluate matrix transpose vector product. */ + virtual returnValue transTimes ( const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ) const; + + /** Adds given offset to diagonal of matrix. + * \return SUCCESSFUL_RETURN \n + RET_NO_DIAGONAL_AVAILABLE */ + virtual returnValue addToDiag( real_t alpha /**< Diagonal offset. */ + ); + + /** Create jd field from ir and jc. + * \return Pointer to jd. */ + sparse_int_t *createDiagInfo(); + + /** Allocates and creates dense matrix array in row major format. + * + * Note: Calling function has to free allocated memory! + * + * \return Pointer to matrix array. + */ + virtual real_t* full() const; + + /** Prints matrix to screen. + * \return SUCCESSFUL_RETURN */ + virtual returnValue print( const char* name = 0 /** Name of matrix. */ + ) const; + + + protected: + int nRows; /**< Number of rows. */ + int nCols; /**< Number of columns. */ + sparse_int_t *jr; /**< Indices to first entry of row (nRows+1). */ + sparse_int_t *ic; /**< Column indices (length). */ + sparse_int_t *jd; /**< Indices to first entry of upper triangle (including diagonal) (nRows). */ + real_t *val; /**< Vector of entries (length). */ +}; + + +/** + * \brief Interfaces matrix-vector operations tailored to symmetric sparse matrices. + * + * Symmetric sparse matrix class (column compressed format). + * + * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau + * \version 3.0 + * \date 2011-2014 + */ +class SymSparseMat : public SymmetricMatrix, public SparseMatrix +{ + public: + /** Default constructor. */ + SymSparseMat() : SparseMatrix() {} + + /** Constructor with arguments. */ + SymSparseMat( int nr, /**< Number of rows. */ + int nc, /**< Number of columns. */ + sparse_int_t *r, /**< Row indices (length). */ + sparse_int_t *c, /**< Indices to first entry of columns (nCols+1). */ + real_t *v /**< Vector of entries (length). */ + ) : SparseMatrix(nr, nc, r, c, v) {} + + /** Constructor from dense matrix. */ + SymSparseMat( int nr, /**< Number of rows. */ + int nc, /**< Number of columns. */ + int ld, /**< Leading dimension. */ + const real_t * const v /**< Row major stored matrix elements. */ + ) : SparseMatrix(nr, nc, ld, v) {} + + /** Returns a deep-copy of the Matrix object. + * \return Deep-copy of Matrix object */ + virtual Matrix *duplicate( ) const; + + /** Returns a deep-copy of the SymmetricMatrix object. + * \return Deep-copy of SymmetricMatrix object */ + virtual SymmetricMatrix* duplicateSym( ) const; + + + /** Compute bilinear form y = x'*H*x using submatrix given by index list. + * \return SUCCESSFUL_RETURN */ + virtual returnValue bilinear( const Indexlist* const icols, /**< Index list specifying columns of x. */ + int xN, /**< Number of vectors to multiply. */ + const real_t *x, /**< Input vector to be multiplied (uncompressed). */ + int xLD, /**< Leading dimension of input x. */ + real_t *y, /**< Output vector of results (compressed). */ + int yLD /**< Leading dimension of output y. */ + ) const; +}; + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_MATRICES_HPP */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/MessageHandling.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/MessageHandling.hpp new file mode 100644 index 00000000000..fcddeb8fd89 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/MessageHandling.hpp @@ -0,0 +1,472 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/MessageHandling.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches (thanks to Leonard Wirsching) + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the MessageHandling class including global return values. + */ + + +#ifndef QPOASES_MESSAGEHANDLING_HPP +#define QPOASES_MESSAGEHANDLING_HPP + + +#include +#include + +#ifdef __DEBUG__ +#include +#endif + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** Default file to display messages. */ +static FILE* stdFile = stdout; + + +/** + * \brief Defines all symbols for global return values. + * + * The enumeration returnValueType defines all symbols for global return values. + * Important: All return values are assumed to be nonnegative! + * + * \author Hans Joachim Ferreau + */ +enum returnValue +{ +TERMINAL_LIST_ELEMENT = -1, /**< Terminal list element, internal usage only! */ +/* miscellaneous */ +SUCCESSFUL_RETURN = 0, /**< Successful return. */ +RET_DIV_BY_ZERO, /**< Division by zero. */ +RET_INDEX_OUT_OF_BOUNDS, /**< Index out of bounds. */ +RET_INVALID_ARGUMENTS, /**< At least one of the arguments is invalid. */ +RET_ERROR_UNDEFINED, /**< Error number undefined. */ +RET_WARNING_UNDEFINED, /**< Warning number undefined. */ +RET_INFO_UNDEFINED, /**< Info number undefined. */ +RET_EWI_UNDEFINED, /**< Error/warning/info number undefined. */ +RET_AVAILABLE_WITH_LINUX_ONLY, /**< This function is available under Linux only. */ +RET_UNKNOWN_BUG, /**< The error occurred is not yet known. */ +RET_PRINTLEVEL_CHANGED, /**< Print level changed. */ +RET_NOT_YET_IMPLEMENTED, /**< Requested function is not yet implemented in this version of qpOASES. */ +/* Indexlist */ +RET_INDEXLIST_MUST_BE_REORDERD, /**< Index list has to be reordered. (12) */ +RET_INDEXLIST_EXCEEDS_MAX_LENGTH, /**< Index list exceeds its maximal physical length. */ +RET_INDEXLIST_CORRUPTED, /**< Index list corrupted. */ +RET_INDEXLIST_OUTOFBOUNDS, /**< Physical index is out of bounds. */ +RET_INDEXLIST_ADD_FAILED, /**< Adding indices from another index set failed. */ +RET_INDEXLIST_INTERSECT_FAILED, /**< Intersection with another index set failed. */ +/* SubjectTo / Bounds / Constraints */ +RET_INDEX_ALREADY_OF_DESIRED_STATUS, /**< Index is already of desired status. (18) */ +RET_ADDINDEX_FAILED, /**< Adding index to index set failed. */ +RET_REMOVEINDEX_FAILED, /**< Removing index from index set failed. (20) */ +RET_SWAPINDEX_FAILED, /**< Cannot swap between different indexsets. */ +RET_NOTHING_TO_DO, /**< Nothing to do. */ +RET_SETUP_BOUND_FAILED, /**< Setting up bound index failed. */ +RET_SETUP_CONSTRAINT_FAILED, /**< Setting up constraint index failed. */ +RET_MOVING_BOUND_FAILED, /**< Moving bound between index sets failed. */ +RET_MOVING_CONSTRAINT_FAILED, /**< Moving constraint between index sets failed. */ +RET_SHIFTING_FAILED, /**< Shifting of bounds/constraints failed. */ +RET_ROTATING_FAILED, /**< Rotating of bounds/constraints failed. */ +/* QProblem */ +RET_QPOBJECT_NOT_SETUP, /**< The QP object has not been setup correctly, use another constructor. (29) */ +RET_QP_ALREADY_INITIALISED, /**< QProblem has already been initialised. (30) */ +RET_NO_INIT_WITH_STANDARD_SOLVER, /**< Initialisation via extern QP solver is not yet implemented. */ +RET_RESET_FAILED, /**< Reset failed. */ +RET_INIT_FAILED, /**< Initialisation failed. */ +RET_INIT_FAILED_TQ, /**< Initialisation failed due to TQ factorisation. */ +RET_INIT_FAILED_CHOLESKY, /**< Initialisation failed due to Cholesky decomposition. */ +RET_INIT_FAILED_HOTSTART, /**< Initialisation failed! QP could not be solved! */ +RET_INIT_FAILED_INFEASIBILITY, /**< Initial QP could not be solved due to infeasibility! */ +RET_INIT_FAILED_UNBOUNDEDNESS, /**< Initial QP could not be solved due to unboundedness! */ +RET_INIT_FAILED_REGULARISATION, /**< Initialisation failed as Hessian matrix could not be regularised. */ +RET_INIT_SUCCESSFUL, /**< Initialisation done. (40) */ +RET_OBTAINING_WORKINGSET_FAILED, /**< Failed to obtain working set for auxiliary QP. */ +RET_SETUP_WORKINGSET_FAILED, /**< Failed to setup working set for auxiliary QP. */ +RET_SETUP_AUXILIARYQP_FAILED, /**< Failed to setup auxiliary QP for initialised homotopy. */ +RET_NO_EXTERN_SOLVER, /**< No extern QP solver available. */ +RET_QP_UNBOUNDED, /**< QP is unbounded. */ +RET_QP_INFEASIBLE, /**< QP is infeasible. */ +RET_QP_NOT_SOLVED, /**< Problems occurred while solving QP with standard solver. */ +RET_QP_SOLVED, /**< QP successfully solved. */ +RET_UNABLE_TO_SOLVE_QP, /**< Problems occurred while solving QP. */ +RET_INITIALISATION_STARTED, /**< Starting problem initialisation... */ +RET_HOTSTART_FAILED, /**< Unable to perform homotopy due to internal error. (50) */ +RET_HOTSTART_FAILED_TO_INIT, /**< Unable to initialise problem. */ +RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED, /**< Unable to perform homotopy as previous QP is not solved. */ +RET_ITERATION_STARTED, /**< Iteration... */ +RET_SHIFT_DETERMINATION_FAILED, /**< Determination of shift of the QP data failed. */ +RET_STEPDIRECTION_DETERMINATION_FAILED, /**< Determination of step direction failed. */ +RET_STEPLENGTH_DETERMINATION_FAILED, /**< Determination of step direction failed. */ +RET_OPTIMAL_SOLUTION_FOUND, /**< Optimal solution of neighbouring QP found. */ +RET_HOMOTOPY_STEP_FAILED, /**< Unable to perform homotopy step. */ +RET_HOTSTART_STOPPED_INFEASIBILITY, /**< Premature homotopy termination because QP is infeasible. */ +RET_HOTSTART_STOPPED_UNBOUNDEDNESS, /**< Premature homotopy termination because QP is unbounded. (60) */ +RET_WORKINGSET_UPDATE_FAILED, /**< Unable to update working sets according to initial guesses. */ +RET_MAX_NWSR_REACHED, /**< Maximum number of working set recalculations performed. */ +RET_CONSTRAINTS_NOT_SPECIFIED, /**< Problem does comprise constraints! You also have to specify new constraints' bounds. */ +RET_INVALID_FACTORISATION_FLAG, /**< Invalid factorisation flag. */ +RET_UNABLE_TO_SAVE_QPDATA, /**< Unable to save QP data. */ +RET_STEPDIRECTION_FAILED_TQ, /**< Abnormal termination due to TQ factorisation. */ +RET_STEPDIRECTION_FAILED_CHOLESKY, /**< Abnormal termination due to Cholesky factorisation. */ +RET_CYCLING_DETECTED, /**< Cycling detected. */ +RET_CYCLING_NOT_RESOLVED, /**< Cycling cannot be resolved, QP probably infeasible. */ +RET_CYCLING_RESOLVED, /**< Cycling probably resolved. (70) */ +RET_STEPSIZE, /**< For displaying performed stepsize. */ +RET_STEPSIZE_NONPOSITIVE, /**< For displaying non-positive stepsize. */ +RET_SETUPSUBJECTTOTYPE_FAILED, /**< Setup of SubjectToTypes failed. */ +RET_ADDCONSTRAINT_FAILED, /**< Addition of constraint to working set failed. */ +RET_ADDCONSTRAINT_FAILED_INFEASIBILITY, /**< Addition of constraint to working set failed (due to QP infeasibility). */ +RET_ADDBOUND_FAILED, /**< Addition of bound to working set failed. */ +RET_ADDBOUND_FAILED_INFEASIBILITY, /**< Addition of bound to working set failed (due to QP infeasibility). */ +RET_REMOVECONSTRAINT_FAILED, /**< Removal of constraint from working set failed. */ +RET_REMOVEBOUND_FAILED, /**< Removal of bound from working set failed. */ +RET_REMOVE_FROM_ACTIVESET, /**< Removing from active set... (80) */ +RET_ADD_TO_ACTIVESET, /**< Adding to active set... */ +RET_REMOVE_FROM_ACTIVESET_FAILED, /**< Removing from active set failed. */ +RET_ADD_TO_ACTIVESET_FAILED, /**< Adding to active set failed. */ +RET_CONSTRAINT_ALREADY_ACTIVE, /**< Constraint is already active. */ +RET_ALL_CONSTRAINTS_ACTIVE, /**< All constraints are active, no further constraint can be added. */ +RET_LINEARLY_DEPENDENT, /**< New bound/constraint is linearly dependent. */ +RET_LINEARLY_INDEPENDENT, /**< New bound/constraint is linearly independent. */ +RET_LI_RESOLVED, /**< Linear independence of active constraint matrix successfully resolved. */ +RET_ENSURELI_FAILED, /**< Failed to ensure linear independence of active constraint matrix. */ +RET_ENSURELI_FAILED_TQ, /**< Abnormal termination due to TQ factorisation. (90) */ +RET_ENSURELI_FAILED_NOINDEX, /**< QP is infeasible. */ +RET_ENSURELI_FAILED_CYCLING, /**< QP is infeasible. */ +RET_BOUND_ALREADY_ACTIVE, /**< Bound is already active. */ +RET_ALL_BOUNDS_ACTIVE, /**< All bounds are active, no further bound can be added. */ +RET_CONSTRAINT_NOT_ACTIVE, /**< Constraint is not active. */ +RET_BOUND_NOT_ACTIVE, /**< Bound is not active. */ +RET_HESSIAN_NOT_SPD, /**< Projected Hessian matrix not positive definite. */ +RET_HESSIAN_INDEFINITE, /**< Hessian matrix is indefinite. */ +RET_MATRIX_SHIFT_FAILED, /**< Unable to update matrices or to transform vectors. */ +RET_MATRIX_FACTORISATION_FAILED, /**< Unable to calculate new matrix factorisations. (100) */ +RET_PRINT_ITERATION_FAILED, /**< Unable to print information on current iteration. */ +RET_NO_GLOBAL_MESSAGE_OUTPUTFILE, /**< No global message output file initialised. */ +RET_DISABLECONSTRAINTS_FAILED, /**< Unable to disbable constraints. */ +RET_ENABLECONSTRAINTS_FAILED, /**< Unable to enbable constraints. */ +RET_ALREADY_ENABLED, /**< Bound or constraint is already enabled. */ +RET_ALREADY_DISABLED, /**< Bound or constraint is already disabled. */ +RET_NO_HESSIAN_SPECIFIED, /**< No Hessian matrix has been specified. */ +RET_USING_REGULARISATION, /**< Using regularisation as Hessian matrix is not positive definite. */ +RET_EPS_MUST_BE_POSITVE, /**< Eps for regularisation must be sufficiently positive. */ +RET_REGSTEPS_MUST_BE_POSITVE, /**< Maximum number of regularisation steps must be non-negative. (110) */ +RET_HESSIAN_ALREADY_REGULARISED, /**< Hessian has been already regularised. */ +RET_CANNOT_REGULARISE_IDENTITY, /**< Identity Hessian matrix cannot be regularised. */ +RET_CANNOT_REGULARISE_SPARSE, /**< Sparse matrix cannot be regularised as diagonal entry is missing. */ +RET_NO_REGSTEP_NWSR, /**< No additional regularisation step could be performed due to limits. */ +RET_FEWER_REGSTEPS_NWSR, /**< Fewer additional regularisation steps have been performed due to limits. */ +RET_CHOLESKY_OF_ZERO_HESSIAN, /**< Cholesky decomposition of (unregularised) zero Hessian matrix. */ +RET_CONSTRAINTS_ARE_NOT_SCALED, /**< (no longer in use) */ +RET_INITIAL_BOUNDS_STATUS_NYI, /**< (no longer in use) */ +RET_ERROR_IN_CONSTRAINTPRODUCT, /**< Error in user-defined constraint product function. */ +RET_FIX_BOUNDS_FOR_LP, /**< All initial bounds must be fixed when solving an (unregularised) LP. */ +RET_USE_REGULARISATION_FOR_LP, /**< Set options.enableRegularisation=BT_TRUE for solving LPs. */ +/* SQProblem */ +RET_UPDATEMATRICES_FAILED, /**< Unable to update QP matrices. */ +RET_UPDATEMATRICES_FAILED_AS_QP_NOT_SOLVED, /**< Unable to update matrices as previous QP is not solved. */ +/* Utils */ +RET_UNABLE_TO_OPEN_FILE, /**< Unable to open file. (120) */ +RET_UNABLE_TO_WRITE_FILE, /**< Unable to write into file. */ +RET_UNABLE_TO_READ_FILE, /**< Unable to read from file. */ +RET_FILEDATA_INCONSISTENT, /**< File contains inconsistent data. */ +/* Options */ +RET_OPTIONS_ADJUSTED, /**< Options needed to be adjusted for consistency reasons. */ +/* SolutionAnalysis */ +RET_UNABLE_TO_ANALYSE_QPROBLEM, /**< Unable to analyse (S)QProblem(B) object. */ +/* Benchmark */ +RET_NWSR_SET_TO_ONE, /**< Maximum number of working set changes was set to 1. */ +RET_UNABLE_TO_READ_BENCHMARK, /**< Unable to read benchmark data. */ +RET_BENCHMARK_ABORTED, /**< Benchmark aborted. */ +RET_INITIAL_QP_SOLVED, /**< Initial QP solved. */ +RET_QP_SOLUTION_STARTED, /**< Solving QP... */ +RET_BENCHMARK_SUCCESSFUL, /**< Benchmark terminated successfully. (130) */ +/* Sparse matrices */ +RET_NO_DIAGONAL_AVAILABLE, /**< Sparse matrix does not have entries on full diagonal. */ +RET_DIAGONAL_NOT_INITIALISED, /**< Diagonal data of sparse matrix has not been initialised. */ +/* Dropping of infeasible constraints */ +RET_ENSURELI_DROPPED, /**< Linear independence resolved by dropping blocking constraint. */ +/* Simple exitflags */ +RET_SIMPLE_STATUS_P1, /**< QP problem could not be solved within given number of iterations. */ +RET_SIMPLE_STATUS_P0, /**< QP problem solved. */ +RET_SIMPLE_STATUS_M1, /**< QP problem could not be solved due to an internal error. */ +RET_SIMPLE_STATUS_M2, /**< QP problem is infeasible (and thus could not be solved). */ +RET_SIMPLE_STATUS_M3 /**< QP problem is unbounded (and thus could not be solved). */ +}; + + +/** + * \brief Handles all kind of error messages, warnings and other information. + * + * This class handles all kinds of messages (errors, warnings, infos) initiated + * by qpOASES modules and stores the corresponding global preferences. + * + * \author Hans Joachim Ferreau (thanks to Leonard Wirsching) + * \version 3.0 + * \date 2007-2014 + */ +class MessageHandling +{ + /* + * INTERNAL DATA STRUCTURES + */ + public: + /** + * \brief Data structure for entries in global message list. + * + * Data structure for entries in global message list. + * + * \author Hans Joachim Ferreau + */ + typedef struct { + returnValue key; /**< Global return value. */ + const char* data; /**< Corresponding message. */ + VisibilityStatus globalVisibilityStatus; /**< Determines if message can be printed. + * If this value is set to VS_HIDDEN, no message is printed! */ + } ReturnValueList; + + + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + MessageHandling( ); + + /** Constructor which takes the desired output file. */ + MessageHandling( FILE* _outputFile /**< Output file. */ + ); + + /** Constructor which takes the desired visibility states. */ + MessageHandling( VisibilityStatus _errorVisibility, /**< Visibility status for error messages. */ + VisibilityStatus _warningVisibility,/**< Visibility status for warning messages. */ + VisibilityStatus _infoVisibility /**< Visibility status for info messages. */ + ); + + /** Constructor which takes the desired output file and desired visibility states. */ + MessageHandling( FILE* _outputFile, /**< Output file. */ + VisibilityStatus _errorVisibility, /**< Visibility status for error messages. */ + VisibilityStatus _warningVisibility,/**< Visibility status for warning messages. */ + VisibilityStatus _infoVisibility /**< Visibility status for info messages. */ + ); + + /** Copy constructor (deep copy). */ + MessageHandling( const MessageHandling& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + ~MessageHandling( ); + + /** Assignment operator (deep copy). */ + MessageHandling& operator=( const MessageHandling& rhs /**< Rhs object. */ + ); + + + /** Prints an error message(a simplified macro THROWERROR is also provided). \n + * Errors are definied as abnormal events which cause an immediate termination of the current (sub) function. + * Errors of a sub function should be commented by the calling function by means of a warning message + * (if this error does not cause an error of the calling function, either)! + * \return Error number returned by sub function call + */ + returnValue throwError( returnValue Enumber, /**< Error number returned by sub function call. */ + const char* additionaltext, /**< Additional error text (0, if none). */ + const char* functionname, /**< Name of function which caused the error. */ + const char* filename, /**< Name of file which caused the error. */ + const unsigned long linenumber, /**< Number of line which caused the error.incompatible binary file */ + VisibilityStatus localVisibilityStatus /**< Determines (locally) if error message can be printed to stdFile. + * If GLOBAL visibility status of the message is set to VS_HIDDEN, + * no message is printed, anyway! */ + ); + + /** Prints a warning message (a simplified macro THROWWARNING is also provided). + * Warnings are definied as abnormal events which does NOT cause an immediate termination of the current (sub) function. + * \return Warning number returned by sub function call + */ + returnValue throwWarning( returnValue Wnumber, /**< Warning number returned by sub function call. */ + const char* additionaltext, /**< Additional warning text (0, if none). */ + const char* functionname, /**< Name of function which caused the warning. */ + const char* filename, /**< Name of file which caused the warning. */ + const unsigned long linenumber, /**< Number of line which caused the warning. */ + VisibilityStatus localVisibilityStatus /**< Determines (locally) if warning message can be printed to stdFile. + * If GLOBAL visibility status of the message is set to VS_HIDDEN, + * no message is printed, anyway! */ + ); + + /** Prints a info message (a simplified macro THROWINFO is also provided). + * \return Info number returned by sub function call + */ + returnValue throwInfo( returnValue Inumber, /**< Info number returned by sub function call. */ + const char* additionaltext, /**< Additional warning text (0, if none). */ + const char* functionname, /**< Name of function which submitted the info. */ + const char* filename, /**< Name of file which submitted the info. */ + const unsigned long linenumber, /**< Number of line which submitted the info. */ + VisibilityStatus localVisibilityStatus /**< Determines (locally) if info message can be printed to stdFile. + * If GLOBAL visibility status of the message is set to VS_HIDDEN, + * no message is printed, anyway! */ + ); + + + /** Resets all preferences to default values. + * \return SUCCESSFUL_RETURN */ + returnValue reset( ); + + + /** Prints a complete list of all messages to output file. + * \return SUCCESSFUL_RETURN */ + returnValue listAllMessages( ); + + + /** Returns visibility status for error messages. + * \return Visibility status for error messages. */ + inline VisibilityStatus getErrorVisibilityStatus( ) const; + + /** Returns visibility status for warning messages. + * \return Visibility status for warning messages. */ + inline VisibilityStatus getWarningVisibilityStatus( ) const; + + /** Returns visibility status for info messages. + * \return Visibility status for info messages. */ + inline VisibilityStatus getInfoVisibilityStatus( ) const; + + /** Returns pointer to output file. + * \return Pointer to output file. */ + inline FILE* getOutputFile( ) const; + + /** Returns error count value. + * \return Error count value. */ + inline int getErrorCount( ) const; + + + /** Changes visibility status for error messages. */ + inline void setErrorVisibilityStatus( VisibilityStatus _errorVisibility /**< New visibility status for error messages. */ + ); + + /** Changes visibility status for warning messages. */ + inline void setWarningVisibilityStatus( VisibilityStatus _warningVisibility /**< New visibility status for warning messages. */ + ); + + /** Changes visibility status for info messages. */ + inline void setInfoVisibilityStatus( VisibilityStatus _infoVisibility /**< New visibility status for info messages. */ + ); + + /** Changes output file for messages. */ + inline void setOutputFile( FILE* _outputFile /**< New output file for messages. */ + ); + + /** Changes error count. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENT */ + inline returnValue setErrorCount( int _errorCount /**< New error count value. */ + ); + + /** Provides message text corresponding to given \a returnValue. + * \return String containing message text. */ + static const char* getErrorCodeMessage( const returnValue _returnValue + ); + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Prints a info message to stdFile (auxiliary function). + * \return Error/warning/info number returned by sub function call + */ + returnValue throwMessage( + returnValue RETnumber, /**< Error/warning/info number returned by sub function call. */ + const char* additionaltext, /**< Additional warning text (0, if none). */ + const char* functionname, /**< Name of function which caused the error/warning/info. */ + const char* filename, /**< Name of file which caused the error/warning/info. */ + const unsigned long linenumber, /**< Number of line which caused the error/warning/info. */ + VisibilityStatus localVisibilityStatus, /**< Determines (locally) if info message can be printed to stdFile. + * If GLOBAL visibility status of the message is set to VS_HIDDEN, + * no message is printed, anyway! */ + const char* RETstring /**< Leading string of error/warning/info message. */ + ); + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + VisibilityStatus errorVisibility; /**< Error messages visible? */ + VisibilityStatus warningVisibility; /**< Warning messages visible? */ + VisibilityStatus infoVisibility; /**< Info messages visible? */ + + FILE* outputFile; /**< Output file for messages. */ + + int errorCount; /**< Counts number of errors (for nicer output only). */ +}; + + +#ifndef __FUNCTION__ + /** Ensures that __FUNCTION__ macro is defined. */ + #define __FUNCTION__ 0 +#endif + +#ifndef __FILE__ + /** Ensures that __FILE__ macro is defined. */ + #define __FILE__ 0 +#endif + +#ifndef __LINE__ + /** Ensures that __LINE__ macro is defined. */ + #define __LINE__ 0 +#endif + + +/** Short version of throwError with default values, only returnValue is needed */ +#define THROWERROR(retval) ( getGlobalMessageHandler( )->throwError((retval),0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE) ) + +/** Short version of throwWarning with default values, only returnValue is needed */ +#define THROWWARNING(retval) ( getGlobalMessageHandler( )->throwWarning((retval),0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE) ) + +/** Short version of throwInfo with default values, only returnValue is needed */ +#define THROWINFO(retval) ( getGlobalMessageHandler( )->throwInfo((retval),0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE) ) + + +/** Returns a pointer to global message handler. + * \return Pointer to global message handler. + */ +MessageHandling* getGlobalMessageHandler( ); + + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_MESSAGEHANDLING_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/MessageHandling.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/MessageHandling.ipp new file mode 100644 index 00000000000..69b17651cb7 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/MessageHandling.ipp @@ -0,0 +1,144 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/MessageHandling.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Implementation of inlined member functions of the MessageHandling class. + */ + + +BEGIN_NAMESPACE_QPOASES + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + + +/* + * g e t E r r o r V i s i b i l i t y S t a t u s + */ +inline VisibilityStatus MessageHandling::getErrorVisibilityStatus( ) const +{ + return errorVisibility; +} + + +/* + * g e t W a r n i n g V i s i b i l i t y S t a t u s + */ +inline VisibilityStatus MessageHandling::getWarningVisibilityStatus( ) const +{ + return warningVisibility; +} + + +/* + * g e t I n f o V i s i b i l i t y S t a t u s + */ +inline VisibilityStatus MessageHandling::getInfoVisibilityStatus( ) const +{ + return infoVisibility; +} + + +/* + * g e t O u t p u t F i l e + */ +inline FILE* MessageHandling::getOutputFile( ) const +{ + return outputFile; +} + + +/* + * g e t E r r o r C o u n t + */ +inline int MessageHandling::getErrorCount( ) const +{ + return errorCount; +} + + +/* + * s e t E r r o r V i s i b i l i t y S t a t u s + */ +inline void MessageHandling::setErrorVisibilityStatus( VisibilityStatus _errorVisibility ) +{ + errorVisibility = _errorVisibility; +} + + +/* + * s e t W a r n i n g V i s i b i l i t y S t a t u s + */ +inline void MessageHandling::setWarningVisibilityStatus( VisibilityStatus _warningVisibility ) +{ + warningVisibility = _warningVisibility; +} + + +/* + * s e t I n f o V i s i b i l i t y S t a t u s + */ +inline void MessageHandling::setInfoVisibilityStatus( VisibilityStatus _infoVisibility ) +{ + infoVisibility = _infoVisibility; +} + + +/* + * s e t O u t p u t F i l e + */ +inline void MessageHandling::setOutputFile( FILE* _outputFile ) +{ + outputFile = _outputFile; +} + + +/* + * s e t E r r o r C o u n t + */ +inline returnValue MessageHandling::setErrorCount( int _errorCount ) +{ + if ( _errorCount >= -1 ) + { + errorCount = _errorCount; + return SUCCESSFUL_RETURN; + } + else + return RET_INVALID_ARGUMENTS; +} + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Options.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Options.hpp new file mode 100644 index 00000000000..83c520cadd0 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Options.hpp @@ -0,0 +1,170 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Options.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the Options class designed to manage user-specified + * options for solving a QProblem. + */ + + +#ifndef QPOASES_OPTIONS_HPP +#define QPOASES_OPTIONS_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Manages all user-specified options for solving QPs. + * + * This class manages all user-specified options used for solving + * quadratic programs. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + */ +class Options +{ + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + Options( ); + + /** Copy constructor (deep copy). */ + Options( const Options& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + ~Options( ); + + /** Assignment operator (deep copy). */ + Options& operator=( const Options& rhs /**< Rhs object. */ + ); + + + /** Sets all options to default values. + * \return SUCCESSFUL_RETURN */ + returnValue setToDefault( ); + + /** Sets all options to values resulting in maximum reliabilty. + * \return SUCCESSFUL_RETURN */ + returnValue setToReliable( ); + + /** Sets all options to values resulting in minimum solution time. + * \return SUCCESSFUL_RETURN */ + returnValue setToMPC( ); + + /** Same as setToMPC( ), for ensuring backwards compatibility. + * \return SUCCESSFUL_RETURN */ + returnValue setToFast( ); + + + /** Ensures that all options have consistent values by automatically + * adjusting inconsistent ones. + * Note: This routine cannot (and does not try to) ensure that values + * are set to reasonable values that make the QP solution work! + * \return SUCCESSFUL_RETURN \n + * RET_OPTIONS_ADJUSTED */ + returnValue ensureConsistency( ); + + + /** Prints values of all options. + * \return SUCCESSFUL_RETURN */ + returnValue print( ) const; + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + + /** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ + returnValue copy( const Options& rhs /**< Rhs object. */ + ); + + /* + * PUBLIC MEMBER VARIABLES + */ + public: + PrintLevel printLevel; /**< Print level. */ + + BooleanType enableRamping; /**< Specifies whether ramping shall be enabled or not. */ + BooleanType enableFarBounds; /**< Specifies whether far bounds shall be used or not. */ + BooleanType enableFlippingBounds; /**< Specifies whether flipping bounds shall be used or not. */ + BooleanType enableRegularisation; /**< Specifies whether Hessian matrix shall be regularised in case semi-definiteness is detected. */ + BooleanType enableFullLITests; /**< Specifies whether condition-hardened LI test shall be used or not. */ + BooleanType enableNZCTests; /**< Specifies whether nonzero curvature tests shall be used. */ + int enableDriftCorrection; /**< Specifies the frequency of drift corrections (0 = off). */ + int enableCholeskyRefactorisation; /**< Specifies the frequency of full refactorisation of proj. Hessian (otherwise updates). */ + BooleanType enableEqualities; /**< Specifies whether equalities shall be always treated as active constraints. */ + + real_t terminationTolerance; /**< Termination tolerance. */ + real_t boundTolerance; /**< Lower/upper (constraints') bound tolerance (an inequality constraint whose lower and upper bounds differ by less is regarded to be an equality constraint). */ + real_t boundRelaxation; /**< Offset for relaxing (constraints') bounds at beginning of an initial homotopy. It is also as initial value for far bounds. */ + real_t epsNum; /**< Numerator tolerance for ratio tests. */ + real_t epsDen; /**< Denominator tolerance for ratio tests. */ + real_t maxPrimalJump; /**< Maximum allowed jump in primal variables in nonzero curvature tests. */ + real_t maxDualJump; /**< Maximum allowed jump in dual variables in linear independence tests. */ + + real_t initialRamping; /**< Start value for Ramping Strategy. */ + real_t finalRamping; /**< Final value for Ramping Strategy. */ + real_t initialFarBounds; /**< Initial size of Far Bounds. */ + real_t growFarBounds; /**< Factor to grow Far Bounds. */ + SubjectToStatus initialStatusBounds; /**< Initial status of bounds at first iteration. */ + real_t epsFlipping; /**< Tolerance of squared Cholesky diagonal factor which triggers flipping bound. */ + int numRegularisationSteps; /**< Maximum number of successive regularisation steps. */ + real_t epsRegularisation; /**< Scaling factor of identity matrix used for Hessian regularisation. */ + int numRefinementSteps; /**< Maximum number of iterative refinement steps. */ + real_t epsIterRef; /**< Early termination tolerance for iterative refinement. */ + real_t epsLITests; /**< Tolerance for linear independence tests. */ + real_t epsNZCTests; /**< Tolerance for nonzero curvature tests. */ + + BooleanType enableDropInfeasibles; /**< ... */ + int dropBoundPriority; /**< ... */ + int dropEqConPriority; /**< ... */ + int dropIneqConPriority; /**< ... */ +}; + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_OPTIONS_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblem.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblem.hpp new file mode 100644 index 00000000000..6e2232fdcf5 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblem.hpp @@ -0,0 +1,1163 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/QProblem.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the QProblem class which is able to use the newly + * developed online active set strategy for parametric quadratic programming. + */ + + + +#ifndef QPOASES_QPROBLEM_HPP +#define QPOASES_QPROBLEM_HPP + + +#include +#include +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Implements the online active set strategy for QPs with general constraints. + * + * A class for setting up and solving quadratic programs. The main feature is + * the possibily to use the newly developed online active set strategy for + * parametric quadratic programming. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + */ +class QProblem : public QProblemB +{ + /* allow SolutionAnalysis class to access private members */ + friend class SolutionAnalysis; + + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + QProblem( ); + + /** Constructor which takes the QP dimension and Hessian type + * information. If the Hessian is the zero (i.e. HST_ZERO) or the + * identity matrix (i.e. HST_IDENTITY), respectively, no memory + * is allocated for it and a NULL pointer can be passed for it + * to the init() functions. */ + QProblem( int _nV, /**< Number of variables. */ + int _nC, /**< Number of constraints. */ + HessianType _hessianType = HST_UNKNOWN /**< Type of Hessian matrix. */ + ); + + /** Copy constructor (deep copy). */ + QProblem( const QProblem& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + virtual ~QProblem( ); + + /** Assignment operator (deep copy). */ + QProblem& operator=( const QProblem& rhs /**< Rhs object. */ + ); + + + /** Clears all data structures of QProblemB except for QP data. + * \return SUCCESSFUL_RETURN \n + RET_RESET_FAILED */ + virtual returnValue reset( ); + + + /** Initialises a QProblem with given QP data and solves it + * using an initial homotopy with empty working set (at most nWSR iterations). + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ + returnValue init( SymmetricMatrix *_H, /**< Hessian matrix (a shallow copy is made). */ + const real_t* const _g, /**< Gradient vector. */ + Matrix *_A, /**< Constraint matrix (a shallow copy is made). */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA, /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation (if pointer passed). */ + ); + + + /** Initialises a QProblem with given QP data and solves it + * using an initial homotopy with empty working set (at most nWSR iterations). + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ + returnValue init( const real_t* const _H, /**< Hessian matrix (a shallow copy is made). \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _A, /**< Constraint matrix (a shallow copy is made). */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA, /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation (if pointer passed). */ + ); + + /** Initialises a QProblem with given QP data to be read from files and solves it + * using an initial homotopy with empty working set (at most nWSR iterations). + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_UNABLE_TO_READ_FILE */ + returnValue init( const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient vector is stored. */ + const char* const A_file, /**< Name of file where constraint matrix is stored. */ + const char* const lb_file, /**< Name of file where lower bound vector. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bound vector. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bound vector. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation (if pointer passed). */ + ); + + /** Initialises a QProblem with given QP data and solves it + * depending on the parameter constellation: \n + * 1. 0, 0, 0 : start with xOpt = 0, yOpt = 0 and IB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : start with xOpt, yOpt = 0 and obtain IB by "clipping", \n + * 3. 0, yOpt, 0 : start with xOpt = 0, yOpt and obtain IB from yOpt != 0, \n + * 4. 0, 0, IB: start with xOpt = 0, yOpt = 0 and IB, \n + * 5. xOpt, yOpt, 0 : start with xOpt, yOpt and obtain IB from yOpt != 0, \n + * 6. xOpt, 0, IB: start with xOpt, yOpt = 0 and IB, \n + * 7. xOpt, yOpt, IB: start with xOpt, yOpt and IB (assume them to be consistent!) + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ + returnValue init( SymmetricMatrix *_H, /**< Hessian matrix (a shallow copy is made). */ + const real_t* const _g, /**< Gradient vector. */ + Matrix *_A, /**< Constraint matrix (a shallow copy is made). */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA, /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + * Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. \n + (If a null pointer is passed, the old dual solution is kept!) */ + const Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). */ + const Constraints* const guessedConstraints /**< Optimal working set of constraints for solution (xOpt,yOpt). */ + ); + + /** Initialises a QProblem with given QP data and solves it + * depending on the parameter constellation: \n + * 1. 0, 0, 0 : start with xOpt = 0, yOpt = 0 and IB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : start with xOpt, yOpt = 0 and obtain IB by "clipping", \n + * 3. 0, yOpt, 0 : start with xOpt = 0, yOpt and obtain IB from yOpt != 0, \n + * 4. 0, 0, IB: start with xOpt = 0, yOpt = 0 and IB, \n + * 5. xOpt, yOpt, 0 : start with xOpt, yOpt and obtain IB from yOpt != 0, \n + * 6. xOpt, 0, IB: start with xOpt, yOpt = 0 and IB, \n + * 7. xOpt, yOpt, IB: start with xOpt, yOpt and IB (assume them to be consistent!) + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ + returnValue init( const real_t* const _H, /**< Hessian matrix (a shallow copy is made). \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _A, /**< Constraint matrix (a shallow copy is made). */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA, /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + * Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. \n + (If a null pointer is passed, the old dual solution is kept!) */ + const Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). */ + const Constraints* const guessedConstraints /**< Optimal working set of constraints for solution (xOpt,yOpt). */ + ); + + /** Initialises a QProblem with given QP data to be read from files and solves it + * depending on the parameter constellation: \n + * Note: This function internally calls solveInitialQP for initialisation! + * 1. 0, 0, 0 : start with xOpt = 0, yOpt = 0 and IB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : start with xOpt, yOpt = 0 and obtain IB by "clipping", \n + * 3. 0, yOpt, 0 : start with xOpt = 0, yOpt and obtain IB from yOpt != 0, \n + * 4. 0, 0, IB: start with xOpt = 0, yOpt = 0 and IB, \n + * 5. xOpt, yOpt, 0 : start with xOpt, yOpt and obtain IB from yOpt != 0, \n + * 6. xOpt, 0, IB: start with xOpt, yOpt = 0 and IB, \n + * 7. xOpt, yOpt, IB: start with xOpt, yOpt and IB (assume them to be consistent!) + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_UNABLE_TO_READ_FILE */ + returnValue init( const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient vector is stored. */ + const char* const A_file, /**< Name of file where constraint matrix is stored. */ + const char* const lb_file, /**< Name of file where lower bound vector. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bound vector. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bound vector. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. \n + (If a null pointer is passed, the old dual solution is kept!) */ + const Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). */ + const Constraints* const guessedConstraints /**< Optimal working set of constraints for solution (xOpt,yOpt). */ + ); + + + /** Solves QProblem using online active set strategy. + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ + returnValue hotstart( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves QProblem using online active set strategy + * reading QP data from files. + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ + returnValue hotstart( const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised QProblem using online active set strategy (using an initialised homotopy). + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED */ + returnValue hotstart( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + const Bounds* const guessedBounds, /**< Initial guess for working set of bounds. + * A null pointer corresponds to an empty working set! */ + const Constraints* const guessedConstraints /**< Initial guess for working set of constraints. + * A null pointer corresponds to an empty working set! */ + ); + + /** Solves an initialised QProblem using online active set strategy (using an initialised homotopy) + * reading QP data from files. + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ + returnValue hotstart( const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + const Bounds* const guessedBounds, /**< Initial guess for working set of bounds. + * A null pointer corresponds to an empty working set! */ + const Constraints* const guessedConstraints /**< Initial guess for working set of constraints. + * A null pointer corresponds to an empty working set! */ + ); + + /** Solves using the current working set + * \return SUCCESSFUL_RETURN \n + * RET_STEPDIRECTION_FAILED_TQ \n + * RET_STEPDIRECTION_FAILED_CHOLESKY */ + returnValue solveCurrentEQP ( const int n_rhs, /**< Number of consecutive right hand sides */ + const real_t* g_in, /**< Gradient of neighbouring QP to be solved. */ + const real_t* lb_in, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* ub_in, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* lbA_in, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* ubA_in, /**< Upper constraints' bounds of neighbouring QP to be solved. \n */ + real_t* x_out, /**< Primal solution */ + real_t* y_out /**< Dual solution */ + ); + + /** Writes a vector with the state of the (constraints') bounds + * \return SUCCESSFUL_RETURN */ + returnValue getWorkingSet( real_t* workingSet /** Output: array containing state of the working set. */ + ); + + /** Returns current constraints object of the QP (deep copy). + * \return SUCCESSFUL_RETURN \n + RET_QPOBJECT_NOT_SETUP */ + inline returnValue getConstraints( Constraints& _constraints /** Output: Constraints object. */ + ) const; + + + /** Returns the number of constraints. + * \return Number of constraints. */ + inline int getNC( ) const; + + /** Returns the number of (implicitly defined) equality constraints. + * \return Number of (implicitly defined) equality constraints. */ + inline int getNEC( ) const; + + /** Returns the number of active constraints. + * \return Number of active constraints. */ + inline int getNAC( ) const; + + /** Returns the number of inactive constraints. + * \return Number of inactive constraints. */ + inline int getNIAC( ) const; + + /** Returns the dimension of null space. + * \return Dimension of null space. */ + virtual int getNZ( ) const; + + + /** Returns the dual solution vector (deep copy). + * \return SUCCESSFUL_RETURN \n + RET_QP_NOT_SOLVED */ + virtual returnValue getDualSolution( real_t* const yOpt /**< Output: Dual solution vector (if QP has been solved). */ + ) const; + + + /** Defines user-defined routine for calculating the constraint product A*x + * \return SUCCESSFUL_RETURN \n */ + returnValue setConstraintProduct( ConstraintProduct* const _constraintProduct + ); + + + /** Prints concise list of properties of the current QP. + * \return SUCCESSFUL_RETURN \n */ + virtual returnValue printProperties( ); + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Frees all allocated memory. + * \return SUCCESSFUL_RETURN */ + returnValue clear( ); + + /** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ + returnValue copy( const QProblem& rhs /**< Rhs object. */ + ); + + /** Solves a QProblem whose QP data is assumed to be stored in the member variables. + * A guess for its primal/dual optimal solution vectors and the corresponding + * working sets of bounds and constraints can be provided. + * Note: This function is internally called by all init functions! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED */ + returnValue solveInitialQP( const real_t* const xOpt, /**< Optimal primal solution vector. + * A NULL pointer can be passed. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + * A NULL pointer can be passed. */ + const Bounds* const guessedBounds, /**< Guessed working set of bounds for solution (xOpt,yOpt). + * A NULL pointer can be passed. */ + const Constraints* const guessedConstraints, /**< Optimal working set of constraints for solution (xOpt,yOpt). + * A NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + * Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves QProblem using online active set strategy. + * Note: This function is internally called by all hotstart functions! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ + returnValue solveQP( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + int nWSRperformed = 0 /**< Number of working set recalculations already performed to solve + this QP within previous solveQP() calls. This number is + always zero, except for successive calls from solveRegularisedQP() + or when using the far bound strategy. */ + ); + + + /** Solves QProblem using online active set strategy. + * Note: This function is internally called by all hotstart functions! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ + returnValue solveRegularisedQP( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + int nWSRperformed = 0 /**< Number of working set recalculations already performed to solve + this QP within previous solveRegularisedQP() calls. This number is + always zero, except for successive calls when using the far bound strategy. */ + ); + + + /** Determines type of existing constraints and bounds (i.e. implicitly fixed, unbounded etc.). + * \return SUCCESSFUL_RETURN \n + RET_SETUPSUBJECTTOTYPE_FAILED */ + virtual returnValue setupSubjectToType( ); + + /** Determines type of new constraints and bounds (i.e. implicitly fixed, unbounded etc.). + * \return SUCCESSFUL_RETURN \n + RET_SETUPSUBJECTTOTYPE_FAILED */ + virtual returnValue setupSubjectToType( const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new, /**< New upper bounds. */ + const real_t* const lbA_new, /**< New lower constraints' bounds. */ + const real_t* const ubA_new /**< New upper constraints' bounds. */ + ); + + /** Computes the Cholesky decomposition of the projected Hessian (i.e. R^T*R = Z^T*H*Z). + * Note: If Hessian turns out not to be positive definite, the Hessian type + * is set to HST_SEMIDEF accordingly. + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ + returnValue computeProjectedCholesky( ); + + /** Computes initial Cholesky decomposition of the projected Hessian making + * use of the function computeCholesky() or computeProjectedCholesky(). + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ + virtual returnValue setupInitialCholesky( ); + + /** Initialises TQ factorisation of A (i.e. A*Q = [0 T]) if NO constraint is active. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ + returnValue setupTQfactorisation( ); + + + /** Obtains the desired working set for the auxiliary initial QP in + * accordance with the user specifications + * (assumes that member AX has already been initialised!) + * \return SUCCESSFUL_RETURN \n + RET_OBTAINING_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS */ + returnValue obtainAuxiliaryWorkingSet( const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + const Bounds* const guessedBounds, /**< Guessed working set of bounds for solution (xOpt,yOpt). */ + const Constraints* const guessedConstraints, /**< Guessed working set for solution (xOpt,yOpt). */ + Bounds* auxiliaryBounds, /**< Input: Allocated bound object. \n + * Ouput: Working set of constraints for auxiliary QP. */ + Constraints* auxiliaryConstraints /**< Input: Allocated bound object. \n + * Ouput: Working set for auxiliary QP. */ + ) const; + + /** Sets up bound and constraints data structures according to auxiliaryBounds/Constraints. + * (If the working set shall be setup afresh, make sure that + * bounds and constraints data structure have been resetted + * and the TQ factorisation has been initialised!) + * \return SUCCESSFUL_RETURN \n + RET_SETUP_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS \n + RET_UNKNOWN_BUG */ + returnValue setupAuxiliaryWorkingSet( const Bounds* const auxiliaryBounds, /**< Working set of bounds for auxiliary QP. */ + const Constraints* const auxiliaryConstraints, /**< Working set of constraints for auxiliary QP. */ + BooleanType setupAfresh /**< Flag indicating if given working set shall be + * setup afresh or by updating the current one. */ + ); + + /** Sets up the optimal primal/dual solution of the auxiliary initial QP. + * \return SUCCESSFUL_RETURN */ + returnValue setupAuxiliaryQPsolution( const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are set to zero. */ + const real_t* const yOpt /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are set to zero. */ + ); + + /** Sets up gradient of the auxiliary initial QP for given + * optimal primal/dual solution and given initial working set + * (assumes that members X, Y and BOUNDS, CONSTRAINTS have already been initialised!). + * \return SUCCESSFUL_RETURN */ + returnValue setupAuxiliaryQPgradient( ); + + /** Sets up (constraints') bounds of the auxiliary initial QP for given + * optimal primal/dual solution and given initial working set + * (assumes that members X, Y and BOUNDS, CONSTRAINTS have already been initialised!). + * \return SUCCESSFUL_RETURN \n + RET_UNKNOWN_BUG */ + returnValue setupAuxiliaryQPbounds( const Bounds* const auxiliaryBounds, /**< Working set of bounds for auxiliary QP. */ + const Constraints* const auxiliaryConstraints, /**< Working set of constraints for auxiliary QP. */ + BooleanType useRelaxation /**< Flag indicating if inactive (constraints') bounds shall be relaxed. */ + ); + + + /** Adds a constraint to active set. + * \return SUCCESSFUL_RETURN \n + RET_ADDCONSTRAINT_FAILED \n + RET_ADDCONSTRAINT_FAILED_INFEASIBILITY \n + RET_ENSURELI_FAILED */ + returnValue addConstraint( int number, /**< Number of constraint to be added to active set. */ + SubjectToStatus C_status, /**< Status of new active constraint. */ + BooleanType updateCholesky, /**< Flag indicating if Cholesky decomposition shall be updated. */ + BooleanType ensureLI = BT_TRUE /**< Ensure linear independence by exchange rules by default. */ + ); + + /** Checks if new active constraint to be added is linearly dependent from + * from row of the active constraints matrix. + * \return RET_LINEARLY_DEPENDENT \n + RET_LINEARLY_INDEPENDENT \n + RET_INDEXLIST_CORRUPTED */ + returnValue addConstraint_checkLI( int number /**< Number of constraint to be added to active set. */ + ); + + /** Ensures linear independence of constraint matrix when a new constraint is added. + * To this end a bound or constraint is removed simultaneously if necessary. + * \return SUCCESSFUL_RETURN \n + RET_LI_RESOLVED \n + RET_ENSURELI_FAILED \n + RET_ENSURELI_FAILED_TQ \n + RET_ENSURELI_FAILED_NOINDEX \n + RET_REMOVE_FROM_ACTIVESET */ + returnValue addConstraint_ensureLI( int number, /**< Number of constraint to be added to active set. */ + SubjectToStatus C_status /**< Status of new active bound. */ + ); + + /** Adds a bound to active set. + * \return SUCCESSFUL_RETURN \n + RET_ADDBOUND_FAILED \n + RET_ADDBOUND_FAILED_INFEASIBILITY \n + RET_ENSURELI_FAILED */ + returnValue addBound( int number, /**< Number of bound to be added to active set. */ + SubjectToStatus B_status, /**< Status of new active bound. */ + BooleanType updateCholesky, /**< Flag indicating if Cholesky decomposition shall be updated. */ + BooleanType ensureLI = BT_TRUE /**< Ensure linear independence by exchange rules by default. */ + ); + + /** Checks if new active bound to be added is linearly dependent from + * from row of the active constraints matrix. + * \return RET_LINEARLY_DEPENDENT \n + RET_LINEARLY_INDEPENDENT */ + returnValue addBound_checkLI( int number /**< Number of bound to be added to active set. */ + ); + + /** Ensures linear independence of constraint matrix when a new bound is added. + * To this end a bound or constraint is removed simultaneously if necessary. + * \return SUCCESSFUL_RETURN \n + RET_LI_RESOLVED \n + RET_ENSURELI_FAILED \n + RET_ENSURELI_FAILED_TQ \n + RET_ENSURELI_FAILED_NOINDEX \n + RET_REMOVE_FROM_ACTIVESET */ + returnValue addBound_ensureLI( int number, /**< Number of bound to be added to active set. */ + SubjectToStatus B_status /**< Status of new active bound. */ + ); + + /** Removes a constraint from active set. + * \return SUCCESSFUL_RETURN \n + RET_CONSTRAINT_NOT_ACTIVE \n + RET_REMOVECONSTRAINT_FAILED \n + RET_HESSIAN_NOT_SPD */ + returnValue removeConstraint( int number, /**< Number of constraint to be removed from active set. */ + BooleanType updateCholesky, /**< Flag indicating if Cholesky decomposition shall be updated. */ + BooleanType allowFlipping = BT_FALSE, /**< Flag indicating if flipping bounds are allowed. */ + BooleanType ensureNZC = BT_FALSE /**< Flag indicating if non-zero curvature is ensured by exchange rules. */ + ); + + /** Removes a bounds from active set. + * \return SUCCESSFUL_RETURN \n + RET_BOUND_NOT_ACTIVE \n + RET_HESSIAN_NOT_SPD \n + RET_REMOVEBOUND_FAILED */ + returnValue removeBound( int number, /**< Number of bound to be removed from active set. */ + BooleanType updateCholesky, /**< Flag indicating if Cholesky decomposition shall be updated. */ + BooleanType allowFlipping = BT_FALSE, /**< Flag indicating if flipping bounds are allowed. */ + BooleanType ensureNZC = BT_FALSE /**< Flag indicating if non-zero curvature is ensured by exchange rules. */ + ); + + + /** Performs robustified ratio test yield the maximum possible step length + * along the homotopy path. + * \return SUCCESSFUL_RETURN */ + returnValue performPlainRatioTest( int nIdx, /**< Number of ratios to be checked. */ + const int* const idxList, /**< Array containing the indices of all ratios to be checked. */ + const real_t* const num, /**< Array containing all numerators for performing the ratio test. */ + const real_t* const den, /**< Array containing all denominators for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t& t, /**< Output: Maximum possible step length along the homotopy path. */ + int& BC_idx /**< Output: Index of blocking constraint. */ + ) const; + + + /** Ensure non-zero curvature by primal jump. + * \return SUCCESSFUL_RETURN \n + * RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ + returnValue ensureNonzeroCurvature( + BooleanType removeBoundNotConstraint, /**< SubjectTo to be removed is a bound. */ + int remIdx, /**< Index of bound/constraint to be removed. */ + BooleanType &exchangeHappened, /**< Output: Exchange was necessary to ensure. */ + BooleanType &addBoundNotConstraint, /**< SubjectTo to be added is a bound. */ + int &addIdx, /**< Index of bound/constraint to be added. */ + SubjectToStatus &addStatus /**< Status of bound/constraint to be added. */ + ); + + + /** Solves the system Ta = b or T^Ta = b where T is a reverse upper triangular matrix. + * \return SUCCESSFUL_RETURN \n + RET_DIV_BY_ZERO */ + returnValue backsolveT( const real_t* const b, /**< Right hand side vector. */ + BooleanType transposed, /**< Indicates if the transposed system shall be solved. */ + real_t* const a /**< Output: Solution vector */ + ) const; + + + /** Determines step direction of the shift of the QP data. + * \return SUCCESSFUL_RETURN */ + returnValue determineDataShift( const real_t* const g_new, /**< New gradient vector. */ + const real_t* const lbA_new,/**< New lower constraints' bounds. */ + const real_t* const ubA_new,/**< New upper constraints' bounds. */ + const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new, /**< New upper bounds. */ + real_t* const delta_g, /**< Output: Step direction of gradient vector. */ + real_t* const delta_lbA, /**< Output: Step direction of lower constraints' bounds. */ + real_t* const delta_ubA, /**< Output: Step direction of upper constraints' bounds. */ + real_t* const delta_lb, /**< Output: Step direction of lower bounds. */ + real_t* const delta_ub, /**< Output: Step direction of upper bounds. */ + BooleanType& Delta_bC_isZero,/**< Output: Indicates if active constraints' bounds are to be shifted. */ + BooleanType& Delta_bB_isZero/**< Output: Indicates if active bounds are to be shifted. */ + ); + + /** Determines step direction of the homotopy path. + * \return SUCCESSFUL_RETURN \n + RET_STEPDIRECTION_FAILED_TQ \n + RET_STEPDIRECTION_FAILED_CHOLESKY */ + returnValue determineStepDirection( const real_t* const delta_g, /**< Step direction of gradient vector. */ + const real_t* const delta_lbA, /**< Step direction of lower constraints' bounds. */ + const real_t* const delta_ubA, /**< Step direction of upper constraints' bounds. */ + const real_t* const delta_lb, /**< Step direction of lower bounds. */ + const real_t* const delta_ub, /**< Step direction of upper bounds. */ + BooleanType Delta_bC_isZero, /**< Indicates if active constraints' bounds are to be shifted. */ + BooleanType Delta_bB_isZero, /**< Indicates if active bounds are to be shifted. */ + real_t* const delta_xFX, /**< Output: Primal homotopy step direction of fixed variables. */ + real_t* const delta_xFR, /**< Output: Primal homotopy step direction of free variables. */ + real_t* const delta_yAC, /**< Output: Dual homotopy step direction of active constraints' multiplier. */ + real_t* const delta_yFX /**< Output: Dual homotopy step direction of fixed variables' multiplier. */ + ); + + /** Determines the maximum possible step length along the homotopy path + * and performs this step (without changing working set). + * \return SUCCESSFUL_RETURN \n + * RET_ERROR_IN_CONSTRAINTPRODUCT \n + * RET_QP_INFEASIBLE */ + returnValue performStep( const real_t* const delta_g, /**< Step direction of gradient. */ + const real_t* const delta_lbA, /**< Step direction of lower constraints' bounds. */ + const real_t* const delta_ubA, /**< Step direction of upper constraints' bounds. */ + const real_t* const delta_lb, /**< Step direction of lower bounds. */ + const real_t* const delta_ub, /**< Step direction of upper bounds. */ + const real_t* const delta_xFX, /**< Primal homotopy step direction of fixed variables. */ + const real_t* const delta_xFR, /**< Primal homotopy step direction of free variables. */ + const real_t* const delta_yAC, /**< Dual homotopy step direction of active constraints' multiplier. */ + const real_t* const delta_yFX, /**< Dual homotopy step direction of fixed variables' multiplier. */ + int& BC_idx, /**< Output: Index of blocking constraint. */ + SubjectToStatus& BC_status, /**< Output: Status of blocking constraint. */ + BooleanType& BC_isBound /**< Output: Indicates if blocking constraint is a bound. */ + ); + + /** Updates the active set. + * \return SUCCESSFUL_RETURN \n + RET_REMOVE_FROM_ACTIVESET_FAILED \n + RET_ADD_TO_ACTIVESET_FAILED */ + returnValue changeActiveSet( int BC_idx, /**< Index of blocking constraint. */ + SubjectToStatus BC_status, /**< Status of blocking constraint. */ + BooleanType BC_isBound /**< Indicates if blocking constraint is a bound. */ + ); + + + /** Compute relative length of homotopy in data space for termination + * criterion. + * \return Relative length in data space. */ + real_t getRelativeHomotopyLength( const real_t* const g_new, /**< Final gradient. */ + const real_t* const lb_new, /**< Final lower variable bounds. */ + const real_t* const ub_new, /**< Final upper variable bounds. */ + const real_t* const lbA_new, /**< Final lower constraint bounds. */ + const real_t* const ubA_new /**< Final upper constraint bounds. */ + ); + + + /** Ramping Strategy to avoid ties. Modifies homotopy start without + * changing current active set. + * \return SUCCESSFUL_RETURN */ + virtual returnValue performRamping( ); + + + /** ... */ + returnValue updateFarBounds( real_t curFarBound, /**< ... */ + int nRamp, /**< ... */ + const real_t* const lb_new, /**< ... */ + real_t* const lb_new_far, /**< ... */ + const real_t* const ub_new, /**< ... */ + real_t* const ub_new_far, /**< ... */ + const real_t* const lbA_new, /**< ... */ + real_t* const lbA_new_far, /**< ... */ + const real_t* const ubA_new, /**< ... */ + real_t* const ubA_new_far /**< ... */ + ) const; + + + /** Drift correction at end of each active set iteration + * \return SUCCESSFUL_RETURN */ + virtual returnValue performDriftCorrection( ); + + + /** Updates QP vectors, working sets and internal data structures in order to + start from an optimal solution corresponding to initial guesses of the working + set for bounds and constraints. + * \return SUCCESSFUL_RETURN \n + * RET_SETUP_AUXILIARYQP_FAILED \n + RET_INVALID_ARGUMENTS */ + virtual returnValue setupAuxiliaryQP( const Bounds* const guessedBounds, /**< Initial guess for working set of bounds. */ + const Constraints* const guessedConstraints /**< Initial guess for working set of constraints. */ + ); + + /** Determines if it is more efficient to refactorise the matrices when + * hotstarting or not (i.e. better to update the existing factorisations). + * \return BT_TRUE iff matrices shall be refactorised afresh + */ + BooleanType shallRefactorise( const Bounds* const guessedBounds, /**< Guessed new working set of bounds. */ + const Constraints* const guessedConstraints /**< Guessed new working set of constraints. */ + ) const; + + /** Sets up internal QP data. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_UNKNONW_BUG */ + returnValue setupQPdata( SymmetricMatrix *_H, /**< Hessian matrix. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + Matrix *_A, /**< Constraint matrix. */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + ); + + + /** Sets up dense internal QP data. If the current Hessian is trivial + * (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_UNKNONW_BUG */ + returnValue setupQPdata( const real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _A, /**< Constraint matrix. */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + ); + + /** Sets up internal QP data by loading it from files. If the current Hessian + * is trivial (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS \n + RET_UNKNONW_BUG */ + returnValue setupQPdataFromFile( const char* const H_file, /**< Name of file where Hessian matrix, of neighbouring QP to be solved, is stored. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const A_file, /**< Name of file where constraint matrix, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + ); + + /** Loads new QP vectors from files (internal members are not affected!). + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ + returnValue loadQPvectorsFromFile( const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + real_t* const g_new, /**< Output: Gradient of neighbouring QP to be solved. */ + real_t* const lb_new, /**< Output: Lower bounds of neighbouring QP to be solved */ + real_t* const ub_new, /**< Output: Upper bounds of neighbouring QP to be solved */ + real_t* const lbA_new, /**< Output: Lower constraints' bounds of neighbouring QP to be solved */ + real_t* const ubA_new /**< Output: Upper constraints' bounds of neighbouring QP to be solved */ + ) const; + + + /** Prints concise information on the current iteration. + * \return SUCCESSFUL_RETURN \n */ + returnValue printIteration( int iter, /**< Number of current iteration. */ + int BC_idx, /**< Index of blocking constraint. */ + SubjectToStatus BC_status, /**< Status of blocking constraint. */ + BooleanType BC_isBound, /**< Indicates if blocking constraint is a bound. */ + real_t homotopyLength /**< Current homotopy distance. */ + ); + + + /** Sets constraint matrix of the QP. \n + Note: Also internal vector Ax is recomputed! + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ + inline returnValue setA( Matrix *A_new /**< New constraint matrix (a shallow copy is made). */ + ); + + /** Sets dense constraint matrix of the QP. \n + Note: Also internal vector Ax is recomputed! + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ + inline returnValue setA( const real_t* const A_new /**< New dense constraint matrix (with correct dimension!), a shallow copy is made. */ + ); + + + /** Sets constraints' lower bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP */ + inline returnValue setLBA( const real_t* const lbA_new /**< New constraints' lower bound vector (with correct dimension!). */ + ); + + /** Changes single entry of lower constraints' bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP \n + * RET_INDEX_OUT_OF_BOUNDS */ + inline returnValue setLBA( int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of lower constraints' bound vector (with correct dimension!). */ + ); + + /** Sets constraints' upper bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP */ + inline returnValue setUBA( const real_t* const ubA_new /**< New constraints' upper bound vector (with correct dimension!). */ + ); + + /** Changes single entry of upper constraints' bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP \n + * RET_INDEX_OUT_OF_BOUNDS */ + inline returnValue setUBA( int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of upper constraints' bound vector (with correct dimension!). */ + ); + + + /** Drops the blocking bound/constraint that led to infeasibility, or finds another + * bound/constraint to drop according to drop priorities. + * \return SUCCESSFUL_RETURN \n + */ + returnValue dropInfeasibles ( int BC_number, /**< Number of the bound or constraint to be added. */ + SubjectToStatus BC_status, /**< New status of the bound or constraint to be added. */ + BooleanType BC_isBound, /**< Whether a bound or a constraint is to be added. */ + real_t *xiB, /**< (not yet documented) */ + real_t *xiC /**< (not yet documented) */ + ); + + /** Decides if lower bounds are smaller than upper bounds + * + * \return SUCCESSFUL_RETURN \n + * RET_QP_INFEASIBLE */ + + returnValue areBoundsConsistent(const real_t* const lb, /**< Vector of lower bounds*/ + const real_t* const ub, /**< Vector of upper bounds*/ + const real_t* const lbA, /**< Vector of lower constraints*/ + const real_t* const ubA /**< Vector of upper constraints*/ + ) const; + + + public: + /** ... + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ + returnValue writeQpDataIntoMatFile( const char* const filename /**< Mat file name. */ + ) const; + + /** ... + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ + returnValue writeQpWorkspaceIntoMatFile( const char* const filename /**< Mat file name. */ + ); + + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + BooleanType freeConstraintMatrix; /**< Flag indicating whether the constraint matrix needs to be de-allocated. */ + Matrix* A; /**< Constraint matrix. */ + + real_t* lbA; /**< Lower constraints' bound vector. */ + real_t* ubA; /**< Upper constraints' bound vector. */ + + Constraints constraints; /**< Data structure for problem's constraints. */ + + real_t* T; /**< Reverse triangular matrix, A = [0 T]*Q'. */ + real_t* Q; /**< Orthonormal quadratic matrix, A = [0 T]*Q'. */ + int sizeT; /**< Matrix T is stored in a (sizeT x sizeT) array. */ + + real_t* Ax; /**< Stores the current A*x \n + * (for increased efficiency only). */ + real_t* Ax_l; /**< Stores the current distance to lower constraints' bounds A*x-lbA \n + * (for increased efficiency only). */ + real_t* Ax_u; /**< Stores the current distance to lower constraints' bounds ubA-A*x \n + * (for increased efficiency only). */ + + ConstraintProduct* constraintProduct; /**< Pointer to user-defined constraint product function. */ + + real_t* tempA; /**< Temporary for determineStepDirection. */ + real_t* tempB; /**< Temporary for determineStepDirection. */ + real_t* ZFR_delta_xFRz; /**< Temporary for determineStepDirection. */ + real_t* delta_xFRy; /**< Temporary for determineStepDirection. */ + real_t* delta_xFRz; /**< Temporary for determineStepDirection. */ + real_t* delta_yAC_TMP; /**< Temporary for determineStepDirection. */ +}; + + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_QPROBLEM_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblem.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblem.ipp new file mode 100644 index 00000000000..84662a069d3 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblem.ipp @@ -0,0 +1,283 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/QProblem.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Implementation of inlined member functions of the QProblem class which + * is able to use the newly developed online active set strategy for + * parametric quadratic programming. + */ + + +BEGIN_NAMESPACE_QPOASES + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + + +/* + * g e t C o n s t r a i n t s + */ +inline returnValue QProblem::getConstraints( Constraints& _constraints ) const +{ + int nV = getNV( ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + _constraints = constraints; + + return SUCCESSFUL_RETURN; +} + + + +/* + * g e t N C + */ +inline int QProblem::getNC( ) const +{ + return constraints.getNC( ); +} + + +/* + * g e t N E C + */ +inline int QProblem::getNEC( ) const +{ + return constraints.getNEC( ); +} + + +/* + * g e t N A C + */ +inline int QProblem::getNAC( ) const +{ + return constraints.getNAC( ); +} + + +/* + * g e t N I A C + */ +inline int QProblem::getNIAC( ) const +{ + return constraints.getNIAC( ); +} + + + +/***************************************************************************** + * P R O T E C T E D * + *****************************************************************************/ + + +/* + * s e t A + */ +inline returnValue QProblem::setA( Matrix *A_new ) +{ + int j; + int nV = getNV( ); + int nC = getNC( ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( A_new == 0 ) + return THROWERROR( RET_INVALID_ARGUMENTS ); + + /* Set constraint matrix AND update member AX. */ + if ( ( freeConstraintMatrix == BT_TRUE ) && ( A != 0 ) ) + { + delete A; + A = 0; + } + A = A_new; + freeConstraintMatrix = BT_FALSE; + + A->times(1, 1.0, x, nV, 0.0, Ax, nC); + + for( j=0; jgetRowNorm (j) ) == BT_TRUE ) + constraints.setType ( j, ST_DISABLED ); + } + + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t A + */ +inline returnValue QProblem::setA( const real_t* const A_new ) +{ + int j; + int nV = getNV( ); + int nC = getNC( ); + DenseMatrix* dA; + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( A_new == 0 ) + return THROWERROR( RET_INVALID_ARGUMENTS ); + + /* Set constraint matrix AND update member AX. */ + if ( ( freeConstraintMatrix == BT_TRUE ) && ( A != 0 ) ) + { + delete A; + A = 0; + } + A = dA = new DenseMatrix(nC, nV, nV, (real_t*) A_new); + freeConstraintMatrix = BT_TRUE; + + A->times(1, 1.0, x, nV, 0.0, Ax, nC); + + for( j=0; j= 0 ) && ( number < nC ) ) + { + lbA[number] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +/* + * s e t U B A + */ +inline returnValue QProblem::setUBA( const real_t* const ubA_new ) +{ + unsigned int i; + unsigned int nV = (unsigned int)getNV( ); + unsigned int nC = (unsigned int)getNC( ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ubA_new != 0 ) + { + memcpy( ubA,ubA_new,nC*sizeof(real_t) ); + } + else + { + /* if no upper constraints' bounds are specified, set them to infinity */ + for( i=0; i= 0 ) && ( number < nC ) ) + { + ubA[number] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblemB.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblemB.hpp new file mode 100644 index 00000000000..d62244e130e --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblemB.hpp @@ -0,0 +1,1091 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/QProblemB.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the QProblemB class which is able to use the newly + * developed online active set strategy for parametric quadratic programming + * for problems with (simple) bounds only. + */ + + + +#ifndef QPOASES_QPROBLEMB_HPP +#define QPOASES_QPROBLEMB_HPP + + +#include +#include +#include + + +BEGIN_NAMESPACE_QPOASES + + +class SolutionAnalysis; + +/** + * \brief Implements the online active set strategy for box-constrained QPs. + * + * Class for setting up and solving quadratic programs with bounds (= box constraints) only. + * The main feature is the possibily to use the newly developed online active set strategy + * for parametric quadratic programming. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + */ +class QProblemB +{ + /* allow SolutionAnalysis class to access private members */ + friend class SolutionAnalysis; + + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + QProblemB( ); + + /** Constructor which takes the QP dimension and Hessian type + * information. If the Hessian is the zero (i.e. HST_ZERO) or the + * identity matrix (i.e. HST_IDENTITY), respectively, no memory + * is allocated for it and a NULL pointer can be passed for it + * to the init() functions. */ + QProblemB( int _nV, /**< Number of variables. */ + HessianType _hessianType = HST_UNKNOWN /**< Type of Hessian matrix. */ + ); + + /** Copy constructor (deep copy). */ + QProblemB( const QProblemB& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + virtual ~QProblemB( ); + + /** Assignment operator (deep copy). */ + QProblemB& operator=( const QProblemB& rhs /**< Rhs object. */ + ); + + + /** Clears all data structures of QProblemB except for QP data. + * \return SUCCESSFUL_RETURN \n + RET_RESET_FAILED */ + virtual returnValue reset( ); + + + /** Initialises a QProblemB with given QP data and solves it + * using an initial homotopy with empty working set (at most nWSR iterations). + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ + returnValue init( SymmetricMatrix *_H, /**< Hessian matrix (a shallow copy is made). */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation (if pointer passed). */ + ); + + /** Initialises a QProblemB with given QP data and solves it + * using an initial homotopy with empty working set (at most nWSR iterations). + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ + returnValue init( const real_t* const _H, /**< Hessian matrix (a shallow copy is made). \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation (if pointer passed). */ + ); + + /** Initialises a QProblemB with given QP data to be read from files and solves it + * using an initial homotopy with empty working set (at most nWSR iterations). + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_UNABLE_TO_READ_FILE */ + returnValue init( const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient vector is stored. */ + const char* const lb_file, /**< Name of file where lower bound vector. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bound vector. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation (if pointer passed). */ + ); + + /** Initialises a QProblemB with given QP data and solves it + * depending on the parameter constellation: \n + * 1. 0, 0, 0 : start with xOpt = 0, yOpt = 0 and IB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : start with xOpt, yOpt = 0 and obtain IB by "clipping", \n + * 3. 0, yOpt, 0 : start with xOpt = 0, yOpt and obtain IB from yOpt != 0, \n + * 4. 0, 0, IB: start with xOpt = 0, yOpt = 0 and IB, \n + * 5. xOpt, yOpt, 0 : start with xOpt, yOpt and obtain IB from yOpt != 0, \n + * 6. xOpt, 0, IB: start with xOpt, yOpt = 0 and IB, \n + * 7. xOpt, yOpt, IB: start with xOpt, yOpt and IB (assume them to be consistent!) + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ + returnValue init( SymmetricMatrix *_H, /**< Hessian matrix (a shallow copy is made). */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. + A NULL pointer can be passed. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + A NULL pointer can be passed. */ + const Bounds* const guessedBounds /**< Optimal working set for solution (xOpt,yOpt). + A NULL pointer can be passed. */ + ); + + /** Initialises a QProblemB with given QP data and solves it + * depending on the parameter constellation: \n + * 1. 0, 0, 0 : start with xOpt = 0, yOpt = 0 and IB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : start with xOpt, yOpt = 0 and obtain IB by "clipping", \n + * 3. 0, yOpt, 0 : start with xOpt = 0, yOpt and obtain IB from yOpt != 0, \n + * 4. 0, 0, IB: start with xOpt = 0, yOpt = 0 and IB, \n + * 5. xOpt, yOpt, 0 : start with xOpt, yOpt and obtain IB from yOpt != 0, \n + * 6. xOpt, 0, IB: start with xOpt, yOpt = 0 and IB, \n + * 7. xOpt, yOpt, IB: start with xOpt, yOpt and IB (assume them to be consistent!) + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ + returnValue init( const real_t* const _H, /**< Hessian matrix (a shallow copy is made). \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. + A NULL pointer can be passed. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + A NULL pointer can be passed. */ + const Bounds* const guessedBounds /**< Optimal working set for solution (xOpt,yOpt). + A NULL pointer can be passed. */ + ); + + /** Initialises a QProblemB with given QP data to be read from files and solves it + * depending on the parameter constellation: \n + * 1. 0, 0, 0 : start with xOpt = 0, yOpt = 0 and IB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : start with xOpt, yOpt = 0 and obtain IB by "clipping", \n + * 3. 0, yOpt, 0 : start with xOpt = 0, yOpt and obtain IB from yOpt != 0, \n + * 4. 0, 0, IB: start with xOpt = 0, yOpt = 0 and IB, \n + * 5. xOpt, yOpt, 0 : start with xOpt, yOpt and obtain IB from yOpt != 0, \n + * 6. xOpt, 0, IB: start with xOpt, yOpt = 0 and IB, \n + * 7. xOpt, yOpt, IB: start with xOpt, yOpt and IB (assume them to be consistent!) + * Note: This function internally calls solveInitialQP for initialisation! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_UNABLE_TO_READ_FILE */ + returnValue init( const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient vector is stored. */ + const char* const lb_file, /**< Name of file where lower bound vector. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bound vector. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spend for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. + A NULL pointer can be passed. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + A NULL pointer can be passed. */ + const Bounds* const guessedBounds /**< Optimal working set for solution (xOpt,yOpt). + A NULL pointer can be passed. */ + ); + + + /** Solves an initialised QProblemB using online active set strategy. + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ + returnValue hotstart( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised QProblemB online active set strategy + * reading QP data from files. + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ + returnValue hotstart( const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised QProblemB using online active set strategy (using an initialised homotopy). + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED */ + returnValue hotstart( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + const Bounds* const guessedBounds /**< Initial guess for working set of bounds. + * A null pointer corresponds to an empty working set! */ + ); + + /** Solves an initialised QProblemB using online active set strategy (using an initialised homotopy) + * reading QP data from files. + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS \n + RET_SETUP_AUXILIARYQP_FAILED */ + returnValue hotstart( const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + const Bounds* const guessedBounds /**< Initial guess for working set of bounds. + * A null pointer corresponds to an empty working set! */ + ); + + + /** Writes a vector with the state of the bounds + * \return SUCCESSFUL_RETURN */ + virtual returnValue getWorkingSet( real_t* workingSet /** Output: array containing state of the working set. */ + ); + + /** Returns current bounds object of the QP (deep copy). + * \return SUCCESSFUL_RETURN \n + RET_QPOBJECT_NOT_SETUP */ + inline returnValue getBounds( Bounds& _bounds /** Output: Bounds object. */ + ) const; + + + /** Returns the number of variables. + * \return Number of variables. */ + inline int getNV( ) const; + + /** Returns the number of free variables. + * \return Number of free variables. */ + inline int getNFR( ) const; + + /** Returns the number of fixed variables. + * \return Number of fixed variables. */ + inline int getNFX( ) const; + + /** Returns the number of implicitly fixed variables. + * \return Number of implicitly fixed variables. */ + inline int getNFV( ) const; + + /** Returns the dimension of null space. + * \return Dimension of null space. */ + virtual int getNZ( ) const; + + + /** Returns the optimal objective function value. + * \return finite value: Optimal objective function value (QP was solved) \n + +infinity: QP was not yet solved */ + real_t getObjVal( ) const; + + /** Returns the objective function value at an arbitrary point x. + * \return Objective function value at point x */ + real_t getObjVal( const real_t* const _x /**< Point at which the objective function shall be evaluated. */ + ) const; + + /** Returns the primal solution vector. + * \return SUCCESSFUL_RETURN \n + RET_QP_NOT_SOLVED */ + returnValue getPrimalSolution( real_t* const xOpt /**< Output: Primal solution vector (if QP has been solved). */ + ) const; + + /** Returns the dual solution vector. + * \return SUCCESSFUL_RETURN \n + RET_QP_NOT_SOLVED */ + virtual returnValue getDualSolution( real_t* const yOpt /**< Output: Dual solution vector (if QP has been solved). */ + ) const; + + + /** Returns status of the solution process. + * \return Status of solution process. */ + inline QProblemStatus getStatus( ) const; + + + /** Returns if the QProblem object is initialised. + * \return BT_TRUE: QProblemB initialised \n + BT_FALSE: QProblemB not initialised */ + inline BooleanType isInitialised( ) const; + + /** Returns if the QP has been solved. + * \return BT_TRUE: QProblemB solved \n + BT_FALSE: QProblemB not solved */ + inline BooleanType isSolved( ) const; + + /** Returns if the QP is infeasible. + * \return BT_TRUE: QP infeasible \n + BT_FALSE: QP feasible (or not known to be infeasible!) */ + inline BooleanType isInfeasible( ) const; + + /** Returns if the QP is unbounded. + * \return BT_TRUE: QP unbounded \n + BT_FALSE: QP unbounded (or not known to be unbounded!) */ + inline BooleanType isUnbounded( ) const; + + + /** Returns Hessian type flag (type is not determined due to this call!). + * \return Hessian type. */ + inline HessianType getHessianType( ) const; + + /** Changes the print level. + * \return SUCCESSFUL_RETURN */ + inline returnValue setHessianType( HessianType _hessianType /**< New Hessian type. */ + ); + + /** Returns if the QP has been internally regularised. + * \return BT_TRUE: Hessian is internally regularised for QP solution \n + BT_FALSE: No internal Hessian regularisation is used for QP solution */ + inline BooleanType usingRegularisation( ) const; + + /** Returns current options struct. + * \return Current options struct. */ + inline Options getOptions( ) const; + + /** Overrides current options with given ones. + * \return SUCCESSFUL_RETURN */ + inline returnValue setOptions( const Options& _options /**< New options. */ + ); + + /** Returns the print level. + * \return Print level. */ + inline PrintLevel getPrintLevel( ) const; + + /** Changes the print level. + * \return SUCCESSFUL_RETURN */ + returnValue setPrintLevel( PrintLevel _printlevel /**< New print level. */ + ); + + + /** Prints concise list of properties of the current QP. + * \return SUCCESSFUL_RETURN \n */ + virtual returnValue printProperties( ); + + /** Prints a list of all options and their current values. + * \return SUCCESSFUL_RETURN \n */ + returnValue printOptions( ) const; + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Frees all allocated memory. + * \return SUCCESSFUL_RETURN */ + returnValue clear( ); + + /** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ + returnValue copy( const QProblemB& rhs /**< Rhs object. */ + ); + + /** If Hessian type has been set by the user, nothing is done. + * Otherwise the Hessian type is set to HST_IDENTITY, HST_ZERO, or + * HST_POSDEF (default), respectively. + * \return SUCCESSFUL_RETURN \n + RET_HESSIAN_INDEFINITE */ + returnValue determineHessianType( ); + + /** Determines type of existing constraints and bounds (i.e. implicitly fixed, unbounded etc.). + * \return SUCCESSFUL_RETURN \n + RET_SETUPSUBJECTTOTYPE_FAILED */ + virtual returnValue setupSubjectToType( ); + + /** Determines type of new constraints and bounds (i.e. implicitly fixed, unbounded etc.). + * \return SUCCESSFUL_RETURN \n + RET_SETUPSUBJECTTOTYPE_FAILED */ + virtual returnValue setupSubjectToType( const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new /**< New upper bounds. */ + ); + + /** Computes the Cholesky decomposition of the (simply projected) Hessian + * (i.e. R^T*R = Z^T*H*Z). It only works in the case where Z is a simple + * projection matrix! + * Note: If Hessian turns out not to be positive definite, the Hessian type + * is set to HST_SEMIDEF accordingly. + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ + returnValue computeCholesky( ); + + + /** Computes initial Cholesky decomposition of the (simply projected) Hessian + * making use of the function computeCholesky(). + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ + virtual returnValue setupInitialCholesky( ); + + /** Obtains the desired working set for the auxiliary initial QP in + * accordance with the user specifications + * \return SUCCESSFUL_RETURN \n + RET_OBTAINING_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS */ + returnValue obtainAuxiliaryWorkingSet( const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + const Bounds* const guessedBounds, /**< Guessed working set for solution (xOpt,yOpt). */ + Bounds* auxiliaryBounds /**< Input: Allocated bound object. \n + * Output: Working set for auxiliary QP. */ + ) const; + + /** Decides if lower bounds are smaller than upper bounds + * + * \return SUCCESSFUL_RETURN \n + * RET_QP_INFEASIBLE */ + + returnValue areBoundsConsistent(const real_t* const lb, /**< Vector of lower bounds*/ + const real_t* const ub /**< Vector of upper bounds*/ + ) const; + + /** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix. + * \return SUCCESSFUL_RETURN \n + RET_DIV_BY_ZERO */ + returnValue backsolveR( const real_t* const b, /**< Right hand side vector. */ + BooleanType transposed, /**< Indicates if the transposed system shall be solved. */ + real_t* const a /**< Output: Solution vector */ + ) const; + + /** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix. \n + * Special variant for the case that this function is called from within "removeBound()". + * \return SUCCESSFUL_RETURN \n + RET_DIV_BY_ZERO */ + returnValue backsolveR( const real_t* const b, /**< Right hand side vector. */ + BooleanType transposed, /**< Indicates if the transposed system shall be solved. */ + BooleanType removingBound, /**< Indicates if function is called from "removeBound()". */ + real_t* const a /**< Output: Solution vector */ + ) const; + + + /** Determines step direction of the shift of the QP data. + * \return SUCCESSFUL_RETURN */ + returnValue determineDataShift( const real_t* const g_new, /**< New gradient vector. */ + const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new, /**< New upper bounds. */ + real_t* const delta_g, /**< Output: Step direction of gradient vector. */ + real_t* const delta_lb, /**< Output: Step direction of lower bounds. */ + real_t* const delta_ub, /**< Output: Step direction of upper bounds. */ + BooleanType& Delta_bB_isZero/**< Output: Indicates if active bounds are to be shifted. */ + ); + + + /** Sets up internal QP data. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ + returnValue setupQPdata( SymmetricMatrix *_H, /**< Hessian matrix.*/ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + + /** Sets up internal QP data. If the current Hessian is trivial + * (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_NO_HESSIAN_SPECIFIED */ + returnValue setupQPdata( const real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + + /** Sets up internal QP data by loading it from files. If the current Hessian + * is trivial (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS \n + RET_NO_HESSIAN_SPECIFIED */ + returnValue setupQPdataFromFile( const char* const H_file, /**< Name of file where Hessian matrix, of neighbouring QP to be solved, is stored. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + + /** Loads new QP vectors from files (internal members are not affected!). + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ + returnValue loadQPvectorsFromFile( const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + real_t* const g_new, /**< Output: Gradient of neighbouring QP to be solved. */ + real_t* const lb_new, /**< Output: Lower bounds of neighbouring QP to be solved */ + real_t* const ub_new /**< Output: Upper bounds of neighbouring QP to be solved */ + ) const; + + + /** Sets internal infeasibility flag and throws given error in case the far bound + * strategy is not enabled (as QP might actually not be infeasible in this case). + * \return RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_ENSURELI_FAILED_CYCLING \n + RET_ENSURELI_FAILED_NOINDEX */ + returnValue setInfeasibilityFlag( returnValue returnvalue, /**< Returnvalue to be tunneled. */ + BooleanType doThrowError = BT_FALSE /**< Flag forcing to throw an error. */ + ); + + + /** Determines if next QP iteration can be performed within given CPU time limit. + * \return BT_TRUE: CPU time limit is exceeded, stop QP solution. \n + BT_FALSE: Sufficient CPU time for next QP iteration. */ + BooleanType isCPUtimeLimitExceeded( const real_t* const cputime, /**< Maximum CPU time allowed for QP solution. */ + real_t starttime, /**< Start time of current QP solution. */ + int nWSR /**< Number of working set recalculations performed so far. */ + ) const; + + + /** Regularise Hessian matrix by adding a scaled identity matrix to it. + * \return SUCCESSFUL_RETURN \n + RET_HESSIAN_ALREADY_REGULARISED */ + returnValue regulariseHessian( ); + + + /** Sets Hessian matrix of the QP. + * \return SUCCESSFUL_RETURN */ + inline returnValue setH( SymmetricMatrix* H_new /**< New Hessian matrix (a shallow copy is made). */ + ); + + /** Sets dense Hessian matrix of the QP. + * If a null pointer is passed and + * a) hessianType is HST_IDENTITY, nothing is done, + * b) hessianType is not HST_IDENTITY, Hessian matrix is set to zero. + * \return SUCCESSFUL_RETURN */ + inline returnValue setH( const real_t* const H_new /**< New dense Hessian matrix (with correct dimension!), a shallow copy is made. */ + ); + + /** Changes gradient vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ + inline returnValue setG( const real_t* const g_new /**< New gradient vector (with correct dimension!). */ + ); + + /** Changes lower bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP */ + inline returnValue setLB( const real_t* const lb_new /**< New lower bound vector (with correct dimension!). */ + ); + + /** Changes single entry of lower bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP \n + * RET_INDEX_OUT_OF_BOUNDS */ + inline returnValue setLB( int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of lower bound vector. */ + ); + + /** Changes upper bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP */ + inline returnValue setUB( const real_t* const ub_new /**< New upper bound vector (with correct dimension!). */ + ); + + /** Changes single entry of upper bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP \n + * RET_INDEX_OUT_OF_BOUNDS */ + inline returnValue setUB( int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of upper bound vector. */ + ); + + + /** Computes parameters for the Givens matrix G for which [x,y]*G = [z,0] + * \return SUCCESSFUL_RETURN */ + inline void computeGivens( real_t xold, /**< Matrix entry to be normalised. */ + real_t yold, /**< Matrix entry to be annihilated. */ + real_t& xnew, /**< Output: Normalised matrix entry. */ + real_t& ynew, /**< Output: Annihilated matrix entry. */ + real_t& c, /**< Output: Cosine entry of Givens matrix. */ + real_t& s /**< Output: Sine entry of Givens matrix. */ + ) const; + + /** Applies Givens matrix determined by c and s (cf. computeGivens). + * \return SUCCESSFUL_RETURN */ + inline void applyGivens( real_t c, /**< Cosine entry of Givens matrix. */ + real_t s, /**< Sine entry of Givens matrix. */ + real_t nu, /**< Further factor: s/(1+c). */ + real_t xold, /**< Matrix entry to be transformed corresponding to + * the normalised entry of the original matrix. */ + real_t yold, /**< Matrix entry to be transformed corresponding to + * the annihilated entry of the original matrix. */ + real_t& xnew, /**< Output: Transformed matrix entry corresponding to + * the normalised entry of the original matrix. */ + real_t& ynew /**< Output: Transformed matrix entry corresponding to + * the annihilated entry of the original matrix. */ + ) const; + + + + /** Compute relative length of homotopy in data space for termination + * criterion. + * \return Relative length in data space. */ + real_t getRelativeHomotopyLength( const real_t* const g_new, /**< Final gradient. */ + const real_t* const lb_new, /**< Final lower variable bounds. */ + const real_t* const ub_new /**< Final upper variable bounds. */ + ); + + /** Ramping Strategy to avoid ties. Modifies homotopy start without + * changing current active set. + * \return SUCCESSFUL_RETURN */ + virtual returnValue performRamping( ); + + + /** ... */ + returnValue updateFarBounds( real_t curFarBound, /**< ... */ + int nRamp, /**< ... */ + const real_t* const lb_new, /**< ... */ + real_t* const lb_new_far, /**< ... */ + const real_t* const ub_new, /**< ... */ + real_t* const ub_new_far /**< ... */ + ) const; + + + /** Performs robustified ratio test yield the maximum possible step length + * along the homotopy path. + * \return SUCCESSFUL_RETURN */ + returnValue performRatioTest( int nIdx, /**< Number of ratios to be checked. */ + const int* const idxList, /**< Array containing the indices of all ratios to be checked. */ + const SubjectTo* const subjectTo, /**< Bound/Constraint object corresponding to ratios to be checked. */ + const real_t* const num, /**< Array containing all numerators for performing the ratio test. */ + const real_t* const den, /**< Array containing all denominators for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t& t, /**< Output: Maximum possible step length along the homotopy path. */ + int& BC_idx /**< Output: Index of blocking constraint. */ + ) const; + + /** Checks whether given ratio is blocking, i.e. limits the maximum step length + * along the homotopy path to a value lower than given one. + * \return SUCCESSFUL_RETURN */ + inline BooleanType isBlocking( real_t num, /**< Numerator for performing the ratio test. */ + real_t den, /**< Denominator for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t& t /**< Input: Current maximum step length along the homotopy path, + * Output: Updated maximum possible step length along the homotopy path. */ + ) const; + + + /** Creates a sparse diagonal (square-)matrix which is a given + * multiple of the identity matrix. + * \return Diagonal matrix \n + */ + SymSparseMat* createDiagSparseMat( int n, /**< Row/column dimension of matrix to be created. */ + real_t diagVal = 1.0 /**< Value of all diagonal entries. */ + ); + + + /* + * PRIVATE MEMBER FUNCTIONS + */ + private: + /** Solves a QProblemB whose QP data is assumed to be stored in the member variables. + * A guess for its primal/dual optimal solution vectors and the corresponding + * optimal working set can be provided. + * Note: This function is internally called by all init functions! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED */ + returnValue solveInitialQP( const real_t* const xOpt, /**< Optimal primal solution vector. + * A NULL pointer can be passed. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + * A NULL pointer can be passed. */ + const Bounds* const guessedBounds, /**< Guessed working set for solution (xOpt,yOpt). + * A NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + * Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised QProblemB using online active set strategy. + * Note: This function is internally called by all hotstart functions! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ + returnValue solveQP( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + int nWSRperformed = 0 /**< Number of working set recalculations already performed to solve + this QP within previous solveQP() calls. This number is + always zero, except for successive calls from solveRegularisedQP() + or when using the far bound strategy. */ + ); + + + /** Solves an initialised QProblemB using online active set strategy. + * Note: This function is internally called by all hotstart functions! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ + returnValue solveRegularisedQP( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + int nWSRperformed = 0 /**< Number of working set recalculations already performed to solve + this QP within previous solveRegularisedQP() calls. This number is + always zero, except for successive calls when using the far bound strategy. */ + ); + + + /** Sets up bound data structure according to auxiliaryBounds. + * (If the working set shall be setup afresh, make sure that + * bounds data structure has been resetted!) + * \return SUCCESSFUL_RETURN \n + RET_SETUP_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS \n + RET_UNKNOWN_BUG */ + returnValue setupAuxiliaryWorkingSet( const Bounds* const auxiliaryBounds, /**< Working set for auxiliary QP. */ + BooleanType setupAfresh /**< Flag indicating if given working set shall be + * setup afresh or by updating the current one. */ + ); + + /** Sets up the optimal primal/dual solution of the auxiliary initial QP. + * \return SUCCESSFUL_RETURN */ + returnValue setupAuxiliaryQPsolution( const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are set to zero. */ + const real_t* const yOpt /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are set to zero. */ + ); + + /** Sets up gradient of the auxiliary initial QP for given + * optimal primal/dual solution and given initial working set + * (assumes that members X, Y and BOUNDS have already been initialised!). + * \return SUCCESSFUL_RETURN */ + returnValue setupAuxiliaryQPgradient( ); + + /** Sets up bounds of the auxiliary initial QP for given + * optimal primal/dual solution and given initial working set + * (assumes that members X, Y and BOUNDS have already been initialised!). + * \return SUCCESSFUL_RETURN \n + RET_UNKNOWN_BUG */ + returnValue setupAuxiliaryQPbounds( BooleanType useRelaxation /**< Flag indicating if inactive bounds shall be relaxed. */ + ); + + + /** Updates QP vectors, working sets and internal data structures in order to + start from an optimal solution corresponding to initial guesses of the working + set for bounds + * \return SUCCESSFUL_RETURN \n + * RET_SETUP_AUXILIARYQP_FAILED */ + returnValue setupAuxiliaryQP( const Bounds* const guessedBounds /**< Initial guess for working set of bounds. */ + ); + + /** Determines step direction of the homotopy path. + * \return SUCCESSFUL_RETURN \n + RET_STEPDIRECTION_FAILED_CHOLESKY */ + returnValue determineStepDirection( const real_t* const delta_g, /**< Step direction of gradient vector. */ + const real_t* const delta_lb, /**< Step direction of lower bounds. */ + const real_t* const delta_ub, /**< Step direction of upper bounds. */ + BooleanType Delta_bB_isZero, /**< Indicates if active bounds are to be shifted. */ + real_t* const delta_xFX, /**< Output: Primal homotopy step direction of fixed variables. */ + real_t* const delta_xFR, /**< Output: Primal homotopy step direction of free variables. */ + real_t* const delta_yFX /**< Output: Dual homotopy step direction of fixed variables' multiplier. */ + ); + + /** Determines the maximum possible step length along the homotopy path + * and performs this step (without changing working set). + * \return SUCCESSFUL_RETURN \n + * RET_QP_INFEASIBLE \n + */ + returnValue performStep( const real_t* const delta_g, /**< Step direction of gradient. */ + const real_t* const delta_lb, /**< Step direction of lower bounds. */ + const real_t* const delta_ub, /**< Step direction of upper bounds. */ + const real_t* const delta_xFX, /**< Primal homotopy step direction of fixed variables. */ + const real_t* const delta_xFR, /**< Primal homotopy step direction of free variables. */ + const real_t* const delta_yFX, /**< Dual homotopy step direction of fixed variables' multiplier. */ + int& BC_idx, /**< Output: Index of blocking constraint. */ + SubjectToStatus& BC_status /**< Output: Status of blocking constraint. */ + ); + + /** Updates active set. + * \return SUCCESSFUL_RETURN \n + RET_REMOVE_FROM_ACTIVESET_FAILED \n + RET_ADD_TO_ACTIVESET_FAILED */ + returnValue changeActiveSet( int BC_idx, /**< Index of blocking constraint. */ + SubjectToStatus BC_status /**< Status of blocking constraint. */ + ); + + /** Drift correction at end of each active set iteration + * \return SUCCESSFUL_RETURN */ + virtual returnValue performDriftCorrection( ); + + /** Determines if it is more efficient to refactorise the matrices when + * hotstarting or not (i.e. better to update the existing factorisations). + * \return BT_TRUE iff matrices shall be refactorised afresh + */ + BooleanType shallRefactorise( const Bounds* const guessedBounds /**< Guessed new working set. */ + ) const; + + + /** Adds a bound to active set (specialised version for the case where no constraints exist). + * \return SUCCESSFUL_RETURN \n + RET_ADDBOUND_FAILED */ + returnValue addBound( int number, /**< Number of bound to be added to active set. */ + SubjectToStatus B_status, /**< Status of new active bound. */ + BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */ + ); + + /** Removes a bounds from active set (specialised version for the case where no constraints exist). + * \return SUCCESSFUL_RETURN \n + RET_HESSIAN_NOT_SPD \n + RET_REMOVEBOUND_FAILED */ + returnValue removeBound( int number, /**< Number of bound to be removed from active set. */ + BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */ + ); + + + /** Prints concise information on the current iteration. + * \return SUCCESSFUL_RETURN \n */ + returnValue printIteration( int iter, /**< Number of current iteration. */ + int BC_idx, /**< Index of blocking bound. */ + SubjectToStatus BC_status, /**< Status of blocking bound. */ + real_t homotopyLength /**< Current homotopy distance. */ + ); + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + BooleanType freeHessian; /**< Flag indicating whether the Hessian matrix needs to be de-allocated. */ + SymmetricMatrix* H; /**< Hessian matrix. */ + + real_t* g; /**< Gradient. */ + real_t* lb; /**< Lower bound vector (on variables). */ + real_t* ub; /**< Upper bound vector (on variables). */ + + Bounds bounds; /**< Data structure for problem's bounds. */ + + real_t* R; /**< Cholesky factor of H (i.e. H = R^T*R). */ + BooleanType haveCholesky; /**< Flag indicating whether Cholesky decomposition has already been setup. */ + + real_t* x; /**< Primal solution vector. */ + real_t* y; /**< Dual solution vector. */ + + real_t tau; /**< Last homotopy step length. */ + + QProblemStatus status; /**< Current status of the solution process. */ + + BooleanType infeasible; /**< QP infeasible? */ + BooleanType unbounded; /**< QP unbounded? */ + + HessianType hessianType; /**< Type of Hessian matrix. */ + real_t regVal; /**< Holds the offset used to regularise Hessian matrix (zero by default). */ + + int count; /**< Counts the number of hotstart function calls (internal usage only!). */ + + real_t *delta_xFR_TMP; /**< Temporary for determineStepDirection */ + + real_t ramp0; /**< Start value for Ramping Strategy. */ + real_t ramp1; /**< Final value for Ramping Strategy. */ + int rampOffset; /**< Offset index for Ramping. */ + + Options options; /**< Struct containing all user-defined options for solving QPs. */ + + Flipper flipper; /**< Struct for making a temporary copy of the matrix factorisations. */ + + TabularOutput tabularOutput; /**< Struct storing information for tabular output (printLevel == PL_TABULAR). */ +}; + + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_QPROBLEMB_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblemB.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblemB.ipp new file mode 100644 index 00000000000..2a0922cae5e --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/QProblemB.ipp @@ -0,0 +1,477 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/QProblemB.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Implementation of inlined member functions of the QProblemB class which + * is able to use the newly developed online active set strategy for + * parametric quadratic programming. + */ + + + +BEGIN_NAMESPACE_QPOASES + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + +/* + * g e t B o u n d s + */ +inline returnValue QProblemB::getBounds( Bounds& _bounds ) const +{ + int nV = getNV( ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + _bounds = bounds; + + return SUCCESSFUL_RETURN; +} + + +/* + * g e t N V + */ +inline int QProblemB::getNV( ) const +{ + return bounds.getNV( ); +} + + +/* + * g e t N F R + */ +inline int QProblemB::getNFR( ) const +{ + return bounds.getNFR( ); +} + + +/* + * g e t N F X + */ +inline int QProblemB::getNFX( ) const +{ + return bounds.getNFX( ); +} + + +/* + * g e t N F V + */ +inline int QProblemB::getNFV( ) const +{ + return bounds.getNFV( ); +} + + +/* + * g e t S t a t u s + */ +inline QProblemStatus QProblemB::getStatus( ) const +{ + return status; +} + + +/* + * i s I n i t i a l i s e d + */ +inline BooleanType QProblemB::isInitialised( ) const +{ + if ( status == QPS_NOTINITIALISED ) + return BT_FALSE; + else + return BT_TRUE; +} + + +/* + * i s S o l v e d + */ +inline BooleanType QProblemB::isSolved( ) const +{ + if ( status == QPS_SOLVED ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * i s I n f e a s i b l e + */ +inline BooleanType QProblemB::isInfeasible( ) const +{ + return infeasible; +} + + +/* + * i s U n b o u n d e d + */ +inline BooleanType QProblemB::isUnbounded( ) const +{ + return unbounded; +} + + +/* + * g e t H e s s i a n T y p e + */ +inline HessianType QProblemB::getHessianType( ) const +{ + return hessianType; +} + + +/* + * s e t H e s s i a n T y p e + */ +inline returnValue QProblemB::setHessianType( HessianType _hessianType ) +{ + hessianType = _hessianType; + return SUCCESSFUL_RETURN; +} + + +/* + * u s i n g R e g u l a r i s a t i o n + */ +inline BooleanType QProblemB::usingRegularisation( ) const +{ + if ( regVal > ZERO ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * g e t O p t i o n s + */ +inline Options QProblemB::getOptions( ) const +{ + return options; +} + + +/* + * s e t O p t i o n s + */ +inline returnValue QProblemB::setOptions( const Options& _options + ) +{ + options = _options; + options.ensureConsistency( ); + + setPrintLevel( options.printLevel ); + + return SUCCESSFUL_RETURN; +} + + +/* + * g e t P r i n t L e v e l + */ +inline PrintLevel QProblemB::getPrintLevel( ) const +{ + return options.printLevel; +} + + + +/***************************************************************************** + * P R O T E C T E D * + *****************************************************************************/ + +/* + * s e t H + */ +inline returnValue QProblemB::setH( SymmetricMatrix* H_new ) +{ + if ( ( freeHessian == BT_TRUE ) && ( H != 0 ) ) + { + delete H; + H = 0; + } + + H = H_new; + freeHessian = BT_FALSE; + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t H + */ +inline returnValue QProblemB::setH( const real_t* const H_new ) +{ + int nV = getNV(); + SymDenseMat* dH; + + /* if null pointer is passed, Hessian is set to zero matrix + * (or stays identity matrix) */ + if ( H_new == 0 ) + { + if ( hessianType == HST_IDENTITY ) + return SUCCESSFUL_RETURN; + + hessianType = HST_ZERO; + + if ( ( freeHessian == BT_TRUE ) && ( H != 0 ) ) + delete H; + + H = 0; + freeHessian = BT_FALSE; + } + else + { + if ( ( freeHessian == BT_TRUE ) && ( H != 0 ) ) + delete H; + + H = dH = new SymDenseMat( nV, nV, nV, (real_t*) H_new ); + freeHessian = BT_TRUE; + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t G + */ +inline returnValue QProblemB::setG( const real_t* const g_new ) +{ + unsigned int nV = getNV( ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( g_new == 0 ) + return THROWERROR( RET_INVALID_ARGUMENTS ); + + memcpy( g,g_new,nV*sizeof(real_t) ); + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t L B + */ +inline returnValue QProblemB::setLB( const real_t* const lb_new ) +{ + unsigned int i; + unsigned int nV = getNV( ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( lb_new != 0 ) + { + memcpy( lb,lb_new,nV*sizeof(real_t) ); + } + else + { + /* if no lower bounds are specified, set them to -infinity */ + for( i=0; i= 0 ) && ( number < nV ) ) + { + lb[number] = value; + return SUCCESSFUL_RETURN; + } + else + { + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); + } +} + + +/* + * s e t U B + */ +inline returnValue QProblemB::setUB( const real_t* const ub_new ) +{ + unsigned int i; + unsigned int nV = getNV( ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ub_new != 0 ) + { + memcpy( ub,ub_new,nV*sizeof(real_t) ); + } + else + { + /* if no upper bounds are specified, set them to infinity */ + for( i=0; i= 0 ) && ( number < nV ) ) + { + ub[number] = value; + + return SUCCESSFUL_RETURN; + } + else + { + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); + } +} + + +/* + * c o m p u t e G i v e n s + */ +inline void QProblemB::computeGivens( real_t xold, real_t yold, real_t& xnew, real_t& ynew, + real_t& c, real_t& s + ) const +{ + real_t t, mu; + + if ( isZero( yold ) == BT_TRUE ) + { + c = 1.0; + s = 0.0; + + xnew = xold; + ynew = yold; + } + else + { + mu = getAbs( xold ); + if ( getAbs( yold ) > mu ) + mu = getAbs( yold ); + + t = mu * getSqrt( (xold/mu)*(xold/mu) + (yold/mu)*(yold/mu) ); + + if ( xold < 0.0 ) + t = -t; + + c = xold/t; + s = yold/t; + xnew = t; + ynew = 0.0; + } + + return; +} + + +/* + * a p p l y G i v e n s + */ +inline void QProblemB::applyGivens( real_t c, real_t s, real_t nu, real_t xold, real_t yold, + real_t& xnew, real_t& ynew + ) const +{ + #ifdef __USE_THREE_MULTS_GIVENS__ + + /* Givens plane rotation requiring only three multiplications, + * cf. Hammarling, S.: A note on modifications to the givens plane rotation. + * J. Inst. Maths Applics, 13:215-218, 1974. */ + xnew = xold*c + yold*s; + ynew = (xnew+xold)*nu - yold; + + #else + + /* Usual Givens plane rotation requiring four multiplications. */ + xnew = c*xold + s*yold; + ynew = -s*xold + c*yold; + + #endif + + return; +} + + +/* + * i s B l o c k i n g + */ +inline BooleanType QProblemB::isBlocking( real_t num, + real_t den, + real_t epsNum, + real_t epsDen, + real_t& t + ) const +{ + if ( ( den >= epsDen ) && ( num >= epsNum ) ) + { + if ( num < t*den ) + return BT_TRUE; + } + + return BT_FALSE; +} + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SQProblem.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SQProblem.hpp new file mode 100644 index 00000000000..aec5adab23f --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SQProblem.hpp @@ -0,0 +1,394 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/SQProblem.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the SQProblem class which is able to use the newly + * developed online active set strategy for parametric quadratic programming + * with varying matrices. + */ + + + +#ifndef QPOASES_SQPROBLEM_HPP +#define QPOASES_SQPROBLEM_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Implements the online active set strategy for QPs with varying matrices. + * + * A class for setting up and solving quadratic programs with varying QP matrices. + * The main feature is the possibily to use the newly developed online active set strategy + * for parametric quadratic programming. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + */ +class SQProblem : public QProblem +{ + /* allow SolutionAnalysis class to access private members */ + friend class SolutionAnalysis; + + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + SQProblem( ); + + /** Constructor which takes the QP dimension and Hessian type + * information. If the Hessian is the zero (i.e. HST_ZERO) or the + * identity matrix (i.e. HST_IDENTITY), respectively, no memory + * is allocated for it and a NULL pointer can be passed for it + * to the init() functions. */ + SQProblem( int _nV, /**< Number of variables. */ + int _nC, /**< Number of constraints. */ + HessianType _hessianType = HST_UNKNOWN /**< Type of Hessian matrix. */ + ); + + /** Copy constructor (deep copy). */ + SQProblem( const SQProblem& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + virtual ~SQProblem( ); + + /** Assignment operator (deep copy). */ + SQProblem& operator=( const SQProblem& rhs /**< Rhs object. */ + ); + + + /** Solves an initialised SQProblem using online active set strategy. + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_MATRIX_SHIFT_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED */ + returnValue hotstart( const real_t* const H_new, /**< Hessian matrix of neighbouring QP to be solved (a shallow copy is made). \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const A_new, /**< Constraint matrix of neighbouring QP to be solved (a shallow copy is made). \n + If QP sequence does not involve constraints, a NULL pointer can be passed. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new,/**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new,/**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised SQProblem using online active set strategy + * reading QP data from files. + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_MATRIX_SHIFT_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ + returnValue hotstart( const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const A_file, /**< Name of file where constraint matrix is stored. \n + If QP sequence does not involve constraints, a NULL pointer can be passed. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised SQProblem using online active set strategy. + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_MATRIX_SHIFT_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED */ + returnValue hotstart( SymmetricMatrix *H_new, /**< Hessian matrix of neighbouring QP to be solved (a shallow copy is made). \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + Matrix *A_new, /**< Constraint matrix of neighbouring QP to be solved (a shallow copy is made). \n + If QP sequence does not involve constraints, a NULL pointer can be passed. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new,/**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new,/**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised SQProblem (without matrix shift) using online active set strategy. + * Note: This functions just forwards to the corresponding + * QProblem::hotstart member function. + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ + returnValue hotstart( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised SQProblem (without matrix shift) using online active set strategy + * reading QP data from files. + * Note: This functions just forwards to the corresponding + * QProblem::hotstart member function. + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_UNABLE_TO_READ_FILE */ + returnValue hotstart( const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime = 0 /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + ); + + /** Solves an initialised SQProblem (without matrix shift) using online active set strategy + * (using an initialised homotopy). + * Note: This functions just forwards to the corresponding + * QProblem::hotstart member function. + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_WORKINGSET_UPDATE_FAILED */ + returnValue hotstart( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + const Bounds* const guessedBounds, /**< Initial guess for working set of bounds. + * A null pointer corresponds to an empty working set! */ + const Constraints* const guessedConstraints /**< Initial guess for working set of constraints. + * A null pointer corresponds to an empty working set! */ + ); + + /** Solves an initialised SQProblem (without matrix shift) using online active set strategy + * (using an initialised homotopy) reading QP data from files. + * Note: This functions just forwards to the corresponding + * QProblem::hotstart member function. + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_WORKINGSET_UPDATE_FAILED \n + RET_UNABLE_TO_READ_FILE */ + returnValue hotstart( const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spend for QP solution (or to perform nWSR iterations). */ + const Bounds* const guessedBounds, /**< Initial guess for working set of bounds. + * A null pointer corresponds to an empty working set! */ + const Constraints* const guessedConstraints /**< Initial guess for working set of constraints. + * A null pointer corresponds to an empty working set! */ + ); + + + + #ifdef __MATLAB__ + /** Sets pointer of Hessian and constraint matrix to zero. + * QUICK HACK FOR MAKING THE MATLAB INTERFACE RUN! TO BE REMOVED! + * \return SUCCESSFUL_RETURN */ + returnValue resetMatrixPointers( ); + #endif + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Sets new matrices and calculates their factorisations. If the + * current Hessian is trivial (i.e. HST_ZERO or HST_IDENTITY) but a + * non-trivial one is given, memory for Hessian is allocated and + * it is set to the given one. Afterwards, all QP vectors are + * transformed in order to start from an optimal solution. + * \return SUCCESSFUL_RETURN \n + * RET_MATRIX_FACTORISATION_FAILED \n + * RET_NO_HESSIAN_SPECIFIED */ + virtual returnValue setupAuxiliaryQP( const real_t* const H_new, /**< New Hessian matrix. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const A_new, /**< New constraint matrix. \n + If QP sequence does not involve constraints, a NULL pointer can be passed. */ + const real_t *lb_new, /**< New lower bounds. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t *ub_new, /**< New upper bounds. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t *lbA_new, /**< New lower constraints' bounds. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t *ubA_new /**< New lower constraints' bounds. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + ); + + /** Sets new matrices and calculates their factorisations. If the + * current Hessian is trivial (i.e. HST_ZERO or HST_IDENTITY) but a + * non-trivial one is given, memory for Hessian is allocated and + * it is set to the given one. Afterwards, all QP vectors are + * transformed in order to start from an optimal solution. + * \return SUCCESSFUL_RETURN \n + * RET_MATRIX_FACTORISATION_FAILED \n + * RET_NO_HESSIAN_SPECIFIED */ + virtual returnValue setupAuxiliaryQP( SymmetricMatrix *H_new, /**< New Hessian matrix. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + Matrix *A_new, /**< New constraint matrix. \n + If QP sequence does not involve constraints, a NULL pointer can be passed. */ + const real_t *lb_new, /**< New lower bounds. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t *ub_new, /**< New upper bounds. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t *lbA_new, /**< New lower constraints' bounds. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t *ubA_new /**< New lower constraints' bounds. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + ); + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + +}; + + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_SQPROBLEM_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SQProblem.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SQProblem.ipp new file mode 100644 index 00000000000..61a88faeb32 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SQProblem.ipp @@ -0,0 +1,51 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/SQProblem.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Implementation of inlined member functions of the SQProblem class which + * is able to use the newly developed online active set strategy for + * parametric quadratic programming with varying matrices. + */ + + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + + +BEGIN_NAMESPACE_QPOASES + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SubjectTo.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SubjectTo.hpp new file mode 100644 index 00000000000..9d3d4bea812 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SubjectTo.hpp @@ -0,0 +1,229 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/SubjectTo.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of the SubjectTo class designed to manage working sets of + * constraints and bounds within a QProblem. + */ + + +#ifndef QPOASES_SUBJECTTO_HPP +#define QPOASES_SUBJECTTO_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Base class for managing working sets of bounds and constraints. + * + * This class manages working sets of bounds and constraints by storing + * index sets and other status information. + * + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + */ +class SubjectTo +{ + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + SubjectTo( ); + + /** Constructor which takes the number of constraints or bounds. */ + SubjectTo( int _n /**< Number of constraints or bounds. */ + ); + + /** Copy constructor (deep copy). */ + SubjectTo( const SubjectTo& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + virtual ~SubjectTo( ); + + /** Assignment operator (deep copy). */ + SubjectTo& operator=( const SubjectTo& rhs /**< Rhs object. */ + ); + + + /** Initialises object with given number of constraints or bounds. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ + returnValue init( int _n = 0 /**< Number of constraints or bounds. */ + ); + + + /** Returns number of constraints/bounds with given SubjectTo type. + * \return Number of constraints/bounds with given type. */ + inline int getNumberOfType( SubjectToType _type /**< Type of (constraints') bound. */ + ) const; + + + /** Returns type of (constraints') bound. + * \return Type of (constraints') bound \n + RET_INDEX_OUT_OF_BOUNDS */ + inline SubjectToType getType( int i /**< Number of (constraints') bound. */ + ) const; + + /** Returns status of (constraints') bound. + * \return Status of (constraints') bound \n + ST_UNDEFINED */ + inline SubjectToStatus getStatus( int i /**< Number of (constraints') bound. */ + ) const; + + + /** Sets type of (constraints') bound. + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS */ + inline returnValue setType( int i, /**< Number of (constraints') bound. */ + SubjectToType value /**< Type of (constraints') bound. */ + ); + + /** Sets status of (constraints') bound. + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS */ + inline returnValue setStatus( int i, /**< Number of (constraints') bound. */ + SubjectToStatus value /**< Status of (constraints') bound. */ + ); + + + /** Sets status of lower (constraints') bounds. */ + inline void setNoLower( BooleanType _status /**< Status of lower (constraints') bounds. */ + ); + + /** Sets status of upper (constraints') bounds. */ + inline void setNoUpper( BooleanType _status /**< Status of upper (constraints') bounds. */ + ); + + + /** Returns status of lower (constraints') bounds. + * \return BT_TRUE if there is no lower (constraints') bound on any variable. */ + inline BooleanType hasNoLower( ) const; + + /** Returns status of upper bounds. + * \return BT_TRUE if there is no upper (constraints') bound on any variable. */ + inline BooleanType hasNoUpper( ) const; + + + /** Shifts forward type and status of all constraints/bounds by a given + * offset. This offset has to lie within the range [0,n/2] and has to + * be an integer divisor of the total number of constraints/bounds n. + * Type and status of the first \ constraints/bounds is thrown away, + * type and status of the last \ constraints/bounds is doubled, + * e.g. for offset = 2: \n + * shift( {c/b1,c/b2,c/b3,c/b4,c/b5,c/b6} ) = {c/b3,c/b4,c/b5,c/b6,c/b5,c/b6} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS \n + RET_SHIFTING_FAILED */ + virtual returnValue shift( int offset /**< Shift offset within the range [0,n/2] and integer divisor of n. */ + ) = 0; + + /** Rotates forward type and status of all constraints/bounds by a given + * offset. This offset has to lie within the range [0,n]. + * Example for offset = 2: \n + * rotate( {c/b1,c/b2,c/b3,c/b4,c/b5,c/b6} ) = {c/b3,c/b4,c/b5,c/b6,c/b1,c/b2} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_ROTATING_FAILED */ + virtual returnValue rotate( int offset /**< Rotation offset within the range [0,n]. */ + ) = 0; + + + /* + * PROTECTED MEMBER FUNCTIONS + */ + protected: + /** Frees all allocated memory. + * \return SUCCESSFUL_RETURN */ + returnValue clear( ); + + /** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ + returnValue copy( const SubjectTo& rhs /**< Rhs object. */ + ); + + + /** Adds the index of a new constraint or bound to index set. + * \return SUCCESSFUL_RETURN \n + RET_ADDINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ + returnValue addIndex( Indexlist* const indexlist, /**< Index list to which the new index shall be added. */ + int newnumber, /**< Number of new constraint or bound. */ + SubjectToStatus newstatus /**< Status of new constraint or bound. */ + ); + + /** Removes the index of a constraint or bound from index set. + * \return SUCCESSFUL_RETURN \n + RET_REMOVEINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ + returnValue removeIndex( Indexlist* const indexlist, /**< Index list from which the new index shall be removed. */ + int removenumber /**< Number of constraint or bound to be removed. */ + ); + + /** Swaps the indices of two constraints or bounds within the index set. + * \return SUCCESSFUL_RETURN \n + RET_SWAPINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ + returnValue swapIndex( Indexlist* const indexlist, /**< Index list in which the indices shold be swapped. */ + int number1, /**< Number of first constraint or bound. */ + int number2 /**< Number of second constraint or bound. */ + ); + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + int n; /**< Total number of constraints/bounds. */ + + SubjectToType* type; /**< Type of constraints/bounds. */ + SubjectToStatus* status; /**< Status of constraints/bounds. */ + + BooleanType noLower; /**< This flag indicates if there is no lower bound on any variable. */ + BooleanType noUpper; /**< This flag indicates if there is no upper bound on any variable. */ +}; + + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_SUBJECTTO_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SubjectTo.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SubjectTo.ipp new file mode 100644 index 00000000000..086f54ca528 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/SubjectTo.ipp @@ -0,0 +1,158 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/SubjectTo.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Implementation of the inlined member functions of the SubjectTo class + * designed to manage working sets of constraints and bounds within a QProblem. + */ + + +BEGIN_NAMESPACE_QPOASES + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + + +/* + * g e t N u m b e r O f T y p e + */ +inline int SubjectTo::getNumberOfType( SubjectToType _type ) const +{ + int i; + int numberOfType = 0; + + if ( type != 0 ) + { + for( i=0; i= 0 ) && ( i < n ) ) + return type[i]; + + return ST_UNKNOWN; +} + + +/* + * g e t S t a t u s + */ +inline SubjectToStatus SubjectTo::getStatus( int i ) const +{ + if ( ( i >= 0 ) && ( i < n ) ) + return status[i]; + + return ST_UNDEFINED; +} + + +/* + * s e t T y p e + */ +inline returnValue SubjectTo::setType( int i, SubjectToType value ) +{ + if ( ( i >= 0 ) && ( i < n ) ) + { + type[i] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +/* + * s e t S t a t u s + */ +inline returnValue SubjectTo::setStatus( int i, SubjectToStatus value ) +{ + if ( ( i >= 0 ) && ( i < n ) ) + { + status[i] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +/* + * s e t N o L o w e r + */ +inline void SubjectTo::setNoLower( BooleanType _status ) +{ + noLower = _status; +} + + +/* + * s e t N o U p p e r + */ +inline void SubjectTo::setNoUpper( BooleanType _status ) +{ + noUpper = _status; +} + + +/* + * h a s N o L o w e r + */ +inline BooleanType SubjectTo::hasNoLower( ) const +{ + return noLower; +} + + +/* + * h a s N o U p p p e r + */ +inline BooleanType SubjectTo::hasNoUpper( ) const +{ + return noUpper; +} + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Types.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Types.hpp new file mode 100644 index 00000000000..fc42d1288c7 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Types.hpp @@ -0,0 +1,281 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Types.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of all non-built-in types (except for classes). + */ + + +#ifndef QPOASES_TYPES_HPP +#define QPOASES_TYPES_HPP + + +/* If your compiler does not support the snprintf() function, + * uncomment the following line and try to compile again. */ +/* #define __NO_SNPRINTF__ */ + + +/* Uncomment the following line for setting the __DSPACE__ flag. */ +/* #define __DSPACE__ */ + +/* Uncomment the following line for setting the __XPCTARGET__ flag. */ +/* #define __XPCTARGET__ */ + + +/* Uncomment the following line for setting the __NO_FMATH__ flag. */ +/* #define __NO_FMATH__ */ + +/* Uncomment the following line to enable debug information. */ +/* #define __DEBUG__ */ + +/* Uncomment the following line to enable suppress any kind of console output. */ +/* #define __SUPPRESSANYOUTPUT__ */ + + +/** Forces to always include all implicitly fixed bounds and all equality constraints + * into the initial working set when setting up an auxiliary QP. */ +#define __ALWAYS_INITIALISE_WITH_ALL_EQUALITIES__ + + +/* Uncomment the following line to activate the use of an alternative Givens + * plane rotation requiring only three multiplications. */ +/* #define __USE_THREE_MULTS_GIVENS__ */ + +/* Uncomment the following line to activate the use of single precision arithmetic. */ +/* #define __USE_SINGLE_PRECISION__ */ + + + +/* Work-around for Borland BCC 5.5 compiler. */ +#ifdef __BORLANDC__ +#if __BORLANDC__ < 0x0561 + #define __STDC__ 1 +#endif +#endif + + +/* Work-around for Microsoft compilers. */ +#ifdef _MSC_VER + #define __NO_SNPRINTF__ + #pragma warning( disable : 4061 4100 4250 4514 4996 ) +#endif + + +#ifdef __DSPACE__ + + #define __NO_SNPRINTF__ + + /** Macro for switching on/off the beginning of the qpOASES namespace definition. */ + #define BEGIN_NAMESPACE_QPOASES + + /** Macro for switching on/off the end of the qpOASES namespace definition. */ + #define END_NAMESPACE_QPOASES + + /** Macro for switching on/off the use of the qpOASES namespace. */ + #define USING_NAMESPACE_QPOASES + + /** Macro for switching on/off references to the qpOASES namespace. */ + #define REFER_NAMESPACE_QPOASES :: + +#else + + /** Macro for switching on/off the beginning of the qpOASES namespace definition. */ + #define BEGIN_NAMESPACE_QPOASES namespace qpOASES { + + /** Macro for switching on/off the end of the qpOASES namespace definition. */ + #define END_NAMESPACE_QPOASES } + + /** Macro for switching on/off the use of the qpOASES namespace. */ + #define USING_NAMESPACE_QPOASES using namespace qpOASES; + + /** Macro for switching on/off references to the qpOASES namespace. */ + #define REFER_NAMESPACE_QPOASES qpOASES:: + +#endif + + +/** Macro for accessing the Cholesky factor R. */ +#define RR( I,J ) R[(I)+nV*(J)] + +/** Macro for accessing the orthonormal matrix Q of the QT factorisation. */ +#define QQ( I,J ) Q[(I)+nV*(J)] + +/** Macro for accessing the triangular matrix T of the QT factorisation. */ +#define TT( I,J ) T[(I)*sizeT+(J)] + + + +BEGIN_NAMESPACE_QPOASES + + +/** Defines real_t for facilitating switching between double and float. */ +#ifdef __USE_SINGLE_PRECISION__ +typedef float real_t; +#else +typedef double real_t; +#endif /* __USE_SINGLE_PRECISION__ */ + + +/** Summarises all possible logical values. */ +enum BooleanType +{ + BT_FALSE, /**< Logical value for "false". */ + BT_TRUE /**< Logical value for "true". */ +}; + + +/** Summarises all possible print levels. Print levels are used to describe + * the desired amount of output during runtime of qpOASES. */ +enum PrintLevel +{ + PL_DEBUG_ITER = -2, /**< Full tabular debugging output. */ + PL_TABULAR, /**< Normal tabular output. */ + PL_NONE, /**< No output. */ + PL_LOW, /**< Print error messages only. */ + PL_MEDIUM, /**< Print error and warning messages as well as concise info messages. */ + PL_HIGH /**< Print all messages with full details. */ +}; + + +/** Defines visibility status of a message. */ +enum VisibilityStatus +{ + VS_HIDDEN, /**< Message not visible. */ + VS_VISIBLE /**< Message visible. */ +}; + + +/** Summarises all possible states of the (S)QProblem(B) object during the +solution process of a QP sequence. */ +enum QProblemStatus +{ + QPS_NOTINITIALISED, /**< QProblem object is freshly instantiated or reset. */ + QPS_PREPARINGAUXILIARYQP, /**< An auxiliary problem is currently setup, either at the very beginning + * via an initial homotopy or after changing the QP matrices. */ + QPS_AUXILIARYQPSOLVED, /**< An auxilary problem was solved, either at the very beginning + * via an initial homotopy or after changing the QP matrices. */ + QPS_PERFORMINGHOMOTOPY, /**< A homotopy according to the main idea of the online active + * set strategy is performed. */ + QPS_HOMOTOPYQPSOLVED, /**< An intermediate QP along the homotopy path was solved. */ + QPS_SOLVED /**< The solution of the actual QP was found. */ +}; + + +/** Summarises all possible types of the QP's Hessian matrix. */ +enum HessianType +{ + HST_ZERO, /**< Hessian is zero matrix (i.e. LP formulation). */ + HST_IDENTITY, /**< Hessian is identity matrix. */ + HST_POSDEF, /**< Hessian is (strictly) positive definite. */ + HST_POSDEF_NULLSPACE, /**< Hessian is positive definite on null space of active bounds/constraints. */ + HST_SEMIDEF, /**< Hessian is positive semi-definite. */ + HST_INDEF, /**< Hessian is indefinite. */ + HST_UNKNOWN /**< Hessian type is unknown. */ +}; + + +/** Summarises all possible types of bounds and constraints. */ +enum SubjectToType +{ + ST_UNBOUNDED, /**< Bound/constraint is unbounded. */ + ST_BOUNDED, /**< Bound/constraint is bounded but not fixed. */ + ST_EQUALITY, /**< Bound/constraint is fixed (implicit equality bound/constraint). */ + ST_DISABLED, /**< Bound/constraint is disabled (i.e. ignored when solving QP). */ + ST_UNKNOWN /**< Type of bound/constraint unknown. */ +}; + + +/** Summarises all possible states of bounds and constraints. */ +enum SubjectToStatus +{ + ST_LOWER = -1, /**< Bound/constraint is at its lower bound. */ + ST_INACTIVE, /**< Bound/constraint is inactive. */ + ST_UPPER, /**< Bound/constraint is at its upper bound. */ + ST_INFEASIBLE_LOWER, /**< (to be documented) */ + ST_INFEASIBLE_UPPER, /**< (to be documented) */ + ST_UNDEFINED /**< Status of bound/constraint undefined. */ +}; + +/** + * \brief Stores internal information for tabular (debugging) output. + * + * Struct storing internal information for tabular (debugging) output + * when using the (S)QProblem(B) objects. + * + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2013-2014 + */ +struct TabularOutput { + int idxAddB; /**< Index of bound that has been added to working set. */ + int idxRemB; /**< Index of bound that has been removed from working set. */ + int idxAddC; /**< Index of constraint that has been added to working set. */ + int idxRemC; /**< Index of constraint that has been removed from working set. */ + int excAddB; /**< Flag indicating whether a bound has been added to working set to keep a regular projected Hessian. */ + int excRemB; /**< Flag indicating whether a bound has been removed from working set to keep a regular projected Hessian. */ + int excAddC; /**< Flag indicating whether a constraint has been added to working set to keep a regular projected Hessian. */ + int excRemC; /**< Flag indicating whether a constraint has been removed from working set to keep a regular projected Hessian. */ +}; + + + +/** + * \brief Struct containing the variable header for mat file. + * + * Struct storing the header of a variable to be stored in + * Matlab's binary format (using the outdated Level 4 variant + * for simplictiy). + * + * Note, this code snippet has been inspired from the document + * "Matlab(R) MAT-file Format, R2013b" by MathWorks + * + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2013-2014 + */ +typedef struct { + long numericFormat; /**< Flag indicating numerical format. */ + long nRows; /**< Number of rows. */ + long nCols; /**< Number of rows. */ + long imaginaryPart; /**< (to be documented) */ + long nCharName; /**< Number of character in name. */ +} MatMatrixHeader; + + + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_TYPES_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/UnitTesting.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/UnitTesting.hpp new file mode 100644 index 00000000000..96ade4b8bb2 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/UnitTesting.hpp @@ -0,0 +1,79 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/UnitTesting.hpp + * \author Hans Joachim Ferreau + * \version 3.0 + * \date 2014 + * + * Definition of auxiliary functions/macros for unit testing. + */ + + +#ifndef QPOASES_UNIT_TESTING_HPP +#define QPOASES_UNIT_TESTING_HPP + + +#ifndef TEST_TOL_FACTOR +#define TEST_TOL_FACTOR 1 +#endif + + +/** Return value for tests that passed. */ +#define TEST_PASSED 0 + +/** Return value for tests that failed. */ +#define TEST_FAILED 1 + +/** Return value for tests that could not run due to missing external data. */ +#define TEST_DATA_NOT_FOUND 99 + + +/** Macro verifying that two numerical values are equal in order to pass unit test. */ +#define QPOASES_TEST_FOR_EQUAL( x,y ) if ( REFER_NAMESPACE_QPOASES isEqual( (x),(y) ) == BT_FALSE ) { return TEST_FAILED; } + +/** Macro verifying that two numerical values are close to each other in order to pass unit test. */ +#define QPOASES_TEST_FOR_NEAR( x,y ) if ( REFER_NAMESPACE_QPOASES getAbs((x)-(y)) / REFER_NAMESPACE_QPOASES getMax( 1.0,REFER_NAMESPACE_QPOASES getAbs(x) ) >= 1e-10 ) { return TEST_FAILED; } + +/** Macro verifying that first quantity is lower or equal than second one in order to pass unit test. */ +#define QPOASES_TEST_FOR_TOL( x,tol ) if ( (x) > (tol)*(TEST_TOL_FACTOR) ) { return TEST_FAILED; } + +/** Macro verifying that a logical expression holds in order to pass unit test. */ +#define QPOASES_TEST_FOR_TRUE( x ) if ( (x) == false ) { return TEST_FAILED; } + + + +BEGIN_NAMESPACE_QPOASES + + +END_NAMESPACE_QPOASES + + +#endif /* UNIT_TESTING */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Utils.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Utils.hpp new file mode 100644 index 00000000000..ddef94320b6 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Utils.hpp @@ -0,0 +1,370 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/Utils.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of some utility functions for working with qpOASES. + */ + + +#ifndef QPOASES_UTILS_HPP +#define QPOASES_UTILS_HPP + + +#include + + +#ifdef __NO_SNPRINTF__ + #if (!defined(_MSC_VER)) || defined(__DSPACE__) + /* If snprintf is not available, provide an empty implementation... */ + int snprintf( char* s, size_t n, const char* format, ... ); + #else + /* ... or substitute snprintf by _snprintf for Microsoft compilers. */ + #define snprintf _snprintf + #endif +#endif /* __NO_SNPRINTF__ */ + + +BEGIN_NAMESPACE_QPOASES + + +/** Prints a (possibly named) vector. + * \return SUCCESSFUL_RETURN */ +returnValue print( const real_t* const v, /**< Vector to be printed. */ + int n, /**< Length of vector. */ + const char* name = 0 /**< Name of vector. */ + ); + +/** Prints a (possibly named) permuted vector. + * \return SUCCESSFUL_RETURN */ +returnValue print( const real_t* const v, /**< Vector to be printed. */ + int n, /**< Length of vector. */ + const int* const V_idx, /**< Pemutation vector. */ + const char* name = 0 /**< Name of vector. */ + ); + +/** Prints a (possibly named) matrix. + * \return SUCCESSFUL_RETURN */ +returnValue print( const real_t* const M, /**< Matrix to be printed. */ + int nrow, /**< Row number of matrix. */ + int ncol, /**< Column number of matrix. */ + const char* name = 0 /**< Name of matrix. */ + ); + +/** Prints a (possibly named) permuted matrix. + * \return SUCCESSFUL_RETURN */ +returnValue print( const real_t* const M, /**< Matrix to be printed. */ + int nrow, /**< Row number of matrix. */ + int ncol , /**< Column number of matrix. */ + const int* const ROW_idx, /**< Row pemutation vector. */ + const int* const COL_idx, /**< Column pemutation vector. */ + const char* name = 0 /**< Name of matrix. */ + ); + +/** Prints a (possibly named) index array. + * \return SUCCESSFUL_RETURN */ +returnValue print( const int* const index, /**< Index array to be printed. */ + int n, /**< Length of index array. */ + const char* name = 0 /**< Name of index array. */ + ); + + +/** Prints a string to desired output target (useful also for MATLAB output!). + * \return SUCCESSFUL_RETURN */ +returnValue myPrintf( const char* s /**< String to be written. */ + ); + + +/** Prints qpOASES copyright notice. + * \return SUCCESSFUL_RETURN */ +returnValue printCopyrightNotice( ); + + +/** Reads a real_t matrix from file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE */ +returnValue readFromFile( real_t* data, /**< Matrix to be read from file. */ + int nrow, /**< Row number of matrix. */ + int ncol, /**< Column number of matrix. */ + const char* datafilename /**< Data file name. */ + ); + +/** Reads a real_t vector from file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE */ +returnValue readFromFile( real_t* data, /**< Vector to be read from file. */ + int n, /**< Length of vector. */ + const char* datafilename /**< Data file name. */ + ); + +/** Reads an integer (column) vector from file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE */ +returnValue readFromFile( int* data, /**< Vector to be read from file. */ + int n, /**< Length of vector. */ + const char* datafilename /**< Data file name. */ + ); + + +/** Writes a real_t matrix into a file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ +returnValue writeIntoFile( const real_t* const data, /**< Matrix to be written into file. */ + int nrow, /**< Row number of matrix. */ + int ncol, /**< Column number of matrix. */ + const char* datafilename, /**< Data file name. */ + BooleanType append = BT_FALSE /**< Indicates if data shall be appended if the file already exists (otherwise it is overwritten). */ + ); + +/** Writes a real_t vector into a file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ +returnValue writeIntoFile( const real_t* const data, /**< Vector to be written into file. */ + int n, /**< Length of vector. */ + const char* datafilename, /**< Data file name. */ + BooleanType append = BT_FALSE /**< Indicates if data shall be appended if the file already exists (otherwise it is overwritten). */ + ); + +/** Writes an integer (column) vector into a file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ +returnValue writeIntoFile( const int* const integer, /**< Integer vector to be written into file. */ + int n, /**< Length of vector. */ + const char* datafilename, /**< Data file name. */ + BooleanType append = BT_FALSE /**< Indicates if integer shall be appended if the file already exists (otherwise it is overwritten). */ + ); + +/** Writes a real_t matrix/vector into a Matlab binary file. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS + RET_UNABLE_TO_WRITE_FILE */ +returnValue writeIntoMatFile( FILE* const matFile, /**< Pointer to Matlab binary file. */ + const real_t* const data, /**< Data to be written into file. */ + int nRows, /**< Row number of matrix. */ + int nCols, /**< Column number of matrix. */ + const char* name /**< Matlab name of matrix/vector to be stored. */ + ); + +/** Writes in integer matrix/vector into a Matlab binary file. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS + RET_UNABLE_TO_WRITE_FILE */ +returnValue writeIntoMatFile( FILE* const matFile, /**< Pointer to Matlab binary file. */ + const int* const data, /**< Data to be written into file. */ + int nRows, /**< Row number of matrix. */ + int nCols, /**< Column number of matrix. */ + const char* name /**< Matlab name of matrix/vector to be stored. */ + ); + + +/** Returns the current system time. + * \return current system time */ +real_t getCPUtime( ); + + +/** Returns the N-norm of a vector. + * \return >= 0.0: successful */ +real_t getNorm( const real_t* const v, /**< Vector. */ + int n, /**< Vector's dimension. */ + int type = 2 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ); + + +/** Tests whether two real_t-valued arguments are (numerically) equal. + * \return BT_TRUE: arguments differ not more than TOL \n + BT_FALSE: arguments differ more than TOL */ +inline BooleanType isEqual( real_t x, /**< First real number. */ + real_t y, /**< Second real number. */ + real_t TOL = ZERO /**< Tolerance for comparison. */ + ); + + +/** Tests whether a real-valued argument is (numerically) zero. + * \return BT_TRUE: argument differs from 0.0 not more than TOL \n + BT_FALSE: argument differs from 0.0 more than TOL */ +inline BooleanType isZero( real_t x, /**< Real number. */ + real_t TOL = ZERO /**< Tolerance for comparison. */ + ); + + +/** Returns sign of a real-valued argument. + * \return 1.0: argument is non-negative \n + -1.0: argument is negative */ +inline real_t getSign( real_t arg /**< real-valued argument whose sign is to be determined. */ + ); + + +/** Returns maximum of two integers. + * \return Maximum of two integers */ +inline int getMax( int x, /**< First integer. */ + int y /**< Second integer. */ + ); + +/** Returns minimum of two integers. + * \return Minimum of two integers */ +inline int getMin( int x, /**< First integer. */ + int y /**< Second integer. */ + ); + + +/** Returns maximum of two reals. + * \return Maximum of two reals */ +inline real_t getMax( real_t x, /**< First real number. */ + real_t y /**< Second real number. */ + ); + +/** Returns minimum of two reals. + * \return Minimum of two reals */ +inline real_t getMin( real_t x, /**< First real number. */ + real_t y /**< Second real number. */ + ); + +/** Returns the absolute value of a real number. + * \return Absolute value of a real number */ +inline real_t getAbs( real_t x /**< Real number. */ + ); + +/** Returns the square-root of a real number. + * \return Square-root of a real number */ +inline real_t getSqrt( real_t x /**< Non-negative real number. */ + ); + + +/** Computes "residual" of KKT system. */ +void getKKTResidual( int nV, /**< Number of variables. */ + int nC, /**< Number of constraints. */ + const real_t* const H, /**< Hessian matrix. */ + const real_t* const g, /**< Sequence of gradient vectors. */ + const real_t* const A, /**< Constraint matrix. */ + const real_t* const lb, /**< Sequence of lower bound vectors (on variables). */ + const real_t* const ub, /**< Sequence of upper bound vectors (on variables). */ + const real_t* const lbA, /**< Sequence of lower constraints' bound vectors. */ + const real_t* const ubA, /**< Sequence of upper constraints' bound vectors. */ + const real_t* const x, /**< Sequence of primal trial vectors. */ + const real_t* const y, /**< Sequence of dual trial vectors. */ + real_t& stat, /**< Maximum value of stationarity condition residual. */ + real_t& feas, /**< Maximum value of primal feasibility violation. */ + real_t& cmpl /**< Maximum value of complementarity residual. */ + ); + +/** Computes "residual" of KKT system (for simply bounded QPs). */ +void getKKTResidual( int nV, /**< Number of variables. */ + const real_t* const H, /**< Hessian matrix. */ + const real_t* const g, /**< Sequence of gradient vectors. */ + const real_t* const lb, /**< Sequence of lower bound vectors (on variables). */ + const real_t* const ub, /**< Sequence of upper bound vectors (on variables). */ + const real_t* const x, /**< Sequence of primal trial vectors. */ + const real_t* const y, /**< Sequence of dual trial vectors. */ + real_t& stat, /**< Maximum value of stationarity condition residual. */ + real_t& feas, /**< Maximum value of primal feasibility violation. */ + real_t& cmpl /**< Maximum value of complementarity residual. */ + ); + + +/** Writes a value of BooleanType into a string. + * \return SUCCESSFUL_RETURN */ +returnValue convertBooleanTypeToString( BooleanType value, /**< Value to be written. */ + char* const string /**< Input: String of sufficient size, \n + Output: String containing value. */ + ); + +/** Writes a value of SubjectToStatus into a string. + * \return SUCCESSFUL_RETURN */ +returnValue convertSubjectToStatusToString( SubjectToStatus value, /**< Value to be written. */ + char* const string /**< Input: String of sufficient size, \n + Output: String containing value. */ + ); + +/** Writes a value of PrintLevel into a string. + * \return SUCCESSFUL_RETURN */ +returnValue convertPrintLevelToString( PrintLevel value, /**< Value to be written. */ + char* const string /**< Input: String of sufficient size, \n + Output: String containing value. */ + ); + + +/** Converts a returnValue from an (S)QProblem(B) object into a more + * simple status flag. + * + * \return 0: QP problem solved + * 1: QP could not be solved within given number of iterations + * -1: QP could not be solved due to an internal error + * -2: QP is infeasible (and thus could not be solved) + * -3: QP is unbounded (and thus could not be solved) + */ +int getSimpleStatus( returnValue returnvalue, /**< ReturnValue to be analysed. */ + BooleanType doPrintStatus = BT_FALSE /**< Flag indicating whether simple status shall be printed to screen. */ + ); + + +/** Normalises QP constraints. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +returnValue normaliseConstraints( int nV, /**< Number of variables. */ + int nC, /**< Number of constraints. */ + real_t* A, /**< Input: Constraint matrix, \n + Output: Normalised constraint matrix. */ + real_t* lbA, /**< Input: Constraints' lower bound vector, \n + Output: Normalised constraints' lower bound vector. */ + real_t* ubA, /**< Input: Constraints' upper bound vector, \n + Output: Normalised constraints' upper bound vector. */ + int type = 1 /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ); + + +#ifdef __DEBUG__ +/** Writes matrix with given dimension into specified file. */ +extern "C" void gdb_printmat( const char *fname, /**< File name. */ + real_t *M, /**< Matrix to be written. */ + int n, /**< Number of rows. */ + int m, /**< Number of columns. */ + int ldim /**< Leading dimension. */ + ); +#endif /* __DEBUG__ */ + + +#if defined(__DSPACE__) || defined(__XPCTARGET__) +extern "C" void __cxa_pure_virtual( void ); +#endif /* __DSPACE__ || __XPCTARGET__*/ + + + +END_NAMESPACE_QPOASES + + +#include + +#endif /* QPOASES_UTILS_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Utils.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Utils.ipp new file mode 100644 index 00000000000..3d89822b8b9 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/Utils.ipp @@ -0,0 +1,174 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + + +/** + * \file include/qpOASES/Utils.ipp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Implementation of some inlined utilities for working with the different QProblem classes. + */ + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/* + * i s E q u a l + */ +inline BooleanType isEqual( real_t x, + real_t y, + real_t TOL + ) +{ + if ( getAbs(x-y) <= TOL ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * i s Z e r o + */ +inline BooleanType isZero( real_t x, + real_t TOL + ) +{ + if ( getAbs(x) <= TOL ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * g e t S i g n + */ +inline real_t getSign( real_t arg + ) +{ + if ( arg >= 0.0 ) + return 1.0; + else + return -1.0; +} + + + +/* + * g e t M a x + */ +inline int getMax( int x, + int y + ) +{ + return (yx) ? x : y; +} + + + +/* + * g e t M a x + */ +inline real_t getMax( real_t x, + real_t y + ) +{ + #ifdef __NO_FMATH__ + return (yx) ? x : y; + #else + return (y>x) ? x : y; + //return fmin(x,y); /* seems to be slower */ + #endif +} + + +/* + * g e t A b s + */ +inline real_t getAbs( real_t x + ) +{ + #ifdef __NO_FMATH__ + return (x>=0.0) ? x : -x; + #else + return fabs(x); + #endif +} + + +/* + * g e t S q r t + */ +inline real_t getSqrt( real_t x + ) +{ + #ifdef __NO_FMATH__ + return sqrt(x); /* put your custom sqrt-replacement here */ + #else + return sqrt(x); + #endif +} + + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/OQPinterface.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/OQPinterface.hpp new file mode 100644 index 00000000000..4623aa32840 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/OQPinterface.hpp @@ -0,0 +1,250 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/extras/OQPinterface.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.0 + * \date 2007-2014 + * + * Declaration of an interface comprising several utility functions + * for solving test problems from the Online QP Benchmark Collection + * (This collection is no longer maintained, see + * http://www.qpOASES.org/onlineQP for a backup). + */ + + +#ifndef QPOASES_OQPINTERFACE_HPP +#define QPOASES_OQPINTERFACE_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** Reads dimensions of an Online QP Benchmark problem from file. + * + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_READ_FILE \n + RET_FILEDATA_INCONSISTENT */ +returnValue readOQPdimensions( const char* path, /**< Full path of the data files (without trailing slash!). */ + int& nQP, /**< Output: Number of QPs. */ + int& nV, /**< Output: Number of variables. */ + int& nC, /**< Output: Number of constraints. */ + int& nEC /**< Output: Number of equality constraints. */ + ); + +/** Reads data of an Online QP Benchmark problem from file. + * This function allocates the required memory for all data; after successfully calling it, + * you have to free this memory yourself! + * + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_UNABLE_TO_READ_FILE \n + RET_FILEDATA_INCONSISTENT */ +returnValue readOQPdata( const char* path, /**< Full path of the data files (without trailing slash!). */ + int& nQP, /**< Output: Number of QPs. */ + int& nV, /**< Output: Number of variables. */ + int& nC, /**< Output: Number of constraints. */ + int& nEC, /**< Output: Number of equality constraints. */ + real_t** H, /**< Output: Hessian matrix. */ + real_t** g, /**< Output: Sequence of gradient vectors. */ + real_t** A, /**< Output: Constraint matrix. */ + real_t** lb, /**< Output: Sequence of lower bound vectors (on variables). */ + real_t** ub, /**< Output: Sequence of upper bound vectors (on variables). */ + real_t** lbA, /**< Output: Sequence of lower constraints' bound vectors. */ + real_t** ubA, /**< Output: Sequence of upper constraints' bound vectors. */ + real_t** xOpt, /**< Output: Sequence of primal solution vectors + * (not read if a null pointer is passed). */ + real_t** yOpt, /**< Output: Sequence of dual solution vectors + * (not read if a null pointer is passed). */ + real_t** objOpt /**< Output: Sequence of optimal objective function values + * (not read if a null pointer is passed). */ + ); + + +/** Solves an Online QP Benchmark problem as specified by the arguments. + * The maximum deviations from the given optimal solution as well as the + * maximum CPU time to solve each QP are determined. + * + * Note: This variant is outdated and only kept to ensure + * backwards-compatibility! + * + * \return SUCCESSFUL_RETURN \n + RET_BENCHMARK_ABORTED */ +returnValue solveOQPbenchmark( int nQP, /**< Number of QPs. */ + int nV, /**< Number of variables. */ + int nC, /**< Number of constraints. */ + int nEC, /**< Number of equality constraints. */ + const real_t* const _H, /**< Hessian matrix. */ + const real_t* const g, /**< Sequence of gradient vectors. */ + const real_t* const _A, /**< Constraint matrix. */ + const real_t* const lb, /**< Sequence of lower bound vectors (on variables). */ + const real_t* const ub, /**< Sequence of upper bound vectors (on variables). */ + const real_t* const lbA, /**< Sequence of lower constraints' bound vectors. */ + const real_t* const ubA, /**< Sequence of upper constraints' bound vectors. */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + const Options& options, /**< QP solver options to be used while solving benchmark problems. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Maximum number of performed working set recalculations. */ + real_t& maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t& maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t& maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t& maxComplementarity /**< Output: Maximum residual of complementarity condition. */ + ); + +/** Solves an Online QP Benchmark problem as specified by the arguments. + * The maximum deviations from the given optimal solution as well as the + * maximum CPU time to solve each QP are determined. + * + * \return SUCCESSFUL_RETURN \n + RET_BENCHMARK_ABORTED */ +returnValue solveOQPbenchmark( int nQP, /**< Number of QPs. */ + int nV, /**< Number of variables. */ + int nC, /**< Number of constraints. */ + int nEC, /**< Number of equality constraints. */ + const real_t* const _H, /**< Hessian matrix. */ + const real_t* const g, /**< Sequence of gradient vectors. */ + const real_t* const _A, /**< Constraint matrix. */ + const real_t* const lb, /**< Sequence of lower bound vectors (on variables). */ + const real_t* const ub, /**< Sequence of upper bound vectors (on variables). */ + const real_t* const lbA, /**< Sequence of lower constraints' bound vectors. */ + const real_t* const ubA, /**< Sequence of upper constraints' bound vectors. */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + BooleanType useHotstarts, /**< Shall QP solution be hotstarted? */ + const Options& options, /**< QP solver options to be used while solving benchmark problems. */ + int maxAllowedNWSR, /**< Maximum number of working set recalculations to be performed. */ + real_t& maxNWSR, /**< Output: Maximum number of performed working set recalculations. */ + real_t& avgNWSR, /**< Output: Average number of performed working set recalculations. */ + real_t& maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t& avgCPUtime, /**< Output: Average CPU time required for solving each QP. */ + real_t& maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t& maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t& maxComplementarity /**< Output: Maximum residual of complementarity condition. */ + ); + + +/** Solves an Online QP Benchmark problem (without constraints) as specified + * by the arguments. The maximum deviations from the given optimal solution + * as well as the maximum CPU time to solve each QP are determined. + * + * Note: This variant is outdated and only kept to ensure + * backwards-compatibility! + * + * \return SUCCESSFUL_RETURN \n + RET_BENCHMARK_ABORTED */ +returnValue solveOQPbenchmark( int nQP, /**< Number of QPs. */ + int nV, /**< Number of variables. */ + const real_t* const _H, /**< Hessian matrix. */ + const real_t* const g, /**< Sequence of gradient vectors. */ + const real_t* const lb, /**< Sequence of lower bound vectors (on variables). */ + const real_t* const ub, /**< Sequence of upper bound vectors (on variables). */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + const Options& options, /**< QP solver options to be used while solving benchmark problems. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Maximum number of performed working set recalculations. */ + real_t& maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t& maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t& maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t& maxComplementarity /**< Output: Maximum residual of complementarity condition. */ + ); + +/** Solves an Online QP Benchmark problem (without constraints) as specified + * by the arguments. The maximum deviations from the given optimal solution + * as well as the maximum CPU time to solve each QP are determined. + * + * \return SUCCESSFUL_RETURN \n + RET_BENCHMARK_ABORTED */ +returnValue solveOQPbenchmark( int nQP, /**< Number of QPs. */ + int nV, /**< Number of variables. */ + const real_t* const _H, /**< Hessian matrix. */ + const real_t* const g, /**< Sequence of gradient vectors. */ + const real_t* const lb, /**< Sequence of lower bound vectors (on variables). */ + const real_t* const ub, /**< Sequence of upper bound vectors (on variables). */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + BooleanType useHotstarts, /**< Shall QP solution be hotstarted? */ + const Options& options, /**< QP solver options to be used while solving benchmark problems. */ + int maxAllowedNWSR, /**< Maximum number of working set recalculations to be performed. */ + real_t& maxNWSR, /**< Output: Maximum number of performed working set recalculations. */ + real_t& avgNWSR, /**< Output: Average number of performed working set recalculations. */ + real_t& maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t& avgCPUtime, /**< Output: Average CPU time required for solving each QP. */ + real_t& maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t& maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t& maxComplementarity /**< Output: Maximum residual of complementarity condition. */ + ); + + +/** Runs an Online QP Benchmark problem and determines the maximum + * violation of the KKT optimality conditions as well as the + * maximum CPU time to solve each QP. + * + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_READ_BENCHMARK \n + RET_BENCHMARK_ABORTED */ +returnValue runOQPbenchmark( const char* path, /**< Full path of the benchmark files (without trailing slash!). */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + const Options& options, /**< QP solver options to be used while solving benchmark problems. */ + int& nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Maximum number of performed working set recalculations. */ + real_t& maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t& maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t& maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t& maxComplementarity /**< Output: Maximum residual of complementarity condition. */ + ); + + +/** Runs an Online QP Benchmark problem and determines the maximum + * violation of the KKT optimality conditions as well as the + * maximum and average number of iterations and CPU time to solve + * each QP. + * + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_READ_BENCHMARK \n + RET_BENCHMARK_ABORTED */ +returnValue runOQPbenchmark( const char* path, /**< Full path of the benchmark files (without trailing slash!). */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + BooleanType useHotstarts, /**< Shall QP solution be hotstarted? */ + const Options& options, /**< QP solver options to be used while solving benchmark problems. */ + int maxAllowedNWSR, /**< Maximum number of working set recalculations to be performed. */ + real_t& maxNWSR, /**< Output: Maximum number of performed working set recalculations. */ + real_t& avgNWSR, /**< Output: Average number of performed working set recalculations. */ + real_t& maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t& avgCPUtime, /**< Output: Average CPU time required for solving each QP. */ + real_t& maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t& maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t& maxComplementarity /**< Output: Maximum residual of complementarity condition. */ + ); + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_OQPINTERFACE_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/SolutionAnalysis.hpp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/SolutionAnalysis.hpp new file mode 100644 index 00000000000..ad625807495 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/SolutionAnalysis.hpp @@ -0,0 +1,155 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/extras/SolutionAnalysis.hpp + * \author Hans Joachim Ferreau (thanks to Boris Houska) + * \version 3.0 + * \date 2008-2014 + * + * Declaration of the SolutionAnalysis class designed to perform + * additional analysis after solving a QP with qpOASES. + */ + + +#ifndef QPOASES_SOLUTIONANALYSIS_HPP +#define QPOASES_SOLUTIONANALYSIS_HPP + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Provides additional tools for analysing QP solutions. + * + * This class is intended to provide additional tools for analysing + * a QP solution obtained with qpOASES. + * + * \author Hans Joachim Ferreau (thanks to Boris Houska) + * \version 3.0 + * \date 2007-2014 + */ +class SolutionAnalysis +{ + /* + * PUBLIC MEMBER FUNCTIONS + */ + public: + /** Default constructor. */ + SolutionAnalysis( ); + + /** Copy constructor (deep copy). */ + SolutionAnalysis( const SolutionAnalysis& rhs /**< Rhs object. */ + ); + + /** Destructor. */ + ~SolutionAnalysis( ); + + /** Assignment operator (deep copy). */ + SolutionAnalysis& operator=( const SolutionAnalysis& rhs /**< Rhs object. */ + ); + + + /** Determines the maximum violation of the KKT optimality conditions + * of the current iterate within the QProblemB object. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_ANALYSE_QPROBLEM */ + returnValue getMaxKKTviolation( QProblemB* qp, /**< QProblemB to be analysed. */ + real_t& maxKKTviolation /**< OUTPUT: maximum violation of the KKT conditions. */ + ) const; + + /** Determines the maximum violation of the KKT optimality conditions + * of the current iterate within the QProblem object. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_ANALYSE_QPROBLEM */ + returnValue getMaxKKTviolation( QProblem* qp, /**< QProblem to be analysed. */ + real_t& maxKKTviolation /**< OUTPUT: maximum violation of the KKT conditions. */ + ) const; + + /** Determines the maximum violation of the KKT optimality conditions + * of the current iterate within the SQProblem object. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_ANALYSE_QPROBLEM */ + returnValue getMaxKKTviolation( SQProblem* qp, /**< SQProblem to be analysed. */ + real_t& maxKKTviolation /**< OUTPUT: maximum violation of the KKT conditions. */ + ) const; + + + /** Computes the variance-covariance matrix of the QP output for uncertain + inputs. + * \return SUCCESSFUL_RETURN \n + RET_HOTSTART_FAILED \n + RET_STEPDIRECTION_FAILED_TQ \n + RET_STEPDIRECTION_FAILED_CHOLESKY */ + returnValue getVarianceCovariance( QProblemB* qp, /**< QProblemB to be analysed. */ + real_t* g_b_bA_VAR, /**< INPUT : Variance-covariance of g, the bounds lb and ub, and lbA and ubA respectively. Dimension: 2nV x 2nV */ + real_t* Primal_Dual_VAR /**< OUTPUT: The result for the variance-covariance of the primal and dual variables. Dimension: 2nV x 2nV */ + ) const; + + /** Computes the variance-covariance matrix of the QP output for uncertain + inputs. + * \return SUCCESSFUL_RETURN \n + RET_HOTSTART_FAILED \n + RET_STEPDIRECTION_FAILED_TQ \n + RET_STEPDIRECTION_FAILED_CHOLESKY */ + returnValue getVarianceCovariance( QProblem* qp, /**< QProblem to be analysed. */ + real_t* g_b_bA_VAR, /**< INPUT : Variance-covariance of g, the bounds lb and ub, and lbA and ubA respectively. Dimension: (2nV+nC) x (2nV+nC) */ + real_t* Primal_Dual_VAR /**< OUTPUT: The result for the variance-covariance of the primal and dual variables. Dimension: (2nV+nC) x (2nV+nC) */ + ) const; + + /** Computes the variance-covariance matrix of the QP output for uncertain + inputs. + * \return SUCCESSFUL_RETURN \n + RET_HOTSTART_FAILED \n + RET_STEPDIRECTION_FAILED_TQ \n + RET_STEPDIRECTION_FAILED_CHOLESKY */ + returnValue getVarianceCovariance( SQProblem* qp, /**< SQProblem to be analysed. */ + real_t* g_b_bA_VAR, /**< INPUT : Variance-covariance of g, the bounds lb and ub, and lbA and ubA respectively. Dimension: (2nV+nC) x (2nV+nC) */ + real_t* Primal_Dual_VAR /**< OUTPUT: The result for the variance-covariance of the primal and dual variables. Dimension: (2nV+nC) x (2nV+nC) */ + ) const; + + /** Checks if a direction of negative curvature shows up if we remove all bounds that just recently became active */ + + + /* + * PROTECTED MEMBER VARIABLES + */ + protected: + +}; + + +END_NAMESPACE_QPOASES + +#include + +#endif /* QPOASES_SOLUTIONANALYSIS_HPP */ + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/SolutionAnalysis.ipp b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/SolutionAnalysis.ipp new file mode 100644 index 00000000000..dc59a7e3d60 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/SolutionAnalysis.ipp @@ -0,0 +1,51 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES/extras/SolutionAnalysis.ipp + * \author Hans Joachim Ferreau (thanks to Boris Houska) + * \version 3.0 + * \date 2008-2014 + * + * Implementation of inlined member functions of the SolutionAnalysis class + * designed to perform additional analysis after solving a QP with qpOASES. + * + */ + + + +/***************************************************************************** + * P U B L I C * + *****************************************************************************/ + + +BEGIN_NAMESPACE_QPOASES + + +END_NAMESPACE_QPOASES + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/index.html b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/index.html new file mode 100644 index 00000000000..6cb3040f5aa --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/extras/index.html @@ -0,0 +1,10 @@ +qpOASES - Revision 198: /stable/3.0/include/qpOASES/extras + +

qpOASES - Revision 198: /stable/3.0/include/qpOASES/extras

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/index.html b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/index.html new file mode 100644 index 00000000000..7bc668d65bf --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/include/qpOASES/index.html @@ -0,0 +1,33 @@ +qpOASES - Revision 198: /stable/3.0/include/qpOASES + +

qpOASES - Revision 198: /stable/3.0/include/qpOASES

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/index.html b/3rdparty/qpOASES/qpOASES-3.0/index.html new file mode 100644 index 00000000000..f03255769ac --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/index.html @@ -0,0 +1,31 @@ +qpOASES - Revision 198: /stable/3.0 + +

qpOASES - Revision 198: /stable/3.0

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/index.html b/3rdparty/qpOASES/qpOASES-3.0/interfaces/index.html new file mode 100644 index 00000000000..70331be2a27 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/index.html @@ -0,0 +1,12 @@ +qpOASES - Revision 198: /stable/3.0/interfaces + +

qpOASES - Revision 198: /stable/3.0/interfaces

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1.mat b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1.mat new file mode 100644 index 0000000000000000000000000000000000000000..c0bd0d2ed4364ebaf2b16eeb1791b99510164d60 GIT binary patch literal 790 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQgHY2i?A@$QE)CwO)N=GQOM7; zQV7W?Rq#(PQBW{ZFtoHXwy-iZQZOA%wc4c5GZW8!2gYzq2v=QA4sbvTq}xwN{M9( rdcH+H=e>2)6PUUhjxboKF`MIYAV|YGPpF2pgrpzeL4oIZl~o4-!Xx*U literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1a.mat b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1a.mat new file mode 100644 index 0000000000000000000000000000000000000000..48c784fcb7c53eedc3b3124e3577f8d0822e1cb2 GIT binary patch literal 896 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQgHY2i?A@$QE)CwO)N=GQOM7; zQV7W?Rq#(PQBW{ZFtoHXwzM)dRWLFzFjpWIFfe-h@-r|n=m2rWoX5!t2^A%wc4c5GZW8!2gYzq2v=QA4sbvTq}xwN{M9( zdcH+H=e>2)6PUUhjxboKF`MIYAV|YGPpF2pgrpzeL4oIZl~o6%$pCIk2ePk#sWRk@ zvYq}`8INM7jZDluH5=M5@Ec?>oIk~G0n(=h*N5UdV9K1r)@ga{`O<04M`r+2CliB_ HDN`x{YE&BX literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1b.mat b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/example1b.mat new file mode 100644 index 0000000000000000000000000000000000000000..b45b4f74c6a935c350dac6de0673396f20801338 GIT binary patch literal 549 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQgHY2i?A@$QE)CwO)N=GQOM7; zQV7W?Rq#(PQBW{ZFtoHXwy-iXRWLFzFjpWIFfe-h@-r|n=m2rWoX5!t2^Gx%BvR z(CJ1KbpdXJ0|(fvIsP7&V$n literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/index.html b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/index.html new file mode 100644 index 00000000000..2e1a48f8c63 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/index.html @@ -0,0 +1,20 @@ +qpOASES - Revision 198: /stable/3.0/interfaces/matlab + +

qpOASES - Revision 198: /stable/3.0/interfaces/matlab

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/make.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/make.m new file mode 100644 index 00000000000..0970f19b2ff --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/make.m @@ -0,0 +1,238 @@ +function [] = make( varargin ) +%MAKE Compiles the Matlab interface of qpOASES. +% +%Type make to compile all interfaces that +% have been modified, +%type make clean to delete all compiled interfaces, +%type make clean all to first delete and then compile +% all interfaces, +%type make 'name' to compile only the interface with +% the given name (if it has been modified), +%type make 'opt' to compile all interfaces using the +% given compiler options. +% +%Copyright (C) 2013-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. + +%% +%% This file is part of qpOASES. +%% +%% qpOASES -- An Implementation of the Online Active Set Strategy. +%% Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%% Christian Kirches et al. All rights reserved. +%% +%% qpOASES is free software; you can redistribute it and/or +%% modify it under the terms of the GNU Lesser General Public +%% License as published by the Free Software Foundation; either +%% version 2.1 of the License, or (at your option) any later version. +%% +%% qpOASES is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%% See the GNU Lesser General Public License for more details. +%% +%% You should have received a copy of the GNU Lesser General Public +%% License along with qpOASES; if not, write to the Free Software +%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +%% + +%% +%% Filename: interfaces/matlab/make.m +%% Author: Hans Joachim Ferreau, Andreas Potschka, Christian Kirches +%% Version: 3.0 +%% Date: 2007-2014 +%% + + + %% consistency check + if ( exist( [pwd, '/make.m'],'file' ) == 0 ) + error( ['ERROR (',mfilename '.m): Run this make script directly within the directory', ... + '/interfaces/matlab, please.'] ); + end + + + if ( nargin > 2 ) + error( ['ERROR (',mfilename '.m): At most two make arguments supported!'] ); + else + [ doClean,fcnNames,userFlags ] = analyseMakeArguments( nargin,varargin ); + end + + + %% define compiler settings + QPOASESPATH = '../../'; + + DEBUGFLAGS = ' '; + %DEBUGFLAGS = ' -g CXXDEBUGFLAGS=''$CXXDEBUGFLAGS -Wall -pedantic -Wshadow'' '; + + IFLAGS = [ '-I. -I',QPOASESPATH,'include',' -I',QPOASESPATH,'src',' ' ]; + CPPFLAGS = [ IFLAGS, DEBUGFLAGS, '-largeArrayDims -D__cpluplus -D__MATLAB__ -D__SINGLE_OBJECT__',' ' ]; + defaultFlags = '-O -D__NO_COPYRIGHT__ '; %% -D__SUPPRESSANYOUTPUT__ + + if ( ispc == 0 ) + CPPFLAGS = [ CPPFLAGS, '-DLINUX ',' ' ]; + else + CPPFLAGS = [ CPPFLAGS, '-DWIN32 ',' ' ]; + end + + if ( isempty(userFlags) > 0 ) + CPPFLAGS = [ CPPFLAGS, defaultFlags,' ' ]; + else + CPPFLAGS = [ CPPFLAGS, userFlags,' ' ]; + end + + mexExt = eval('mexext'); + + + %% ensure copyright notice is displayed + if ~isempty( strfind( CPPFLAGS,'-D__NO_COPYRIGHT__' ) ) + printCopyrightNotice( ); + end + + + %% clean if desired + if ( doClean > 0 ) + + eval( 'delete *.o;' ); + eval( ['delete *.',mexExt,'*;'] ); + disp( [ 'INFO (',mfilename '.m): Cleaned all compiled files.'] ); + pause( 0.2 ); + + end + + + if ( ~isempty(userFlags) ) + disp( [ 'INFO (',mfilename '.m): Compiling all files with user-defined compiler flags (''',userFlags,''')...'] ); + end + + + %% call mex compiler + for ii=1:length(fcnNames) + + cmd = [ 'mex -output ', fcnNames{ii}, ' ', CPPFLAGS, [fcnNames{ii},'.cpp'] ]; + + if ( exist( [fcnNames{ii},'.',mexExt],'file' ) == 0 ) + + eval( cmd ); + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' successfully created.'] ); + + else + + % check modification time of source/Make files and compiled mex file + cppFile = dir( [pwd,'/',fcnNames{ii},'.cpp'] ); + cppFileTimestamp = getTimestamp( cppFile ); + + utilsFile = dir( [pwd,'/qpOASES_matlab_utils.cpp'] ); + utilsFileTimestamp = getTimestamp( utilsFile ); + + makeFile = dir( [pwd,'/make.m'] ); + makeFileTimestamp = getTimestamp( makeFile ); + + mexFile = dir( [pwd,'/',fcnNames{ii},'.',mexExt] ); + if ( isempty(mexFile) == 0 ) + mexFileTimestamp = getTimestamp( mexFile ); + else + mexFileTimestamp = 0; + end + + if ( ( cppFileTimestamp >= mexFileTimestamp ) || ... + ( utilsFileTimestamp >= mexFileTimestamp ) || ... + ( makeFileTimestamp >= mexFileTimestamp ) ) + eval( cmd ); + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' successfully created.'] ); + else + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' already exists.'] ); + end + + end + + end + + %% add qpOASES directory to path + path( path,pwd ); + +end + + +function [ doClean,fcnNames,userIFlags ] = analyseMakeArguments( nArgs,args ) + + doClean = 0; + fcnNames = []; + userIFlags = []; + + switch ( nArgs ) + + case 1 + if ( strcmp( args{1},'all' ) > 0 ) + fcnNames = { 'qpOASES','qpOASES_sequence' }; + elseif ( strcmp( args{1},'qpOASES' ) > 0 ) + fcnNames = { 'qpOASES' }; + elseif ( strcmp( args{1},'qpOASES_sequence' ) > 0 ) + fcnNames = { 'qpOASES_sequence' }; + elseif ( strcmp( args{1},'clean' ) > 0 ) + doClean = 1; + elseif ( strcmp( args{1}(1),'-' ) > 0 ) + % make clean all with user-specified compiler flags + userIFlags = args{1}; + doClean = 1; + fcnNames = { 'qpOASES','qpOASES_sequence' }; + else + error( ['ERROR (',mfilename '.m): Invalid first argument (''',args{1},''')!'] ); + end + + case 2 + if ( strcmp( args{1},'clean' ) > 0 ) + doClean = 1; + else + error( ['ERROR (',mfilename '.m): First argument must be ''clean'' if two arguments are provided!'] ); + end + + if ( strcmp( args{2},'all' ) > 0 ) + fcnNames = { 'qpOASES','qpOASES_sequence' }; + elseif ( strcmp( args{2},'qpOASES' ) > 0 ) + fcnNames = { 'qpOASES' }; + elseif ( strcmp( args{2},'qpOASES_sequence' ) > 0 ) + fcnNames = { 'qpOASES_sequence' }; + else + error( ['ERROR (',mfilename '.m): Invalid second argument (''',args{2},''')!'] ); + end + + otherwise + fcnNames = { 'qpOASES','qpOASES_sequence' }; + + end + +end + + +function [ timestamp ] = getTimestamp( dateString ) + + try + timestamp = dateString.datenum; + catch + timestamp = Inf; + end + +end + + +function [ ] = printCopyrightNotice( ) + + disp( ' ' ); + disp( 'qpOASES -- An Implementation of the Online Active Set Strategy.' ); + disp( 'Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka,' ); + disp( 'Christian Kirches et al. All rights reserved.' ); + disp( ' ' ); + disp( 'qpOASES is distributed under the terms of the' ); + disp( 'GNU Lesser General Public License 2.1 in the hope that it will be' ); + disp( 'useful, but WITHOUT ANY WARRANTY; without even the implied warranty' ); + disp( 'of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.' ); + disp( 'See the GNU Lesser General Public License for more details.' ); + disp( ' ' ); + disp( ' ' ); + +end + + +%% +%% end of file +%% diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES.cpp new file mode 100644 index 00000000000..0f1175b754e --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES.cpp @@ -0,0 +1,557 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/matlab/qpOASES.cpp + * \author Hans Joachim Ferreau, Alexander Buchner (thanks to Aude Perrin) + * \version 3.0 + * \date 2007-2014 + * + * Interface for Matlab(R) that enables to call qpOASES as a MEX function. + * + */ + + +#include + + +USING_NAMESPACE_QPOASES + + +#include "qpOASES_matlab_utils.hpp" + +/** initialise handle counter of QPInstance class */ +int QPInstance::s_nexthandle = 1; + +/** global pointer to QP objects */ +static std::vector g_instances; + +#include "qpOASES_matlab_utils.cpp" + + +/* + * q p O A S E S m e x _ c o n s t r a i n t s + */ +int qpOASESmex_constraints( int nV, int nC, int nP, + SymmetricMatrix *H, real_t* g, Matrix *A, + real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int nWSRin, real_t maxCpuTimeIn, + real_t* x0, Options* options, + int nOutputs, mxArray* plhs[], + double* guessedBounds, double* guessedConstraints + ) +{ + int nWSRout; + real_t maxCpuTimeOut; + + /* 1) Setup initial QP. */ + QProblem QP( nV,nC ); + QP.setOptions( *options ); + + /* 2) Solve initial QP. */ + returnValue returnvalue; + + Bounds bounds(nV); + Constraints constraints(nC); + if (guessedBounds != 0) { + for (int i = 0; i < nV; i++) { + if ( isEqual(guessedBounds[i],-1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_LOWER); + } else if ( isEqual(guessedBounds[i],1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_UPPER); + } else if ( isEqual(guessedBounds[i],0.0) == BT_TRUE ) { + bounds.setupBound(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of bounds!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + if (guessedConstraints != 0) { + for (int i = 0; i < nC; i++) { + if ( isEqual(guessedConstraints[i],-1.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_LOWER); + } else if ( isEqual(guessedConstraints[i],1.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_UPPER); + } else if ( isEqual(guessedConstraints[i],0.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of constraints!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + nWSRout = nWSRin; + maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + if (x0 == 0 && guessedBounds == 0 && guessedConstraints == 0) + returnvalue = QP.init( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut); + else + returnvalue = QP.init( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut, x0, 0, + guessedBounds != 0 ? &bounds : 0, + guessedConstraints != 0 ? &constraints : 0); + + /* 3) Solve remaining QPs and assign lhs arguments. */ + /* Set up pointers to the current QP vectors */ + real_t* g_current = g; + real_t* lb_current = lb; + real_t* ub_current = ub; + real_t* lbA_current = lbA; + real_t* ubA_current = ubA; + + /* Loop through QP sequence. */ + for ( int k=0; k 0 ) + { + /* update pointers to the current QP vectors */ + g_current = &(g[k*nV]); + if ( lb != 0 ) + lb_current = &(lb[k*nV]); + if ( ub != 0 ) + ub_current = &(ub[k*nV]); + if ( lbA != 0 ) + lbA_current = &(lbA[k*nC]); + if ( ubA != 0 ) + ubA_current = &(ubA[k*nC]); + + nWSRout = nWSRin; + maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + returnvalue = QP.hotstart( g_current,lb_current,ub_current,lbA_current,ubA_current, nWSRout,&maxCpuTimeOut ); + } + + /* write results into output vectors */ + obtainOutputs( k,&QP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,nV,nC ); + } + + //QP.writeQpDataIntoMatFile( "qpDataMat0.mat" ); + + return 0; +} + + + +/* + * q p O A S E S m e x _ b o u n d s + */ +int qpOASESmex_bounds( int nV, int nP, + SymmetricMatrix *H, real_t* g, + real_t* lb, real_t* ub, + int nWSRin, real_t maxCpuTimeIn, + real_t* x0, Options* options, + int nOutputs, mxArray* plhs[], + double* guessedBounds + ) +{ + int nWSRout; + real_t maxCpuTimeOut; + + /* 1) Setup initial QP. */ + QProblemB QP( nV ); + QP.setOptions( *options ); + + /* 2) Solve initial QP. */ + returnValue returnvalue; + + Bounds bounds(nV); + if (guessedBounds != 0) { + for (int i = 0; i < nV; i++) { + if ( isEqual(guessedBounds[i],-1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_LOWER); + } else if ( isEqual(guessedBounds[i],1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_UPPER); + } else if ( isEqual(guessedBounds[i],0.0) == BT_TRUE ) { + bounds.setupBound(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of bounds!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + nWSRout = nWSRin; + maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + if (x0 == 0 && guessedBounds == 0) + returnvalue = QP.init( H,g,lb,ub, nWSRout,&maxCpuTimeOut ); + else + returnvalue = QP.init( H,g,lb,ub, nWSRout,&maxCpuTimeOut, x0, 0, + guessedBounds != 0 ? &bounds : 0); + + /* 3) Solve remaining QPs and assign lhs arguments. */ + /* Set up pointers to the current QP vectors */ + real_t* g_current = g; + real_t* lb_current = lb; + real_t* ub_current = ub; + + /* Loop through QP sequence. */ + for ( int k=0; k 0 ) + { + /* update pointers to the current QP vectors */ + g_current = &(g[k*nV]); + if ( lb != 0 ) + lb_current = &(lb[k*nV]); + if ( ub != 0 ) + ub_current = &(ub[k*nV]); + + nWSRout = nWSRin; + maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + returnvalue = QP.hotstart( g_current,lb_current,ub_current, nWSRout,&maxCpuTimeOut ); + } + + /* write results into output vectors */ + obtainOutputs( k,&QP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,nV ); + } + + return 0; +} + + + +/* + * m e x F u n c t i o n + */ +void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] ) +{ + /* inputs */ + SymmetricMatrix *H=0; + Matrix *A=0; + real_t *g=0, *lb=0, *ub=0, *lbA=0, *ubA=0, *x0=0; + int H_idx, g_idx, A_idx, lb_idx, ub_idx, lbA_idx, ubA_idx, options_idx=-1, x0_idx=-1, auxInput_idx=-1; + + double *guessedBoundsAndConstraints = 0; + double *guessedBounds = 0, *guessedConstraints = 0; + + /* Setup default options */ + Options options; + options.printLevel = PL_LOW; + #ifdef __DEBUG__ + options.printLevel = PL_HIGH; + #endif + #ifdef __SUPPRESSANYOUTPUT__ + options.printLevel = PL_NONE; + #endif + + /* dimensions */ + unsigned int nV=0, nC=0, nP=0; + BooleanType isSimplyBoundedQp = BT_FALSE; + + /* sparse matrix indices and values */ + sparse_int_t *Hir = 0, *Hjc = 0, *Air = 0, *Ajc = 0; + real_t *Hv = 0, *Av = 0; + + /* I) CONSISTENCY CHECKS: */ + /* 1a) Ensure that qpOASES is called with a feasible number of input arguments. */ + if ( ( nrhs < 4 ) || ( nrhs > 9 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES' for further information." ); + return; + } + + /* 2) Check for proper number of output arguments. */ + if ( nlhs > 6 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): At most six output arguments are allowed: \n [x,fval,exitflag,iter,lambda,workingSet]!" ); + return; + } + if ( nlhs < 1 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): At least one output argument is required: [x,...]!" ); + return; + } + + + /* II) PREPARE RESPECTIVE QPOASES FUNCTION CALL: */ + /* Choose between QProblem and QProblemB object and assign the corresponding + * indices of the input pointer array in to order to access QP data correctly. */ + H_idx = 0; + g_idx = 1; + nV = (int)mxGetM( prhs[ H_idx ] ); /* row number of Hessian matrix */ + nP = (int)mxGetN( prhs[ g_idx ] ); /* number of columns of the gradient matrix (vectors series have to be stored columnwise!) */ + + if ( nrhs <= 6 ) + isSimplyBoundedQp = BT_TRUE; + else + isSimplyBoundedQp = BT_FALSE; + + + /* 0) Check whether options are specified .*/ + if ( isSimplyBoundedQp == BT_TRUE ) + { + if ( ( nrhs >= 5 ) && ( !mxIsEmpty(prhs[4]) ) && ( mxIsStruct(prhs[4]) ) ) + options_idx = 4; + } + else + { + /* Consistency check */ + if ( ( !mxIsEmpty(prhs[4]) ) && ( mxIsStruct(prhs[4]) ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Fifth input argument must not be a struct when solving QP with general constraints!\nType 'help qpOASES' for further information." ); + return; + } + + if ( ( nrhs >= 8 ) && ( !mxIsEmpty(prhs[7]) ) && ( mxIsStruct(prhs[7]) ) ) + options_idx = 7; + } + + // Is the third argument constraint Matrix A? + int numberOfColumns = (int)mxGetN(prhs[2]); + + /* 1) Simply bounded QP. */ + if ( ( isSimplyBoundedQp == BT_TRUE ) || + ( ( numberOfColumns == 1 ) && ( nV != 1 ) ) ) + { + lb_idx = 2; + ub_idx = 3; + + if ( ( nrhs >= 6 ) && ( !mxIsEmpty(prhs[5]) ) ) + { + /* auxInput specified */ + if ( mxIsStruct(prhs[5]) ) + { + auxInput_idx = 5; + x0_idx = -1; + } + else + { + auxInput_idx = -1; + x0_idx = 5; + } + } + else + { + auxInput_idx = -1; + x0_idx = -1; + } + } + else + { + A_idx = 2; + + /* If constraint matrix is empty, use a QProblemB object! */ + if ( mxIsEmpty( prhs[ A_idx ] ) ) + { + lb_idx = 3; + ub_idx = 4; + + nC = 0; + } + else + { + lb_idx = 3; + ub_idx = 4; + lbA_idx = 5; + ubA_idx = 6; + + nC = (int)mxGetM( prhs[ A_idx ] ); /* row number of constraint matrix */ + } + + if ( ( nrhs >= 9 ) && ( !mxIsEmpty(prhs[8]) ) ) + { + /* auxInput specified */ + if ( mxIsStruct(prhs[8]) ) + { + auxInput_idx = 8; + x0_idx = -1; + } + else + { + auxInput_idx = -1; + x0_idx = 8; + } + } + else + { + auxInput_idx = -1; + x0_idx = -1; + } + } + + + /* ensure that data is given in real_t precision */ + if ( ( mxIsDouble( prhs[ H_idx ] ) == 0 ) || + ( mxIsDouble( prhs[ g_idx ] ) == 0 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in double precision!" ); + return; + } + + /* check if supplied data contains 'NaN' or 'Inf' */ + if (containsNaNorInf(prhs, nV * nV, H_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + if ( mxGetN( prhs[ H_idx ] ) != nV ) + { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Hessian matrix input dimension mismatch (%ld != %d)!", + (long int)mxGetN(prhs[H_idx]), nV); + myMexErrMsgTxt(msg); + return; + } + + if ( nC > 0 ) + { + /* ensure that data is given in real_t precision */ + if ( mxIsDouble( prhs[ A_idx ] ) == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in real_t precision!" ); + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + if ( mxGetN( prhs[ A_idx ] ) != nV ) + { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Constraint matrix input dimension mismatch (%ld != %d)!", + (long int)mxGetN(prhs[A_idx]), nV); + myMexErrMsgTxt(msg); + return; + } + + if (containsNaNorInf(prhs, nV * nC, A_idx, 0) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + } + + /* check dimensions and copy auxInputs */ + if ( smartDimensionCheck( &g,nV,nP, BT_FALSE,prhs,g_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,nP, BT_TRUE,prhs,lb_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,nP, BT_TRUE,prhs,ub_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &x0,nV,1, BT_TRUE,prhs,x0_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( nC > 0 ) + { + if ( smartDimensionCheck( &lbA,nC,nP, BT_TRUE,prhs,lbA_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,nP, BT_TRUE,prhs,ubA_idx ) != SUCCESSFUL_RETURN ) + return; + } + + if ( auxInput_idx >= 0 ) + setupAuxiliaryInputs( prhs[auxInput_idx],nV,nC, &x0,&guessedBoundsAndConstraints,&guessedBounds,&guessedConstraints ); + + + /* III) ACTUALLY PERFORM QPOASES FUNCTION CALL: */ + int nWSRin = 5*(nV+nC); + real_t maxCpuTimeIn = -1.0; + + if ( options_idx > 0 ) + setupOptions( &options,prhs[options_idx],nWSRin,maxCpuTimeIn ); + + /* make a deep-copy of the user-specified Hessian matrix (possibly sparse) */ + setupHessianMatrix( prhs[H_idx],nV, &H,&Hir,&Hjc,&Hv ); + + /* make a deep-copy of the user-specified constraint matrix (possibly sparse) */ + if ( nC > 0 ) + setupConstraintMatrix( prhs[A_idx],nV,nC, &A,&Air,&Ajc,&Av ); + + allocateOutputs( nlhs,plhs,nV,nC,nP ); + + if ( nC == 0 ) + { + /* Call qpOASES (using QProblemB class). */ + qpOASESmex_bounds( nV,nP, + H,g, + lb,ub, + nWSRin,maxCpuTimeIn, + x0,&options, + nlhs,plhs, + guessedBounds + ); + + deleteAuxiliaryInputs( &guessedBounds,0 ); + delete H; + if (Hv != 0) delete[] Hv; + if (Hjc != 0) delete[] Hjc; + if (Hir != 0) delete[] Hir; + return; + } + else + { + /* Call qpOASES (using QProblem class). */ + qpOASESmex_constraints( nV,nC,nP, + H,g,A, + lb,ub,lbA,ubA, + nWSRin,maxCpuTimeIn, + x0,&options, + nlhs,plhs, + guessedBounds, guessedConstraints + ); + + deleteAuxiliaryInputs( &guessedBounds,&guessedConstraints ); + delete A; + delete H; + if (Av != 0) delete[] Av; + if (Ajc != 0) delete[] Ajc; + if (Air != 0) delete[] Air; + if (Hv != 0) delete[] Hv; + if (Hjc != 0) delete[] Hjc; + if (Hir != 0) delete[] Hir; + return; + } +} + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES.m new file mode 100644 index 00000000000..e5ab89631e9 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES.m @@ -0,0 +1,77 @@ +%qpOASES -- An Implementation of the Online Active Set Strategy. +%Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. +% +%qpOASES is distributed under the terms of the +%GNU Lesser General Public License 2.1 in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%See the GNU Lesser General Public License for more details. +% +%--------------------------------------------------------------------------------- +% +%qpOASES solves (a series) of quadratic programming (QP) problems of the +%following form: +% +% min 1/2*x'Hx + x'g +% s.t. lb <= x <= ub +% lbA <= Ax <= ubA {optional} +% +%Call +% +% [x,fval,exitflag,iter,lambda,auxOutput] = +% qpOASES( H,g,A,lb,ub,lbA,ubA{,options{,auxInput}} ) +% +%for solving the above-mentioned QP. H must be a symmetric (but possibly +%indefinite) matrix and all vectors g, lb, ub, lbA, ubA have to be given +%as column vectors. Options can be generated using the qpOASES_options command, +%otherwise default values are used. Optionally, further auxiliary inputs +%may be generated using qpOASES_auxInput command and passed to the solver. +%Both matrices H or A may be passed in sparse matrix format. +% +%Call +% +% [x,fval,exitflag,iter,lambda,auxOutput] = +% qpOASES( H,g,lb,ub{,options{,auxInput}} ) +% +%for solving the above-mentioned QP without general constraints. +% +% +%Optional outputs (only x is mandatory): +% x - Optimal primal solution vector (if exitflag==0). +% fval - Optimal objective function value (if exitflag==0). +% exitflag - 0: QP problem solved, +% 1: QP could not be solved within given number of iterations, +% -1: QP could not be solved due to an internal error, +% -2: QP is infeasible (and thus could not be solved), +% -3: QP is unbounded (and thus could not be solved). +% iter - Number of active set iterations actually performed. +% lambda - Optimal dual solution vector (if status==0). +% auxOutput - Struct containing auxiliary outputs as described below. +% +%The auxOutput struct contains the following entries: +% workingSet - The working set at point x. The working set is a subset +% of the active set (which is the set of all indices +% corresponding to bounds/constraints that hold with +% equality). The working set corresponds to bound/ +% constraint row vectors forming a linear independent set. +% The first nV elements correspond to the bounds, the last +% nC elements to the constraints. +% The working set is encoded as follows: +% 1: bound/constraint at its upper bound +% 0: bound/constraint not at any bound +% -1: bound/constraint at its lower bound +% cpuTime - Internally measured CPU time for solving QP. +% +% +%If not a single QP but a sequence of QPs with varying vectors is to be solved, +%the i-th QP is given by the i-th columns of the QP vectors g, lb, ub, lbA, ubA +%(i.e. they are matrices in this case). Both matrices H and A remain constant. +% +%See also QPOASES_OPTIONS, QPOASES_AUXINPUT, QPOASES_SEQUENCE +% +% +%For additional information see the qpOASES User's Manual or +%visit http://www.qpOASES.org/. +% +%Please send remarks and questions to support@qpOASES.org! diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_auxInput.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_auxInput.m new file mode 100644 index 00000000000..6d46efe149d --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_auxInput.m @@ -0,0 +1,103 @@ +%qpOASES -- An Implementation of the Online Active Set Strategy. +%Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. +% +%qpOASES is distributed under the terms of the +%GNU Lesser General Public License 2.1 in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%See the GNU Lesser General Public License for more details. +% +%--------------------------------------------------------------------------------- +% +%Returns a struct containing all possible auxiliary inputs to be passed +%to qpOASES. +% +%Call +% auxInput = qpOASES_auxInput(); +%to obtain a struct with all auxiliary inputs empty. +% +%Call +% auxInput = qpOASES_auxInput( 'input1',value1,'input2',value2,... ) +%to obtain a struct with 'input1' set to value1 etc. and all remaining +%auxiliary inputs empty. +% +%Call +% auxInput = qpOASES_auxInput( oldInputs,'input1',value1,... ) +%to obtain a copy of the options struct oldInputs but with 'input1' set to +%value1 etc. +% +% +%qpOASES features the following auxiliary inputs: +% x0 - Initial guess for optimal primal solution. +% guessedWorkingSet - Initial guess for working set at optimal +% solution. The first nV elements correspond +% to the bounds, the last nC elements to the +% constraints. +% The working set needs to be encoded as follows: +% 1: bound/constraint at its upper bound +% 0: bound/constraint not at any bound +% -1: bound/constraint at its lower bound +% +% +%See also QPOASES, QPOASES_SEQUENCE, QPOASES_OPTIONS +% +% +%For additional information see the qpOASES User's Manual or +%visit http://www.qpOASES.org/. +% +%Please send remarks and questions to support@qpOASES.org! +function [ auxInput ] = qpOASES_auxInput( varargin ) + + firstIsStruct = 0; + + if ( nargin == 0 ) + auxInput = qpOASES_emptyAuxInput(); + else + if ( isstruct( varargin{1} ) ) + if ( mod( nargin,2 ) ~= 1 ) + error('ERROR (qpOASES_auxInput): Auxiliary inputs must be specified in pairs!'); + end + auxInput = varargin{1}; + firstIsStruct = 1; + else + if ( mod( nargin,2 ) ~= 0 ) + error('ERROR (qpOASES_auxInput): Auxiliary inputs must be specified in pairs!'); + end + auxInput = qpOASES_emptyAuxInput(); + end + end + + % set options to user-defined values + for i=(1+firstIsStruct):2:nargin + + argName = varargin{i}; + argValue = varargin{i+1}; + + if ( ( isempty( argName ) ) || ( ~ischar( argName ) ) ) + error('ERROR (qpOASES_auxInput): Argmument no. %d has to be a non-empty string!',i ); + end + + if ( ( ischar(argValue) ) || ( ~isnumeric( argValue ) ) ) + error('ERROR (qpOASES_auxInput): Argmument no. %d has to be a numerical constant!',i+1 ); + end + + if ( ~isfield( auxInput,argName ) ) + error('ERROR (qpOASES_auxInput): Argmument no. %d is not a valid auxiliary input!',i ); + end + + eval( ['auxInput.',argName,' = argValue;'] ); + + end + +end + + +function [ auxInput ] = qpOASES_emptyAuxInput( ) + + % setup auxiliary input struct with all entries empty + auxInput = struct( 'x0', [], ... + 'guessedWorkingSet', [] ... + ); + +end diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_matlab_utils.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_matlab_utils.cpp new file mode 100644 index 00000000000..7362704f46a --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_matlab_utils.cpp @@ -0,0 +1,885 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/matlab/qpOASES_matlab_utils.cpp + * \author Hans Joachim Ferreau, Alexander Buchner + * \version 3.0 + * \date 2007-2014 + * + * Collects utility functions for Interface to Matlab(R) that + * enables to call qpOASES as a MEX function. + * + */ + + + +QPInstance::QPInstance( int _nV, int _nC, BooleanType _isSimplyBounded + ) +{ + handle = s_nexthandle++; + + if ( _nC > 0 ) + isSimplyBounded = BT_FALSE; + else + isSimplyBounded = _isSimplyBounded; + + if ( isSimplyBounded == BT_TRUE ) + { + sqp = 0; + qpb = new QProblemB( _nV ); + } + else + { + sqp = new SQProblem( _nV,_nC ); + qpb = 0; + } + + H = 0; + A = 0; + Hir = 0; + Hjc = 0; + Air = 0; + Ajc = 0; + Hv = 0; + Av = 0; +} + + +QPInstance::~QPInstance( ) +{ + deleteQPMatrices(); + + if ( sqp != 0 ) + { + delete sqp; + sqp = 0; + } + + if ( qpb != 0 ) + { + delete qpb; + qpb = 0; + } +} + + +returnValue QPInstance::deleteQPMatrices( ) +{ + if ( H != 0 ) + { + delete H; + H = 0; + } + + if (Hv != 0) + { + delete[] Hv; + Hv = 0; + } + + if (Hjc != 0) + { + delete[] Hjc; + Hjc = 0; + } + + if (Hir != 0) + { + delete[] Hir; + Hir = 0; + } + + if ( A != 0 ) + { + delete A; + A = 0; + } + + if (Av != 0) + { + delete[] Av; + Av = 0; + } + + if (Ajc != 0) + { + delete[] Ajc; + Ajc = 0; + } + + if (Air != 0) + { + delete[] Air; + Air = 0; + } + + return SUCCESSFUL_RETURN; +} + + +int QPInstance::getNV() const +{ + if ( sqp != 0 ) + return sqp->getNV(); + + if ( qpb != 0 ) + return qpb->getNV(); + + return 0; +} + + +int QPInstance::getNC() const +{ + if ( sqp != 0 ) + return sqp->getNC(); + + return 0; +} + + +/* + * a l l o c a t e Q P r o b l e m I n s t a n c e + */ +int allocateQPInstance( int nV, int nC, BooleanType isSimplyBounded, const Options *options + ) +{ + QPInstance* inst = new QPInstance( nV,nC,isSimplyBounded ); + + if ( inst->sqp != 0 ) + inst->sqp->setOptions ( *options ); + + if ( inst->qpb != 0 ) + inst->qpb->setOptions ( *options ); + + g_instances.push_back (inst); + return inst->handle; +} + + +/* + * g e t Q P r o b l e m I n s t a n c e + */ +QPInstance* getQPInstance( int handle ) +{ + unsigned int ii; + // TODO: this may become slow ... + for (ii = 0; ii < g_instances.size (); ++ii) + if (g_instances[ii]->handle == handle) + return g_instances[ii]; + return 0; +} + + +/* + * d e l e t e Q P r o b l e m I n s t a n c e + */ +void deleteQPInstance( int handle ) +{ + QPInstance *instance = getQPInstance (handle); + if (instance != 0) { + for (std::vector::iterator itor = g_instances.begin (); + itor != g_instances.end (); ++itor) + if ((*itor)->handle == handle) { + g_instances.erase (itor); + break; + } + delete instance; + } +} + + + +/* + * s m a r t D i m e n s i o n C h e c k + */ +returnValue smartDimensionCheck( real_t** input, unsigned int m, unsigned int n, BooleanType emptyAllowed, + const mxArray* prhs[], int idx + ) +{ + /* If index is negative, the input does not exist. */ + if ( idx < 0 ) + { + *input = 0; + return SUCCESSFUL_RETURN; + } + + /* Otherwise the input has been passed by the user. */ + if ( mxIsEmpty( prhs[ idx ] ) ) + { + /* input is empty */ + if ( ( emptyAllowed == BT_TRUE ) || ( idx == 0 ) ) /* idx==0 used for auxInput */ + { + *input = 0; + return SUCCESSFUL_RETURN; + } + else + { + char msg[MAX_STRING_LENGTH]; + if ( idx > 0 ) + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Empty argument %d not allowed!", idx+1); + myMexErrMsgTxt( msg ); + return RET_INVALID_ARGUMENTS; + } + } + else + { + /* input is non-empty */ + if ( mxIsSparse( prhs[ idx ] ) == 0 ) + { + if ( ( mxGetM( prhs[ idx ] ) == m ) && ( mxGetN( prhs[ idx ] ) == n ) ) + { + *input = (real_t*) mxGetPr( prhs[ idx ] ); + return SUCCESSFUL_RETURN; + } + else + { + char msg[MAX_STRING_LENGTH]; + if ( idx > 0 ) + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Input dimension mismatch for argument %d ([%ld,%ld] ~= [%d,%d]).", + idx+1, (long int)mxGetM(prhs[idx]), (long int)mxGetN(prhs[idx]), m, n); + else /* idx==0 used for auxInput */ + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Input dimension mismatch for some auxInput entry ([%ld,%ld] ~= [%d,%d]).", + (long int)mxGetM(prhs[idx]), (long int)mxGetN(prhs[idx]), m, n); + myMexErrMsgTxt( msg ); + return RET_INVALID_ARGUMENTS; + } + } + else + { + char msg[MAX_STRING_LENGTH]; + if ( idx > 0 ) + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Vector argument %d must not be in sparse format!", idx+1); + else /* idx==0 used for auxInput */ + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): auxInput entries must not be in sparse format!" ); + myMexErrMsgTxt( msg ); + return RET_INVALID_ARGUMENTS; + } + } + + return SUCCESSFUL_RETURN; +} + + + +/* + * c o n t a i n s N a N + */ +BooleanType containsNaN( const real_t* const data, int dim ) +{ + int i; + + if ( data == 0 ) + return BT_FALSE; + + for ( i = 0; i < dim; ++i ) + if ( mxIsNaN(data[i]) == 1 ) + return BT_TRUE; + + return BT_FALSE; +} + + +/* + * c o n t a i n s I n f + */ +BooleanType containsInf( const real_t* const data, int dim ) +{ + int i; + + if ( data == 0 ) + return BT_FALSE; + + for ( i = 0; i < dim; ++i ) + if ( mxIsInf(data[i]) == 1 ) + return BT_TRUE; + + return BT_FALSE; +} + + +/* + * c o n t a i n s N a N o r I n f + */ +BooleanType containsNaNorInf(const mxArray* prhs[], int dim, int rhs_index, + bool mayContainInf) { + + char msg[MAX_STRING_LENGTH]; + + // overwrite dim for sparse matrices + if (mxIsSparse(prhs[rhs_index]) == 1) { + dim = mxGetNzmax(prhs[rhs_index]); + } + + if (containsNaN((real_t*) mxGetPr(prhs[rhs_index]), dim) == BT_TRUE) { + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Argument %d contains 'NaN' !", rhs_index + 1); + myMexErrMsgTxt(msg); + return BT_TRUE; + } + + if (mayContainInf == 0) { + if (containsInf((real_t*) mxGetPr(prhs[rhs_index]), dim) == BT_TRUE) { + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Argument %d contains 'Inf' !", + rhs_index + 1); + myMexErrMsgTxt(msg); + return BT_TRUE; + } + } + + return BT_FALSE; +} + + +/* + * c o n v e r t F o r t r a n T o C + */ +returnValue convertFortranToC( const real_t* const A_for, int nV, int nC, real_t* const A ) +{ + int i,j; + + for ( i=0; i = ; */ + if ( mxGetNumberOfFields(optionsPtr) != 31 ) + mexWarnMsgTxt( "Options might be set incorrectly as struct has wrong number of entries!\n Type 'help qpOASES_options' for further information." ); + + + if ( hasOptionsValue( optionsPtr,"maxIter",&optionValue ) == BT_TRUE ) + if ( *optionValue >= 0.0 ) + nWSRin = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"maxCpuTime",&optionValue ) == BT_TRUE ) + if ( *optionValue >= 0.0 ) + maxCpuTime = *optionValue; + + if ( hasOptionsValue( optionsPtr,"printLevel",&optionValue ) == BT_TRUE ) + { + #ifdef __SUPPRESSANYOUTPUT__ + options->printLevel = PL_NONE; + #else + optionValueInt = (int)*optionValue; + options->printLevel = (REFER_NAMESPACE_QPOASES PrintLevel)optionValueInt; + if ( options->printLevel < PL_DEBUG_ITER ) + options->printLevel = PL_DEBUG_ITER; + if ( options->printLevel > PL_HIGH ) + options->printLevel = PL_HIGH; + #endif + } + + if ( hasOptionsValue( optionsPtr,"enableRamping",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableRamping = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableFarBounds",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableFarBounds = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableFlippingBounds",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableFlippingBounds = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableRegularisation",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableRegularisation = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableFullLITests",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableFullLITests = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableNZCTests",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableNZCTests = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableDriftCorrection",&optionValue ) == BT_TRUE ) + options->enableDriftCorrection = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"enableCholeskyRefactorisation",&optionValue ) == BT_TRUE ) + options->enableCholeskyRefactorisation = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"enableEqualities",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableEqualities = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + + if ( hasOptionsValue( optionsPtr,"terminationTolerance",&optionValue ) == BT_TRUE ) + options->terminationTolerance = *optionValue; + + if ( hasOptionsValue( optionsPtr,"boundTolerance",&optionValue ) == BT_TRUE ) + options->boundTolerance = *optionValue; + + if ( hasOptionsValue( optionsPtr,"boundRelaxation",&optionValue ) == BT_TRUE ) + options->boundRelaxation = *optionValue; + + if ( hasOptionsValue( optionsPtr,"epsNum",&optionValue ) == BT_TRUE ) + options->epsNum = *optionValue; + + if ( hasOptionsValue( optionsPtr,"epsDen",&optionValue ) == BT_TRUE ) + options->epsDen = *optionValue; + + if ( hasOptionsValue( optionsPtr,"maxPrimalJump",&optionValue ) == BT_TRUE ) + options->maxPrimalJump = *optionValue; + + if ( hasOptionsValue( optionsPtr,"maxDualJump",&optionValue ) == BT_TRUE ) + options->maxDualJump = *optionValue; + + + if ( hasOptionsValue( optionsPtr,"initialRamping",&optionValue ) == BT_TRUE ) + options->initialRamping = *optionValue; + + if ( hasOptionsValue( optionsPtr,"finalRamping",&optionValue ) == BT_TRUE ) + options->finalRamping = *optionValue; + + if ( hasOptionsValue( optionsPtr,"initialFarBounds",&optionValue ) == BT_TRUE ) + options->initialFarBounds = *optionValue; + + if ( hasOptionsValue( optionsPtr,"growFarBounds",&optionValue ) == BT_TRUE ) + options->growFarBounds = *optionValue; + + if ( hasOptionsValue( optionsPtr,"initialStatusBounds",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + if ( optionValueInt < -1 ) + optionValueInt = -1; + if ( optionValueInt > 1 ) + optionValueInt = 1; + options->initialStatusBounds = (REFER_NAMESPACE_QPOASES SubjectToStatus)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"epsFlipping",&optionValue ) == BT_TRUE ) + options->epsFlipping = *optionValue; + + if ( hasOptionsValue( optionsPtr,"numRegularisationSteps",&optionValue ) == BT_TRUE ) + options->numRegularisationSteps = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"epsRegularisation",&optionValue ) == BT_TRUE ) + options->epsRegularisation = *optionValue; + + if ( hasOptionsValue( optionsPtr,"numRefinementSteps",&optionValue ) == BT_TRUE ) + options->numRefinementSteps = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"epsIterRef",&optionValue ) == BT_TRUE ) + options->epsIterRef = *optionValue; + + if ( hasOptionsValue( optionsPtr,"epsLITests",&optionValue ) == BT_TRUE ) + options->epsLITests = *optionValue; + + if ( hasOptionsValue( optionsPtr,"epsNZCTests",&optionValue ) == BT_TRUE ) + options->epsNZCTests = *optionValue; + + return SUCCESSFUL_RETURN; +} + + + +/* + * s e t u p A u x i l i a r y I n p u t s + */ +returnValue setupAuxiliaryInputs( const mxArray* auxInput, unsigned int nV, unsigned int nC, + double** x0, double** guessedBoundsAndConstraints, double** guessedBounds, double** guessedConstraints + ) +{ + unsigned int i; + mxArray* curField = 0; + + /* x0 */ + curField = mxGetField( auxInput,0,"x0" ); + if ( curField == NULL ) + mexWarnMsgTxt( "auxInput struct does not contain entry 'x0'!\n Type 'help qpOASES_auxInput' for further information." ); + else + { + *x0 = mxGetPr(curField); + if ( smartDimensionCheck( x0,nV,1, BT_TRUE,((const mxArray**)&curField),0 ) != SUCCESSFUL_RETURN ) + return RET_INVALID_ARGUMENTS; + } + + /* guessedWorkingSet */ + curField = mxGetField( auxInput,0,"guessedWorkingSet" ); + if ( curField == NULL ) + mexWarnMsgTxt( "auxInput struct does not contain entry 'guessedWorkingSet'!\n Type 'help qpOASES_auxInput' for further information." ); + else + { + *guessedBoundsAndConstraints = mxGetPr(curField); + if ( smartDimensionCheck( guessedBoundsAndConstraints,nV+nC,1, BT_TRUE,((const mxArray**)&curField),0 ) != SUCCESSFUL_RETURN ) + return RET_INVALID_ARGUMENTS; + + if ( *guessedBoundsAndConstraints != 0 ) + { + *guessedBounds = new double[nV]; + for (i = 0; i < nV; i++) + (*guessedBounds)[i] = (*guessedBoundsAndConstraints)[i]; + + if ( nC > 0 ) + { + *guessedConstraints = new double[nC]; + for (i = 0; i < nC; i++) + (*guessedConstraints)[i] = (*guessedBoundsAndConstraints)[i + nV]; + } + } + } + + return SUCCESSFUL_RETURN; +} + + +/* + * d e l e t e A u x i l i a r y I n p u t s + */ +returnValue deleteAuxiliaryInputs( double** guessedBounds, double** guessedConstraints + ) +{ + if ( ( guessedBounds != 0 ) && ( *guessedBounds != 0 ) ) + { + delete[] (*guessedBounds); + *guessedBounds = 0; + } + + if ( ( guessedConstraints != 0 ) && ( guessedConstraints != 0 ) ) + { + delete[] (*guessedConstraints); + *guessedConstraints = 0; + } + + return SUCCESSFUL_RETURN; +} + + + +/* + * a l l o c a t e O u t p u t s + */ +returnValue allocateOutputs( int nlhs, mxArray* plhs[], int nV, int nC = 0, int nP = 1, int handle = -1 + ) +{ + /* Create output vectors and assign pointers to them. */ + int curIdx = 0; + + /* handle */ + if ( handle >= 0 ) + plhs[curIdx++] = mxCreateDoubleMatrix( 1, 1, mxREAL ); + + /* x */ + plhs[curIdx++] = mxCreateDoubleMatrix( nV, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* fval */ + plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* exitflag */ + plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* iter */ + plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* lambda */ + plhs[curIdx++] = mxCreateDoubleMatrix( nV+nC, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* setup auxiliary output struct */ + mxArray* auxOutput = mxCreateStructMatrix( 1,1,0,0 ); + int curFieldNum; + + /* working set */ + curFieldNum = mxAddField( auxOutput,"workingSet" ); + if ( curFieldNum >= 0 ) + mxSetFieldByNumber( auxOutput,0,curFieldNum,mxCreateDoubleMatrix( nV+nC, nP, mxREAL ) ); + + curFieldNum = mxAddField( auxOutput,"cpuTime" ); + if ( curFieldNum >= 0 ) + mxSetFieldByNumber( auxOutput,0,curFieldNum,mxCreateDoubleMatrix( 1, nP, mxREAL ) ); + + plhs[curIdx] = auxOutput; + } + } + } + } + } + + return SUCCESSFUL_RETURN; +} + + +/* + * o b t a i n O u t p u t s + */ +returnValue obtainOutputs( int k, QProblemB* qp, returnValue returnvalue, int _nWSRout, real_t _cpuTime, + int nlhs, mxArray* plhs[], int nV, int nC = 0, int handle = -1 + ) +{ + /* Create output vectors and assign pointers to them. */ + int curIdx = 0; + + /* handle */ + if ( handle >= 0 ) + plhs[curIdx++] = mxCreateDoubleScalar( handle ); + + /* x */ + double* x = mxGetPr( plhs[curIdx++] ); + qp->getPrimalSolution( &(x[k*nV]) ); + + if ( nlhs > curIdx ) + { + /* fval */ + double* obj = mxGetPr( plhs[curIdx++] ); + obj[k] = qp->getObjVal( ); + + if ( nlhs > curIdx ) + { + /* exitflag */ + double* status = mxGetPr( plhs[curIdx++] ); + status[k] = (real_t)getSimpleStatus( returnvalue ); + + if ( nlhs > curIdx ) + { + /* iter */ + double* nWSRout = mxGetPr( plhs[curIdx++] ); + nWSRout[k] = (real_t) _nWSRout; + + if ( nlhs > curIdx ) + { + /* lambda */ + double* y = mxGetPr( plhs[curIdx++] ); + qp->getDualSolution( &(y[k*(nV+nC)]) ); + + if ( nlhs > curIdx ) + { + + mxArray* auxOutput = plhs[curIdx]; + mxArray* curField = 0; + + /* working set */ + curField = mxGetField( auxOutput,0,"workingSet" ); + double* workingSet = mxGetPr(curField); + + QProblem* problemPointer; + problemPointer = dynamic_cast(qp); + + // cast successful? + if (problemPointer != NULL) { + problemPointer->getWorkingSet( &(workingSet[k*(nV+nC)]) ); + } else { + qp->getWorkingSet( &(workingSet[k*(nV+nC)]) ); + } + + /* cpu time */ + curField = mxGetField( auxOutput,0,"cpuTime" ); + double* cpuTime = mxGetPr(curField); + cpuTime[0] = (real_t) _cpuTime; + } + } + } + } + } + + return SUCCESSFUL_RETURN; +} + + + +/* + * s e t u p H e s s i a n M a t r i x + */ +returnValue setupHessianMatrix( const mxArray* prhsH, int nV, + SymmetricMatrix** H, sparse_int_t** Hir, sparse_int_t** Hjc, real_t** Hv + ) +{ + if ( mxIsSparse( prhsH ) != 0 ) + { + mwIndex *mat_ir = mxGetIr( prhsH ); + mwIndex *mat_jc = mxGetJc( prhsH ); + double *v = (double*)mxGetPr( prhsH ); + sparse_int_t nfill = 0; + mwIndex i, j; + BooleanType needInsertDiag; + + /* copy indices to avoid 64/32-bit integer confusion */ + /* also add explicit zeros on diagonal for regularization strategy */ + /* copy values, too */ + *Hir = new sparse_int_t[mat_jc[nV] + nV]; + *Hjc = new sparse_int_t[nV+1]; + *Hv = new real_t[mat_jc[nV] + nV]; + for (j = 0; j < nV; j++) + { + needInsertDiag = BT_TRUE; + + (*Hjc)[j] = (sparse_int_t)(mat_jc[j]) + nfill; + /* fill up to diagonal */ + for (i = mat_jc[j]; i < mat_jc[j+1]; i++) + { + if ( mat_ir[i] == j ) + needInsertDiag = BT_FALSE; + + /* add zero diagonal element if not present */ + if ( ( mat_ir[i] > j ) && ( needInsertDiag == BT_TRUE ) ) + { + (*Hir)[i + nfill] = (sparse_int_t)j; + (*Hv)[i + nfill] = 0.0; + nfill++; + /* only add diag once */ + needInsertDiag = BT_FALSE; + } + + (*Hir)[i + nfill] = (sparse_int_t)(mat_ir[i]); + (*Hv)[i + nfill] = (real_t)(v[i]); + } + } + (*Hjc)[nV] = (sparse_int_t)(mat_jc[nV]) + nfill; + + SymSparseMat *sH; + *H = sH = new SymSparseMat(nV, nV, *Hir, *Hjc, *Hv); + sH->createDiagInfo(); + } + else + { + /* make a deep-copy in order to avoid modifying input data when regularising */ + real_t* H_for = (real_t*) mxGetPr( prhsH ); + real_t* H_mem = new real_t[nV*nV]; + memcpy( H_mem,H_for, nV*nV*sizeof(real_t) ); + + *H = new SymDenseMat( nV,nV,nV, H_mem ); + (*H)->doFreeMemory( ); + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t u p C o n s t r a i n t M a t r i x + */ +returnValue setupConstraintMatrix( const mxArray* prhsA, int nV, int nC, + Matrix** A, sparse_int_t** Air, sparse_int_t** Ajc, real_t** Av + ) +{ + if ( mxIsSparse( prhsA ) != 0 ) + { + mwIndex i; + long j; + + mwIndex *mat_ir = mxGetIr( prhsA ); + mwIndex *mat_jc = mxGetJc( prhsA ); + double *v = (double*)mxGetPr( prhsA ); + + /* copy indices to avoid 64/32-bit integer confusion */ + *Air = new sparse_int_t[mat_jc[nV]]; + *Ajc = new sparse_int_t[nV+1]; + for (i = 0; i < mat_jc[nV]; i++) + (*Air)[i] = (sparse_int_t)(mat_ir[i]); + for (i = 0; i < nV + 1; i++) + (*Ajc)[i] = (sparse_int_t)(mat_jc[i]); + + /* copy values, too */ + *Av = new real_t[(*Ajc)[nV]]; + for (j = 0; j < (*Ajc)[nV]; j++) + (*Av)[j] = (real_t)(v[j]); + + *A = new SparseMatrix(nC, nV, *Air, *Ajc, *Av); + } + else + { + /* Convert constraint matrix A from FORTRAN to C style + * (not necessary for H as it should be symmetric!). */ + real_t* A_for = (real_t*) mxGetPr( prhsA ); + real_t* A_mem = new real_t[nC*nV]; + convertFortranToC( A_for,nV,nC, A_mem ); + *A = new DenseMatrix(nC, nV, nV, A_mem ); + (*A)->doFreeMemory(); + } + + return SUCCESSFUL_RETURN; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_matlab_utils.hpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_matlab_utils.hpp new file mode 100644 index 00000000000..ad588e8ddf9 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_matlab_utils.hpp @@ -0,0 +1,92 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/matlab/qpOASES_matlab_utils.hpp + * \author Hans Joachim Ferreau, Alexander Buchner + * \version 3.0 + * \date 2007-2014 + * + * Collects utility functions for Interface to Matlab(R) that + * enables to call qpOASES as a MEX function. + * + */ + + + +/* Work-around for settings where mexErrMsgTxt causes unexpected behaviour. */ +#ifdef __AVOID_MEXERRMSGTXT__ + #define myMexErrMsgTxt( TEXT ) mexPrintf( "%s\n\n",(TEXT) ); +#else + #define myMexErrMsgTxt mexErrMsgTxt +#endif + + +#include "mex.h" +#include "matrix.h" +#include "string.h" +#include + + +/* + * QProblem instance class + */ +class QPInstance +{ + private: + static int s_nexthandle; + + public: + QPInstance( int _nV = 0, + int _nC = 0, + BooleanType _isSimplyBounded = BT_FALSE + ); + + ~QPInstance( ); + + returnValue deleteQPMatrices(); + + int getNV() const; + int getNC() const; + + int handle; + + SQProblem* sqp; + QProblemB* qpb; + BooleanType isSimplyBounded; + + SymmetricMatrix* H; + Matrix* A; + sparse_int_t* Hir; + sparse_int_t* Hjc; + sparse_int_t* Air; + sparse_int_t* Ajc; + real_t* Hv; + real_t* Av; +}; + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_options.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_options.m new file mode 100644 index 00000000000..01b0e17e7c4 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_options.m @@ -0,0 +1,251 @@ +%qpOASES -- An Implementation of the Online Active Set Strategy. +%Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. +% +%qpOASES is distributed under the terms of the +%GNU Lesser General Public License 2.1 in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%See the GNU Lesser General Public License for more details. +% +%--------------------------------------------------------------------------------- +% +%Returns a struct containing values for all options to be used within qpOASES. +% +%Call +% options = qpOASES_options( 'default' ); +% options = qpOASES_options( 'reliable' ); +% options = qpOASES_options( 'MPC' ); +%to obtain a set of default options or a pre-defined set of options tuned +%for reliable or fast QP solution, respectively. +% +%Call +% options = qpOASES_options( 'option1',value1,'option2',value2,... ) +%to obtain a set of default options but with 'option1' set to value1 etc. +% +%Call +% options = qpOASES_options( oldOptions,'option1',value1,... ) +%to obtain a copy of the options struct oldOptions but with 'option1' set +%to value1 etc. +% +%Call +% options = qpOASES_options( 'default', 'option1',value1,... ) +% options = qpOASES_options( 'reliable','option1',value1,... ) +% options = qpOASES_options( 'MPC', 'option1',value1,... ) +%to obtain a set of default options or a pre-defined set of options tuned +%for reliable or fast QP solution, respectively, but with 'option1' set to +%value1 etc. +% +% +%qpOASES features the following options: +% maxIter - Maximum number of iterations (if set +% to -1, a value is chosen heuristically) +% maxCpuTime - Maximum CPU time in seconds (if set +% to -1, only iteration limit is used) +% printLevel - 0: no printed output, +% 1: only error messages are printed, +% 2: iterations and error messages are printed, +% 3: all available messages are printed. +% +% enableRamping - Enables (1) or disables (0) ramping. +% enableFarBounds - Enables (1) or disables (0) the use of +% far bounds. +% enableFlippingBounds - Enables (1) or disables (0) the use of +% flipping bounds. +% enableRegularisation - Enables (1) or disables (0) automatic +% Hessian regularisation. +% enableFullLITests - Enables (1) or disables (0) condition-hardened +% (but more expensive) LI test. +% enableNZCTests - Enables (1) or disables (0) nonzero curvature +% tests. +% enableDriftCorrection - Specifies the frequency of drift corrections: +% 0: turns them off, +% 1: uses them at each iteration etc. +% enableCholeskyRefactorisation - Specifies the frequency of a full re- +% factorisation of projected Hessian matrix: +% 0: turns them off, +% 1: uses them at each iteration etc. +% enableEqualities - Specifies whether equalities should be treated +% as always active (1) or not (0) +% +% terminationTolerance - Relative termination tolerance to stop homotopy. +% boundTolerance - If upper and lower bounds differ less than this +% tolerance, they are regarded equal, i.e. as +% equality constraint. +% boundRelaxation - Initial relaxation of bounds to start homotopy +% and initial value for far bounds. +% epsNum - Numerator tolerance for ratio tests. +% epsDen - Denominator tolerance for ratio tests. +% maxPrimalJump - Maximum allowed jump in primal variables in +% nonzero curvature tests. +% maxDualJump - Maximum allowed jump in dual variables in +% linear independence tests. +% +% initialRamping - Start value for ramping strategy. +% finalRamping - Final value for ramping strategy. +% initialFarBounds - Initial size for far bounds. +% growFarBounds - Factor to grow far bounds. +% initialStatusBounds - Initial status of bounds at first iteration: +% 0: all bounds inactive, +% -1: all bounds active at their lower bound, +% +1: all bounds active at their upper bound. +% epsFlipping - Tolerance of squared Cholesky diagonal factor +% which triggers flipping bound. +% numRegularisationSteps - Maximum number of successive regularisation steps. +% epsRegularisation - Scaling factor of identity matrix used for +% Hessian regularisation. +% numRefinementSteps - Maximum number of iterative refinement steps. +% epsIterRef - Early termination tolerance for iterative +% refinement. +% epsLITests - Tolerance for linear independence tests. +% epsNZCTests - Tolerance for nonzero curvature tests. +% +% +%See also QPOASES, QPOASES_SEQUENCE +% +% +%For additional information see the qpOASES User's Manual or +%visit http://www.qpOASES.org/. +% +%Please send remarks and questions to support@qpOASES.org! +function [ options ] = qpOASES_options( varargin ) + + firstIsStructOrScheme = 0; + + if ( nargin == 0 ) + options = qpOASES_default_options(); + else + if ( isstruct( varargin{1} ) ) + if ( mod( nargin,2 ) ~= 1 ) + error('ERROR (qpOASES_options): Options must be specified in pairs!'); + end + options = varargin{1}; + firstIsStructOrScheme = 1; + else + if ( ischar( varargin{1} ) ) + if ( mod( nargin,2 ) == 0 ) + options = qpOASES_default_options(); + else + if ( ( nargin > 1 ) && ( ischar( varargin{nargin} ) ) ) + error('ERROR (qpOASES_options): Options must be specified in pairs!'); + end + + switch ( varargin{1} ) + case 'default' + options = qpOASES_default_options(); + case 'reliable' + options = qpOASES_reliable_options(); + case {'MPC','mpc','fast'} + options = qpOASES_MPC_options(); + otherwise + error( ['ERROR (qpOASES_options): Only the following option schemes are defined: ''default'', ''reliable'', ''MPC''!'] ); + + end + firstIsStructOrScheme = 1; + end + else + error('ERROR (qpOASES_options): First argument needs to be a string or an options struct!'); + end + end + end + + % set options to user-defined values + for i=(1+firstIsStructOrScheme):2:nargin + + argName = varargin{i}; + argValue = varargin{i+1}; + + if ( ( isempty( argName ) ) || ( ~ischar( argName ) ) ) + error('ERROR (qpOASES_options): Argmument no. %d has to be a non-empty string!',i ); + end + + if ( ( ischar(argValue) ) || ( ~isscalar( argValue ) ) ) + error('ERROR (qpOASES_options): Argmument no. %d has to be a scalar constant!',i+1 ); + end + + if ( ~isfield( options,argName ) ) + error('ERROR (qpOASES_options): Argmument no. %d is an invalid option!',i ); + end + + eval( ['options.',argName,' = ',num2str(argValue),';'] ); + + end + +end + + +function [ options ] = qpOASES_default_options( ) + + % setup options struct with default values + options = struct( 'maxIter', -1, ... + 'maxCpuTime', -1, ... + 'printLevel', 1, ... + ... + 'enableRamping', 1, ... + 'enableFarBounds', 1, ... + 'enableFlippingBounds', 1, ... + 'enableRegularisation', 0, ... + 'enableFullLITests', 0, ... + 'enableNZCTests', 1, ... + 'enableDriftCorrection', 1, ... + 'enableCholeskyRefactorisation', 0, ... + 'enableEqualities', 0, ... + ... + 'terminationTolerance', 5.0e6*eps, ... + 'boundTolerance', 1.0e6*eps, ... + 'boundRelaxation', 1.0e4, ... + 'epsNum', -1.0e3*eps, ... + 'epsDen', 1.0e3*eps, ... + 'maxPrimalJump', 1.0e8, ... + 'maxDualJump', 1.0e8, ... + ... + 'initialRamping', 0.5, ... + 'finalRamping', 1.0, ... + 'initialFarBounds', 1.0e6, ... + 'growFarBounds', 1.0e3, ... + 'initialStatusBounds', -1, ... + 'epsFlipping', 1.0e3*eps, ... + 'numRegularisationSteps', 0, ... + 'epsRegularisation', 1.0e3*eps, ... + 'numRefinementSteps', 1, ... + 'epsIterRef', 1.0e2*eps, ... + 'epsLITests', 1.0e5*eps, ... + 'epsNZCTests', 3.0e3*eps ); + +end + + + +function [ options ] = qpOASES_reliable_options( ) + + % setup options struct with values for most reliable QP solution + options = qpOASES_default_options( ); + + options.enableFullLITests = 1; + options.enableCholeskyRefactorisation = 1; + + options.numRefinementSteps = 2; + +end + + +function [ options ] = qpOASES_MPC_options( ) + + % setup options struct with values for most reliable QP solution + options = qpOASES_default_options( ); + + options.enableRamping = 0; + options.enableFarBounds = 1; + options.enableFlippingBounds = 0; + options.enableRegularisation = 1; + options.enableNZCTests = 0; + options.enableDriftCorrection = 0; + options.enableEqualities = 1; + + options.terminationTolerance = 1.0e9*eps; + + options.initialStatusBounds = 0; + options.numRegularisationSteps = 1; + options.numRefinementSteps = 0; + +end diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_sequence.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_sequence.cpp new file mode 100644 index 00000000000..943e529e8eb --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_sequence.cpp @@ -0,0 +1,1061 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/matlab/qpOASES_sequence.cpp + * \author Hans Joachim Ferreau, Christian Kirches, Andreas Potschka, Alexander Buchner + * \version 3.0 + * \date 2007-2014 + * + * Interface for Matlab(R) that enables to call qpOASES as a MEX function + * (variant for solving QP sequences). + * + */ + + + +#include + + +USING_NAMESPACE_QPOASES + + +#include "qpOASES_matlab_utils.hpp" + +/** initialise handle counter of QPInstance class */ +int QPInstance::s_nexthandle = 1; + +/** global pointer to QP objects */ +static std::vector g_instances; + +#include "qpOASES_matlab_utils.cpp" + + +/* + * i n i t S B + */ +int initSB( int handle, + SymmetricMatrix *H, real_t* g, + const real_t* const lb, const real_t* const ub, + int nWSRin, real_t maxCpuTimeIn, + const real_t* const x0, Options* options, + int nOutputs, mxArray* plhs[], + double* guessedBounds + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + /* 1) setup initial QP. */ + QProblemB* globalQPB = getQPInstance(handle)->qpb; + + if ( globalQPB == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return -1; + } + + globalQPB->setOptions( *options ); + + /* 2) Solve initial QP. */ + returnValue returnvalue; + int nV = globalQPB->getNV(); + + /* 3) Fill the working set. */ + Bounds bounds(nV); + if (guessedBounds != 0) { + for (int i = 0; i < nV; i++) { + if ( isEqual(guessedBounds[i],-1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_LOWER); + } else if ( isEqual(guessedBounds[i],1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_UPPER); + } else if ( isEqual(guessedBounds[i],0.0) == BT_TRUE ) { + bounds.setupBound(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of bounds!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + if (x0 == 0 && guessedBounds == 0) + returnvalue = globalQPB->init( H,g,lb,ub, nWSRout,&maxCpuTimeOut ); + else + returnvalue = globalQPB->init( H,g,lb,ub, nWSRout,&maxCpuTimeOut, x0, 0, + guessedBounds != 0 ? &bounds : 0); + + /* 3) Assign lhs arguments. */ + obtainOutputs( 0,globalQPB,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,nV,0,handle ); + + return 0; +} + + +/* + * i n i t + */ +int init( int handle, + SymmetricMatrix *H, real_t* g, Matrix *A, + const real_t* const lb, const real_t* const ub, const real_t* const lbA, const real_t* const ubA, + int nWSRin, real_t maxCpuTimeIn, + const real_t* const x0, Options* options, + int nOutputs, mxArray* plhs[], + double* guessedBounds, double* guessedConstraints + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + /* 1) setup initial QP. */ + SQProblem* globalSQP = getQPInstance(handle)->sqp; + + if ( globalSQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return -1; + } + + globalSQP->setOptions( *options ); + + /* 2) Solve initial QP. */ + returnValue returnvalue; + int nV = globalSQP->getNV(); + int nC = globalSQP->getNC(); + + /* 3) Fill the working set. */ + Bounds bounds(nV); + Constraints constraints(nC); + if (guessedBounds != 0) { + for (int i = 0; i < nV; i++) { + if ( isEqual(guessedBounds[i],-1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_LOWER); + } else if ( isEqual(guessedBounds[i],1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_UPPER); + } else if ( isEqual(guessedBounds[i],0.0) == BT_TRUE ) { + bounds.setupBound(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of bounds!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + if (guessedConstraints != 0) { + for (int i = 0; i < nC; i++) { + if ( isEqual(guessedConstraints[i],-1.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_LOWER); + } else if ( isEqual(guessedConstraints[i],1.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_UPPER); + } else if ( isEqual(guessedConstraints[i],0.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of constraints!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + if (x0 == 0 && guessedBounds == 0 && guessedConstraints == 0) + returnvalue = globalSQP->init( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut); + else + returnvalue = globalSQP->init( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut, x0, 0, + guessedBounds != 0 ? &bounds : 0, + guessedConstraints != 0 ? &constraints : 0); + + /* 3) Assign lhs arguments. */ + obtainOutputs( 0,globalSQP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,nV,nC,handle ); + + return 0; +} + + + +/* + * h o t s t a r t S B + */ +int hotstartSB( int handle, + const real_t* const g, + const real_t* const lb, const real_t* const ub, + int nWSRin, real_t maxCpuTimeIn, + Options* options, + int nOutputs, mxArray* plhs[] + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + QProblemB* globalQPB = getQPInstance(handle)->qpb; + + if ( globalQPB == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): QP needs to be initialised first!" ); + return -1; + } + + /* 1) Solve QP with given options. */ + globalQPB->setOptions( *options ); + returnValue returnvalue = globalQPB->hotstart( g,lb,ub, nWSRout,&maxCpuTimeOut ); + + /* 2) Assign lhs arguments. */ + obtainOutputs( 0,globalQPB,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,0,0 ); + + return 0; +} + + +/* + * h o t s t a r t + */ +int hotstart( int handle, + const real_t* const g, + const real_t* const lb, const real_t* const ub, + const real_t* const lbA, const real_t* const ubA, + int nWSRin, real_t maxCpuTimeIn, + Options* options, + int nOutputs, mxArray* plhs[] + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + QProblem* globalSQP = getQPInstance(handle)->sqp; + + if ( globalSQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): QP needs to be initialised first!" ); + return -1; + } + + /* 1) Solve QP with given options. */ + globalSQP->setOptions( *options ); + returnValue returnvalue = globalSQP->hotstart( g,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut ); + + /* 2) Assign lhs arguments. */ + obtainOutputs( 0,globalSQP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,0,0 ); + + return 0; +} + + +/* + * h o t s t a r t V M + */ +int hotstartVM( int handle, + SymmetricMatrix *H, real_t* g, Matrix *A, + const real_t* const lb, const real_t* const ub, const real_t* const lbA, const real_t* const ubA, + int nWSRin, real_t maxCpuTimeIn, + Options* options, + int nOutputs, mxArray* plhs[] + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + SQProblem* globalSQP = getQPInstance(handle)->sqp; + + if ( globalSQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): QP needs to be initialised first!" ); + return -1; + } + + /* 1) Solve QP. */ + globalSQP->setOptions( *options ); + returnValue returnvalue = globalSQP->hotstart( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut ); + + switch (returnvalue) + { + case SUCCESSFUL_RETURN: + case RET_QP_UNBOUNDED: + case RET_QP_INFEASIBLE: + break; + otherwise: + myMexErrMsgTxt( "ERROR (qpOASES): Hotstart failed." ); + return -1; + } + + /* 2) Assign lhs arguments. */ + obtainOutputs( 0,globalSQP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,0,0 ); + + return 0; +} + + + +/* + * m e x F u n c t i o n + */ +void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] ) +{ + /* inputs */ + char typeString[2]; + real_t *g=0, *lb=0, *ub=0, *lbA=0, *ubA=0, *x0=0; + int H_idx=-1, g_idx=-1, A_idx=-1, lb_idx=-1, ub_idx=-1, lbA_idx=-1, ubA_idx=-1; + int x0_idx=-1, auxInput_idx=-1; + + double *guessedBoundsAndConstraints = 0; + double *guessedBounds = 0, *guessedConstraints = 0; + + BooleanType isSimplyBoundedQp = BT_FALSE; + + Options options; + options.printLevel = PL_LOW; + #ifdef __DEBUG__ + options.printLevel = PL_HIGH; + #endif + #ifdef __SUPPRESSANYOUTPUT__ + options.printLevel = PL_NONE; + #endif + + /* dimensions */ + unsigned int nV=0, nC=0, handle=0; + int nWSRin; + real_t maxCpuTimeIn = -1.0; + QPInstance* globalQP = 0; + + /* I) CONSISTENCY CHECKS: */ + /* 1) Ensure that qpOASES is called with a feasible number of input arguments. */ + if ( ( nrhs < 5 ) || ( nrhs > 10 ) ) + { + if ( nrhs != 2 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + } + + /* 2) Ensure that first input is a string ... */ + if ( mxIsChar( prhs[0] ) != 1 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): First input argument must be a string!" ); + return; + } + + mxGetString( prhs[0], typeString, 2 ); + + /* ... and if so, check if it is an allowed one. */ + if ( ( strcmp( typeString,"i" ) != 0 ) && ( strcmp( typeString,"I" ) != 0 ) && + ( strcmp( typeString,"h" ) != 0 ) && ( strcmp( typeString,"H" ) != 0 ) && + ( strcmp( typeString,"m" ) != 0 ) && ( strcmp( typeString,"M" ) != 0 ) && + ( strcmp( typeString,"e" ) != 0 ) && ( strcmp( typeString,"E" ) != 0 ) && + ( strcmp( typeString,"c" ) != 0 ) && ( strcmp( typeString,"C" ) != 0 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Undefined first input argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + + /* II) SELECT RESPECTIVE QPOASES FUNCTION CALL: */ + /* 1) Init (without or with initial guess for primal solution). */ + if ( ( strcmp( typeString,"i" ) == 0 ) || ( strcmp( typeString,"I" ) == 0 ) ) + { + /* consistency checks */ + if ( ( nlhs < 2 ) || ( nlhs > 7 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( nrhs < 5 ) || ( nrhs > 10 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* ensure that data is given in double precision */ + if ((mxIsDouble(prhs[1]) == 0) || (mxIsDouble(prhs[2]) == 0)) { + myMexErrMsgTxt( + "ERROR (qpOASES): All data has to be provided in double precision!"); + return; + } + + nV = (unsigned int)mxGetM( prhs[1] ); /* row number of Hessian matrix */ + + /* Check for 'Inf' and 'Nan' in Hessian */ + H_idx = 1; + g_idx = 2; + if (containsNaNorInf(prhs, nV * nV, H_idx, 0) == BT_TRUE) { + return; + } + + /* Check for 'Inf' and 'Nan' in gradient */ + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + + /* determine whether is it a simply bounded QP */ + if ( nrhs <= 7 ) + isSimplyBoundedQp = BT_TRUE; + else + isSimplyBoundedQp = BT_FALSE; + + if ( isSimplyBoundedQp == BT_TRUE ) + { + lb_idx = 3; + ub_idx = 4; + + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + nC = 0; /* row number of constraint matrix */ + + if ( mxGetN( prhs[1] ) != nV ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Input dimension mismatch!" ); + return; + } + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*nV; + + /* Check whether x0 and options are specified .*/ + if ( nrhs >= 6 ) + { + if ((!mxIsEmpty(prhs[5])) && (mxIsStruct(prhs[5]))) + setupOptions( &options,prhs[5],nWSRin,maxCpuTimeIn ); + + if ( ( nrhs >= 7 ) && ( !mxIsEmpty(prhs[6]) ) ) + { + /* auxInput specified */ + if ( mxIsStruct(prhs[6]) ) + { + auxInput_idx = 6; + x0_idx = -1; + } + else + { + auxInput_idx = -1; + x0_idx = 6; + } + } + else + { + auxInput_idx = -1; + x0_idx = -1; + } + } + } + else + { + /* ensure that data is given in double precision */ + if ( ( mxIsDouble( prhs[1] ) == 0 ) || + ( mxIsDouble( prhs[2] ) == 0 ) || + ( mxIsDouble( prhs[3] ) == 0 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in double precision!" ); + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + nC = (unsigned int)mxGetM( prhs[3] ); /* row number of constraint matrix */ + + A_idx = 3; + lb_idx = 4; + ub_idx = 5; + lbA_idx = 6; + ubA_idx = 7; + + if (containsNaNorInf(prhs, nV * nC, A_idx, 0) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + + if ( ( mxGetN( prhs[1] ) != nV ) || ( ( mxGetN( prhs[3] ) != 0 ) && ( mxGetN( prhs[3] ) != nV ) ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Input dimension mismatch!" ); + return; + } + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,5 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lbA,nC,1, BT_TRUE,prhs,6 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,1, BT_TRUE,prhs,7 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*(nV+nC); + + /* Check whether x0 and options are specified .*/ + if ( nrhs >= 9 ) + { + if ((!mxIsEmpty(prhs[8])) && (mxIsStruct(prhs[8]))) + setupOptions( &options,prhs[8],nWSRin,maxCpuTimeIn ); + + if ( ( nrhs >= 10 ) && ( !mxIsEmpty(prhs[9]) ) ) + { + /* auxInput specified */ + if ( mxIsStruct(prhs[9]) ) + { + auxInput_idx = 9; + x0_idx = -1; + } + else + { + auxInput_idx = -1; + x0_idx = 9; + } + } + else + { + auxInput_idx = -1; + x0_idx = -1; + } + } + } + + + /* check dimensions and copy auxInputs */ + if ( smartDimensionCheck( &x0,nV,1, BT_TRUE,prhs,x0_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( auxInput_idx >= 0 ) + setupAuxiliaryInputs( prhs[auxInput_idx],nV,nC, &x0,&guessedBoundsAndConstraints,&guessedBounds,&guessedConstraints ); + + + /* allocate instance */ + handle = allocateQPInstance( nV,nC,isSimplyBoundedQp, &options ); + globalQP = getQPInstance( handle ); + + /* make a deep-copy of the user-specified Hessian matrix (possibly sparse) */ + setupHessianMatrix( prhs[1],nV, &(globalQP->H),&(globalQP->Hir),&(globalQP->Hjc),&(globalQP->Hv) ); + + /* make a deep-copy of the user-specified constraint matrix (possibly sparse) */ + if ( nC > 0 ) + setupConstraintMatrix( prhs[3],nV,nC, &(globalQP->A),&(globalQP->Air),&(globalQP->Ajc),&(globalQP->Av) ); + + /* Create output vectors and assign pointers to them. */ + allocateOutputs( nlhs,plhs, nV,nC,1,handle ); + + /* Call qpOASES. */ + if ( isSimplyBoundedQp == BT_TRUE ) + { + initSB( handle, + globalQP->H,g, + lb,ub, + nWSRin,maxCpuTimeIn, + x0,&options, + nlhs,plhs, + guessedBounds + ); + + deleteAuxiliaryInputs( &guessedBounds,0 ); + } + else + { + init( handle, + globalQP->H,g,globalQP->A, + lb,ub,lbA,ubA, + nWSRin,maxCpuTimeIn, + x0,&options, + nlhs,plhs, + guessedBounds, guessedConstraints + ); + + deleteAuxiliaryInputs( &guessedBounds,&guessedConstraints ); + } + + return; + } + + /* 2) Hotstart. */ + if ( ( strcmp( typeString,"h" ) == 0 ) || ( strcmp( typeString,"H" ) == 0 ) ) + { + /* consistency checks */ + if ( ( nlhs < 1 ) || ( nlhs > 6 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( nrhs < 5 ) || ( nrhs > 8 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* determine whether is it a simply bounded QP */ + if ( nrhs < 7 ) + isSimplyBoundedQp = BT_TRUE; + else + isSimplyBoundedQp = BT_FALSE; + + + if ( ( mxIsDouble( prhs[1] ) == false ) || ( mxGetM( prhs[1] ) != 1 ) || ( mxGetN( prhs[1] ) != 1 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Expecting a handle to QP object as second argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* get QP instance */ + handle = (unsigned int)mxGetScalar( prhs[1] ); + globalQP = getQPInstance ( handle ); + if ( globalQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return; + } + + nV = globalQP->getNV(); + + g_idx = 2; + lb_idx = 3; + ub_idx = 4; + + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + + /* Check inputs dimensions and assign pointers to inputs. */ + if ( isSimplyBoundedQp == BT_TRUE ) + { + nC = 0; + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*nV; + + /* Check whether options are specified .*/ + if ( nrhs == 6 ) + if ( ( !mxIsEmpty( prhs[5] ) ) && ( mxIsStruct( prhs[5] ) ) ) + setupOptions( &options,prhs[5],nWSRin,maxCpuTimeIn ); + } + else + { + nC = globalQP->getNC( ); + + lbA_idx = 5; + ubA_idx = 6; + + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lbA,nC,1, BT_TRUE,prhs,5 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,1, BT_TRUE,prhs,6 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*(nV+nC); + + /* Check whether options are specified .*/ + if ( nrhs == 8 ) + if ( ( !mxIsEmpty( prhs[7] ) ) && ( mxIsStruct( prhs[7] ) ) ) + setupOptions( &options,prhs[7],nWSRin,maxCpuTimeIn ); + } + + /* Create output vectors and assign pointers to them. */ + allocateOutputs( nlhs,plhs, nV,nC ); + + /* call qpOASES */ + if ( isSimplyBoundedQp == BT_TRUE ) + { + hotstartSB( handle, g, + lb,ub, + nWSRin,maxCpuTimeIn, + &options, + nlhs,plhs + ); + } + else + { + hotstart( handle, g, + lb,ub,lbA,ubA, + nWSRin,maxCpuTimeIn, + &options, + nlhs,plhs + ); + } + + return; + } + + /* 3) Modify matrices. */ + if ( ( strcmp( typeString,"m" ) == 0 ) || ( strcmp( typeString,"M" ) == 0 ) ) + { + /* consistency checks */ + if ( ( nlhs < 1 ) || ( nlhs > 6 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( nrhs < 9 ) || ( nrhs > 10 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( mxIsDouble( prhs[1] ) == false ) || ( mxGetM( prhs[1] ) != 1 ) || ( mxGetN( prhs[1] ) != 1 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Expecting a handle to QP object as second argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* ensure that data is given in double precision */ + if ( ( mxIsDouble( prhs[2] ) == 0 ) || + ( mxIsDouble( prhs[3] ) == 0 ) || + ( mxIsDouble( prhs[4] ) == 0 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in real_t precision!" ); + return; + } + + /* get QP instance */ + handle = (unsigned int)mxGetScalar( prhs[1]); + globalQP = getQPInstance ( handle ); + if ( globalQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + nV = (unsigned int)mxGetM( prhs[2] ); /* row number of Hessian matrix */ + nC = (unsigned int)mxGetM( prhs[4] ); /* row number of constraint matrix */ + + H_idx = 2; + g_idx = 3; + A_idx = 4; + lb_idx = 5; + ub_idx = 6; + lbA_idx = 7; + ubA_idx = 8; + + /* check if supplied data contains 'NaN' or 'Inf' */ + if (containsNaNorInf(prhs, nV * nV, H_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV * nC, A_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + + /* Check that dimensions are consistent with existing QP instance */ + if (nV != (unsigned int) globalQP->getNV () || nC != (unsigned int) globalQP->getNC ()) + { + myMexErrMsgTxt( "ERROR (qpOASES): QP dimensions must be constant during a sequence! Try creating a new QP instance instead." ); + return; + } + + if ( ( mxGetN( prhs[2] ) != nV ) || ( ( mxGetN( prhs[4] ) != 0 ) && ( mxGetN( prhs[4] ) != nV ) ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Input dimension mismatch!" ); + return; + } + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,5 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,6 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lbA,nC,1, BT_TRUE,prhs,7 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,1, BT_TRUE,prhs,8 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*(nV+nC); + + /* Check whether options are specified .*/ + if ( nrhs > 9 ) + if ( ( !mxIsEmpty( prhs[9] ) ) && ( mxIsStruct( prhs[9] ) ) ) + setupOptions( &options,prhs[9],nWSRin,maxCpuTimeIn ); + + globalQP->deleteQPMatrices( ); + + /* make a deep-copy of the user-specified Hessian matrix (possibly sparse) */ + setupHessianMatrix( prhs[2],nV, &(globalQP->H),&(globalQP->Hir),&(globalQP->Hjc),&(globalQP->Hv) ); + + /* make a deep-copy of the user-specified constraint matrix (possibly sparse) */ + if ( nC > 0 ) + setupConstraintMatrix( prhs[4],nV,nC, &(globalQP->A),&(globalQP->Air),&(globalQP->Ajc),&(globalQP->Av) ); + + /* Create output vectors and assign pointers to them. */ + allocateOutputs( nlhs,plhs, nV,nC ); + + /* Call qpOASES */ + hotstartVM( handle, globalQP->H,g,globalQP->A, + lb,ub,lbA,ubA, + nWSRin,maxCpuTimeIn, + &options, + nlhs,plhs + ); + + return; + } + + /* 4) Solve current equality constrained QP. */ + if ( ( strcmp( typeString,"e" ) == 0 ) || ( strcmp( typeString,"E" ) == 0 ) ) + { + /* consistency checks */ + if ( ( nlhs < 1 ) || ( nlhs > 3 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( nrhs < 7 ) || ( nrhs > 8 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( mxIsDouble( prhs[1] ) == false ) || ( mxGetM( prhs[1] ) != 1 ) || ( mxGetN( prhs[1] ) != 1 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Expecting a handle to QP object as second argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* get QP instance */ + handle = (unsigned int)mxGetScalar( prhs[1] ); + globalQP = getQPInstance ( handle ); + if ( globalQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + int nRHS = (int)mxGetN(prhs[2]); + nV = globalQP->getNV( ); + nC = globalQP->getNC( ); + real_t *x_out, *y_out; + + g_idx = 2; + lb_idx = 3; + ub_idx = 4; + lbA_idx = 5; + ubA_idx = 6; + + /* check if supplied data contains 'NaN' or 'Inf' */ + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + + if ( smartDimensionCheck( &g,nV,nRHS, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,nRHS, BT_TRUE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,nRHS, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lbA,nC,nRHS, BT_TRUE,prhs,5 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,nRHS, BT_TRUE,prhs,6 ) != SUCCESSFUL_RETURN ) + return; + + /* Check whether options are specified .*/ + if ( ( nrhs == 8 ) && ( !mxIsEmpty( prhs[7] ) ) && ( mxIsStruct( prhs[7] ) ) ) + { + nWSRin = 5*(nV+nC); + setupOptions( &options,prhs[7],nWSRin,maxCpuTimeIn ); + globalQP->sqp->setOptions( options ); + } + + /* Create output vectors and assign pointers to them. */ + plhs[0] = mxCreateDoubleMatrix( nV, nRHS, mxREAL ); + x_out = mxGetPr(plhs[0]); + if (nlhs >= 2) + { + plhs[1] = mxCreateDoubleMatrix( nV+nC, nRHS, mxREAL ); + y_out = mxGetPr(plhs[1]); + + if (nlhs >= 3) { + plhs[2] = mxCreateDoubleMatrix( nV+nC, nRHS, mxREAL ); + double* workingSet = mxGetPr(plhs[2]); + + globalQP->sqp->getWorkingSet(workingSet); + } + } + else + y_out = new real_t[nV+nC]; + + /* Solve equality constrained QP */ + returnValue returnvalue = globalQP->sqp->solveCurrentEQP( nRHS,g,lb,ub,lbA,ubA, x_out,y_out ); + + if (nlhs < 2) + delete[] y_out; + + if (returnvalue != SUCCESSFUL_RETURN) + { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Couldn't solve current EQP (code %d)!", returnvalue); + myMexErrMsgTxt(msg); + return; + } + + return; + } + + /* 5) Cleanup. */ + if ( ( strcmp( typeString,"c" ) == 0 ) || ( strcmp( typeString,"C" ) == 0 ) ) + { + /* consistency checks */ + if ( nlhs != 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( nrhs != 2 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( mxIsDouble( prhs[1] ) == false ) || ( mxGetM( prhs[1] ) != 1 ) || ( mxGetN( prhs[1] ) != 1 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Expecting a handle to QP object as second argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* Cleanup SQProblem instance. */ + handle =(unsigned int)mxGetScalar( prhs[1] ); + deleteQPInstance ( handle ); + + return; + } + +} + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_sequence.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_sequence.m new file mode 100644 index 00000000000..e5d97b6229e --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/matlab/qpOASES_sequence.m @@ -0,0 +1,112 @@ +%qpOASES -- An Implementation of the Online Active Set Strategy. +%Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. +% +%qpOASES is distributed under the terms of the +%GNU Lesser General Public License 2.1 in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%See the GNU Lesser General Public License for more details. +% +%--------------------------------------------------------------------------------- +% +%qpOASES_sequence is intended to solve a sequence of quadratic +%programming (QP) problems of the following form: +% +% min 1/2*x'Hx + x'g +% s.t. lb <= x <= ub +% lbA <= Ax <= ubA {optional} +% +%I) Call +% +% [QP,x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'i',H,g,A,lb,ub,lbA,ubA{,options{,auxInput}} ) +%or +% [QP,x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'i',H,g,lb,ub{,options{,auxInput}} ) +% +%for initialising and solving the first above-mentioned QP of the sequence +%starting from an initial guess x0. H must be a symmetric (possibly indefinite) +%matrix and all vectors g, lb, ub, lbA, ubA have to be given as column vectors. +%Options can be generated using the qpOASES_options command, otherwise default +%values are used. Optionally, further auxiliary inputs may be generated +%using qpOASES_auxInput command and passed to the solver. +%Both matrices H or A may be passed in sparse matrix format. +% +%II) Call +% +% [x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'h',QP,g,lb,ub,lbA,ubA{,options} ) +%or +% [x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'h',QP,g,lb,ub{,options} ) +% +%for hotstarting from the previous QP solution to the one of the next QP +%given by the vectors g, lb, ub, lbA, ubA. Options can be generated using the +%qpOASES_options command, otherwise default values are used. +% +%III) Call +% +% [x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'm',QP,H,g,A,lb,ub,lbA,ubA{,options} ) +% +%for hotstarting from the previous QP solution to the one of the next QP +%given by the matrices H, A and the vectors g, lb, ub, lbA, ubA. The previous +%active set serves as a starting guess. If the new projected Hessian matrix +%turns out to be not positive definite, qpOASES recedes to a safe initial active +%set guess automatically. This can result in a high number of iterations iter. +%Options can be generated using the qpOASES_options command, otherwise default +%values are used. +% +%IV) Call +% +% [x,lambda,workingSet] = qpOASES_sequence( 'e',QP,g,lb,ub,lbA,ubA{,options} ) +% +%for solving the equality constrained QP with constraints determined by the +%current active set. All inequalities and bounds which were not active in the +%previous solution might be violated. This command does not alter the internal +%state of qpOASES. Instead of calling this command multiple times, it is +%possible to supply several columns simultaneously in g, lb, ub, lbA, and ubA. +%Options can be generated using the qpOASES_options command, otherwise default +%values are used. +% +%V) Having solved the last QP of your sequence, call +% +% qpOASES_sequence( 'c',QP ) +% +%in order to cleanup the internal memory. +% +% +%Optional outputs (only x is mandatory): +% x - Optimal primal solution vector (if exitflag==0). +% fval - Optimal objective function value (if exitflag==0). +% exitflag - 0: QP solved, +% 1: QP could not be solved within given number of iterations, +% -1: QP could not be solved due to an internal error, +% -2: QP is infeasible (and thus could not be solved), +% -3: QP is unbounded (and thus could not be solved). +% iter - Number of active set iterations actually performed. +% lambda - Optimal dual solution vector (if status==0). +% auxOutput - Struct containing auxiliary outputs as described below. +% +%The auxOutput struct contains the following entries: +% workingSet - The working set at point x. The working set is a subset +% of the active set (which is the set of all indices +% corresponding to bounds/constraints that hold with +% equality). The working set corresponds to bound/ +% constraint row vectors forming a linear independent set. +% The first nV elements correspond to the bounds, the last +% nC elements to the constraints. +% The working set is encoded as follows: +% 1: bound/constraint at its upper bound +% 0: bound/constraint not at any bound +% -1: bound/constraint at its lower bound +% cpuTime - Internally measured CPU time for solving QP. +% +%See also QPOASES_OPTIONS, QPOASES_AUXINPUT, QPOASES +% +% +%For additional information see the qpOASES User's Manual or +%visit http://www.qpOASES.org/. +% +%Please send remarks and questions to support@qpOASES.org! diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/clean b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/clean new file mode 100644 index 00000000000..2957397008a --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/clean @@ -0,0 +1,3 @@ +rm *.*~ +rm *.o +rm qpOASES qpOASES_sequence diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/clean.sh b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/clean.sh new file mode 100644 index 00000000000..2957397008a --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/clean.sh @@ -0,0 +1,3 @@ +rm *.*~ +rm *.o +rm qpOASES qpOASES_sequence diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1.mat b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1.mat new file mode 100644 index 0000000000000000000000000000000000000000..c0bd0d2ed4364ebaf2b16eeb1791b99510164d60 GIT binary patch literal 790 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQgHY2i?A@$QE)CwO)N=GQOM7; zQV7W?Rq#(PQBW{ZFtoHXwy-iZQZOA%wc4c5GZW8!2gYzq2v=QA4sbvTq}xwN{M9( rdcH+H=e>2)6PUUhjxboKF`MIYAV|YGPpF2pgrpzeL4oIZl~o4-!Xx*U literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1a.mat b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1a.mat new file mode 100644 index 0000000000000000000000000000000000000000..48c784fcb7c53eedc3b3124e3577f8d0822e1cb2 GIT binary patch literal 896 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQgHY2i?A@$QE)CwO)N=GQOM7; zQV7W?Rq#(PQBW{ZFtoHXwzM)dRWLFzFjpWIFfe-h@-r|n=m2rWoX5!t2^A%wc4c5GZW8!2gYzq2v=QA4sbvTq}xwN{M9( zdcH+H=e>2)6PUUhjxboKF`MIYAV|YGPpF2pgrpzeL4oIZl~o6%$pCIk2ePk#sWRk@ zvYq}`8INM7jZDluH5=M5@Ec?>oIk~G0n(=h*N5UdV9K1r)@ga{`O<04M`r+2CliB_ HDN`x{YE&BX literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1b.mat b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/example1b.mat new file mode 100644 index 0000000000000000000000000000000000000000..b45b4f74c6a935c350dac6de0673396f20801338 GIT binary patch literal 549 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQgHY2i?A@$QE)CwO)N=GQOM7; zQV7W?Rq#(PQBW{ZFtoHXwy-iXRWLFzFjpWIFfe-h@-r|n=m2rWoX5!t2^Gx%BvR z(CJ1KbpdXJ0|(fvIsP7&V$n literal 0 HcmV?d00001 diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/index.html b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/index.html new file mode 100644 index 00000000000..6383f5f1115 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/index.html @@ -0,0 +1,21 @@ +qpOASES - Revision 198: /stable/3.0/interfaces/octave + +

qpOASES - Revision 198: /stable/3.0/interfaces/octave

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/make.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/make.m new file mode 100644 index 00000000000..28cef5fc907 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/make.m @@ -0,0 +1,238 @@ +function [] = make( varargin ) +%MAKE Compiles the octave interface of qpOASES. +% +%Type make to compile all interfaces that +% have been modified, +%type make clean to delete all compiled interfaces, +%type make clean all to first delete and then compile +% all interfaces, +%type make 'name' to compile only the interface with +% the given name (if it has been modified), +%type make 'opt' to compile all interfaces using the +% given compiler options. +% +%Copyright (C) 2013-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. + +%% +%% This file is part of qpOASES. +%% +%% qpOASES -- An Implementation of the Online Active Set Strategy. +%% Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%% Christian Kirches et al. All rights reserved. +%% +%% qpOASES is free software; you can redistribute it and/or +%% modify it under the terms of the GNU Lesser General Public +%% License as published by the Free Software Foundation; either +%% version 2.1 of the License, or (at your option) any later version. +%% +%% qpOASES is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%% See the GNU Lesser General Public License for more details. +%% +%% You should have received a copy of the GNU Lesser General Public +%% License along with qpOASES; if not, write to the Free Software +%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +%% + +%% +%% Filename: interfaces/octave/make.m +%% Author: Hans Joachim Ferreau, Andreas Potschka, Christian Kirches +%% Version: 3.0 +%% Date: 2007-2014 +%% + + + %% consistency check + if ( exist( [pwd, '/make.m'],'file' ) == 0 ) + error( ['ERROR (',mfilename '.m): Run this make script directly within the directory', ... + '/interfaces/octave, please.'] ); + end + + + if ( nargin > 2 ) + error( ['ERROR (',mfilename '.m): At most two make arguments supported!'] ); + else + [ doClean,fcnNames,userFlags ] = analyseMakeArguments( nargin,varargin ); + end + + + %% define compiler settings + QPOASESPATH = '../../'; + + DEBUGFLAGS = ' '; + %DEBUGFLAGS = ' -g CXXDEBUGFLAGS=''$CXXDEBUGFLAGS -Wall -pedantic -Wshadow'' '; + + IFLAGS = [ '-I. -I',QPOASESPATH,'include',' -I',QPOASESPATH,'src',' ' ]; + CPPFLAGS = [ IFLAGS, DEBUGFLAGS, '-D__cpluplus -D__MATLAB__ -D__SINGLE_OBJECT__',' ' ]; %%removed: -largeArrayDims + defaultFlags = '-D__NO_COPYRIGHT__ '; %% -D__NO_COPYRIGHT__ -D__SUPPRESSANYOUTPUT__ %%removed: -O + + if ( ispc == 0 ) + CPPFLAGS = [ CPPFLAGS, '-DLINUX ',' ' ]; + else + CPPFLAGS = [ CPPFLAGS, '-DWIN32 ',' ' ]; + end + + if ( isempty(userFlags) > 0 ) + CPPFLAGS = [ CPPFLAGS, defaultFlags,' ' ]; + else + CPPFLAGS = [ CPPFLAGS, userFlags,' ' ]; + end + + mexExt = mexext(); + + + %% ensure copyright notice is displayed + if ~isempty( strfind( CPPFLAGS,'-D__NO_COPYRIGHT__' ) ) + printCopyrightNotice( ); + end + + + %% clean if desired + if ( doClean > 0 ) + + eval( 'delete *.o;' ); + eval( ['delete *.',mexExt,'*;'] ); + disp( [ 'INFO (',mfilename '.m): Cleaned all compiled files.'] ); + pause( 0.2 ); + + end + + + if ( ~isempty(userFlags) ) + disp( [ 'INFO (',mfilename '.m): Compiling all files with user-defined compiler flags (''',userFlags,''')...'] ); + end + + + %% call mex compiler + for ii=1:length(fcnNames) + + cmd = [ 'mkoctfile --mex --output ', fcnNames{ii}, '.', mexext(), ' ', CPPFLAGS, [fcnNames{ii},'.cpp'] ]; + + if ( exist( [fcnNames{ii},'.',mexExt],'file' ) == 0 ) + + eval( cmd ); + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' successfully created.'] ); + + else + + % check modification time of source/Make files and compiled mex file + cppFile = dir( [pwd,'/',fcnNames{ii},'.cpp'] ); + cppFileTimestamp = getTimestamp( cppFile.date ); + + utilsFile = dir( [pwd,'/qpOASES_octave_utils.cpp'] ); + utilsFileTimestamp = getTimestamp( utilsFile.date ); + + makeFile = dir( [pwd,'/make.m'] ); + makeFileTimestamp = getTimestamp( makeFile.date ); + + mexFile = dir( [pwd,'/',fcnNames{ii},'.',mexExt] ); + if ( isempty(mexFile) == 0 ) + mexFileTimestamp = getTimestamp( mexFile.date ); + else + mexFileTimestamp = 0; + end + + if ( ( cppFileTimestamp >= mexFileTimestamp ) || ... + ( utilsFileTimestamp >= mexFileTimestamp ) || ... + ( makeFileTimestamp >= mexFileTimestamp ) ) + eval( cmd ); + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' successfully created.'] ); + else + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' already exists.'] ); + end + + end + + end + + %% add qpOASES directory to path + path( path,pwd ); + +end + + +function [ doClean,fcnNames,userIFlags ] = analyseMakeArguments( nArgs,args ) + + doClean = 0; + fcnNames = []; + userIFlags = []; + + switch ( nArgs ) + + case 1 + if ( strcmp( args{1},'all' ) > 0 ) + fcnNames = { 'qpOASES','qpOASES_sequence' }; + elseif ( strcmp( args{1},'qpOASES' ) > 0 ) + fcnNames = { 'qpOASES' }; + elseif ( strcmp( args{1},'qpOASES_sequence' ) > 0 ) + fcnNames = { 'qpOASES_sequence' }; + elseif ( strcmp( args{1},'clean' ) > 0 ) + doClean = 1; + elseif ( strcmp( args{1}(1),'-' ) > 0 ) + % make clean all with user-specified compiler flags + userIFlags = args{1}; + doClean = 1; + fcnNames = { 'qpOASES','qpOASES_sequence' }; + else + error( ['ERROR (',mfilename '.m): Invalid first argument (''',args{1},''')!'] ); + end + + case 2 + if ( strcmp( args{1},'clean' ) > 0 ) + doClean = 1; + else + error( ['ERROR (',mfilename '.m): First argument must be ''clean'' if two arguments are provided!'] ); + end + + if ( strcmp( args{2},'all' ) > 0 ) + fcnNames = { 'qpOASES','qpOASES_sequence' }; + elseif ( strcmp( args{2},'qpOASES' ) > 0 ) + fcnNames = { 'qpOASES' }; + elseif ( strcmp( args{2},'qpOASES_sequence' ) > 0 ) + fcnNames = { 'qpOASES_sequence' }; + else + error( ['ERROR (',mfilename '.m): Invalid second argument (''',args{2},''')!'] ); + end + + otherwise + fcnNames = { 'qpOASES','qpOASES_sequence' }; + + end + +end + + +function [ timestamp ] = getTimestamp( dateString ) + + try + timestamp = datenum( dateString ); + catch + timestamp = Inf; + end + +end + + +function [ ] = printCopyrightNotice( ) + + disp( ' ' ); + disp( 'qpOASES -- An Implementation of the Online Active Set Strategy.' ); + disp( 'Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka,' ); + disp( 'Christian Kirches et al. All rights reserved.' ); + disp( ' ' ); + disp( 'qpOASES is distributed under the terms of the' ); + disp( 'GNU Lesser General Public License 2.1 in the hope that it will be' ); + disp( 'useful, but WITHOUT ANY WARRANTY; without even the implied warranty' ); + disp( 'of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.' ); + disp( 'See the GNU Lesser General Public License for more details.' ); + disp( ' ' ); + disp( ' ' ); + +end + + +%% +%% end of file +%% diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES.cpp new file mode 100644 index 00000000000..32aaf7ed9f7 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES.cpp @@ -0,0 +1,557 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/octave/qpOASES.cpp + * \author Hans Joachim Ferreau, Alexander Buchner, Andreas Potschka + * \version 3.0 + * \date 2007-2014 + * + * Interface for Matlab(R) that enables to call qpOASES as a MEX function. + * + */ + + +#include + + +USING_NAMESPACE_QPOASES + + +#include "qpOASES_octave_utils.hpp" + +/** initialise handle counter of QPInstance class */ +int QPInstance::s_nexthandle = 1; + +/** global pointer to QP objects */ +static std::vector g_instances; + +#include "qpOASES_octave_utils.cpp" + + +/* + * q p O A S E S m e x _ c o n s t r a i n t s + */ +int qpOASESmex_constraints( int nV, int nC, int nP, + SymmetricMatrix *H, real_t* g, Matrix *A, + real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int nWSRin, real_t maxCpuTimeIn, + real_t* x0, Options* options, + int nOutputs, mxArray* plhs[], + double* guessedBounds, double* guessedConstraints + ) +{ + int nWSRout; + real_t maxCpuTimeOut; + + /* 1) Setup initial QP. */ + QProblem QP( nV,nC ); + QP.setOptions( *options ); + + /* 2) Solve initial QP. */ + returnValue returnvalue; + + Bounds bounds(nV); + Constraints constraints(nC); + if (guessedBounds != 0) { + for (int i = 0; i < nV; i++) { + if ( isEqual(guessedBounds[i],-1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_LOWER); + } else if ( isEqual(guessedBounds[i],1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_UPPER); + } else if ( isEqual(guessedBounds[i],0.0) == BT_TRUE ) { + bounds.setupBound(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of bounds!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + if (guessedConstraints != 0) { + for (int i = 0; i < nC; i++) { + if ( isEqual(guessedConstraints[i],-1.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_LOWER); + } else if ( isEqual(guessedConstraints[i],1.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_UPPER); + } else if ( isEqual(guessedConstraints[i],0.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of constraints!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + nWSRout = nWSRin; + maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + if (x0 == 0 && guessedBounds == 0 && guessedConstraints == 0) + returnvalue = QP.init( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut); + else + returnvalue = QP.init( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut, x0, 0, + guessedBounds != 0 ? &bounds : 0, + guessedConstraints != 0 ? &constraints : 0); + + /* 3) Solve remaining QPs and assign lhs arguments. */ + /* Set up pointers to the current QP vectors */ + real_t* g_current = g; + real_t* lb_current = lb; + real_t* ub_current = ub; + real_t* lbA_current = lbA; + real_t* ubA_current = ubA; + + /* Loop through QP sequence. */ + for ( int k=0; k 0 ) + { + /* update pointers to the current QP vectors */ + g_current = &(g[k*nV]); + if ( lb != 0 ) + lb_current = &(lb[k*nV]); + if ( ub != 0 ) + ub_current = &(ub[k*nV]); + if ( lbA != 0 ) + lbA_current = &(lbA[k*nC]); + if ( ubA != 0 ) + ubA_current = &(ubA[k*nC]); + + nWSRout = nWSRin; + maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + returnvalue = QP.hotstart( g_current,lb_current,ub_current,lbA_current,ubA_current, nWSRout,&maxCpuTimeOut ); + } + + /* write results into output vectors */ + obtainOutputs( k,&QP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,nV,nC ); + } + + //QP.writeQpDataIntoMatFile( "qpDataMat0.mat" ); + + return 0; +} + + + +/* + * q p O A S E S m e x _ b o u n d s + */ +int qpOASESmex_bounds( int nV, int nP, + SymmetricMatrix *H, real_t* g, + real_t* lb, real_t* ub, + int nWSRin, real_t maxCpuTimeIn, + real_t* x0, Options* options, + int nOutputs, mxArray* plhs[], + double* guessedBounds + ) +{ + int nWSRout; + real_t maxCpuTimeOut; + + /* 1) Setup initial QP. */ + QProblemB QP( nV ); + QP.setOptions( *options ); + + /* 2) Solve initial QP. */ + returnValue returnvalue; + + Bounds bounds(nV); + if (guessedBounds != 0) { + for (int i = 0; i < nV; i++) { + if ( isEqual(guessedBounds[i],-1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_LOWER); + } else if ( isEqual(guessedBounds[i],1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_UPPER); + } else if ( isEqual(guessedBounds[i],0.0) == BT_TRUE ) { + bounds.setupBound(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of bounds!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + nWSRout = nWSRin; + maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + if (x0 == 0 && guessedBounds == 0) + returnvalue = QP.init( H,g,lb,ub, nWSRout,&maxCpuTimeOut ); + else + returnvalue = QP.init( H,g,lb,ub, nWSRout,&maxCpuTimeOut, x0, 0, + guessedBounds != 0 ? &bounds : 0); + + /* 3) Solve remaining QPs and assign lhs arguments. */ + /* Set up pointers to the current QP vectors */ + real_t* g_current = g; + real_t* lb_current = lb; + real_t* ub_current = ub; + + /* Loop through QP sequence. */ + for ( int k=0; k 0 ) + { + /* update pointers to the current QP vectors */ + g_current = &(g[k*nV]); + if ( lb != 0 ) + lb_current = &(lb[k*nV]); + if ( ub != 0 ) + ub_current = &(ub[k*nV]); + + nWSRout = nWSRin; + maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + returnvalue = QP.hotstart( g_current,lb_current,ub_current, nWSRout,&maxCpuTimeOut ); + } + + /* write results into output vectors */ + obtainOutputs( k,&QP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,nV ); + } + + return 0; +} + + + +/* + * m e x F u n c t i o n + */ +void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] ) +{ + /* inputs */ + SymmetricMatrix *H=0; + Matrix *A=0; + real_t *g=0, *lb=0, *ub=0, *lbA=0, *ubA=0, *x0=0; + int H_idx, g_idx, A_idx, lb_idx, ub_idx, lbA_idx, ubA_idx, options_idx=-1, x0_idx=-1, auxInput_idx=-1; + + double *guessedBoundsAndConstraints = 0; + double *guessedBounds = 0, *guessedConstraints = 0; + + /* Setup default options */ + Options options; + options.printLevel = PL_LOW; + #ifdef __DEBUG__ + options.printLevel = PL_HIGH; + #endif + #ifdef __SUPPRESSANYOUTPUT__ + options.printLevel = PL_NONE; + #endif + + /* dimensions */ + unsigned int nV=0, nC=0, nP=0; + BooleanType isSimplyBoundedQp = BT_FALSE; + + /* sparse matrix indices and values */ + sparse_int_t *Hir = 0, *Hjc = 0, *Air = 0, *Ajc = 0; + real_t *Hv = 0, *Av = 0; + + /* I) CONSISTENCY CHECKS: */ + /* 1a) Ensure that qpOASES is called with a feasible number of input arguments. */ + if ( ( nrhs < 4 ) || ( nrhs > 9 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES' for further information." ); + return; + } + + /* 2) Check for proper number of output arguments. */ + if ( nlhs > 6 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): At most six output arguments are allowed: \n [x,fval,exitflag,iter,lambda,workingSet]!" ); + return; + } + if ( nlhs < 1 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): At least one output argument is required: [x,...]!" ); + return; + } + + + /* II) PREPARE RESPECTIVE QPOASES FUNCTION CALL: */ + /* Choose between QProblem and QProblemB object and assign the corresponding + * indices of the input pointer array in to order to access QP data correctly. */ + H_idx = 0; + g_idx = 1; + nV = (int)mxGetM( prhs[ H_idx ] ); /* row number of Hessian matrix */ + nP = (int)mxGetN( prhs[ g_idx ] ); /* number of columns of the gradient matrix (vectors series have to be stored columnwise!) */ + + if ( nrhs <= 6 ) + isSimplyBoundedQp = BT_TRUE; + else + isSimplyBoundedQp = BT_FALSE; + + + /* 0) Check whether options are specified .*/ + if ( isSimplyBoundedQp == BT_TRUE ) + { + if ( ( nrhs >= 5 ) && ( !mxIsEmpty(prhs[4]) ) && ( mxIsStruct(prhs[4]) ) ) + options_idx = 4; + } + else + { + /* Consistency check */ + if ( ( !mxIsEmpty(prhs[4]) ) && ( mxIsStruct(prhs[4]) ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Fifth input argument must not be a struct when solving QP with general constraints!\nType 'help qpOASES' for further information." ); + return; + } + + if ( ( nrhs >= 8 ) && ( !mxIsEmpty(prhs[7]) ) && ( mxIsStruct(prhs[7]) ) ) + options_idx = 7; + } + + // Is the third argument constraint Matrix A? + int numberOfColumns = (int)mxGetN(prhs[2]); + + /* 1) Simply bounded QP. */ + if ( ( isSimplyBoundedQp == BT_TRUE ) || + ( ( numberOfColumns == 1 ) && ( nV != 1 ) ) ) + { + lb_idx = 2; + ub_idx = 3; + + if ( ( nrhs >= 6 ) && ( !mxIsEmpty(prhs[5]) ) ) + { + /* auxInput specified */ + if ( mxIsStruct(prhs[5]) ) + { + auxInput_idx = 5; + x0_idx = -1; + } + else + { + auxInput_idx = -1; + x0_idx = 5; + } + } + else + { + auxInput_idx = -1; + x0_idx = -1; + } + } + else + { + A_idx = 2; + + /* If constraint matrix is empty, use a QProblemB object! */ + if ( mxIsEmpty( prhs[ A_idx ] ) ) + { + lb_idx = 3; + ub_idx = 4; + + nC = 0; + } + else + { + lb_idx = 3; + ub_idx = 4; + lbA_idx = 5; + ubA_idx = 6; + + nC = (int)mxGetM( prhs[ A_idx ] ); /* row number of constraint matrix */ + } + + if ( ( nrhs >= 9 ) && ( !mxIsEmpty(prhs[8]) ) ) + { + /* auxInput specified */ + if ( mxIsStruct(prhs[8]) ) + { + auxInput_idx = 8; + x0_idx = -1; + } + else + { + auxInput_idx = -1; + x0_idx = 8; + } + } + else + { + auxInput_idx = -1; + x0_idx = -1; + } + } + + + /* ensure that data is given in real_t precision */ + if ( ( mxIsDouble( prhs[ H_idx ] ) == 0 ) || + ( mxIsDouble( prhs[ g_idx ] ) == 0 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in double precision!" ); + return; + } + + /* check if supplied data contains 'NaN' or 'Inf' */ + if (containsNaNorInf(prhs, nV * nV, H_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + if ( mxGetN( prhs[ H_idx ] ) != nV ) + { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Hessian matrix input dimension mismatch (%ld != %d)!", + (long int)mxGetN(prhs[H_idx]), nV); + myMexErrMsgTxt(msg); + return; + } + + if ( nC > 0 ) + { + /* ensure that data is given in real_t precision */ + if ( mxIsDouble( prhs[ A_idx ] ) == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in real_t precision!" ); + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + if ( mxGetN( prhs[ A_idx ] ) != nV ) + { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Constraint matrix input dimension mismatch (%ld != %d)!", + (long int)mxGetN(prhs[A_idx]), nV); + myMexErrMsgTxt(msg); + return; + } + + if (containsNaNorInf(prhs, nV * nC, A_idx, 0) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + } + + /* check dimensions and copy auxInputs */ + if ( smartDimensionCheck( &g,nV,nP, BT_FALSE,prhs,g_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,nP, BT_TRUE,prhs,lb_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,nP, BT_TRUE,prhs,ub_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &x0,nV,1, BT_TRUE,prhs,x0_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( nC > 0 ) + { + if ( smartDimensionCheck( &lbA,nC,nP, BT_TRUE,prhs,lbA_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,nP, BT_TRUE,prhs,ubA_idx ) != SUCCESSFUL_RETURN ) + return; + } + + if ( auxInput_idx >= 0 ) + setupAuxiliaryInputs( prhs[auxInput_idx],nV,nC, &x0,&guessedBoundsAndConstraints,&guessedBounds,&guessedConstraints ); + + + /* III) ACTUALLY PERFORM QPOASES FUNCTION CALL: */ + int nWSRin = 5*(nV+nC); + real_t maxCpuTimeIn = -1.0; + + if ( options_idx > 0 ) + setupOptions( &options,prhs[options_idx],nWSRin,maxCpuTimeIn ); + + /* make a deep-copy of the user-specified Hessian matrix (possibly sparse) */ + setupHessianMatrix( prhs[H_idx],nV, &H,&Hir,&Hjc,&Hv ); + + /* make a deep-copy of the user-specified constraint matrix (possibly sparse) */ + if ( nC > 0 ) + setupConstraintMatrix( prhs[A_idx],nV,nC, &A,&Air,&Ajc,&Av ); + + allocateOutputs( nlhs,plhs,nV,nC,nP ); + + if ( nC == 0 ) + { + /* Call qpOASES (using QProblemB class). */ + qpOASESmex_bounds( nV,nP, + H,g, + lb,ub, + nWSRin,maxCpuTimeIn, + x0,&options, + nlhs,plhs, + guessedBounds + ); + + deleteAuxiliaryInputs( &guessedBounds,0 ); + delete H; + if (Hv != 0) delete[] Hv; + if (Hjc != 0) delete[] Hjc; + if (Hir != 0) delete[] Hir; + return; + } + else + { + /* Call qpOASES (using QProblem class). */ + qpOASESmex_constraints( nV,nC,nP, + H,g,A, + lb,ub,lbA,ubA, + nWSRin,maxCpuTimeIn, + x0,&options, + nlhs,plhs, + guessedBounds, guessedConstraints + ); + + deleteAuxiliaryInputs( &guessedBounds,&guessedConstraints ); + delete A; + delete H; + if (Av != 0) delete[] Av; + if (Ajc != 0) delete[] Ajc; + if (Air != 0) delete[] Air; + if (Hv != 0) delete[] Hv; + if (Hjc != 0) delete[] Hjc; + if (Hir != 0) delete[] Hir; + return; + } +} + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES.m new file mode 100644 index 00000000000..970a446414c --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES.m @@ -0,0 +1,77 @@ +%qpOASES -- An Implementation of the Online Active Set Strategy. +%Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. +% +%qpOASES is distributed under the terms of the +%GNU Lesser General Public License 2.1 in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%See the GNU Lesser General Public License for more details. +% +%--------------------------------------------------------------------------------- +% +%qpOASES solves (a series) of quadratic programming (QP) problems of the +%following form: +% +% min 1/2*x'Hx + x'g +% s.t. lb <= x <= ub +% lbA <= Ax <= ubA {optional} +% +%Call +% +% [x,fval,exitflag,iter,lambda,auxOutput] = +% qpOASES( H,g,A,lb,ub,lbA,ubA{,options{,auxInput} ) +% +%for solving the above-mentioned QP. H must be a symmetric (but possibly +%indefinite) matrix and all vectors g, lb, ub, lbA, ubA have to be given +%as column vectors. Options can be generated using the qpOASES_options command, +%otherwise default values are used. Optionally, further auxiliary inputs +%may be generated using qpOASES_auxInput command and passed to the solver. +%Both matrices H or A may be passed in sparse matrix format. +% +%Call +% +% [x,fval,exitflag,iter,lambda,auxOutput] = +% qpOASES( H,g,lb,ub{,options{,auxInput} ) +% +%for solving the above-mentioned QP without general constraints. +% +% +%Optional outputs (only x is mandatory): +% x - Optimal primal solution vector (if exitflag==0). +% fval - Optimal objective function value (if exitflag==0). +% exitflag - 0: QP problem solved, +% 1: QP could not be solved within given number of iterations, +% -1: QP could not be solved due to an internal error, +% -2: QP is infeasible (and thus could not be solved), +% -3: QP is unbounded (and thus could not be solved). +% iter - Number of active set iterations actually performed. +% lambda - Optimal dual solution vector (if status==0). +% auxOutput - Struct containing auxiliary outputs as described below. +% +%The auxOutput struct contains the following entries: +% workingSet - The working set at point x. The working set is a subset +% of the active set (which is the set of all indices +% corresponding to bounds/constraints that hold with +% equality). The working set corresponds to bound/ +% constraint row vectors forming a linear independent set. +% The first nV elements correspond to the bounds, the last +% nC elements to the constraints. +% The working set is encoded as follows: +% 1: bound/constraint at its upper bound +% 0: bound/constraint not at any bound +% -1: bound/constraint at its lower bound +% cpuTime - Internally measured CPU time for solving QP. +% +% +%If not a single QP but a sequence of QPs with varying vectors is to be solved, +%the i-th QP is given by the i-th columns of the QP vectors g, lb, ub, lbA, ubA +%(i.e. they are matrices in this case). Both matrices H and A remain constant. +% +%See also QPOASES_OPTIONS, QPOASES_AUXINPUT, QPOASES_SEQUENCE +% +% +%For additional information see the qpOASES User's Manual or +%visit http://www.qpOASES.org/. +% +%Please send remarks and questions to support@qpOASES.org! diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_auxInput.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_auxInput.m new file mode 100644 index 00000000000..cd27e656909 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_auxInput.m @@ -0,0 +1,103 @@ +%qpOASES -- An Implementation of the Online Active Set Strategy. +%Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. +% +%qpOASES is distributed under the terms of the +%GNU Lesser General Public License 2.1 in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%See the GNU Lesser General Public License for more details. +% +%--------------------------------------------------------------------------------- +% +%Returns a struct containing all possible auxiliary inputs to be passed +%to qpOASES. +% +%Call +% auxInput = qpOASES_auxInput(); +%to obtain a struct with all auxiliary inputs empty. +% +%Call +% options = qpOASES_auxInput( 'input1',value1,'input2',value2,... ) +%to obtain a struct with 'input1' set to value1 etc. and all remaining +%auxiliary inputs empty. +% +%Call +% options = qpOASES_auxInput( oldInputs,'input1',value1,... ) +%to obtain a copy of the options struct oldInputs but with 'input1' set to +%value1 etc. +% +% +%qpOASES features the following auxiliary inputs: +% x0 - Initial guess for optimal primal solution. +% guessedWorkingSet - Initial guess for working set at optimal +% solution. The first nV elements correspond +% to the bounds, the last nC elements to the +% constraints. +% The working set needs to be encoded as follows: +% 1: bound/constraint at its upper bound +% 0: bound/constraint not at any bound +% -1: bound/constraint at its lower bound +% +% +%See also QPOASES, QPOASES_SEQUENCE, QPOASES_OPTIONS +% +% +%For additional information see the qpOASES User's Manual or +%visit http://www.qpOASES.org/. +% +%Please send remarks and questions to support@qpOASES.org! +function [ auxInput ] = qpOASES_auxInput( varargin ) + + firstIsStruct = 0; + + if ( nargin == 0 ) + auxInput = qpOASES_emptyAuxInput(); + else + if ( isstruct( varargin{1} ) ) + if ( mod( nargin,2 ) ~= 1 ) + error('ERROR (qpOASES_auxInput): Auxiliary inputs must be specified in pairs!'); + end + auxInput = varargin{1}; + firstIsStruct = 1; + else + if ( mod( nargin,2 ) ~= 0 ) + error('ERROR (qpOASES_auxInput): Auxiliary inputs must be specified in pairs!'); + end + auxInput = qpOASES_emptyAuxInput(); + end + end + + % set options to user-defined values + for i=(1+firstIsStruct):2:nargin + + argName = varargin{i}; + argValue = varargin{i+1}; + + if ( ( isempty( argName ) ) || ( ~ischar( argName ) ) ) + error('ERROR (qpOASES_auxInput): Argmument no. %d has to be a non-empty string!',i ); + end + + if ( ( ischar(argValue) ) || ( ~isnumeric( argValue ) ) ) + error('ERROR (qpOASES_auxInput): Argmument no. %d has to be a numerical constant!',i+1 ); + end + + if ( ~isfield( auxInput,argName ) ) + error('ERROR (qpOASES_auxInput): Argmument no. %d is not a valid auxiliary input!',i ); + end + + eval( ['auxInput.',argName,' = argValue;'] ); + + end + +end + + +function [ auxInput ] = qpOASES_emptyAuxInput( ) + + % setup auxiliary input struct with all entries empty + auxInput = struct( 'x0', [], ... + 'guessedWorkingSet', [] ... + ); + +end diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_octave_utils.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_octave_utils.cpp new file mode 100644 index 00000000000..7f75b721c8e --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_octave_utils.cpp @@ -0,0 +1,884 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/octave/qpOASES_octave_utils.cpp + * \author Hans Joachim Ferreau, Andreas Potschka, Alexander Buchner + * \version 3.0 + * \date 2007-2014 + * + * Collects utility functions for Interface to octave that + * enables to call qpOASES as a MEX function. + * + */ + + + +QPInstance::QPInstance( int _nV, int _nC, BooleanType _isSimplyBounded + ) +{ + handle = s_nexthandle++; + + if ( _nC > 0 ) + isSimplyBounded = BT_FALSE; + else + isSimplyBounded = _isSimplyBounded; + + if ( isSimplyBounded == BT_TRUE ) + { + sqp = 0; + qpb = new QProblemB( _nV ); + } + else + { + sqp = new SQProblem( _nV,_nC ); + qpb = 0; + } + + H = 0; + A = 0; + Hir = 0; + Hjc = 0; + Air = 0; + Ajc = 0; + Hv = 0; + Av = 0; +} + + +QPInstance::~QPInstance( ) +{ + deleteQPMatrices(); + + if ( sqp != 0 ) + { + delete sqp; + sqp = 0; + } + + if ( qpb != 0 ) + { + delete qpb; + qpb = 0; + } +} + + +returnValue QPInstance::deleteQPMatrices( ) +{ + if ( H != 0 ) + { + delete H; + H = 0; + } + + if (Hv != 0) + { + delete[] Hv; + Hv = 0; + } + + if (Hjc != 0) + { + delete[] Hjc; + Hjc = 0; + } + + if (Hir != 0) + { + delete[] Hir; + Hir = 0; + } + + if ( A != 0 ) + { + delete A; + A = 0; + } + + if (Av != 0) + { + delete[] Av; + Av = 0; + } + + if (Ajc != 0) + { + delete[] Ajc; + Ajc = 0; + } + + if (Air != 0) + { + delete[] Air; + Air = 0; + } + + return SUCCESSFUL_RETURN; +} + + +int QPInstance::getNV() const +{ + if ( sqp != 0 ) + return sqp->getNV(); + + if ( qpb != 0 ) + return qpb->getNV(); + + return 0; +} + + +int QPInstance::getNC() const +{ + if ( sqp != 0 ) + return sqp->getNC(); + + return 0; +} + + +/* + * a l l o c a t e Q P r o b l e m I n s t a n c e + */ +int allocateQPInstance( int nV, int nC, BooleanType isSimplyBounded, const Options *options + ) +{ + QPInstance* inst = new QPInstance( nV,nC,isSimplyBounded ); + + if ( inst->sqp != 0 ) + inst->sqp->setOptions ( *options ); + + if ( inst->qpb != 0 ) + inst->qpb->setOptions ( *options ); + + g_instances.push_back (inst); + return inst->handle; +} + + +/* + * g e t Q P r o b l e m I n s t a n c e + */ +QPInstance* getQPInstance( int handle ) +{ + unsigned int ii; + // TODO: this may become slow ... + for (ii = 0; ii < g_instances.size (); ++ii) + if (g_instances[ii]->handle == handle) + return g_instances[ii]; + return 0; +} + + +/* + * d e l e t e Q P r o b l e m I n s t a n c e + */ +void deleteQPInstance( int handle ) +{ + QPInstance *instance = getQPInstance (handle); + if (instance != 0) { + for (std::vector::iterator itor = g_instances.begin (); + itor != g_instances.end (); ++itor) + if ((*itor)->handle == handle) { + g_instances.erase (itor); + break; + } + delete instance; + } +} + + + +/* + * s m a r t D i m e n s i o n C h e c k + */ +returnValue smartDimensionCheck( real_t** input, unsigned int m, unsigned int n, BooleanType emptyAllowed, + const mxArray* prhs[], int idx + ) +{ + /* If index is negative, the input does not exist. */ + if ( idx < 0 ) + { + *input = 0; + return SUCCESSFUL_RETURN; + } + + /* Otherwise the input has been passed by the user. */ + if ( mxIsEmpty( prhs[ idx ] ) ) + { + /* input is empty */ + if ( ( emptyAllowed == BT_TRUE ) || ( idx == 0 ) ) /* idx==0 used for auxInput */ + { + *input = 0; + return SUCCESSFUL_RETURN; + } + else + { + char msg[MAX_STRING_LENGTH]; + if ( idx > 0 ) + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Empty argument %d not allowed!", idx+1); + myMexErrMsgTxt( msg ); + return RET_INVALID_ARGUMENTS; + } + } + else + { + /* input is non-empty */ + if ( mxIsSparse( prhs[ idx ] ) == 0 ) + { + if ( ( mxGetM( prhs[ idx ] ) == m ) && ( mxGetN( prhs[ idx ] ) == n ) ) + { + *input = (real_t*) mxGetPr( prhs[ idx ] ); + return SUCCESSFUL_RETURN; + } + else + { + char msg[MAX_STRING_LENGTH]; + if ( idx > 0 ) + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Input dimension mismatch for argument %d ([%ld,%ld] ~= [%d,%d]).", + idx+1, (long int)mxGetM(prhs[idx]), (long int)mxGetN(prhs[idx]), m, n); + else /* idx==0 used for auxInput */ + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Input dimension mismatch for some auxInput entry ([%ld,%ld] ~= [%d,%d]).", + (long int)mxGetM(prhs[idx]), (long int)mxGetN(prhs[idx]), m, n); + myMexErrMsgTxt( msg ); + return RET_INVALID_ARGUMENTS; + } + } + else + { + char msg[MAX_STRING_LENGTH]; + if ( idx > 0 ) + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Vector argument %d must not be in sparse format!", idx+1); + else /* idx==0 used for auxInput */ + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): auxInput entries must not be in sparse format!" ); + myMexErrMsgTxt( msg ); + return RET_INVALID_ARGUMENTS; + } + } + + return SUCCESSFUL_RETURN; +} + + + +/* + * c o n t a i n s N a N + */ +BooleanType containsNaN( const real_t* const data, int dim ) +{ + int i; + + if ( data == 0 ) + return BT_FALSE; + + for ( i = 0; i < dim; ++i ) + if ( mxIsNaN(data[i]) == 1 ) + return BT_TRUE; + + return BT_FALSE; +} + + +/* + * c o n t a i n s I n f + */ +BooleanType containsInf( const real_t* const data, int dim ) +{ + int i; + + if ( data == 0 ) + return BT_FALSE; + + for ( i = 0; i < dim; ++i ) + if ( mxIsInf(data[i]) == 1 ) + return BT_TRUE; + + return BT_FALSE; +} + + +/* + * c o n t a i n s N a N o r I n f + */ +BooleanType containsNaNorInf(const mxArray* prhs[], int dim, int rhs_index, + bool mayContainInf) { + + char msg[MAX_STRING_LENGTH]; + + // overwrite dim for sparse matrices + if (mxIsSparse(prhs[rhs_index]) == 1) { + dim = mxGetNzmax(prhs[rhs_index]); + } + + if (containsNaN((real_t*) mxGetPr(prhs[rhs_index]), dim) == BT_TRUE) { + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Argument %d contains 'NaN' !", rhs_index + 1); + myMexErrMsgTxt(msg); + return BT_TRUE; + } + + if (mayContainInf == 0) { + if (containsInf((real_t*) mxGetPr(prhs[rhs_index]), dim) == BT_TRUE) { + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Argument %d contains 'Inf' !", + rhs_index + 1); + myMexErrMsgTxt(msg); + return BT_TRUE; + } + } + + return BT_FALSE; +} + + +/* + * c o n v e r t F o r t r a n T o C + */ +returnValue convertFortranToC( const real_t* const A_for, int nV, int nC, real_t* const A ) +{ + int i,j; + + for ( i=0; i = ; */ + if ( mxGetNumberOfFields(optionsPtr) != 31 ) + mexWarnMsgTxt( "Options might be set incorrectly as struct has wrong number of entries!\n Type 'help qpOASES_options' for further information." ); + + + if ( hasOptionsValue( optionsPtr,"maxIter",&optionValue ) == BT_TRUE ) + if ( *optionValue >= 0.0 ) + nWSRin = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"maxCpuTime",&optionValue ) == BT_TRUE ) + if ( *optionValue >= 0.0 ) + maxCpuTime = *optionValue; + + if ( hasOptionsValue( optionsPtr,"printLevel",&optionValue ) == BT_TRUE ) + { + #ifdef __SUPPRESSANYOUTPUT__ + options->printLevel = PL_NONE; + #else + optionValueInt = (int)*optionValue; + options->printLevel = (REFER_NAMESPACE_QPOASES PrintLevel)optionValueInt; + if ( options->printLevel < PL_DEBUG_ITER ) + options->printLevel = PL_DEBUG_ITER; + if ( options->printLevel > PL_HIGH ) + options->printLevel = PL_HIGH; + #endif + } + + if ( hasOptionsValue( optionsPtr,"enableRamping",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableRamping = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableFarBounds",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableFarBounds = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableFlippingBounds",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableFlippingBounds = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableRegularisation",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableRegularisation = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableFullLITests",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableFullLITests = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableNZCTests",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableNZCTests = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"enableDriftCorrection",&optionValue ) == BT_TRUE ) + options->enableDriftCorrection = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"enableCholeskyRefactorisation",&optionValue ) == BT_TRUE ) + options->enableCholeskyRefactorisation = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"enableEqualities",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + options->enableEqualities = (REFER_NAMESPACE_QPOASES BooleanType)optionValueInt; + } + + + if ( hasOptionsValue( optionsPtr,"terminationTolerance",&optionValue ) == BT_TRUE ) + options->terminationTolerance = *optionValue; + + if ( hasOptionsValue( optionsPtr,"boundTolerance",&optionValue ) == BT_TRUE ) + options->boundTolerance = *optionValue; + + if ( hasOptionsValue( optionsPtr,"boundRelaxation",&optionValue ) == BT_TRUE ) + options->boundRelaxation = *optionValue; + + if ( hasOptionsValue( optionsPtr,"epsNum",&optionValue ) == BT_TRUE ) + options->epsNum = *optionValue; + + if ( hasOptionsValue( optionsPtr,"epsDen",&optionValue ) == BT_TRUE ) + options->epsDen = *optionValue; + + if ( hasOptionsValue( optionsPtr,"maxPrimalJump",&optionValue ) == BT_TRUE ) + options->maxPrimalJump = *optionValue; + + if ( hasOptionsValue( optionsPtr,"maxDualJump",&optionValue ) == BT_TRUE ) + options->maxDualJump = *optionValue; + + + if ( hasOptionsValue( optionsPtr,"initialRamping",&optionValue ) == BT_TRUE ) + options->initialRamping = *optionValue; + + if ( hasOptionsValue( optionsPtr,"finalRamping",&optionValue ) == BT_TRUE ) + options->finalRamping = *optionValue; + + if ( hasOptionsValue( optionsPtr,"initialFarBounds",&optionValue ) == BT_TRUE ) + options->initialFarBounds = *optionValue; + + if ( hasOptionsValue( optionsPtr,"growFarBounds",&optionValue ) == BT_TRUE ) + options->growFarBounds = *optionValue; + + if ( hasOptionsValue( optionsPtr,"initialStatusBounds",&optionValue ) == BT_TRUE ) + { + optionValueInt = (int)*optionValue; + if ( optionValueInt < -1 ) + optionValueInt = -1; + if ( optionValueInt > 1 ) + optionValueInt = 1; + options->initialStatusBounds = (REFER_NAMESPACE_QPOASES SubjectToStatus)optionValueInt; + } + + if ( hasOptionsValue( optionsPtr,"epsFlipping",&optionValue ) == BT_TRUE ) + options->epsFlipping = *optionValue; + + if ( hasOptionsValue( optionsPtr,"numRegularisationSteps",&optionValue ) == BT_TRUE ) + options->numRegularisationSteps = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"epsRegularisation",&optionValue ) == BT_TRUE ) + options->epsRegularisation = *optionValue; + + if ( hasOptionsValue( optionsPtr,"numRefinementSteps",&optionValue ) == BT_TRUE ) + options->numRefinementSteps = (int)*optionValue; + + if ( hasOptionsValue( optionsPtr,"epsIterRef",&optionValue ) == BT_TRUE ) + options->epsIterRef = *optionValue; + + if ( hasOptionsValue( optionsPtr,"epsLITests",&optionValue ) == BT_TRUE ) + options->epsLITests = *optionValue; + + if ( hasOptionsValue( optionsPtr,"epsNZCTests",&optionValue ) == BT_TRUE ) + options->epsNZCTests = *optionValue; + + return SUCCESSFUL_RETURN; +} + + + +/* + * s e t u p A u x i l i a r y I n p u t s + */ +returnValue setupAuxiliaryInputs( const mxArray* auxInput, unsigned int nV, unsigned int nC, + double** x0, double** guessedBoundsAndConstraints, double** guessedBounds, double** guessedConstraints + ) +{ + unsigned int i; + mxArray* curField = 0; + + /* x0 */ + curField = mxGetField( auxInput,0,"x0" ); + if ( curField == NULL ) + mexWarnMsgTxt( "auxInput struct does not contain entry 'x0'!\n Type 'help qpOASES_auxInput' for further information." ); + else + { + *x0 = mxGetPr(curField); + if ( smartDimensionCheck( x0,nV,1, BT_TRUE,((const mxArray**)&curField),0 ) != SUCCESSFUL_RETURN ) + return RET_INVALID_ARGUMENTS; + } + + /* guessedWorkingSet */ + curField = mxGetField( auxInput,0,"guessedWorkingSet" ); + if ( curField == NULL ) + mexWarnMsgTxt( "auxInput struct does not contain entry 'guessedWorkingSet'!\n Type 'help qpOASES_auxInput' for further information." ); + else + { + *guessedBoundsAndConstraints = mxGetPr(curField); + if ( smartDimensionCheck( guessedBoundsAndConstraints,nV+nC,1, BT_TRUE,((const mxArray**)&curField),0 ) != SUCCESSFUL_RETURN ) + return RET_INVALID_ARGUMENTS; + + if ( *guessedBoundsAndConstraints != 0 ) + { + *guessedBounds = new double[nV]; + for (i = 0; i < nV; i++) + (*guessedBounds)[i] = (*guessedBoundsAndConstraints)[i]; + + if ( nC > 0 ) + { + *guessedConstraints = new double[nC]; + for (i = 0; i < nC; i++) + (*guessedConstraints)[i] = (*guessedBoundsAndConstraints)[i + nV]; + } + } + } + + return SUCCESSFUL_RETURN; +} + + +/* + * d e l e t e A u x i l i a r y I n p u t s + */ +returnValue deleteAuxiliaryInputs( double** guessedBounds, double** guessedConstraints + ) +{ + if ( ( guessedBounds != 0 ) && ( *guessedBounds != 0 ) ) + { + delete[] (*guessedBounds); + *guessedBounds = 0; + } + + if ( ( guessedConstraints != 0 ) && ( guessedConstraints != 0 ) ) + { + delete[] (*guessedConstraints); + *guessedConstraints = 0; + } + + return SUCCESSFUL_RETURN; +} + + + +/* + * a l l o c a t e O u t p u t s + */ +returnValue allocateOutputs( int nlhs, mxArray* plhs[], int nV, int nC = 0, int nP = 1, int handle = -1 + ) +{ + /* Create output vectors and assign pointers to them. */ + int curIdx = 0; + + /* handle */ + if ( handle >= 0 ) + plhs[curIdx++] = mxCreateDoubleMatrix( 1, 1, mxREAL ); + + /* x */ + plhs[curIdx++] = mxCreateDoubleMatrix( nV, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* fval */ + plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* exitflag */ + plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* iter */ + plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* lambda */ + plhs[curIdx++] = mxCreateDoubleMatrix( nV+nC, nP, mxREAL ); + + if ( nlhs > curIdx ) + { + /* setup auxiliary output struct */ + mxArray* auxOutput = mxCreateStructMatrix( 1,1,0,0 ); + int curFieldNum; + + /* working set */ + curFieldNum = mxAddField( auxOutput,"workingSet" ); + if ( curFieldNum >= 0 ) + mxSetFieldByNumber( auxOutput,0,curFieldNum,mxCreateDoubleMatrix( nV+nC, nP, mxREAL ) ); + + curFieldNum = mxAddField( auxOutput,"cpuTime" ); + if ( curFieldNum >= 0 ) + mxSetFieldByNumber( auxOutput,0,curFieldNum,mxCreateDoubleMatrix( 1, nP, mxREAL ) ); + + plhs[curIdx] = auxOutput; + } + } + } + } + } + + return SUCCESSFUL_RETURN; +} + + +/* + * o b t a i n O u t p u t s + */ +returnValue obtainOutputs( int k, QProblemB* qp, returnValue returnvalue, int _nWSRout, real_t _cpuTime, + int nlhs, mxArray* plhs[], int nV, int nC = 0, int handle = -1 + ) +{ + /* Create output vectors and assign pointers to them. */ + int curIdx = 0; + + /* handle */ + if ( handle >= 0 ) + plhs[curIdx++] = mxCreateDoubleScalar( handle ); + + /* x */ + double* x = mxGetPr( plhs[curIdx++] ); + qp->getPrimalSolution( &(x[k*nV]) ); + + if ( nlhs > curIdx ) + { + /* fval */ + double* obj = mxGetPr( plhs[curIdx++] ); + obj[k] = qp->getObjVal( ); + + if ( nlhs > curIdx ) + { + /* exitflag */ + double* status = mxGetPr( plhs[curIdx++] ); + status[k] = (real_t)getSimpleStatus( returnvalue ); + + if ( nlhs > curIdx ) + { + /* iter */ + double* nWSRout = mxGetPr( plhs[curIdx++] ); + nWSRout[k] = (real_t) _nWSRout; + + if ( nlhs > curIdx ) + { + /* lambda */ + double* y = mxGetPr( plhs[curIdx++] ); + qp->getDualSolution( &(y[k*(nV+nC)]) ); + + if ( nlhs > curIdx ) + { + + mxArray* auxOutput = plhs[curIdx]; + mxArray* curField = 0; + + /* working set */ + curField = mxGetField( auxOutput,0,"workingSet" ); + double* workingSet = mxGetPr(curField); + + QProblem* problemPointer; + problemPointer = dynamic_cast(qp); + + // cast successful? + if (problemPointer != NULL) { + problemPointer->getWorkingSet( &(workingSet[k*(nV+nC)]) ); + } else { + qp->getWorkingSet( &(workingSet[k*(nV+nC)]) ); + } + + /* cpu time */ + curField = mxGetField( auxOutput,0,"cpuTime" ); + double* cpuTime = mxGetPr(curField); + cpuTime[0] = (real_t) _cpuTime; + } + } + } + } + } + + return SUCCESSFUL_RETURN; +} + + + +/* + * s e t u p H e s s i a n M a t r i x + */ +returnValue setupHessianMatrix( const mxArray* prhsH, int nV, + SymmetricMatrix** H, sparse_int_t** Hir, sparse_int_t** Hjc, real_t** Hv + ) +{ + if ( mxIsSparse( prhsH ) != 0 ) + { + mwIndex *oct_ir = mxGetIr( prhsH ); + mwIndex *oct_jc = mxGetJc( prhsH ); + double *v = (double*)mxGetPr( prhsH ); + long nfill = 0; + long i, j; + BooleanType needInsertDiag; + + /* copy indices to avoid 64/32-bit integer confusion */ + /* also add explicit zeros on diagonal for regularization strategy */ + /* copy values, too */ + *Hir = new sparse_int_t[oct_jc[nV] + nV]; + *Hjc = new sparse_int_t[nV+1]; + *Hv = new real_t[oct_jc[nV] + nV]; + for (j = 0; j < nV; j++) + { + needInsertDiag = BT_TRUE; + + (*Hjc)[j] = (sparse_int_t)(oct_jc[j]) + nfill; + /* fill up to diagonal */ + for (i = oct_jc[j]; i < oct_jc[j+1]; i++) + { + if ( oct_ir[i] == j ) + needInsertDiag = BT_FALSE; + + /* add zero diagonal element if not present */ + if ( ( oct_ir[i] > j ) && ( needInsertDiag == BT_TRUE ) ) + { + (*Hir)[i + nfill] = (sparse_int_t)j; + (*Hv)[i + nfill] = 0.0; + nfill++; + /* only add diag once */ + needInsertDiag = BT_FALSE; + } + + (*Hir)[i + nfill] = (sparse_int_t)(oct_ir[i]); + (*Hv)[i + nfill] = (real_t)(v[i]); + } + } + (*Hjc)[nV] = (sparse_int_t)(oct_jc[nV]) + nfill; + + SymSparseMat *sH; + *H = sH = new SymSparseMat(nV, nV, *Hir, *Hjc, *Hv); + sH->createDiagInfo(); + } + else + { + /* make a deep-copy in order to avoid modifying input data when regularising */ + real_t* H_for = (real_t*) mxGetPr( prhsH ); + real_t* H_mem = new real_t[nV*nV]; + memcpy( H_mem,H_for, nV*nV*sizeof(real_t) ); + + *H = new SymDenseMat( nV,nV,nV, H_mem ); + (*H)->doFreeMemory( ); + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t u p C o n s t r a i n t M a t r i x + */ +returnValue setupConstraintMatrix( const mxArray* prhsA, int nV, int nC, + Matrix** A, sparse_int_t** Air, sparse_int_t** Ajc, real_t** Av + ) +{ + if ( mxIsSparse( prhsA ) != 0 ) + { + long i; + + mwIndex *oct_ir = mxGetIr( prhsA ); + mwIndex *oct_jc = mxGetJc( prhsA ); + double *v = (double*)mxGetPr( prhsA ); + + /* copy indices to avoid 64/32-bit integer confusion */ + *Air = new sparse_int_t[oct_jc[nV]]; + *Ajc = new sparse_int_t[nV+1]; + for (i = 0; i < oct_jc[nV]; i++) + (*Air)[i] = (sparse_int_t)(oct_ir[i]); + for (i = 0; i < nV + 1; i++) + (*Ajc)[i] = (sparse_int_t)(oct_jc[i]); + + /* copy values, too */ + *Av = new real_t[(*Ajc)[nV]]; + for (i = 0; i < (*Ajc)[nV]; i++) + (*Av)[i] = (real_t)(v[i]); + + *A = new SparseMatrix(nC, nV, *Air, *Ajc, *Av); + } + else + { + /* Convert constraint matrix A from FORTRAN to C style + * (not necessary for H as it should be symmetric!). */ + real_t* A_for = (real_t*) mxGetPr( prhsA ); + real_t* A_mem = new real_t[nC*nV]; + convertFortranToC( A_for,nV,nC, A_mem ); + *A = new DenseMatrix(nC, nV, nV, A_mem ); + (*A)->doFreeMemory(); + } + + return SUCCESSFUL_RETURN; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_octave_utils.hpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_octave_utils.hpp new file mode 100644 index 00000000000..5430fdeac44 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_octave_utils.hpp @@ -0,0 +1,92 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/octave/qpOASES_octave_utils.hpp + * \author Hans Joachim Ferreau, Andreas Potschka, Alexander Buchner + * \version 3.0 + * \date 2007-2014 + * + * Collects utility functions for Interface to octave that + * enables to call qpOASES as a MEX function. + * + */ + + + +/* Work-around for settings where mexErrMsgTxt causes unexpected behaviour. */ +#ifdef __AVOID_MEXERRMSGTXT__ + #define myMexErrMsgTxt( TEXT ) mexPrintf( "%s\n\n",(TEXT) ); +#else + #define myMexErrMsgTxt mexErrMsgTxt +#endif + + +#include "mex.h" +//#include "matrix.h" +#include "string.h" +#include + + +/* + * QProblem instance class + */ +class QPInstance +{ + private: + static int s_nexthandle; + + public: + QPInstance( int _nV = 0, + int _nC = 0, + BooleanType _isSimplyBounded = BT_FALSE + ); + + ~QPInstance( ); + + returnValue deleteQPMatrices(); + + int getNV() const; + int getNC() const; + + int handle; + + SQProblem* sqp; + QProblemB* qpb; + BooleanType isSimplyBounded; + + SymmetricMatrix* H; + Matrix* A; + sparse_int_t* Hir; + sparse_int_t* Hjc; + sparse_int_t* Air; + sparse_int_t* Ajc; + real_t* Hv; + real_t* Av; +}; + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_options.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_options.m new file mode 100644 index 00000000000..f3cd4175129 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_options.m @@ -0,0 +1,251 @@ +%qpOASES -- An Implementation of the Online Active Set Strategy. +%Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. +% +%qpOASES is distributed under the terms of the +%GNU Lesser General Public License 2.1 in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%See the GNU Lesser General Public License for more details. +% +%--------------------------------------------------------------------------------- +% +%Returns a struct containing values for all options to be used within qpOASES. +% +%Call +% options = qpOASES_options( 'default' ); +% options = qpOASES_options( 'reliable' ); +% options = qpOASES_options( 'MPC' ); +%to obtain a set of default options or a pre-defined set of options tuned +%for reliable or fast QP solution, respectively. +% +%Call +% options = qpOASES_options( 'option1',value1,'option2',value2,... ) +%to obtain a set of default options but with 'option1' set to value1 etc. +% +%Call +% options = qpOASES_options( oldopts,'option1',value1,... ) +%to obtain a copy of the options struct oldopts but with 'option1' set to +%value1 etc. +% +%Call +% options = qpOASES_options( 'default', 'option1',value1,... ) +% options = qpOASES_options( 'reliable','option1',value1,... ) +% options = qpOASES_options( 'MPC', 'option1',value1,... ) +%to obtain a set of default options or a pre-defined set of options tuned +%for reliable or fast QP solution, respectively, but with 'option1' set to +%value1 etc. +% +% +%qpOASES features the following options: +% maxIter - Maximum number of iterations (if set +% to -1, a value is chosen heuristically) +% maxCpuTime - Maximum CPU time in seconds (if set +% to -1, only iteration limit is used) +% printLevel - 0: no printed output, +% 1: only error messages are printed, +% 2: iterations and error messages are printed, +% 3: all available messages are printed. +% +% enableRamping - Enables (1) or disables (0) ramping. +% enableFarBounds - Enables (1) or disables (0) the use of +% far bounds. +% enableFlippingBounds - Enables (1) or disables (0) the use of +% flipping bounds. +% enableRegularisation - Enables (1) or disables (0) automatic +% Hessian regularisation. +% enableFullLITests - Enables (1) or disables (0) condition-hardened +% (but more expensive) LI test. +% enableNZCTests - Enables (1) or disables (0) nonzero curvature +% tests. +% enableDriftCorrection - Specifies the frequency of drift corrections: +% 0: turns them off, +% 1: uses them at each iteration etc. +% enableCholeskyRefactorisation - Specifies the frequency of a full re- +% factorisation of projected Hessian matrix: +% 0: turns them off, +% 1: uses them at each iteration etc. +% enableEqualities - Specifies whether equalities should be treated +% as always active (1) or not (0) +% +% terminationTolerance - Relative termination tolerance to stop homotopy. +% boundTolerance - If upper and lower bounds differ less than this +% tolerance, they are regarded equal, i.e. as +% equality constraint. +% boundRelaxation - Initial relaxation of bounds to start homotopy +% and initial value for far bounds. +% epsNum - Numerator tolerance for ratio tests. +% epsDen - Denominator tolerance for ratio tests. +% maxPrimalJump - Maximum allowed jump in primal variables in +% nonzero curvature tests. +% maxDualJump - Maximum allowed jump in dual variables in +% linear independence tests. +% +% initialRamping - Start value for ramping strategy. +% finalRamping - Final value for ramping strategy. +% initialFarBounds - Initial size for far bounds. +% growFarBounds - Factor to grow far bounds. +% initialStatusBounds - Initial status of bounds at first iteration: +% 0: all bounds inactive, +% -1: all bounds active at their lower bound, +% +1: all bounds active at their upper bound. +% epsFlipping - Tolerance of squared Cholesky diagonal factor +% which triggers flipping bound. +% numRegularisationSteps - Maximum number of successive regularisation steps. +% epsRegularisation - Scaling factor of identity matrix used for +% Hessian regularisation. +% numRefinementSteps - Maximum number of iterative refinement steps. +% epsIterRef - Early termination tolerance for iterative +% refinement. +% epsLITests - Tolerance for linear independence tests. +% epsNZCTests - Tolerance for nonzero curvature tests. +% +% +%See also QPOASES, QPOASES_SEQUENCE +% +% +%For additional information see the qpOASES User's Manual or +%visit http://www.qpOASES.org/. +% +%Please send remarks and questions to support@qpOASES.org! +function [ options ] = qpOASES_options( varargin ) + + firstIsStructOrScheme = 0; + + if ( nargin == 0 ) + options = qpOASES_default_options(); + else + if ( isstruct( varargin{1} ) ) + if ( mod( nargin,2 ) ~= 1 ) + error('ERROR (qpOASES_options): Options must be specified in pairs!'); + end + options = varargin{1}; + firstIsStructOrScheme = 1; + else + if ( ischar( varargin{1} ) ) + if ( mod( nargin,2 ) == 0 ) + options = qpOASES_default_options(); + else + if ( ( nargin > 1 ) && ( ischar( varargin{nargin} ) ) ) + error('ERROR (qpOASES_options): Options must be specified in pairs!'); + end + + switch ( varargin{1} ) + case 'default' + options = qpOASES_default_options(); + case 'reliable' + options = qpOASES_reliable_options(); + case {'MPC','mpc','fast'} + options = qpOASES_MPC_options(); + otherwise + error( ['ERROR (qpOASES_options): Only the following option schemes are defined: ''default'', ''reliable'', ''MPC''!'] ); + + end + firstIsStructOrScheme = 1; + end + else + error('ERROR (qpOASES_options): First argument needs to be a string or an options struct!'); + end + end + end + + % set options to user-defined values + for i=(1+firstIsStructOrScheme):2:nargin + + argName = varargin{i}; + argValue = varargin{i+1}; + + if ( ( isempty( argName ) ) || ( ~ischar( argName ) ) ) + error('ERROR (qpOASES_options): Argmument no. %d has to be a non-empty string!',i ); + end + + if ( ( ischar(argValue) ) || ( ~isscalar( argValue ) ) ) + error('ERROR (qpOASES_options): Argmument no. %d has to be a numerical constant!',i+1 ); + end + + if ( ~isfield( options,argName ) ) + error('ERROR (qpOASES_options): Argmument no. %d is an invalid option!',i ); + end + + eval( ['options.',argName,' = ',num2str(argValue),';'] ); + + end + +end + + +function [ options ] = qpOASES_default_options( ) + + % setup options struct with default values + options = struct( 'maxIter', -1, ... + 'maxCpuTime', -1, ... + 'printLevel', 1, ... + ... + 'enableRamping', 1, ... + 'enableFarBounds', 1, ... + 'enableFlippingBounds', 1, ... + 'enableRegularisation', 0, ... + 'enableFullLITests', 0, ... + 'enableNZCTests', 1, ... + 'enableDriftCorrection', 1, ... + 'enableCholeskyRefactorisation', 0, ... + 'enableEqualities', 0, ... + ... + 'terminationTolerance', 5.0e6*eps, ... + 'boundTolerance', 1.0e6*eps, ... + 'boundRelaxation', 1.0e4, ... + 'epsNum', -1.0e3*eps, ... + 'epsDen', 1.0e3*eps, ... + 'maxPrimalJump', 1.0e8, ... + 'maxDualJump', 1.0e8, ... + ... + 'initialRamping', 0.5, ... + 'finalRamping', 1.0, ... + 'initialFarBounds', 1.0e6, ... + 'growFarBounds', 1.0e3, ... + 'initialStatusBounds', -1, ... + 'epsFlipping', 1.0e3*eps, ... + 'numRegularisationSteps', 0, ... + 'epsRegularisation', 1.0e3*eps, ... + 'numRefinementSteps', 1, ... + 'epsIterRef', 1.0e2*eps, ... + 'epsLITests', 1.0e5*eps, ... + 'epsNZCTests', 3.0e3*eps ); + +end + + + +function [ options ] = qpOASES_reliable_options( ) + + % setup options struct with values for most reliable QP solution + options = qpOASES_default_options( ); + + options.enableFullLITests = 1; + options.enableCholeskyRefactorisation = 1; + + options.numRefinementSteps = 2; + +end + + +function [ options ] = qpOASES_MPC_options( ) + + % setup options struct with values for most reliable QP solution + options = qpOASES_default_options( ); + + options.enableRamping = 0; + options.enableFarBounds = 1; + options.enableFlippingBounds = 0; + options.enableRegularisation = 1; + options.enableNZCTests = 0; + options.enableDriftCorrection = 0; + options.enableEqualities = 1; + + options.terminationTolerance = 1.0e9*eps; + + options.initialStatusBounds = 0; + options.numRegularisationSteps = 1; + options.numRefinementSteps = 0; + +end diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_sequence.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_sequence.cpp new file mode 100644 index 00000000000..35ea59741be --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_sequence.cpp @@ -0,0 +1,1061 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/octave/qpOASES_sequence.cpp + * \author Hans Joachim Ferreau, Christian Kirches, Andreas Potschka, Alexander Buchner + * \version 3.0 + * \date 2007-2014 + * + * Interface for octave that enables to call qpOASES as a MEX function + * (variant for solving QP sequences). + * + */ + + + +#include + + +USING_NAMESPACE_QPOASES + + +#include "qpOASES_octave_utils.hpp" + +/** initialise handle counter of QPInstance class */ +int QPInstance::s_nexthandle = 1; + +/** global pointer to QP objects */ +static std::vector g_instances; + +#include "qpOASES_octave_utils.cpp" + + +/* + * i n i t S B + */ +int initSB( int handle, + SymmetricMatrix *H, real_t* g, + const real_t* const lb, const real_t* const ub, + int nWSRin, real_t maxCpuTimeIn, + const real_t* const x0, Options* options, + int nOutputs, mxArray* plhs[], + double* guessedBounds + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + /* 1) setup initial QP. */ + QProblemB* globalQPB = getQPInstance(handle)->qpb; + + if ( globalQPB == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return -1; + } + + globalQPB->setOptions( *options ); + + /* 2) Solve initial QP. */ + returnValue returnvalue; + int nV = globalQPB->getNV(); + + /* 3) Fill the working set. */ + Bounds bounds(nV); + if (guessedBounds != 0) { + for (int i = 0; i < nV; i++) { + if ( isEqual(guessedBounds[i],-1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_LOWER); + } else if ( isEqual(guessedBounds[i],1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_UPPER); + } else if ( isEqual(guessedBounds[i],0.0) == BT_TRUE ) { + bounds.setupBound(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of bounds!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + if (x0 == 0 && guessedBounds == 0) + returnvalue = globalQPB->init( H,g,lb,ub, nWSRout,&maxCpuTimeOut ); + else + returnvalue = globalQPB->init( H,g,lb,ub, nWSRout,&maxCpuTimeOut, x0, 0, + guessedBounds != 0 ? &bounds : 0); + + /* 3) Assign lhs arguments. */ + obtainOutputs( 0,globalQPB,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,nV,0,handle ); + + return 0; +} + + +/* + * i n i t + */ +int init( int handle, + SymmetricMatrix *H, real_t* g, Matrix *A, + const real_t* const lb, const real_t* const ub, const real_t* const lbA, const real_t* const ubA, + int nWSRin, real_t maxCpuTimeIn, + const real_t* const x0, Options* options, + int nOutputs, mxArray* plhs[], + double* guessedBounds, double* guessedConstraints + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + /* 1) setup initial QP. */ + SQProblem* globalSQP = getQPInstance(handle)->sqp; + + if ( globalSQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return -1; + } + + globalSQP->setOptions( *options ); + + /* 2) Solve initial QP. */ + returnValue returnvalue; + int nV = globalSQP->getNV(); + int nC = globalSQP->getNC(); + + /* 3) Fill the working set. */ + Bounds bounds(nV); + Constraints constraints(nC); + if (guessedBounds != 0) { + for (int i = 0; i < nV; i++) { + if ( isEqual(guessedBounds[i],-1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_LOWER); + } else if ( isEqual(guessedBounds[i],1.0) == BT_TRUE ) { + bounds.setupBound(i, ST_UPPER); + } else if ( isEqual(guessedBounds[i],0.0) == BT_TRUE ) { + bounds.setupBound(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of bounds!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + if (guessedConstraints != 0) { + for (int i = 0; i < nC; i++) { + if ( isEqual(guessedConstraints[i],-1.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_LOWER); + } else if ( isEqual(guessedConstraints[i],1.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_UPPER); + } else if ( isEqual(guessedConstraints[i],0.0) == BT_TRUE ) { + constraints.setupConstraint(i, ST_INACTIVE); + } else { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, + "ERROR (qpOASES): Only {-1, 0, 1} allowed for status of constraints!"); + myMexErrMsgTxt(msg); + return -1; + } + } + } + + if (x0 == 0 && guessedBounds == 0 && guessedConstraints == 0) + returnvalue = globalSQP->init( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut); + else + returnvalue = globalSQP->init( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut, x0, 0, + guessedBounds != 0 ? &bounds : 0, + guessedConstraints != 0 ? &constraints : 0); + + /* 3) Assign lhs arguments. */ + obtainOutputs( 0,globalSQP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,nV,nC,handle ); + + return 0; +} + + + +/* + * h o t s t a r t S B + */ +int hotstartSB( int handle, + const real_t* const g, + const real_t* const lb, const real_t* const ub, + int nWSRin, real_t maxCpuTimeIn, + Options* options, + int nOutputs, mxArray* plhs[] + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + QProblemB* globalQPB = getQPInstance(handle)->qpb; + + if ( globalQPB == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): QP needs to be initialised first!" ); + return -1; + } + + /* 1) Solve QP with given options. */ + globalQPB->setOptions( *options ); + returnValue returnvalue = globalQPB->hotstart( g,lb,ub, nWSRout,&maxCpuTimeOut ); + + /* 2) Assign lhs arguments. */ + obtainOutputs( 0,globalQPB,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,0,0 ); + + return 0; +} + + +/* + * h o t s t a r t + */ +int hotstart( int handle, + const real_t* const g, + const real_t* const lb, const real_t* const ub, + const real_t* const lbA, const real_t* const ubA, + int nWSRin, real_t maxCpuTimeIn, + Options* options, + int nOutputs, mxArray* plhs[] + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + QProblem* globalSQP = getQPInstance(handle)->sqp; + + if ( globalSQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): QP needs to be initialised first!" ); + return -1; + } + + /* 1) Solve QP with given options. */ + globalSQP->setOptions( *options ); + returnValue returnvalue = globalSQP->hotstart( g,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut ); + + /* 2) Assign lhs arguments. */ + obtainOutputs( 0,globalSQP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,0,0 ); + + return 0; +} + + +/* + * h o t s t a r t V M + */ +int hotstartVM( int handle, + SymmetricMatrix *H, real_t* g, Matrix *A, + const real_t* const lb, const real_t* const ub, const real_t* const lbA, const real_t* const ubA, + int nWSRin, real_t maxCpuTimeIn, + Options* options, + int nOutputs, mxArray* plhs[] + ) +{ + int nWSRout = nWSRin; + real_t maxCpuTimeOut = (maxCpuTimeIn >= 0.0) ? maxCpuTimeIn : INFTY; + + SQProblem* globalSQP = getQPInstance(handle)->sqp; + + if ( globalSQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): QP needs to be initialised first!" ); + return -1; + } + + /* 1) Solve QP. */ + globalSQP->setOptions( *options ); + returnValue returnvalue = globalSQP->hotstart( H,g,A,lb,ub,lbA,ubA, nWSRout,&maxCpuTimeOut ); + + switch (returnvalue) + { + case SUCCESSFUL_RETURN: + case RET_QP_UNBOUNDED: + case RET_QP_INFEASIBLE: + break; + otherwise: + myMexErrMsgTxt( "ERROR (qpOASES): Hotstart failed." ); + return -1; + } + + /* 2) Assign lhs arguments. */ + obtainOutputs( 0,globalSQP,returnvalue,nWSRout,maxCpuTimeOut, + nOutputs,plhs,0,0 ); + + return 0; +} + + + +/* + * m e x F u n c t i o n + */ +void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] ) +{ + /* inputs */ + char typeString[2]; + real_t *g=0, *lb=0, *ub=0, *lbA=0, *ubA=0, *x0=0; + int H_idx=-1, g_idx=-1, A_idx=-1, lb_idx=-1, ub_idx=-1, lbA_idx=-1, ubA_idx=-1; + int x0_idx=-1, auxInput_idx=-1; + + double *guessedBoundsAndConstraints = 0; + double *guessedBounds = 0, *guessedConstraints = 0; + + BooleanType isSimplyBoundedQp = BT_FALSE; + + Options options; + options.printLevel = PL_LOW; + #ifdef __DEBUG__ + options.printLevel = PL_HIGH; + #endif + #ifdef __SUPPRESSANYOUTPUT__ + options.printLevel = PL_NONE; + #endif + + /* dimensions */ + unsigned int nV=0, nC=0, handle=0; + int nWSRin; + real_t maxCpuTimeIn = -1.0; + QPInstance* globalQP = 0; + + /* I) CONSISTENCY CHECKS: */ + /* 1) Ensure that qpOASES is called with a feasible number of input arguments. */ + if ( ( nrhs < 5 ) || ( nrhs > 10 ) ) + { + if ( nrhs != 2 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + } + + /* 2) Ensure that first input is a string ... */ + if ( mxIsChar( prhs[0] ) != 1 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): First input argument must be a string!" ); + return; + } + + mxGetString( prhs[0], typeString, 2 ); + + /* ... and if so, check if it is an allowed one. */ + if ( ( strcmp( typeString,"i" ) != 0 ) && ( strcmp( typeString,"I" ) != 0 ) && + ( strcmp( typeString,"h" ) != 0 ) && ( strcmp( typeString,"H" ) != 0 ) && + ( strcmp( typeString,"m" ) != 0 ) && ( strcmp( typeString,"M" ) != 0 ) && + ( strcmp( typeString,"e" ) != 0 ) && ( strcmp( typeString,"E" ) != 0 ) && + ( strcmp( typeString,"c" ) != 0 ) && ( strcmp( typeString,"C" ) != 0 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Undefined first input argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + + /* II) SELECT RESPECTIVE QPOASES FUNCTION CALL: */ + /* 1) Init (without or with initial guess for primal solution). */ + if ( ( strcmp( typeString,"i" ) == 0 ) || ( strcmp( typeString,"I" ) == 0 ) ) + { + /* consistency checks */ + if ( ( nlhs < 2 ) || ( nlhs > 7 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( nrhs < 5 ) || ( nrhs > 10 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* ensure that data is given in double precision */ + if ((mxIsDouble(prhs[1]) == 0) || (mxIsDouble(prhs[2]) == 0)) { + myMexErrMsgTxt( + "ERROR (qpOASES): All data has to be provided in double precision!"); + return; + } + + nV = (unsigned int)mxGetM( prhs[1] ); /* row number of Hessian matrix */ + + /* Check for 'Inf' and 'Nan' in Hessian */ + H_idx = 1; + g_idx = 2; + if (containsNaNorInf(prhs, nV * nV, H_idx, 0) == BT_TRUE) { + return; + } + + /* Check for 'Inf' and 'Nan' in gradient */ + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + + /* determine whether is it a simply bounded QP */ + if ( nrhs <= 7 ) + isSimplyBoundedQp = BT_TRUE; + else + isSimplyBoundedQp = BT_FALSE; + + if ( isSimplyBoundedQp == BT_TRUE ) + { + lb_idx = 3; + ub_idx = 4; + + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + nC = 0; /* row number of constraint matrix */ + + if ( mxGetN( prhs[1] ) != nV ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Input dimension mismatch!" ); + return; + } + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*nV; + + /* Check whether x0 and options are specified .*/ + if ( nrhs >= 6 ) + { + if ((!mxIsEmpty(prhs[5])) && (mxIsStruct(prhs[5]))) + setupOptions( &options,prhs[5],nWSRin,maxCpuTimeIn ); + + if ( ( nrhs >= 7 ) && ( !mxIsEmpty(prhs[6]) ) ) + { + /* auxInput specified */ + if ( mxIsStruct(prhs[6]) ) + { + auxInput_idx = 6; + x0_idx = -1; + } + else + { + auxInput_idx = -1; + x0_idx = 6; + } + } + else + { + auxInput_idx = -1; + x0_idx = -1; + } + } + } + else + { + /* ensure that data is given in double precision */ + if ( ( mxIsDouble( prhs[1] ) == 0 ) || + ( mxIsDouble( prhs[2] ) == 0 ) || + ( mxIsDouble( prhs[3] ) == 0 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in double precision!" ); + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + nC = (unsigned int)mxGetM( prhs[3] ); /* row number of constraint matrix */ + + A_idx = 3; + lb_idx = 4; + ub_idx = 5; + lbA_idx = 6; + ubA_idx = 7; + + if (containsNaNorInf(prhs, nV * nC, A_idx, 0) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + + if ( ( mxGetN( prhs[1] ) != nV ) || ( ( mxGetN( prhs[3] ) != 0 ) && ( mxGetN( prhs[3] ) != nV ) ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Input dimension mismatch!" ); + return; + } + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,5 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lbA,nC,1, BT_TRUE,prhs,6 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,1, BT_TRUE,prhs,7 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*(nV+nC); + + /* Check whether x0 and options are specified .*/ + if ( nrhs >= 9 ) + { + if ((!mxIsEmpty(prhs[8])) && (mxIsStruct(prhs[8]))) + setupOptions( &options,prhs[8],nWSRin,maxCpuTimeIn ); + + if ( ( nrhs >= 10 ) && ( !mxIsEmpty(prhs[9]) ) ) + { + /* auxInput specified */ + if ( mxIsStruct(prhs[9]) ) + { + auxInput_idx = 9; + x0_idx = -1; + } + else + { + auxInput_idx = -1; + x0_idx = 9; + } + } + else + { + auxInput_idx = -1; + x0_idx = -1; + } + } + } + + + /* check dimensions and copy auxInputs */ + if ( smartDimensionCheck( &x0,nV,1, BT_TRUE,prhs,x0_idx ) != SUCCESSFUL_RETURN ) + return; + + if ( auxInput_idx >= 0 ) + setupAuxiliaryInputs( prhs[auxInput_idx],nV,nC, &x0,&guessedBoundsAndConstraints,&guessedBounds,&guessedConstraints ); + + + /* allocate instance */ + handle = allocateQPInstance( nV,nC,isSimplyBoundedQp, &options ); + globalQP = getQPInstance( handle ); + + /* make a deep-copy of the user-specified Hessian matrix (possibly sparse) */ + setupHessianMatrix( prhs[1],nV, &(globalQP->H),&(globalQP->Hir),&(globalQP->Hjc),&(globalQP->Hv) ); + + /* make a deep-copy of the user-specified constraint matrix (possibly sparse) */ + if ( nC > 0 ) + setupConstraintMatrix( prhs[3],nV,nC, &(globalQP->A),&(globalQP->Air),&(globalQP->Ajc),&(globalQP->Av) ); + + /* Create output vectors and assign pointers to them. */ + allocateOutputs( nlhs,plhs, nV,nC,1,handle ); + + /* Call qpOASES. */ + if ( isSimplyBoundedQp == BT_TRUE ) + { + initSB( handle, + globalQP->H,g, + lb,ub, + nWSRin,maxCpuTimeIn, + x0,&options, + nlhs,plhs, + guessedBounds + ); + + deleteAuxiliaryInputs( &guessedBounds,0 ); + } + else + { + init( handle, + globalQP->H,g,globalQP->A, + lb,ub,lbA,ubA, + nWSRin,maxCpuTimeIn, + x0,&options, + nlhs,plhs, + guessedBounds, guessedConstraints + ); + + deleteAuxiliaryInputs( &guessedBounds,&guessedConstraints ); + } + + return; + } + + /* 2) Hotstart. */ + if ( ( strcmp( typeString,"h" ) == 0 ) || ( strcmp( typeString,"H" ) == 0 ) ) + { + /* consistency checks */ + if ( ( nlhs < 1 ) || ( nlhs > 6 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( nrhs < 5 ) || ( nrhs > 8 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* determine whether is it a simply bounded QP */ + if ( nrhs < 7 ) + isSimplyBoundedQp = BT_TRUE; + else + isSimplyBoundedQp = BT_FALSE; + + + if ( ( mxIsDouble( prhs[1] ) == false ) || ( mxGetM( prhs[1] ) != 1 ) || ( mxGetN( prhs[1] ) != 1 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Expecting a handle to QP object as second argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* get QP instance */ + handle = (unsigned int)mxGetScalar( prhs[1] ); + globalQP = getQPInstance ( handle ); + if ( globalQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return; + } + + nV = globalQP->getNV(); + + g_idx = 2; + lb_idx = 3; + ub_idx = 4; + + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + + /* Check inputs dimensions and assign pointers to inputs. */ + if ( isSimplyBoundedQp == BT_TRUE ) + { + nC = 0; + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*nV; + + /* Check whether options are specified .*/ + if ( nrhs == 6 ) + if ( ( !mxIsEmpty( prhs[5] ) ) && ( mxIsStruct( prhs[5] ) ) ) + setupOptions( &options,prhs[5],nWSRin,maxCpuTimeIn ); + } + else + { + nC = globalQP->getNC( ); + + lbA_idx = 5; + ubA_idx = 6; + + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lbA,nC,1, BT_TRUE,prhs,5 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,1, BT_TRUE,prhs,6 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*(nV+nC); + + /* Check whether options are specified .*/ + if ( nrhs == 8 ) + if ( ( !mxIsEmpty( prhs[7] ) ) && ( mxIsStruct( prhs[7] ) ) ) + setupOptions( &options,prhs[7],nWSRin,maxCpuTimeIn ); + } + + /* Create output vectors and assign pointers to them. */ + allocateOutputs( nlhs,plhs, nV,nC ); + + /* call qpOASES */ + if ( isSimplyBoundedQp == BT_TRUE ) + { + hotstartSB( handle, g, + lb,ub, + nWSRin,maxCpuTimeIn, + &options, + nlhs,plhs + ); + } + else + { + hotstart( handle, g, + lb,ub,lbA,ubA, + nWSRin,maxCpuTimeIn, + &options, + nlhs,plhs + ); + } + + return; + } + + /* 3) Modify matrices. */ + if ( ( strcmp( typeString,"m" ) == 0 ) || ( strcmp( typeString,"M" ) == 0 ) ) + { + /* consistency checks */ + if ( ( nlhs < 1 ) || ( nlhs > 6 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( nrhs < 9 ) || ( nrhs > 10 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( mxIsDouble( prhs[1] ) == false ) || ( mxGetM( prhs[1] ) != 1 ) || ( mxGetN( prhs[1] ) != 1 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Expecting a handle to QP object as second argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* ensure that data is given in double precision */ + if ( ( mxIsDouble( prhs[2] ) == 0 ) || + ( mxIsDouble( prhs[3] ) == 0 ) || + ( mxIsDouble( prhs[4] ) == 0 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in real_t precision!" ); + return; + } + + /* get QP instance */ + handle = (unsigned int)mxGetScalar( prhs[1]); + globalQP = getQPInstance ( handle ); + if ( globalQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + nV = (unsigned int)mxGetM( prhs[2] ); /* row number of Hessian matrix */ + nC = (unsigned int)mxGetM( prhs[4] ); /* row number of constraint matrix */ + + H_idx = 2; + g_idx = 3; + A_idx = 4; + lb_idx = 5; + ub_idx = 6; + lbA_idx = 7; + ubA_idx = 8; + + /* check if supplied data contains 'NaN' or 'Inf' */ + if (containsNaNorInf(prhs, nV * nV, H_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV * nC, A_idx, 0) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + + /* Check that dimensions are consistent with existing QP instance */ + if (nV != (unsigned int) globalQP->getNV () || nC != (unsigned int) globalQP->getNC ()) + { + myMexErrMsgTxt( "ERROR (qpOASES): QP dimensions must be constant during a sequence! Try creating a new QP instance instead." ); + return; + } + + if ( ( mxGetN( prhs[2] ) != nV ) || ( ( mxGetN( prhs[4] ) != 0 ) && ( mxGetN( prhs[4] ) != nV ) ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Input dimension mismatch!" ); + return; + } + + if ( smartDimensionCheck( &g,nV,1, BT_FALSE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,1, BT_TRUE,prhs,5 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,1, BT_TRUE,prhs,6 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lbA,nC,1, BT_TRUE,prhs,7 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,1, BT_TRUE,prhs,8 ) != SUCCESSFUL_RETURN ) + return; + + /* default value for nWSR */ + nWSRin = 5*(nV+nC); + + /* Check whether options are specified .*/ + if ( nrhs > 9 ) + if ( ( !mxIsEmpty( prhs[9] ) ) && ( mxIsStruct( prhs[9] ) ) ) + setupOptions( &options,prhs[9],nWSRin,maxCpuTimeIn ); + + globalQP->deleteQPMatrices( ); + + /* make a deep-copy of the user-specified Hessian matrix (possibly sparse) */ + setupHessianMatrix( prhs[2],nV, &(globalQP->H),&(globalQP->Hir),&(globalQP->Hjc),&(globalQP->Hv) ); + + /* make a deep-copy of the user-specified constraint matrix (possibly sparse) */ + if ( nC > 0 ) + setupConstraintMatrix( prhs[4],nV,nC, &(globalQP->A),&(globalQP->Air),&(globalQP->Ajc),&(globalQP->Av) ); + + /* Create output vectors and assign pointers to them. */ + allocateOutputs( nlhs,plhs, nV,nC ); + + /* Call qpOASES */ + hotstartVM( handle, globalQP->H,g,globalQP->A, + lb,ub,lbA,ubA, + nWSRin,maxCpuTimeIn, + &options, + nlhs,plhs + ); + + return; + } + + /* 4) Solve current equality constrained QP. */ + if ( ( strcmp( typeString,"e" ) == 0 ) || ( strcmp( typeString,"E" ) == 0 ) ) + { + /* consistency checks */ + if ( ( nlhs < 1 ) || ( nlhs > 3 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( nrhs < 7 ) || ( nrhs > 8 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( mxIsDouble( prhs[1] ) == false ) || ( mxGetM( prhs[1] ) != 1 ) || ( mxGetN( prhs[1] ) != 1 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Expecting a handle to QP object as second argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* get QP instance */ + handle = (unsigned int)mxGetScalar( prhs[1] ); + globalQP = getQPInstance ( handle ); + if ( globalQP == 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid handle to QP instance!" ); + return; + } + + /* Check inputs dimensions and assign pointers to inputs. */ + int nRHS = (int)mxGetN(prhs[2]); + nV = globalQP->getNV( ); + nC = globalQP->getNC( ); + real_t *x_out, *y_out; + + g_idx = 2; + lb_idx = 3; + ub_idx = 4; + lbA_idx = 5; + ubA_idx = 6; + + /* check if supplied data contains 'NaN' or 'Inf' */ + if (containsNaNorInf(prhs, nV, g_idx, 0) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, lb_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nV, ub_idx, 1) == BT_TRUE) { + return; + } + + if (containsNaNorInf(prhs, nC, lbA_idx, 1) == BT_TRUE) { + return; + } + if (containsNaNorInf(prhs, nC, ubA_idx, 1) == BT_TRUE) { + return; + } + + if ( smartDimensionCheck( &g,nV,nRHS, BT_FALSE,prhs,2 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lb,nV,nRHS, BT_TRUE,prhs,3 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ub,nV,nRHS, BT_TRUE,prhs,4 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &lbA,nC,nRHS, BT_TRUE,prhs,5 ) != SUCCESSFUL_RETURN ) + return; + + if ( smartDimensionCheck( &ubA,nC,nRHS, BT_TRUE,prhs,6 ) != SUCCESSFUL_RETURN ) + return; + + /* Check whether options are specified .*/ + if ( ( nrhs == 8 ) && ( !mxIsEmpty( prhs[7] ) ) && ( mxIsStruct( prhs[7] ) ) ) + { + nWSRin = 5*(nV+nC); + setupOptions( &options,prhs[7],nWSRin,maxCpuTimeIn ); + globalQP->sqp->setOptions( options ); + } + + /* Create output vectors and assign pointers to them. */ + plhs[0] = mxCreateDoubleMatrix( nV, nRHS, mxREAL ); + x_out = mxGetPr(plhs[0]); + if (nlhs >= 2) + { + plhs[1] = mxCreateDoubleMatrix( nV+nC, nRHS, mxREAL ); + y_out = mxGetPr(plhs[1]); + + if (nlhs >= 3) { + plhs[2] = mxCreateDoubleMatrix( nV+nC, nRHS, mxREAL ); + double* workingSet = mxGetPr(plhs[2]); + + globalQP->sqp->getWorkingSet(workingSet); + } + } + else + y_out = new real_t[nV+nC]; + + /* Solve equality constrained QP */ + returnValue returnvalue = globalQP->sqp->solveCurrentEQP( nRHS,g,lb,ub,lbA,ubA, x_out,y_out ); + + if (nlhs < 2) + delete[] y_out; + + if (returnvalue != SUCCESSFUL_RETURN) + { + char msg[MAX_STRING_LENGTH]; + snprintf(msg, MAX_STRING_LENGTH, "ERROR (qpOASES): Couldn't solve current EQP (code %d)!", returnvalue); + myMexErrMsgTxt(msg); + return; + } + + return; + } + + /* 5) Cleanup. */ + if ( ( strcmp( typeString,"c" ) == 0 ) || ( strcmp( typeString,"C" ) == 0 ) ) + { + /* consistency checks */ + if ( nlhs != 0 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of output arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( nrhs != 2 ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + if ( ( mxIsDouble( prhs[1] ) == false ) || ( mxGetM( prhs[1] ) != 1 ) || ( mxGetN( prhs[1] ) != 1 ) ) + { + myMexErrMsgTxt( "ERROR (qpOASES): Expecting a handle to QP object as second argument!\nType 'help qpOASES_sequence' for further information." ); + return; + } + + /* Cleanup SQProblem instance. */ + handle =(unsigned int)mxGetScalar( prhs[1] ); + deleteQPInstance ( handle ); + + return; + } + +} + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_sequence.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_sequence.m new file mode 100644 index 00000000000..6dc57dc767f --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/octave/qpOASES_sequence.m @@ -0,0 +1,112 @@ +%qpOASES -- An Implementation of the Online Active Set Strategy. +%Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. +% +%qpOASES is distributed under the terms of the +%GNU Lesser General Public License 2.1 in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%See the GNU Lesser General Public License for more details. +% +%--------------------------------------------------------------------------------- +% +%qpOASES_sequence is intended to solve a sequence of quadratic +%programming (QP) problems of the following form: +% +% min 1/2*x'Hx + x'g +% s.t. lb <= x <= ub +% lbA <= Ax <= ubA {optional} +% +%I) Call +% +% [QP,x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'i',H,g,A,lb,ub,lbA,ubA{,options{,auxInput} ) +%or +% [QP,x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'i',H,g,lb,ub{,options{,auxInput} ) +% +%for initialising and solving the first above-mentioned QP of the sequence +%starting from an initial guess x0. H must be a symmetric (possibly indefinite) +%matrix and all vectors g, lb, ub, lbA, ubA have to be given as column vectors. +%Options can be generated using the qpOASES_options command, otherwise default +%values are used. Optionally, further auxiliary inputs may be generated +%using qpOASES_auxInput command and passed to the solver. +%Both matrices H or A may be passed in sparse matrix format. +% +%II) Call +% +% [x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'h',QP,g,lb,ub,lbA,ubA{,options} ) +%or +% [x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'h',QP,g,lb,ub{,options} ) +% +%for hotstarting from the previous QP solution to the one of the next QP +%given by the vectors g, lb, ub, lbA, ubA. Options can be generated using the +%qpOASES_options command, otherwise default values are used. +% +%III) Call +% +% [x,fval,exitflag,iter,lambda,auxOutput] = ... +% qpOASES_sequence( 'm',QP,H,g,A,lb,ub,lbA,ubA{,options} ) +% +%for hotstarting from the previous QP solution to the one of the next QP +%given by the matrices H, A and the vectors g, lb, ub, lbA, ubA. The previous +%active set serves as a starting guess. If the new projected Hessian matrix +%turns out to be not positive definite, qpOASES recedes to a safe initial active +%set guess automatically. This can result in a high number of iterations iter. +%Options can be generated using the qpOASES_options command, otherwise default +%values are used. +% +%IV) Call +% +% [x,lambda,workingSet] = qpOASES_sequence( 'e',QP,g,lb,ub,lbA,ubA{,options} ) +% +%for solving the equality constrained QP with constraints determined by the +%current active set. All inequalities and bounds which were not active in the +%previous solution might be violated. This command does not alter the internal +%state of qpOASES. Instead of calling this command multiple times, it is +%possible to supply several columns simultaneously in g, lb, ub, lbA, and ubA. +%Options can be generated using the qpOASES_options command, otherwise default +%values are used. +% +%V) Having solved the last QP of your sequence, call +% +% qpOASES_sequence( 'c',QP ) +% +%in order to cleanup the internal memory. +% +% +%Optional outputs (only x is mandatory): +% x - Optimal primal solution vector (if exitflag==0). +% fval - Optimal objective function value (if exitflag==0). +% exitflag - 0: QP solved, +% 1: QP could not be solved within given number of iterations, +% -1: QP could not be solved due to an internal error, +% -2: QP is infeasible (and thus could not be solved), +% -3: QP is unbounded (and thus could not be solved). +% iter - Number of active set iterations actually performed. +% lambda - Optimal dual solution vector (if status==0). +% auxOutput - Struct containing auxiliary outputs as described below. +% +%The auxOutput struct contains the following entries: +% workingSet - The working set at point x. The working set is a subset +% of the active set (which is the set of all indices +% corresponding to bounds/constraints that hold with +% equality). The working set corresponds to bound/ +% constraint row vectors forming a linear independent set. +% The first nV elements correspond to the bounds, the last +% nC elements to the constraints. +% The working set is encoded as follows: +% 1: bound/constraint at its upper bound +% 0: bound/constraint not at any bound +% -1: bound/constraint at its lower bound +% cpuTime - Internally measured CPU time for solving QP. +% +%See also QPOASES_OPTIONS, QPOASES_AUXINPUT, QPOASES +% +% +%For additional information see the qpOASES User's Manual or +%visit http://www.qpOASES.org/. +% +%Please send remarks and questions to support@qpOASES.org! diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/README.rst b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/README.rst new file mode 100644 index 00000000000..64911d9f4cb --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/README.rst @@ -0,0 +1,68 @@ +pyqpOASES: a Python interface to qpOASES + +:Author: Sebastian F. Walter, Manuel Kudruss + + +Installation +------------ + + +Requirements: + + You'll need numpy and cython. Install for instance with:: + + sudo pip install cython + sudo pip install numpy + +Method 1: + + This is a local installation and creates `./interfaces/python/qpoases.so`:: + + make python + + Then, you'll have to update your PYTHONPATH, e.g., on LINUX you have to add:: + + export PYTHONPATH=$PYTHONPATH:/home/swalter/projects/qpOASES/interfaces/python + + to your ``~/.bashrc``. + +Method 2: + + global installation:: + + sudo make pythoninstall + +Method 3:: + + cd ./interfaces/python/ + python setup.py build_ext --inplace + # or python setup.py install + + +Testing your installation +------------------------- + +For a quick test run:: + + cd ./interfaces/python + python example1.py + + +To run a complete unit test you need ``nose``. Install for instance with:: + + sudo pip install nose + +Then:: + + cd ./interfaces/python/ + nosestests ./tests + +The results of the tests can be found in `./interfaces/python/tests/results`. + +Tested setups +------------- + +The Python interface is known to work on + +* Windows, Python 3 +* Linux (Ubuntu 12.04) using Python 2.7.3, Python 3.2.3. NumPy 1.8, Cython 0.19 diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/example1.pyx b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/example1.pyx new file mode 100644 index 00000000000..1cdfbc8f5b9 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/example1.pyx @@ -0,0 +1,73 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + +## Example adapted from examples/example1.cpp. +## author of this file: Sebastian F. Walter + +import numpy as np +from qpoases import PyQProblem as QProblem +from qpoases import PyPrintLevel as PrintLevel +from qpoases import PyOptions as Options +cimport numpy as np + +def run(): + + #Setup data of QP. + + cdef np.ndarray[np.double_t, ndim=2] H + cdef np.ndarray[np.double_t, ndim=2] A + cdef np.ndarray[np.double_t, ndim=1] g + cdef np.ndarray[np.double_t, ndim=1] lb + cdef np.ndarray[np.double_t, ndim=1] ub + cdef np.ndarray[np.double_t, ndim=1] lbA + cdef np.ndarray[np.double_t, ndim=1] ubA + + H = np.array([1.0, 0.0, 0.0, 0.5 ]).reshape((2,2)) + A = np.array([1.0, 1.0 ]).reshape((2,1)) + g = np.array([1.5, 1.0 ]) + lb = np.array([0.5, -2.0]) + ub = np.array([5.0, 2.0 ]) + lbA = np.array([-1.0 ]) + ubA = np.array([2.0]) + + # Setting up QProblem object. + + cdef example = QProblem(2, 1) + cdef options = Options() + options.printLevel = PrintLevel.NONE + example.setOptions(options) + + # Solve first QP. + + cdef int nWSR = 10 + example.init(H, g, A, lb, ub, lbA, ubA, nWSR) + + # Solve subsequent QPs + + cdef int i,j + for i in range(100000): + for j in range(1, 100): + g[0] = i%j + example.hotstart(g, lb, ub, lbA, ubA, nWSR) + +run() + diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/index.html b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/index.html new file mode 100644 index 00000000000..8054f6c1c37 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/index.html @@ -0,0 +1,9 @@ +qpOASES - Revision 198: /stable/3.0/interfaces/python/examples/cython + +

qpOASES - Revision 198: /stable/3.0/interfaces/python/examples/cython

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/setup.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/setup.py new file mode 100644 index 00000000000..d605d2c33a1 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/cython/setup.py @@ -0,0 +1,16 @@ +from distutils.core import setup +from distutils.extension import Extension +from Cython.Distutils import build_ext + +ext_module = Extension( + "example1", + ["example1.pyx"], + extra_compile_args=['-fopenmp'], + extra_link_args=['-fopenmp'], +) + +setup( + name = 'Hello world app', + cmdclass = {'build_ext': build_ext}, + ext_modules = [ext_module], +) diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example1.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example1.py new file mode 100644 index 00000000000..b3da19a52fc --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example1.py @@ -0,0 +1,76 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + +## Example adapted from examples/example1.cpp. +## author of this file: Sebastian F. Walter + +import numpy as np +from qpoases import PyQProblem as QProblem +from qpoases import PyOptions as Options +from qpoases import PyPrintLevel as PrintLevel + +#Setup data of first QP. + +H = np.array([1.0, 0.0, 0.0, 0.5 ]).reshape((2,2)) +A = np.array([1.0, 1.0 ]).reshape((2,1)) +g = np.array([1.5, 1.0 ]) +lb = np.array([0.5, -2.0]) +ub = np.array([5.0, 2.0 ]) +lbA = np.array([-1.0 ]) +ubA = np.array([2.0]) + + +# Setup data of second QP. + +g_new = np.array([1.0, 1.5]) +lb_new = np.array([0.0, -1.0]) +ub_new = np.array([5.0, -0.5]) +lbA_new = np.array([-2.0]) +ubA_new = np.array([1.0]) + + +# Setting up QProblem object. + +example = QProblem(2, 1) +options = Options() +options.printLevel = PrintLevel.NONE +example.setOptions(options) + +# Solve first QP. +nWSR = 10; +example.init(H, g, A, lb, ub, lbA, ubA, nWSR) + + +# Solve second QP. +nWSR = 10 + +for i in range(100000): + for j in range(1, 100): + g_new[0] = i%j + example.hotstart( g_new, lb_new, ub_new, lbA_new, ubA_new, nWSR) + +# Get and print solution of second QP. + +xOpt = np.zeros(2) +example.getPrimalSolution(xOpt); +print("\nxOpt = [ %e, %e ]; objVal = %e\n\n"%(xOpt[0],xOpt[1],example.getObjVal())) +example.printOptions(); diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example1b.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example1b.py new file mode 100644 index 00000000000..7fb519ad11c --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example1b.py @@ -0,0 +1,72 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + +## Example adapted from examples/example1b.cpp. +## author of this file: Sebastian F. Walter + +import numpy as np +from qpoases import PyQProblemB as QProblemB +from qpoases import PyBooleanType as BooleanType +from qpoases import PySubjectToStatus as SubjectToStatus +from qpoases import PyOptions as Options + +# Example for qpOASES main function using the QProblemB class. + +#Setup data of first QP. + +H = np.array([1.0, 0.0, 0.0, 0.5 ]).reshape((2,2)) +g = np.array([1.5, 1.0 ]) +lb = np.array([0.5, -2.0]) +ub = np.array([5.0, 2.0 ]) + +# Setup data of second QP. + +g_new = np.array([1.0, 1.5]) +lb_new = np.array([0.0, -1.0]) +ub_new = np.array([5.0, -0.5]) + + +# Setting up QProblemB object. +example = QProblemB(2) + +options = Options() +options.enableFlippingBounds = BooleanType.FALSE +options.initialStatusBounds = SubjectToStatus.INACTIVE +options.numRefinementSteps = 1 + +example.setOptions(options) + +# Solve first QP. +nWSR = 10 +example.init(H, g, lb, ub, nWSR); +print("\nnWSR = %d\n\n"%nWSR) + +# Solve second QP. +nWSR = 10; +example.hotstart(g_new, lb_new, ub_new, nWSR) +print("\nnWSR = %d\n\n"% nWSR) + +# Get and print solution of second QP. +xOpt = np.zeros(2) +example.getPrimalSolution(xOpt) +print("\nxOpt = [ %e, %e ]; objVal = %e\n\n" %(xOpt[0], xOpt[1], + example.getObjVal())) diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example2.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example2.py new file mode 100644 index 00000000000..d093e2e17fb --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/example2.py @@ -0,0 +1,90 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + +## Example adapted from examples/example2.cpp. +## author of this file: Sebastian F. Walter + +import numpy as np +from qpoases import PySQProblem as SQProblem +from qpoases import PySolutionAnalysis as SolutionAnalysis + + +# Setup data of first QP. +H = np.array([ 1.0, 0.0, 0.0, 0.5 ]).reshape((2,2)) +A = np.array([ 1.0, 1.0 ]).reshape((2,1)) +g = np.array([ 1.5, 1.0 ]) +lb = np.array([ 0.5, -2.0 ]) +ub = np.array([ 5.0, 2.0 ]) +lbA = np.array([ -1.0 ]) +ubA = np.array([ 2.0 ]) + +# Setup data of second QP. +H_new = np.array([ 1.0, 0.5, 0.5, 0.5 ]).reshape((2,2)) +A_new = np.array([ 1.0, 5.0 ]).reshape((2,1)) +g_new = np.array([ 1.0, 1.5 ]) +lb_new = np.array([ 0.0, -1.0 ]) +ub_new = np.array([ 5.0, -0.5 ]) +lbA_new = np.array([ -2.0 ]) +ubA_new = np.array([ 1.0 ]) + +# Setting up SQProblem object and solution analyser. +example = SQProblem(2, 1) +analyser = SolutionAnalysis() + +# Solve first QP ... +nWSR = 10 +example.init(H, g, A, lb, ub, lbA, ubA, nWSR) + +# ... and analyse it. +maxKKTviolation = np.zeros(1) +analyser.getMaxKKTviolation(example, maxKKTviolation) +print("maxKKTviolation: %e\n"%maxKKTviolation) + +# Solve second QP ... +nWSR = 10; +example.hotstart(H_new, g_new, A_new, lb_new, ub_new, + lbA_new, ubA_new, nWSR) + +# ... and analyse it. +analyser.getMaxKKTviolation(example, maxKKTviolation) +print("maxKKTviolation: %e\n"%maxKKTviolation) + + +# ------------ VARIANCE-COVARIANCE EVALUATION -------------------- + +Var = np.zeros(5*5) +Primal_Dual_Var = np.zeros(5*5) + +Var.reshape((5,5))[0,0] = 1. +Var.reshape((5,5))[1,1] = 1. + +# ( 1 0 0 0 0 ) +# ( 0 1 0 0 0 ) +# Var = ( 0 0 0 0 0 ) +# ( 0 0 0 0 0 ) +# ( 0 0 0 0 0 ) + + +analyser.getVarianceCovariance(example, Var, Primal_Dual_Var) +print('Primal_Dual_Var=\n', Primal_Dual_Var.reshape((5,5))) + +print(maxKKTviolation) diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/index.html b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/index.html new file mode 100644 index 00000000000..af694d2f6b3 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/examples/index.html @@ -0,0 +1,11 @@ +qpOASES - Revision 198: /stable/3.0/interfaces/python/examples + +

qpOASES - Revision 198: /stable/3.0/interfaces/python/examples

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/index.html b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/index.html new file mode 100644 index 00000000000..75e2a483c3d --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/index.html @@ -0,0 +1,13 @@ +qpOASES - Revision 198: /stable/3.0/interfaces/python + +

qpOASES - Revision 198: /stable/3.0/interfaces/python

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/qpoases.pxd b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/qpoases.pxd new file mode 100644 index 00000000000..60fcf99426a --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/qpoases.pxd @@ -0,0 +1,476 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + +## +## Filename: qpoases.pxd +## Author: Sebastian F. Walter, Manuel Kudruss +## Version: 3.0 +## Date: 2013-2014 +## + +cdef extern from "qpOASES.hpp" namespace "qpOASES": + + ctypedef double real_t + + cdef enum BooleanType: + + BT_FALSE + BT_TRUE + + cdef enum PrintLevel: + + PL_DEBUG_ITER = -2 + PL_TABULAR + PL_NONE + PL_LOW + PL_MEDIUM + PL_HIGH + + cdef enum VisibilityStatus: + + VS_HIDDEN + VS_VISIBLE + + cdef enum QProblemStatus: + + QPS_NOTINITIALISED + QPS_PREPARINGAUXILIARYQP + + QPS_AUXILIARYQPSOLVED + + QPS_PERFORMINGHOMOTOPY + + QPS_HOMOTOPYQPSOLVED + QPS_SOLVED + + cdef enum HessianType: + HST_ZERO + HST_IDENTITY + HST_POSDEF + HST_POSDEF_NULLSPACE + HST_SEMIDEF + HST_INDEF + HST_UNKNOWN + + cdef enum SubjectToType: + + ST_UNBOUNDED + ST_BOUNDED + ST_EQUALITY + ST_DISABLED + ST_UNKNOWN + + cdef enum SubjectToStatus: + + ST_LOWER = -1 + ST_INACTIVE + ST_UPPER + ST_INFEASIBLE_LOWER + ST_INFEASIBLE_UPPER + ST_UNDEFINED + + cdef enum returnValue: + TERMINAL_LIST_ELEMENT = -1 + SUCCESSFUL_RETURN = 0 + RET_DIV_BY_ZERO + RET_INDEX_OUT_OF_BOUNDS + RET_INVALID_ARGUMENTS + RET_ERROR_UNDEFINED + RET_WARNING_UNDEFINED + RET_INFO_UNDEFINED + RET_EWI_UNDEFINED + RET_AVAILABLE_WITH_LINUX_ONLY + RET_UNKNOWN_BUG + RET_PRINTLEVEL_CHANGED + RET_NOT_YET_IMPLEMENTED + RET_INDEXLIST_MUST_BE_REORDERD + RET_INDEXLIST_EXCEEDS_MAX_LENGTH + RET_INDEXLIST_CORRUPTED + RET_INDEXLIST_OUTOFBOUNDS + RET_INDEXLIST_ADD_FAILED + RET_INDEXLIST_INTERSECT_FAILED + RET_INDEX_ALREADY_OF_DESIRED_STATUS + RET_ADDINDEX_FAILED + RET_REMOVEINDEX_FAILED + RET_SWAPINDEX_FAILED + RET_NOTHING_TO_DO + RET_SETUP_BOUND_FAILED + RET_SETUP_CONSTRAINT_FAILED + RET_MOVING_BOUND_FAILED + RET_MOVING_CONSTRAINT_FAILED + RET_SHIFTING_FAILED + RET_ROTATING_FAILED + RET_QPOBJECT_NOT_SETUP + RET_QP_ALREADY_INITIALISED + RET_NO_INIT_WITH_STANDARD_SOLVER + RET_RESET_FAILED + RET_INIT_FAILED + RET_INIT_FAILED_TQ + RET_INIT_FAILED_CHOLESKY + RET_INIT_FAILED_HOTSTART + RET_INIT_FAILED_INFEASIBILITY + RET_INIT_FAILED_UNBOUNDEDNESS + RET_INIT_FAILED_REGULARISATION + RET_INIT_SUCCESSFUL + RET_OBTAINING_WORKINGSET_FAILED + RET_SETUP_WORKINGSET_FAILED + RET_SETUP_AUXILIARYQP_FAILED + RET_NO_EXTERN_SOLVER + RET_QP_UNBOUNDED + RET_QP_INFEASIBLE + RET_QP_NOT_SOLVED + RET_QP_SOLVED + RET_UNABLE_TO_SOLVE_QP + RET_INITIALISATION_STARTED + RET_HOTSTART_FAILED + RET_HOTSTART_FAILED_TO_INIT + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED + RET_ITERATION_STARTED + RET_SHIFT_DETERMINATION_FAILED + RET_STEPDIRECTION_DETERMINATION_FAILED + RET_STEPLENGTH_DETERMINATION_FAILED + RET_OPTIMAL_SOLUTION_FOUND + RET_HOMOTOPY_STEP_FAILED + RET_HOTSTART_STOPPED_INFEASIBILITY + RET_HOTSTART_STOPPED_UNBOUNDEDNESS + RET_WORKINGSET_UPDATE_FAILED + RET_MAX_NWSR_REACHED + RET_CONSTRAINTS_NOT_SPECIFIED + RET_INVALID_FACTORISATION_FLAG + RET_UNABLE_TO_SAVE_QPDATA + RET_STEPDIRECTION_FAILED_TQ + RET_STEPDIRECTION_FAILED_CHOLESKY + RET_CYCLING_DETECTED + RET_CYCLING_NOT_RESOLVED + RET_CYCLING_RESOLVED + RET_STEPSIZE + RET_STEPSIZE_NONPOSITIVE + RET_SETUPSUBJECTTOTYPE_FAILED + RET_ADDCONSTRAINT_FAILED + RET_ADDCONSTRAINT_FAILED_INFEASIBILITY + RET_ADDBOUND_FAILED + RET_ADDBOUND_FAILED_INFEASIBILITY + RET_REMOVECONSTRAINT_FAILED + RET_REMOVEBOUND_FAILED + RET_REMOVE_FROM_ACTIVESET + RET_ADD_TO_ACTIVESET + RET_REMOVE_FROM_ACTIVESET_FAILED + RET_ADD_TO_ACTIVESET_FAILED + RET_CONSTRAINT_ALREADY_ACTIVE + RET_ALL_CONSTRAINTS_ACTIVE + RET_LINEARLY_DEPENDENT + RET_LINEARLY_INDEPENDENT + RET_LI_RESOLVED + RET_ENSURELI_FAILED + RET_ENSURELI_FAILED_TQ + RET_ENSURELI_FAILED_NOINDEX + RET_ENSURELI_FAILED_CYCLING + RET_BOUND_ALREADY_ACTIVE + RET_ALL_BOUNDS_ACTIVE + RET_CONSTRAINT_NOT_ACTIVE + RET_BOUND_NOT_ACTIVE + RET_HESSIAN_NOT_SPD + RET_HESSIAN_INDEFINITE + RET_MATRIX_SHIFT_FAILED + RET_MATRIX_FACTORISATION_FAILED + RET_PRINT_ITERATION_FAILED + RET_NO_GLOBAL_MESSAGE_OUTPUTFILE + RET_DISABLECONSTRAINTS_FAILED + RET_ENABLECONSTRAINTS_FAILED + RET_ALREADY_ENABLED + RET_ALREADY_DISABLED + RET_NO_HESSIAN_SPECIFIED + RET_USING_REGULARISATION + RET_EPS_MUST_BE_POSITVE + RET_REGSTEPS_MUST_BE_POSITVE + RET_HESSIAN_ALREADY_REGULARISED + RET_CANNOT_REGULARISE_IDENTITY + RET_CANNOT_REGULARISE_SPARSE + RET_NO_REGSTEP_NWSR + RET_FEWER_REGSTEPS_NWSR + RET_CHOLESKY_OF_ZERO_HESSIAN + RET_CONSTRAINTS_ARE_NOT_SCALED + RET_INITIAL_BOUNDS_STATUS_NYI + RET_ERROR_IN_CONSTRAINTPRODUCT + RET_FIX_BOUNDS_FOR_LP + RET_USE_REGULARISATION_FOR_LP + RET_UPDATEMATRICES_FAILED + RET_UPDATEMATRICES_FAILED_AS_QP_NOT_SOLVED + RET_UNABLE_TO_OPEN_FILE + RET_UNABLE_TO_WRITE_FILE + RET_UNABLE_TO_READ_FILE + RET_FILEDATA_INCONSISTENT + RET_UNABLE_TO_ANALYSE_QPROBLEM + RET_OPTIONS_ADJUSTED + RET_NWSR_SET_TO_ONE + RET_UNABLE_TO_READ_BENCHMARK + RET_BENCHMARK_ABORTED + RET_INITIAL_QP_SOLVED + RET_QP_SOLUTION_STARTED + RET_BENCHMARK_SUCCESSFUL + RET_NO_DIAGONAL_AVAILABLE + RET_DIAGONAL_NOT_INITIALISED + RET_ENSURELI_DROPPED + RET_SIMPLE_STATUS_P1 + RET_SIMPLE_STATUS_P0 + RET_SIMPLE_STATUS_M1 + RET_SIMPLE_STATUS_M2 + RET_SIMPLE_STATUS_M3 + + + cdef cppclass Options: + + Options() + Options(const Options&) + # Options& operator=( const Options&) # equality operator cannot be overloaded in Python + returnValue setToDefault() + returnValue setToReliable() + returnValue setToMPC() + returnValue setToFast() + returnValue ensureConsistency() + # returnValue print() # print is a reserved keyword in Python + returnValue copy(const Options& ) + + PrintLevel printLevel + + BooleanType enableRamping + BooleanType enableFarBounds + BooleanType enableFlippingBounds + BooleanType enableRegularisation + BooleanType enableFullLITests + BooleanType enableNZCTests + int enableDriftCorrection + int enableCholeskyRefactorisation + BooleanType enableEqualities + + real_t terminationTolerance + real_t boundTolerance + real_t boundRelaxation + real_t epsNum + real_t epsDen + real_t maxPrimalJump + real_t maxDualJump + + real_t initialRamping + real_t finalRamping + real_t initialFarBounds + real_t growFarBounds + SubjectToStatus initialStatusBounds + real_t epsFlipping + int numRegularisationSteps + real_t epsRegularisation + int numRefinementSteps + real_t epsIterRef + real_t epsLITests + real_t epsNZCTests + + BooleanType enableDropInfeasibles + int dropBoundPriority + int dropEqConPriority + int dropIneqConPriority + + cdef cppclass QProblemB: + QProblemB() + QProblemB(int, HessianType) + + QProblemB(const QProblemB&) + + returnValue init(real_t*, + real_t*, + real_t*, + real_t*, + int&) + + returnValue init(real_t*, + real_t*, + real_t*, + real_t*, + int&, + real_t*) + + returnValue hotstart(real_t*, + real_t*, + real_t*, + int&) + + returnValue hotstart(real_t*, + real_t*, + real_t*, + int&, + real_t*) + + + returnValue getPrimalSolution(real_t*) + returnValue getDualSolution(real_t*) + returnValue printOptions() + real_t getObjVal() + + Options getOptions() + returnValue setOptions(Options&) + + cdef cppclass QProblem: + QProblem() + QProblem(int, int, HessianType) + + QProblem(const QProblem&) + + returnValue init(real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + int&) + + returnValue init(real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + int&, + real_t*) + + returnValue hotstart(real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + int&) + + returnValue hotstart(real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + int&, + real_t*) + + returnValue getPrimalSolution(real_t*) + returnValue getDualSolution(real_t*) + returnValue printOptions() + real_t getObjVal() + + Options getOptions() + returnValue setOptions(Options&) + + + cdef cppclass SQProblem: + SQProblem() + SQProblem(int, int, HessianType) + + SQProblem(const QProblem&) + + returnValue init(real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + int&) + + returnValue init(real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + int&, + real_t*) + + returnValue hotstart(real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + int&) + + returnValue hotstart(real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + real_t*, + int&, + real_t*) + + returnValue getPrimalSolution(real_t*) + returnValue getDualSolution(real_t*) + returnValue printOptions() + real_t getObjVal() + + Options getOptions() + returnValue setOptions(Options&) + + + cdef cppclass SolutionAnalysis: + SolutionAnalysis() + SolutionAnalysis(const SolutionAnalysis&) + # ~SolutionAnalysis() + # SolutionAnalysis& operator=(const SolutionAnalysis&) + returnValue getMaxKKTviolation(QProblem*, real_t& ) + returnValue getMaxKKTviolation(QProblemB*, real_t&) + returnValue getMaxKKTviolation(SQProblem*, real_t&) + returnValue getVarianceCovariance(QProblem*, real_t*, real_t*) + returnValue getVarianceCovariance(QProblemB*, real_t*, real_t*) + returnValue getVarianceCovariance(SQProblem*, real_t*, real_t*) + + +cdef extern from "qpOASES/Utils.hpp" namespace "qpOASES": + void getKKTResidual(int nV, # Number of variables. + int nC, # Number of constraints. + const real_t* const H, # Hessian matrix. + const real_t* const g, # Sequence of gradient vectors. + const real_t* const A, # Constraint matrix. + const real_t* const lb, # Sequence of lower bound vectors (on variables). + const real_t* const ub, # Sequence of upper bound vectors (on variables). + const real_t* const lbA, # Sequence of lower constraints' bound vectors. + const real_t* const ubA, # Sequence of upper constraints' bound vectors. + const real_t* const x, # Sequence of primal trial vectors. + const real_t* const y, # Sequence of dual trial vectors. + real_t& stat, # Maximum value of stationarity condition residual. + real_t& feas, # Maximum value of primal feasibility violation. + real_t& cmpl # Maximum value of complementarity residual. + ) + + +cdef extern from "qpOASES/extras/OQPinterface.hpp" namespace "qpOASES": + returnValue runOQPbenchmark(const char* path, # Full path of the benchmark files (without trailing slash!). + BooleanType isSparse, # Shall convert matrices to sparse format before solution? + BooleanType useHotstarts, # Shall QP solution be hotstarted? + const Options& options, # QP solver options to be used while solving benchmark problems. + int maxAllowedNWSR, # Maximum number of working set recalculations to be performed. + real_t& maxNWSR, # Output: Maximum number of performed working set recalculations. + real_t& avgNWSR, # Output: Average number of performed working set recalculations. + real_t& maxCPUtime, # Output: Maximum CPU time required for solving each QP. + real_t& avgCPUtime, # Output: Average CPU time required for solving each QP. + real_t& maxStationarity, # Output: Maximum residual of stationarity condition. + real_t& maxFeasibility, # Output: Maximum residual of primal feasibility condition. + real_t& maxComplementarity # Output: Maximum residual of complementarity condition. + ) diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/qpoases.pyx b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/qpoases.pyx new file mode 100644 index 00000000000..bb011c393a2 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/qpoases.pyx @@ -0,0 +1,779 @@ +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + +## author of this file: Sebastian F. Walter + +""" +Python interface to qpOASES +using Cython +:author: Sebastian F. Walter, Manuel Kudruss +""" + +import numpy as np +cimport numpy as np + +from cython.operator cimport dereference as deref + +cimport qpoases + +cdef class PyBooleanType: + FALSE = BT_FALSE + TRUE = BT_TRUE + +cdef class PyPrintLevel: + DEBUG_ITER = PL_DEBUG_ITER + TABULAR = PL_TABULAR + NONE = PL_NONE + LOW = PL_LOW + MEDIUM = PL_MEDIUM + HIGH = PL_HIGH + +cdef class PyHessianType: + ZERO = HST_ZERO + IDENTITY = HST_IDENTITY + POSDEF = HST_POSDEF + POSDEF_NULLSPACE = HST_POSDEF_NULLSPACE + SEMIDEF = HST_SEMIDEF + INDEF = HST_INDEF + UNKNOWN = HST_UNKNOWN + +cdef class PySubjectToStatus: + LOWER = ST_LOWER + INACTIVE = ST_INACTIVE + UPPER = ST_UPPER + INFEASIBLE_LOWER = ST_INFEASIBLE_LOWER + INFEASIBLE_UPPER = ST_INFEASIBLE_UPPER + UNDEFINED = ST_UNDEFINED + +cdef class PyReturnValue: + TERMINAL_LIST_ELEMENT = -1 + SUCCESSFUL_RETURN = 0 + DIV_BY_ZERO = RET_DIV_BY_ZERO + INDEX_OUT_OF_BOUNDS = RET_INDEX_OUT_OF_BOUNDS + INVALID_ARGUMENTS = RET_INVALID_ARGUMENTS + ERROR_UNDEFINED = RET_ERROR_UNDEFINED + WARNING_UNDEFINED = RET_WARNING_UNDEFINED + INFO_UNDEFINED = RET_INFO_UNDEFINED + EWI_UNDEFINED = RET_EWI_UNDEFINED + AVAILABLE_WITH_LINUX_ONLY = RET_AVAILABLE_WITH_LINUX_ONLY + UNKNOWN_BUG = RET_UNKNOWN_BUG + PRINTLEVEL_CHANGED = RET_PRINTLEVEL_CHANGED + NOT_YET_IMPLEMENTED = RET_NOT_YET_IMPLEMENTED + INDEXLIST_MUST_BE_REORDERD = RET_INDEXLIST_MUST_BE_REORDERD + INDEXLIST_EXCEEDS_MAX_LENGTH = RET_INDEXLIST_EXCEEDS_MAX_LENGTH + INDEXLIST_CORRUPTED = RET_INDEXLIST_CORRUPTED + INDEXLIST_OUTOFBOUNDS = RET_INDEXLIST_OUTOFBOUNDS + INDEXLIST_ADD_FAILED = RET_INDEXLIST_ADD_FAILED + INDEXLIST_INTERSECT_FAILED = RET_INDEXLIST_INTERSECT_FAILED + INDEX_ALREADY_OF_DESIRED_STATUS = RET_INDEX_ALREADY_OF_DESIRED_STATUS + ADDINDEX_FAILED = RET_ADDINDEX_FAILED + REMOVEINDEX_FAILED = RET_REMOVEINDEX_FAILED + SWAPINDEX_FAILED = RET_SWAPINDEX_FAILED + NOTHING_TO_DO = RET_NOTHING_TO_DO + SETUP_BOUND_FAILED = RET_SETUP_BOUND_FAILED + SETUP_CONSTRAINT_FAILED = RET_SETUP_CONSTRAINT_FAILED + MOVING_BOUND_FAILED = RET_MOVING_BOUND_FAILED + MOVING_CONSTRAINT_FAILED = RET_MOVING_CONSTRAINT_FAILED + SHIFTING_FAILED = RET_SHIFTING_FAILED + ROTATING_FAILED = RET_ROTATING_FAILED + QPOBJECT_NOT_SETUP = RET_QPOBJECT_NOT_SETUP + QP_ALREADY_INITIALISED = RET_QP_ALREADY_INITIALISED + NO_INIT_WITH_STANDARD_SOLVER = RET_NO_INIT_WITH_STANDARD_SOLVER + RESET_FAILED = RET_RESET_FAILED + INIT_FAILED = RET_INIT_FAILED + INIT_FAILED_TQ = RET_INIT_FAILED_TQ + INIT_FAILED_CHOLESKY = RET_INIT_FAILED_CHOLESKY + INIT_FAILED_HOTSTART = RET_INIT_FAILED_HOTSTART + INIT_FAILED_INFEASIBILITY = RET_INIT_FAILED_INFEASIBILITY + INIT_FAILED_UNBOUNDEDNESS = RET_INIT_FAILED_UNBOUNDEDNESS + INIT_FAILED_REGULARISATION = RET_INIT_FAILED_REGULARISATION + INIT_SUCCESSFUL = RET_INIT_SUCCESSFUL + OBTAINING_WORKINGSET_FAILED = RET_OBTAINING_WORKINGSET_FAILED + SETUP_WORKINGSET_FAILED = RET_SETUP_WORKINGSET_FAILED + SETUP_AUXILIARYQP_FAILED = RET_SETUP_AUXILIARYQP_FAILED + NO_EXTERN_SOLVER = RET_NO_EXTERN_SOLVER + QP_UNBOUNDED = RET_QP_UNBOUNDED + QP_INFEASIBLE = RET_QP_INFEASIBLE + QP_NOT_SOLVED = RET_QP_NOT_SOLVED + QP_SOLVED = RET_QP_SOLVED + UNABLE_TO_SOLVE_QP = RET_UNABLE_TO_SOLVE_QP + INITIALISATION_STARTED = RET_INITIALISATION_STARTED + HOTSTART_FAILED = RET_HOTSTART_FAILED + HOTSTART_FAILED_TO_INIT = RET_HOTSTART_FAILED_TO_INIT + HOTSTART_FAILED_AS_QP_NOT_INITIALISED = RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED + ITERATION_STARTED = RET_ITERATION_STARTED + SHIFT_DETERMINATION_FAILED = RET_SHIFT_DETERMINATION_FAILED + STEPDIRECTION_DETERMINATION_FAILED = RET_STEPDIRECTION_DETERMINATION_FAILED + STEPLENGTH_DETERMINATION_FAILED = RET_STEPLENGTH_DETERMINATION_FAILED + OPTIMAL_SOLUTION_FOUND = RET_OPTIMAL_SOLUTION_FOUND + HOMOTOPY_STEP_FAILED = RET_HOMOTOPY_STEP_FAILED + HOTSTART_STOPPED_INFEASIBILITY = RET_HOTSTART_STOPPED_INFEASIBILITY + HOTSTART_STOPPED_UNBOUNDEDNESS = RET_HOTSTART_STOPPED_UNBOUNDEDNESS + WORKINGSET_UPDATE_FAILED = RET_WORKINGSET_UPDATE_FAILED + MAX_NWSR_REACHED = RET_MAX_NWSR_REACHED + CONSTRAINTS_NOT_SPECIFIED = RET_CONSTRAINTS_NOT_SPECIFIED + INVALID_FACTORISATION_FLAG = RET_INVALID_FACTORISATION_FLAG + UNABLE_TO_SAVE_QPDATA = RET_UNABLE_TO_SAVE_QPDATA + STEPDIRECTION_FAILED_TQ = RET_STEPDIRECTION_FAILED_TQ + STEPDIRECTION_FAILED_CHOLESKY = RET_STEPDIRECTION_FAILED_CHOLESKY + CYCLING_DETECTED = RET_CYCLING_DETECTED + CYCLING_NOT_RESOLVED = RET_CYCLING_NOT_RESOLVED + CYCLING_RESOLVED = RET_CYCLING_RESOLVED + STEPSIZE = RET_STEPSIZE + STEPSIZE_NONPOSITIVE = RET_STEPSIZE_NONPOSITIVE + SETUPSUBJECTTOTYPE_FAILED = RET_SETUPSUBJECTTOTYPE_FAILED + ADDCONSTRAINT_FAILED = RET_ADDCONSTRAINT_FAILED + ADDCONSTRAINT_FAILED_INFEASIBILITY = RET_ADDCONSTRAINT_FAILED_INFEASIBILITY + ADDBOUND_FAILED = RET_ADDBOUND_FAILED + ADDBOUND_FAILED_INFEASIBILITY = RET_ADDBOUND_FAILED_INFEASIBILITY + REMOVECONSTRAINT_FAILED = RET_REMOVECONSTRAINT_FAILED + REMOVEBOUND_FAILED = RET_REMOVEBOUND_FAILED + REMOVE_FROM_ACTIVESET = RET_REMOVE_FROM_ACTIVESET + ADD_TO_ACTIVESET = RET_ADD_TO_ACTIVESET + REMOVE_FROM_ACTIVESET_FAILED = RET_REMOVE_FROM_ACTIVESET_FAILED + ADD_TO_ACTIVESET_FAILED = RET_ADD_TO_ACTIVESET_FAILED + CONSTRAINT_ALREADY_ACTIVE = RET_CONSTRAINT_ALREADY_ACTIVE + ALL_CONSTRAINTS_ACTIVE = RET_ALL_CONSTRAINTS_ACTIVE + LINEARLY_DEPENDENT = RET_LINEARLY_DEPENDENT + LINEARLY_INDEPENDENT = RET_LINEARLY_INDEPENDENT + LI_RESOLVED = RET_LI_RESOLVED + ENSURELI_FAILED = RET_ENSURELI_FAILED + ENSURELI_FAILED_TQ = RET_ENSURELI_FAILED_TQ + ENSURELI_FAILED_NOINDEX = RET_ENSURELI_FAILED_NOINDEX + ENSURELI_FAILED_CYCLING = RET_ENSURELI_FAILED_CYCLING + BOUND_ALREADY_ACTIVE = RET_BOUND_ALREADY_ACTIVE + ALL_BOUNDS_ACTIVE = RET_ALL_BOUNDS_ACTIVE + CONSTRAINT_NOT_ACTIVE = RET_CONSTRAINT_NOT_ACTIVE + BOUND_NOT_ACTIVE = RET_BOUND_NOT_ACTIVE + HESSIAN_NOT_SPD = RET_HESSIAN_NOT_SPD + HESSIAN_INDEFINITE = RET_HESSIAN_INDEFINITE + MATRIX_SHIFT_FAILED = RET_MATRIX_SHIFT_FAILED + MATRIX_FACTORISATION_FAILED = RET_MATRIX_FACTORISATION_FAILED + PRINT_ITERATION_FAILED = RET_PRINT_ITERATION_FAILED + NO_GLOBAL_MESSAGE_OUTPUTFILE = RET_NO_GLOBAL_MESSAGE_OUTPUTFILE + DISABLECONSTRAINTS_FAILED = RET_DISABLECONSTRAINTS_FAILED + ENABLECONSTRAINTS_FAILED = RET_ENABLECONSTRAINTS_FAILED + ALREADY_ENABLED = RET_ALREADY_ENABLED + ALREADY_DISABLED = RET_ALREADY_DISABLED + NO_HESSIAN_SPECIFIED = RET_NO_HESSIAN_SPECIFIED + USING_REGULARISATION = RET_USING_REGULARISATION + EPS_MUST_BE_POSITVE = RET_EPS_MUST_BE_POSITVE + REGSTEPS_MUST_BE_POSITVE = RET_REGSTEPS_MUST_BE_POSITVE + HESSIAN_ALREADY_REGULARISED = RET_HESSIAN_ALREADY_REGULARISED + CANNOT_REGULARISE_IDENTITY = RET_CANNOT_REGULARISE_IDENTITY + CANNOT_REGULARISE_SPARSE = RET_CANNOT_REGULARISE_SPARSE + NO_REGSTEP_NWSR = RET_NO_REGSTEP_NWSR + FEWER_REGSTEPS_NWSR = RET_FEWER_REGSTEPS_NWSR + CHOLESKY_OF_ZERO_HESSIAN = RET_CHOLESKY_OF_ZERO_HESSIAN + CONSTRAINTS_ARE_NOT_SCALED = RET_CONSTRAINTS_ARE_NOT_SCALED + INITIAL_BOUNDS_STATUS_NYI = RET_INITIAL_BOUNDS_STATUS_NYI + ERROR_IN_CONSTRAINTPRODUCT = RET_ERROR_IN_CONSTRAINTPRODUCT + FIX_BOUNDS_FOR_LP = RET_FIX_BOUNDS_FOR_LP + USE_REGULARISATION_FOR_LP = RET_USE_REGULARISATION_FOR_LP + UPDATEMATRICES_FAILED = RET_UPDATEMATRICES_FAILED + UPDATEMATRICES_FAILED_AS_QP_NOT_SOLVED= RET_UPDATEMATRICES_FAILED_AS_QP_NOT_SOLVED + UNABLE_TO_OPEN_FILE = RET_UNABLE_TO_OPEN_FILE + UNABLE_TO_WRITE_FILE = RET_UNABLE_TO_WRITE_FILE + UNABLE_TO_READ_FILE = RET_UNABLE_TO_READ_FILE + FILEDATA_INCONSISTENT = RET_FILEDATA_INCONSISTENT + UNABLE_TO_ANALYSE_QPROBLEM = RET_UNABLE_TO_ANALYSE_QPROBLEM + OPTIONS_ADJUSTED = RET_OPTIONS_ADJUSTED + NWSR_SET_TO_ONE = RET_NWSR_SET_TO_ONE + UNABLE_TO_READ_BENCHMARK = RET_UNABLE_TO_READ_BENCHMARK + BENCHMARK_ABORTED = RET_BENCHMARK_ABORTED + INITIAL_QP_SOLVED = RET_INITIAL_QP_SOLVED + QP_SOLUTION_STARTED = RET_QP_SOLUTION_STARTED + BENCHMARK_SUCCESSFUL = RET_BENCHMARK_SUCCESSFUL + NO_DIAGONAL_AVAILABLE = RET_NO_DIAGONAL_AVAILABLE + DIAGONAL_NOT_INITIALISED = RET_DIAGONAL_NOT_INITIALISED + ENSURELI_DROPPED = RET_ENSURELI_DROPPED + SIMPLE_STATUS_P1 = RET_SIMPLE_STATUS_P1 + SIMPLE_STATUS_P0 = RET_SIMPLE_STATUS_P0 + SIMPLE_STATUS_M1 = RET_SIMPLE_STATUS_M1 + SIMPLE_STATUS_M2 = RET_SIMPLE_STATUS_M2 + SIMPLE_STATUS_M3 = RET_SIMPLE_STATUS_M3 + + + +cdef class PyOptions: + cdef Options *thisptr # hold a C++ instance which we're wrapping + def __cinit__(self): + # FIXME: add support for the other constructors + self.thisptr = new Options() + + def __dealloc__(self): + del self.thisptr + + def setToDefault(self): + return self.thisptr.setToDefault() + + def setToReliable(self): + return self.thisptr.setToReliable() + + def setToMPC(self): + return self.thisptr.setToMPC() + + def setToFast(self): + return self.thisptr.setToFast() + + def ensureConsistency(self): + return self.thisptr.ensureConsistency() + + property printLevel: + def __get__(self): return self.thisptr.printLevel + def __set__(self, printLevel): self.thisptr.printLevel = printLevel + + property enableRamping: + def __get__(self): return self.thisptr.enableRamping + def __set__(self, enableRamping): self.thisptr.enableRamping = enableRamping + + property enableFarBounds: + def __get__(self): return self.thisptr.enableFarBounds + def __set__(self, enableFarBounds): self.thisptr.enableFarBounds = enableFarBounds + + property enableFlippingBounds: + def __get__(self): return self.thisptr.enableFlippingBounds + def __set__(self, enableFlippingBounds): self.thisptr.enableFlippingBounds = enableFlippingBounds + + property enableRegularisation: + def __get__(self): return self.thisptr.enableRegularisation + def __set__(self, enableRegularisation): self.thisptr.enableRegularisation = enableRegularisation + + property enableFullLITests: + def __get__(self): return self.thisptr.enableFullLITests + def __set__(self, enableFullLITests): self.thisptr.enableFullLITests = enableFullLITests + + property enableNZCTests: + def __get__(self): return self.thisptr.enableNZCTests + def __set__(self, enableNZCTests): self.thisptr.enableNZCTests = enableNZCTests + + property enableDriftCorrection: + def __get__(self): return self.thisptr.enableDriftCorrection + def __set__(self, enableDriftCorrection): self.thisptr.enableDriftCorrection = enableDriftCorrection + + property enableCholeskyRefactorisation: + def __get__(self): return self.thisptr.enableCholeskyRefactorisation + def __set__(self, enableCholeskyRefactorisation): self.thisptr.enableCholeskyRefactorisation = enableCholeskyRefactorisation + + property enableEqualities: + def __get__(self): return self.thisptr.enableEqualities + def __set__(self, enableEqualities): self.thisptr.enableEqualities = enableEqualities + + property terminationTolerance: + def __get__(self): return self.thisptr.terminationTolerance + def __set__(self, terminationTolerance): self.thisptr.terminationTolerance = terminationTolerance + + property boundTolerance: + def __get__(self): return self.thisptr.boundTolerance + def __set__(self, boundTolerance): self.thisptr.boundTolerance = boundTolerance + + property boundRelaxation: + def __get__(self): return self.thisptr.boundRelaxation + def __set__(self, boundRelaxation): self.thisptr.boundRelaxation = boundRelaxation + + property epsNum: + def __get__(self): return self.thisptr.epsNum + def __set__(self, epsNum): self.thisptr.epsNum = epsNum + + property epsDen: + def __get__(self): return self.thisptr.epsDen + def __set__(self, epsDen): self.thisptr.epsDen = epsDen + + property maxPrimalJump: + def __get__(self): return self.thisptr.maxPrimalJump + def __set__(self, maxPrimalJump): self.thisptr.maxPrimalJump = maxPrimalJump + + property maxDualJump: + def __get__(self): return self.thisptr.maxDualJump + def __set__(self, maxDualJump): self.thisptr.maxDualJump = maxDualJump + + property initialRamping: + def __get__(self): return self.thisptr.initialRamping + def __set__(self, initialRamping): self.thisptr.initialRamping = initialRamping + + property finalRamping: + def __get__(self): return self.thisptr.finalRamping + def __set__(self, finalRamping): self.thisptr.finalRamping = finalRamping + + property initialFarBounds: + def __get__(self): return self.thisptr.initialFarBounds + def __set__(self, initialFarBounds): self.thisptr.initialFarBounds = initialFarBounds + + property growFarBounds: + def __get__(self): return self.thisptr.growFarBounds + def __set__(self, growFarBounds): self.thisptr.growFarBounds = growFarBounds + + property initialStatusBounds: + def __get__(self): return self.thisptr.initialStatusBounds + def __set__(self, initialStatusBounds): self.thisptr.initialStatusBounds = initialStatusBounds + + property epsFlipping: + def __get__(self): return self.thisptr.epsFlipping + def __set__(self, epsFlipping): self.thisptr.epsFlipping = epsFlipping + + property numRegularisationSteps: + def __get__(self): return self.thisptr.numRegularisationSteps + def __set__(self, numRegularisationSteps): self.thisptr.numRegularisationSteps = numRegularisationSteps + + property epsRegularisation: + def __get__(self): return self.thisptr.epsRegularisation + def __set__(self, epsRegularisation): self.thisptr.epsRegularisation = epsRegularisation + + property numRefinementSteps: + def __get__(self): return self.thisptr.numRefinementSteps + def __set__(self, numRefinementSteps): self.thisptr.numRefinementSteps = numRefinementSteps + + property epsIterRef: + def __get__(self): return self.thisptr.epsIterRef + def __set__(self, epsIterRef): self.thisptr.epsIterRef = epsIterRef + + property epsLITests: + def __get__(self): return self.thisptr.epsLITests + def __set__(self, epsLITests): self.thisptr.epsLITests = epsLITests + + property epsNZCTests: + def __get__(self): return self.thisptr.epsNZCTests + def __set__(self, epsNZCTests): self.thisptr.epsNZCTests = epsNZCTests + + property dropBoundPriority: + def __get__(self): return self.thisptr.dropBoundPriority + def __set__(self, dropBoundPriority): self.thisptr.dropBoundPriority = dropBoundPriority + + property dropEqConPriority: + def __get__(self): return self.thisptr.dropEqConPriority + def __set__(self, dropEqConPriority): self.thisptr.dropEqConPriority = dropEqConPriority + + property dropIneqConPriority: + def __get__(self): return self.thisptr.dropIneqConPriority + def __set__(self, dropIneqConPriority): self.thisptr.dropIneqConPriority = dropIneqConPriority + + + +cdef class PyQProblemB: + cdef QProblemB *thisptr # hold a C++ instance which we're wrapping + def __cinit__(self, int nV): + # FIXME: allow other HessianTypes! + self.thisptr = new QProblemB(nV, HST_UNKNOWN) + def __dealloc__(self): + del self.thisptr + + def init(self, + np.ndarray[np.double_t, ndim=2] H, + np.ndarray[np.double_t, ndim=1] g, + np.ndarray[np.double_t, ndim=1] lb, + np.ndarray[np.double_t, ndim=1] ub, + nWSR, + double cputime=0): + + # FIXME: add asserts + + if cputime > 1.e-16: + return self.thisptr.init( + H.data, + g.data, + lb.data, + ub.data, + nWSR, + &cputime + ) + + return self.thisptr.init( + H.data, + g.data, + lb.data, + ub.data, + nWSR) + + def hotstart(self, + np.ndarray[np.double_t, ndim=1] g, + np.ndarray[np.double_t, ndim=1] lb, + np.ndarray[np.double_t, ndim=1] ub, + nWSR, + double cputime=0): + + # FIXME: add asserts + + if cputime > 1.e-16: + return self.thisptr.hotstart( + g.data, + lb.data, + ub.data, + nWSR, + &cputime + ) + + return self.thisptr.hotstart( + g.data, + lb.data, + ub.data, + nWSR) + + def getPrimalSolution(self, np.ndarray[np.double_t, ndim=1] xOpt): + return self.thisptr.getPrimalSolution( xOpt.data) + + def getDualSolution(self, np.ndarray[np.double_t, ndim=1] yOpt): + return self.thisptr.getDualSolution( yOpt.data) + + def getObjVal(self): + return self.thisptr.getObjVal() + + def printOptions(self): + return self.thisptr.printOptions() + + def getOptions(self): + # FIXME: memory management? who deallocates o + cdef Options *o = new Options(self.thisptr.getOptions()) + retval = PyOptions() + retval.thisptr = o + return retval + + def setOptions(self, PyOptions options): + self.thisptr.setOptions(deref(options.thisptr)) + + +cdef class PyQProblem: + cdef QProblem *thisptr # hold a C++ instance which we're wrapping + def __cinit__(self, int nV, int nC): + self.thisptr = new QProblem(nV, nC, HST_UNKNOWN) + def __dealloc__(self): + del self.thisptr + + cpdef init(self, + np.ndarray[np.double_t, ndim=2] H, + np.ndarray[np.double_t, ndim=1] g, + np.ndarray[np.double_t, ndim=2] A, + np.ndarray[np.double_t, ndim=1] lb, + np.ndarray[np.double_t, ndim=1] ub, + np.ndarray[np.double_t, ndim=1] lbA, + np.ndarray[np.double_t, ndim=1] ubA, + nWSR, + double cputime=0): + + # FIXME: add asserts + + if cputime > 1.e-16: + return self.thisptr.init( + H.data, + g.data, + A.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + nWSR, + &cputime) + + return self.thisptr.init( + H.data, + g.data, + A.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + nWSR) + + cpdef hotstart(self, + np.ndarray[np.double_t, ndim=1] g, + np.ndarray[np.double_t, ndim=1] lb, + np.ndarray[np.double_t, ndim=1] ub, + np.ndarray[np.double_t, ndim=1] lbA, + np.ndarray[np.double_t, ndim=1] ubA, + nWSR, + double cputime=0): + + # FIXME: add asserts + + if cputime > 1.e-16: + return self.thisptr.hotstart( + g.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + nWSR, + &cputime + ) + + return self.thisptr.hotstart( + g.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + nWSR) + + cpdef getPrimalSolution(self, np.ndarray[np.double_t, ndim=1] xOpt): + return self.thisptr.getPrimalSolution( xOpt.data) + + cpdef getDualSolution(self, np.ndarray[np.double_t, ndim=1] yOpt): + return self.thisptr.getDualSolution( yOpt.data) + + cpdef getObjVal(self): + return self.thisptr.getObjVal() + + cpdef printOptions(self): + return self.thisptr.printOptions() + + cpdef setOptions(self, PyOptions options): + self.thisptr.setOptions(deref(options.thisptr)) + +cdef class PySQProblem: + cdef SQProblem *thisptr # hold a C++ instance which we're wrapping + def __cinit__(self, int nV, int nC): + self.thisptr = new SQProblem(nV, nC, HST_UNKNOWN) + def __dealloc__(self): + del self.thisptr + + cpdef init(self, + np.ndarray[np.double_t, ndim=2] H, + np.ndarray[np.double_t, ndim=1] g, + np.ndarray[np.double_t, ndim=2] A, + np.ndarray[np.double_t, ndim=1] lb, + np.ndarray[np.double_t, ndim=1] ub, + np.ndarray[np.double_t, ndim=1] lbA, + np.ndarray[np.double_t, ndim=1] ubA, + int nWSR, + double cputime=0): + + # FIXME: add asserts + + if cputime > 1.e-16: + return self.thisptr.init( + H.data, + g.data, + A.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + nWSR, + &cputime + ) + + return self.thisptr.init( + H.data, + g.data, + A.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + nWSR + ) + + cpdef hotstart(self, + np.ndarray[np.double_t, ndim=2] H, + np.ndarray[np.double_t, ndim=1] g, + np.ndarray[np.double_t, ndim=2] A, + np.ndarray[np.double_t, ndim=1] lb, + np.ndarray[np.double_t, ndim=1] ub, + np.ndarray[np.double_t, ndim=1] lbA, + np.ndarray[np.double_t, ndim=1] ubA, + int nWSR, + double cputime=0): + + # FIXME: add asserts + + if cputime > 1.e-16: + return self.thisptr.hotstart( + H.data, + g.data, + A.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + nWSR, + &cputime + ) + + return self.thisptr.hotstart( + H.data, + g.data, + A.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + nWSR + ) + + cpdef getPrimalSolution(self, np.ndarray[np.double_t, ndim=1] xOpt): + return self.thisptr.getPrimalSolution( xOpt.data) + + cpdef getDualSolution(self, np.ndarray[np.double_t, ndim=1] yOpt): + return self.thisptr.getDualSolution( yOpt.data) + + cpdef getObjVal(self): + return self.thisptr.getObjVal() + + cpdef printOptions(self): + return self.thisptr.printOptions() + + cpdef setOptions(self, PyOptions options): + self.thisptr.setOptions(deref(options.thisptr)) + + +cdef class PySolutionAnalysis: + cdef SolutionAnalysis *thisptr # hold a C++ instance which we're wrapping + def __cinit__(self): + self.thisptr = new SolutionAnalysis() + def __dealloc__(self): + del self.thisptr + + cpdef getMaxKKTviolation(self, qp, np.ndarray[np.double_t, ndim=1] maxKKTviolation): + + if isinstance(qp, PyQProblemB): + return self._getMaxKKTviolation_QProblemB(qp, maxKKTviolation) + + elif isinstance(qp, PyQProblem): + return self._getMaxKKTviolation_QProblem(qp, maxKKTviolation) + + elif isinstance(qp, PySQProblem): + return self._getMaxKKTviolation_SQProblem(qp, maxKKTviolation) + + else: + raise ValueError('argument 1 must be QProblemB, QProblem or SQProblem') + + + cpdef _getMaxKKTviolation_QProblemB(self, PyQProblemB qp, np.ndarray[np.double_t, ndim=1] maxKKTviolation): + return self.thisptr.getMaxKKTviolation(qp.thisptr, maxKKTviolation.data[0]) + + cpdef _getMaxKKTviolation_QProblem(self, PyQProblem qp, np.ndarray[np.double_t, ndim=1] maxKKTviolation): + return self.thisptr.getMaxKKTviolation(qp.thisptr, maxKKTviolation.data[0]) + + cpdef _getMaxKKTviolation_SQProblem(self, PySQProblem qp, np.ndarray[np.double_t, ndim=1] maxKKTviolation): + return self.thisptr.getMaxKKTviolation(qp.thisptr, maxKKTviolation.data[0]) + + + + cpdef getVarianceCovariance(self, + qp, + np.ndarray[np.double_t, ndim=1] g_b_bA_VAR, + np.ndarray[np.double_t, ndim=1] Primal_Dual_VAR ): + + if isinstance(qp, PyQProblemB): + return self._getVarianceCovariance_QProblemB(qp, g_b_bA_VAR, Primal_Dual_VAR) + + elif isinstance(qp, PyQProblem): + return self._getVarianceCovariance_QProblem(qp, g_b_bA_VAR, Primal_Dual_VAR) + + elif isinstance(qp, PySQProblem): + return self._getVarianceCovariance_SQProblem(qp, g_b_bA_VAR, Primal_Dual_VAR) + + else: + raise ValueError('argument 1 must be QProblemB, QProblem or SQProblem') + + cpdef _getVarianceCovariance_QProblemB(self, + PyQProblemB qp, + np.ndarray[np.double_t, ndim=1] g_b_bA_VAR, + np.ndarray[np.double_t, ndim=1] Primal_Dual_VAR ): + return self.thisptr.getVarianceCovariance(qp.thisptr, + g_b_bA_VAR.data, + Primal_Dual_VAR.data) + + cpdef _getVarianceCovariance_QProblem(self, + PyQProblem qp, + np.ndarray[np.double_t, ndim=1] g_b_bA_VAR, + np.ndarray[np.double_t, ndim=1] Primal_Dual_VAR ): + return self.thisptr.getVarianceCovariance(qp.thisptr, + g_b_bA_VAR.data, + Primal_Dual_VAR.data) + + cpdef _getVarianceCovariance_SQProblem(self, + PySQProblem qp, + np.ndarray[np.double_t, ndim=1] g_b_bA_VAR, + np.ndarray[np.double_t, ndim=1] Primal_Dual_VAR ): + return self.thisptr.getVarianceCovariance(qp.thisptr, + g_b_bA_VAR.data, + Primal_Dual_VAR.data) + +# Wrapped some utility functions for unit testing +cpdef py_runOQPbenchmark(path, # Full path of the benchmark files (without trailing slash!). + isSparse, # Shall convert matrices to sparse format before solution? + useHotstarts, # Shall QP solution be hotstarted? + PyOptions options, # QP solver options to be used while solving benchmark problems. + int maxAllowedNWSR, # Maximum number of working set recalculations to be performed. + double maxCPUTime, # Maximum allowed CPU time for qp solving. + ): + """run a QP benchmark example""" + maxNWSR = 0.0 # Output: Maximum number of performed working set recalculations. + avgNWSR = 0.0 # Output: Average number of performed working set recalculations. + maxCPUtime = 0.0 # Output: Maximum CPU time required for solving each QP. + avgCPUtime = 0.0 # Output: Average CPU time required for solving each QP. + maxStationarity = 0.0 # Output: Maximum residual of stationarity condition. + maxFeasibility = 0.0 # Output: Maximum residual of primal feasibility condition. + maxComplementarity = 0.0 # Output: Maximum residual of complementarity condition. + + maxCPUtime = maxCPUTime + + p = path.encode() + returnValue = runOQPbenchmark(p, + isSparse, + useHotstarts, + deref(options.thisptr), + maxAllowedNWSR, + maxNWSR, + avgNWSR, + maxCPUtime, + avgCPUtime, + maxStationarity, + maxFeasibility, + maxComplementarity) + + return returnValue, maxNWSR, avgNWSR, maxCPUtime, avgCPUtime, \ + maxStationarity, maxFeasibility, maxComplementarity + + +def py_getKKTResidual(int nV, # Number of variables. + int nC, # Number of constraints. + np.ndarray[np.double_t, ndim=2] H, # Hessian matrix. + np.ndarray[np.double_t, ndim=1] g, # Sequence of gradient vectors. + np.ndarray[np.double_t, ndim=2] A, # Constraint matrix. + np.ndarray[np.double_t, ndim=1] lb, # Sequence of lower bound vectors (on variables). + np.ndarray[np.double_t, ndim=1] ub, # Sequence of upper bound vectors (on variables). + np.ndarray[np.double_t, ndim=1] lbA, # Sequence of lower constraints' bound vectors. + np.ndarray[np.double_t, ndim=1] ubA, # Sequence of upper constraints' bound vectors. + np.ndarray[np.double_t, ndim=1] x, # Sequence of primal trial vectors. + np.ndarray[np.double_t, ndim=1] y, # Sequence of dual trial vectors. + ): + stat = 0.0 # Maximum value of stationarity condition residual. + feas = 0.0 # Maximum value of primal feasibility violation. + cmpl = 0.0 # Maximum value of complementarity residual. + getKKTResidual(nV, + nC, + H.data, + g.data, + A.data, + lb.data, + ub.data, + lbA.data, + ubA.data, + x.data, + y.data, + stat, + feas, + cmpl + ) + return stat, feas, cmpl + diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/setup.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/setup.py new file mode 100644 index 00000000000..e338fc993ad --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/setup.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +## +## This file is part of qpOASES. +## +## qpOASES -- An Implementation of the Online Active Set Strategy. +## Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +## Christian Kirches et al. All rights reserved. +## +## qpOASES is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## qpOASES is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with qpOASES; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## + +## +## Filename: setup.py +## Author: Sebastian F. Walter, Manuel Kudruss +## Version: 3.0 +## Date: 2013-2014 +## + + +from distutils.core import setup +from distutils.extension import Extension +from Cython.Distutils import build_ext +from Cython.Build import cythonize + +import os +import numpy as np + +BASEDIR = os.path.dirname(os.path.abspath(__file__)) +BASEDIR = os.path.dirname(BASEDIR) +BASEDIR = os.path.dirname(BASEDIR) +print(('BASEDIR=', BASEDIR)) + +extra_params = {} +extra_params['include_dirs'] = [ + '/usr/include', + os.path.join(BASEDIR, 'include'), + os.path.join(BASEDIR, 'include', 'qpOASES'), + np.get_include()] +extra_params['extra_compile_args'] = ["-O2", "-Wno-unused-variable"] +extra_params['extra_link_args'] = ["-Wl,-O1", "-Wl,--as-needed"] + +extra_params = extra_params.copy() +extra_params['libraries'] = ['qpOASES'] + +extra_params['library_dirs'] = ['/usr/lib', os.path.join(BASEDIR, 'bin')] +extra_params['language'] = 'c++' + +if os.name == 'posix': + extra_params['runtime_library_dirs'] = extra_params['library_dirs'] + +ext_modules = [ + Extension("qpoases", ["qpoases.pyx", "qpoases.pxd"], **extra_params), +] + +setup( + name='qpOASES interface', + cmdclass={'build_ext': build_ext}, + ext_modules=cythonize(ext_modules), +) diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/__init__.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/index.html b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/index.html new file mode 100644 index 00000000000..2adccecf074 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/index.html @@ -0,0 +1,11 @@ +qpOASES - Revision 198: /stable/3.0/interfaces/python/tests + +

qpOASES - Revision 198: /stable/3.0/interfaces/python/tests

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_examples.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_examples.py new file mode 100644 index 00000000000..b826ef08868 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_examples.py @@ -0,0 +1,328 @@ +""" +This file is part of qpOASES. + +qpOASES -- An Implementation of the Online Active Set Strategy. +Copyright (C) 2007-2009 by Hans Joachim Ferreau et al. All rights reserved. + +qpOASES is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +qpOASES is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with qpOASES; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +author Manuel Kudruss +version 3.0 +date 2013-2014 +""" + +import os +import re +import numpy as np +from numpy.testing import * +from subprocess import Popen, PIPE, STDOUT + +from qpoases import PyQProblem as QProblem +from qpoases import PyQProblemB as QProblemB +from qpoases import PySQProblem as SQProblem +from qpoases import PySolutionAnalysis as SolutionAnalysis +from qpoases import PyBooleanType as BooleanType +from qpoases import PySubjectToStatus as SubjectToStatus +from qpoases import PyOptions as Options +from qpoases import PyPrintLevel as PrintLevel + +# get qpOASES path +qpoases_path = os.path.dirname(os.path.abspath(__file__)) +qpoases_path = os.path.dirname(qpoases_path) +qpoases_path = os.path.dirname(qpoases_path) +qpoases_path = os.path.dirname(qpoases_path) + +# set qpOASES binary path +bin_path = os.path.join(qpoases_path, "bin") + +class TestExamples(TestCase): + + def test_example1(self): + return 0 + # Example for qpOASES main function using the QProblem class. + #Setup data of first QP. + + H = np.array([1.0, 0.0, 0.0, 0.5 ]).reshape((2,2)) + A = np.array([1.0, 1.0 ]).reshape((2,1)) + g = np.array([1.5, 1.0 ]) + lb = np.array([0.5, -2.0]) + ub = np.array([5.0, 2.0 ]) + lbA = np.array([-1.0 ]) + ubA = np.array([2.0]) + + # Setup data of second QP. + + g_new = np.array([1.0, 1.5]) + lb_new = np.array([0.0, -1.0]) + ub_new = np.array([5.0, -0.5]) + lbA_new = np.array([-2.0]) + ubA_new = np.array([1.0]) + + # Setting up QProblemB object. + qp = QProblem(2, 1) + options = Options() + options.printLevel = PrintLevel.NONE + qp.setOptions(options) + + # Solve first QP. + nWSR = 10 + qp.init(H, g, A, lb, ub, lbA, ubA, nWSR) + + # Solve second QP. + nWSR = 10 + qp.hotstart(g_new, lb_new, ub_new, lbA_new, ubA_new, nWSR) + + # Get and print solution of second QP. + xOpt_actual = np.zeros(2) + qp.getPrimalSolution(xOpt_actual) + xOpt_actual = np.asarray(xOpt_actual, dtype=float) + objVal_actual = qp.getObjVal() + objVal_actual = np.asarray(objVal_actual, dtype=float) + + cmd = os.path.join(bin_path, "example1") + p = Popen(cmd, shell=True, stdout=PIPE) + stdout, stderr = p.communicate() + stdout = str(stdout).replace('\\n', '\n') + stdout = stdout.replace("'", '') + print(stdout) + + # get c++ solution from std + pattern = re.compile(r'xOpt\s*=\s*\[\s+(?P([0-9., e+-])*)\];') + match = pattern.search(stdout) + xOpt_expected = match.group('xOpt') + xOpt_expected = xOpt_expected.split(",") + xOpt_expected = np.asarray(xOpt_expected, dtype=float) + + pattern = re.compile(r'objVal = (?P[0-9-+e.]*)') + match = pattern.search(stdout) + objVal_expected = match.group('objVal') + objVal_expected = np.asarray(objVal_expected, dtype=float) + + print("xOpt_actual =", xOpt_actual) + print("xOpt_expected =", xOpt_expected) + print("objVal_actual = ", objVal_actual) + print("objVal_expected = ", objVal_expected) + + assert_almost_equal(xOpt_actual, xOpt_expected, decimal=7) + assert_almost_equal(objVal_actual, objVal_expected, decimal=7) + + + def test_example1b(self): + # Example for qpOASES main function using the QProblemB class. + #Setup data of first QP. + + H = np.array([1.0, 0.0, 0.0, 0.5 ]).reshape((2,2)) + g = np.array([1.5, 1.0 ]) + lb = np.array([0.5, -2.0]) + ub = np.array([5.0, 2.0 ]) + + # Setup data of second QP. + + g_new = np.array([1.0, 1.5]) + lb_new = np.array([0.0, -1.0]) + ub_new = np.array([5.0, -0.5]) + + # Setting up QProblemB object. + qp = QProblemB(2) + + options = Options() + options.enableFlippingBounds = BooleanType.FALSE + options.initialStatusBounds = SubjectToStatus.INACTIVE + options.numRefinementSteps = 1 + options.printLevel = PrintLevel.NONE + qp.setOptions(options) + + # Solve first QP. + nWSR = 10 + qp.init(H, g, lb, ub, nWSR) + + # Solve second QP. + nWSR = 10; + qp.hotstart(g_new, lb_new, ub_new, nWSR) + + # Get and print solution of second QP. + xOpt_actual = np.zeros(2) + qp.getPrimalSolution(xOpt_actual) + xOpt_actual = np.asarray(xOpt_actual, dtype=float) + objVal_actual = qp.getObjVal() + objVal_actual = np.asarray(objVal_actual, dtype=float) + + cmd = os.path.join(bin_path, "example1b") + p = Popen(cmd, shell=True, stdout=PIPE) + stdout, stderr = p.communicate() + stdout = str(stdout).replace('\\n', '\n') + stdout = stdout.replace("'", '') + print(stdout) + + # get c++ solution from std + pattern = re.compile(r'xOpt\s*=\s*\[\s+(?P([0-9., e+-])*)\];') + match = pattern.search(stdout) + xOpt_expected = match.group('xOpt') + xOpt_expected = xOpt_expected.split(",") + xOpt_expected = np.asarray(xOpt_expected, dtype=float) + + pattern = re.compile(r'objVal = (?P[0-9-+e.]*)') + match = pattern.search(stdout) + objVal_expected = match.group('objVal') + objVal_expected = np.asarray(objVal_expected, dtype=float) + + print("xOpt_actual =", xOpt_actual) + print("xOpt_expected =", xOpt_expected) + print("objVal_actual = ", objVal_actual) + print("objVal_expected = ", objVal_expected) + + assert_almost_equal(xOpt_actual, xOpt_expected, decimal=7) + assert_almost_equal(objVal_actual, objVal_expected, decimal=7) + + + def test_example2(self): + # Example for qpOASES main function using the SQProblem class. + # Setup data of first QP. + H = np.array([ 1.0, 0.0, 0.0, 0.5 ]).reshape((2,2)) + A = np.array([ 1.0, 1.0 ]).reshape((2,1)) + g = np.array([ 1.5, 1.0 ]) + lb = np.array([ 0.5, -2.0 ]) + ub = np.array([ 5.0, 2.0 ]) + lbA = np.array([ -1.0 ]) + ubA = np.array([ 2.0 ]) + + # Setup data of second QP. + H_new = np.array([ 1.0, 0.5, 0.5, 0.5 ]).reshape((2,2)) + A_new = np.array([ 1.0, 5.0 ]).reshape((2,1)) + g_new = np.array([ 1.0, 1.5 ]) + lb_new = np.array([ 0.0, -1.0 ]) + ub_new = np.array([ 5.0, -0.5 ]) + lbA_new = np.array([ -2.0 ]) + ubA_new = np.array([ 1.0 ]) + + # Setting up SQProblem object and solution analyser. + qp = SQProblem(2, 1) + options = Options() + options.printLevel = PrintLevel.NONE + qp.setOptions(options) + + analyser = SolutionAnalysis() + + # get c++ solution from std + cmd = os.path.join(bin_path, "example2") + p = Popen(cmd, shell=True, stdout=PIPE) + stdout, stderr = p.communicate() + stdout = str(stdout).replace('\\n', '\n') + stdout = stdout.replace("'", '') + print(stdout) + + # Solve first QP ... + nWSR = 10 + qp.init(H, g, A, lb, ub, lbA, ubA, nWSR) + + # ... and analyse it. + maxKKTviolation = np.zeros(1) + analyser.getMaxKKTviolation(qp, maxKKTviolation) + print("maxKKTviolation: %e\n"%maxKKTviolation) + actual = np.asarray(maxKKTviolation) + + pattern = re.compile(r'maxKKTviolation: (?P[0-9+-e.]*)') + + match = pattern.findall(stdout) + expected = np.asarray(match[0], dtype=float) + + assert_almost_equal(actual, expected, decimal=7) + + # Solve second QP ... + nWSR = 10 + qp.hotstart(H_new, g_new, A_new, + lb_new, ub_new, + lbA_new, ubA_new, nWSR) + + # ... and analyse it. + analyser.getMaxKKTviolation(qp, maxKKTviolation) + print("maxKKTviolation: %e\n"%maxKKTviolation) + actual = np.asarray(maxKKTviolation) + + expected = np.asarray(match[1], dtype=float) + + assert_almost_equal(actual, expected, decimal=7) + + + # ------------ VARIANCE-COVARIANCE EVALUATION -------------------- + + Var = np.zeros(5*5) + Primal_Dual_Var = np.zeros(5*5) + + Var.reshape((5,5))[0,0] = 1. + Var.reshape((5,5))[1,1] = 1. + + # ( 1 0 0 0 0 ) + # ( 0 1 0 0 0 ) + # Var = ( 0 0 0 0 0 ) + # ( 0 0 0 0 0 ) + # ( 0 0 0 0 0 ) + + + analyser.getVarianceCovariance(qp, Var, Primal_Dual_Var) + print('Primal_Dual_Var=\n', Primal_Dual_Var.reshape((5,5))) + actual = Primal_Dual_Var.reshape((5,5)) + + pattern = re.compile(r'Primal_Dual_VAR = (?P.*)', + re.DOTALL) + + print(stdout) + match = pattern.search(stdout) + expected = match.group('VAR').strip().split("\n") + expected = [x.strip().split() for x in expected] + print(expected) + expected = np.asarray(expected, dtype=float) + + assert_almost_equal(actual, expected, decimal=7) + + + def test_example7(self): + H = np.array([ 0.8514828085899353, -0.15739890933036804, -0.081726007163524628, -0.530426025390625, 0.16773293912410736, + -0.15739890933036804, 1.1552412509918213, 0.57780224084854126, -0.0072606131434440613, 0.010559185408055782, + -0.081726007163524628, 0.57780224084854126, 0.28925251960754395, 5.324830453901086e-006, -3.0256599075073609e-006, + -0.530426025390625, -0.0072606131434440613, 5.324830453901086e-006, 0.35609596967697144, -0.15124998986721039, + 0.16773293912410736, 0.010559185408055782, -3.0256599075073609e-006, -0.15124998986721039, + 0.15129712224006653], dtype=float).reshape((5, 5)) + g = np.array([0.30908384919166565, 0.99325823783874512, 0.49822014570236206, -0.26309865713119507, 0.024296050891280174], dtype=float).reshape((5,)) + A = np.array([1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1], dtype=float).reshape((5, 5)) + lb = np.array([-0.052359879016876221, -0.052359879016876221, -0.052359879016876221, -0.052359879016876221, -0.052359938621520996], dtype=float).reshape((5,)) + ub = np.array([ 0.052359879016876221, 0.052359879016876221, 0.052359879016876221, 0, 0], dtype=float).reshape((5,)) + lbA = np.array([-0.052359879016876221, -0.052359879016876221, -0.052359879016876221, -0.052359879016876221, -0.052359938621520996], dtype=float).reshape((5,)) + ubA = np.array([0.052359879016876221, 0.052359879016876221, 0.052359879016876221, 0, 0], dtype=float).reshape((5,)) + + # Setting up QProblem object. + qp = QProblem(5, 5) + options = Options() + options.printLevel = PrintLevel.NONE + qp.setOptions(options) + + # Solve first QP. + nWSR = 100 + qp.init(H, g, A, lb, ub, lbA, ubA, nWSR) + + result = np.zeros((5,)) + qp.getPrimalSolution(result) + + # TODO check against what? + # Where can I find solution? + +if __name__=="__main__": + try: + import nose + nose.runmodule() + + except ImportError: + sys.stderr.write("Please install nosestests for python unittesting.\n") + diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_idhessian.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_idhessian.py new file mode 100644 index 00000000000..4bddb2dc4b0 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_idhessian.py @@ -0,0 +1,94 @@ +""" +This file is part of qpOASES. + +qpOASES -- An Implementation of the Online Active Set Strategy. +Copyright (C) 2007-2009 by Hans Joachim Ferreau et al. All rights reserved. + +qpOASES is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +qpOASES is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with qpOASES; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +""" + +#TODO add doxygen support +# \author Manuel Kudruss +# \version 3.0 +# \date 2013-2014 + +import os +import numpy as np +from numpy.testing import * +from qpoases import PyQProblem as QProblem +from qpoases import PyBooleanType as BooleanType +from qpoases import PyOptions as Options +from qpoases import PyPrintLevel as PrintLevel + +# get qpOASES path +qpoases_path = os.path.dirname(os.path.abspath(__file__)) +qpoases_path = os.path.dirname(qpoases_path) +qpoases_path = os.path.dirname(qpoases_path) +qpoases_path = os.path.dirname(qpoases_path) + +# set qpOASES testing path +testing_path = os.path.join(qpoases_path, "testing") + +class TestIdHessian(TestCase): + + def test_id_hessian(self): + """Very simple example for testing qpOASES (using QProblem class).""" + + path = os.path.join(testing_path, "dev_idhessian_data") + + #Setup data for QP. + H = np.loadtxt(os.path.join(path, "H.txt")) + g = np.loadtxt(os.path.join(path, "g.txt")) + A = np.loadtxt(os.path.join(path, "A.txt")) + lb = np.loadtxt(os.path.join(path, "lb.txt")) + ub = np.loadtxt(os.path.join(path, "ub.txt")) + lbA = np.loadtxt(os.path.join(path, "lbA.txt")) + ubA = np.loadtxt(os.path.join(path, "ubA.txt")) + + #Setting up QProblem object. + qp = QProblem(72,144) + + options = Options() + options.numRefinementSteps = 1 + options.printLevel = PrintLevel.NONE + + #options.setToMPC() + #options.setToReliable() + #options.enableFlippingBounds = BooleanType.FALSE + options.enableRamping = BooleanType.FALSE + #options.enableRamping = BooleanType.TRUE + #options.enableFarBounds = BooleanType.FALSE + #options.enableRamping = BooleanType.FALSE + #options.printLevel = PL_LOW + #options.enableFullLITests = BooleanType.FALSE + #options.boundRelaxation = 1.0e-1 + qp.setOptions( options ) + + #Solve QP. + nWSR = 1200 + + qp.init(H, g, A, lb, ub, lbA, ubA, nWSR) + + # FIXME check against what? + # Where can I find solution? + +if __name__=="__main__": + try: + import nose + nose.runmodule() + + except ImportError: + sys.stderr.write("Please install nosestests for python unittesting.\n") + diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_testbench.py b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_testbench.py new file mode 100644 index 00000000000..0333ff7e42b --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/python/tests/test_testbench.py @@ -0,0 +1,332 @@ +""" +This file is part of qpOASES. + +qpOASES -- An Implementation of the Online Active Set Strategy. +Copyright (C) 2007-2009 by Hans Joachim Ferreau et al. All rights reserved. + +qpOASES is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +qpOASES is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with qpOASES; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +author Manuel Kudruss +version 3.0 +date 2013-2014 +""" + +import os +import numpy as np +from numpy.testing import * +from qpoases import py_runOQPbenchmark as runOQPbenchmark +from qpoases import PyQProblem as QProblem +from qpoases import PyBooleanType as BooleanType +from qpoases import PyReturnValue as ReturnValue +from qpoases import PyOptions as Options +from qpoases import PyPrintLevel as PrintLevel + +# get qpOASES path +qpoases_path = os.path.dirname(os.path.abspath(__file__)) +qpoases_path = os.path.dirname(qpoases_path) +qpoases_path = os.path.dirname(qpoases_path) +qpoases_path = os.path.dirname(qpoases_path) + +# set qpOASES testing path +testing_path = os.path.join(qpoases_path, 'testing') + + +benchmarks = ('CVXQP1_S', + 'CVXQP2_S', + 'CVXQP3_S', + 'DPKLO1', + 'DUAL1', + 'DUAL2', + 'DUAL3', + 'DUAL4', + 'DUALC1', + 'DUALC2', + 'DUALC5', + 'DUALC8', + 'GENHS28', + 'HS118', + 'HS21', + 'HS268', + 'HS35', + 'HS35MOD', + 'HS51', + 'HS52', + 'HS53', + 'HS76', + 'LOTSCHD', + 'PRIMALC1', + 'PRIMALC2', + 'PRIMALC5', + 'QADLITTL', + 'QAFIRO', + 'QBEACONF', + 'QBRANDY', + 'QE226', + 'QISRAEL', + 'QPCBLEND', + 'QPCBOEI2', + 'QPTEST', + 'QRECIPE', + 'QSC205', + 'QSCAGR7', + 'QSHARE1B', + 'QSHARE2B', + 'S268', + 'TAME', + 'VALUES', + 'ZECEVIC2', + ) + +def results2str(results): + """converts results dictionary to pretty string""" + hline = '{0:->11}|{0:-<12}|{0:-<12}|{0:-<12}|{0:-<8}|{0:-<8}\n'.format("") + + npass = 0 + nfail = 0 + + string = "" + string += '{:<10} | {: <10} | {: <10} | {: <10} | {: <6} | {:<6}\n'.format('problem', 'stat', 'feas', 'compl', 'nWSR', 'result') + string += hline + for key in results: + line = '{name:<10} | {stat: >10.4e} | {feas: >10.4e} | {comp: >10.4e} | {nwsr: >6d} | {pass!s:<6}\n'.format(**results[key]) + string += line + if results[key]['pass']: + npass += 1 + else: + nfail +=1 + + string += hline + string += '\n' + string += 'Testbench results:\n' + string += '==================\n' + string += 'Pass: {: >10d}\n'.format(npass) + string += 'Fail: {: >10d}\n'.format(nfail) + string += '------------------\n' + string += 'Ratio: {: >10.2%}\n'.format(npass/float(len(results))) + + return string + +def write_results(name, string): + """writes results into results dictionary""" + path = os.path.dirname(os.path.abspath(__file__)) + + directory = os.path.join(path, 'results') + + if not os.path.exists(directory): + os.makedirs(directory) + + with open(os.path.join(directory, name), 'w') as f: + f.write(string) + +def get_nfail(results): + """get nfail from results dictionary""" + nfail = 0 + for key in results: + if not results[key]['pass']: + nfail +=1 + + return nfail + +def run_benchmarks(benchmarks, options, isSparse, useHotstarts, + nWSR, cpu_time, TOL): + """run all benchmarks and return results as dictionary""" + results = {} + for item in benchmarks: + # NOTE: c/c++ function epects trailing slash in path! + path = os.path.join(testing_path, 'problems', item, '') + + # Run QP benchmark + returnvalue, maxNWSR, avgNWSR, maxCPUtime, avgCPUtime, \ + maxStationarity, maxFeasibility, maxComplementarity \ + = runOQPbenchmark(path, isSparse, useHotstarts, + options, nWSR, cpu_time ) + + if (returnvalue == ReturnValue.SUCCESSFUL_RETURN + and maxStationarity < TOL + and maxFeasibility < TOL + and maxComplementarity < TOL): + ret_val = True + + else: + ret_val = False + + tmp_d = {'name': item, + 'stat': maxStationarity, + 'feas': maxFeasibility, + 'comp': maxComplementarity, + 'nwsr': int(maxNWSR), + 'pass': bool(ret_val), + } + results[item] = tmp_d + + return results + + +class Testbench(TestCase): + + def setUp(self): + # Setup global options for every problem + self.TOL = 1e-5 + self.nWSR = 3500 + self.cpu_time = 300 + self.decimal = 7 # number of decimals for assert + + def test_m44_default_dense(self): + test_name = 'mm44_default_dense.txt' + print("Test: ", test_name) + + # QP Options + options = Options() + options.setToDefault() + options.printLevel = PrintLevel.NONE + + isSparse = False + useHotstarts = False + + # run QP benchmarks + results = run_benchmarks(benchmarks, options, isSparse, useHotstarts, + self.nWSR, self.cpu_time, self.TOL) + + # print and write results + string = results2str(results) + print(string) + write_results(test_name, string) + + assert get_nfail(results) <= 0, 'One ore more tests failed.' + + def test_m44_default_sparse(self): + test_name = 'mm44_default_sparse.txt' + print("Test: ", test_name) + + # QP Options + options = Options() + options.setToDefault() + options.printLevel = PrintLevel.NONE + + isSparse = True + useHotstarts = False + + # run QP benchmarks + results = run_benchmarks(benchmarks, options, isSparse, useHotstarts, + self.nWSR, self.cpu_time, self.TOL) + + # print and write results + string = results2str(results) + print(string) + write_results(test_name, string) + + assert get_nfail(results) <= 0, 'One ore more tests failed.' + + def test_m44_mpc_dense(self): + test_name ='mm44_mpc_dense.txt' + print("Test: ", test_name) + + # QP Options + options = Options() + options.setToMPC() + options.printLevel = PrintLevel.NONE + + isSparse = False + useHotstarts = False + + # run QP benchmarks + results = run_benchmarks(benchmarks, options, isSparse, useHotstarts, + self.nWSR, self.cpu_time, self.TOL) + + # print and write results + string = results2str(results) + print(string) + write_results(test_name, string) + + assert get_nfail(results) <= 2, 'One ore more tests failed.' + + def test_m44_mpc_sparse(self): + test_name ='mm44_mpc_sparse.txt' + print("Test: ", test_name) + + # QP Options + options = Options() + options.setToMPC() + options.printLevel = PrintLevel.NONE + + isSparse = True + useHotstarts = False + + # run QP benchmarks + results = run_benchmarks(benchmarks, options, isSparse, useHotstarts, + self.nWSR, self.cpu_time, self.TOL) + + # print and write results + string = results2str(results) + print(string) + write_results(test_name, string) + + assert get_nfail(results) <= 19, 'One ore more tests failed.' + + def test_m44_reliable_dense(self): + test_name = 'mm44_reliable_dense.txt' + print("Test: ", test_name) + + # QP Options + options = Options() + options.setToReliable() + options.printLevel = PrintLevel.NONE + + isSparse = False + useHotstarts = False + + # run QP benchmarks + results = run_benchmarks(benchmarks, options, isSparse, useHotstarts, + self.nWSR, self.cpu_time, self.TOL) + + # print and write results + string = results2str(results) + print(string) + write_results(test_name, string) + + assert get_nfail(results) <= 0, 'One ore more tests failed.' + + def test_m44_reliable_sparse(self): + test_name = 'mm44_reliable_sparse.txt' + print(test_name) + + # QP Options + options = Options() + options.setToReliable() + options.printLevel = PrintLevel.NONE + + isSparse = True + useHotstarts = False + + # run QP benchmarks + results = run_benchmarks(benchmarks, options, isSparse, useHotstarts, + self.nWSR, self.cpu_time, self.TOL) + + # print and write results + string = results2str(results) + print(string) + write_results(test_name, string) + + assert get_nfail(results) <= 0, 'One ore more tests failed.' + + +if __name__=='__main__': + try: + import nose + nose.runmodule(argv=['', '-s', '-v']) + + except ImportError: + sys.stderr.write('Please install nosestests for python unittesting.\n') + diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/example1.dat b/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/example1.dat new file mode 100644 index 0000000000000000000000000000000000000000..1c9e594b6da775ef2a23e6db6ce75a676f91f100 GIT binary patch literal 656 zcmb7AK?;O05bJss77vOy5mvCjnEqU!(jPb{@wiiH&_WOz7}7&C$>dl)#m70<sb9o^zR_9VV>O$x*y427N97KSb=-AQ2z^%n8wouhaIvnpLq1Rst}5DbL4@VzfT>F{bij4{uW zQc5u4)z(O}>f$|oa;qpOASES - Revision 198: /stable/3.0/interfaces/scilab + +

qpOASES - Revision 198: /stable/3.0/interfaces/scilab

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESinterface.c b/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESinterface.c new file mode 100644 index 00000000000..9be0a6f223c --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESinterface.c @@ -0,0 +1,1061 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/scilab/qpOASESinterface.c + * \author Holger Diedam, Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + * + * Interface that enables to call qpOASES from scilab. + * (Please excuse a lot of copy and paste...) + * + */ + + +#include +#include + +#include +#include + + +extern int int_qpOASES( char* fname ); + +extern int int_init( char* fname ); +extern int int_initSB( char* fname ); +extern int int_initVM( char* fname ); + +extern int int_solve( char* fname ); +extern int int_solveSB( char* fname ); +extern int int_solveVM( char* fname ); + +extern int int_cleanup( char* fname ); +extern int int_cleanupSB( char* fname ); +extern int int_cleanupVM( char* fname ); + + +typedef int (*gate_function) ( char* ); +extern int sci_gateway( char* name, gate_function f ); +extern int C2F(qpOASESgateway)(); + + +/* forward declaration of C++ routines */ +void qpoases( double* H, double* g, double* A, double* lb, double* ub, double* lbA, double* ubA, + int *nV, int* nC, int* nWSR, + double* x, double* obj, int* status, int* nWSRout, double* y + ); + +void init( double* H, double* g, double* A, double* lb, double* ub, double* lbA, double* ubA, + int *nV, int* nC, int* nWSR, + double* x, double* obj, int* status, int* nWSRout, double* y + ); +void initSB( double* H, double* g, double* lb, double* ub, + int *nV, int* nWSR, + double* x, double* obj, int* status, int* nWSRout, double* y + ); +void initVM( double* H, double* g, double* A, double* lb, double* ub, double* lbA, double* ubA, + int *nV, int* nC, int* nWSR, + double* x, double* obj, int* status, int* nWSRout, double* y + ); + +void hotstart( double* g, double* lb, double* ub, double* lbA, double* ubA, + int* nWSR, + double* x, double* obj, int* status, int* nWSRout, double* y + ); +void hotstartSB( double* g, double* lb, double* ub, + int* nWSR, + double* x, double* obj, int* status, int* nWSRout, double* y + ); +void hotstartVM( double* H, double* g, double* A, double* lb, double* ub, double* lbA, double* ubA, + int* nWSR, + double* x, double* obj, int* status, int* nWSRout, double* y + ); + +void cleanupp( ); +void cleanupSB( ); +void cleanupVM( ); + + +/* global variables containing dimensions of matrices + * (also used to check whether qpOASES object were initialised) */ +static int qp_rowsH = -1; +static int qp_rowsA = -1; +static int qpb_rowsH = -1; +static int sqp_rowsH = -1; +static int sqp_rowsA = -1; + + +/* + * i n t _ q p O A S E S + */ +int int_qpOASES( char* fname ) +{ + int H, H_rows, H_cols; + int g, g_rows, g_cols; + int A, A_rows, A_cols; + int lb, lb_rows, lb_cols; + int ub, ub_rows, ub_cols; + int lbA, lbA_rows, lbA_cols; + int ubA, ubA_rows, ubA_cols; + int nWSR, nWSR_rows, nWSR_cols; + + int x, obj, status, nWSRout, y; + + + int minlhs = 1, maxlhs = 5, minrhs = 8, maxrhs = 8, one = 1, y_size; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + + /* check dimensions */ + GetRhsVar( 1,"d", &H_rows,&H_cols,&H ); + if ( ( H_rows != H_cols ) || ( H_rows < 1 ) ) + { + Scierror( 111,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 2,"d", &g_rows,&g_cols,&g ); + if ( !( ( ( g_rows == H_rows ) && ( g_cols == 1 ) ) || ( ( g_rows == 1 ) && ( g_cols == H_rows ) ) ) ) + { + Scierror( 112,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 3,"d", &A_rows,&A_cols,&A ); + if ( ( A_cols != H_rows ) || ( A_rows < 1 ) ) + { + Scierror( 113,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 4,"d", &lb_rows,&lb_cols,&lb); + if ( !( ( ( lb_rows == H_rows ) && ( lb_cols == 1 ) ) || ( ( lb_rows == 0 ) && ( lb_cols == 0 ) ) ) ) + { + Scierror( 114,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 5,"d", &ub_rows,&ub_cols,&ub); + if ( !( ( ( ub_rows == H_rows ) && ( ub_cols == 1 ) ) || ( ( ub_rows == 0 ) && ( ub_cols == 0 ) ) ) ) + { + Scierror( 115,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 6,"d", &lbA_rows,&lbA_cols,&lbA); + if ( ( lbA_rows != A_rows ) || ( lbA_cols != 1 ) ) + { + Scierror( 116,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 7,"d", &ubA_rows,&ubA_cols,&ubA); + if ( ( ubA_rows != A_rows ) || ( ubA_cols != 1 ) ) + { + Scierror( 117,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 8,"i", &nWSR_rows,&nWSR_cols,&nWSR); + if ( ( nWSR_rows != nWSR_cols ) || ( nWSR_cols != 1 ) ) + { + Scierror( 118,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + + y_size = H_rows + A_rows; + + CreateVar( 9,"d", &H_rows,&one,&x ); + CreateVar( 10,"d", &one,&one,&obj ); + CreateVar( 11,"i", &one,&one,&status ); + CreateVar( 12,"i", &one,&one,&nWSRout ); + CreateVar( 13,"d", &y_size,&one,&y ); + + + /* call interfaced qpOASES routines with appropriate arguments */ + if ( ( lb_rows != 0 ) && ( ub_rows != 0 ) ) + { + qpoases( stk(H),stk(g),stk(A),stk(lb),stk(ub),stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows == 0 ) && ( ub_rows != 0 ) ) + { + qpoases( stk(H),stk(g),stk(A),0,stk(ub),stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows != 0 ) && ( ub_rows == 0 ) ) + { + qpoases( stk(H),stk(g),stk(A),stk(lb),0,stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else + { + qpoases( stk(H),stk(g),stk(A),0,0,stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + + LhsVar(1) = 9; + LhsVar(2) = 10; + LhsVar(3) = 11; + LhsVar(4) = 12; + LhsVar(5) = 13; + + return 0; +} + + +/* + * i n t _ i n i t + */ +int int_init( char* fname ) +{ + int H, H_rows, H_cols; + int g, g_rows, g_cols; + int A, A_rows, A_cols; + int lb, lb_rows, lb_cols; + int ub, ub_rows, ub_cols; + int lbA, lbA_rows, lbA_cols; + int ubA, ubA_rows, ubA_cols; + int nWSR, nWSR_rows, nWSR_cols; + + int x, obj, status, nWSRout, y; + + + int minlhs = 1, maxlhs = 5, minrhs = 8, maxrhs = 8, one = 1, y_size; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + + /* check dimensions */ + GetRhsVar( 1,"d", &H_rows,&H_cols,&H ); + if ( ( H_rows != H_cols ) || ( H_rows < 1 ) ) + { + Scierror( 211,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 2,"d", &g_rows,&g_cols,&g ); + if ( !( ( ( g_rows == H_rows ) && ( g_cols == 1 ) ) || ( ( g_rows == 1 ) && ( g_cols == H_rows ) ) ) ) + { + Scierror( 212,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 3,"d", &A_rows,&A_cols,&A ); + if ( ( A_cols != H_rows ) || ( A_rows < 1 ) ) + { + Scierror( 213,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 4,"d", &lb_rows,&lb_cols,&lb); + if ( !( ( ( lb_rows == H_rows ) && ( lb_cols == 1 ) ) || ( ( lb_rows == 0 ) && ( lb_cols == 0 ) ) ) ) + { + Scierror( 214,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 5,"d", &ub_rows,&ub_cols,&ub); + if ( !( ( ( ub_rows == H_rows ) && ( ub_cols == 1 ) ) || ( ( ub_rows == 0 ) && ( ub_cols == 0 ) ) ) ) + { + Scierror( 215,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 6,"d", &lbA_rows,&lbA_cols,&lbA); + if ( ( lbA_rows != A_rows ) || ( lbA_cols != 1 ) ) + { + Scierror( 216,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 7,"d", &ubA_rows,&ubA_cols,&ubA); + if ( ( ubA_rows != A_rows ) || ( ubA_cols != 1 ) ) + { + Scierror( 217,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 8,"i", &nWSR_rows,&nWSR_cols,&nWSR); + if ( ( nWSR_rows != nWSR_cols ) || ( nWSR_cols != 1 ) ) + { + Scierror( 218,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + + y_size = H_rows + A_rows; + + CreateVar( 9,"d", &H_rows,&one,&x ); + CreateVar( 10,"d", &one,&one,&obj ); + CreateVar( 11,"i", &one,&one,&status ); + CreateVar( 12,"i", &one,&one,&nWSRout ); + CreateVar( 13,"d", &y_size,&one,&y ); + + + qp_rowsH = H_rows; + qp_rowsA = A_rows; + + + /* call interfaced qpOASES routines with appropriate arguments */ + if ( ( lb_rows != 0 ) && ( ub_rows != 0 ) ) + { + init( stk(H),stk(g),stk(A),stk(lb),stk(ub),stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows == 0 ) && ( ub_rows != 0 ) ) + { + init( stk(H),stk(g),stk(A),0,stk(ub),stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows != 0 ) && ( ub_rows == 0 ) ) + { + init( stk(H),stk(g),stk(A),stk(lb),0,stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else + { + init( stk(H),stk(g),stk(A),0,0,stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + + LhsVar(1) = 9; + LhsVar(2) = 10; + LhsVar(3) = 11; + LhsVar(4) = 12; + LhsVar(5) = 13; + + return 0; +} + + +/* + * i n t _ i n i t S B + */ +int int_initSB( char* fname ) +{ + int H, H_rows, H_cols; + int g, g_rows, g_cols; + int lb, lb_rows, lb_cols; + int ub, ub_rows, ub_cols; + int nWSR, nWSR_rows, nWSR_cols; + + int x, obj, status, nWSRout, y; + + + int minlhs = 1, maxlhs = 5, minrhs = 5, maxrhs = 5, one = 1; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + + /* check dimensions */ + GetRhsVar( 1,"d", &H_rows,&H_cols,&H ); + if ( ( H_rows != H_cols ) || ( H_rows < 1 ) ) + { + Scierror( 221,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 2,"d", &g_rows,&g_cols,&g ); + if ( !( ( ( g_rows == H_rows ) && ( g_cols == 1 ) ) || ( ( g_rows == 1 ) && ( g_cols == H_rows ) ) ) ) + { + Scierror( 222,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 3,"d", &lb_rows,&lb_cols,&lb); + if ( !( ( ( lb_rows == H_rows ) && ( lb_cols == 1 ) ) || ( ( lb_rows == 0 ) && ( lb_cols == 0 ) ) ) ) + { + Scierror( 223,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 4,"d", &ub_rows,&ub_cols,&ub); + if ( !( ( ( ub_rows == H_rows ) && ( ub_cols == 1 ) ) || ( ( ub_rows == 0 ) && ( ub_cols == 0 ) ) ) ) + { + Scierror( 224,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 5,"i", &nWSR_rows,&nWSR_cols,&nWSR); + if ( ( nWSR_rows != nWSR_cols ) || ( nWSR_cols != 1 ) ) + { + Scierror( 225,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + + CreateVar( 9,"d", &H_rows,&one,&x ); + CreateVar( 10,"d", &one,&one,&obj ); + CreateVar( 11,"i", &one,&one,&status ); + CreateVar( 12,"i", &one,&one,&nWSRout ); + CreateVar( 13,"d", &H_rows,&one,&y ); + + + qpb_rowsH = H_rows; + + + /* call interfaced qpOASES routines with appropriate arguments */ + if ( ( lb_rows != 0 ) && ( ub_rows != 0 ) ) + { + initSB( stk(H),stk(g),stk(lb),stk(ub), + &H_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows == 0 ) && ( ub_rows != 0 ) ) + { + initSB( stk(H),stk(g),0,stk(ub), + &H_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows != 0 ) && ( ub_rows == 0 ) ) + { + initSB( stk(H),stk(g),stk(lb),0, + &H_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else + { + initSB( stk(H),stk(g),0,0, + &H_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + + LhsVar(1) = 9; + LhsVar(2) = 10; + LhsVar(3) = 11; + LhsVar(4) = 12; + LhsVar(5) = 13; + + return 0; +} + + +/* + * i n t _ i n i t V M + */ +int int_initVM( char* fname ) +{ + int H, H_rows, H_cols; + int g, g_rows, g_cols; + int A, A_rows, A_cols; + int lb, lb_rows, lb_cols; + int ub, ub_rows, ub_cols; + int lbA, lbA_rows, lbA_cols; + int ubA, ubA_rows, ubA_cols; + int nWSR, nWSR_rows, nWSR_cols; + + int x, obj, status, nWSRout, y; + + + int minlhs = 1, maxlhs = 5, minrhs = 8, maxrhs = 8, one = 1, y_size; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + + /* check dimensions */ + GetRhsVar( 1,"d", &H_rows,&H_cols,&H ); + if ( ( H_rows != H_cols ) || ( H_rows < 1 ) ) + { + Scierror( 231,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 2,"d", &g_rows,&g_cols,&g ); + if ( !( ( ( g_rows == H_rows ) && ( g_cols == 1 ) ) || ( ( g_rows == 1 ) && ( g_cols == H_rows ) ) ) ) + { + Scierror( 232,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 3,"d", &A_rows,&A_cols,&A ); + if ( ( A_cols != H_rows ) || ( A_rows < 1 ) ) + { + Scierror( 233,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 4,"d", &lb_rows,&lb_cols,&lb ); + if ( !( ( ( lb_rows == H_rows ) && ( lb_cols == 1 ) ) || ( ( lb_rows == 0 ) && ( lb_cols == 0 ) ) ) ) + { + Scierror( 234,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 5,"d", &ub_rows,&ub_cols,&ub ); + if ( !( ( ( ub_rows == H_rows ) && ( ub_cols == 1 ) ) || ( ( ub_rows == 0 ) && ( ub_cols == 0 ) ) ) ) + { + Scierror( 235,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 6,"d", &lbA_rows,&lbA_cols,&lbA ); + if ( ( lbA_rows != A_rows ) || ( lbA_cols != 1 ) ) + { + Scierror( 236,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 7,"d", &ubA_rows,&ubA_cols,&ubA ); + if ( ( ubA_rows != A_rows ) || ( ubA_cols != 1 ) ) + { + Scierror( 237,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 8,"i", &nWSR_rows,&nWSR_cols,&nWSR) ; + if ( ( nWSR_rows != nWSR_cols ) || ( nWSR_cols != 1 ) ) + { + Scierror( 238,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + + y_size = H_rows + A_rows; + + CreateVar( 9,"d", &H_rows,&one,&x ); + CreateVar( 10,"d", &one,&one,&obj ); + CreateVar( 11,"i", &one,&one,&status ); + CreateVar( 12,"i", &one,&one,&nWSRout ); + CreateVar( 13,"d", &y_size,&one,&y ); + + + sqp_rowsH = H_rows; + sqp_rowsA = A_rows; + + + /* call interfaced qpOASES routines with appropriate arguments */ + if ( ( lb_rows != 0 ) && ( ub_rows != 0 ) ) + { + initVM( stk(H),stk(g),stk(A),stk(lb),stk(ub),stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows == 0 ) && ( ub_rows != 0 ) ) + { + initVM( stk(H),stk(g),stk(A),0,stk(ub),stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows != 0 ) && ( ub_rows == 0 ) ) + { + initVM( stk(H),stk(g),stk(A),stk(lb),0,stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else + { + initVM( stk(H),stk(g),stk(A),0,0,stk(lbA),stk(ubA), + &H_rows,&A_rows,istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + + LhsVar(1) = 9; + LhsVar(2) = 10; + LhsVar(3) = 11; + LhsVar(4) = 12; + LhsVar(5) = 13; + + return 0; +} + + +/* + * i n t _ h o t s t a r t + */ +int int_hotstart( char* fname ) +{ + int g, g_rows, g_cols; + int lb, lb_rows, lb_cols; + int ub, ub_rows, ub_cols; + int lbA, lbA_rows, lbA_cols; + int ubA, ubA_rows, ubA_cols; + int nWSR, nWSR_rows, nWSR_cols; + + int x, obj, status, nWSRout, y; + + + int minlhs = 1, maxlhs = 5, minrhs = 6, maxrhs = 6, one = 1, y_size; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + + if ( ( qp_rowsH == -1 ) || ( qp_rowsA == -1 ) ) + { + Scierror( 311,"ERROR (qpOASES): Need to call qpOASES_init first!\n" ); + return 0; + } + + /* check dimensions */ + GetRhsVar( 1,"d", &g_rows,&g_cols,&g ); + if ( !( ( ( g_rows == qp_rowsH ) && ( g_cols == 1 ) ) || ( ( g_rows == 1 ) && ( g_cols == qp_rowsH ) ) ) ) + { + Scierror( 312,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 2,"d", &lb_rows,&lb_cols,&lb ); + if ( !( ( ( lb_rows == qp_rowsH ) && ( lb_cols == 1 ) ) || ( ( lb_rows == 0 ) && ( lb_cols == 0 ) ) ) ) + { + Scierror( 313,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 3,"d", &ub_rows,&ub_cols,&ub ); + if ( !( ( ( ub_rows == qp_rowsH ) && ( ub_cols == 1 ) ) || ( ( ub_rows == 0 ) && ( ub_cols == 0 ) ) ) ) + { + Scierror( 314,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 4,"d", &lbA_rows,&lbA_cols,&lbA ); + if ( ( lbA_rows != qp_rowsA ) || ( lbA_cols != 1 ) ) + { + Scierror( 315,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 5,"d", &ubA_rows,&ubA_cols,&ubA ); + if ( ( ubA_rows != qp_rowsA ) || ( ubA_cols != 1 ) ) + { + Scierror( 316,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 6,"i", &nWSR_rows,&nWSR_cols,&nWSR ); + if ( ( nWSR_rows != nWSR_cols ) || ( nWSR_cols != 1 ) ) + { + Scierror( 317,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + + y_size = qp_rowsH + qp_rowsA; + + CreateVar( 7,"d", &qp_rowsH,&one,&x ); + CreateVar( 8,"d", &one,&one,&obj ); + CreateVar( 9,"i", &one,&one,&status ); + CreateVar( 10,"i", &one,&one,&nWSRout ); + CreateVar( 11,"d", &y_size,&one,&y ); + + + /* call interfaced qpOASES routines with appropriate arguments */ + if ( ( lb_rows != 0 ) && ( ub_rows != 0 ) ) + { + hotstart( stk(g),stk(lb),stk(ub),stk(lbA),stk(ubA), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows == 0 ) && ( ub_rows != 0 ) ) + { + hotstart( stk(g),0,stk(ub),stk(lbA),stk(ubA), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows != 0 ) && ( ub_rows == 0 ) ) + { + hotstart( stk(g),stk(lb),0,stk(lbA),stk(ubA), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else + { + hotstart( stk(g),0,0,stk(lbA),stk(ubA), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + + + LhsVar(1) = 7; + LhsVar(2) = 8; + LhsVar(3) = 9; + LhsVar(4) = 10; + LhsVar(5) = 11; + + return 0; +} + + +/* + * i n t _ h o t s t a r t S B + */ +int int_hotstartSB( char* fname ) +{ + int g, g_rows, g_cols; + int lb, lb_rows, lb_cols; + int ub, ub_rows, ub_cols; + int nWSR, nWSR_rows, nWSR_cols; + + int x, obj, status, nWSRout, y; + + + int minlhs = 1, maxlhs = 5, minrhs = 4, maxrhs = 4, one = 1; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + + if ( qpb_rowsH == -1 ) + { + Scierror( 321,"ERROR (qpOASES): Need to call qpOASES_init first!\n" ); + return 0; + } + + /* check dimensions */ + GetRhsVar( 1,"d", &g_rows,&g_cols,&g ); + if ( !( ( ( g_rows == qpb_rowsH ) && ( g_cols == 1 ) ) || ( ( g_rows == 1 ) && ( g_cols == qpb_rowsH ) ) ) ) + { + Scierror( 322,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 2,"d", &lb_rows,&lb_cols,&lb ); + if ( !( ( ( lb_rows == qpb_rowsH ) && ( lb_cols == 1 ) ) || ( ( lb_rows == 0 ) && ( lb_cols == 0 ) ) ) ) + { + Scierror( 323,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 3,"d", &ub_rows,&ub_cols,&ub ); + if ( !( ( ( ub_rows == qpb_rowsH ) && ( ub_cols == 1 ) ) || ( ( ub_rows == 0 ) && ( ub_cols == 0 ) ) ) ) + { + Scierror( 324,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 4,"i", &nWSR_rows,&nWSR_cols,&nWSR ); + if ( ( nWSR_rows != nWSR_cols ) || ( nWSR_cols != 1 ) ) + { + Scierror( 325,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + + CreateVar( 5,"d", &qpb_rowsH,&one,&x ); + CreateVar( 6,"d", &one,&one,&obj ); + CreateVar( 7,"i", &one,&one,&status ); + CreateVar( 8,"i", &one,&one,&nWSRout ); + CreateVar( 9,"d", &qpb_rowsH,&one,&y ); + + + /* call interfaced qpOASES routines with appropriate arguments */ + if ( ( lb_rows != 0 ) && ( ub_rows != 0 ) ) + { + hotstartSB( stk(g),stk(lb),stk(ub), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows == 0 ) && ( ub_rows != 0 ) ) + { + hotstartSB( stk(g),0,stk(ub), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows != 0 ) && ( ub_rows == 0 ) ) + { + hotstartSB( stk(g),stk(lb),0, + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else + { + hotstartSB( stk(g),0,0, + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + + + LhsVar(1) = 5; + LhsVar(2) = 6; + LhsVar(3) = 7; + LhsVar(4) = 8; + LhsVar(5) = 9; + + return 0; +} + + +/* + * i n t _ h o t s t a r t V M + */ +int int_hotstartVM( char* fname ) +{ + int H, H_rows, H_cols; + int g, g_rows, g_cols; + int A, A_rows, A_cols; + int lb, lb_rows, lb_cols; + int ub, ub_rows, ub_cols; + int lbA, lbA_rows, lbA_cols; + int ubA, ubA_rows, ubA_cols; + int nWSR, nWSR_rows, nWSR_cols; + + int obj, x, y, status, nWSRout; + + + int minlhs = 1, maxlhs = 5, minrhs = 8, maxrhs = 8, one = 1, y_size; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + + if ( ( sqp_rowsH == -1 ) || ( sqp_rowsA == -1 ) ) + { + Scierror( 331,"ERROR (qpOASES): Need to call qpOASES_init first!\n" ); + return 0; + } + + /* check dimensions */ + GetRhsVar( 1,"d", &H_rows,&H_cols,&H ); + if ( ( H_rows != H_cols ) || ( H_rows < 1 ) ) + { + Scierror( 332,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 2,"d", &g_rows,&g_cols,&g ); + if ( !( ( ( g_rows == H_rows ) && ( g_cols == 1 ) ) || ( ( g_rows == 1 ) && ( g_cols == H_rows ) ) ) ) + { + Scierror( 333,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 3,"d", &A_rows,&A_cols,&A ); + if ( ( A_cols != H_rows ) || ( A_rows < 1 ) ) + { + Scierror( 334,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 4,"d", &lb_rows,&lb_cols,&lb); + if ( !( ( ( lb_rows == H_rows ) && ( lb_cols == 1 ) ) || ( ( lb_rows == 0 ) && ( lb_cols == 0 ) ) ) ) + { + Scierror( 335,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 5,"d", &ub_rows,&ub_cols,&ub); + if ( !( ( ( ub_rows == H_rows ) && ( ub_cols == 1 ) ) || ( ( ub_rows == 0 ) && ( ub_cols == 0 ) ) ) ) + { + Scierror( 399,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 6,"d", &lbA_rows,&lbA_cols,&lbA); + if ( ( lbA_rows != A_rows ) || ( lbA_cols != 1 ) ) + { + Scierror( 336,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 7,"d", &ubA_rows,&ubA_cols,&ubA); + if ( ( ubA_rows != A_rows ) || ( ubA_cols != 1 ) ) + { + Scierror( 337,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + GetRhsVar( 8,"i", &nWSR_rows,&nWSR_cols,&nWSR); + if ( ( nWSR_rows != nWSR_cols ) || ( nWSR_cols != 1 ) ) + { + Scierror( 338,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + /* have matrices same dimension as last QP? */ + if ( ( sqp_rowsH != H_rows ) || ( sqp_rowsA != A_rows ) ) + { + Scierror( 339,"ERROR (qpOASES): Dimension mismatch!\n" ); + return 0; + } + + + y_size = H_rows + A_rows; + + CreateVar( 9,"d", &H_rows,&one,&x ); + CreateVar( 10,"d", &one,&one,&obj ); + CreateVar( 11,"i", &one,&one,&status ); + CreateVar( 12,"i", &one,&one,&nWSRout ); + CreateVar( 13,"d", &y_size,&one,&y ); + + + /* call interfaced qpOASES routines with appropriate arguments */ + if ( ( lb_rows != 0 ) && ( ub_rows != 0 ) ) + { + hotstartVM( stk(H),stk(g),stk(A),stk(lb),stk(ub),stk(lbA),stk(ubA), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows == 0 ) && ( ub_rows != 0 ) ) + { + hotstartVM( stk(H),stk(g),stk(A),0,stk(ub),stk(lbA),stk(ubA), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else if ( ( lb_rows != 0 ) && ( ub_rows == 0 ) ) + { + hotstartVM( stk(H),stk(g),stk(A),stk(lb),0,stk(lbA),stk(ubA), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + else + { + hotstartVM( stk(H),stk(g),stk(A),0,0,stk(lbA),stk(ubA), + istk(nWSR), + stk(x),stk(obj),istk(status),istk(nWSRout),stk(y) + ); + } + + + LhsVar(1) = 9; + LhsVar(2) = 10; + LhsVar(3) = 11; + LhsVar(4) = 12; + LhsVar(5) = 13; + + return 0; +} + + +/* + * i n t _ c l e a n u p + */ +int int_cleanup( char* fname ) +{ + const int minlhs = 0, maxlhs = 1, minrhs = 0, maxrhs = 0; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + cleanupp( ); + qp_rowsH = -1; + qp_rowsA = -1; + + return 0; +} + + +/* + * i n t _ c l e a n u p S B + */ +int int_cleanupSB( char* fname ) +{ + const int minlhs = 0, maxlhs = 1, minrhs = 0, maxrhs = 0; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + cleanupSB( ); + qpb_rowsH = -1; + + return 0; +} + + +/* + * i n t _ c l e a n u p V M + */ +int int_cleanupVM( char* fname ) +{ + const int minlhs = 0, maxlhs = 1, minrhs = 0, maxrhs = 0; + + CheckRhs( minrhs,maxrhs ); + CheckLhs( minlhs,maxlhs ); + + cleanupVM( ); + sqp_rowsH = -1; + sqp_rowsA = -1; + + return 0; +} + + +/* + * q p O A S E S g a t e w a y + */ +int C2F(qpOASESgateway)( ) +{ + gate_function function[] = { int_qpOASES, + int_init, int_initSB, int_initVM, + int_hotstart, int_hotstartSB, int_hotstartVM, + int_cleanup, int_cleanupSB, int_cleanupVM + }; + char* name[] = { "qpOASES", + "qpOASES_init", "qpOASES_initSB", "qpOASES_initVM", + "qpOASES_hotstart", "qpOASES_hotstartSB", "qpOASES_hotstartVM", + "qpOASES_cleanup", "qpOASES_cleanupSB", "qpOASES_cleanupVM" + }; + + Rhs = Max( 0,Rhs ); + sci_gateway( name[Fin-1],function[Fin-1] ); + + return 0; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESinterface.sce b/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESinterface.sce new file mode 100644 index 00000000000..bbe36140e74 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESinterface.sce @@ -0,0 +1,41 @@ +// +// This file is part of qpOASES. +// +// qpOASES -- An Implementation of the Online Active Set Strategy. +// Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +// Christian Kirches et al. All rights reserved. +// +// qpOASES is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// qpOASES is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with qpOASES; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + + + +// +// Filename: interfaces/scilab/qpOASESinterface.sci +// Author: Holger Diedam, Hans Joachim Ferreau +// Version: 3.0 +// Date: 2007-2014 +// + + + +sharedlib = link( './libqpOASESinterface.so' ); +addinter( './libqpOASESinterface.so', 'qpOASESgateway', ["qpOASES","qpOASES_init","qpOASES_initSB","qpOASES_initVM","qpOASES_hotstart","qpOASES_hotstartSB","qpOASES_hotstartVM","qpOASES_cleanup","qpOASES_cleanupSB","qpOASES_cleanupVM"] ); + + + +// +// end of file +// diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESroutines.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESroutines.cpp new file mode 100644 index 00000000000..d84c2e1dd01 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/scilab/qpOASESroutines.cpp @@ -0,0 +1,365 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/scilab/qpOASESroutines.cpp + * \author Holger Diedam, Hans Joachim Ferreau + * \version 3.0 + * \date 2007-2014 + * + * Interface that enables to call qpOASES from scilab + * (C++ file to provide an interface between the files that + * have to be compiled with gcc and the qpOASES library). + * + */ + + +#include + +#include + + +USING_NAMESPACE_QPOASES + +/* global pointers to qpOASES objects */ +static QProblem* qp = 0; +static QProblemB* qpb = 0; +static SQProblem* sqp = 0; + + +extern "C" +{ + void qpoases( real_t* H, real_t* g, real_t* A, real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int *nV, int* nC, int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ); + + void init( real_t* H, real_t* g, real_t* A, real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int* nV, int* nC, int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ); + void initSB( real_t* H, real_t* g, real_t* lb, real_t* ub, + int* nV, int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ); + void initVM( real_t* H, real_t* g, real_t* A, real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int* nV, int* nC, int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ); + + void hotstart( real_t* g, real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ); + void hotstartSB( real_t* g, real_t* lb, real_t* ub, + int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ); + void hotstartVM( real_t* H, real_t* g, real_t* A, real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ); + + void cleanupp( ); + void cleanupSB( ); + void cleanupVM( ); +} /* extern "C" */ + + + +/* + * t r a n s f o r m A + */ +void transformA( real_t* A, int nV, int nC ) +{ + int i, j; + + real_t* A_tmp = new real_t[nC*nV]; + + for( i=0; isetPrintLevel( PL_LOW ); + returnValue returnvalue = qp->init( H,g,A,lb,ub,lbA,ubA, *nWSR,0 ); + + /* assign lhs arguments */ + qp->getPrimalSolution( x ); + *obj = qp->getObjVal( ); + *status = getSimpleStatus( returnvalue ); + *nWSRout = *nWSR; + qp->getDualSolution( y ); + + return; +} + + +/* + * i n i t S B + */ +void initSB( real_t* H, real_t* g, real_t* lb, real_t* ub, + int* nV, int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ) +{ + cleanupSB( ); + + /* setup and solve initial QP */ + qpb = new QProblemB( *nV ); + qpb->setPrintLevel( PL_LOW ); + returnValue returnvalue = qpb->init( H,g,lb,ub, *nWSR,0 ); + + /* assign lhs arguments */ + qpb->getPrimalSolution( x ); + *obj = qpb->getObjVal( ); + *status = getSimpleStatus( returnvalue ); + *nWSRout = *nWSR; + qpb->getDualSolution( y ); + + return; +} + + +/* + * i n i t V M + */ +void initVM( real_t* H, real_t* g, real_t* A, real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int* nV, int* nC, int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ) +{ + cleanupVM( ); + + /* transform A into C style matrix */ + transformA( A, *nV,*nC ); + + /* setup and solve initial QP */ + sqp = new SQProblem( *nV,*nC ); + sqp->setPrintLevel( PL_LOW ); + returnValue returnvalue = sqp->init( H,g,A,lb,ub,lbA,ubA, *nWSR,0 ); + + /* assign lhs arguments */ + sqp->getPrimalSolution( x ); + *obj = sqp->getObjVal( ); + *status = getSimpleStatus( returnvalue ); + *nWSRout = *nWSR; + sqp->getDualSolution( y ); + + return; +} + + +/* + * h o t s t a r t + */ +void hotstart( real_t* g, real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ) +{ + /* has QP been initialised? */ + if ( qp == 0 ) + { + *status = -1; + Scierror( 999,"ERROR (qpOASES): Need to call qpOASES_init first!\n" ); + return; + } + + /* solve QP */ + returnValue returnvalue = qp->hotstart( g,lb,ub,lbA,ubA, *nWSR,0 ); + + /* assign lhs arguments */ + qp->getPrimalSolution( x ); + *obj = qp->getObjVal( ); + *status = getSimpleStatus( returnvalue ); + *nWSRout = *nWSR; + qp->getDualSolution( y ); + + return; +} + + +/* + * h o t s t a r t S B + */ +void hotstartSB( real_t* g, real_t* lb, real_t* ub, + int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ) +{ + /* has QP been initialised? */ + if ( qpb == 0 ) + { + *status = -1; + Scierror( 999,"ERROR (qpOASES): Need to call qpOASES_init first!\n" ); + return; + } + + /* solve QP */ + returnValue returnvalue = qpb->hotstart( g,lb,ub, *nWSR,0 ); + + /* assign lhs arguments */ + qpb->getPrimalSolution( x ); + *obj = qpb->getObjVal( ); + *status = getSimpleStatus( returnvalue ); + *nWSRout = *nWSR; + qpb->getDualSolution( y ); + + return; +} + + +/* + * h o t s t a r t V M + */ +void hotstartVM( real_t* H, real_t* g, real_t* A, real_t* lb, real_t* ub, real_t* lbA, real_t* ubA, + int* nWSR, + real_t* x, real_t* obj, int* status, int* nWSRout, real_t* y + ) +{ + /* has QP been initialised? */ + if ( sqp == 0 ) + { + *status = -1; + Scierror( 999,"ERROR (qpOASES): Need to call qpOASES_init first!\n" ); + return; + } + + /* transform A into C style matrix */ + transformA( A, sqp->getNV( ),sqp->getNC( ) ); + + /* solve QP */ + returnValue returnvalue = sqp->hotstart( H,g,A,lb,ub,lbA,ubA, *nWSR,0 ); + + /* assign lhs arguments */ + sqp->getPrimalSolution( x ); + *obj = sqp->getObjVal( ); + *status = getSimpleStatus( returnvalue ); + *nWSRout = *nWSR; + sqp->getDualSolution( y ); + + return; +} + + +/* + * c l e a n u p p + */ +void cleanupp( ) +{ + /* Remark: A function cleanup already exists! */ + if ( qp != 0 ) + { + delete qp; + qp = 0; + } + + return; +} + + +/* + * c l e a n u p S B + */ +void cleanupSB( ) +{ + if ( qpb != 0 ) + { + delete qpb; + qpb = 0; + } + + return; +} + + +/* + * c l e a n u p V M + */ +void cleanupVM( ) +{ + if ( sqp != 0 ) + { + delete sqp; + sqp = 0; + } + + return; +} + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_QProblem.mdl b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_QProblem.mdl new file mode 100644 index 00000000000..6b284674b4d --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_QProblem.mdl @@ -0,0 +1,803 @@ +Model { + Name "example_QProblem" + Version 7.4 + MdlSubVersion 0 + GraphicalInterface { + NumRootInports 0 + NumRootOutports 0 + ParameterArgumentNames "" + ComputedModelVersion "1.65" + NumModelReferences 0 + NumTestPointedSignals 0 + } + SavedCharacterEncoding "UTF-8" + SaveDefaultBlockParams on + ScopeRefreshTime 0.035000 + OverrideScopeRefreshTime on + DisableAllScopes off + DataTypeOverride "UseLocalSettings" + MinMaxOverflowLogging "UseLocalSettings" + MinMaxOverflowArchiveMode "Overwrite" + MaxMDLFileLineLength 120 + Created "Fri Apr 13 11:08:51 2007" + Creator "jferreau" + UpdateHistory "UpdateHistoryNever" + ModifiedByFormat "%" + LastModifiedBy "chjofer2" + ModifiedDateFormat "%" + LastModifiedDate "Thu Feb 20 15:11:24 2014" + RTWModifiedTimeStamp 314809883 + ModelVersionFormat "1.%" + ConfigurationManager "None" + SampleTimeColors off + SampleTimeAnnotations off + LibraryLinkDisplay "none" + WideLines off + ShowLineDimensions off + ShowPortDataTypes off + ShowLoopsOnError on + IgnoreBidirectionalLines off + ShowStorageClass off + ShowTestPointIcons on + ShowSignalResolutionIcons on + ShowViewerIcons on + SortedOrder off + ExecutionContextIcon off + ShowLinearizationAnnotations on + BlockNameDataTip off + BlockParametersDataTip off + BlockDescriptionStringDataTip off + ToolBar on + StatusBar on + BrowserShowLibraryLinks off + BrowserLookUnderMasks off + SimulationMode "normal" + LinearizationMsg "none" + Profile off + ParamWorkspaceSource "MATLABWorkspace" + AccelSystemTargetFile "accel.tlc" + AccelTemplateMakefile "accel_default_tmf" + AccelMakeCommand "make_rtw" + TryForcingSFcnDF off + RecordCoverage off + CovPath "/" + CovSaveName "covdata" + CovMetricSettings "dw" + CovNameIncrementing off + CovHtmlReporting on + CovForceBlockReductionOff on + covSaveCumulativeToWorkspaceVar on + CovSaveSingleToWorkspaceVar on + CovCumulativeVarName "covCumulativeData" + CovCumulativeReport off + CovReportOnPause on + CovModelRefEnable "Off" + CovExternalEMLEnable off + ExtModeBatchMode off + ExtModeEnableFloating on + ExtModeTrigType "manual" + ExtModeTrigMode "normal" + ExtModeTrigPort "1" + ExtModeTrigElement "any" + ExtModeTrigDuration 1000 + ExtModeTrigDurationFloating "auto" + ExtModeTrigHoldOff 0 + ExtModeTrigDelay 0 + ExtModeTrigDirection "rising" + ExtModeTrigLevel 0 + ExtModeArchiveMode "off" + ExtModeAutoIncOneShot off + ExtModeIncDirWhenArm off + ExtModeAddSuffixToVar off + ExtModeWriteAllDataToWs off + ExtModeArmWhenConnect on + ExtModeSkipDownloadWhenConnect off + ExtModeLogAll on + ExtModeAutoUpdateStatusClock off + BufferReuse on + ShowModelReferenceBlockVersion off + ShowModelReferenceBlockIO off + Array { + Type "Handle" + Dimension 1 + Simulink.ConfigSet { + $ObjectID 1 + Version "1.6.0" + Array { + Type "Handle" + Dimension 8 + Simulink.SolverCC { + $ObjectID 2 + Version "1.6.0" + StartTime "0.0" + StopTime "0.5" + AbsTol "auto" + FixedStep "auto" + InitialStep "auto" + MaxNumMinSteps "-1" + MaxOrder 5 + ZcThreshold "auto" + ConsecutiveZCsStepRelTol "10*128*eps" + MaxConsecutiveZCs "1000" + ExtrapolationOrder 4 + NumberNewtonIterations 1 + MaxStep "auto" + MinStep "auto" + MaxConsecutiveMinStep "1" + RelTol "1e-3" + SolverMode "Auto" + Solver "FixedStepDiscrete" + SolverName "FixedStepDiscrete" + ShapePreserveControl "DisableAll" + ZeroCrossControl "UseLocalSettings" + ZeroCrossAlgorithm "Nonadaptive" + AlgebraicLoopSolver "TrustRegion" + SolverResetMethod "Fast" + PositivePriorityOrder off + AutoInsertRateTranBlk off + SampleTimeConstraint "Unconstrained" + InsertRTBMode "Whenever possible" + } + Simulink.DataIOCC { + $ObjectID 3 + Version "1.6.0" + Decimation "1" + ExternalInput "[t, u]" + FinalStateName "xFinal" + InitialState "xInitial" + LimitDataPoints on + MaxDataPoints "1000" + LoadExternalInput off + LoadInitialState off + SaveFinalState off + SaveCompleteFinalSimState off + SaveFormat "Array" + SaveOutput on + SaveState off + SignalLogging on + InspectSignalLogs off + SaveTime on + ReturnWorkspaceOutputs off + StateSaveName "xout" + TimeSaveName "tout" + OutputSaveName "yout" + SignalLoggingName "logsout" + OutputOption "RefineOutputTimes" + OutputTimes "[]" + ReturnWorkspaceOutputsName "out" + Refine "1" + } + Simulink.OptimizationCC { + $ObjectID 4 + Version "1.6.0" + Array { + Type "Cell" + Dimension 4 + Cell "ZeroExternalMemoryAtStartup" + Cell "ZeroInternalMemoryAtStartup" + Cell "NoFixptDivByZeroProtection" + Cell "OptimizeModelRefInitCode" + PropName "DisabledProps" + } + BlockReduction on + BooleanDataType on + ConditionallyExecuteInputs on + InlineParams off + UseIntDivNetSlope off + InlineInvariantSignals off + OptimizeBlockIOStorage on + BufferReuse on + EnhancedBackFolding off + StrengthReduction off + EnforceIntegerDowncast on + ExpressionFolding on + BooleansAsBitfields off + EnableMemcpy on + MemcpyThreshold 64 + PassReuseOutputArgsAs "Structure reference" + ExpressionDepthLimit 2147483647 + FoldNonRolledExpr on + LocalBlockOutputs on + RollThreshold 5 + SystemCodeInlineAuto off + StateBitsets off + DataBitsets off + UseTempVars off + ZeroExternalMemoryAtStartup on + ZeroInternalMemoryAtStartup on + InitFltsAndDblsToZero on + NoFixptDivByZeroProtection off + EfficientFloat2IntCast off + EfficientMapNaN2IntZero on + OptimizeModelRefInitCode off + LifeSpan "inf" + BufferReusableBoundary on + SimCompilerOptimization "Off" + AccelVerboseBuild off + } + Simulink.DebuggingCC { + $ObjectID 5 + Version "1.6.0" + RTPrefix "error" + ConsistencyChecking "none" + ArrayBoundsChecking "none" + SignalInfNanChecking "none" + SignalRangeChecking "none" + ReadBeforeWriteMsg "UseLocalSettings" + WriteAfterWriteMsg "UseLocalSettings" + WriteAfterReadMsg "UseLocalSettings" + AlgebraicLoopMsg "warning" + ArtificialAlgebraicLoopMsg "warning" + SaveWithDisabledLinksMsg "warning" + SaveWithParameterizedLinksMsg "none" + CheckSSInitialOutputMsg on + UnderspecifiedInitializationDetection "Classic" + MergeDetectMultiDrivingBlocksExec "none" + CheckExecutionContextPreStartOutputMsg off + CheckExecutionContextRuntimeOutputMsg off + SignalResolutionControl "TryResolveAllWithWarning" + BlockPriorityViolationMsg "warning" + MinStepSizeMsg "warning" + TimeAdjustmentMsg "none" + MaxConsecutiveZCsMsg "error" + SolverPrmCheckMsg "warning" + InheritedTsInSrcMsg "warning" + DiscreteInheritContinuousMsg "warning" + MultiTaskDSMMsg "error" + MultiTaskCondExecSysMsg "error" + MultiTaskRateTransMsg "error" + SingleTaskRateTransMsg "none" + TasksWithSamePriorityMsg "warning" + SigSpecEnsureSampleTimeMsg "warning" + CheckMatrixSingularityMsg "none" + IntegerOverflowMsg "warning" + Int32ToFloatConvMsg "warning" + ParameterDowncastMsg "error" + ParameterOverflowMsg "error" + ParameterUnderflowMsg "none" + ParameterPrecisionLossMsg "warning" + ParameterTunabilityLossMsg "warning" + FixptConstUnderflowMsg "none" + FixptConstOverflowMsg "none" + FixptConstPrecisionLossMsg "none" + UnderSpecifiedDataTypeMsg "none" + UnnecessaryDatatypeConvMsg "none" + VectorMatrixConversionMsg "none" + InvalidFcnCallConnMsg "error" + FcnCallInpInsideContextMsg "Use local settings" + SignalLabelMismatchMsg "none" + UnconnectedInputMsg "warning" + UnconnectedOutputMsg "warning" + UnconnectedLineMsg "warning" + SFcnCompatibilityMsg "none" + UniqueDataStoreMsg "none" + BusObjectLabelMismatch "warning" + RootOutportRequireBusObject "warning" + AssertControl "UseLocalSettings" + EnableOverflowDetection off + ModelReferenceIOMsg "none" + ModelReferenceVersionMismatchMessage "none" + ModelReferenceIOMismatchMessage "none" + ModelReferenceCSMismatchMessage "none" + UnknownTsInhSupMsg "warning" + ModelReferenceDataLoggingMessage "warning" + ModelReferenceSymbolNameMessage "warning" + ModelReferenceExtraNoncontSigs "error" + StateNameClashWarn "warning" + SimStateInterfaceChecksumMismatchMsg "warning" + StrictBusMsg "Warning" + LoggingUnavailableSignals "error" + BlockIODiagnostic "none" + } + Simulink.HardwareCC { + $ObjectID 6 + Version "1.6.0" + ProdBitPerChar 8 + ProdBitPerShort 16 + ProdBitPerInt 32 + ProdBitPerLong 32 + ProdIntDivRoundTo "Undefined" + ProdEndianess "Unspecified" + ProdWordSize 32 + ProdShiftRightIntArith on + ProdHWDeviceType "32-bit Generic" + TargetBitPerChar 8 + TargetBitPerShort 16 + TargetBitPerInt 32 + TargetBitPerLong 32 + TargetShiftRightIntArith on + TargetIntDivRoundTo "Undefined" + TargetEndianess "Unspecified" + TargetWordSize 32 + TargetTypeEmulationWarnSuppressLevel 0 + TargetPreprocMaxBitsSint 32 + TargetPreprocMaxBitsUint 32 + TargetHWDeviceType "Specified" + TargetUnknown off + ProdEqTarget on + } + Simulink.ModelReferenceCC { + $ObjectID 7 + Version "1.6.0" + UpdateModelReferenceTargets "IfOutOfDateOrStructuralChange" + CheckModelReferenceTargetMessage "error" + ModelReferenceNumInstancesAllowed "Multi" + ModelReferencePassRootInputsByReference on + ModelReferenceMinAlgLoopOccurrences off + } + Simulink.SFSimCC { + $ObjectID 8 + Version "1.6.0" + SFSimEnableDebug on + SFSimOverflowDetection on + SFSimEcho on + SimBlas on + SimCtrlC on + SimExtrinsic on + SimIntegrity on + SimUseLocalCustomCode off + SimBuildMode "sf_incremental_build" + } + Simulink.RTWCC { + $BackupClass "Simulink.RTWCC" + $ObjectID 9 + Version "1.6.0" + Array { + Type "Cell" + Dimension 1 + Cell "IncludeHyperlinkInReport" + PropName "DisabledProps" + } + SystemTargetFile "grt.tlc" + GenCodeOnly off + MakeCommand "make_rtw" + GenerateMakefile on + TemplateMakefile "grt_default_tmf" + GenerateReport off + SaveLog off + RTWVerbose on + RetainRTWFile off + ProfileTLC off + TLCDebug off + TLCCoverage off + TLCAssert off + ProcessScriptMode "Default" + ConfigurationMode "Optimized" + ConfigAtBuild off + RTWUseLocalCustomCode off + RTWUseSimCustomCode off + IncludeHyperlinkInReport off + LaunchReport off + TargetLang "C" + IncludeBusHierarchyInRTWFileBlockHierarchyMap off + IncludeERTFirstTime off + GenerateTraceInfo off + GenerateTraceReport off + GenerateTraceReportSl off + GenerateTraceReportSf off + GenerateTraceReportEml off + GenerateCodeInfo off + RTWCompilerOptimization "Off" + CheckMdlBeforeBuild "Off" + Array { + Type "Handle" + Dimension 2 + Simulink.CodeAppCC { + $ObjectID 10 + Version "1.6.0" + Array { + Type "Cell" + Dimension 16 + Cell "IgnoreCustomStorageClasses" + Cell "InsertBlockDesc" + Cell "SFDataObjDesc" + Cell "SimulinkDataObjDesc" + Cell "DefineNamingRule" + Cell "SignalNamingRule" + Cell "ParamNamingRule" + Cell "InlinedPrmAccess" + Cell "CustomSymbolStr" + Cell "CustomSymbolStrGlobalVar" + Cell "CustomSymbolStrType" + Cell "CustomSymbolStrField" + Cell "CustomSymbolStrFcn" + Cell "CustomSymbolStrBlkIO" + Cell "CustomSymbolStrTmpVar" + Cell "CustomSymbolStrMacro" + PropName "DisabledProps" + } + ForceParamTrailComments off + GenerateComments on + IgnoreCustomStorageClasses on + IgnoreTestpoints off + IncHierarchyInIds off + MaxIdLength 31 + PreserveName off + PreserveNameWithParent off + ShowEliminatedStatement off + IncAutoGenComments off + SimulinkDataObjDesc off + SFDataObjDesc off + IncDataTypeInIds off + MangleLength 1 + CustomSymbolStrGlobalVar "$R$N$M" + CustomSymbolStrType "$N$R$M" + CustomSymbolStrField "$N$M" + CustomSymbolStrFcn "$R$N$M$F" + CustomSymbolStrFcnArg "rt$I$N$M" + CustomSymbolStrBlkIO "rtb_$N$M" + CustomSymbolStrTmpVar "$N$M" + CustomSymbolStrMacro "$R$N$M" + DefineNamingRule "None" + ParamNamingRule "None" + SignalNamingRule "None" + InsertBlockDesc off + SimulinkBlockComments on + EnableCustomComments off + InlinedPrmAccess "Literals" + ReqsInCode off + UseSimReservedNames off + } + Simulink.GRTTargetCC { + $BackupClass "Simulink.TargetCC" + $ObjectID 11 + Version "1.6.0" + Array { + Type "Cell" + Dimension 13 + Cell "IncludeMdlTerminateFcn" + Cell "CombineOutputUpdateFcns" + Cell "SuppressErrorStatus" + Cell "ERTCustomFileBanners" + Cell "GenerateSampleERTMain" + Cell "GenerateTestInterfaces" + Cell "MultiInstanceERTCode" + Cell "PurelyIntegerCode" + Cell "SupportNonFinite" + Cell "SupportComplex" + Cell "SupportAbsoluteTime" + Cell "SupportContinuousTime" + Cell "SupportNonInlinedSFcns" + PropName "DisabledProps" + } + TargetFcnLib "ansi_tfl_tmw.mat" + TargetLibSuffix "" + TargetPreCompLibLocation "" + TargetFunctionLibrary "ANSI_C" + UtilityFuncGeneration "Auto" + ERTMultiwordTypeDef "System defined" + ERTMultiwordLength 256 + MultiwordLength 2048 + GenerateFullHeader on + GenerateSampleERTMain off + GenerateTestInterfaces off + IsPILTarget off + ModelReferenceCompliant on + ParMdlRefBuildCompliant on + CompOptLevelCompliant on + IncludeMdlTerminateFcn on + GeneratePreprocessorConditionals "Disable all" + CombineOutputUpdateFcns off + SuppressErrorStatus off + ERTFirstTimeCompliant off + IncludeFileDelimiter "Auto" + ERTCustomFileBanners off + SupportAbsoluteTime on + LogVarNameModifier "rt_" + MatFileLogging on + MultiInstanceERTCode off + SupportNonFinite on + SupportComplex on + PurelyIntegerCode off + SupportContinuousTime on + SupportNonInlinedSFcns on + SupportVariableSizeSignals off + EnableShiftOperators on + ParenthesesLevel "Nominal" + PortableWordSizes off + ModelStepFunctionPrototypeControlCompliant off + CPPClassGenCompliant off + AutosarCompliant off + UseMalloc off + ExtMode off + ExtModeStaticAlloc off + ExtModeTesting off + ExtModeStaticAllocSize 1000000 + ExtModeTransport 0 + ExtModeMexFile "ext_comm" + ExtModeIntrfLevel "Level1" + RTWCAPISignals off + RTWCAPIParams off + RTWCAPIStates off + GenerateASAP2 off + } + PropName "Components" + } + } + PropName "Components" + } + Name "Configuration" + CurrentDlgPage "Solver" + ConfigPrmDlgPosition " [ 200, 197, 1080, 827 ] " + } + PropName "ConfigurationSets" + } + Simulink.ConfigSet { + $PropName "ActiveConfigurationSet" + $ObjectID 1 + } + BlockDefaults { + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + NamePlacement "normal" + FontName "Courier" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + ShowName on + BlockRotation 0 + BlockMirror off + } + AnnotationDefaults { + HorizontalAlignment "center" + VerticalAlignment "middle" + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + FontName "Courier" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + UseDisplayTextAsClickCallback off + } + LineDefaults { + FontName "Courier" + FontSize 9 + FontWeight "normal" + FontAngle "normal" + } + BlockParameterDefaults { + Block { + BlockType FromWorkspace + VariableName "simulink_input" + SampleTime "-1" + Interpolate on + ZeroCross off + OutputAfterFinalValue "Extrapolation" + } + Block { + BlockType "S-Function" + FunctionName "system" + SFunctionModules "''" + PortCounts "[]" + SFunctionDeploymentMode off + } + Block { + BlockType Scope + ModelBased off + TickLabels "OneTimeTick" + ZoomMode "on" + Grid "on" + TimeRange "auto" + YMin "-5" + YMax "5" + SaveToWorkspace off + SaveName "ScopeData" + LimitDataPoints on + MaxDataPoints "5000" + Decimation "1" + SampleInput off + SampleTime "-1" + } + } + System { + Name "example_QProblem" + Location [2, 82, 1918, 1147] + Open on + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "125" + ReportName "simulink-default.rpt" + SIDHighWatermark 9 + Block { + BlockType FromWorkspace + Name "From\nWorkspace1" + SID 1 + Position [85, 53, 150, 77] + VariableName "H" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace2" + SID 2 + Position [85, 113, 150, 137] + VariableName "g" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace3" + SID 3 + Position [85, 173, 150, 197] + VariableName "A" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace4" + SID 4 + Position [85, 233, 150, 257] + VariableName "lb" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace5" + SID 5 + Position [85, 293, 150, 317] + VariableName "ub" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace6" + SID 6 + Position [85, 353, 150, 377] + VariableName "lbA" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace7" + SID 7 + Position [85, 418, 150, 442] + VariableName "ubA" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType Scope + Name "fval,\nx,\nexitflag,\niter" + SID 8 + Ports [4] + Position [915, 229, 945, 261] + Floating off + Location [6, 78, 1276, 993] + Open off + NumInputPorts "4" + List { + ListType AxesTitles + axes1 "%" + axes2 "%" + axes3 "%" + axes4 "%" + } + YMin "-5~-5~-5~-5" + YMax "5~5~5~5" + SaveName "ScopeData1" + DataFormat "StructureWithTime" + SampleTime "0" + } + Block { + BlockType "S-Function" + Name "qpOASES" + SID 9 + Ports [7, 4] + Position [595, 226, 790, 264] + BackgroundColor "[1.000000, 0.915850, 0.439000]" + FunctionName "qpOASES_QProblem" + EnableBusSupport off + MaskHelp "file://../../DOC/manual.pdf" + MaskIconFrame on + MaskIconOpaque on + MaskIconRotate "none" + MaskPortRotate "default" + MaskIconUnits "autoscale" + } + Line { + SrcBlock "From\nWorkspace1" + SrcPort 1 + Points [180, 0; 0, 165] + DstBlock "qpOASES" + DstPort 1 + } + Line { + SrcBlock "From\nWorkspace2" + SrcPort 1 + Points [115, 0; 0, 110] + DstBlock "qpOASES" + DstPort 2 + } + Line { + Labels [3, 0] + SrcBlock "From\nWorkspace7" + SrcPort 1 + Points [180, 0; 0, -170] + DstBlock "qpOASES" + DstPort 7 + } + Line { + SrcBlock "From\nWorkspace5" + SrcPort 1 + Points [55, 0; 0, -55] + DstBlock "qpOASES" + DstPort 5 + } + Line { + SrcBlock "From\nWorkspace4" + SrcPort 1 + DstBlock "qpOASES" + DstPort 4 + } + Line { + SrcBlock "From\nWorkspace3" + SrcPort 1 + Points [55, 0; 0, 55] + DstBlock "qpOASES" + DstPort 3 + } + Line { + Labels [3, 0] + SrcBlock "From\nWorkspace6" + SrcPort 1 + Points [115, 0; 0, -110] + DstBlock "qpOASES" + DstPort 6 + } + Line { + SrcBlock "qpOASES" + SrcPort 1 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 1 + } + Line { + SrcBlock "qpOASES" + SrcPort 2 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 2 + } + Line { + SrcBlock "qpOASES" + SrcPort 3 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 3 + } + Line { + SrcBlock "qpOASES" + SrcPort 4 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 4 + } + Annotation { + Position [335, 96] + } + Annotation { + Name "This file is part of qpOASES.\n\nqpOASES -- An Implementation of the Online Active Set Strategy.\nC" + "opyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, Christian Kirches et al.\nAll rights reserved." + Position [693, 128] + } + } +} diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_QProblemB.mdl b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_QProblemB.mdl new file mode 100644 index 00000000000..e86ed8e85aa --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_QProblemB.mdl @@ -0,0 +1,745 @@ +Model { + Name "example_QProblemB" + Version 7.4 + MdlSubVersion 0 + GraphicalInterface { + NumRootInports 0 + NumRootOutports 0 + ParameterArgumentNames "" + ComputedModelVersion "1.64" + NumModelReferences 0 + NumTestPointedSignals 0 + } + SavedCharacterEncoding "UTF-8" + SaveDefaultBlockParams on + ScopeRefreshTime 0.035000 + OverrideScopeRefreshTime on + DisableAllScopes off + DataTypeOverride "UseLocalSettings" + MinMaxOverflowLogging "UseLocalSettings" + MinMaxOverflowArchiveMode "Overwrite" + MaxMDLFileLineLength 120 + Created "Fri Apr 13 11:08:51 2007" + Creator "jferreau" + UpdateHistory "UpdateHistoryNever" + ModifiedByFormat "%" + LastModifiedBy "chjofer2" + ModifiedDateFormat "%" + LastModifiedDate "Thu Feb 20 15:12:19 2014" + RTWModifiedTimeStamp 314809937 + ModelVersionFormat "1.%" + ConfigurationManager "None" + SampleTimeColors off + SampleTimeAnnotations off + LibraryLinkDisplay "none" + WideLines off + ShowLineDimensions off + ShowPortDataTypes off + ShowLoopsOnError on + IgnoreBidirectionalLines off + ShowStorageClass off + ShowTestPointIcons on + ShowSignalResolutionIcons on + ShowViewerIcons on + SortedOrder off + ExecutionContextIcon off + ShowLinearizationAnnotations on + BlockNameDataTip off + BlockParametersDataTip off + BlockDescriptionStringDataTip off + ToolBar on + StatusBar on + BrowserShowLibraryLinks off + BrowserLookUnderMasks off + SimulationMode "normal" + LinearizationMsg "none" + Profile off + ParamWorkspaceSource "MATLABWorkspace" + AccelSystemTargetFile "accel.tlc" + AccelTemplateMakefile "accel_default_tmf" + AccelMakeCommand "make_rtw" + TryForcingSFcnDF off + RecordCoverage off + CovPath "/" + CovSaveName "covdata" + CovMetricSettings "dw" + CovNameIncrementing off + CovHtmlReporting on + CovForceBlockReductionOff on + covSaveCumulativeToWorkspaceVar on + CovSaveSingleToWorkspaceVar on + CovCumulativeVarName "covCumulativeData" + CovCumulativeReport off + CovReportOnPause on + CovModelRefEnable "Off" + CovExternalEMLEnable off + ExtModeBatchMode off + ExtModeEnableFloating on + ExtModeTrigType "manual" + ExtModeTrigMode "normal" + ExtModeTrigPort "1" + ExtModeTrigElement "any" + ExtModeTrigDuration 1000 + ExtModeTrigDurationFloating "auto" + ExtModeTrigHoldOff 0 + ExtModeTrigDelay 0 + ExtModeTrigDirection "rising" + ExtModeTrigLevel 0 + ExtModeArchiveMode "off" + ExtModeAutoIncOneShot off + ExtModeIncDirWhenArm off + ExtModeAddSuffixToVar off + ExtModeWriteAllDataToWs off + ExtModeArmWhenConnect on + ExtModeSkipDownloadWhenConnect off + ExtModeLogAll on + ExtModeAutoUpdateStatusClock off + BufferReuse on + ShowModelReferenceBlockVersion off + ShowModelReferenceBlockIO off + Array { + Type "Handle" + Dimension 1 + Simulink.ConfigSet { + $ObjectID 1 + Version "1.6.0" + Array { + Type "Handle" + Dimension 8 + Simulink.SolverCC { + $ObjectID 2 + Version "1.6.0" + StartTime "0.0" + StopTime "0.5" + AbsTol "auto" + FixedStep "auto" + InitialStep "auto" + MaxNumMinSteps "-1" + MaxOrder 5 + ZcThreshold "auto" + ConsecutiveZCsStepRelTol "10*128*eps" + MaxConsecutiveZCs "1000" + ExtrapolationOrder 4 + NumberNewtonIterations 1 + MaxStep "auto" + MinStep "auto" + MaxConsecutiveMinStep "1" + RelTol "1e-3" + SolverMode "Auto" + Solver "VariableStepDiscrete" + SolverName "VariableStepDiscrete" + ShapePreserveControl "DisableAll" + ZeroCrossControl "UseLocalSettings" + ZeroCrossAlgorithm "Nonadaptive" + AlgebraicLoopSolver "TrustRegion" + SolverResetMethod "Fast" + PositivePriorityOrder off + AutoInsertRateTranBlk off + SampleTimeConstraint "Unconstrained" + InsertRTBMode "Whenever possible" + } + Simulink.DataIOCC { + $ObjectID 3 + Version "1.6.0" + Decimation "1" + ExternalInput "[t, u]" + FinalStateName "xFinal" + InitialState "xInitial" + LimitDataPoints on + MaxDataPoints "1000" + LoadExternalInput off + LoadInitialState off + SaveFinalState off + SaveCompleteFinalSimState off + SaveFormat "Array" + SaveOutput on + SaveState off + SignalLogging on + InspectSignalLogs off + SaveTime on + ReturnWorkspaceOutputs off + StateSaveName "xout" + TimeSaveName "tout" + OutputSaveName "yout" + SignalLoggingName "logsout" + OutputOption "RefineOutputTimes" + OutputTimes "[]" + ReturnWorkspaceOutputsName "out" + Refine "1" + } + Simulink.OptimizationCC { + $ObjectID 4 + Version "1.6.0" + Array { + Type "Cell" + Dimension 4 + Cell "ZeroExternalMemoryAtStartup" + Cell "ZeroInternalMemoryAtStartup" + Cell "NoFixptDivByZeroProtection" + Cell "OptimizeModelRefInitCode" + PropName "DisabledProps" + } + BlockReduction on + BooleanDataType on + ConditionallyExecuteInputs on + InlineParams off + UseIntDivNetSlope off + InlineInvariantSignals off + OptimizeBlockIOStorage on + BufferReuse on + EnhancedBackFolding off + StrengthReduction off + EnforceIntegerDowncast on + ExpressionFolding on + BooleansAsBitfields off + EnableMemcpy on + MemcpyThreshold 64 + PassReuseOutputArgsAs "Structure reference" + ExpressionDepthLimit 2147483647 + FoldNonRolledExpr on + LocalBlockOutputs on + RollThreshold 5 + SystemCodeInlineAuto off + StateBitsets off + DataBitsets off + UseTempVars off + ZeroExternalMemoryAtStartup on + ZeroInternalMemoryAtStartup on + InitFltsAndDblsToZero on + NoFixptDivByZeroProtection off + EfficientFloat2IntCast off + EfficientMapNaN2IntZero on + OptimizeModelRefInitCode off + LifeSpan "inf" + BufferReusableBoundary on + SimCompilerOptimization "Off" + AccelVerboseBuild off + } + Simulink.DebuggingCC { + $ObjectID 5 + Version "1.6.0" + RTPrefix "error" + ConsistencyChecking "none" + ArrayBoundsChecking "none" + SignalInfNanChecking "none" + SignalRangeChecking "none" + ReadBeforeWriteMsg "UseLocalSettings" + WriteAfterWriteMsg "UseLocalSettings" + WriteAfterReadMsg "UseLocalSettings" + AlgebraicLoopMsg "warning" + ArtificialAlgebraicLoopMsg "warning" + SaveWithDisabledLinksMsg "warning" + SaveWithParameterizedLinksMsg "none" + CheckSSInitialOutputMsg on + UnderspecifiedInitializationDetection "Classic" + MergeDetectMultiDrivingBlocksExec "none" + CheckExecutionContextPreStartOutputMsg off + CheckExecutionContextRuntimeOutputMsg off + SignalResolutionControl "TryResolveAllWithWarning" + BlockPriorityViolationMsg "warning" + MinStepSizeMsg "warning" + TimeAdjustmentMsg "none" + MaxConsecutiveZCsMsg "error" + SolverPrmCheckMsg "warning" + InheritedTsInSrcMsg "warning" + DiscreteInheritContinuousMsg "warning" + MultiTaskDSMMsg "error" + MultiTaskCondExecSysMsg "error" + MultiTaskRateTransMsg "error" + SingleTaskRateTransMsg "none" + TasksWithSamePriorityMsg "warning" + SigSpecEnsureSampleTimeMsg "warning" + CheckMatrixSingularityMsg "none" + IntegerOverflowMsg "warning" + Int32ToFloatConvMsg "warning" + ParameterDowncastMsg "error" + ParameterOverflowMsg "error" + ParameterUnderflowMsg "none" + ParameterPrecisionLossMsg "warning" + ParameterTunabilityLossMsg "warning" + FixptConstUnderflowMsg "none" + FixptConstOverflowMsg "none" + FixptConstPrecisionLossMsg "none" + UnderSpecifiedDataTypeMsg "none" + UnnecessaryDatatypeConvMsg "none" + VectorMatrixConversionMsg "none" + InvalidFcnCallConnMsg "error" + FcnCallInpInsideContextMsg "Use local settings" + SignalLabelMismatchMsg "none" + UnconnectedInputMsg "warning" + UnconnectedOutputMsg "warning" + UnconnectedLineMsg "warning" + SFcnCompatibilityMsg "none" + UniqueDataStoreMsg "none" + BusObjectLabelMismatch "warning" + RootOutportRequireBusObject "warning" + AssertControl "UseLocalSettings" + EnableOverflowDetection off + ModelReferenceIOMsg "none" + ModelReferenceVersionMismatchMessage "none" + ModelReferenceIOMismatchMessage "none" + ModelReferenceCSMismatchMessage "none" + UnknownTsInhSupMsg "warning" + ModelReferenceDataLoggingMessage "warning" + ModelReferenceSymbolNameMessage "warning" + ModelReferenceExtraNoncontSigs "error" + StateNameClashWarn "warning" + SimStateInterfaceChecksumMismatchMsg "warning" + StrictBusMsg "Warning" + LoggingUnavailableSignals "error" + BlockIODiagnostic "none" + } + Simulink.HardwareCC { + $ObjectID 6 + Version "1.6.0" + ProdBitPerChar 8 + ProdBitPerShort 16 + ProdBitPerInt 32 + ProdBitPerLong 32 + ProdIntDivRoundTo "Undefined" + ProdEndianess "Unspecified" + ProdWordSize 32 + ProdShiftRightIntArith on + ProdHWDeviceType "32-bit Generic" + TargetBitPerChar 8 + TargetBitPerShort 16 + TargetBitPerInt 32 + TargetBitPerLong 32 + TargetShiftRightIntArith on + TargetIntDivRoundTo "Undefined" + TargetEndianess "Unspecified" + TargetWordSize 32 + TargetTypeEmulationWarnSuppressLevel 0 + TargetPreprocMaxBitsSint 32 + TargetPreprocMaxBitsUint 32 + TargetHWDeviceType "Specified" + TargetUnknown off + ProdEqTarget on + } + Simulink.ModelReferenceCC { + $ObjectID 7 + Version "1.6.0" + UpdateModelReferenceTargets "IfOutOfDateOrStructuralChange" + CheckModelReferenceTargetMessage "error" + ModelReferenceNumInstancesAllowed "Multi" + ModelReferencePassRootInputsByReference on + ModelReferenceMinAlgLoopOccurrences off + } + Simulink.SFSimCC { + $ObjectID 8 + Version "1.6.0" + SFSimEnableDebug on + SFSimOverflowDetection on + SFSimEcho on + SimBlas on + SimCtrlC on + SimExtrinsic on + SimIntegrity on + SimUseLocalCustomCode off + SimBuildMode "sf_incremental_build" + } + Simulink.RTWCC { + $BackupClass "Simulink.RTWCC" + $ObjectID 9 + Version "1.6.0" + Array { + Type "Cell" + Dimension 1 + Cell "IncludeHyperlinkInReport" + PropName "DisabledProps" + } + SystemTargetFile "grt.tlc" + GenCodeOnly off + MakeCommand "make_rtw" + GenerateMakefile on + TemplateMakefile "grt_default_tmf" + GenerateReport off + SaveLog off + RTWVerbose on + RetainRTWFile off + ProfileTLC off + TLCDebug off + TLCCoverage off + TLCAssert off + ProcessScriptMode "Default" + ConfigurationMode "Optimized" + ConfigAtBuild off + RTWUseLocalCustomCode off + RTWUseSimCustomCode off + IncludeHyperlinkInReport off + LaunchReport off + TargetLang "C" + IncludeBusHierarchyInRTWFileBlockHierarchyMap off + IncludeERTFirstTime off + GenerateTraceInfo off + GenerateTraceReport off + GenerateTraceReportSl off + GenerateTraceReportSf off + GenerateTraceReportEml off + GenerateCodeInfo off + RTWCompilerOptimization "Off" + CheckMdlBeforeBuild "Off" + Array { + Type "Handle" + Dimension 2 + Simulink.CodeAppCC { + $ObjectID 10 + Version "1.6.0" + Array { + Type "Cell" + Dimension 16 + Cell "IgnoreCustomStorageClasses" + Cell "InsertBlockDesc" + Cell "SFDataObjDesc" + Cell "SimulinkDataObjDesc" + Cell "DefineNamingRule" + Cell "SignalNamingRule" + Cell "ParamNamingRule" + Cell "InlinedPrmAccess" + Cell "CustomSymbolStr" + Cell "CustomSymbolStrGlobalVar" + Cell "CustomSymbolStrType" + Cell "CustomSymbolStrField" + Cell "CustomSymbolStrFcn" + Cell "CustomSymbolStrBlkIO" + Cell "CustomSymbolStrTmpVar" + Cell "CustomSymbolStrMacro" + PropName "DisabledProps" + } + ForceParamTrailComments off + GenerateComments on + IgnoreCustomStorageClasses on + IgnoreTestpoints off + IncHierarchyInIds off + MaxIdLength 31 + PreserveName off + PreserveNameWithParent off + ShowEliminatedStatement off + IncAutoGenComments off + SimulinkDataObjDesc off + SFDataObjDesc off + IncDataTypeInIds off + MangleLength 1 + CustomSymbolStrGlobalVar "$R$N$M" + CustomSymbolStrType "$N$R$M" + CustomSymbolStrField "$N$M" + CustomSymbolStrFcn "$R$N$M$F" + CustomSymbolStrFcnArg "rt$I$N$M" + CustomSymbolStrBlkIO "rtb_$N$M" + CustomSymbolStrTmpVar "$N$M" + CustomSymbolStrMacro "$R$N$M" + DefineNamingRule "None" + ParamNamingRule "None" + SignalNamingRule "None" + InsertBlockDesc off + SimulinkBlockComments on + EnableCustomComments off + InlinedPrmAccess "Literals" + ReqsInCode off + UseSimReservedNames off + } + Simulink.GRTTargetCC { + $BackupClass "Simulink.TargetCC" + $ObjectID 11 + Version "1.6.0" + Array { + Type "Cell" + Dimension 13 + Cell "IncludeMdlTerminateFcn" + Cell "CombineOutputUpdateFcns" + Cell "SuppressErrorStatus" + Cell "ERTCustomFileBanners" + Cell "GenerateSampleERTMain" + Cell "GenerateTestInterfaces" + Cell "MultiInstanceERTCode" + Cell "PurelyIntegerCode" + Cell "SupportNonFinite" + Cell "SupportComplex" + Cell "SupportAbsoluteTime" + Cell "SupportContinuousTime" + Cell "SupportNonInlinedSFcns" + PropName "DisabledProps" + } + TargetFcnLib "ansi_tfl_tmw.mat" + TargetLibSuffix "" + TargetPreCompLibLocation "" + TargetFunctionLibrary "ANSI_C" + UtilityFuncGeneration "Auto" + ERTMultiwordTypeDef "System defined" + ERTMultiwordLength 256 + MultiwordLength 2048 + GenerateFullHeader on + GenerateSampleERTMain off + GenerateTestInterfaces off + IsPILTarget off + ModelReferenceCompliant on + ParMdlRefBuildCompliant on + CompOptLevelCompliant on + IncludeMdlTerminateFcn on + GeneratePreprocessorConditionals "Disable all" + CombineOutputUpdateFcns off + SuppressErrorStatus off + ERTFirstTimeCompliant off + IncludeFileDelimiter "Auto" + ERTCustomFileBanners off + SupportAbsoluteTime on + LogVarNameModifier "rt_" + MatFileLogging on + MultiInstanceERTCode off + SupportNonFinite on + SupportComplex on + PurelyIntegerCode off + SupportContinuousTime on + SupportNonInlinedSFcns on + SupportVariableSizeSignals off + EnableShiftOperators on + ParenthesesLevel "Nominal" + PortableWordSizes off + ModelStepFunctionPrototypeControlCompliant off + CPPClassGenCompliant off + AutosarCompliant off + UseMalloc off + ExtMode off + ExtModeStaticAlloc off + ExtModeTesting off + ExtModeStaticAllocSize 1000000 + ExtModeTransport 0 + ExtModeMexFile "ext_comm" + ExtModeIntrfLevel "Level1" + RTWCAPISignals off + RTWCAPIParams off + RTWCAPIStates off + GenerateASAP2 off + } + PropName "Components" + } + } + PropName "Components" + } + Name "Configuration" + CurrentDlgPage "Solver" + ConfigPrmDlgPosition " [ 200, 197, 1080, 827 ] " + } + PropName "ConfigurationSets" + } + Simulink.ConfigSet { + $PropName "ActiveConfigurationSet" + $ObjectID 1 + } + BlockDefaults { + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + NamePlacement "normal" + FontName "Courier" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + ShowName on + BlockRotation 0 + BlockMirror off + } + AnnotationDefaults { + HorizontalAlignment "center" + VerticalAlignment "middle" + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + FontName "Courier" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + UseDisplayTextAsClickCallback off + } + LineDefaults { + FontName "Courier" + FontSize 9 + FontWeight "normal" + FontAngle "normal" + } + BlockParameterDefaults { + Block { + BlockType FromWorkspace + VariableName "simulink_input" + SampleTime "-1" + Interpolate on + ZeroCross off + OutputAfterFinalValue "Extrapolation" + } + Block { + BlockType "S-Function" + FunctionName "system" + SFunctionModules "''" + PortCounts "[]" + SFunctionDeploymentMode off + } + Block { + BlockType Scope + ModelBased off + TickLabels "OneTimeTick" + ZoomMode "on" + Grid "on" + TimeRange "auto" + YMin "-5" + YMax "5" + SaveToWorkspace off + SaveName "ScopeData" + LimitDataPoints on + MaxDataPoints "5000" + Decimation "1" + SampleInput off + SampleTime "-1" + } + } + System { + Name "example_QProblemB" + Location [214, 137, 1484, 1054] + Open on + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "125" + ReportName "simulink-default.rpt" + SIDHighWatermark 6 + Block { + BlockType FromWorkspace + Name "From\nWorkspace1" + SID 1 + Position [85, 93, 150, 117] + VariableName "H" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace2" + SID 2 + Position [85, 158, 150, 182] + VariableName "g" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace3" + SID 3 + Position [85, 218, 150, 242] + VariableName "lb" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace4" + SID 4 + Position [85, 283, 150, 307] + VariableName "ub" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType Scope + Name "fval,\nx,\nexitflag,\niter" + SID 5 + Ports [4] + Position [840, 184, 870, 216] + Floating off + Location [6, 78, 1276, 993] + Open off + NumInputPorts "4" + List { + ListType AxesTitles + axes1 "%" + axes2 "%" + axes3 "%" + axes4 "%" + } + YMin "-5~-5~-5~-5" + YMax "5~5~5~5" + SaveName "ScopeData1" + DataFormat "StructureWithTime" + SampleTime "0" + } + Block { + BlockType "S-Function" + Name "qpOASES" + SID 6 + Ports [4, 4] + Position [510, 181, 705, 219] + BackgroundColor "yellow" + FunctionName "qpOASES_QProblemB" + EnableBusSupport off + } + Line { + SrcBlock "From\nWorkspace1" + SrcPort 1 + Points [130, 0; 0, 80] + DstBlock "qpOASES" + DstPort 1 + } + Line { + SrcBlock "From\nWorkspace2" + SrcPort 1 + Points [80, 0; 0, 26; 260, 0] + DstBlock "qpOASES" + DstPort 2 + } + Line { + SrcBlock "qpOASES" + SrcPort 1 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 1 + } + Line { + SrcBlock "qpOASES" + SrcPort 2 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 2 + } + Line { + SrcBlock "qpOASES" + SrcPort 3 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 3 + } + Line { + SrcBlock "qpOASES" + SrcPort 4 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 4 + } + Line { + SrcBlock "From\nWorkspace3" + SrcPort 1 + Points [80, 0; 0, -25] + DstBlock "qpOASES" + DstPort 3 + } + Line { + SrcBlock "From\nWorkspace4" + SrcPort 1 + Points [130, 0; 0, -79; 210, 0] + DstBlock "qpOASES" + DstPort 4 + } + Annotation { + Position [335, 96] + } + Annotation { + Name "This file is part of qpOASES.\n\nqpOASES -- An Implementation of the Online Active Set Strategy.\nC" + "opyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, Christian Kirches et al.\nAll rights reserved." + Position [608, 108] + } + } +} diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_SQProblem.mdl b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_SQProblem.mdl new file mode 100644 index 00000000000..106f19a56ed --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/example_SQProblem.mdl @@ -0,0 +1,797 @@ +Model { + Name "example_SQProblem" + Version 7.4 + MdlSubVersion 0 + GraphicalInterface { + NumRootInports 0 + NumRootOutports 0 + ParameterArgumentNames "" + ComputedModelVersion "1.62" + NumModelReferences 0 + NumTestPointedSignals 0 + } + SavedCharacterEncoding "UTF-8" + SaveDefaultBlockParams on + ScopeRefreshTime 0.035000 + OverrideScopeRefreshTime on + DisableAllScopes off + DataTypeOverride "UseLocalSettings" + MinMaxOverflowLogging "UseLocalSettings" + MinMaxOverflowArchiveMode "Overwrite" + MaxMDLFileLineLength 120 + Created "Fri Apr 13 11:08:51 2007" + Creator "jferreau" + UpdateHistory "UpdateHistoryNever" + ModifiedByFormat "%" + LastModifiedBy "chjofer2" + ModifiedDateFormat "%" + LastModifiedDate "Thu Feb 20 15:12:07 2014" + RTWModifiedTimeStamp 314809925 + ModelVersionFormat "1.%" + ConfigurationManager "None" + SampleTimeColors off + SampleTimeAnnotations off + LibraryLinkDisplay "none" + WideLines off + ShowLineDimensions off + ShowPortDataTypes off + ShowLoopsOnError on + IgnoreBidirectionalLines off + ShowStorageClass off + ShowTestPointIcons on + ShowSignalResolutionIcons on + ShowViewerIcons on + SortedOrder off + ExecutionContextIcon off + ShowLinearizationAnnotations on + BlockNameDataTip off + BlockParametersDataTip off + BlockDescriptionStringDataTip off + ToolBar on + StatusBar on + BrowserShowLibraryLinks off + BrowserLookUnderMasks off + SimulationMode "normal" + LinearizationMsg "none" + Profile off + ParamWorkspaceSource "MATLABWorkspace" + AccelSystemTargetFile "accel.tlc" + AccelTemplateMakefile "accel_default_tmf" + AccelMakeCommand "make_rtw" + TryForcingSFcnDF off + RecordCoverage off + CovPath "/" + CovSaveName "covdata" + CovMetricSettings "dw" + CovNameIncrementing off + CovHtmlReporting on + CovForceBlockReductionOff on + covSaveCumulativeToWorkspaceVar on + CovSaveSingleToWorkspaceVar on + CovCumulativeVarName "covCumulativeData" + CovCumulativeReport off + CovReportOnPause on + CovModelRefEnable "Off" + CovExternalEMLEnable off + ExtModeBatchMode off + ExtModeEnableFloating on + ExtModeTrigType "manual" + ExtModeTrigMode "normal" + ExtModeTrigPort "1" + ExtModeTrigElement "any" + ExtModeTrigDuration 1000 + ExtModeTrigDurationFloating "auto" + ExtModeTrigHoldOff 0 + ExtModeTrigDelay 0 + ExtModeTrigDirection "rising" + ExtModeTrigLevel 0 + ExtModeArchiveMode "off" + ExtModeAutoIncOneShot off + ExtModeIncDirWhenArm off + ExtModeAddSuffixToVar off + ExtModeWriteAllDataToWs off + ExtModeArmWhenConnect on + ExtModeSkipDownloadWhenConnect off + ExtModeLogAll on + ExtModeAutoUpdateStatusClock off + BufferReuse on + ShowModelReferenceBlockVersion off + ShowModelReferenceBlockIO off + Array { + Type "Handle" + Dimension 1 + Simulink.ConfigSet { + $ObjectID 1 + Version "1.6.0" + Array { + Type "Handle" + Dimension 8 + Simulink.SolverCC { + $ObjectID 2 + Version "1.6.0" + StartTime "0.0" + StopTime "0.5" + AbsTol "auto" + FixedStep "auto" + InitialStep "auto" + MaxNumMinSteps "-1" + MaxOrder 5 + ZcThreshold "auto" + ConsecutiveZCsStepRelTol "10*128*eps" + MaxConsecutiveZCs "1000" + ExtrapolationOrder 4 + NumberNewtonIterations 1 + MaxStep "auto" + MinStep "auto" + MaxConsecutiveMinStep "1" + RelTol "1e-3" + SolverMode "Auto" + Solver "VariableStepDiscrete" + SolverName "VariableStepDiscrete" + ShapePreserveControl "DisableAll" + ZeroCrossControl "UseLocalSettings" + ZeroCrossAlgorithm "Nonadaptive" + AlgebraicLoopSolver "TrustRegion" + SolverResetMethod "Fast" + PositivePriorityOrder off + AutoInsertRateTranBlk off + SampleTimeConstraint "Unconstrained" + InsertRTBMode "Whenever possible" + } + Simulink.DataIOCC { + $ObjectID 3 + Version "1.6.0" + Decimation "1" + ExternalInput "[t, u]" + FinalStateName "xFinal" + InitialState "xInitial" + LimitDataPoints on + MaxDataPoints "1000" + LoadExternalInput off + LoadInitialState off + SaveFinalState off + SaveCompleteFinalSimState off + SaveFormat "Array" + SaveOutput on + SaveState off + SignalLogging on + InspectSignalLogs off + SaveTime on + ReturnWorkspaceOutputs off + StateSaveName "xout" + TimeSaveName "tout" + OutputSaveName "yout" + SignalLoggingName "logsout" + OutputOption "RefineOutputTimes" + OutputTimes "[]" + ReturnWorkspaceOutputsName "out" + Refine "1" + } + Simulink.OptimizationCC { + $ObjectID 4 + Version "1.6.0" + Array { + Type "Cell" + Dimension 4 + Cell "ZeroExternalMemoryAtStartup" + Cell "ZeroInternalMemoryAtStartup" + Cell "NoFixptDivByZeroProtection" + Cell "OptimizeModelRefInitCode" + PropName "DisabledProps" + } + BlockReduction on + BooleanDataType on + ConditionallyExecuteInputs on + InlineParams off + UseIntDivNetSlope off + InlineInvariantSignals off + OptimizeBlockIOStorage on + BufferReuse on + EnhancedBackFolding off + StrengthReduction off + EnforceIntegerDowncast on + ExpressionFolding on + BooleansAsBitfields off + EnableMemcpy on + MemcpyThreshold 64 + PassReuseOutputArgsAs "Structure reference" + ExpressionDepthLimit 2147483647 + FoldNonRolledExpr on + LocalBlockOutputs on + RollThreshold 5 + SystemCodeInlineAuto off + StateBitsets off + DataBitsets off + UseTempVars off + ZeroExternalMemoryAtStartup on + ZeroInternalMemoryAtStartup on + InitFltsAndDblsToZero on + NoFixptDivByZeroProtection off + EfficientFloat2IntCast off + EfficientMapNaN2IntZero on + OptimizeModelRefInitCode off + LifeSpan "inf" + BufferReusableBoundary on + SimCompilerOptimization "Off" + AccelVerboseBuild off + } + Simulink.DebuggingCC { + $ObjectID 5 + Version "1.6.0" + RTPrefix "error" + ConsistencyChecking "none" + ArrayBoundsChecking "none" + SignalInfNanChecking "none" + SignalRangeChecking "none" + ReadBeforeWriteMsg "UseLocalSettings" + WriteAfterWriteMsg "UseLocalSettings" + WriteAfterReadMsg "UseLocalSettings" + AlgebraicLoopMsg "warning" + ArtificialAlgebraicLoopMsg "warning" + SaveWithDisabledLinksMsg "warning" + SaveWithParameterizedLinksMsg "none" + CheckSSInitialOutputMsg on + UnderspecifiedInitializationDetection "Classic" + MergeDetectMultiDrivingBlocksExec "none" + CheckExecutionContextPreStartOutputMsg off + CheckExecutionContextRuntimeOutputMsg off + SignalResolutionControl "TryResolveAllWithWarning" + BlockPriorityViolationMsg "warning" + MinStepSizeMsg "warning" + TimeAdjustmentMsg "none" + MaxConsecutiveZCsMsg "error" + SolverPrmCheckMsg "warning" + InheritedTsInSrcMsg "warning" + DiscreteInheritContinuousMsg "warning" + MultiTaskDSMMsg "error" + MultiTaskCondExecSysMsg "error" + MultiTaskRateTransMsg "error" + SingleTaskRateTransMsg "none" + TasksWithSamePriorityMsg "warning" + SigSpecEnsureSampleTimeMsg "warning" + CheckMatrixSingularityMsg "none" + IntegerOverflowMsg "warning" + Int32ToFloatConvMsg "warning" + ParameterDowncastMsg "error" + ParameterOverflowMsg "error" + ParameterUnderflowMsg "none" + ParameterPrecisionLossMsg "warning" + ParameterTunabilityLossMsg "warning" + FixptConstUnderflowMsg "none" + FixptConstOverflowMsg "none" + FixptConstPrecisionLossMsg "none" + UnderSpecifiedDataTypeMsg "none" + UnnecessaryDatatypeConvMsg "none" + VectorMatrixConversionMsg "none" + InvalidFcnCallConnMsg "error" + FcnCallInpInsideContextMsg "Use local settings" + SignalLabelMismatchMsg "none" + UnconnectedInputMsg "warning" + UnconnectedOutputMsg "warning" + UnconnectedLineMsg "warning" + SFcnCompatibilityMsg "none" + UniqueDataStoreMsg "none" + BusObjectLabelMismatch "warning" + RootOutportRequireBusObject "warning" + AssertControl "UseLocalSettings" + EnableOverflowDetection off + ModelReferenceIOMsg "none" + ModelReferenceVersionMismatchMessage "none" + ModelReferenceIOMismatchMessage "none" + ModelReferenceCSMismatchMessage "none" + UnknownTsInhSupMsg "warning" + ModelReferenceDataLoggingMessage "warning" + ModelReferenceSymbolNameMessage "warning" + ModelReferenceExtraNoncontSigs "error" + StateNameClashWarn "warning" + SimStateInterfaceChecksumMismatchMsg "warning" + StrictBusMsg "Warning" + LoggingUnavailableSignals "error" + BlockIODiagnostic "none" + } + Simulink.HardwareCC { + $ObjectID 6 + Version "1.6.0" + ProdBitPerChar 8 + ProdBitPerShort 16 + ProdBitPerInt 32 + ProdBitPerLong 32 + ProdIntDivRoundTo "Undefined" + ProdEndianess "Unspecified" + ProdWordSize 32 + ProdShiftRightIntArith on + ProdHWDeviceType "32-bit Generic" + TargetBitPerChar 8 + TargetBitPerShort 16 + TargetBitPerInt 32 + TargetBitPerLong 32 + TargetShiftRightIntArith on + TargetIntDivRoundTo "Undefined" + TargetEndianess "Unspecified" + TargetWordSize 32 + TargetTypeEmulationWarnSuppressLevel 0 + TargetPreprocMaxBitsSint 32 + TargetPreprocMaxBitsUint 32 + TargetHWDeviceType "Specified" + TargetUnknown off + ProdEqTarget on + } + Simulink.ModelReferenceCC { + $ObjectID 7 + Version "1.6.0" + UpdateModelReferenceTargets "IfOutOfDateOrStructuralChange" + CheckModelReferenceTargetMessage "error" + ModelReferenceNumInstancesAllowed "Multi" + ModelReferencePassRootInputsByReference on + ModelReferenceMinAlgLoopOccurrences off + } + Simulink.SFSimCC { + $ObjectID 8 + Version "1.6.0" + SFSimEnableDebug on + SFSimOverflowDetection on + SFSimEcho on + SimBlas on + SimCtrlC on + SimExtrinsic on + SimIntegrity on + SimUseLocalCustomCode off + SimBuildMode "sf_incremental_build" + } + Simulink.RTWCC { + $BackupClass "Simulink.RTWCC" + $ObjectID 9 + Version "1.6.0" + Array { + Type "Cell" + Dimension 1 + Cell "IncludeHyperlinkInReport" + PropName "DisabledProps" + } + SystemTargetFile "grt.tlc" + GenCodeOnly off + MakeCommand "make_rtw" + GenerateMakefile on + TemplateMakefile "grt_default_tmf" + GenerateReport off + SaveLog off + RTWVerbose on + RetainRTWFile off + ProfileTLC off + TLCDebug off + TLCCoverage off + TLCAssert off + ProcessScriptMode "Default" + ConfigurationMode "Optimized" + ConfigAtBuild off + RTWUseLocalCustomCode off + RTWUseSimCustomCode off + IncludeHyperlinkInReport off + LaunchReport off + TargetLang "C" + IncludeBusHierarchyInRTWFileBlockHierarchyMap off + IncludeERTFirstTime off + GenerateTraceInfo off + GenerateTraceReport off + GenerateTraceReportSl off + GenerateTraceReportSf off + GenerateTraceReportEml off + GenerateCodeInfo off + RTWCompilerOptimization "Off" + CheckMdlBeforeBuild "Off" + Array { + Type "Handle" + Dimension 2 + Simulink.CodeAppCC { + $ObjectID 10 + Version "1.6.0" + Array { + Type "Cell" + Dimension 16 + Cell "IgnoreCustomStorageClasses" + Cell "InsertBlockDesc" + Cell "SFDataObjDesc" + Cell "SimulinkDataObjDesc" + Cell "DefineNamingRule" + Cell "SignalNamingRule" + Cell "ParamNamingRule" + Cell "InlinedPrmAccess" + Cell "CustomSymbolStr" + Cell "CustomSymbolStrGlobalVar" + Cell "CustomSymbolStrType" + Cell "CustomSymbolStrField" + Cell "CustomSymbolStrFcn" + Cell "CustomSymbolStrBlkIO" + Cell "CustomSymbolStrTmpVar" + Cell "CustomSymbolStrMacro" + PropName "DisabledProps" + } + ForceParamTrailComments off + GenerateComments on + IgnoreCustomStorageClasses on + IgnoreTestpoints off + IncHierarchyInIds off + MaxIdLength 31 + PreserveName off + PreserveNameWithParent off + ShowEliminatedStatement off + IncAutoGenComments off + SimulinkDataObjDesc off + SFDataObjDesc off + IncDataTypeInIds off + MangleLength 1 + CustomSymbolStrGlobalVar "$R$N$M" + CustomSymbolStrType "$N$R$M" + CustomSymbolStrField "$N$M" + CustomSymbolStrFcn "$R$N$M$F" + CustomSymbolStrFcnArg "rt$I$N$M" + CustomSymbolStrBlkIO "rtb_$N$M" + CustomSymbolStrTmpVar "$N$M" + CustomSymbolStrMacro "$R$N$M" + DefineNamingRule "None" + ParamNamingRule "None" + SignalNamingRule "None" + InsertBlockDesc off + SimulinkBlockComments on + EnableCustomComments off + InlinedPrmAccess "Literals" + ReqsInCode off + UseSimReservedNames off + } + Simulink.GRTTargetCC { + $BackupClass "Simulink.TargetCC" + $ObjectID 11 + Version "1.6.0" + Array { + Type "Cell" + Dimension 13 + Cell "IncludeMdlTerminateFcn" + Cell "CombineOutputUpdateFcns" + Cell "SuppressErrorStatus" + Cell "ERTCustomFileBanners" + Cell "GenerateSampleERTMain" + Cell "GenerateTestInterfaces" + Cell "MultiInstanceERTCode" + Cell "PurelyIntegerCode" + Cell "SupportNonFinite" + Cell "SupportComplex" + Cell "SupportAbsoluteTime" + Cell "SupportContinuousTime" + Cell "SupportNonInlinedSFcns" + PropName "DisabledProps" + } + TargetFcnLib "ansi_tfl_tmw.mat" + TargetLibSuffix "" + TargetPreCompLibLocation "" + TargetFunctionLibrary "ANSI_C" + UtilityFuncGeneration "Auto" + ERTMultiwordTypeDef "System defined" + ERTMultiwordLength 256 + MultiwordLength 2048 + GenerateFullHeader on + GenerateSampleERTMain off + GenerateTestInterfaces off + IsPILTarget off + ModelReferenceCompliant on + ParMdlRefBuildCompliant on + CompOptLevelCompliant on + IncludeMdlTerminateFcn on + GeneratePreprocessorConditionals "Disable all" + CombineOutputUpdateFcns off + SuppressErrorStatus off + ERTFirstTimeCompliant off + IncludeFileDelimiter "Auto" + ERTCustomFileBanners off + SupportAbsoluteTime on + LogVarNameModifier "rt_" + MatFileLogging on + MultiInstanceERTCode off + SupportNonFinite on + SupportComplex on + PurelyIntegerCode off + SupportContinuousTime on + SupportNonInlinedSFcns on + SupportVariableSizeSignals off + EnableShiftOperators on + ParenthesesLevel "Nominal" + PortableWordSizes off + ModelStepFunctionPrototypeControlCompliant off + CPPClassGenCompliant off + AutosarCompliant off + UseMalloc off + ExtMode off + ExtModeStaticAlloc off + ExtModeTesting off + ExtModeStaticAllocSize 1000000 + ExtModeTransport 0 + ExtModeMexFile "ext_comm" + ExtModeIntrfLevel "Level1" + RTWCAPISignals off + RTWCAPIParams off + RTWCAPIStates off + GenerateASAP2 off + } + PropName "Components" + } + } + PropName "Components" + } + Name "Configuration" + CurrentDlgPage "Solver" + ConfigPrmDlgPosition " [ 200, 197, 1080, 827 ] " + } + PropName "ConfigurationSets" + } + Simulink.ConfigSet { + $PropName "ActiveConfigurationSet" + $ObjectID 1 + } + BlockDefaults { + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + NamePlacement "normal" + FontName "Courier" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + ShowName on + BlockRotation 0 + BlockMirror off + } + AnnotationDefaults { + HorizontalAlignment "center" + VerticalAlignment "middle" + ForegroundColor "black" + BackgroundColor "white" + DropShadow off + FontName "Courier" + FontSize 10 + FontWeight "normal" + FontAngle "normal" + UseDisplayTextAsClickCallback off + } + LineDefaults { + FontName "Courier" + FontSize 9 + FontWeight "normal" + FontAngle "normal" + } + BlockParameterDefaults { + Block { + BlockType FromWorkspace + VariableName "simulink_input" + SampleTime "-1" + Interpolate on + ZeroCross off + OutputAfterFinalValue "Extrapolation" + } + Block { + BlockType "S-Function" + FunctionName "system" + SFunctionModules "''" + PortCounts "[]" + SFunctionDeploymentMode off + } + Block { + BlockType Scope + ModelBased off + TickLabels "OneTimeTick" + ZoomMode "on" + Grid "on" + TimeRange "auto" + YMin "-5" + YMax "5" + SaveToWorkspace off + SaveName "ScopeData" + LimitDataPoints on + MaxDataPoints "5000" + Decimation "1" + SampleInput off + SampleTime "-1" + } + } + System { + Name "example_SQProblem" + Location [2, 74, 1918, 1139] + Open on + ModelBrowserVisibility off + ModelBrowserWidth 200 + ScreenColor "white" + PaperOrientation "landscape" + PaperPositionMode "auto" + PaperType "usletter" + PaperUnits "inches" + TiledPaperMargins [0.500000, 0.500000, 0.500000, 0.500000] + TiledPageScale 1 + ShowPageBoundaries off + ZoomFactor "125" + ReportName "simulink-default.rpt" + SIDHighWatermark 9 + Block { + BlockType FromWorkspace + Name "From\nWorkspace1" + SID 1 + Position [85, 53, 150, 77] + VariableName "H" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace2" + SID 2 + Position [85, 113, 150, 137] + VariableName "g" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace3" + SID 3 + Position [85, 173, 150, 197] + VariableName "A" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace4" + SID 4 + Position [85, 233, 150, 257] + VariableName "lb" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace5" + SID 5 + Position [85, 293, 150, 317] + VariableName "ub" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace6" + SID 6 + Position [85, 353, 150, 377] + VariableName "lbA" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType FromWorkspace + Name "From\nWorkspace7" + SID 7 + Position [85, 418, 150, 442] + VariableName "ubA" + SampleTime "0.1" + ZeroCross on + OutputAfterFinalValue "Holding final value" + } + Block { + BlockType Scope + Name "fval,\nx,\nexitflag,\niter" + SID 8 + Ports [4] + Position [935, 229, 965, 261] + Floating off + Location [6, 78, 1276, 993] + Open off + NumInputPorts "4" + List { + ListType AxesTitles + axes1 "%" + axes2 "%" + axes3 "%" + axes4 "%" + } + YMin "-5~-5~-5~-5" + YMax "5~5~5~5" + SaveName "ScopeData1" + DataFormat "StructureWithTime" + SampleTime "0" + } + Block { + BlockType "S-Function" + Name "qpOASES" + SID 9 + Ports [7, 4] + Position [600, 226, 795, 264] + BackgroundColor "yellow" + FunctionName "qpOASES_SQProblem" + EnableBusSupport off + } + Line { + SrcBlock "From\nWorkspace1" + SrcPort 1 + Points [180, 0; 0, 165] + DstBlock "qpOASES" + DstPort 1 + } + Line { + SrcBlock "From\nWorkspace2" + SrcPort 1 + Points [115, 0; 0, 110] + DstBlock "qpOASES" + DstPort 2 + } + Line { + Labels [3, 0] + SrcBlock "From\nWorkspace7" + SrcPort 1 + Points [180, 0; 0, -170] + DstBlock "qpOASES" + DstPort 7 + } + Line { + SrcBlock "From\nWorkspace5" + SrcPort 1 + Points [55, 0; 0, -55] + DstBlock "qpOASES" + DstPort 5 + } + Line { + SrcBlock "From\nWorkspace4" + SrcPort 1 + DstBlock "qpOASES" + DstPort 4 + } + Line { + SrcBlock "From\nWorkspace3" + SrcPort 1 + Points [55, 0; 0, 55] + DstBlock "qpOASES" + DstPort 3 + } + Line { + Labels [3, 0] + SrcBlock "From\nWorkspace6" + SrcPort 1 + Points [115, 0; 0, -110] + DstBlock "qpOASES" + DstPort 6 + } + Line { + SrcBlock "qpOASES" + SrcPort 1 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 1 + } + Line { + SrcBlock "qpOASES" + SrcPort 2 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 2 + } + Line { + SrcBlock "qpOASES" + SrcPort 3 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 3 + } + Line { + SrcBlock "qpOASES" + SrcPort 4 + DstBlock "fval,\nx,\nexitflag,\niter" + DstPort 4 + } + Annotation { + Position [335, 96] + } + Annotation { + Name "This file is part of qpOASES.\n\nqpOASES -- An Implementation of the Online Active Set Strategy.\nC" + "opyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, Christian Kirches et al.\nAll rights reserved." + Position [698, 138] + } + } +} diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/index.html b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/index.html new file mode 100644 index 00000000000..e3ce9152edb --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/index.html @@ -0,0 +1,17 @@ +qpOASES - Revision 198: /stable/3.0/interfaces/simulink + +

qpOASES - Revision 198: /stable/3.0/interfaces/simulink

+ + \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_QProblem.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_QProblem.m new file mode 100644 index 00000000000..af2a81d91c9 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_QProblem.m @@ -0,0 +1,93 @@ +%% +%% This file is part of qpOASES. +%% +%% qpOASES -- An Implementation of the Online Active Set Strategy. +%% Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%% Christian Kirches et al. All rights reserved. +%% +%% qpOASES is free software; you can redistribute it and/or +%% modify it under the terms of the GNU Lesser General Public +%% License as published by the Free Software Foundation; either +%% version 2.1 of the License, or (at your option) any later version. +%% +%% qpOASES is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%% See the GNU Lesser General Public License for more details. +%% +%% You should have received a copy of the GNU Lesser General Public +%% License along with qpOASES; if not, write to the Free Software +%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +%% + + + +%% +%% Filename: interfaces/simulink/load_example_QProblem.m +%% Author: Hans Joachim Ferreau (thanks to Aude Perrin) +%% Version: 3.0 +%% Date: 2007-2014 +%% + + + +clear all; + + +%% setup QP data +simulationTime = [0;0.1]; + +H.time = simulationTime; +data1 = [1.0,0.0,0.0,0.5]; +data2 = [1.0,0.0,0.0,0.5]; +H.signals.values = [data1; data2]; +H.signals.dimensions = length(data1); + +g.time = simulationTime; +data1 = [1.5,1.0]; +data2 = [1.0,1.5]; +g.signals.values = [data1; data2]; +g.signals.dimensions = length(data1); + +A.time = simulationTime; +data1 = [1.0,1.0]; +data2 = [1.0,1.0]; +A.signals.values = [data1; data2]; +A.signals.dimensions = length(data1); + +lb.time = simulationTime; +data1 = [0.5,-2.0]; +data2 = [0.0,-1.0]; +lb.signals.values = [data1; data2]; +lb.signals.dimensions = length(data1); + +ub.time = simulationTime; +data1 = [5.0,2.0]; +data2 = [5.0,-0.5]; +ub.signals.values = [data1; data2]; +ub.signals.dimensions = length(data1); + +lbA.time = simulationTime; +data1 = [-1.0]; +data2 = [-2.0]; +lbA.signals.values = [data1; data2]; +lbA.signals.dimensions = length(data1); + +ubA.time = simulationTime; +data1 = [2.0]; +data2 = [1.0]; +ubA.signals.values = [data1; data2]; +ubA.signals.dimensions = length(data1); + + +clear simulationTime data1 data2 + + +%% open corresponding simulink example +open( 'example_QProblem.mdl' ); + + + +%% +%% end of file +%% diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_QProblemB.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_QProblemB.m new file mode 100644 index 00000000000..8c3900c9922 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_QProblemB.m @@ -0,0 +1,75 @@ +%% +%% This file is part of qpOASES. +%% +%% qpOASES -- An Implementation of the Online Active Set Strategy. +%% Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%% Christian Kirches et al. All rights reserved. +%% +%% qpOASES is free software; you can redistribute it and/or +%% modify it under the terms of the GNU Lesser General Public +%% License as published by the Free Software Foundation; either +%% version 2.1 of the License, or (at your option) any later version. +%% +%% qpOASES is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%% See the GNU Lesser General Public License for more details. +%% +%% You should have received a copy of the GNU Lesser General Public +%% License along with qpOASES; if not, write to the Free Software +%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +%% + + + +%% +%% Filename: interfaces/simulink/load_example_QProblemB.m +%% Author: Hans Joachim Ferreau (thanks to Aude Perrin) +%% Version: 3.0 +%% Date: 2007-2014 +%% + + + +clear all; + + +%% setup QP data +simulationTime = [0;0.1]; + +H.time = simulationTime; +data1 = [1.0,0.0,0.0,0.5]; +data2 = [1.0,0.0,0.0,0.5]; +H.signals.values = [data1; data2]; +H.signals.dimensions = length(data1); + +g.time = simulationTime; +data1 = [1.5,1.0]; +data2 = [1.0,1.5]; +g.signals.values = [data1; data2]; +g.signals.dimensions = length(data1); + +lb.time = simulationTime; +data1 = [0.5,-2.0]; +data2 = [0.0,-1.0]; +lb.signals.values = [data1; data2]; +lb.signals.dimensions = length(data1); + +ub.time = simulationTime; +data1 = [5.0,2.0]; +data2 = [5.0,-0.5]; +ub.signals.values = [data1; data2]; +ub.signals.dimensions = length(data1); + + +clear simulationTime data1 data2 + + +%% open corresponding simulink example +open( 'example_QProblemB.mdl' ); + + + +%% +%% end of file +%% diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_SQProblem.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_SQProblem.m new file mode 100644 index 00000000000..afde11103d5 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/load_example_SQProblem.m @@ -0,0 +1,93 @@ +%% +%% This file is part of qpOASES. +%% +%% qpOASES -- An Implementation of the Online Active Set Strategy. +%% Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%% Christian Kirches et al. All rights reserved. +%% +%% qpOASES is free software; you can redistribute it and/or +%% modify it under the terms of the GNU Lesser General Public +%% License as published by the Free Software Foundation; either +%% version 2.1 of the License, or (at your option) any later version. +%% +%% qpOASES is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%% See the GNU Lesser General Public License for more details. +%% +%% You should have received a copy of the GNU Lesser General Public +%% License along with qpOASES; if not, write to the Free Software +%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +%% + + + +%% +%% Filename: interfaces/simulink/load_example_SQProblem.m +%% Author: Hans Joachim Ferreau (thanks to Aude Perrin) +%% Version: 3.0 +%% Date: 2007-2014 +%% + + + +clear all; + + +%% setup QP data +simulationTime = [0;0.1]; + +H.time = simulationTime; +data1 = [1.0,0.0,0.0,0.5]; +data2 = [1.0,0.5,0.5,0.5]; +H.signals.values = [data1; data2]; +H.signals.dimensions = length(data1); + +g.time = simulationTime; +data1 = [1.5,1.0]; +data2 = [1.0,1.5]; +g.signals.values = [data1; data2]; +g.signals.dimensions = length(data1); + +A.time = simulationTime; +data1 = [1.0,1.0]; +data2 = [1.0,5.0]; +A.signals.values = [data1; data2]; +A.signals.dimensions = length(data1); + +lb.time = simulationTime; +data1 = [0.5,-2.0]; +data2 = [0.0,-1.0]; +lb.signals.values = [data1; data2]; +lb.signals.dimensions = length(data1); + +ub.time = simulationTime; +data1 = [5.0,2.0]; +data2 = [5.0,-0.5]; +ub.signals.values = [data1; data2]; +ub.signals.dimensions = length(data1); + +lbA.time = simulationTime; +data1 = [-1.0]; +data2 = [-2.0]; +lbA.signals.values = [data1; data2]; +lbA.signals.dimensions = length(data1); + +ubA.time = simulationTime; +data1 = [2.0]; +data2 = [1.0]; +ubA.signals.values = [data1; data2]; +ubA.signals.dimensions = length(data1); + + +clear simulationTime data1 data2 + + +%% open corresponding simulink example +open( 'example_SQProblem.mdl' ); + + + +%% +%% end of file +%% diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/make.m b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/make.m new file mode 100644 index 00000000000..96352251986 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/make.m @@ -0,0 +1,239 @@ +function [] = make( varargin ) +%MAKE Compiles the Simulink interface of qpOASES. +% +%Type make to compile all interfaces that +% have been modified, +%type make clean to delete all compiled interfaces, +%type make clean all to first delete and then compile +% all interfaces, +%type make 'name' to compile only the interface with +% the given name (if it has been modified), +%type make 'opt' to compile all interfaces using the +% given compiler options. +% +%Copyright (C) 2013-2014 by Hans Joachim Ferreau, Andreas Potschka, +%Christian Kirches et al. All rights reserved. + +%% +%% This file is part of qpOASES. +%% +%% qpOASES -- An Implementation of the Online Active Set Strategy. +%% Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, +%% Christian Kirches et al. All rights reserved. +%% +%% qpOASES is free software; you can redistribute it and/or +%% modify it under the terms of the GNU Lesser General Public +%% License as published by the Free Software Foundation; either +%% version 2.1 of the License, or (at your option) any later version. +%% +%% qpOASES is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +%% See the GNU Lesser General Public License for more details. +%% +%% You should have received a copy of the GNU Lesser General Public +%% License along with qpOASES; if not, write to the Free Software +%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +%% + +%% +%% Filename: interfaces/simulink/make.m +%% Author: Hans Joachim Ferreau, Andreas Potschka, Christian Kirches +%% Version: 3.0 +%% Date: 2007-2014 +%% + + + %% consistency check + if ( exist( [pwd, '/make.m'],'file' ) == 0 ) + error( ['ERROR (',mfilename '.m): Run this make script directly within the directory', ... + '/interfaces/simulink, please.'] ); + end + + + if ( nargin > 2 ) + error( ['ERROR (',mfilename '.m): At most two make arguments supported!'] ); + else + [ doClean,fcnNames,userFlags ] = analyseMakeArguments( nargin,varargin ); + end + + + %% define compiler settings + QPOASESPATH = '../../'; + + DEBUGFLAGS = ' '; + %DEBUGFLAGS = ' -g CXXDEBUGFLAGS=''$CXXDEBUGFLAGS -Wall -pedantic -Wshadow'' '; + + IFLAGS = [ '-I. -I',QPOASESPATH,'include',' -I',QPOASESPATH,'src',' ' ]; + CPPFLAGS = [ IFLAGS, DEBUGFLAGS, '-largeArrayDims -D__cpluplus -D__MATLAB__ -D__SINGLE_OBJECT__',' ' ]; + defaultFlags = '-O '; %% -D__NO_COPYRIGHT__ -D__SUPPRESSANYOUTPUT__ + + if ( ispc == 0 ) + CPPFLAGS = [ CPPFLAGS, '-DLINUX ',' ' ]; + else + CPPFLAGS = [ CPPFLAGS, '-DWIN32 ',' ' ]; + end + + if ( isempty(userFlags) > 0 ) + CPPFLAGS = [ CPPFLAGS, defaultFlags,' ' ]; + else + CPPFLAGS = [ CPPFLAGS, userFlags,' ' ]; + end + + mexExt = eval('mexext'); + + + %% ensure copyright notice is displayed + if ~isempty( strfind( CPPFLAGS,'-D__NO_COPYRIGHT__' ) ) + printCopyrightNotice( ); + end + + + %% clean if desired + if ( doClean > 0 ) + + eval( 'delete *.o;' ); + eval( ['delete *.',mexExt,'*;'] ); + disp( [ 'INFO (',mfilename '.m): Cleaned all compiled files.'] ); + pause( 0.2 ); + + end + + + if ( ~isempty(userFlags) ) + disp( [ 'INFO (',mfilename '.m): Compiling all files with user-defined compiler flags (''',userFlags,''')...'] ); + end + + + %% call mex compiler + for ii=1:length(fcnNames) + + cmd = [ 'mex -output ', fcnNames{ii}, ' ', CPPFLAGS, [fcnNames{ii},'.cpp'] ]; + + if ( exist( [fcnNames{ii},'.',mexExt],'file' ) == 0 ) + + eval( cmd ); + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' successfully created.'] ); + + else + + % check modification time of source/Make files and compiled mex file + cppFile = dir( [pwd,'/',fcnNames{ii},'.cpp'] ); + cppFileTimestamp = getTimestamp( cppFile ); + + makeFile = dir( [pwd,'/make.m'] ); + makeFileTimestamp = getTimestamp( makeFile ); + + mexFile = dir( [pwd,'/',fcnNames{ii},'.',mexExt] ); + if ( isempty(mexFile) == 0 ) + mexFileTimestamp = getTimestamp( mexFile ); + else + mexFileTimestamp = 0; + end + + if ( ( cppFileTimestamp >= mexFileTimestamp ) || ... + ( makeFileTimestamp >= mexFileTimestamp ) ) + eval( cmd ); + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' successfully created.'] ); + else + disp( [ 'INFO (',mfilename '.m): ', fcnNames{ii},'.',mexExt, ' already exists.'] ); + end + + end + + end + + %% add qpOASES directory to path + path( path,pwd ); + +end + + +function [ doClean,fcnNames,userIFlags ] = analyseMakeArguments( nArgs,args ) + + doClean = 0; + fcnNames = []; + userIFlags = []; + + switch ( nArgs ) + + case 1 + if ( strcmp( args{1},'all' ) > 0 ) + fcnNames = { 'qpOASES_QProblemB','qpOASES_QProblem','qpOASES_SQProblem' }; + elseif ( strcmp( args{1},'qpOASES_QProblemB' ) > 0 ) + fcnNames = { 'qpOASES_QProblemB' }; + elseif ( strcmp( args{1},'qpOASES_QProblem' ) > 0 ) + fcnNames = { 'qpOASES_QProblem' }; + elseif ( strcmp( args{1},'qpOASES_SQProblem' ) > 0 ) + fcnNames = { 'qpOASES_SQProblem' }; + elseif ( strcmp( args{1},'clean' ) > 0 ) + doClean = 1; + elseif ( strcmp( args{1}(1),'-' ) > 0 ) + % make clean all with user-specified compiler flags + userIFlags = args{1}; + doClean = 1; + fcnNames = { 'qpOASES_QProblemB','qpOASES_QProblem','qpOASES_SQProblem' }; + else + error( ['ERROR (',mfilename '.m): Invalid first argument (''',args{1},''')!'] ); + end + + case 2 + if ( strcmp( args{1},'clean' ) > 0 ) + doClean = 1; + else + error( ['ERROR (',mfilename '.m): First argument must be ''clean'' if two arguments are provided!'] ); + end + + if ( strcmp( args{2},'all' ) > 0 ) + fcnNames = { 'qpOASES_QProblemB','qpOASES_QProblem','qpOASES_SQProblem' }; + elseif ( strcmp( args{2},'qpOASES_QProblemB' ) > 0 ) + fcnNames = { 'qpOASES_QProblemB' }; + elseif ( strcmp( args{2},'qpOASES_QProblem' ) > 0 ) + fcnNames = { 'qpOASES_QProblem' }; + elseif ( strcmp( args{2},'qpOASES_SQProblem' ) > 0 ) + fcnNames = { 'qpOASES_SQProblem' }; + else + error( ['ERROR (',mfilename '.m): Invalid second argument (''',args{2},''')!'] ); + end + + otherwise + doClean = 0; + fcnNames = { 'qpOASES_QProblemB','qpOASES_QProblem','qpOASES_SQProblem' }; + userIFlags = []; + end + +end + + +function [ timestamp ] = getTimestamp( dateString ) + + try + timestamp = dateString.datenum; + catch + timestamp = Inf; + end + +end + + +function [ ] = printCopyrightNotice( ) + + disp( ' ' ); + disp( 'qpOASES -- An Implementation of the Online Active Set Strategy.' ); + disp( 'Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka,' ); + disp( 'Christian Kirches et al. All rights reserved.' ); + disp( ' ' ); + disp( 'qpOASES is distributed under the terms of the' ); + disp( 'GNU Lesser General Public License 2.1 in the hope that it will be' ); + disp( 'useful, but WITHOUT ANY WARRANTY; without even the implied warranty' ); + disp( 'of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.' ); + disp( 'See the GNU Lesser General Public License for more details.' ); + disp( ' ' ); + disp( ' ' ); + +end + + +%% +%% end of file +%% diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_QProblem.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_QProblem.cpp new file mode 100644 index 00000000000..e5cba8ffd18 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_QProblem.cpp @@ -0,0 +1,447 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/simulink/qpOASES_QProblem.cpp + * \author Hans Joachim Ferreau (thanks to Aude Perrin) + * \version 3.0 + * \date 2007-2014 + * + * Interface for Simulink(R) that enables to call qpOASES as a S function + * (variant for QPs with fixed matrices). + * + */ + + +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define S_FUNCTION_NAME qpOASES_QProblem /**< Name of the S function. */ +#define S_FUNCTION_LEVEL 2 /**< S function level. */ + +#define MDL_START /**< Activate call to mdlStart. */ + +#include "simstruc.h" + + +/* SETTINGS: */ +#define SAMPLINGTIME -1 /**< Sampling time. */ +#define NCONTROLINPUTS 2 /**< Number of control inputs. */ +#define NWSR 100 /**< Maximum number of working set recalculations. */ + + +static void mdlInitializeSizes (SimStruct *S) /* Init sizes array */ +{ + int nU = NCONTROLINPUTS; + + /* Specify the number of continuous and discrete states */ + ssSetNumContStates(S, 0); + ssSetNumDiscStates(S, 0); + + /* Specify the number of intput ports */ + if ( !ssSetNumInputPorts(S, 7) ) + return; + + /* Specify the number of output ports */ + if ( !ssSetNumOutputPorts(S, 4) ) + return; + + /* Specify dimension information for the input ports */ + ssSetInputPortVectorDimension(S, 0, DYNAMICALLY_SIZED); /* H */ + ssSetInputPortVectorDimension(S, 1, DYNAMICALLY_SIZED); /* g */ + ssSetInputPortVectorDimension(S, 2, DYNAMICALLY_SIZED); /* A */ + ssSetInputPortVectorDimension(S, 3, DYNAMICALLY_SIZED); /* lb */ + ssSetInputPortVectorDimension(S, 4, DYNAMICALLY_SIZED); /* ub */ + ssSetInputPortVectorDimension(S, 5, DYNAMICALLY_SIZED); /* lbA */ + ssSetInputPortVectorDimension(S, 6, DYNAMICALLY_SIZED); /* ubA */ + + /* Specify dimension information for the output ports */ + ssSetOutputPortVectorDimension(S, 0, 1 ); /* fval */ + ssSetOutputPortVectorDimension(S, 1, nU ); /* uOpt */ + ssSetOutputPortVectorDimension(S, 2, 1 ); /* exitflag */ + ssSetOutputPortVectorDimension(S, 3, 1 ); /* iter */ + + /* Specify the direct feedthrough status */ + ssSetInputPortDirectFeedThrough(S, 0, 1); + ssSetInputPortDirectFeedThrough(S, 1, 1); + ssSetInputPortDirectFeedThrough(S, 2, 1); + ssSetInputPortDirectFeedThrough(S, 3, 1); + ssSetInputPortDirectFeedThrough(S, 4, 1); + ssSetInputPortDirectFeedThrough(S, 5, 1); + ssSetInputPortDirectFeedThrough(S, 6, 1); + + /* One sample time */ + ssSetNumSampleTimes(S, 1); + + /* global variables: + * 0: problem + * 1: H + * 2: g + * 3: A + * 4: lb + * 5: ub + * 6: lbA + * 7: ubA + * 8: count + */ + + /* Specify the size of the block's pointer work vector */ + ssSetNumPWork(S, 9); +} + + +#if defined(MATLAB_MEX_FILE) + +#define MDL_SET_INPUT_PORT_DIMENSION_INFO +#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO + +static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +#endif + + +static void mdlInitializeSampleTimes(SimStruct *S) +{ + ssSetSampleTime(S, 0, SAMPLINGTIME); + ssSetOffsetTime(S, 0, 0.0); +} + + +static void mdlStart(SimStruct *S) +{ + USING_NAMESPACE_QPOASES + + int nU = NCONTROLINPUTS; + int size_H, size_g, size_A, size_lb, size_ub, size_lbA, size_ubA; + int nV, nC; + + QProblem* problem; + real_t* count; + + + /* get block inputs dimensions */ + size_H = ssGetInputPortWidth(S, 0); + size_g = ssGetInputPortWidth(S, 1); + size_A = ssGetInputPortWidth(S, 2); + size_lb = ssGetInputPortWidth(S, 3); + size_ub = ssGetInputPortWidth(S, 4); + size_lbA = ssGetInputPortWidth(S, 5); + size_ubA = ssGetInputPortWidth(S, 6); + + + /* dimension checks */ + nV = size_g; + nC = (int) ( ((real_t) size_A) / ((real_t) nV) ); + + + if ( NWSR < 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Maximum number of iterations must not be negative!" ); + #endif + #endif + return; + } + + if ( nV <= 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_H != nV*nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( ( nU < 1 ) || ( nU > nV ) ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Invalid number of control inputs!" ); + #endif + #endif + return; + } + + if ( size_lb != nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_ub != nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_lbA != nC ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_ubA != nC ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + + /* allocate QProblem object */ + problem = new QProblem( nV,nC ); + if ( problem == 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Unable to create QProblem object!" ); + #endif + #endif + return; + } + + Options problemOptions; + problemOptions.setToMPC(); + problem->setOptions( problemOptions ); + + #ifndef __DEBUG__ + problem->setPrintLevel( PL_LOW ); + #endif + #ifdef __SUPPRESSANYOUTPUT__ + problem->setPrintLevel( PL_NONE ); + #endif + #ifdef __DSPACE__ + problem->setPrintLevel( PL_NONE ); + #endif + + ssGetPWork(S)[0] = (void *) problem; + + /* allocate memory for QP data ... */ + ssGetPWork(S)[1] = (void *) calloc( size_H, sizeof(real_t) ); /* H */ + ssGetPWork(S)[2] = (void *) calloc( size_g, sizeof(real_t) ); /* g */ + ssGetPWork(S)[3] = (void *) calloc( size_A, sizeof(real_t) ); /* A */ + ssGetPWork(S)[4] = (void *) calloc( size_lb, sizeof(real_t) ); /* lb */ + ssGetPWork(S)[5] = (void *) calloc( size_ub, sizeof(real_t) ); /* ub */ + ssGetPWork(S)[6] = (void *) calloc( size_lbA, sizeof(real_t) ); /* lbA */ + ssGetPWork(S)[7] = (void *) calloc( size_ubA, sizeof(real_t) ); /* ubA */ + ssGetPWork(S)[8] = (void *) calloc( 1, sizeof(real_t) ); /* count */ + + /* reset counter */ + count = (real_t *) ssGetPWork(S)[8]; + count[0] = 0.0; +} + + +static void mdlOutputs(SimStruct *S, int_T tid) +{ + USING_NAMESPACE_QPOASES + + int i; + int nV, nC; + returnValue status; + + int nWSR = NWSR; + int nU = NCONTROLINPUTS; + + InputRealPtrsType in_H, in_g, in_A, in_lb, in_ub, in_lbA, in_ubA; + + QProblem* problem; + real_t *H, *g, *A, *lb, *ub, *lbA, *ubA, *count; + + real_t *xOpt; + + real_T *out_objVal, *out_uOpt, *out_status, *out_nWSR; + + + /* get pointers to block inputs ... */ + in_H = ssGetInputPortRealSignalPtrs(S, 0); + in_g = ssGetInputPortRealSignalPtrs(S, 1); + in_A = ssGetInputPortRealSignalPtrs(S, 2); + in_lb = ssGetInputPortRealSignalPtrs(S, 3); + in_ub = ssGetInputPortRealSignalPtrs(S, 4); + in_lbA = ssGetInputPortRealSignalPtrs(S, 5); + in_ubA = ssGetInputPortRealSignalPtrs(S, 6); + + + /* ... and to the QP data */ + problem = (QProblem *) ssGetPWork(S)[0]; + + H = (real_t *) ssGetPWork(S)[1]; + g = (real_t *) ssGetPWork(S)[2]; + A = (real_t *) ssGetPWork(S)[3]; + lb = (real_t *) ssGetPWork(S)[4]; + ub = (real_t *) ssGetPWork(S)[5]; + lbA = (real_t *) ssGetPWork(S)[6]; + ubA = (real_t *) ssGetPWork(S)[7]; + + count = (real_t *) ssGetPWork(S)[8]; + + + /* setup QP data */ + nV = ssGetInputPortWidth(S, 1); /* nV = size_g */ + nC = (int) ( ((real_t) ssGetInputPortWidth(S, 2)) / ((real_t) nV) ); /* nC = size_A / size_g */ + + for ( i=0; iinit( H,g,A,lb,ub,lbA,ubA, nWSR,0 ); + problem->getPrimalSolution( xOpt ); + } + else + { + /* solve neighbouring QP using hotstart technique */ + status = problem->hotstart( g,lb,ub,lbA,ubA, nWSR,0 ); + if ( ( status != SUCCESSFUL_RETURN ) && ( status != RET_MAX_NWSR_REACHED ) ) + { + /* if an error occurs, reset problem data structures ... */ + problem->reset( ); + + /* ... and initialise/solve again with remaining number of iterations. */ + int nWSR_retry = NWSR-nWSR; + status = problem->init( H,g,A,lb,ub,lbA,ubA, nWSR_retry,0 ); + nWSR += nWSR_retry; + + } + + /* obtain optimal solution */ + problem->getPrimalSolution( xOpt ); + } + + /* generate block output: status information ... */ + out_objVal = ssGetOutputPortRealSignal(S, 0); + out_uOpt = ssGetOutputPortRealSignal(S, 1); + out_status = ssGetOutputPortRealSignal(S, 2); + out_nWSR = ssGetOutputPortRealSignal(S, 3); + + out_objVal[0] = ((real_T) problem->getObjVal( )); + + for ( i=0; ireset( ); + + int i; + for ( i=0; i<9; ++i ) + { + if ( ssGetPWork(S)[i] != 0 ) + free( ssGetPWork(S)[i] ); + } +} + + +#ifdef MATLAB_MEX_FILE +#include "simulink.c" +#else +#include "cg_sfun.h" +#endif + + +#ifdef __cplusplus +} +#endif + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_QProblemB.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_QProblemB.cpp new file mode 100644 index 00000000000..404cb5e47a3 --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_QProblemB.cpp @@ -0,0 +1,392 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/simulink/qpOASES_QProblemB.cpp + * \author Hans Joachim Ferreau (thanks to Aude Perrin) + * \version 3.0 + * \date 2007-2014 + * + * Interface for Simulink(R) that enables to call qpOASES as a S function + * (variant for simply bounded QPs with fixed matrices). + * + */ + + +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define S_FUNCTION_NAME qpOASES_QProblemB /**< Name of the S function. */ +#define S_FUNCTION_LEVEL 2 /**< S function level. */ + +#define MDL_START /**< Activate call to mdlStart. */ + +#include "simstruc.h" + + +/* SETTINGS */ +#define SAMPLINGTIME -1 /**< Sampling time. */ +#define NCONTROLINPUTS 2 /**< Number of control inputs. */ +#define NWSR 100 /**< Maximum number of working set recalculations. */ + + +static void mdlInitializeSizes (SimStruct *S) /* Init sizes array */ +{ + int nU = NCONTROLINPUTS; + + /* Specify the number of continuous and discrete states */ + ssSetNumContStates(S, 0); + ssSetNumDiscStates(S, 0); + + /* Specify the number of intput ports */ + if ( !ssSetNumInputPorts(S, 4) ) + return; + + /* Specify the number of output ports */ + if ( !ssSetNumOutputPorts(S, 4) ) + return; + + /* Specify dimension information for the input ports */ + ssSetInputPortVectorDimension(S, 0, DYNAMICALLY_SIZED); /* H */ + ssSetInputPortVectorDimension(S, 1, DYNAMICALLY_SIZED); /* g */ + ssSetInputPortVectorDimension(S, 2, DYNAMICALLY_SIZED); /* lb */ + ssSetInputPortVectorDimension(S, 3, DYNAMICALLY_SIZED); /* ub */ + + /* Specify dimension information for the output ports */ + ssSetOutputPortVectorDimension(S, 0, 1 ); /* fval */ + ssSetOutputPortVectorDimension(S, 1, nU ); /* uOpt */ + ssSetOutputPortVectorDimension(S, 2, 1 ); /* exitflag */ + ssSetOutputPortVectorDimension(S, 3, 1 ); /* iter */ + + /* Specify the direct feedthrough status */ + ssSetInputPortDirectFeedThrough(S, 0, 1); + ssSetInputPortDirectFeedThrough(S, 1, 1); + ssSetInputPortDirectFeedThrough(S, 2, 1); + ssSetInputPortDirectFeedThrough(S, 3, 1); + + /* One sample time */ + ssSetNumSampleTimes(S, 1); + + /* global variables: + * 0: problem + * 1: H + * 2: g + * 3: lb + * 4: ub + * 5: count + */ + + /* Specify the size of the block's pointer work vector */ + ssSetNumPWork(S, 6); +} + + +#if defined(MATLAB_MEX_FILE) + +#define MDL_SET_INPUT_PORT_DIMENSION_INFO +#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO + +static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +#endif + + +static void mdlInitializeSampleTimes(SimStruct *S) +{ + ssSetSampleTime(S, 0, SAMPLINGTIME); + ssSetOffsetTime(S, 0, 0.0); +} + + +static void mdlStart(SimStruct *S) +{ + USING_NAMESPACE_QPOASES + + int nU = NCONTROLINPUTS; + int size_H, size_g, size_lb, size_ub; + int nV; + + QProblemB* problem; + real_t* count; + + + /* get block inputs dimensions */ + size_H = ssGetInputPortWidth(S, 0); + size_g = ssGetInputPortWidth(S, 1); + size_lb = ssGetInputPortWidth(S, 2); + size_ub = ssGetInputPortWidth(S, 3); + + + /* dimension checks */ + nV = size_g; + + if ( NWSR < 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Maximum number of iterations must not be negative!" ); + #endif + #endif + return; + } + + if ( nV <= 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_H != nV*nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( ( nU < 1 ) || ( nU > nV ) ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_lb != nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_ub != nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + + /* allocate QProblemB object */ + problem = new QProblemB( nV ); + if ( problem == 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Unable to create QProblemB object!" ); + #endif + #endif + return; + } + + Options problemOptions; + problemOptions.setToMPC(); + problem->setOptions( problemOptions ); + + #ifndef __DEBUG__ + problem->setPrintLevel( PL_LOW ); + #endif + #ifdef __SUPPRESSANYOUTPUT__ + problem->setPrintLevel( PL_NONE ); + #endif + #ifdef __DSPACE__ + problem->setPrintLevel( PL_NONE ); + #endif + + ssGetPWork(S)[0] = (void *) problem; + + /* allocate memory for QP data ... */ + ssGetPWork(S)[1] = (void *) calloc( size_H, sizeof(real_t) ); /* H */ + ssGetPWork(S)[2] = (void *) calloc( size_g, sizeof(real_t) ); /* g */ + ssGetPWork(S)[3] = (void *) calloc( size_lb, sizeof(real_t) ); /* lb */ + ssGetPWork(S)[4] = (void *) calloc( size_ub, sizeof(real_t) ); /* ub */ + ssGetPWork(S)[5] = (void *) calloc( 1, sizeof(real_t) ); /* count */ + + /* reset counter */ + count = (real_t *) ssGetPWork(S)[5]; + count[0] = 0.0; +} + + +static void mdlOutputs(SimStruct *S, int_T tid) +{ + USING_NAMESPACE_QPOASES + + int i; + int nV; + returnValue status; + + int nWSR = NWSR; + int nU = NCONTROLINPUTS; + + InputRealPtrsType in_H, in_g, in_lb, in_ub; + + QProblemB* problem; + real_t *H, *g, *lb, *ub, *count; + + real_t *xOpt; + + real_T *out_objVal, *out_uOpt, *out_status, *out_nWSR; + + + /* get pointers to block inputs ... */ + in_H = ssGetInputPortRealSignalPtrs(S, 0); + in_g = ssGetInputPortRealSignalPtrs(S, 1); + in_lb = ssGetInputPortRealSignalPtrs(S, 2); + in_ub = ssGetInputPortRealSignalPtrs(S, 3); + + /* ... and to the QP data */ + problem = (QProblemB *) ssGetPWork(S)[0]; + + H = (real_t *) ssGetPWork(S)[1]; + g = (real_t *) ssGetPWork(S)[2]; + lb = (real_t *) ssGetPWork(S)[3]; + ub = (real_t *) ssGetPWork(S)[4]; + + count = (real_t *) ssGetPWork(S)[5]; + + + /* setup QP data */ + nV = ssGetInputPortWidth(S, 1); /* nV = size_g */ + + for ( i=0; iinit( H,g,lb,ub, nWSR,0 ); + problem->getPrimalSolution( xOpt ); + } + else + { + /* solve neighbouring QP using hotstart technique */ + status = problem->hotstart( g,lb,ub, nWSR,0 ); + if ( ( status != SUCCESSFUL_RETURN ) && ( status != RET_MAX_NWSR_REACHED ) ) + { + /* if an error occurs, reset problem data structures ... */ + problem->reset( ); + + /* ... and initialise/solve again with remaining number of iterations. */ + int nWSR_retry = NWSR-nWSR; + status = problem->init( H,g,lb,ub, nWSR_retry,0 ); + nWSR += nWSR_retry; + } + + /* obtain optimal solution */ + problem->getPrimalSolution( xOpt ); + } + + /* generate block output: status information ... */ + out_objVal = ssGetOutputPortRealSignal(S, 0); + out_uOpt = ssGetOutputPortRealSignal(S, 1); + out_status = ssGetOutputPortRealSignal(S, 2); + out_nWSR = ssGetOutputPortRealSignal(S, 3); + + out_objVal[0] = ((real_T) problem->getObjVal( )); + + for ( i=0; ireset( ); + + int i; + for ( i=0; i<6; ++i ) + { + if ( ssGetPWork(S)[i] != 0 ) + free( ssGetPWork(S)[i] ); + } +} + + +#ifdef MATLAB_MEX_FILE +#include "simulink.c" +#else +#include "cg_sfun.h" +#endif + + +#ifdef __cplusplus +} +#endif + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_SQProblem.cpp b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_SQProblem.cpp new file mode 100644 index 00000000000..533d07a4cda --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/interfaces/simulink/qpOASES_SQProblem.cpp @@ -0,0 +1,460 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2014 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file interfaces/simulink/qpOASES_SQProblem.cpp + * \author Hans Joachim Ferreau (thanks to Aude Perrin) + * \version 3.0 + * \date 2007-2014 + * + * Interface for Simulink(R) that enables to call qpOASES as a S function + * (variant for QPs with varying matrices). + * + */ + + +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define S_FUNCTION_NAME qpOASES_SQProblem /**< Name of the S function. */ +#define S_FUNCTION_LEVEL 2 /**< S function level. */ + +#define MDL_START /**< Activate call to mdlStart. */ + +#include "simstruc.h" + + +/* SETTINGS */ +#define SAMPLINGTIME -1 /**< Sampling time. */ +#define NCONTROLINPUTS 2 /**< Number of control inputs. */ +#define NWSR 100 /**< Maximum number of working set recalculations. */ + + +static void mdlInitializeSizes (SimStruct *S) /* Init sizes array */ +{ + int nU = NCONTROLINPUTS; + + /* Specify the number of continuous and discrete states */ + ssSetNumContStates(S, 0); + ssSetNumDiscStates(S, 0); + + /* Specify the number of intput ports */ + if ( !ssSetNumInputPorts(S, 7) ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Invalid number of input ports!" ); + #endif + #endif + return; + } + + /* Specify the number of output ports */ + if ( !ssSetNumOutputPorts(S, 4) ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Invalid number of output ports!" ); + #endif + #endif + return; + } + + /* Specify dimension information for the input ports */ + ssSetInputPortVectorDimension(S, 0, DYNAMICALLY_SIZED); /* H */ + ssSetInputPortVectorDimension(S, 1, DYNAMICALLY_SIZED); /* g */ + ssSetInputPortVectorDimension(S, 2, DYNAMICALLY_SIZED); /* A */ + ssSetInputPortVectorDimension(S, 3, DYNAMICALLY_SIZED); /* lb */ + ssSetInputPortVectorDimension(S, 4, DYNAMICALLY_SIZED); /* ub */ + ssSetInputPortVectorDimension(S, 5, DYNAMICALLY_SIZED); /* lbA */ + ssSetInputPortVectorDimension(S, 6, DYNAMICALLY_SIZED); /* ubA */ + + /* Specify dimension information for the output ports */ + ssSetOutputPortVectorDimension(S, 0, 1 ); /* fval */ + ssSetOutputPortVectorDimension(S, 1, nU ); /* uOpt */ + ssSetOutputPortVectorDimension(S, 2, 1 ); /* exitflag */ + ssSetOutputPortVectorDimension(S, 3, 1 ); /* iter */ + + /* Specify the direct feedthrough status */ + ssSetInputPortDirectFeedThrough(S, 0, 1); + ssSetInputPortDirectFeedThrough(S, 1, 1); + ssSetInputPortDirectFeedThrough(S, 2, 1); + ssSetInputPortDirectFeedThrough(S, 3, 1); + ssSetInputPortDirectFeedThrough(S, 4, 1); + ssSetInputPortDirectFeedThrough(S, 5, 1); + ssSetInputPortDirectFeedThrough(S, 6, 1); + + /* One sample time */ + ssSetNumSampleTimes(S, 1); + + /* global variables: + * 0: problem + * 1: H + * 2: g + * 3: A + * 4: lb + * 5: ub + * 6: lbA + * 7: ubA + * 8: count + */ + + /* Specify the size of the block's pointer work vector */ + ssSetNumPWork(S, 9); +} + + +#if defined(MATLAB_MEX_FILE) + +#define MDL_SET_INPUT_PORT_DIMENSION_INFO +#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO + +static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +#endif + + +static void mdlInitializeSampleTimes(SimStruct *S) +{ + ssSetSampleTime(S, 0, SAMPLINGTIME); + ssSetOffsetTime(S, 0, 0.0); +} + + +static void mdlStart(SimStruct *S) +{ + USING_NAMESPACE_QPOASES + + int nU = NCONTROLINPUTS; + int size_H, size_g, size_A, size_lb, size_ub, size_lbA, size_ubA; + int nV, nC; + + SQProblem* problem; + real_t* count; + + + /* get block inputs dimensions */ + size_H = ssGetInputPortWidth(S, 0); + size_g = ssGetInputPortWidth(S, 1); + size_A = ssGetInputPortWidth(S, 2); + size_lb = ssGetInputPortWidth(S, 3); + size_ub = ssGetInputPortWidth(S, 4); + size_lbA = ssGetInputPortWidth(S, 5); + size_ubA = ssGetInputPortWidth(S, 6); + + + /* dimension checks */ + nV = size_g; + nC = (int) ( ((real_t) size_A) / ((real_t) nV) ); + + if ( NWSR < 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Maximum number of iterations must not be negative!" ); + #endif + #endif + return; + } + + if ( nV <= 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_H != nV*nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( ( nU < 1 ) || ( nU > nV ) ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Invalid number of control inputs!" ); + #endif + #endif + return; + } + + if ( size_lb != nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_ub != nV ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_lbA != nC ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + if ( size_ubA != nC ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" ); + #endif + #endif + return; + } + + + /* allocate QProblem object */ + problem = new SQProblem( nV,nC ); + if ( problem == 0 ) + { + #ifndef __DSPACE__ + #ifndef __XPCTARGET__ + mexErrMsgTxt( "ERROR (qpOASES): Unable to create QProblem object!" ); + #endif + #endif + return; + } + + Options problemOptions; + problemOptions.setToMPC(); + problem->setOptions( problemOptions ); + + #ifndef __DEBUG__ + problem->setPrintLevel( PL_LOW ); + #endif + #ifdef __SUPPRESSANYOUTPUT__ + problem->setPrintLevel( PL_NONE ); + #endif + #ifdef __DSPACE__ + problem->setPrintLevel( PL_NONE ); + #endif + + ssGetPWork(S)[0] = (void *) problem; + + /* allocate memory for QP data ... */ + ssGetPWork(S)[1] = (void *) calloc( size_H, sizeof(real_t) ); /* H */ + ssGetPWork(S)[2] = (void *) calloc( size_g, sizeof(real_t) ); /* g */ + ssGetPWork(S)[3] = (void *) calloc( size_A, sizeof(real_t) ); /* A */ + ssGetPWork(S)[4] = (void *) calloc( size_lb, sizeof(real_t) ); /* lb */ + ssGetPWork(S)[5] = (void *) calloc( size_ub, sizeof(real_t) ); /* ub */ + ssGetPWork(S)[6] = (void *) calloc( size_lbA, sizeof(real_t) ); /* lbA */ + ssGetPWork(S)[7] = (void *) calloc( size_ubA, sizeof(real_t) ); /* ubA */ + ssGetPWork(S)[8] = (void *) calloc( 1, sizeof(real_t) ); /* count */ + + /* reset counter */ + count = (real_t *) ssGetPWork(S)[8]; + count[0] = 0.0; +} + + + +static void mdlOutputs(SimStruct *S, int_T tid) +{ + USING_NAMESPACE_QPOASES + + int i; + int nV, nC; + returnValue status; + + int nWSR = NWSR; + int nU = NCONTROLINPUTS; + + InputRealPtrsType in_H, in_g, in_A, in_lb, in_ub, in_lbA, in_ubA; + + SQProblem* problem; + real_t *H, *g, *A, *lb, *ub, *lbA, *ubA, *count; + + real_t *xOpt; + + real_T *out_objVal, *out_uOpt, *out_status, *out_nWSR; + + + /* get pointers to block inputs ... */ + in_H = ssGetInputPortRealSignalPtrs(S, 0); + in_g = ssGetInputPortRealSignalPtrs(S, 1); + in_A = ssGetInputPortRealSignalPtrs(S, 2); + in_lb = ssGetInputPortRealSignalPtrs(S, 3); + in_ub = ssGetInputPortRealSignalPtrs(S, 4); + in_lbA = ssGetInputPortRealSignalPtrs(S, 5); + in_ubA = ssGetInputPortRealSignalPtrs(S, 6); + + + /* ... and to the QP data */ + problem = (SQProblem *) ssGetPWork(S)[0]; + + H = (real_t *) ssGetPWork(S)[1]; + g = (real_t *) ssGetPWork(S)[2]; + A = (real_t *) ssGetPWork(S)[3]; + lb = (real_t *) ssGetPWork(S)[4]; + ub = (real_t *) ssGetPWork(S)[5]; + lbA = (real_t *) ssGetPWork(S)[6]; + ubA = (real_t *) ssGetPWork(S)[7]; + + count = (real_t *) ssGetPWork(S)[8]; + + + /* setup QP data */ + nV = ssGetInputPortWidth(S, 1); /* nV = size_g */ + nC = (int) ( ((real_t) ssGetInputPortWidth(S, 2)) / ((real_t) nV) ); /* nC = size_A / size_g */ + + for ( i=0; iinit( H,g,A,lb,ub,lbA,ubA, nWSR,0 ); + problem->getPrimalSolution( xOpt ); + } + else + { + /* solve neighbouring QP using hotstart technique */ + status = problem->hotstart( H,g,A,lb,ub,lbA,ubA, nWSR,0 ); + if ( ( status != SUCCESSFUL_RETURN ) && ( status != RET_MAX_NWSR_REACHED ) ) + { + /* if an error occurs, reset problem data structures ... */ + problem->reset( ); + + /* ... and initialise/solve again with remaining number of iterations. */ + int nWSR_retry = NWSR-nWSR; + status = problem->init( H,g,A,lb,ub,lbA,ubA, nWSR_retry,0 ); + nWSR += nWSR_retry; + } + + /* obtain optimal solution */ + problem->getPrimalSolution( xOpt ); + } + + /* generate block output: status information ... */ + out_objVal = ssGetOutputPortRealSignal(S, 0); + out_uOpt = ssGetOutputPortRealSignal(S, 1); + out_status = ssGetOutputPortRealSignal(S, 2); + out_nWSR = ssGetOutputPortRealSignal(S, 3); + + out_objVal[0] = ((real_T) problem->getObjVal( )); + + for ( i=0; ireset( ); + + int i; + for ( i=0; i<9; ++i ) + { + if ( ssGetPWork(S)[i] != 0 ) + free( ssGetPWork(S)[i] ); + } +} + + +#ifdef MATLAB_MEX_FILE +#include "simulink.c" +#else +#include "cg_sfun.h" +#endif + + +#ifdef __cplusplus +} +#endif + + +/* + * end of file + */ diff --git a/3rdparty/qpOASES/qpOASES-3.0/libs/libqpOASES.so b/3rdparty/qpOASES/qpOASES-3.0/libs/libqpOASES.so new file mode 120000 index 00000000000..6b42ca6417a --- /dev/null +++ b/3rdparty/qpOASES/qpOASES-3.0/libs/libqpOASES.so @@ -0,0 +1 @@ +libqpOASES.so.3.0 \ No newline at end of file diff --git a/3rdparty/qpOASES/qpOASES-3.0/libs/libqpOASES.so.3.0 b/3rdparty/qpOASES/qpOASES-3.0/libs/libqpOASES.so.3.0 new file mode 100755 index 0000000000000000000000000000000000000000..363fa77a0367dd7857020474fa0ccfd668b2b2a4 GIT binary patch literal 1269403 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