Пример #1
0
    def set_contacts(self,
                     contact_points,
                     contact_normals,
                     mu,
                     regularization=1e-5):
        # compute matrix A, which maps the force generator coefficients into the centroidal wrench
        (self.A,
         self.G4) = compute_centroidal_cone_generators(contact_points,
                                                       contact_normals, mu)

        # since the size of the problem may have changed we need to recreate the solver and all the problem matrices/vectors
        self.n = contact_points.shape[0] * 4 + 1
        self.qpOasesSolver = SQProblem(self.n, self.m_in)
        #, HessianType.SEMIDEF);
        self.qpOasesSolver.setOptions(self.options)
        self.Hess = INITIAL_HESSIAN_REGULARIZATION * np.identity(self.n)
        self.grad = np.ones(self.n) * regularization
        self.grad[-1] = 1.0
        self.constrMat = np.zeros((self.m_in, self.n))
        self.constrMat[:, :-1] = self.A
        self.constrMat[:3, -1] = self.mass * self.v
        self.constrMat[3:, -1] = self.mass * np.cross(self.c0, self.v)
        self.lb = np.zeros(self.n)
        self.lb[-1] = -1e100
        self.ub = np.array(self.n * [
            1e100,
        ])
        self.x = np.zeros(self.n)
        self.y = np.zeros(self.n + self.m_in)
        self.initialized = False
    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)
Пример #3
0
    def fit(self, X):
        q, n = len(self.alphas), X.shape[0]
        self.X = X
        if self.kernel == 'gauss':
            H = self.kernel_fun(X, gamma=self.gamma)
        else:
            H = self.kernel_fun(X, X)

        H = 1 / 2 * (H + np.transpose(H))
        H = repmat(H, q, q)
        g = np.zeros(q * n)
        A = np.zeros((q, q * n))
        lbA = np.ones(q)
        lb = np.zeros(q * n)
        ub = np.ones(q * n)
        for i in range(q):
            start = i * n + 1
            end = start + n - 1
            ub[start:end] = 1 / (n * (1 - self.alphas[i]))
            A[i, start:end] = 1

        qp = QProblem(q * n, q)

        if not self.verbose:
            options = Options()
            options.printLevel = PrintLevel.NONE
            qp.setOptions(options)
        suc = qp.init(H, g, A, lb, ub, lbA, lbA, self.max_iter)
        if suc == ReturnValue.MAX_NWSR_REACHED:
            msg = "qPOASES reached the maximum number of iterations ({}). ".format(
                self.max_iter)
            msg += "\nThe resulting regions may not be reliable"
            print(msg)

        etas = np.zeros(q * n)
        qp.getPrimalSolution(etas)
        etas = etas.reshape(q, n)
        etastars = etas.sum(axis=0)
        nus = 1 - self.alphas
        SVidx = np.arange(len(etastars))[etastars > self.tol]
        nSV = len(SVidx)
        ub = 1 / n * nus
        rhos = np.zeros(q)
        for j, eta in enumerate(etas):
            choose = np.logical_and(eta > self.tol, eta < ub[j])
            hyperSVidx = np.arange(len(eta))[choose]
            if len(hyperSVidx) == 0:
                hyperSVidx = np.arange(len(eta))[eta > self.tol]
                rhos[j] = max(
                    np.dot(H[hyperSVidx][:, SVidx], etastars[SVidx]) / q)
            else:
                rhos[j] = np.median(
                    np.dot(H[hyperSVidx][:, SVidx], etastars[SVidx]) / q)
        self.rhos = rhos
        self.etastars = etastars
        tmp = np.dot(H[:, SVidx], etastars[SVidx]) / q
        self.rhobounds = tmp.max(), tmp.min()
        return self
Пример #4
0
    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)
Пример #5
0
    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)
    def __init__(self, name, n, m_in, maxIter=1000, verb=1):
        self.name = name
        self.iter = 0
        self.maxIter = maxIter
        self.verb = verb

        self.m_in = m_in
        self.n = n
        self.iter = 0
        self.qpOasesSolver = SQProblem(self.n, self.m_in)
        #, HessianType.SEMIDEF);
        self.options = Options()
        if (self.verb <= 1):
            self.options.printLevel = PrintLevel.NONE
        elif (self.verb == 2):
            self.options.printLevel = PrintLevel.LOW
        elif (self.verb == 3):
            self.options.printLevel = PrintLevel.MEDIUM
        elif (self.verb > 4):
            self.options.printLevel = PrintLevel.DEBUG_ITER
            print("set high print level")
        self.options.enableRegularisation = True
        self.qpOasesSolver.setOptions(self.options)
        self.initialized = False

        self.Hess = np.identity(self.n)
        self.grad = np.zeros(self.n)
        self.x_lb = np.array(self.n * [
            -1e10,
        ])
        self.x_ub = np.array(self.n * [
            1e10,
        ])

        self.B = np.zeros((self.m_in, self.n))
        self.b_ub = np.zeros(self.m_in) + 1e10
        self.b_lb = np.zeros(self.m_in) - 1e10

        self.x = np.zeros(self.n)
Пример #7
0
def qpoases_solve_qp(P,
                     q,
                     G=None,
                     h=None,
                     A=None,
                     b=None,
                     initvals=None,
                     max_wsr=1000):
    """
    Solve a Quadratic Program defined as:

        minimize
            (1/2) * x.T * P * x + q.T * x

        subject to
            G * x <= h
            A * x == b

    using qpOASES <https://projects.coin-or.org/qpOASES>.

    Parameters
    ----------
    P : numpy.array
        Symmetric quadratic-cost matrix.
    q : numpy.array
        Quadratic-cost vector.
    G : numpy.array
        Linear inequality constraint matrix.
    h : numpy.array
        Linear inequality constraint vector.
    A : numpy.array, optional
        Linear equality constraint matrix.
    b : numpy.array, optional
        Linear equality constraint vector.
    initvals : numpy.array, optional
        Warm-start guess vector.
    max_wsr : integer, optional
        Maximum number of Working-Set Recalculations given to qpOASES.

    Returns
    -------
    x : numpy.array
        Solution to the QP, if found, otherwise ``None``.

    Note
    ----
    This function relies on some updates from the standard distribution of
    qpOASES (details below). A fully compatible repository is published at
    <https://github.com/stephane-caron/qpOASES>. (Quick install instructions:
    run ``make`` from the cloned repository, then go to interfaces/python and
    run ``sudo python setup.py install``.)

    Note
    ----
    This function allows empty bounds (lb, ub, lbA or ubA). This was
    provisioned by the C++ API but not by the Python API of qpOASES (as of
    version 3.2.0). Be sure to update the Cython file (qpoases.pyx) to convert
    ``None`` to the null pointer.
    """
    if initvals is not None:
        print("qpOASES: note that warm-start values ignored by wrapper")
    n = P.shape[0]
    lb, ub = None, None
    has_cons = G is not None or A is not None
    if G is not None and A is None:
        C = G
        lb_C = None  # NB:
        ub_C = h
    elif G is None and A is not None:
        C = A
        lb_C = b
        ub_C = b
    elif G is not None and A is not None:
        C = vstack([G, A, A])
        lb_C = hstack([-__infty * ones(h.shape[0]), b, b])
        ub_C = hstack([h, b, b])
    if has_cons:
        qp = QProblem(n, C.shape[0])
        qp.setOptions(options)
        return_value = qp.init(P, q, C, lb, ub, lb_C, ub_C, array([max_wsr]))
        if return_value == ReturnValue.MAX_NWSR_REACHED:
            print("qpOASES reached the maximum number of WSR (%d)" % max_wsr)
    else:
        qp = QProblemB(n)
        qp.setOptions(options)
        qp.init(P, q, lb, ub, max_wsr)
    x_opt = zeros(n)
    ret = qp.getPrimalSolution(x_opt)
    if ret != 0:  # 0 == SUCCESSFUL_RETURN code of qpOASES
        print("qpOASES failed with return code %d" % ret)
    return x_opt
Пример #8
0
    def compute_max_deceleration(self, alpha, maxIter=None, maxTime=100.0):
        start = time.time()
        self.alpha = alpha
        if (self.NO_WARM_START):
            self.qpOasesSolver = SQProblem(self.n, self.m_in)
            self.qpOasesSolver.setOptions(self.options)
            self.initialized = False
        if (maxIter == None):
            maxIter = self.maxIter
        maxActiveSetIter = np.array([maxIter])
        maxComputationTime = np.array(maxTime)
        self.constrUB[:6] = np.dot(self.b, alpha) + self.d
        self.constrLB[:6] = self.constrUB[:6]

        while (True):
            if (not self.initialized):
                self.imode = self.qpOasesSolver.init(self.Hess, self.grad,
                                                     self.constrMat, self.lb,
                                                     self.ub, self.constrLB,
                                                     self.constrUB,
                                                     maxActiveSetIter,
                                                     maxComputationTime)
            else:
                self.imode = self.qpOasesSolver.hotstart(
                    self.grad, self.lb, self.ub, self.constrLB, self.constrUB,
                    maxActiveSetIter, maxComputationTime)
            if (self.imode == 0):
                self.initialized = True
            if (self.imode == 0
                    or self.imode == PyReturnValue.INIT_FAILED_INFEASIBILITY or
                    self.imode == PyReturnValue.HOTSTART_STOPPED_INFEASIBILITY
                    or self.Hess[0, 0] >= MAX_HESSIAN_REGULARIZATION):
                break
            self.initialized = False
            self.Hess *= 10.0
            maxActiveSetIter = np.array([maxIter])
            maxComputationTime = np.array(maxTime)
            if (self.verb > -1):
                print "[%s] WARNING %s. Increasing Hessian regularization to %f" % (
                    self.name, qpOasesSolverMsg(self.imode), self.Hess[0, 0])

        self.qpTime = maxComputationTime
        self.iter = 1 + maxActiveSetIter[0]
        if (self.imode == 0):
            self.qpOasesSolver.getPrimalSolution(self.x)
            self.qpOasesSolver.getDualSolution(self.y)

            if ((self.x < self.lb - self.INEQ_VIOLATION_THR).any()):
                self.initialized = False
                raise ValueError("[%s] ERROR lower bound violated" %
                                 (self.name) + str(self.x) + str(self.lb))
            if ((self.x > self.ub + self.INEQ_VIOLATION_THR).any()):
                self.initialized = False
                raise ValueError("[%s] ERROR upper bound violated" %
                                 (self.name) + str(self.x) + str(self.ub))
            if ((np.dot(self.constrMat, self.x) >
                 self.constrUB + self.INEQ_VIOLATION_THR).any()):
                self.initialized = False
                raise ValueError(
                    "[%s] ERROR constraint upper bound violated " %
                    (self.name) +
                    str(np.min(np.dot(self.constrMat, self.x) -
                               self.constrUB)))
            if ((np.dot(self.constrMat, self.x) <
                 self.constrLB - self.INEQ_VIOLATION_THR).any()):
                self.initialized = False
                raise ValueError(
                    "[%s] ERROR constraint lower bound violated " %
                    (self.name) +
                    str(np.max(np.dot(self.constrMat, self.x) -
                               self.constrLB)))

            (dx, alpha_min,
             alpha_max) = self.compute_max_deceleration_derivative()
        else:
            self.initialized = False
            dx = 0.0
            alpha_min = 0.0
            alpha_max = 0.0
            if (self.verb > 0):
                print "[%s] ERROR Qp oases %s" % (self.name,
                                                  qpOasesSolverMsg(self.imode))
        if (self.qpTime >= maxTime):
            if (self.verb > 0):
                print "[%s] Max time reached %f after %d iters" % (
                    self.name, self.qpTime, self.iter)
            self.imode = 9
        self.computationTime = time.time() - start
        return (self.imode, self.x[-1], dx, alpha_min, alpha_max)
Пример #9
0
class ComAccLP(object):
    """
    LP solver dedicated to finding the maximum center of mass (CoM) deceleration in a 
    specified direction, subject to the friction cone constraints.
    This is possible thanks to the simplifying assumption that the CoM acceleration
    is going to be parallel to its velocity. This allows us to represent the 3d
    com trajectory by means of a 1d trajectory alpha(t):
        c(t) = c0 + alpha(t) v
        v = c0 / ||c0||
        dc = dAlpha(t) v
        ddc(t) = ddAlpha(t) v
    The operation amounts to solving the following parametric Linear Program:
      minimize      ddAlpha + w sum_i(f_i)
      subject to    A f = a ddAlpha + b alpha + d
                    f >= 0
    where:
      f         are the contact forces generator coefficients
      ddAlpha   is the magnitude of the CoM acceleration
      alpha     is the magnitude of the CoM displacement (with respect to its initial position c0)
      w         regularization parameter
    Given a CoM position (by means of a value of alpha), this class can compute the 
    minimum com acceleration in direction v (i.e. the maximum acceleration in direction -v).
    Since this is a piecewise-linear function of alpha, it can also compute its derivative with respect 
    to alpha, and the boundaries of the alpha-region in which the derivative remains constant.
    """

    NO_WARM_START = False

    name = ""
    # solver name
    n = 0
    # number of variables
    m_in = 0
    # number of constraints (i.e. 6)

    Hess = []
    # Hessian
    grad = []
    # gradient
    A = None
    # constraint matrix multiplying the contact force generators
    b = None
    # constraint vector multiplying the CoM position parameter alpha
    d = None
    # constraint vector

    mass = 0.0
    # robot mass
    g = None
    # 3d gravity vector

    maxIter = 0
    # max number of iterations
    verb = 0
    # verbosity level of the solver (0=min, 2=max)

    iter = 0
    # current iteration number
    computationTime = 0.0
    # total computation time
    qpTime = 0.0
    # time taken to solve the QP(s) only

    initialized = False
    # true if solver has been initialized
    qpOasesSolver = []
    options = []
    # qp oases solver's options

    epsilon = np.sqrt(np.finfo(float).eps)
    INEQ_VIOLATION_THR = 1e-4

    def __init__(self,
                 name,
                 c0,
                 v,
                 contact_points,
                 contact_normals,
                 mu,
                 g,
                 mass,
                 maxIter=10000,
                 verb=0,
                 regularization=1e-5):
        ''' Constructor
            @param c0 Initial CoM position
            @param v Opposite of the direction in which you want to maximize the CoM acceleration (typically that would be
                                                                                                   the CoM velocity direction)
            @param g Gravity vector
            @param regularization Weight of the force minimization, the higher this value, the sparser the solution
        '''
        self.name = name
        self.maxIter = maxIter
        self.verb = verb
        self.m_in = 6
        self.initialized = False
        self.options = Options()
        self.options.setToReliable()
        if (self.verb <= 1):
            self.options.printLevel = PrintLevel.NONE
        elif (self.verb == 2):
            self.options.printLevel = PrintLevel.LOW
        elif (self.verb == 3):
            self.options.printLevel = PrintLevel.MEDIUM
        elif (self.verb > 3):
            self.options.printLevel = PrintLevel.DEBUG_ITER
        self.options.enableRegularisation = False
        self.options.enableEqualities = True
        #        self.qpOasesSolver.printOptions()
        self.b = np.zeros(6)
        self.d = np.empty(6)
        self.c0 = np.empty(3)
        self.v = np.empty(3)
        self.constrUB = np.zeros(self.m_in) + 1e100
        self.constrLB = np.zeros(self.m_in) - 1e100
        self.set_problem_data(c0, v, contact_points, contact_normals, mu, g,
                              mass, regularization)

    def set_com_state(self, c0, v):
        assert np.asarray(
            c0).squeeze().shape[0] == 3, "Com position vector has not size 3"
        assert np.asarray(v).squeeze(
        ).shape[0] == 3, "Com acceleration direction vector has not size 3"
        self.c0 = np.asarray(c0).squeeze()
        self.v = np.asarray(v).squeeze().copy()
        if (norm(v) == 0.0):
            raise ValueError(
                "[%s] Norm of com acceleration direction v is zero!" %
                self.name)
        self.v /= norm(self.v)

        self.constrMat[:3, -1] = self.mass * self.v
        self.constrMat[3:, -1] = self.mass * np.cross(self.c0, self.v)
        self.b[3:] = self.mass * np.cross(v, self.g)
        self.d[:3] = self.mass * self.g
        self.d[3:] = self.mass * np.cross(c0, self.g)

    def set_contacts(self,
                     contact_points,
                     contact_normals,
                     mu,
                     regularization=1e-5):
        # compute matrix A, which maps the force generator coefficients into the centroidal wrench
        (self.A,
         self.G4) = compute_centroidal_cone_generators(contact_points,
                                                       contact_normals, mu)

        # since the size of the problem may have changed we need to recreate the solver and all the problem matrices/vectors
        self.n = contact_points.shape[0] * 4 + 1
        self.qpOasesSolver = SQProblem(self.n, self.m_in)
        #, HessianType.SEMIDEF);
        self.qpOasesSolver.setOptions(self.options)
        self.Hess = INITIAL_HESSIAN_REGULARIZATION * np.identity(self.n)
        self.grad = np.ones(self.n) * regularization
        self.grad[-1] = 1.0
        self.constrMat = np.zeros((self.m_in, self.n))
        self.constrMat[:, :-1] = self.A
        self.constrMat[:3, -1] = self.mass * self.v
        self.constrMat[3:, -1] = self.mass * np.cross(self.c0, self.v)
        self.lb = np.zeros(self.n)
        self.lb[-1] = -1e100
        self.ub = np.array(self.n * [
            1e100,
        ])
        self.x = np.zeros(self.n)
        self.y = np.zeros(self.n + self.m_in)
        self.initialized = False

    def set_problem_data(self,
                         c0,
                         v,
                         contact_points,
                         contact_normals,
                         mu,
                         g,
                         mass,
                         regularization=1e-5):
        assert g.shape[0] == 3, "Gravity vector has not size 3"
        assert mass > 0.0, "Mass is not positive"
        self.mass = mass
        self.g = np.asarray(g).squeeze()
        self.set_contacts(contact_points, contact_normals, mu, regularization)
        self.set_com_state(c0, v)

    def compute_max_deceleration_derivative(self):
        ''' Compute the derivative of the max CoM deceleration (i.e. the solution of the last LP)
            with respect to the parameter alpha (i.e. the CoM position parameter). Moreover, 
            it also computes the bounds within which this derivative is valid (alpha_min, alpha_max).
        '''
        act_set = np.where(self.y[:self.n - 1] != 0.0)[0]
        # indexes of active bound constraints
        n_as = act_set.shape[0]
        if (n_as > self.n - 6):
            raise ValueError(
                "[%s] ERROR Too many active constraints: %d (rather than %d)" %
                (self.name, n_as, self.n - 6))
        if (self.verb > 0 and n_as < self.n - 6):
            print "[%s] INFO Less active constraints than expected: %d (rather than %d)" % (
                self.name, n_as, self.n - 6)
        self.K = np.zeros((n_as + 6, self.n))
        self.k1 = np.zeros(n_as + 6)
        self.k2 = np.zeros(n_as + 6)
        self.K[:n_as, :] = np.identity(self.n)[act_set, :]
        self.K[-6:, :] = self.constrMat
        self.k1[-6:] = self.b
        self.k2[-6:] = self.d
        U, s, VT = np.linalg.svd(self.K)
        rank = (s > EPS).sum()
        K_inv_k1 = np.dot(VT[:rank, :].T,
                          (1.0 / s[:rank]) * np.dot(U[:, :rank].T, self.k1))
        K_inv_k2 = np.dot(VT[:rank, :].T,
                          (1.0 / s[:rank]) * np.dot(U[:, :rank].T, self.k2))
        if (rank < self.n):
            Z = VT[rank:, :].T
            P = np.dot(
                np.dot(Z, np.linalg.inv(np.dot(Z.T, np.dot(self.Hess, Z)))),
                Z.T)
            K_inv_k1 -= np.dot(P, np.dot(self.Hess, K_inv_k1))
            K_inv_k2 -= np.dot(P,
                               np.dot(self.Hess, K_inv_k2) + self.grad)

        # Check that the solution you get by solving the KKT is the same found by the solver
        x_kkt = K_inv_k1 * self.alpha + K_inv_k2
        if (norm(self.x - x_kkt) > 10 * EPS):
            warnings.warn("[%s] ERROR x different from x_kkt. x=" %
                          (self.name) + str(self.x) + "\nx_kkt=" + str(x_kkt) +
                          " " + str(norm(self.x - x_kkt)))
        # store the derivative of the solution w.r.t. the parameter alpha
        dx = K_inv_k1[-1]
        # act_set_mat * alpha >= act_set_vec
        act_set_mat = K_inv_k1[:-1]
        act_set_vec = -K_inv_k2[:-1]
        for i in range(act_set_mat.shape[0]):
            if (abs(act_set_mat[i]) > EPS):
                act_set_vec[i] /= abs(act_set_mat[i])
                act_set_mat[i] /= abs(act_set_mat[i])
        if (act_set_mat * self.alpha < act_set_vec - EPS).any():
            raise ValueError(
                "ERROR: after normalization current alpha violates constraints "
                + str(act_set_mat * self.alpha - act_set_vec))

        ind_pos = np.where(act_set_mat > EPS)[0]
        if (ind_pos.shape[0] > 0):
            alpha_min = np.max(act_set_vec[ind_pos])
        else:
            alpha_min = -1e10
#            warnings.warn("[%s] alpha_min seems unbounded %.7f"%(self.name, np.max(act_set_mat)));

        ind_neg = np.where(act_set_mat < -EPS)[0]
        if (ind_neg.shape[0] > 0):
            alpha_max = np.min(-act_set_vec[ind_neg])
        else:
            alpha_max = 1e10


#            warnings.warn("[%s] alpha_max seems unbounded %.7f"%(self.name, np.min(act_set_mat)));

        if (alpha_min > alpha_max):
            raise ValueError("ERROR alpha_min %.3f > alpha_max %.3f" %
                             (alpha_min, alpha_max))
        return (dx, alpha_min, alpha_max)

    def compute_max_deceleration(self, alpha, maxIter=None, maxTime=100.0):
        start = time.time()
        self.alpha = alpha
        if (self.NO_WARM_START):
            self.qpOasesSolver = SQProblem(self.n, self.m_in)
            self.qpOasesSolver.setOptions(self.options)
            self.initialized = False
        if (maxIter == None):
            maxIter = self.maxIter
        maxActiveSetIter = np.array([maxIter])
        maxComputationTime = np.array(maxTime)
        self.constrUB[:6] = np.dot(self.b, alpha) + self.d
        self.constrLB[:6] = self.constrUB[:6]

        while (True):
            if (not self.initialized):
                self.imode = self.qpOasesSolver.init(self.Hess, self.grad,
                                                     self.constrMat, self.lb,
                                                     self.ub, self.constrLB,
                                                     self.constrUB,
                                                     maxActiveSetIter,
                                                     maxComputationTime)
            else:
                self.imode = self.qpOasesSolver.hotstart(
                    self.grad, self.lb, self.ub, self.constrLB, self.constrUB,
                    maxActiveSetIter, maxComputationTime)
            if (self.imode == 0):
                self.initialized = True
            if (self.imode == 0
                    or self.imode == PyReturnValue.INIT_FAILED_INFEASIBILITY or
                    self.imode == PyReturnValue.HOTSTART_STOPPED_INFEASIBILITY
                    or self.Hess[0, 0] >= MAX_HESSIAN_REGULARIZATION):
                break
            self.initialized = False
            self.Hess *= 10.0
            maxActiveSetIter = np.array([maxIter])
            maxComputationTime = np.array(maxTime)
            if (self.verb > -1):
                print "[%s] WARNING %s. Increasing Hessian regularization to %f" % (
                    self.name, qpOasesSolverMsg(self.imode), self.Hess[0, 0])

        self.qpTime = maxComputationTime
        self.iter = 1 + maxActiveSetIter[0]
        if (self.imode == 0):
            self.qpOasesSolver.getPrimalSolution(self.x)
            self.qpOasesSolver.getDualSolution(self.y)

            if ((self.x < self.lb - self.INEQ_VIOLATION_THR).any()):
                self.initialized = False
                raise ValueError("[%s] ERROR lower bound violated" %
                                 (self.name) + str(self.x) + str(self.lb))
            if ((self.x > self.ub + self.INEQ_VIOLATION_THR).any()):
                self.initialized = False
                raise ValueError("[%s] ERROR upper bound violated" %
                                 (self.name) + str(self.x) + str(self.ub))
            if ((np.dot(self.constrMat, self.x) >
                 self.constrUB + self.INEQ_VIOLATION_THR).any()):
                self.initialized = False
                raise ValueError(
                    "[%s] ERROR constraint upper bound violated " %
                    (self.name) +
                    str(np.min(np.dot(self.constrMat, self.x) -
                               self.constrUB)))
            if ((np.dot(self.constrMat, self.x) <
                 self.constrLB - self.INEQ_VIOLATION_THR).any()):
                self.initialized = False
                raise ValueError(
                    "[%s] ERROR constraint lower bound violated " %
                    (self.name) +
                    str(np.max(np.dot(self.constrMat, self.x) -
                               self.constrLB)))

            (dx, alpha_min,
             alpha_max) = self.compute_max_deceleration_derivative()
        else:
            self.initialized = False
            dx = 0.0
            alpha_min = 0.0
            alpha_max = 0.0
            if (self.verb > 0):
                print "[%s] ERROR Qp oases %s" % (self.name,
                                                  qpOasesSolverMsg(self.imode))
        if (self.qpTime >= maxTime):
            if (self.verb > 0):
                print "[%s] Max time reached %f after %d iters" % (
                    self.name, self.qpTime, self.iter)
            self.imode = 9
        self.computationTime = time.time() - start
        return (self.imode, self.x[-1], dx, alpha_min, alpha_max)

    def getContactForces(self):
        ''' Get the contact forces obtained by solving the last LP '''
        cg = 4
        nContacts = self.G4.shape[1] / cg
        f = np.empty((3, nContacts))
        for i in range(nContacts):
            f[:, i] = np.dot(self.G4[:, cg * i:cg * i + cg],
                             self.x[cg * i:cg * i + cg])
        return f

    def reset(self):
        self.initialized = False
Пример #10
0
    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<xOpt>([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<objVal>[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)
Пример #11
0
def qpoases_solve_qp(P, q, G=None, h=None, A=None, b=None, initvals=None,
                     max_wsr=1000):
    """
    Solve a Quadratic Program defined as:

        minimize
            (1/2) * x.T * P * x + q.T * x

        subject to
            G * x <= h
            A * x == b

    using qpOASES <https://projects.coin-or.org/qpOASES>.

    Parameters
    ----------
    P : numpy.array
        Symmetric quadratic-cost matrix.
    q : numpy.array
        Quadratic-cost vector.
    G : numpy.array
        Linear inequality constraint matrix.
    h : numpy.array
        Linear inequality constraint vector.
    A : numpy.array, optional
        Linear equality constraint matrix.
    b : numpy.array, optional
        Linear equality constraint vector.
    initvals : numpy.array, optional
        Warm-start guess vector.
    max_wsr : integer, optional
        Maximum number of Working-Set Recalculations given to qpOASES.

    Returns
    -------
    x : numpy.array
        Solution to the QP, if found, otherwise ``None``.

    Note
    ----
    This function relies on some updates from the standard distribution of
    qpOASES (details below). A fully compatible repository is published at
    <https://github.com/stephane-caron/qpOASES>. (Quick install instructions:
    run ``make`` from the cloned repository, then go to interfaces/python and
    run ``sudo python setup.py install``.)

    Note
    ----
    This function allows empty bounds (lb, ub, lbA or ubA). This was
    provisioned by the C++ API but not by the Python API of qpOASES (as of
    version 3.2.0). Be sure to update the Cython file (qpoases.pyx) to convert
    ``None`` to the null pointer.
    """
    if initvals is not None:
        print("qpOASES: note that warm-start values ignored by wrapper")
    n = P.shape[0]
    lb, ub = None, None
    has_cons = G is not None or A is not None
    if G is not None and A is None:
        C = G
        lb_C = None  # NB:
        ub_C = h
    elif G is None and A is not None:
        C = vstack([A, A])
        lb_C = h
        ub_C = h
    elif G is not None and A is not None:
        C = vstack([G, A, A])
        lb_C = hstack([-__infty * ones(h.shape[0]), b, b])
        ub_C = hstack([h, b, b])
    if has_cons:
        qp = QProblem(n, C.shape[0])
        qp.setOptions(options)
        return_value = qp.init(P, q, C, lb, ub, lb_C, ub_C, array([max_wsr]))
        if return_value == ReturnValue.MAX_NWSR_REACHED:
            print("qpOASES reached the maximum number of WSR (%d)" % max_wsr)
    else:
        qp = QProblemB(n)
        qp.setOptions(options)
        qp.init(P, q, lb, ub, max_wsr)
    x_opt = zeros(n)
    ret = qp.getPrimalSolution(x_opt)
    if ret != 0:  # 0 == SUCCESSFUL_RETURN code of qpOASES
        print("qpOASES failed with return code %d" % ret)
    return x_opt
Пример #12
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 = np.array([10])
example.init(H, g, A, lb, ub, lbA, ubA, nWSR)

xOpt = np.zeros(2)
example.getPrimalSolution(xOpt)
print("\nxOpt = [ %e, %e ];  objVal = %e\n\n" %
      (xOpt[0], xOpt[1], example.getObjVal()))

# Solve second QP.
nWSR = np.array([10])
Пример #13
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 = np.array([10])
example.init(H, g, A, lb, ub, lbA, ubA, nWSR)


# Solve second QP.
nWSR = np.array([10])

for i in range(100000):
    for j in range(1, 100):
        g_new[0] = i%j
class qpSolver(object):
    """
    Solver for the following QP:
      minimize      0.5 x' H x + g' x
      subject to    b_lb <= B x <= b_ub
                    x_lb <= x   <= x_ub
    """

    NO_WARM_START = False

    name = ""
    # solver name
    n = 0
    # number of variables
    m_in = 0
    # number of equalities/inequalities

    x = []
    # last solution

    Hess = []
    # Hessian
    grad = []
    # gradient
    B = []
    b_ub = []
    b_lb = []
    x_lb = []
    x_ub = []

    maxIter = 0
    # max number of iterations
    verb = 0
    # verbosity level of the solver (0=min, 2=max)
    iter = 0
    # current iteration number
    computationTime = 0.0
    # total computation time
    qpTime = 0.0
    # time taken to solve the QP(s) only

    qpOasesSolver = []
    options = []
    # qp oases solver's options

    def __init__(self, name, n, m_in, maxIter=1000, verb=1):
        self.name = name
        self.iter = 0
        self.maxIter = maxIter
        self.verb = verb

        self.m_in = m_in
        self.n = n
        self.iter = 0
        self.qpOasesSolver = SQProblem(self.n, self.m_in)
        #, HessianType.SEMIDEF);
        self.options = Options()
        if (self.verb <= 1):
            self.options.printLevel = PrintLevel.NONE
        elif (self.verb == 2):
            self.options.printLevel = PrintLevel.LOW
        elif (self.verb == 3):
            self.options.printLevel = PrintLevel.MEDIUM
        elif (self.verb > 4):
            self.options.printLevel = PrintLevel.DEBUG_ITER
            print("set high print level")
        self.options.enableRegularisation = True
        self.qpOasesSolver.setOptions(self.options)
        self.initialized = False

        self.Hess = np.identity(self.n)
        self.grad = np.zeros(self.n)
        self.x_lb = np.array(self.n * [
            -1e10,
        ])
        self.x_ub = np.array(self.n * [
            1e10,
        ])

        self.B = np.zeros((self.m_in, self.n))
        self.b_ub = np.zeros(self.m_in) + 1e10
        self.b_lb = np.zeros(self.m_in) - 1e10

        self.x = np.zeros(self.n)

    ''' Solve the specified quadratic program. If some problem data are not supplied, the last specified
        values are used. By default upper bounds are set to 1e10 and lower bounds to -1e10, while B=0.
    '''

    def solve(self,
              H,
              g,
              x_lb=None,
              x_ub=None,
              B=None,
              b_lb=None,
              b_ub=None,
              maxIter=None,
              maxTime=100.0):
        start = time.time()

        # copy all data to avoid problem with memory alignement with qpOases
        if (type(H) == np.matrix):
            self.Hess = H.A.squeeze()
        else:
            self.Hess = np.copy(H)

        if (type(g) == np.matrix):
            self.grad = g.A.squeeze()
        else:
            self.grad = np.copy(g)

        if (x_lb is not None):
            if (type(x_lb) == np.matrix):
                self.x_lb = x_lb.A.squeeze()
            else:
                self.x_lb = np.copy(x_lb)

        if (x_ub is not None):
            if (type(x_ub) == np.matrix):
                self.x_ub = x_ub.A.squeeze()
            else:
                self.x_ub = np.copy(x_ub)

        if (b_lb is not None):
            if (type(b_lb) == np.matrix):
                self.b_lb = b_lb.A.squeeze()
            else:
                self.b_lb = np.copy(b_lb)

        if (b_ub is not None):
            if (type(b_ub) == np.matrix):
                self.b_ub = b_ub.A.squeeze()
            else:
                self.b_ub = np.copy(b_ub)

        if (B is not None):
            if (type(B) == np.matrix):
                self.B = B.A.squeeze()
            else:
                self.B = np.copy(B)

        if (maxIter == None):
            maxIter = self.maxIter
        maxActiveSetIter = np.array([maxIter])
        maxComputationTime = np.array(maxTime)
        self.imode = self.qpOasesSolver.init(self.Hess, self.grad, self.B,
                                             self.x_lb, self.x_ub, self.b_lb,
                                             self.b_ub, maxActiveSetIter,
                                             maxComputationTime)
        self.qpTime = maxComputationTime
        self.iter = 1 + maxActiveSetIter[0]
        self.qpOasesSolver.getPrimalSolution(self.x)
        self.print_qp_oases_error_message(self.imode, self.name)

        Bx = np.dot(self.B, self.x)
        for i in range(self.m_in):
            if (Bx[i] > b_ub[i] + EPS):
                print("Constraint %d upper bound violated, B*x = %f, b_ub=%f" %
                      (i, Bx[i], b_ub[i]))
            if (Bx[i] < b_lb[i] - EPS):
                print("Constraint %d lower bound violated, B*x = %f, b_lb=%f" %
                      (i, Bx[i], b_lb[i]))

        # termination conditions
        if (self.qpTime >= maxTime):
            if (self.verb > 0):
                print("[%s] Max time reached %f after %d iters" %
                      (self.name, self.qpTime, self.iter))
            self.imode = 9

        self.computationTime = time.time() - start

        return self.x

    def print_qp_oases_error_message(self, imode, solver_name):
        if (imode != 0 and self.verb >= 0):
            if (imode == PyReturnValue.HOTSTART_STOPPED_INFEASIBILITY):
                print("[%s] ERROR Qp oases HOTSTART_STOPPED_INFEASIBILITY" %
                      solver_name)
                # 60
            elif (imode == PyReturnValue.MAX_NWSR_REACHED):
                print("[%s] ERROR Qp oases RET_MAX_NWSR_REACHED" % solver_name)
                # 63
            elif (imode == PyReturnValue.STEPDIRECTION_FAILED_CHOLESKY):
                print("[%s] ERROR Qp oases STEPDIRECTION_FAILED_CHOLESKY" %
                      solver_name)
                # 68
            elif (imode == PyReturnValue.HOTSTART_FAILED_AS_QP_NOT_INITIALISED
                  ):
                print(
                    "[%s] ERROR Qp oases HOTSTART_FAILED_AS_QP_NOT_INITIALISED"
                    % solver_name)
                # 53
            elif (imode == PyReturnValue.INIT_FAILED_INFEASIBILITY):
                print("[%s] ERROR Qp oases INIT_FAILED_INFEASIBILITY" %
                      solver_name)
                # 37
#                    RET_INIT_FAILED_HOTSTART = 36
            elif (imode == PyReturnValue.UNKNOWN_BUG):
                print("[%s] ERROR Qp oases UNKNOWN_BUG" % solver_name)
                # 9
            else:
                print("[%s] ERROR Qp oases %d " % (solver_name, imode))