In acados, a nonzero qp_solver_warm_start setting does not by itself warm-start the first quadratic subproblem of an NLP solve. A separate flag controls that first QP. Once it is enabled, the backend’s warm-start level determines which previous solver values are reused, and another option can select the NLP iterate as the initialization source.
These are three separate choices: which QP is eligible, which backend initialization rule applies, and where its starting values come from. They explain why changing a single integer can have little effect—or a different effect after switching QP solvers.
The first-QP switch applies at the NLP solve boundary
The acados Python interface documents qp_solver_warm_start with a default of zero. Even when that level is raised, the first QP in an NLP solve is initialized at level zero by default. nlp_solver_warm_start_first_qp=True lets the configured warm-start level apply to that first QP as well.
The relevant boundary is the first QP of an NLP solve, rather than only the first QP ever computed by the application. Consider an illustrative NLP solve with more than one QP and a configured warm-start level of two:
| Setting | First QP of the NLP solve | Later QPs in that solve |
|---|---|---|
| First-QP flag is False | Level 0 | Configured level 2 |
| First-QP flag is True | Configured level 2 | Configured level 2 |
This table describes option routing. The values actually available for reuse depend on the stored solver state. For a solve that contains only one QP, the first-QP choice covers that entire solve’s quadratic subproblem.
HPIPM level one has the same effect as zero in acados
The API describes four levels for HPIPM. Their meaning is easiest to see by separating the QP primal variables from equality multipliers and the inequality variables t and lam.
| HPIPM level | Documented initialization in acados |
|---|---|
| 0 | Primal variables and equality multipliers pi start at zero; t and lam follow t0_init |
| 1 | Same effective initialization as level 0 in acados |
| 2 | Start from qp_out, but clip t and lam to at least 0.1 |
| 3 | Use the values in qp_out without that clipping |
The reason for the level-one result is the QP’s delta-space formulation. Although HPIPM’s level-one description retains a primal guess, acados resets the primal increment guess to zero. An increment of zero refers to the optimization variables around the current linearization; it is not a command to move the robot’s joints to zero. The equality and inequality initialization at level one otherwise follows the level-zero rules documented here.
Levels two and three retain more of the existing QP output. Their difference is specific: level two introduces a lower floor for the inequality slack and multiplier initialization, while level three uses the stored values directly. The value 0.1 is part of that numerical initialization rule, not a newly imposed physical constraint on the robot.
The same integer is not a shared backend contract
The acados option is exposed through one property, but its backend meanings differ. The API lists cold, warm and hot starts as levels 0, 1 and 2 for DAQP and qpOASES. OSQP has documented cold and warm settings, 0 and 1. For Clarabel, the property has no effect.
Consequently, an HPIPM configuration using level two carries an HPIPM-specific interpretation of qp_out, t and lam. Moving to another backend means selecting that backend’s supported initialization behavior. Copying the number alone omits the solver-state choice it represented.
This matters in repeated optimization such as the MPC balance-control loop: each new solve has an updated problem, while the solver may also retain values from its previous work. The warm-start options describe how that numerical state enters initialization. Whether it reduces solve time depends on the resulting problem and solver behavior.
Choosing the NLP iterate instead of the previous QP solution
With the first-QP flag enabled, nlp_solver_warm_start_first_qp_from_nlp selects a further distinction. Its default, False, uses the previous QP solution. Setting it to True initializes that first QP using values from the NLP iterate.
Those sources can diverge. In a hypothetical application that updates the NLP’s initial guess between solve calls, choosing the NLP iterate lets that updated guess supply the first-QP initialization. Choosing the previous QP solution selects the other stored source. This is a change in where the starting values originate, alongside the backend-level rules for using them.
The current API limits the from-NLP option to HPIPM with partial condensing at N = qp_solver_partial_cond_N. Its documented condition keeps the condensed horizon equal to the original one. The note uses qp_solver_partial_cond_N, while the horizon property elsewhere on the same page is qp_solver_cond_N; this naming inconsistency needs resolving against the selected acados version when writing configuration code.
When comparing two warm-start configurations, record the backend, warm-start level, first-QP flag and from-NLP flag together. This four-part description distinguishes an HPIPM level change from enabling reuse for the first QP or switching the source of its initial values.
This article analyzes the official API snapshot checked on October 15, 2026 (UTC). It does not report a local solver or robot execution.