Skip to content

Set of constraints raises Error #702

Closed

Description

@ThomasGiavasopoulos

I am using the python optimal control library to optimise the trajectory of a 2D rocket. Please find attached a minimum reproducible sample code of the optimisation process of the problem. Whenever I am trying to set constraints for only some of the states, I get the error described after the minimum reproducible example. Is there an appropriate way to define multiple separate constraints passed in the "constraints= [..., ..., ...]" argument of the solve.ocp() function? Also, instead of using range -np.inf to np.inf for state parameters that I do not want to bound, is there a value that makes the code ignore the specific state parameter constraints?

T_max_Single = 7607000/9

g = 9.81 
m = 114239.00
k = 18.74
I = 16071705.59

import numpy as np
import math
import control as ct
import control.optimal as opt
import matplotlib.pyplot as plt
import logging
import time
import os
plt.style.use("default")
from IPython.display import display
from colorama import *
import sympy as s
from scipy.integrate import odeint


#Definition of the states
def rocket_update(t, x, u, params):
        
    xpos = x[0] 
    U = x[1] 
    z = x[2] 
    W = x[3] 
    θ = x[4] 
    q = x[5] 
    
    T = u[0]
    a = u[1]

    # Return the derivative of the state
    dydt = np.array([U,
            T*np.cos(θ-a)/m, 
            W,
            T*np.sin(θ-a)/m-g,
            q,
            T*k*np.sin(a)/I])
    
    return(dydt)

def rocket_output(t, x, u, params):
    return x                            # return (full state)



Tf = 8



# Define the rocket movement dynamics as an input/output system
rocket = ct.NonlinearIOSystem(
    rocket_update, rocket_output, states=6, name='rocket',
    inputs=("T", "α"), outputs=("x", "U", "z", "W", "θ", "q")) 

# Define the time horizon (and spacing) for the optimization
horizon = np.linspace(0, Tf, Tf, endpoint=True)                                        #############IMPORTANT

# Provide an intial guess (will be extended to entire horizon)
bend_left = [T_max_Single, 0.01]          # slight left veer                     #############IMPORTANT


# Optimal Control Problem
Initial_x = 0 #m
Final_x =  5 #m

Initial_z =  0 #m
Final_z = 200 #m

Initial_θ = np.pi/2 #m
Final_θ = np.pi/3 #m

Final_Thrust = T_max_Single

x0 = [Initial_x, 0, Initial_z, 0, Initial_θ, 0]; u0 = [bend_left[0], bend_left[1]]
xf = [Final_x, 0, Final_z, 0, Final_θ, 0]; uf = [Final_Thrust, 0]

#T_max_Single
Min_T = 1 * T_max_Single
Max_T = 9 * T_max_Single
a_min = -20* np.pi/180
a_max = 20* np.pi/180

# Approach 3: terminal constraints
#
# We can also remove the cost function on the state and replace it
# with a terminal *constraint* on the state.  If a solution is found,
# it guarantees we get to exactly the final state.
#
print("Initialisation of optimisation")    
# print("Checkpoint_1")

# Input cost and terminal constraints
R = np.diag([0, 0])                 # minimize applied inputs
cost3 = opt.quadratic_cost(rocket, np.zeros((6,6)), R, u0=uf)

con1 = [ opt.input_range_constraint(rocket, [Min_T, a_min], [Max_T, a_max]) ]

terminal = [ opt.state_range_constraint(rocket, [Final_x, -np.inf, Final_z, -np.inf, -np.inf, -np.inf],
                                                [Final_x, np.inf, Final_z, np.inf, np.inf, np.inf]) ]


# Reset logging to its default values
logging.basicConfig(
    level=logging.DEBUG, filename="./steering-terminal_constraint.log",
    filemode='w', force=True)

# Compute the optimal control
start_time = time.process_time()
result3 = opt.solve_ocp(
    rocket, horizon, x0, cost3, con1,          
    terminal_constraints=terminal, initial_guess=bend_left, log=False, method="trust-constr",
    options={'eps': 0.01})

print("* Total time = %5g seconds\n" % (time.process_time() - start_time))

Error:

/opt/anaconda3/lib/python3.8/site-packages/scipy/optimize/_constraints.py:386: OptimizeWarning: At least one constraint is unbounded above and below. Such constraints are ignored.
  warn("At least one constraint is unbounded above and below. Such "
/opt/anaconda3/lib/python3.8/site-packages/scipy/optimize/_constraints.py:432: OptimizeWarning: Equality and inequality constraints are specified in the same element of the constraint list. For efficient use with this method, equality and inequality constraints should be specified in separate elements of the constraint list. 
  warn("Equality and inequality constraints are specified in the same "

Activity

  1. murrayrm commented on Feb 19, 2022

    @murrayrm
    Member

    A couple of issues that might be relevant:

    • You are using input_range_constraints to constrain some of the inputs and not others. Depending on the optimizer, this might now work (this is the first warning you are getting). You may need to use input_poly_constraints to just constrain the inputs that you care about.
    • You are using the method keyword in solve_ocp, but there is no such keyword. You want to use minimize_method (and minimize_options). This one is tricky because there is no warning (I found it because I have put in a warning in a PR that I am working on).
  2. ThomasGiavasopoulos commented on Feb 23, 2022

    @ThomasGiavasopoulos
    Author

    Thank you very much. The second comment described a keyword issue in my uploaded code, which should be fixed.

    Regarding your first comment, is there an example where the constraint structures are used in practice?

  3. murrayrm commented on Feb 23, 2022

    @murrayrm
    Member

    This is not a very good answer, but you can find some examples in the unit test code: control/tests/optimal_test.py.

  4. ThomasGiavasopoulos commented on Feb 23, 2022

    @ThomasGiavasopoulos
    Author

    Thank you very much! I will be closing the issue now. In case there is any example of use of these constraints in similar examples, I will be delighted to learn about it.

  5. ThomasGiavasopoulos commented on Feb 24, 2022

    @ThomasGiavasopoulos
    Author

    I am reopening this issue since I have now improved my opt.solve_ocp() command and wish to fully comply with the documentation of the control library which is otherwise producing results very reliably. As described above, I get the same error messages about the constraints, but the "SLSQP" solver solves correctly. I am using SLSQP solver since my constraints are linear.

    This is the part of the code that has changed:

    con1 = [ opt.input_range_constraint(rocket, [Min_T, a_min], [Max_T, a_max]) ]
    
    terminal = [ opt.state_range_constraint(rocket, [Final_x, -np.inf, Final_z, -np.inf, -np.inf, -np.inf],
                                                                                     [Final_x, np.inf, Final_z, np.inf, np.inf, np.inf]) ]
    result = opt.solve_ocp(
        rocket, horizon, x0, cost, con1, terminal_constraints=terminal,
        initial_guess=bend_left, log=False, minimize_method="SLSQP",
        minimize_options={'ftol': 0.000001, 'eps': np.finfo(float).eps, "maxiter": 500, "disp":True})
    

    And this is the error message:

    /opt/anaconda3/lib/python3.8/site-packages/scipy/optimize/_constraints.py:386: OptimizeWarning: At least one constraint is unbounded above and below. Such constraints are ignored.
      warn("At least one constraint is unbounded above and below. Such "
    /opt/anaconda3/lib/python3.8/site-packages/scipy/optimize/_constraints.py:432: OptimizeWarning: Equality and inequality constraints are specified in the same element of the constraint list. For efficient use with this method, equality and inequality constraints should be specified in separate elements of the constraint list. 
      warn("Equality and inequality constraints are specified in the same "
    

    How can I correctly define multiple constraints on inputs only and then on states only, in the form: input_constraint_1, input_constraint_2, ... input_constraint_n , state_constraint_1, state_constraint_2, ..., state_constraint_n, and then pass them into the opt.solve_ocp().

    I am attempting to promote this excellent solver in my thesis, that is the reason for my need to fully comply with the "grammar" structure of the library.

    Thank you for your time.

  6. self-assigned this
    on Mar 19, 2022
  7. added this to the 0.9.2 milestone on Mar 19, 2022
  8. murrayrm commented on Mar 20, 2022

    @murrayrm
    Member

    The following should work

    # Reformulation
    A = np.array([
        [ 1, 0,  0, 0, 0, 0],
        [-1, 0,  0, 0, 0, 0],
        [ 0, 0,  1, 0, 0, 0],
        [ 0, 0, -1, 0, 0, 0],
    ])
    b = np.array([Final_x, -Final_x, Final_z, -Final_z])
    term_con2 = opt.state_poly_constraint(rocket, A, b)
    
    result2 = opt.solve_ocp(
        rocket, horizon, x0, cost3, con1, terminal_constraints=term_con2,
        initial_guess=bend_left, log=False, minimize_method="SLSQP",
        return_x = True,
        minimize_options={
            'ftol': 0.000001, 'eps': np.finfo(float).eps,
            "maxiter": 500, "disp":True})
    print("* Final state:", result2.states[:, -1])
    

    The output that I get (using a slightly newer devleopment version of the code, so some details may be different) is:

    Optimization terminated successfully    (Exit mode 0)
                Current function value: 0.0
                Iterations: 76
                Function evaluations: 1628
                Gradient evaluations: 76
    Summary statistics:
    * Cost function calls: 1628
    * Constraint calls: 1722
    * System simulations: 2937
    * Final cost: 0.0
    * Final state: [ 5.00000044e+00  2.20695572e+01  2.00000000e+02  2.54755631e+01
      5.57648576e-01 -1.04469522e-01]
    

    I think this addresses the issue. Re-open is not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions