acados: update to 0.2.2 (#28821)
* use 0.2.2
* Add mac binaries
* Replace libqpOASES with symlink on larch64
* Add comment to build script
---------
Co-authored-by: Kacper Rączy <gfw.kra@gmail.com>
old-commit-hash: 4c1b8b71d0
beeps
parent
268fb070a8
commit
df3502d8c8
144 changed files with 7256 additions and 3108 deletions
@ -1,3 +1,3 @@ |
|||||||
version https://git-lfs.github.com/spec/v1 |
version https://git-lfs.github.com/spec/v1 |
||||||
oid sha256:2926c48d96e20086823c87899e5d6d834fada0f616916c0edfe0f58c2aa4b555 |
oid sha256:620195ff61aaccf9adf00a66b8acf4e9915a0895d0a86f9f51ec952e44fad70a |
||||||
size 834016 |
size 853776 |
||||||
|
@ -1,3 +1,3 @@ |
|||||||
version https://git-lfs.github.com/spec/v1 |
version https://git-lfs.github.com/spec/v1 |
||||||
oid sha256:8ee2734e9a056573efbf011f34f85be4d76841ad6c152b52bd9aa2ee24a390b7 |
oid sha256:1d9dbeb68b2ac13c884f606a1f6032f399640e0928cecad4c22b700a8d8ae970 |
||||||
size 2010877 |
size 2010877 |
||||||
|
@ -1,3 +1,3 @@ |
|||||||
version https://git-lfs.github.com/spec/v1 |
version https://git-lfs.github.com/spec/v1 |
||||||
oid sha256:30249b5c6d5c14b064ff3bd69d7b0ebc201cd9484c9686181d99610268a59246 |
oid sha256:35783dba64c2d5bbe7e4c98ad01accac56b478b1bf874969ab5c31d7495499a2 |
||||||
size 2290624 |
size 2290624 |
||||||
|
@ -1,3 +1,3 @@ |
|||||||
version https://git-lfs.github.com/spec/v1 |
version https://git-lfs.github.com/spec/v1 |
||||||
oid sha256:d7153b9b69fb15c05a5e04afacc4b69d7b781da96381114390700d504dacd9c3 |
oid sha256:f57eea51f4b91deff47fbf599eedc3eafedd395f23465b5fb24b2148fdaa2859 |
||||||
size 496707 |
size 496707 |
||||||
|
@ -1,3 +1,3 @@ |
|||||||
version https://git-lfs.github.com/spec/v1 |
version https://git-lfs.github.com/spec/v1 |
||||||
oid sha256:f2304f73cd27c821a8cc03cf990b74ca246a6a95bef46d28e2b5d5e6a3132fdb |
oid sha256:c6c78791cfdd841da14266c62a6099d0af53cec348051118f1a70518729aa5ba |
||||||
size 7776232 |
size 8483768 |
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,64 @@ |
|||||||
|
# -*- coding: future_fstrings -*- |
||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
|
||||||
|
|
||||||
|
cdef extern from "acados/sim/sim_common.h": |
||||||
|
ctypedef struct sim_config: |
||||||
|
pass |
||||||
|
|
||||||
|
ctypedef struct sim_opts: |
||||||
|
pass |
||||||
|
|
||||||
|
ctypedef struct sim_in: |
||||||
|
pass |
||||||
|
|
||||||
|
ctypedef struct sim_out: |
||||||
|
pass |
||||||
|
|
||||||
|
|
||||||
|
cdef extern from "acados_c/sim_interface.h": |
||||||
|
|
||||||
|
ctypedef struct sim_plan: |
||||||
|
pass |
||||||
|
|
||||||
|
ctypedef struct sim_solver: |
||||||
|
pass |
||||||
|
|
||||||
|
# out |
||||||
|
void sim_out_get(sim_config *config, void *dims, sim_out *out, const char *field, void *value) |
||||||
|
int sim_dims_get_from_attr(sim_config *config, void *dims, const char *field, void *dims_data) |
||||||
|
|
||||||
|
# opts |
||||||
|
void sim_opts_set(sim_config *config, void *opts_, const char *field, void *value) |
||||||
|
|
||||||
|
# get/set |
||||||
|
void sim_in_set(sim_config *config, void *dims, sim_in *sim_in, const char *field, void *value) |
||||||
|
void sim_solver_set(sim_solver *solver, const char *field, void *value) |
@ -0,0 +1,256 @@ |
|||||||
|
# -*- coding: future_fstrings -*- |
||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
# cython: language_level=3 |
||||||
|
# cython: profile=False |
||||||
|
# distutils: language=c |
||||||
|
|
||||||
|
cimport cython |
||||||
|
from libc cimport string |
||||||
|
# from libc cimport bool as bool_t |
||||||
|
|
||||||
|
cimport acados_sim_solver_common |
||||||
|
cimport acados_sim_solver |
||||||
|
|
||||||
|
cimport numpy as cnp |
||||||
|
|
||||||
|
import os |
||||||
|
from datetime import datetime |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
|
||||||
|
cdef class AcadosSimSolverCython: |
||||||
|
""" |
||||||
|
Class to interact with the acados sim solver C object. |
||||||
|
""" |
||||||
|
|
||||||
|
cdef acados_sim_solver.sim_solver_capsule *capsule |
||||||
|
cdef void *sim_dims |
||||||
|
cdef acados_sim_solver_common.sim_opts *sim_opts |
||||||
|
cdef acados_sim_solver_common.sim_config *sim_config |
||||||
|
cdef acados_sim_solver_common.sim_out *sim_out |
||||||
|
cdef acados_sim_solver_common.sim_in *sim_in |
||||||
|
cdef acados_sim_solver_common.sim_solver *sim_solver |
||||||
|
|
||||||
|
cdef bint solver_created |
||||||
|
|
||||||
|
cdef str model_name |
||||||
|
|
||||||
|
cdef str sim_solver_type |
||||||
|
|
||||||
|
cdef list gettable_vectors |
||||||
|
cdef list gettable_matrices |
||||||
|
cdef list gettable_scalars |
||||||
|
|
||||||
|
def __cinit__(self, model_name): |
||||||
|
|
||||||
|
self.solver_created = False |
||||||
|
|
||||||
|
self.model_name = model_name |
||||||
|
|
||||||
|
# create capsule |
||||||
|
self.capsule = acados_sim_solver.acados_sim_solver_create_capsule() |
||||||
|
|
||||||
|
# create solver |
||||||
|
assert acados_sim_solver.acados_sim_create(self.capsule) == 0 |
||||||
|
self.solver_created = True |
||||||
|
|
||||||
|
# get pointers solver |
||||||
|
self.__get_pointers_solver() |
||||||
|
|
||||||
|
self.gettable_vectors = ['x', 'u', 'z', 'S_adj'] |
||||||
|
self.gettable_matrices = ['S_forw', 'Sx', 'Su', 'S_hess', 'S_algebraic'] |
||||||
|
self.gettable_scalars = ['CPUtime', 'time_tot', 'ADtime', 'time_ad', 'LAtime', 'time_la'] |
||||||
|
|
||||||
|
def __get_pointers_solver(self): |
||||||
|
""" |
||||||
|
Private function to get the pointers for solver |
||||||
|
""" |
||||||
|
# get pointers solver |
||||||
|
self.sim_opts = acados_sim_solver.acados_get_sim_opts(self.capsule) |
||||||
|
self.sim_dims = acados_sim_solver.acados_get_sim_dims(self.capsule) |
||||||
|
self.sim_config = acados_sim_solver.acados_get_sim_config(self.capsule) |
||||||
|
self.sim_out = acados_sim_solver.acados_get_sim_out(self.capsule) |
||||||
|
self.sim_in = acados_sim_solver.acados_get_sim_in(self.capsule) |
||||||
|
self.sim_solver = acados_sim_solver.acados_get_sim_solver(self.capsule) |
||||||
|
|
||||||
|
|
||||||
|
def simulate(self, x=None, u=None, z=None, p=None): |
||||||
|
""" |
||||||
|
Simulate the system forward for the given x, u, z, p and return x_next. |
||||||
|
Wrapper around `solve()` taking care of setting/getting inputs/outputs. |
||||||
|
""" |
||||||
|
if x is not None: |
||||||
|
self.set('x', x) |
||||||
|
if u is not None: |
||||||
|
self.set('u', u) |
||||||
|
if z is not None: |
||||||
|
self.set('z', z) |
||||||
|
if p is not None: |
||||||
|
self.set('p', p) |
||||||
|
|
||||||
|
status = self.solve() |
||||||
|
|
||||||
|
if status == 2: |
||||||
|
print("Warning: acados_sim_solver reached maximum iterations.") |
||||||
|
elif status != 0: |
||||||
|
raise Exception(f'acados_sim_solver for model {self.model_name} returned status {status}.') |
||||||
|
|
||||||
|
x_next = self.get('x') |
||||||
|
return x_next |
||||||
|
|
||||||
|
|
||||||
|
def solve(self): |
||||||
|
""" |
||||||
|
Solve the sim with current input. |
||||||
|
""" |
||||||
|
return acados_sim_solver.acados_sim_solve(self.capsule) |
||||||
|
|
||||||
|
|
||||||
|
def get(self, field_): |
||||||
|
""" |
||||||
|
Get the last solution of the solver. |
||||||
|
|
||||||
|
:param str field: string in ['x', 'u', 'z', 'S_forw', 'Sx', 'Su', 'S_adj', 'S_hess', 'S_algebraic', 'CPUtime', 'time_tot', 'ADtime', 'time_ad', 'LAtime', 'time_la'] |
||||||
|
""" |
||||||
|
field = field_.encode('utf-8') |
||||||
|
|
||||||
|
if field_ in self.gettable_vectors: |
||||||
|
return self.__get_vector(field) |
||||||
|
elif field_ in self.gettable_matrices: |
||||||
|
return self.__get_matrix(field) |
||||||
|
elif field_ in self.gettable_scalars: |
||||||
|
return self.__get_scalar(field) |
||||||
|
else: |
||||||
|
raise Exception(f'AcadosSimSolver.get(): Unknown field {field_},' \ |
||||||
|
f' available fields are {", ".join(self.gettable.keys())}') |
||||||
|
|
||||||
|
|
||||||
|
def __get_scalar(self, field): |
||||||
|
cdef double scalar |
||||||
|
acados_sim_solver_common.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, <void *> &scalar) |
||||||
|
return scalar |
||||||
|
|
||||||
|
|
||||||
|
def __get_vector(self, field): |
||||||
|
cdef int[2] dims |
||||||
|
acados_sim_solver_common.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, &dims[0]) |
||||||
|
# cdef cnp.ndarray[cnp.float64_t, ndim=1] out = np.ascontiguousarray(np.zeros((dims[0],), dtype=np.float64)) |
||||||
|
cdef cnp.ndarray[cnp.float64_t, ndim=1] out = np.zeros((dims[0]),) |
||||||
|
acados_sim_solver_common.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, <void *> out.data) |
||||||
|
return out |
||||||
|
|
||||||
|
|
||||||
|
def __get_matrix(self, field): |
||||||
|
cdef int[2] dims |
||||||
|
acados_sim_solver_common.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, &dims[0]) |
||||||
|
cdef cnp.ndarray[cnp.float64_t, ndim=2] out = np.zeros((dims[0], dims[1]), order='F', dtype=np.float64) |
||||||
|
acados_sim_solver_common.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, <void *> out.data) |
||||||
|
return out |
||||||
|
|
||||||
|
|
||||||
|
def set(self, field_: str, value_): |
||||||
|
""" |
||||||
|
Set numerical data inside the solver. |
||||||
|
|
||||||
|
:param field: string in ['p', 'seed_adj', 'T', 'x', 'u', 'xdot', 'z'] |
||||||
|
:param value: the value with appropriate size. |
||||||
|
""" |
||||||
|
settable = ['seed_adj', 'T', 'x', 'u', 'xdot', 'z', 'p'] # S_forw |
||||||
|
|
||||||
|
# cast value_ to avoid conversion issues |
||||||
|
if isinstance(value_, (float, int)): |
||||||
|
value_ = np.array([value_]) |
||||||
|
# if len(value_.shape) > 1: |
||||||
|
# raise RuntimeError('AcadosSimSolverCython.set(): value_ should be 1 dimensional') |
||||||
|
|
||||||
|
cdef cnp.ndarray[cnp.float64_t, ndim=1] value = np.ascontiguousarray(value_, dtype=np.float64).flatten() |
||||||
|
|
||||||
|
field = field_.encode('utf-8') |
||||||
|
cdef int[2] dims |
||||||
|
|
||||||
|
# treat parameters separately |
||||||
|
if field_ == 'p': |
||||||
|
assert acados_sim_solver.acados_sim_update_params(self.capsule, <double *> value.data, value.shape[0]) == 0 |
||||||
|
return |
||||||
|
else: |
||||||
|
acados_sim_solver_common.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, &dims[0]) |
||||||
|
|
||||||
|
value_ = np.ravel(value_, order='F') |
||||||
|
|
||||||
|
value_shape = value_.shape |
||||||
|
if len(value_shape) == 1: |
||||||
|
value_shape = (value_shape[0], 0) |
||||||
|
|
||||||
|
if value_shape != tuple(dims): |
||||||
|
raise Exception(f'AcadosSimSolverCython.set(): mismatching dimension' \ |
||||||
|
f' for field "{field_}" with dimension {tuple(dims)} (you have {value_shape}).') |
||||||
|
|
||||||
|
# set |
||||||
|
if field_ in ['xdot', 'z']: |
||||||
|
acados_sim_solver_common.sim_solver_set(self.sim_solver, field, <void *> value.data) |
||||||
|
elif field_ in settable: |
||||||
|
acados_sim_solver_common.sim_in_set(self.sim_config, self.sim_dims, self.sim_in, field, <void *> value.data) |
||||||
|
else: |
||||||
|
raise Exception(f'AcadosSimSolverCython.set(): Unknown field {field_},' \ |
||||||
|
f' available fields are {", ".join(settable)}') |
||||||
|
|
||||||
|
|
||||||
|
def options_set(self, field_: str, value_: bool): |
||||||
|
""" |
||||||
|
Set solver options |
||||||
|
|
||||||
|
:param field: string in ['sens_forw', 'sens_adj', 'sens_hess'] |
||||||
|
:param value: Boolean |
||||||
|
""" |
||||||
|
fields = ['sens_forw', 'sens_adj', 'sens_hess'] |
||||||
|
if field_ not in fields: |
||||||
|
raise Exception(f"field {field_} not supported. Supported values are {', '.join(fields)}.\n") |
||||||
|
|
||||||
|
field = field_.encode('utf-8') |
||||||
|
|
||||||
|
if not isinstance(value_, bool): |
||||||
|
raise TypeError("options_set: expected boolean for value") |
||||||
|
|
||||||
|
cdef bint bool_value = value_ |
||||||
|
acados_sim_solver_common.sim_opts_set(self.sim_config, self.sim_opts, field, <void *> &bool_value) |
||||||
|
# TODO: only allow setting |
||||||
|
# if getattr(self.acados_sim.solver_options, field_) or value_ == False: |
||||||
|
# acados_sim_solver_common.sim_opts_set(self.sim_config, self.sim_opts, field, <void *> &bool_value) |
||||||
|
# else: |
||||||
|
# raise RuntimeError(f"Cannot set option {field_} to True, because it was False in original solver options.\n") |
||||||
|
|
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
|
def __del__(self): |
||||||
|
if self.solver_created: |
||||||
|
acados_sim_solver.acados_sim_free(self.capsule) |
||||||
|
acados_sim_solver.acados_sim_solver_free_capsule(self.capsule) |
@ -1 +0,0 @@ |
|||||||
exclude_files=[main, acados_solver, acados_solver_sfun, Makefile, model].*\.? |
|
@ -0,0 +1,51 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
|
||||||
|
cimport acados_sim_solver_common |
||||||
|
|
||||||
|
cdef extern from "acados_sim_solver_{{ model.name }}.h": |
||||||
|
ctypedef struct sim_solver_capsule "sim_solver_capsule": |
||||||
|
pass |
||||||
|
|
||||||
|
sim_solver_capsule * acados_sim_solver_create_capsule "{{ model.name }}_acados_sim_solver_create_capsule"() |
||||||
|
int acados_sim_solver_free_capsule "{{ model.name }}_acados_sim_solver_free_capsule"(sim_solver_capsule *capsule) |
||||||
|
|
||||||
|
int acados_sim_create "{{ model.name }}_acados_sim_create"(sim_solver_capsule * capsule) |
||||||
|
int acados_sim_solve "{{ model.name }}_acados_sim_solve"(sim_solver_capsule * capsule) |
||||||
|
int acados_sim_free "{{ model.name }}_acados_sim_free"(sim_solver_capsule * capsule) |
||||||
|
int acados_sim_update_params "{{ model.name }}_acados_sim_update_params"(sim_solver_capsule * capsule, double *value, int np_) |
||||||
|
# int acados_sim_update_params_sparse "{{ model.name }}_acados_sim_update_params_sparse"(sim_solver_capsule * capsule, int stage, int *idx, double *p, int n_update) |
||||||
|
|
||||||
|
acados_sim_solver_common.sim_in *acados_get_sim_in "{{ model.name }}_acados_get_sim_in"(sim_solver_capsule * capsule) |
||||||
|
acados_sim_solver_common.sim_out *acados_get_sim_out "{{ model.name }}_acados_get_sim_out"(sim_solver_capsule * capsule) |
||||||
|
acados_sim_solver_common.sim_solver *acados_get_sim_solver "{{ model.name }}_acados_get_sim_solver"(sim_solver_capsule * capsule) |
||||||
|
acados_sim_solver_common.sim_config *acados_get_sim_config "{{ model.name }}_acados_get_sim_config"(sim_solver_capsule * capsule) |
||||||
|
acados_sim_solver_common.sim_opts *acados_get_sim_opts "{{ model.name }}_acados_get_sim_opts"(sim_solver_capsule * capsule) |
||||||
|
void *acados_get_sim_dims "{{ model.name }}_acados_get_sim_dims"(sim_solver_capsule * capsule) |
@ -0,0 +1,238 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) The acados authors. |
||||||
|
* |
||||||
|
* This file is part of acados. |
||||||
|
* |
||||||
|
* The 2-Clause BSD License |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* |
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer in the documentation |
||||||
|
* and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
* POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#ifndef {{ model.name }}_COST |
||||||
|
#define {{ model.name }}_COST |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
// Cost at initial shooting node
|
||||||
|
{% if cost.cost_type_0 == "NONLINEAR_LS" %} |
||||||
|
int {{ model.name }}_cost_y_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_0_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_0_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_0_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_0_fun_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_0_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_y_0_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_0_fun_jac_ut_xt_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_0_fun_jac_ut_xt_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_0_fun_jac_ut_xt_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_y_0_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_0_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_0_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_0_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_0_hess_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_0_hess_n_out(void); |
||||||
|
{% elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} |
||||||
|
|
||||||
|
int {{ model.name }}_conl_cost_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_conl_cost_0_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_conl_cost_0_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_conl_cost_0_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_conl_cost_0_fun_n_in(void); |
||||||
|
int {{ model.name }}_conl_cost_0_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_conl_cost_0_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_conl_cost_0_fun_jac_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_conl_cost_0_fun_jac_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_conl_cost_0_fun_jac_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_conl_cost_0_fun_jac_hess_n_in(void); |
||||||
|
int {{ model.name }}_conl_cost_0_fun_jac_hess_n_out(void); |
||||||
|
|
||||||
|
{% elif cost.cost_type_0 == "EXTERNAL" %} |
||||||
|
{%- if cost.cost_ext_fun_type_0 == "casadi" %} |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_0_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_0_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_jac_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_jac_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_0_fun_jac_n_out(void); |
||||||
|
{%- else %} |
||||||
|
int {{ cost.cost_function_ext_cost_0 }}(void **, void **, void *); |
||||||
|
{%- endif %} |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
|
||||||
|
// Cost at path shooting node
|
||||||
|
{% if cost.cost_type == "NONLINEAR_LS" %} |
||||||
|
int {{ model.name }}_cost_y_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_fun_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_y_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_fun_jac_ut_xt_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_fun_jac_ut_xt_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_fun_jac_ut_xt_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_y_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_hess_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_hess_n_out(void); |
||||||
|
|
||||||
|
{% elif cost.cost_type == "CONVEX_OVER_NONLINEAR" %} |
||||||
|
int {{ model.name }}_conl_cost_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_conl_cost_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_conl_cost_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_conl_cost_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_conl_cost_fun_n_in(void); |
||||||
|
int {{ model.name }}_conl_cost_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_conl_cost_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_conl_cost_fun_jac_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_conl_cost_fun_jac_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_conl_cost_fun_jac_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_conl_cost_fun_jac_hess_n_in(void); |
||||||
|
int {{ model.name }}_conl_cost_fun_jac_hess_n_out(void); |
||||||
|
{% elif cost.cost_type == "EXTERNAL" %} |
||||||
|
{%- if cost.cost_ext_fun_type == "casadi" %} |
||||||
|
int {{ model.name }}_cost_ext_cost_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_ext_cost_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_jac_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_jac_hess_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_jac_hess_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_ext_cost_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_jac_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_fun_jac_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_fun_jac_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_jac_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_fun_jac_n_out(void); |
||||||
|
{%- else %} |
||||||
|
int {{ cost.cost_function_ext_cost }}(void **, void **, void *); |
||||||
|
{%- endif %} |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
// Cost at terminal shooting node
|
||||||
|
{% if cost.cost_type_e == "NONLINEAR_LS" %} |
||||||
|
int {{ model.name }}_cost_y_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_e_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_e_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_e_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_e_fun_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_e_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_y_e_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_e_fun_jac_ut_xt_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_e_fun_jac_ut_xt_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_e_fun_jac_ut_xt_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_y_e_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_y_e_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_y_e_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_y_e_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_y_e_hess_n_in(void); |
||||||
|
int {{ model.name }}_cost_y_e_hess_n_out(void); |
||||||
|
{% elif cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} |
||||||
|
int {{ model.name }}_conl_cost_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_conl_cost_e_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_conl_cost_e_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_conl_cost_e_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_conl_cost_e_fun_n_in(void); |
||||||
|
int {{ model.name }}_conl_cost_e_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_conl_cost_e_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_conl_cost_e_fun_jac_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_conl_cost_e_fun_jac_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_conl_cost_e_fun_jac_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_conl_cost_e_fun_jac_hess_n_in(void); |
||||||
|
int {{ model.name }}_conl_cost_e_fun_jac_hess_n_out(void); |
||||||
|
{% elif cost.cost_type_e == "EXTERNAL" %} |
||||||
|
{%- if cost.cost_ext_fun_type_e == "casadi" %} |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_e_fun_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_e_fun_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_out(void); |
||||||
|
|
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_jac_work(int *, int *, int *, int *); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_in(int); |
||||||
|
const int *{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_out(int); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_jac_n_in(void); |
||||||
|
int {{ model.name }}_cost_ext_cost_e_fun_jac_n_out(void); |
||||||
|
{%- else %} |
||||||
|
int {{ cost.cost_function_ext_cost_e }}(void **, void **, void *); |
||||||
|
{%- endif %} |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} /* extern "C" */ |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif // {{ model.name }}_COST
|
@ -1,69 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
|
||||||
* This file is part of acados. |
|
||||||
* |
|
||||||
* The 2-Clause BSD License |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are met: |
|
||||||
* |
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer in the documentation |
|
||||||
* and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#ifndef {{ model.name }}_Y_0_COST |
|
||||||
#define {{ model.name }}_Y_0_COST |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
{% if cost.cost_type_0 == "NONLINEAR_LS" %} |
|
||||||
int {{ model.name }}_cost_y_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_0_fun_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_0_fun_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_0_fun_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_0_fun_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_0_fun_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_y_0_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_0_fun_jac_ut_xt_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_0_fun_jac_ut_xt_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_0_fun_jac_ut_xt_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_y_0_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_0_hess_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_0_hess_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_0_hess_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_0_hess_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_0_hess_n_out(void); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} /* extern "C" */ |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif // {{ model.name }}_Y_0_COST
|
|
@ -1,69 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
|
||||||
* This file is part of acados. |
|
||||||
* |
|
||||||
* The 2-Clause BSD License |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are met: |
|
||||||
* |
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer in the documentation |
|
||||||
* and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#ifndef {{ model.name }}_Y_E_COST |
|
||||||
#define {{ model.name }}_Y_E_COST |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
{% if cost.cost_type_e == "NONLINEAR_LS" %} |
|
||||||
int {{ model.name }}_cost_y_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_e_fun_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_e_fun_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_e_fun_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_e_fun_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_e_fun_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_y_e_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_e_fun_jac_ut_xt_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_e_fun_jac_ut_xt_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_e_fun_jac_ut_xt_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_y_e_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_e_hess_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_e_hess_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_e_hess_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_e_hess_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_e_hess_n_out(void); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} /* extern "C" */ |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif // {{ model.name }}_Y_E_COST
|
|
@ -1,69 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
|
||||||
* This file is part of acados. |
|
||||||
* |
|
||||||
* The 2-Clause BSD License |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are met: |
|
||||||
* |
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer in the documentation |
|
||||||
* and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#ifndef {{ model.name }}_Y_COST |
|
||||||
#define {{ model.name }}_Y_COST |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
{% if cost.cost_type == "NONLINEAR_LS" %} |
|
||||||
int {{ model.name }}_cost_y_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_fun_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_fun_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_fun_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_fun_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_fun_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_y_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_fun_jac_ut_xt_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_fun_jac_ut_xt_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_fun_jac_ut_xt_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_y_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_y_hess_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_y_hess_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_y_hess_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_y_hess_n_in(void); |
|
||||||
int {{ model.name }}_cost_y_hess_n_out(void); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} /* extern "C" */ |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif // {{ model.name }}_Y_COST
|
|
@ -1,74 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
|
||||||
* This file is part of acados. |
|
||||||
* |
|
||||||
* The 2-Clause BSD License |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are met: |
|
||||||
* |
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer in the documentation |
|
||||||
* and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#ifndef {{ model.name }}_EXT_COST |
|
||||||
#define {{ model.name }}_EXT_COST |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
{% if cost.cost_ext_fun_type == "casadi" %} |
|
||||||
{% if cost.cost_type == "EXTERNAL" %} |
|
||||||
int {{ model.name }}_cost_ext_cost_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_fun_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_fun_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_ext_cost_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_jac_hess_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_jac_hess_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_jac_hess_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_ext_cost_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_jac_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_fun_jac_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_fun_jac_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_jac_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_fun_jac_n_out(void); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% else %} |
|
||||||
int {{ cost.cost_function_ext_cost }}(void **, void **, void *); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} /* extern "C" */ |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif // {{ model.name }}_EXT_COST
|
|
@ -1,75 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
|
||||||
* This file is part of acados. |
|
||||||
* |
|
||||||
* The 2-Clause BSD License |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are met: |
|
||||||
* |
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer in the documentation |
|
||||||
* and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#ifndef {{ model.name }}_EXT_COST_0 |
|
||||||
#define {{ model.name }}_EXT_COST_0 |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
{% if cost.cost_ext_fun_type_0 == "casadi" %} |
|
||||||
|
|
||||||
{% if cost.cost_type_0 == "EXTERNAL" %} |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_0_fun_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_0_fun_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_jac_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_jac_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_0_fun_jac_n_out(void); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% else %} |
|
||||||
int {{ cost.cost_function_ext_cost_0 }}(void **, void **, void *); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} /* extern "C" */ |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif // {{ model.name }}_EXT_COST_0
|
|
@ -1,74 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
|
||||||
* This file is part of acados. |
|
||||||
* |
|
||||||
* The 2-Clause BSD License |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are met: |
|
||||||
* |
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer in the documentation |
|
||||||
* and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#ifndef {{ model.name }}_EXT_COST_E |
|
||||||
#define {{ model.name }}_EXT_COST_E |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
{% if cost.cost_ext_fun_type_e == "casadi" %} |
|
||||||
{% if cost.cost_type_e == "EXTERNAL" %} |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_e_fun_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_e_fun_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_jac_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_out(int); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_jac_n_in(void); |
|
||||||
int {{ model.name }}_cost_ext_cost_e_fun_jac_n_out(void); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% else %} |
|
||||||
int {{ cost.cost_function_ext_cost_e }}(void **, void **, void *); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} /* extern "C" */ |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif // {{ model.name }}_EXT_COST_E
|
|
@ -1,70 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
|
||||||
* This file is part of acados. |
|
||||||
* |
|
||||||
* The 2-Clause BSD License |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are met: |
|
||||||
* |
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
* this list of conditions and the following disclaimer in the documentation |
|
||||||
* and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef {{ model.name }}_H_CONSTRAINT |
|
||||||
#define {{ model.name }}_H_CONSTRAINT |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
{% if dims.nh > 0 %} |
|
||||||
int {{ model.name }}_constr_h_fun_jac_uxt_zt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_constr_h_fun_jac_uxt_zt_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_sparsity_out(int); |
|
||||||
int {{ model.name }}_constr_h_fun_jac_uxt_zt_n_in(void); |
|
||||||
int {{ model.name }}_constr_h_fun_jac_uxt_zt_n_out(void); |
|
||||||
|
|
||||||
int {{ model.name }}_constr_h_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_constr_h_fun_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_constr_h_fun_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_constr_h_fun_sparsity_out(int); |
|
||||||
int {{ model.name }}_constr_h_fun_n_in(void); |
|
||||||
int {{ model.name }}_constr_h_fun_n_out(void); |
|
||||||
|
|
||||||
{% if solver_options.hessian_approx == "EXACT" -%} |
|
||||||
int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_sparsity_out(int); |
|
||||||
int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_n_in(void); |
|
||||||
int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_n_out(void); |
|
||||||
{% endif %} |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} /* extern "C" */ |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif // {{ model.name }}_H_CONSTRAINT
|
|
@ -1,8 +1,5 @@ |
|||||||
/*
|
/*
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
* Copyright (c) The acados authors. |
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
* |
||||||
* This file is part of acados. |
* This file is part of acados. |
||||||
* |
* |
@ -1,8 +1,5 @@ |
|||||||
/*
|
/*
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
* Copyright (c) The acados authors. |
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
* |
||||||
* This file is part of acados. |
* This file is part of acados. |
||||||
* |
* |
@ -1,8 +1,5 @@ |
|||||||
/*
|
/*
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
* Copyright (c) The acados authors. |
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
* |
||||||
* This file is part of acados. |
* This file is part of acados. |
||||||
* |
* |
@ -1,8 +1,5 @@ |
|||||||
/*
|
/*
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
* Copyright (c) The acados authors. |
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
* |
||||||
* This file is part of acados. |
* This file is part of acados. |
||||||
* |
* |
@ -1,8 +1,5 @@ |
|||||||
/*
|
/*
|
||||||
* Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
* Copyright (c) The acados authors. |
||||||
* Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
* Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
* Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
* |
* |
||||||
* This file is part of acados. |
* This file is part of acados. |
||||||
* |
* |
@ -1,21 +0,0 @@ |
|||||||
#ifndef {{ model.name }}_PHI_E_CONSTRAINT |
|
||||||
#define {{ model.name }}_PHI_E_CONSTRAINT |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
{% if dims.nphi_e > 0 %} |
|
||||||
int {{ model.name }}_phi_e_constraint(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); |
|
||||||
int {{ model.name }}_phi_e_constraint_work(int *, int *, int *, int *); |
|
||||||
const int *{{ model.name }}_phi_e_constraint_sparsity_in(int); |
|
||||||
const int *{{ model.name }}_phi_e_constraint_sparsity_out(int); |
|
||||||
int {{ model.name }}_phi_e_constraint_n_in(void); |
|
||||||
int {{ model.name }}_phi_e_constraint_n_out(void); |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} /* extern "C" */ |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif // {{ model.name }}_PHI_E_CONSTRAINT
|
|
@ -0,0 +1,708 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
|
||||||
|
import os |
||||||
|
import casadi as ca |
||||||
|
from .utils import is_empty, casadi_length |
||||||
|
|
||||||
|
|
||||||
|
def get_casadi_symbol(x): |
||||||
|
if isinstance(x, ca.MX): |
||||||
|
return ca.MX.sym |
||||||
|
elif isinstance(x, ca.SX): |
||||||
|
return ca.SX.sym |
||||||
|
else: |
||||||
|
raise TypeError("Expected casadi SX or MX.") |
||||||
|
|
||||||
|
################ |
||||||
|
# Dynamics |
||||||
|
################ |
||||||
|
|
||||||
|
|
||||||
|
def generate_c_code_discrete_dynamics( model, opts ): |
||||||
|
|
||||||
|
casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
||||||
|
|
||||||
|
# load model |
||||||
|
x = model.x |
||||||
|
u = model.u |
||||||
|
p = model.p |
||||||
|
phi = model.disc_dyn_expr |
||||||
|
model_name = model.name |
||||||
|
nx = casadi_length(x) |
||||||
|
|
||||||
|
symbol = get_casadi_symbol(x) |
||||||
|
# assume nx1 = nx !!! |
||||||
|
lam = symbol('lam', nx, 1) |
||||||
|
|
||||||
|
# generate jacobians |
||||||
|
ux = ca.vertcat(u,x) |
||||||
|
jac_ux = ca.jacobian(phi, ux) |
||||||
|
# generate adjoint |
||||||
|
adj_ux = ca.jtimes(phi, ux, lam, True) |
||||||
|
# generate hessian |
||||||
|
hess_ux = ca.jacobian(adj_ux, ux) |
||||||
|
|
||||||
|
# change directory |
||||||
|
cwd = os.getcwd() |
||||||
|
model_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model_name}_model')) |
||||||
|
if not os.path.exists(model_dir): |
||||||
|
os.makedirs(model_dir) |
||||||
|
os.chdir(model_dir) |
||||||
|
|
||||||
|
# set up & generate ca.Functions |
||||||
|
fun_name = model_name + '_dyn_disc_phi_fun' |
||||||
|
phi_fun = ca.Function(fun_name, [x, u, p], [phi]) |
||||||
|
phi_fun.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_dyn_disc_phi_fun_jac' |
||||||
|
phi_fun_jac_ut_xt = ca.Function(fun_name, [x, u, p], [phi, jac_ux.T]) |
||||||
|
phi_fun_jac_ut_xt.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_dyn_disc_phi_fun_jac_hess' |
||||||
|
phi_fun_jac_ut_xt_hess = ca.Function(fun_name, [x, u, lam, p], [phi, jac_ux.T, hess_ux]) |
||||||
|
phi_fun_jac_ut_xt_hess.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
os.chdir(cwd) |
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generate_c_code_explicit_ode( model, opts ): |
||||||
|
|
||||||
|
casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
||||||
|
|
||||||
|
generate_hess = opts["generate_hess"] |
||||||
|
|
||||||
|
# load model |
||||||
|
x = model.x |
||||||
|
u = model.u |
||||||
|
p = model.p |
||||||
|
f_expl = model.f_expl_expr |
||||||
|
model_name = model.name |
||||||
|
|
||||||
|
## get model dimensions |
||||||
|
nx = x.size()[0] |
||||||
|
nu = u.size()[0] |
||||||
|
|
||||||
|
symbol = get_casadi_symbol(x) |
||||||
|
|
||||||
|
## set up functions to be exported |
||||||
|
Sx = symbol('Sx', nx, nx) |
||||||
|
Sp = symbol('Sp', nx, nu) |
||||||
|
lambdaX = symbol('lambdaX', nx, 1) |
||||||
|
|
||||||
|
fun_name = model_name + '_expl_ode_fun' |
||||||
|
|
||||||
|
## Set up functions |
||||||
|
expl_ode_fun = ca.Function(fun_name, [x, u, p], [f_expl]) |
||||||
|
|
||||||
|
vdeX = ca.jtimes(f_expl,x,Sx) |
||||||
|
vdeP = ca.jacobian(f_expl,u) + ca.jtimes(f_expl,x,Sp) |
||||||
|
|
||||||
|
fun_name = model_name + '_expl_vde_forw' |
||||||
|
|
||||||
|
expl_vde_forw = ca.Function(fun_name, [x, Sx, Sp, u, p], [f_expl, vdeX, vdeP]) |
||||||
|
|
||||||
|
adj = ca.jtimes(f_expl, ca.vertcat(x, u), lambdaX, True) |
||||||
|
|
||||||
|
fun_name = model_name + '_expl_vde_adj' |
||||||
|
expl_vde_adj = ca.Function(fun_name, [x, lambdaX, u, p], [adj]) |
||||||
|
|
||||||
|
if generate_hess: |
||||||
|
S_forw = ca.vertcat(ca.horzcat(Sx, Sp), ca.horzcat(ca.DM.zeros(nu,nx), ca.DM.eye(nu))) |
||||||
|
hess = ca.mtimes(ca.transpose(S_forw),ca.jtimes(adj, ca.vertcat(x,u), S_forw)) |
||||||
|
hess2 = [] |
||||||
|
for j in range(nx+nu): |
||||||
|
for i in range(j,nx+nu): |
||||||
|
hess2 = ca.vertcat(hess2, hess[i,j]) |
||||||
|
|
||||||
|
fun_name = model_name + '_expl_ode_hess' |
||||||
|
expl_ode_hess = ca.Function(fun_name, [x, Sx, Sp, lambdaX, u, p], [adj, hess2]) |
||||||
|
|
||||||
|
# change directory |
||||||
|
cwd = os.getcwd() |
||||||
|
model_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model_name}_model')) |
||||||
|
if not os.path.exists(model_dir): |
||||||
|
os.makedirs(model_dir) |
||||||
|
os.chdir(model_dir) |
||||||
|
|
||||||
|
# generate C code |
||||||
|
fun_name = model_name + '_expl_ode_fun' |
||||||
|
expl_ode_fun.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_expl_vde_forw' |
||||||
|
expl_vde_forw.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_expl_vde_adj' |
||||||
|
expl_vde_adj.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
if generate_hess: |
||||||
|
fun_name = model_name + '_expl_ode_hess' |
||||||
|
expl_ode_hess.generate(fun_name, casadi_codegen_opts) |
||||||
|
os.chdir(cwd) |
||||||
|
|
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
|
def generate_c_code_implicit_ode( model, opts ): |
||||||
|
|
||||||
|
casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
||||||
|
|
||||||
|
# load model |
||||||
|
x = model.x |
||||||
|
xdot = model.xdot |
||||||
|
u = model.u |
||||||
|
z = model.z |
||||||
|
p = model.p |
||||||
|
f_impl = model.f_impl_expr |
||||||
|
model_name = model.name |
||||||
|
|
||||||
|
# get model dimensions |
||||||
|
nx = casadi_length(x) |
||||||
|
nz = casadi_length(z) |
||||||
|
|
||||||
|
# generate jacobians |
||||||
|
jac_x = ca.jacobian(f_impl, x) |
||||||
|
jac_xdot = ca.jacobian(f_impl, xdot) |
||||||
|
jac_u = ca.jacobian(f_impl, u) |
||||||
|
jac_z = ca.jacobian(f_impl, z) |
||||||
|
|
||||||
|
# Set up functions |
||||||
|
p = model.p |
||||||
|
fun_name = model_name + '_impl_dae_fun' |
||||||
|
impl_dae_fun = ca.Function(fun_name, [x, xdot, u, z, p], [f_impl]) |
||||||
|
|
||||||
|
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z' |
||||||
|
impl_dae_fun_jac_x_xdot_z = ca.Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_z]) |
||||||
|
|
||||||
|
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u_z' |
||||||
|
impl_dae_fun_jac_x_xdot_u_z = ca.Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_u, jac_z]) |
||||||
|
|
||||||
|
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u' |
||||||
|
impl_dae_fun_jac_x_xdot_u = ca.Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_u]) |
||||||
|
|
||||||
|
fun_name = model_name + '_impl_dae_jac_x_xdot_u_z' |
||||||
|
impl_dae_jac_x_xdot_u_z = ca.Function(fun_name, [x, xdot, u, z, p], [jac_x, jac_xdot, jac_u, jac_z]) |
||||||
|
|
||||||
|
if opts["generate_hess"]: |
||||||
|
x_xdot_z_u = ca.vertcat(x, xdot, z, u) |
||||||
|
symbol = get_casadi_symbol(x) |
||||||
|
multiplier = symbol('multiplier', nx + nz) |
||||||
|
ADJ = ca.jtimes(f_impl, x_xdot_z_u, multiplier, True) |
||||||
|
HESS = ca.jacobian(ADJ, x_xdot_z_u) |
||||||
|
fun_name = model_name + '_impl_dae_hess' |
||||||
|
impl_dae_hess = ca.Function(fun_name, [x, xdot, u, z, multiplier, p], [HESS]) |
||||||
|
|
||||||
|
# change directory |
||||||
|
cwd = os.getcwd() |
||||||
|
model_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model_name}_model')) |
||||||
|
if not os.path.exists(model_dir): |
||||||
|
os.makedirs(model_dir) |
||||||
|
os.chdir(model_dir) |
||||||
|
|
||||||
|
# generate C code |
||||||
|
fun_name = model_name + '_impl_dae_fun' |
||||||
|
impl_dae_fun.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z' |
||||||
|
impl_dae_fun_jac_x_xdot_z.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_impl_dae_jac_x_xdot_u_z' |
||||||
|
impl_dae_jac_x_xdot_u_z.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u_z' |
||||||
|
impl_dae_fun_jac_x_xdot_u_z.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u' |
||||||
|
impl_dae_fun_jac_x_xdot_u.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
if opts["generate_hess"]: |
||||||
|
fun_name = model_name + '_impl_dae_hess' |
||||||
|
impl_dae_hess.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
os.chdir(cwd) |
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
|
def generate_c_code_gnsf( model, opts ): |
||||||
|
|
||||||
|
casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
||||||
|
|
||||||
|
model_name = model.name |
||||||
|
|
||||||
|
# set up directory |
||||||
|
cwd = os.getcwd() |
||||||
|
model_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model_name}_model')) |
||||||
|
if not os.path.exists(model_dir): |
||||||
|
os.makedirs(model_dir) |
||||||
|
os.chdir(model_dir) |
||||||
|
|
||||||
|
# obtain gnsf dimensions |
||||||
|
get_matrices_fun = model.get_matrices_fun |
||||||
|
phi_fun = model.phi_fun |
||||||
|
|
||||||
|
size_gnsf_A = get_matrices_fun.size_out(0) |
||||||
|
gnsf_nx1 = size_gnsf_A[1] |
||||||
|
gnsf_nz1 = size_gnsf_A[0] - size_gnsf_A[1] |
||||||
|
gnsf_nuhat = max(phi_fun.size_in(1)) |
||||||
|
gnsf_ny = max(phi_fun.size_in(0)) |
||||||
|
gnsf_nout = max(phi_fun.size_out(0)) |
||||||
|
|
||||||
|
# set up expressions |
||||||
|
# if the model uses ca.MX because of cost/constraints |
||||||
|
# the DAE can be exported as ca.SX -> detect GNSF in Matlab |
||||||
|
# -> evaluated ca.SX GNSF functions with ca.MX. |
||||||
|
u = model.u |
||||||
|
symbol = get_casadi_symbol(u) |
||||||
|
|
||||||
|
y = symbol("y", gnsf_ny, 1) |
||||||
|
uhat = symbol("uhat", gnsf_nuhat, 1) |
||||||
|
p = model.p |
||||||
|
x1 = symbol("gnsf_x1", gnsf_nx1, 1) |
||||||
|
x1dot = symbol("gnsf_x1dot", gnsf_nx1, 1) |
||||||
|
z1 = symbol("gnsf_z1", gnsf_nz1, 1) |
||||||
|
dummy = symbol("gnsf_dummy", 1, 1) |
||||||
|
empty_var = symbol("gnsf_empty_var", 0, 0) |
||||||
|
|
||||||
|
## generate C code |
||||||
|
fun_name = model_name + '_gnsf_phi_fun' |
||||||
|
phi_fun_ = ca.Function(fun_name, [y, uhat, p], [phi_fun(y, uhat, p)]) |
||||||
|
phi_fun_.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_gnsf_phi_fun_jac_y' |
||||||
|
phi_fun_jac_y = model.phi_fun_jac_y |
||||||
|
phi_fun_jac_y_ = ca.Function(fun_name, [y, uhat, p], phi_fun_jac_y(y, uhat, p)) |
||||||
|
phi_fun_jac_y_.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_gnsf_phi_jac_y_uhat' |
||||||
|
phi_jac_y_uhat = model.phi_jac_y_uhat |
||||||
|
phi_jac_y_uhat_ = ca.Function(fun_name, [y, uhat, p], phi_jac_y_uhat(y, uhat, p)) |
||||||
|
phi_jac_y_uhat_.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_gnsf_f_lo_fun_jac_x1k1uz' |
||||||
|
f_lo_fun_jac_x1k1uz = model.f_lo_fun_jac_x1k1uz |
||||||
|
f_lo_fun_jac_x1k1uz_eval = f_lo_fun_jac_x1k1uz(x1, x1dot, z1, u, p) |
||||||
|
|
||||||
|
# avoid codegeneration issue |
||||||
|
if not isinstance(f_lo_fun_jac_x1k1uz_eval, tuple) and is_empty(f_lo_fun_jac_x1k1uz_eval): |
||||||
|
f_lo_fun_jac_x1k1uz_eval = [empty_var] |
||||||
|
|
||||||
|
f_lo_fun_jac_x1k1uz_ = ca.Function(fun_name, [x1, x1dot, z1, u, p], |
||||||
|
f_lo_fun_jac_x1k1uz_eval) |
||||||
|
f_lo_fun_jac_x1k1uz_.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
fun_name = model_name + '_gnsf_get_matrices_fun' |
||||||
|
get_matrices_fun_ = ca.Function(fun_name, [dummy], get_matrices_fun(1)) |
||||||
|
get_matrices_fun_.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
# remove fields for json dump |
||||||
|
del model.phi_fun |
||||||
|
del model.phi_fun_jac_y |
||||||
|
del model.phi_jac_y_uhat |
||||||
|
del model.f_lo_fun_jac_x1k1uz |
||||||
|
del model.get_matrices_fun |
||||||
|
|
||||||
|
os.chdir(cwd) |
||||||
|
|
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
|
################ |
||||||
|
# Cost |
||||||
|
################ |
||||||
|
|
||||||
|
def generate_c_code_external_cost(model, stage_type, opts): |
||||||
|
|
||||||
|
casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
||||||
|
|
||||||
|
x = model.x |
||||||
|
p = model.p |
||||||
|
u = model.u |
||||||
|
z = model.z |
||||||
|
symbol = get_casadi_symbol(x) |
||||||
|
|
||||||
|
if stage_type == 'terminal': |
||||||
|
suffix_name = "_cost_ext_cost_e_fun" |
||||||
|
suffix_name_hess = "_cost_ext_cost_e_fun_jac_hess" |
||||||
|
suffix_name_jac = "_cost_ext_cost_e_fun_jac" |
||||||
|
ext_cost = model.cost_expr_ext_cost_e |
||||||
|
custom_hess = model.cost_expr_ext_cost_custom_hess_e |
||||||
|
# Last stage cannot depend on u and z |
||||||
|
u = symbol("u", 0, 0) |
||||||
|
z = symbol("z", 0, 0) |
||||||
|
|
||||||
|
elif stage_type == 'path': |
||||||
|
suffix_name = "_cost_ext_cost_fun" |
||||||
|
suffix_name_hess = "_cost_ext_cost_fun_jac_hess" |
||||||
|
suffix_name_jac = "_cost_ext_cost_fun_jac" |
||||||
|
ext_cost = model.cost_expr_ext_cost |
||||||
|
custom_hess = model.cost_expr_ext_cost_custom_hess |
||||||
|
|
||||||
|
elif stage_type == 'initial': |
||||||
|
suffix_name = "_cost_ext_cost_0_fun" |
||||||
|
suffix_name_hess = "_cost_ext_cost_0_fun_jac_hess" |
||||||
|
suffix_name_jac = "_cost_ext_cost_0_fun_jac" |
||||||
|
ext_cost = model.cost_expr_ext_cost_0 |
||||||
|
custom_hess = model.cost_expr_ext_cost_custom_hess_0 |
||||||
|
|
||||||
|
nunx = x.shape[0] + u.shape[0] |
||||||
|
|
||||||
|
# set up functions to be exported |
||||||
|
fun_name = model.name + suffix_name |
||||||
|
fun_name_hess = model.name + suffix_name_hess |
||||||
|
fun_name_jac = model.name + suffix_name_jac |
||||||
|
|
||||||
|
# generate expression for full gradient and Hessian |
||||||
|
hess_uxz, grad_uxz = ca.hessian(ext_cost, ca.vertcat(u, x, z)) |
||||||
|
|
||||||
|
hess_ux = hess_uxz[:nunx, :nunx] |
||||||
|
hess_z = hess_uxz[nunx:, nunx:] |
||||||
|
hess_z_ux = hess_uxz[nunx:, :nunx] |
||||||
|
|
||||||
|
if custom_hess is not None: |
||||||
|
hess_ux = custom_hess |
||||||
|
|
||||||
|
ext_cost_fun = ca.Function(fun_name, [x, u, z, p], [ext_cost]) |
||||||
|
|
||||||
|
ext_cost_fun_jac_hess = ca.Function( |
||||||
|
fun_name_hess, [x, u, z, p], [ext_cost, grad_uxz, hess_ux, hess_z, hess_z_ux] |
||||||
|
) |
||||||
|
ext_cost_fun_jac = ca.Function( |
||||||
|
fun_name_jac, [x, u, z, p], [ext_cost, grad_uxz] |
||||||
|
) |
||||||
|
|
||||||
|
# change directory |
||||||
|
cwd = os.getcwd() |
||||||
|
cost_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model.name}_cost')) |
||||||
|
if not os.path.exists(cost_dir): |
||||||
|
os.makedirs(cost_dir) |
||||||
|
os.chdir(cost_dir) |
||||||
|
|
||||||
|
ext_cost_fun.generate(fun_name, casadi_codegen_opts) |
||||||
|
ext_cost_fun_jac_hess.generate(fun_name_hess, casadi_codegen_opts) |
||||||
|
ext_cost_fun_jac.generate(fun_name_jac, casadi_codegen_opts) |
||||||
|
|
||||||
|
os.chdir(cwd) |
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
|
def generate_c_code_nls_cost( model, cost_name, stage_type, opts ): |
||||||
|
|
||||||
|
casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
||||||
|
|
||||||
|
x = model.x |
||||||
|
z = model.z |
||||||
|
p = model.p |
||||||
|
u = model.u |
||||||
|
|
||||||
|
symbol = get_casadi_symbol(x) |
||||||
|
|
||||||
|
if stage_type == 'terminal': |
||||||
|
middle_name = '_cost_y_e' |
||||||
|
u = symbol('u', 0, 0) |
||||||
|
y_expr = model.cost_y_expr_e |
||||||
|
|
||||||
|
elif stage_type == 'initial': |
||||||
|
middle_name = '_cost_y_0' |
||||||
|
y_expr = model.cost_y_expr_0 |
||||||
|
|
||||||
|
elif stage_type == 'path': |
||||||
|
middle_name = '_cost_y' |
||||||
|
y_expr = model.cost_y_expr |
||||||
|
|
||||||
|
# change directory |
||||||
|
cwd = os.getcwd() |
||||||
|
cost_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model.name}_cost')) |
||||||
|
if not os.path.exists(cost_dir): |
||||||
|
os.makedirs(cost_dir) |
||||||
|
os.chdir(cost_dir) |
||||||
|
|
||||||
|
# set up expressions |
||||||
|
cost_jac_expr = ca.transpose(ca.jacobian(y_expr, ca.vertcat(u, x))) |
||||||
|
dy_dz = ca.jacobian(y_expr, z) |
||||||
|
ny = casadi_length(y_expr) |
||||||
|
|
||||||
|
y = symbol('y', ny, 1) |
||||||
|
|
||||||
|
y_adj = ca.jtimes(y_expr, ca.vertcat(u, x), y, True) |
||||||
|
y_hess = ca.jacobian(y_adj, ca.vertcat(u, x)) |
||||||
|
|
||||||
|
## generate C code |
||||||
|
suffix_name = '_fun' |
||||||
|
fun_name = cost_name + middle_name + suffix_name |
||||||
|
y_fun = ca.Function( fun_name, [x, u, z, p], [ y_expr ]) |
||||||
|
y_fun.generate( fun_name, casadi_codegen_opts ) |
||||||
|
|
||||||
|
suffix_name = '_fun_jac_ut_xt' |
||||||
|
fun_name = cost_name + middle_name + suffix_name |
||||||
|
y_fun_jac_ut_xt = ca.Function(fun_name, [x, u, z, p], [ y_expr, cost_jac_expr, dy_dz ]) |
||||||
|
y_fun_jac_ut_xt.generate( fun_name, casadi_codegen_opts ) |
||||||
|
|
||||||
|
suffix_name = '_hess' |
||||||
|
fun_name = cost_name + middle_name + suffix_name |
||||||
|
y_hess = ca.Function(fun_name, [x, u, z, y, p], [ y_hess ]) |
||||||
|
y_hess.generate( fun_name, casadi_codegen_opts ) |
||||||
|
|
||||||
|
os.chdir(cwd) |
||||||
|
|
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generate_c_code_conl_cost(model, cost_name, stage_type, opts): |
||||||
|
|
||||||
|
casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
||||||
|
|
||||||
|
x = model.x |
||||||
|
z = model.z |
||||||
|
p = model.p |
||||||
|
|
||||||
|
symbol = get_casadi_symbol(x) |
||||||
|
|
||||||
|
if stage_type == 'terminal': |
||||||
|
u = symbol('u', 0, 0) |
||||||
|
|
||||||
|
yref = model.cost_r_in_psi_expr_e |
||||||
|
inner_expr = model.cost_y_expr_e - yref |
||||||
|
outer_expr = model.cost_psi_expr_e |
||||||
|
res_expr = model.cost_r_in_psi_expr_e |
||||||
|
|
||||||
|
suffix_name_fun = '_conl_cost_e_fun' |
||||||
|
suffix_name_fun_jac_hess = '_conl_cost_e_fun_jac_hess' |
||||||
|
|
||||||
|
custom_hess = model.cost_conl_custom_outer_hess_e |
||||||
|
|
||||||
|
elif stage_type == 'initial': |
||||||
|
u = model.u |
||||||
|
|
||||||
|
yref = model.cost_r_in_psi_expr_0 |
||||||
|
inner_expr = model.cost_y_expr_0 - yref |
||||||
|
outer_expr = model.cost_psi_expr_0 |
||||||
|
res_expr = model.cost_r_in_psi_expr_0 |
||||||
|
|
||||||
|
suffix_name_fun = '_conl_cost_0_fun' |
||||||
|
suffix_name_fun_jac_hess = '_conl_cost_0_fun_jac_hess' |
||||||
|
|
||||||
|
custom_hess = model.cost_conl_custom_outer_hess_0 |
||||||
|
|
||||||
|
elif stage_type == 'path': |
||||||
|
u = model.u |
||||||
|
|
||||||
|
yref = model.cost_r_in_psi_expr |
||||||
|
inner_expr = model.cost_y_expr - yref |
||||||
|
outer_expr = model.cost_psi_expr |
||||||
|
res_expr = model.cost_r_in_psi_expr |
||||||
|
|
||||||
|
suffix_name_fun = '_conl_cost_fun' |
||||||
|
suffix_name_fun_jac_hess = '_conl_cost_fun_jac_hess' |
||||||
|
|
||||||
|
custom_hess = model.cost_conl_custom_outer_hess |
||||||
|
|
||||||
|
# set up function names |
||||||
|
fun_name_cost_fun = model.name + suffix_name_fun |
||||||
|
fun_name_cost_fun_jac_hess = model.name + suffix_name_fun_jac_hess |
||||||
|
|
||||||
|
# set up functions to be exported |
||||||
|
outer_loss_fun = ca.Function('psi', [res_expr, p], [outer_expr]) |
||||||
|
cost_expr = outer_loss_fun(inner_expr, p) |
||||||
|
|
||||||
|
outer_loss_grad_fun = ca.Function('outer_loss_grad', [res_expr, p], [ca.jacobian(outer_expr, res_expr).T]) |
||||||
|
|
||||||
|
if custom_hess is None: |
||||||
|
outer_hess_fun = ca.Function('inner_hess', [res_expr, p], [ca.hessian(outer_loss_fun(res_expr, p), res_expr)[0]]) |
||||||
|
else: |
||||||
|
outer_hess_fun = ca.Function('inner_hess', [res_expr, p], [custom_hess]) |
||||||
|
|
||||||
|
Jt_ux_expr = ca.jacobian(inner_expr, ca.vertcat(u, x)).T |
||||||
|
Jt_z_expr = ca.jacobian(inner_expr, z).T |
||||||
|
|
||||||
|
cost_fun = ca.Function( |
||||||
|
fun_name_cost_fun, |
||||||
|
[x, u, z, yref, p], |
||||||
|
[cost_expr]) |
||||||
|
|
||||||
|
cost_fun_jac_hess = ca.Function( |
||||||
|
fun_name_cost_fun_jac_hess, |
||||||
|
[x, u, z, yref, p], |
||||||
|
[cost_expr, outer_loss_grad_fun(inner_expr, p), Jt_ux_expr, Jt_z_expr, outer_hess_fun(inner_expr, p)] |
||||||
|
) |
||||||
|
# change directory |
||||||
|
cwd = os.getcwd() |
||||||
|
cost_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model.name}_cost')) |
||||||
|
if not os.path.exists(cost_dir): |
||||||
|
os.makedirs(cost_dir) |
||||||
|
os.chdir(cost_dir) |
||||||
|
|
||||||
|
# generate C code |
||||||
|
cost_fun.generate(fun_name_cost_fun, casadi_codegen_opts) |
||||||
|
cost_fun_jac_hess.generate(fun_name_cost_fun_jac_hess, casadi_codegen_opts) |
||||||
|
|
||||||
|
os.chdir(cwd) |
||||||
|
|
||||||
|
return |
||||||
|
|
||||||
|
|
||||||
|
################ |
||||||
|
# Constraints |
||||||
|
################ |
||||||
|
def generate_c_code_constraint( model, con_name, is_terminal, opts ): |
||||||
|
|
||||||
|
casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
||||||
|
|
||||||
|
# load constraint variables and expression |
||||||
|
x = model.x |
||||||
|
p = model.p |
||||||
|
|
||||||
|
symbol = get_casadi_symbol(x) |
||||||
|
|
||||||
|
if is_terminal: |
||||||
|
con_h_expr = model.con_h_expr_e |
||||||
|
con_phi_expr = model.con_phi_expr_e |
||||||
|
# create dummy u, z |
||||||
|
u = symbol('u', 0, 0) |
||||||
|
z = symbol('z', 0, 0) |
||||||
|
else: |
||||||
|
con_h_expr = model.con_h_expr |
||||||
|
con_phi_expr = model.con_phi_expr |
||||||
|
u = model.u |
||||||
|
z = model.z |
||||||
|
|
||||||
|
if (not is_empty(con_h_expr)) and (not is_empty(con_phi_expr)): |
||||||
|
raise Exception("acados: you can either have constraint_h, or constraint_phi, not both.") |
||||||
|
|
||||||
|
if (is_empty(con_h_expr) and is_empty(con_phi_expr)): |
||||||
|
# both empty -> nothing to generate |
||||||
|
return |
||||||
|
|
||||||
|
if is_empty(con_h_expr): |
||||||
|
constr_type = 'BGP' |
||||||
|
else: |
||||||
|
constr_type = 'BGH' |
||||||
|
|
||||||
|
if is_empty(p): |
||||||
|
p = symbol('p', 0, 0) |
||||||
|
|
||||||
|
if is_empty(z): |
||||||
|
z = symbol('z', 0, 0) |
||||||
|
|
||||||
|
if not (is_empty(con_h_expr)) and opts['generate_hess']: |
||||||
|
# multipliers for hessian |
||||||
|
nh = casadi_length(con_h_expr) |
||||||
|
lam_h = symbol('lam_h', nh, 1) |
||||||
|
|
||||||
|
# set up & change directory |
||||||
|
cwd = os.getcwd() |
||||||
|
constraints_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model.name}_constraints')) |
||||||
|
if not os.path.exists(constraints_dir): |
||||||
|
os.makedirs(constraints_dir) |
||||||
|
os.chdir(constraints_dir) |
||||||
|
|
||||||
|
# export casadi functions |
||||||
|
if constr_type == 'BGH': |
||||||
|
if is_terminal: |
||||||
|
fun_name = con_name + '_constr_h_e_fun_jac_uxt_zt' |
||||||
|
else: |
||||||
|
fun_name = con_name + '_constr_h_fun_jac_uxt_zt' |
||||||
|
|
||||||
|
jac_ux_t = ca.transpose(ca.jacobian(con_h_expr, ca.vertcat(u,x))) |
||||||
|
jac_z_t = ca.jacobian(con_h_expr, z) |
||||||
|
constraint_fun_jac_tran = ca.Function(fun_name, [x, u, z, p], \ |
||||||
|
[con_h_expr, jac_ux_t, jac_z_t]) |
||||||
|
|
||||||
|
constraint_fun_jac_tran.generate(fun_name, casadi_codegen_opts) |
||||||
|
if opts['generate_hess']: |
||||||
|
|
||||||
|
if is_terminal: |
||||||
|
fun_name = con_name + '_constr_h_e_fun_jac_uxt_zt_hess' |
||||||
|
else: |
||||||
|
fun_name = con_name + '_constr_h_fun_jac_uxt_zt_hess' |
||||||
|
|
||||||
|
# adjoint |
||||||
|
adj_ux = ca.jtimes(con_h_expr, ca.vertcat(u, x), lam_h, True) |
||||||
|
# hessian |
||||||
|
hess_ux = ca.jacobian(adj_ux, ca.vertcat(u, x)) |
||||||
|
|
||||||
|
adj_z = ca.jtimes(con_h_expr, z, lam_h, True) |
||||||
|
hess_z = ca.jacobian(adj_z, z) |
||||||
|
|
||||||
|
# set up functions |
||||||
|
constraint_fun_jac_tran_hess = \ |
||||||
|
ca.Function(fun_name, [x, u, lam_h, z, p], \ |
||||||
|
[con_h_expr, jac_ux_t, hess_ux, jac_z_t, hess_z]) |
||||||
|
|
||||||
|
# generate C code |
||||||
|
constraint_fun_jac_tran_hess.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
if is_terminal: |
||||||
|
fun_name = con_name + '_constr_h_e_fun' |
||||||
|
else: |
||||||
|
fun_name = con_name + '_constr_h_fun' |
||||||
|
h_fun = ca.Function(fun_name, [x, u, z, p], [con_h_expr]) |
||||||
|
h_fun.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
else: # BGP constraint |
||||||
|
if is_terminal: |
||||||
|
fun_name = con_name + '_phi_e_constraint' |
||||||
|
r = model.con_r_in_phi_e |
||||||
|
con_r_expr = model.con_r_expr_e |
||||||
|
else: |
||||||
|
fun_name = con_name + '_phi_constraint' |
||||||
|
r = model.con_r_in_phi |
||||||
|
con_r_expr = model.con_r_expr |
||||||
|
|
||||||
|
nphi = casadi_length(con_phi_expr) |
||||||
|
con_phi_expr_x_u_z = ca.substitute(con_phi_expr, r, con_r_expr) |
||||||
|
phi_jac_u = ca.jacobian(con_phi_expr_x_u_z, u) |
||||||
|
phi_jac_x = ca.jacobian(con_phi_expr_x_u_z, x) |
||||||
|
phi_jac_z = ca.jacobian(con_phi_expr_x_u_z, z) |
||||||
|
|
||||||
|
hess = ca.hessian(con_phi_expr[0], r)[0] |
||||||
|
for i in range(1, nphi): |
||||||
|
hess = ca.vertcat(hess, ca.hessian(con_phi_expr[i], r)[0]) |
||||||
|
|
||||||
|
r_jac_u = ca.jacobian(con_r_expr, u) |
||||||
|
r_jac_x = ca.jacobian(con_r_expr, x) |
||||||
|
|
||||||
|
constraint_phi = \ |
||||||
|
ca.Function(fun_name, [x, u, z, p], \ |
||||||
|
[con_phi_expr_x_u_z, \ |
||||||
|
ca.vertcat(ca.transpose(phi_jac_u), ca.transpose(phi_jac_x)), \ |
||||||
|
ca.transpose(phi_jac_z), \ |
||||||
|
hess, |
||||||
|
ca.vertcat(ca.transpose(r_jac_u), ca.transpose(r_jac_x))]) |
||||||
|
|
||||||
|
constraint_phi.generate(fun_name, casadi_codegen_opts) |
||||||
|
|
||||||
|
# change directory back |
||||||
|
os.chdir(cwd) |
||||||
|
|
||||||
|
return |
||||||
|
|
@ -0,0 +1,819 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) The acados authors. |
||||||
|
* |
||||||
|
* This file is part of acados. |
||||||
|
* |
||||||
|
* The 2-Clause BSD License |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* |
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer in the documentation |
||||||
|
* and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
* POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
*/ |
||||||
|
|
||||||
|
// This is a template based custom_update function
|
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <assert.h> |
||||||
|
#include <math.h> |
||||||
|
|
||||||
|
#include "custom_update_function.h" |
||||||
|
#include "acados_solver_{{ model.name }}.h" |
||||||
|
#include "acados_c/ocp_nlp_interface.h" |
||||||
|
#include "acados/utils/mem.h" |
||||||
|
|
||||||
|
#include "blasfeo/include/blasfeo_d_aux_ext_dep.h" |
||||||
|
#include "blasfeo/include/blasfeo_d_blasfeo_api.h" |
||||||
|
|
||||||
|
|
||||||
|
typedef struct custom_memory |
||||||
|
{ |
||||||
|
// covariance matrics
|
||||||
|
struct blasfeo_dmat *uncertainty_matrix_buffer; // shape = (N+1, nx, nx)
|
||||||
|
// covariance matrix of the additive disturbance
|
||||||
|
struct blasfeo_dmat W_mat; // shape = (nw, nw)
|
||||||
|
struct blasfeo_dmat unc_jac_G_mat; // shape = (nx, nw)
|
||||||
|
struct blasfeo_dmat temp_GW_mat; // shape = (nx, nw)
|
||||||
|
struct blasfeo_dmat GWG_mat; // shape = (nx, nx)
|
||||||
|
// sensitivity matrices
|
||||||
|
struct blasfeo_dmat A_mat; // shape = (nx, nx)
|
||||||
|
struct blasfeo_dmat B_mat; // shape = (nx, nu)
|
||||||
|
// matrix in linear constraints
|
||||||
|
struct blasfeo_dmat Cg_mat; // shape = (ng, nx)
|
||||||
|
struct blasfeo_dmat Dg_mat; // shape = (ng, nu)
|
||||||
|
struct blasfeo_dmat Cg_e_mat; // shape = (ng_e, nx)
|
||||||
|
struct blasfeo_dmat dummy_Dgh_e_mat; // shape = (ngh_e_max, nu)
|
||||||
|
// matrix in nonlinear constraints
|
||||||
|
struct blasfeo_dmat Ch_mat; // shape = (nh, nx)
|
||||||
|
struct blasfeo_dmat Dh_mat; // shape = (nh, nu)
|
||||||
|
struct blasfeo_dmat Ch_e_mat; // shape = (nh_e, nx)
|
||||||
|
// feedback gain matrix
|
||||||
|
struct blasfeo_dmat K_mat; // shape = (nu, nx)
|
||||||
|
// AK = A - B@K
|
||||||
|
struct blasfeo_dmat AK_mat; // shape = (nx, nx)
|
||||||
|
// A@P_k
|
||||||
|
struct blasfeo_dmat temp_AP_mat; // shape = (nx, nx)
|
||||||
|
// K@P_k, K@P_k@K^T
|
||||||
|
struct blasfeo_dmat temp_KP_mat; // shape = (nu, nx)
|
||||||
|
struct blasfeo_dmat temp_KPK_mat; // shape = (nu, nu)
|
||||||
|
// C + D @ K, (C + D @ K) @ P_k
|
||||||
|
struct blasfeo_dmat temp_CaDK_mat; // shape = (ngh_me_max, nx)
|
||||||
|
struct blasfeo_dmat temp_CaDKmP_mat; // shape = (ngh_me_max, nx)
|
||||||
|
struct blasfeo_dmat temp_beta_mat; // shape = (ngh_me_max, ngh_me_max)
|
||||||
|
|
||||||
|
double *d_A_mat; // shape = (nx, nx)
|
||||||
|
double *d_B_mat; // shape = (nx, nu)
|
||||||
|
double *d_Cg_mat; // shape = (ng, nx)
|
||||||
|
double *d_Dg_mat; // shape = (ng, nu)
|
||||||
|
double *d_Cg_e_mat; // shape = (ng_e, nx)
|
||||||
|
double *d_Cgh_mat; // shape = (ng+nh, nx)
|
||||||
|
double *d_Dgh_mat; // shape = (ng+nh, nu)
|
||||||
|
double *d_Cgh_e_mat; // shape = (ng_e+nh_e, nx)
|
||||||
|
double *d_state_vec; |
||||||
|
// upper and lower bounds on state variables
|
||||||
|
double *d_lbx; // shape = (nbx,)
|
||||||
|
double *d_ubx; // shape = (nbx,)
|
||||||
|
double *d_lbx_e; // shape = (nbx_e,)
|
||||||
|
double *d_ubx_e; // shape = (nbx_e,)
|
||||||
|
// tightened upper and lower bounds on state variables
|
||||||
|
double *d_lbx_tightened; // shape = (nbx,)
|
||||||
|
double *d_ubx_tightened; // shape = (nbx,)
|
||||||
|
double *d_lbx_e_tightened; // shape = (nbx_e,)
|
||||||
|
double *d_ubx_e_tightened; // shape = (nbx_e,)
|
||||||
|
// upper and lower bounds on control inputs
|
||||||
|
double *d_lbu; // shape = (nbu,)
|
||||||
|
double *d_ubu; // shape = (nbu,)
|
||||||
|
// tightened upper and lower bounds on control inputs
|
||||||
|
double *d_lbu_tightened; // shape = (nbu,)
|
||||||
|
double *d_ubu_tightened; // shape = (nbu,)
|
||||||
|
// upper and lower bounds on polytopic constraints
|
||||||
|
double *d_lg; // shape = (ng,)
|
||||||
|
double *d_ug; // shape = (ng,)
|
||||||
|
double *d_lg_e; // shape = (ng_e,)
|
||||||
|
double *d_ug_e; // shape = (ng_e,)
|
||||||
|
// tightened lower bounds on polytopic constraints
|
||||||
|
double *d_lg_tightened; // shape = (ng,)
|
||||||
|
double *d_ug_tightened; // shape = (ng,)
|
||||||
|
double *d_lg_e_tightened; // shape = (ng_e,)
|
||||||
|
double *d_ug_e_tightened; // shape = (ng_e,)
|
||||||
|
// upper and lower bounds on nonlinear constraints
|
||||||
|
double *d_lh; // shape = (nh,)
|
||||||
|
double *d_uh; // shape = (nh,)
|
||||||
|
double *d_lh_e; // shape = (nh_e,)
|
||||||
|
double *d_uh_e; // shape = (nh_e,)
|
||||||
|
// tightened upper and lower bounds on nonlinear constraints
|
||||||
|
double *d_lh_tightened; // shape = (nh,)
|
||||||
|
double *d_uh_tightened; // shape = (nh,)
|
||||||
|
double *d_lh_e_tightened; // shape = (nh_e,)
|
||||||
|
double *d_uh_e_tightened; // shape = (nh_e,)
|
||||||
|
|
||||||
|
int *idxbx; // shape = (nbx,)
|
||||||
|
int *idxbu; // shape = (nbu,)
|
||||||
|
int *idxbx_e; // shape = (nbx_e,)
|
||||||
|
|
||||||
|
void *raw_memory; // Pointer to allocated memory, to be used for freeing
|
||||||
|
} custom_memory; |
||||||
|
|
||||||
|
static int int_max(int num1, int num2) |
||||||
|
{ |
||||||
|
return (num1 > num2 ) ? num1 : num2; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static int custom_memory_calculate_size(ocp_nlp_config *nlp_config, ocp_nlp_dims *nlp_dims) |
||||||
|
{ |
||||||
|
int N = nlp_dims->N; |
||||||
|
int nx = {{ dims.nx }}; |
||||||
|
int nu = {{ dims.nu }}; |
||||||
|
int nw = {{ zoro_description.nw }}; |
||||||
|
|
||||||
|
int ng = {{ dims.ng }}; |
||||||
|
int nh = {{ dims.nh }}; |
||||||
|
int nbx = {{ dims.nbx }}; |
||||||
|
int nbu = {{ dims.nbu }}; |
||||||
|
|
||||||
|
int ng_e = {{ dims.ng_e }}; |
||||||
|
int nh_e = {{ dims.nh_e }}; |
||||||
|
int ngh_e_max = int_max(ng_e, nh_e); |
||||||
|
int ngh_me_max = int_max(ngh_e_max, int_max(ng, nh)); |
||||||
|
int nbx_e = {{ dims.nbx_e }}; |
||||||
|
|
||||||
|
assert({{zoro_description.nlbx_t}} <= nbx); |
||||||
|
assert({{zoro_description.nubx_t}} <= nbx); |
||||||
|
assert({{zoro_description.nlbu_t}} <= nbu); |
||||||
|
assert({{zoro_description.nubu_t}} <= nbu); |
||||||
|
assert({{zoro_description.nlg_t}} <= ng); |
||||||
|
assert({{zoro_description.nug_t}} <= ng); |
||||||
|
assert({{zoro_description.nlh_t}} <= nh); |
||||||
|
assert({{zoro_description.nuh_t}} <= nh); |
||||||
|
assert({{zoro_description.nlbx_e_t}} <= nbx_e); |
||||||
|
assert({{zoro_description.nubx_e_t}} <= nbx_e); |
||||||
|
assert({{zoro_description.nlg_e_t}} <= ng_e); |
||||||
|
assert({{zoro_description.nug_e_t}} <= ng_e); |
||||||
|
assert({{zoro_description.nlh_e_t}} <= nh_e); |
||||||
|
assert({{zoro_description.nuh_e_t}} <= nh_e); |
||||||
|
|
||||||
|
acados_size_t size = sizeof(custom_memory); |
||||||
|
size += nbx * sizeof(int); |
||||||
|
/* blasfeo structs */ |
||||||
|
size += (N + 1) * sizeof(struct blasfeo_dmat); |
||||||
|
/* blasfeo mem: mat */ |
||||||
|
size += (N + 1) * blasfeo_memsize_dmat(nx, nx); // uncertainty_matrix_buffer
|
||||||
|
size += blasfeo_memsize_dmat(nw, nw); // W_mat
|
||||||
|
size += 2 * blasfeo_memsize_dmat(nx, nw); // unc_jac_G_mat, temp_GW_mat
|
||||||
|
size += 4 * blasfeo_memsize_dmat(nx, nx); // GWG_mat, A_mat, AK_mat, temp_AP_mat
|
||||||
|
size += blasfeo_memsize_dmat(nx, nu); // B_mat
|
||||||
|
size += 2 * blasfeo_memsize_dmat(nu, nx); // K_mat, temp_KP_mat
|
||||||
|
size += blasfeo_memsize_dmat(nu, nu); // temp_KPK_mat
|
||||||
|
size += blasfeo_memsize_dmat(ng, nx); // Cg_mat
|
||||||
|
size += blasfeo_memsize_dmat(ng, nu); // Dg_mat
|
||||||
|
size += blasfeo_memsize_dmat(ng_e, nx); // Cg_e_mat
|
||||||
|
size += blasfeo_memsize_dmat(ngh_e_max, nu); // dummy_Dgh_e_mat
|
||||||
|
size += blasfeo_memsize_dmat(nh, nx); // Ch_mat
|
||||||
|
size += blasfeo_memsize_dmat(nh, nu); // Dh_mat
|
||||||
|
size += blasfeo_memsize_dmat(nh_e, nx); // Ch_e_mat
|
||||||
|
size += 2 * blasfeo_memsize_dmat(ngh_me_max, nx); // temp_CaDK_mat, temp_CaDKmP_mat
|
||||||
|
size += blasfeo_memsize_dmat(ngh_me_max, ngh_me_max); // temp_beta_mat
|
||||||
|
/* blasfeo mem: vec */ |
||||||
|
/* Arrays */ |
||||||
|
size += nx*nx *sizeof(double); // d_A_mat
|
||||||
|
size += nx*nu *sizeof(double); // d_B_mat
|
||||||
|
size += (ng + ng_e) * nx * sizeof(double); // d_Cg_mat, d_Cg_e_mat
|
||||||
|
size += (ng) * nu * sizeof(double); // d_Dg_mat
|
||||||
|
size += (nh + nh_e + ng + ng_e) * nx * sizeof(double); // d_Cgh_mat, d_Cgh_e_mat
|
||||||
|
size += (nh + ng) * nu * sizeof(double); // d_Dgh_mat
|
||||||
|
// d_state_vec
|
||||||
|
size += nx *sizeof(double); |
||||||
|
// constraints and tightened constraints
|
||||||
|
size += 4 * (nbx + nbu + ng + nh)*sizeof(double); |
||||||
|
size += 4 * (nbx_e + ng_e + nh_e)*sizeof(double); |
||||||
|
size += (nbx + nbu + nbx_e)*sizeof(int); // idxbx, idxbu, idxbx_e
|
||||||
|
|
||||||
|
size += 1 * 8; // initial alignment
|
||||||
|
make_int_multiple_of(64, &size); |
||||||
|
size += 1 * 64; |
||||||
|
|
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static custom_memory *custom_memory_assign(ocp_nlp_config *nlp_config, ocp_nlp_dims *nlp_dims, void *raw_memory) |
||||||
|
{ |
||||||
|
int N = nlp_dims->N; |
||||||
|
int nx = {{ dims.nx }}; |
||||||
|
int nu = {{ dims.nu }}; |
||||||
|
int nw = {{ zoro_description.nw }}; |
||||||
|
|
||||||
|
int ng = {{ dims.ng }}; |
||||||
|
int nh = {{ dims.nh }}; |
||||||
|
int nbx = {{ dims.nbx }}; |
||||||
|
int nbu = {{ dims.nbu }}; |
||||||
|
|
||||||
|
int ng_e = {{ dims.ng_e }}; |
||||||
|
int nh_e = {{ dims.nh_e }}; |
||||||
|
int ngh_e_max = int_max(ng_e, nh_e); |
||||||
|
int ngh_me_max = int_max(ngh_e_max, int_max(ng, nh)); |
||||||
|
int nbx_e = {{ dims.nbx_e }}; |
||||||
|
|
||||||
|
char *c_ptr = (char *) raw_memory; |
||||||
|
custom_memory *mem = (custom_memory *) c_ptr; |
||||||
|
c_ptr += sizeof(custom_memory); |
||||||
|
|
||||||
|
align_char_to(8, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_structs(N+1, &mem->uncertainty_matrix_buffer, &c_ptr); |
||||||
|
|
||||||
|
align_char_to(64, &c_ptr); |
||||||
|
|
||||||
|
for (int ii = 0; ii <= N; ii++) |
||||||
|
{ |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->uncertainty_matrix_buffer[ii], &c_ptr); |
||||||
|
} |
||||||
|
// Disturbance Dynamics
|
||||||
|
assign_and_advance_blasfeo_dmat_mem(nw, nw, &mem->W_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nx, nw, &mem->unc_jac_G_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nx, nw, &mem->temp_GW_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->GWG_mat, &c_ptr); |
||||||
|
// System Dynamics
|
||||||
|
assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->A_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nx, nu, &mem->B_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(ng, nx, &mem->Cg_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(ng, nu, &mem->Dg_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(ng_e, nx, &mem->Cg_e_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(ngh_e_max, nu, &mem->dummy_Dgh_e_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nh, nx, &mem->Ch_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nh, nu, &mem->Dh_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nh_e, nx, &mem->Ch_e_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nu, nx, &mem->K_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->AK_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->temp_AP_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nu, nx, &mem->temp_KP_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(nu, nu, &mem->temp_KPK_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(ngh_me_max, nx, &mem->temp_CaDK_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(ngh_me_max, nx, &mem->temp_CaDKmP_mat, &c_ptr); |
||||||
|
assign_and_advance_blasfeo_dmat_mem(ngh_me_max, ngh_me_max, &mem->temp_beta_mat, &c_ptr); |
||||||
|
|
||||||
|
assign_and_advance_double(nx*nx, &mem->d_A_mat, &c_ptr); |
||||||
|
assign_and_advance_double(nx*nu, &mem->d_B_mat, &c_ptr); |
||||||
|
assign_and_advance_double(ng*nx, &mem->d_Cg_mat, &c_ptr); |
||||||
|
assign_and_advance_double(ng*nu, &mem->d_Dg_mat, &c_ptr); |
||||||
|
assign_and_advance_double(ng_e*nx, &mem->d_Cg_e_mat, &c_ptr); |
||||||
|
assign_and_advance_double((ng + nh)*nx, &mem->d_Cgh_mat, &c_ptr); |
||||||
|
assign_and_advance_double((ng + nh)*nu, &mem->d_Dgh_mat, &c_ptr); |
||||||
|
assign_and_advance_double((ng_e + nh_e)*nx, &mem->d_Cgh_e_mat, &c_ptr); |
||||||
|
assign_and_advance_double(nx, &mem->d_state_vec, &c_ptr); |
||||||
|
assign_and_advance_double(nbx, &mem->d_lbx, &c_ptr); |
||||||
|
assign_and_advance_double(nbx, &mem->d_ubx, &c_ptr); |
||||||
|
assign_and_advance_double(nbx_e, &mem->d_lbx_e, &c_ptr); |
||||||
|
assign_and_advance_double(nbx_e, &mem->d_ubx_e, &c_ptr); |
||||||
|
assign_and_advance_double(nbx, &mem->d_lbx_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nbx, &mem->d_ubx_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nbx_e, &mem->d_lbx_e_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nbx_e, &mem->d_ubx_e_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nbu, &mem->d_lbu, &c_ptr); |
||||||
|
assign_and_advance_double(nbu, &mem->d_ubu, &c_ptr); |
||||||
|
assign_and_advance_double(nbu, &mem->d_lbu_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nbu, &mem->d_ubu_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(ng, &mem->d_lg, &c_ptr); |
||||||
|
assign_and_advance_double(ng, &mem->d_ug, &c_ptr); |
||||||
|
assign_and_advance_double(ng_e, &mem->d_lg_e, &c_ptr); |
||||||
|
assign_and_advance_double(ng_e, &mem->d_ug_e, &c_ptr); |
||||||
|
assign_and_advance_double(ng, &mem->d_lg_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(ng, &mem->d_ug_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(ng_e, &mem->d_lg_e_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(ng_e, &mem->d_ug_e_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nh, &mem->d_lh, &c_ptr); |
||||||
|
assign_and_advance_double(nh, &mem->d_uh, &c_ptr); |
||||||
|
assign_and_advance_double(nh_e, &mem->d_lh_e, &c_ptr); |
||||||
|
assign_and_advance_double(nh_e, &mem->d_uh_e, &c_ptr); |
||||||
|
assign_and_advance_double(nh, &mem->d_lh_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nh, &mem->d_uh_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nh_e, &mem->d_lh_e_tightened, &c_ptr); |
||||||
|
assign_and_advance_double(nh_e, &mem->d_uh_e_tightened, &c_ptr); |
||||||
|
|
||||||
|
assign_and_advance_int(nbx, &mem->idxbx, &c_ptr); |
||||||
|
assign_and_advance_int(nbu, &mem->idxbu, &c_ptr); |
||||||
|
assign_and_advance_int(nbx_e, &mem->idxbx_e, &c_ptr); |
||||||
|
|
||||||
|
assert((char *) raw_memory + custom_memory_calculate_size(nlp_config, nlp_dims) >= c_ptr); |
||||||
|
mem->raw_memory = raw_memory; |
||||||
|
|
||||||
|
return mem; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void *custom_memory_create({{ model.name }}_solver_capsule* capsule) |
||||||
|
{ |
||||||
|
printf("\nin custom_memory_create_function\n"); |
||||||
|
|
||||||
|
ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(capsule); |
||||||
|
ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(capsule); |
||||||
|
acados_size_t bytes = custom_memory_calculate_size(nlp_config, nlp_dims); |
||||||
|
|
||||||
|
void *ptr = acados_calloc(1, bytes); |
||||||
|
|
||||||
|
custom_memory *custom_mem = custom_memory_assign(nlp_config, nlp_dims, ptr); |
||||||
|
custom_mem->raw_memory = ptr; |
||||||
|
|
||||||
|
return custom_mem; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static void custom_val_init_function(ocp_nlp_dims *nlp_dims, ocp_nlp_in *nlp_in, ocp_nlp_solver *nlp_solver, custom_memory *custom_mem) |
||||||
|
{ |
||||||
|
int N = nlp_dims->N; |
||||||
|
int nx = {{ dims.nx }}; |
||||||
|
int nu = {{ dims.nu }}; |
||||||
|
int nw = {{ zoro_description.nw }}; |
||||||
|
|
||||||
|
int ng = {{ dims.ng }}; |
||||||
|
int nh = {{ dims.nh }}; |
||||||
|
int nbx = {{ dims.nbx }}; |
||||||
|
int nbu = {{ dims.nbu }}; |
||||||
|
|
||||||
|
int ng_e = {{ dims.ng_e }}; |
||||||
|
int nh_e = {{ dims.nh_e }}; |
||||||
|
int ngh_e_max = int_max(ng_e, nh_e); |
||||||
|
int nbx_e = {{ dims.nbx_e }}; |
||||||
|
|
||||||
|
/* Get the state constraint bounds */ |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "idxbx", custom_mem->idxbx); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "idxbx", custom_mem->idxbx_e); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lbx", custom_mem->d_lbx); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ubx", custom_mem->d_ubx); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lbx", custom_mem->d_lbx_e); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "ubx", custom_mem->d_ubx_e); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "idxbu", custom_mem->idxbu); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lbu", custom_mem->d_lbu); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ubu", custom_mem->d_ubu); |
||||||
|
// Get the Jacobians and the bounds of the linear constraints
|
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lg", custom_mem->d_lg); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ug", custom_mem->d_ug); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lg", custom_mem->d_lg_e); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "ug", custom_mem->d_ug_e); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "C", custom_mem->d_Cg_mat); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "D", custom_mem->d_Dg_mat); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "C", custom_mem->d_Cg_e_mat); |
||||||
|
blasfeo_pack_dmat(ng, nx, custom_mem->d_Cg_mat, ng, &custom_mem->Cg_mat, 0, 0); |
||||||
|
blasfeo_pack_dmat(ng, nu, custom_mem->d_Dg_mat, ng, &custom_mem->Dg_mat, 0, 0); |
||||||
|
blasfeo_pack_dmat(ng_e, nx, custom_mem->d_Cg_e_mat, ng_e, &custom_mem->Cg_e_mat, 0, 0); |
||||||
|
blasfeo_dgese(ngh_e_max, nu, 0., &custom_mem->dummy_Dgh_e_mat, 0, 0); //fill with zeros
|
||||||
|
// NOTE: fixed lower and upper bounds of nonlinear constraints
|
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lh", custom_mem->d_lh); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "uh", custom_mem->d_uh); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lh", custom_mem->d_lh_e); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "uh", custom_mem->d_uh_e); |
||||||
|
|
||||||
|
/* Initilize tightened constraints*/ |
||||||
|
// NOTE: tightened constraints are only initialized once
|
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lbx", custom_mem->d_lbx_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ubx", custom_mem->d_ubx_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lbx", custom_mem->d_lbx_e_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "ubx", custom_mem->d_ubx_e_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lbu", custom_mem->d_lbu_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ubu", custom_mem->d_ubu_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lg", custom_mem->d_lg_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ug", custom_mem->d_ug_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lg", custom_mem->d_lg_e_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "ug", custom_mem->d_ug_e_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lh", custom_mem->d_lh_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "uh", custom_mem->d_uh_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lh", custom_mem->d_lh_e_tightened); |
||||||
|
ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "uh", custom_mem->d_uh_e_tightened); |
||||||
|
|
||||||
|
/* Initialize the W matrix */ |
||||||
|
// blasfeo_dgese(nw, nw, 0., &custom_mem->W_mat, 0, 0);
|
||||||
|
{%- for ir in range(end=zoro_description.nw) %} |
||||||
|
{%- for ic in range(end=zoro_description.nw) %} |
||||||
|
blasfeo_dgein1({{zoro_description.W_mat[ir][ic]}}, &custom_mem->W_mat, {{ir}}, {{ic}}); |
||||||
|
{%- endfor %} |
||||||
|
{%- endfor %} |
||||||
|
|
||||||
|
{%- for ir in range(end=dims.nx) %} |
||||||
|
{%- for ic in range(end=zoro_description.nw) %} |
||||||
|
blasfeo_dgein1({{zoro_description.unc_jac_G_mat[ir][ic]}}, &custom_mem->unc_jac_G_mat, {{ir}}, {{ic}}); |
||||||
|
{%- endfor %} |
||||||
|
{%- endfor %} |
||||||
|
|
||||||
|
// NOTE: if G is changing this is not in init!
|
||||||
|
// temp_GW_mat = unc_jac_G_mat * W_mat
|
||||||
|
blasfeo_dgemm_nn(nx, nw, nw, 1.0, &custom_mem->unc_jac_G_mat, 0, 0, |
||||||
|
&custom_mem->W_mat, 0, 0, 0.0, |
||||||
|
&custom_mem->temp_GW_mat, 0, 0, &custom_mem->temp_GW_mat, 0, 0); |
||||||
|
// GWG_mat = temp_GW_mat * unc_jac_G_mat^T
|
||||||
|
blasfeo_dgemm_nt(nx, nx, nw, 1.0, &custom_mem->temp_GW_mat, 0, 0, |
||||||
|
&custom_mem->unc_jac_G_mat, 0, 0, 0.0, |
||||||
|
&custom_mem->GWG_mat, 0, 0, &custom_mem->GWG_mat, 0, 0); |
||||||
|
|
||||||
|
/* Initialize the uncertainty_matrix_buffer[0] */ |
||||||
|
{%- for ir in range(end=dims.nx) %} |
||||||
|
{%- for ic in range(end=dims.nx) %} |
||||||
|
blasfeo_dgein1({{zoro_description.P0_mat[ir][ic]}}, &custom_mem->uncertainty_matrix_buffer[0], {{ir}}, {{ic}}); |
||||||
|
{%- endfor %} |
||||||
|
{%- endfor %} |
||||||
|
|
||||||
|
/* Initialize the feedback gain matrix */ |
||||||
|
{%- for ir in range(end=dims.nu) %} |
||||||
|
{%- for ic in range(end=dims.nx) %} |
||||||
|
blasfeo_dgein1({{zoro_description.fdbk_K_mat[ir][ic]}}, &custom_mem->K_mat, {{ir}}, {{ic}}); |
||||||
|
{%- endfor %} |
||||||
|
{%- endfor %} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int custom_update_init_function({{ model.name }}_solver_capsule* capsule) |
||||||
|
{ |
||||||
|
capsule->custom_update_memory = custom_memory_create(capsule); |
||||||
|
ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(capsule); |
||||||
|
|
||||||
|
ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(capsule); |
||||||
|
ocp_nlp_solver *nlp_solver = {{ model.name }}_acados_get_nlp_solver(capsule); |
||||||
|
custom_val_init_function(nlp_dims, nlp_in, nlp_solver, capsule->custom_update_memory); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
static void compute_gh_beta(struct blasfeo_dmat* K_mat, struct blasfeo_dmat* C_mat, |
||||||
|
struct blasfeo_dmat* D_mat, struct blasfeo_dmat* CaDK_mat, |
||||||
|
struct blasfeo_dmat* CaDKmP_mat, struct blasfeo_dmat* beta_mat, |
||||||
|
struct blasfeo_dmat* P_mat, |
||||||
|
int n_cstr, int nx, int nu) |
||||||
|
{ |
||||||
|
// (C+DK)@P@(C^T+K^TD^T)
|
||||||
|
// CaDK_mat = C_mat + D_mat @ K_mat
|
||||||
|
blasfeo_dgemm_nn(n_cstr, nx, nu, 1.0, D_mat, 0, 0, |
||||||
|
K_mat, 0, 0, 1.0, |
||||||
|
C_mat, 0, 0, CaDK_mat, 0, 0); |
||||||
|
// CaDKmP_mat = CaDK_mat @ P_mat
|
||||||
|
blasfeo_dgemm_nn(n_cstr, nx, nx, 1.0, CaDK_mat, 0, 0, |
||||||
|
P_mat, 0, 0, 0.0, |
||||||
|
CaDKmP_mat, 0, 0, CaDKmP_mat, 0, 0); |
||||||
|
// beta_mat = CaDKmP_mat @ CaDK_mat^T
|
||||||
|
blasfeo_dgemm_nt(n_cstr, n_cstr, nx, 1.0, CaDKmP_mat, 0, 0, |
||||||
|
CaDK_mat, 0, 0, 0.0, |
||||||
|
beta_mat, 0, 0, beta_mat, 0, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void compute_KPK(struct blasfeo_dmat* K_mat, struct blasfeo_dmat* temp_KP_mat, |
||||||
|
struct blasfeo_dmat* temp_KPK_mat, struct blasfeo_dmat* P_mat, |
||||||
|
int nx, int nu) |
||||||
|
{ |
||||||
|
// K @ P_k @ K^T
|
||||||
|
// temp_KP_mat = K_mat @ P_mat
|
||||||
|
blasfeo_dgemm_nn(nu, nx, nx, 1.0, K_mat, 0, 0, |
||||||
|
P_mat, 0, 0, 0.0, |
||||||
|
temp_KP_mat, 0, 0, temp_KP_mat, 0, 0); |
||||||
|
// temp_KPK_mat = temp_KP_mat @ K_mat^T
|
||||||
|
blasfeo_dgemm_nt(nu, nu, nx, 1.0, temp_KP_mat, 0, 0, |
||||||
|
K_mat, 0, 0, 0.0, |
||||||
|
temp_KPK_mat, 0, 0, temp_KPK_mat, 0, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void compute_next_P_matrix(struct blasfeo_dmat* P_mat, struct blasfeo_dmat* P_next_mat, |
||||||
|
struct blasfeo_dmat* A_mat, struct blasfeo_dmat* B_mat, |
||||||
|
struct blasfeo_dmat* K_mat, struct blasfeo_dmat* W_mat, |
||||||
|
struct blasfeo_dmat* AK_mat, struct blasfeo_dmat* temp_AP_mat, int nx, int nu) |
||||||
|
{ |
||||||
|
// AK_mat = -B@K + A
|
||||||
|
blasfeo_dgemm_nn(nx, nx, nu, -1.0, B_mat, 0, 0, K_mat, 0, 0, |
||||||
|
1.0, A_mat, 0, 0, AK_mat, 0, 0); |
||||||
|
// temp_AP_mat = AK_mat @ P_k
|
||||||
|
blasfeo_dgemm_nn(nx, nx, nx, 1.0, AK_mat, 0, 0, |
||||||
|
P_mat, 0, 0, 0.0, |
||||||
|
temp_AP_mat, 0, 0, temp_AP_mat, 0, 0); |
||||||
|
// P_{k+1} = temp_AP_mat @ AK_mat^T + GWG_mat
|
||||||
|
blasfeo_dgemm_nt(nx, nx, nx, 1.0, temp_AP_mat, 0, 0, |
||||||
|
AK_mat, 0, 0, 1.0, |
||||||
|
W_mat, 0, 0, P_next_mat, 0, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void reset_P0_matrix(ocp_nlp_dims *nlp_dims, struct blasfeo_dmat* P_mat, double* data) |
||||||
|
{ |
||||||
|
int nx = nlp_dims->nx[0]; |
||||||
|
blasfeo_pack_dmat(nx, nx, data, nx, P_mat, 0, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void uncertainty_propagate_and_update(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out, custom_memory *custom_mem) |
||||||
|
{ |
||||||
|
ocp_nlp_config *nlp_config = solver->config; |
||||||
|
ocp_nlp_dims *nlp_dims = solver->dims; |
||||||
|
|
||||||
|
int N = nlp_dims->N; |
||||||
|
int nx = nlp_dims->nx[0]; |
||||||
|
int nu = nlp_dims->nu[0]; |
||||||
|
int nx_sqr = nx*nx; |
||||||
|
int nbx = {{ dims.nbx }}; |
||||||
|
int nbu = {{ dims.nbu }}; |
||||||
|
int ng = {{ dims.ng }}; |
||||||
|
int nh = {{ dims.nh }}; |
||||||
|
int ng_e = {{ dims.ng_e }}; |
||||||
|
int nh_e = {{ dims.nh_e }}; |
||||||
|
int nbx_e = {{ dims.nbx_e }}; |
||||||
|
double backoff_scaling_gamma = {{ zoro_description.backoff_scaling_gamma }}; |
||||||
|
|
||||||
|
// First Stage
|
||||||
|
// NOTE: lbx_0 and ubx_0 should not be tightened.
|
||||||
|
// NOTE: lg_0 and ug_0 are not tightened.
|
||||||
|
// NOTE: lh_0 and uh_0 are not tightened.
|
||||||
|
{%- if zoro_description.nlbu_t + zoro_description.nubu_t > 0 %} |
||||||
|
compute_KPK(&custom_mem->K_mat, &custom_mem->temp_KP_mat, |
||||||
|
&custom_mem->temp_KPK_mat, &(custom_mem->uncertainty_matrix_buffer[0]), nx, nu); |
||||||
|
|
||||||
|
{%- if zoro_description.nlbu_t > 0 %} |
||||||
|
// backoff lbu
|
||||||
|
{%- for it in zoro_description.idx_lbu_t %} |
||||||
|
custom_mem->d_lbu_tightened[{{it}}] |
||||||
|
= custom_mem->d_lbu[{{it}}] |
||||||
|
+ backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_KPK_mat, |
||||||
|
custom_mem->idxbu[{{it}}],custom_mem->idxbu[{{it}}])); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lbu", custom_mem->d_lbu_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- if zoro_description.nubu_t > 0 %} |
||||||
|
// backoff ubu
|
||||||
|
{%- for it in zoro_description.idx_ubu_t %} |
||||||
|
custom_mem->d_ubu_tightened[{{it}}] |
||||||
|
= custom_mem->d_ubu[{{it}}] |
||||||
|
- backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_KPK_mat, |
||||||
|
custom_mem->idxbu[{{it}}],custom_mem->idxbu[{{it}}])); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "ubu", custom_mem->d_ubu_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- endif %} |
||||||
|
// Middle Stages
|
||||||
|
// constraint tightening: for next stage based on dynamics of ii stage
|
||||||
|
// P[ii+1] = (A-B@K) @ P[ii] @ (A-B@K).T + G@W@G.T
|
||||||
|
for (int ii = 0; ii < N-1; ii++) |
||||||
|
{ |
||||||
|
// get and pack: A, B
|
||||||
|
ocp_nlp_get_at_stage(nlp_config, nlp_dims, solver, ii, "A", custom_mem->d_A_mat); |
||||||
|
blasfeo_pack_dmat(nx, nx, custom_mem->d_A_mat, nx, &custom_mem->A_mat, 0, 0); |
||||||
|
ocp_nlp_get_at_stage(nlp_config, nlp_dims, solver, ii, "B", custom_mem->d_B_mat); |
||||||
|
blasfeo_pack_dmat(nx, nu, custom_mem->d_B_mat, nx, &custom_mem->B_mat, 0, 0); |
||||||
|
|
||||||
|
compute_next_P_matrix(&(custom_mem->uncertainty_matrix_buffer[ii]), |
||||||
|
&(custom_mem->uncertainty_matrix_buffer[ii+1]), |
||||||
|
&custom_mem->A_mat, &custom_mem->B_mat, |
||||||
|
&custom_mem->K_mat, &custom_mem->GWG_mat, |
||||||
|
&custom_mem->AK_mat, &custom_mem->temp_AP_mat, nx, nu); |
||||||
|
|
||||||
|
// state constraints
|
||||||
|
{%- if zoro_description.nlbx_t + zoro_description.nubx_t> 0 %} |
||||||
|
{%- if zoro_description.nlbx_t > 0 %} |
||||||
|
// lbx
|
||||||
|
{%- for it in zoro_description.idx_lbx_t %} |
||||||
|
custom_mem->d_lbx_tightened[{{it}}] |
||||||
|
= custom_mem->d_lbx[{{it}}] |
||||||
|
+ backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->uncertainty_matrix_buffer[ii+1], |
||||||
|
custom_mem->idxbx[{{it}}],custom_mem->idxbx[{{it}}])); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "lbx", custom_mem->d_lbx_tightened); |
||||||
|
{%- endif %} |
||||||
|
{% if zoro_description.nubx_t > 0 %} |
||||||
|
// ubx
|
||||||
|
{%- for it in zoro_description.idx_ubx_t %} |
||||||
|
custom_mem->d_ubx_tightened[{{it}}] = custom_mem->d_ubx[{{it}}] |
||||||
|
- backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->uncertainty_matrix_buffer[ii+1], |
||||||
|
custom_mem->idxbx[{{it}}],custom_mem->idxbx[{{it}}])); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "ubx", custom_mem->d_ubx_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- endif %} |
||||||
|
|
||||||
|
{%- if zoro_description.nlbu_t + zoro_description.nubu_t > 0 %} |
||||||
|
// input constraints
|
||||||
|
compute_KPK(&custom_mem->K_mat, &custom_mem->temp_KP_mat, |
||||||
|
&custom_mem->temp_KPK_mat, &(custom_mem->uncertainty_matrix_buffer[ii+1]), nx, nu); |
||||||
|
|
||||||
|
{%- if zoro_description.nlbu_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_lbu_t %} |
||||||
|
custom_mem->d_lbu_tightened[{{it}}] = custom_mem->d_lbu[{{it}}] |
||||||
|
+ backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_KPK_mat, |
||||||
|
custom_mem->idxbu[{{it}}], custom_mem->idxbu[{{it}}])); |
||||||
|
{%- endfor %} |
||||||
|
|
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "lbu", custom_mem->d_lbu_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- if zoro_description.nubu_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_ubu_t %} |
||||||
|
custom_mem->d_ubu_tightened[{{it}}] = custom_mem->d_ubu[{{it}}] |
||||||
|
- backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_KPK_mat, |
||||||
|
custom_mem->idxbu[{{it}}], custom_mem->idxbu[{{it}}])); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "ubu", custom_mem->d_ubu_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- endif %} |
||||||
|
|
||||||
|
{%- if zoro_description.nlg_t + zoro_description.nug_t > 0 %} |
||||||
|
// Linear constraints: g
|
||||||
|
compute_gh_beta(&custom_mem->K_mat, &custom_mem->Cg_mat, |
||||||
|
&custom_mem->Dg_mat, &custom_mem->temp_CaDK_mat, |
||||||
|
&custom_mem->temp_CaDKmP_mat, &custom_mem->temp_beta_mat, |
||||||
|
&custom_mem->uncertainty_matrix_buffer[ii+1], ng, nx, nu); |
||||||
|
|
||||||
|
{%- if zoro_description.nlg_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_lg_t %} |
||||||
|
custom_mem->d_lg_tightened[{{it}}] |
||||||
|
= custom_mem->d_lg[{{it}}] |
||||||
|
+ backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "lg", custom_mem->d_lg_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- if zoro_description.nug_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_ug_t %} |
||||||
|
custom_mem->d_ug_tightened[{{it}}] |
||||||
|
= custom_mem->d_ug[{{it}}] |
||||||
|
- backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "ug", custom_mem->d_ug_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- endif %} |
||||||
|
|
||||||
|
|
||||||
|
{%- if zoro_description.nlh_t + zoro_description.nuh_t > 0 %} |
||||||
|
// nonlinear constraints: h
|
||||||
|
// Get C_{k+1} and D_{k+1}
|
||||||
|
ocp_nlp_get_at_stage(solver->config, nlp_dims, solver, ii+1, "C", custom_mem->d_Cgh_mat); |
||||||
|
ocp_nlp_get_at_stage(solver->config, nlp_dims, solver, ii+1, "D", custom_mem->d_Dgh_mat); |
||||||
|
// NOTE: the d_Cgh_mat is column-major, the first ng rows are the Jacobians of the linear constraints
|
||||||
|
blasfeo_pack_dmat(nh, nx, custom_mem->d_Cgh_mat+ng, ng+nh, &custom_mem->Ch_mat, 0, 0); |
||||||
|
blasfeo_pack_dmat(nh, nu, custom_mem->d_Dgh_mat+ng, ng+nh, &custom_mem->Dh_mat, 0, 0); |
||||||
|
|
||||||
|
compute_gh_beta(&custom_mem->K_mat, &custom_mem->Ch_mat, |
||||||
|
&custom_mem->Dh_mat, &custom_mem->temp_CaDK_mat, |
||||||
|
&custom_mem->temp_CaDKmP_mat, &custom_mem->temp_beta_mat, |
||||||
|
&custom_mem->uncertainty_matrix_buffer[ii+1], nh, nx, nu); |
||||||
|
|
||||||
|
{%- if zoro_description.nlh_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_lh_t %} |
||||||
|
custom_mem->d_lh_tightened[{{it}}] |
||||||
|
= custom_mem->d_lh[{{it}}] |
||||||
|
+ backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "lh", custom_mem->d_lh_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- if zoro_description.nuh_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_uh_t %} |
||||||
|
custom_mem->d_uh_tightened[{{it}}] = custom_mem->d_uh[{{it}}] |
||||||
|
- backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "uh", custom_mem->d_uh_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- endif %} |
||||||
|
} |
||||||
|
|
||||||
|
// Last stage
|
||||||
|
// get and pack: A, B
|
||||||
|
ocp_nlp_get_at_stage(nlp_config, nlp_dims, solver, N-1, "A", custom_mem->d_A_mat); |
||||||
|
blasfeo_pack_dmat(nx, nx, custom_mem->d_A_mat, nx, &custom_mem->A_mat, 0, 0); |
||||||
|
ocp_nlp_get_at_stage(nlp_config, nlp_dims, solver, N-1, "B", custom_mem->d_B_mat); |
||||||
|
blasfeo_pack_dmat(nx, nu, custom_mem->d_B_mat, nx, &custom_mem->B_mat, 0, 0); |
||||||
|
// AK_mat = -B*K + A
|
||||||
|
compute_next_P_matrix(&(custom_mem->uncertainty_matrix_buffer[N-1]), |
||||||
|
&(custom_mem->uncertainty_matrix_buffer[N]), |
||||||
|
&custom_mem->A_mat, &custom_mem->B_mat, |
||||||
|
&custom_mem->K_mat, &custom_mem->GWG_mat, |
||||||
|
&custom_mem->AK_mat, &custom_mem->temp_AP_mat, nx, nu); |
||||||
|
|
||||||
|
// state constraints nlbx_e_t
|
||||||
|
{%- if zoro_description.nlbx_e_t + zoro_description.nubx_e_t> 0 %} |
||||||
|
{%- if zoro_description.nlbx_e_t > 0 %} |
||||||
|
// lbx_e
|
||||||
|
{%- for it in zoro_description.idx_lbx_e_t %} |
||||||
|
custom_mem->d_lbx_e_tightened[{{it}}] |
||||||
|
= custom_mem->d_lbx_e[{{it}}] |
||||||
|
+ backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->uncertainty_matrix_buffer[N], |
||||||
|
custom_mem->idxbx_e[{{it}}],custom_mem->idxbx_e[{{it}}])); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lbx", custom_mem->d_lbx_e_tightened); |
||||||
|
{%- endif %} |
||||||
|
{% if zoro_description.nubx_e_t > 0 %} |
||||||
|
// ubx_e
|
||||||
|
{%- for it in zoro_description.idx_ubx_e_t %} |
||||||
|
custom_mem->d_ubx_e_tightened[{{it}}] = custom_mem->d_ubx_e[{{it}}] |
||||||
|
- backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->uncertainty_matrix_buffer[N], |
||||||
|
custom_mem->idxbx_e[{{it}}],custom_mem->idxbx_e[{{it}}])); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ubx", custom_mem->d_ubx_e_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- endif %} |
||||||
|
|
||||||
|
{%- if zoro_description.nlg_e_t + zoro_description.nug_e_t > 0 %} |
||||||
|
// Linear constraints: g
|
||||||
|
compute_gh_beta(&custom_mem->K_mat, &custom_mem->Cg_mat, |
||||||
|
&custom_mem->dummy_Dgh_e_mat, &custom_mem->temp_CaDK_mat, |
||||||
|
&custom_mem->temp_CaDKmP_mat, &custom_mem->temp_beta_mat, |
||||||
|
&custom_mem->uncertainty_matrix_buffer[N], ng, nx, nu); |
||||||
|
|
||||||
|
{%- if zoro_description.nlg_e_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_lg_e_t %} |
||||||
|
custom_mem->d_lg_e_tightened[{{it}}] |
||||||
|
= custom_mem->d_lg_e[{{it}}] |
||||||
|
+ backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lg", custom_mem->d_lg_e_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- if zoro_description.nug_e_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_ug_e_t %} |
||||||
|
custom_mem->d_ug_e_tightened[{{it}}] |
||||||
|
= custom_mem->d_ug_e[{{it}}] |
||||||
|
- backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ug", custom_mem->d_ug_e_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- endif %} |
||||||
|
|
||||||
|
|
||||||
|
{%- if zoro_description.nlh_e_t + zoro_description.nuh_e_t > 0 %} |
||||||
|
// nonlinear constraints: h
|
||||||
|
// Get C_{k+1} and D_{k+1}
|
||||||
|
ocp_nlp_get_at_stage(solver->config, nlp_dims, solver, N, "C", custom_mem->d_Cgh_mat); |
||||||
|
// NOTE: the d_Cgh_mat is column-major, the first ng rows are the Jacobians of the linear constraints
|
||||||
|
blasfeo_pack_dmat(nh, nx, custom_mem->d_Cgh_mat+ng, ng+nh, &custom_mem->Ch_mat, 0, 0); |
||||||
|
|
||||||
|
compute_gh_beta(&custom_mem->K_mat, &custom_mem->Ch_mat, |
||||||
|
&custom_mem->dummy_Dgh_e_mat, &custom_mem->temp_CaDK_mat, |
||||||
|
&custom_mem->temp_CaDKmP_mat, &custom_mem->temp_beta_mat, |
||||||
|
&custom_mem->uncertainty_matrix_buffer[N], nh, nx, nu); |
||||||
|
|
||||||
|
{%- if zoro_description.nlh_e_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_lh_e_t %} |
||||||
|
custom_mem->d_lh_e_tightened[{{it}}] |
||||||
|
= custom_mem->d_lh_e[{{it}}] |
||||||
|
+ backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lh", custom_mem->d_lh_e_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- if zoro_description.nuh_e_t > 0 %} |
||||||
|
{%- for it in zoro_description.idx_uh_e_t %} |
||||||
|
custom_mem->d_uh_e_tightened[{{it}}] = custom_mem->d_uh_e[{{it}}] |
||||||
|
- backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); |
||||||
|
{%- endfor %} |
||||||
|
ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "uh", custom_mem->d_uh_e_tightened); |
||||||
|
{%- endif %} |
||||||
|
{%- endif %} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int custom_update_function({{ model.name }}_solver_capsule* capsule, double* data, int data_len) |
||||||
|
{ |
||||||
|
custom_memory *custom_mem = (custom_memory *) capsule->custom_update_memory; |
||||||
|
ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(capsule); |
||||||
|
ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(capsule); |
||||||
|
ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(capsule); |
||||||
|
ocp_nlp_out *nlp_out = {{ model.name }}_acados_get_nlp_out(capsule); |
||||||
|
ocp_nlp_solver *nlp_solver = {{ model.name }}_acados_get_nlp_solver(capsule); |
||||||
|
void *nlp_opts = {{ model.name }}_acados_get_nlp_opts(capsule); |
||||||
|
|
||||||
|
if (data_len > 0) |
||||||
|
{ |
||||||
|
reset_P0_matrix(nlp_dims, &custom_mem->uncertainty_matrix_buffer[0], data); |
||||||
|
} |
||||||
|
uncertainty_propagate_and_update(nlp_solver, nlp_in, nlp_out, custom_mem); |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int custom_update_terminate_function({{ model.name }}_solver_capsule* capsule) |
||||||
|
{ |
||||||
|
custom_memory *mem = capsule->custom_update_memory; |
||||||
|
|
||||||
|
free(mem->raw_memory); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
// useful prints for debugging
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf("A_mat:\n"); |
||||||
|
blasfeo_print_exp_dmat(nx, nx, &custom_mem->A_mat, 0, 0); |
||||||
|
printf("B_mat:\n"); |
||||||
|
blasfeo_print_exp_dmat(nx, nu, &custom_mem->B_mat, 0, 0); |
||||||
|
printf("K_mat:\n"); |
||||||
|
blasfeo_print_exp_dmat(nu, nx, &custom_mem->K_mat, 0, 0); |
||||||
|
printf("AK_mat:\n"); |
||||||
|
blasfeo_print_exp_dmat(nx, nx, &custom_mem->AK_mat, 0, 0); |
||||||
|
printf("temp_AP_mat:\n"); |
||||||
|
blasfeo_print_exp_dmat(nx, nx, &custom_mem->temp_AP_mat, 0, 0); |
||||||
|
printf("W_mat:\n"); |
||||||
|
blasfeo_print_exp_dmat(nx, nx, &custom_mem->W_mat, 0, 0); |
||||||
|
printf("P_k+1:\n"); |
||||||
|
blasfeo_print_exp_dmat(nx, nx, &(custom_mem->uncertainty_matrix_buffer[ii+1]), 0, 0);*/ |
@ -1,180 +0,0 @@ |
|||||||
# |
|
||||||
# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
# |
|
||||||
# This file is part of acados. |
|
||||||
# |
|
||||||
# The 2-Clause BSD License |
|
||||||
# |
|
||||||
# Redistribution and use in source and binary forms, with or without |
|
||||||
# modification, are permitted provided that the following conditions are met: |
|
||||||
# |
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer. |
|
||||||
# |
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer in the documentation |
|
||||||
# and/or other materials provided with the distribution. |
|
||||||
# |
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
# POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
# |
|
||||||
|
|
||||||
import os |
|
||||||
from casadi import * |
|
||||||
from .utils import ALLOWED_CASADI_VERSIONS, is_empty, casadi_length, casadi_version_warning |
|
||||||
|
|
||||||
def generate_c_code_constraint( model, con_name, is_terminal, opts ): |
|
||||||
|
|
||||||
casadi_version = CasadiMeta.version() |
|
||||||
casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
|
||||||
|
|
||||||
if casadi_version not in (ALLOWED_CASADI_VERSIONS): |
|
||||||
casadi_version_warning(casadi_version) |
|
||||||
|
|
||||||
# load constraint variables and expression |
|
||||||
x = model.x |
|
||||||
p = model.p |
|
||||||
|
|
||||||
if isinstance(x, casadi.MX): |
|
||||||
symbol = MX.sym |
|
||||||
else: |
|
||||||
symbol = SX.sym |
|
||||||
|
|
||||||
if is_terminal: |
|
||||||
con_h_expr = model.con_h_expr_e |
|
||||||
con_phi_expr = model.con_phi_expr_e |
|
||||||
# create dummy u, z |
|
||||||
u = symbol('u', 0, 0) |
|
||||||
z = symbol('z', 0, 0) |
|
||||||
else: |
|
||||||
con_h_expr = model.con_h_expr |
|
||||||
con_phi_expr = model.con_phi_expr |
|
||||||
u = model.u |
|
||||||
z = model.z |
|
||||||
|
|
||||||
if (not is_empty(con_h_expr)) and (not is_empty(con_phi_expr)): |
|
||||||
raise Exception("acados: you can either have constraint_h, or constraint_phi, not both.") |
|
||||||
|
|
||||||
if not (is_empty(con_h_expr) and is_empty(con_phi_expr)): |
|
||||||
if is_empty(con_h_expr): |
|
||||||
constr_type = 'BGP' |
|
||||||
else: |
|
||||||
constr_type = 'BGH' |
|
||||||
|
|
||||||
if is_empty(p): |
|
||||||
p = symbol('p', 0, 0) |
|
||||||
|
|
||||||
if is_empty(z): |
|
||||||
z = symbol('z', 0, 0) |
|
||||||
|
|
||||||
if not (is_empty(con_h_expr)) and opts['generate_hess']: |
|
||||||
# multipliers for hessian |
|
||||||
nh = casadi_length(con_h_expr) |
|
||||||
lam_h = symbol('lam_h', nh, 1) |
|
||||||
|
|
||||||
# set up & change directory |
|
||||||
code_export_dir = opts["code_export_directory"] |
|
||||||
if not os.path.exists(code_export_dir): |
|
||||||
os.makedirs(code_export_dir) |
|
||||||
|
|
||||||
cwd = os.getcwd() |
|
||||||
os.chdir(code_export_dir) |
|
||||||
gen_dir = con_name + '_constraints' |
|
||||||
if not os.path.exists(gen_dir): |
|
||||||
os.mkdir(gen_dir) |
|
||||||
gen_dir_location = os.path.join('.', gen_dir) |
|
||||||
os.chdir(gen_dir_location) |
|
||||||
|
|
||||||
# export casadi functions |
|
||||||
if constr_type == 'BGH': |
|
||||||
if is_terminal: |
|
||||||
fun_name = con_name + '_constr_h_e_fun_jac_uxt_zt' |
|
||||||
else: |
|
||||||
fun_name = con_name + '_constr_h_fun_jac_uxt_zt' |
|
||||||
|
|
||||||
jac_ux_t = transpose(jacobian(con_h_expr, vertcat(u,x))) |
|
||||||
jac_z_t = jacobian(con_h_expr, z) |
|
||||||
constraint_fun_jac_tran = Function(fun_name, [x, u, z, p], \ |
|
||||||
[con_h_expr, jac_ux_t, jac_z_t]) |
|
||||||
|
|
||||||
constraint_fun_jac_tran.generate(fun_name, casadi_opts) |
|
||||||
if opts['generate_hess']: |
|
||||||
|
|
||||||
if is_terminal: |
|
||||||
fun_name = con_name + '_constr_h_e_fun_jac_uxt_zt_hess' |
|
||||||
else: |
|
||||||
fun_name = con_name + '_constr_h_fun_jac_uxt_zt_hess' |
|
||||||
|
|
||||||
# adjoint |
|
||||||
adj_ux = jtimes(con_h_expr, vertcat(u, x), lam_h, True) |
|
||||||
# hessian |
|
||||||
hess_ux = jacobian(adj_ux, vertcat(u, x)) |
|
||||||
|
|
||||||
adj_z = jtimes(con_h_expr, z, lam_h, True) |
|
||||||
hess_z = jacobian(adj_z, z) |
|
||||||
|
|
||||||
# set up functions |
|
||||||
constraint_fun_jac_tran_hess = \ |
|
||||||
Function(fun_name, [x, u, lam_h, z, p], \ |
|
||||||
[con_h_expr, jac_ux_t, hess_ux, jac_z_t, hess_z]) |
|
||||||
|
|
||||||
# generate C code |
|
||||||
constraint_fun_jac_tran_hess.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
if is_terminal: |
|
||||||
fun_name = con_name + '_constr_h_e_fun' |
|
||||||
else: |
|
||||||
fun_name = con_name + '_constr_h_fun' |
|
||||||
h_fun = Function(fun_name, [x, u, z, p], [con_h_expr]) |
|
||||||
h_fun.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
else: # BGP constraint |
|
||||||
if is_terminal: |
|
||||||
fun_name = con_name + '_phi_e_constraint' |
|
||||||
r = model.con_r_in_phi_e |
|
||||||
con_r_expr = model.con_r_expr_e |
|
||||||
else: |
|
||||||
fun_name = con_name + '_phi_constraint' |
|
||||||
r = model.con_r_in_phi |
|
||||||
con_r_expr = model.con_r_expr |
|
||||||
|
|
||||||
nphi = casadi_length(con_phi_expr) |
|
||||||
con_phi_expr_x_u_z = substitute(con_phi_expr, r, con_r_expr) |
|
||||||
phi_jac_u = jacobian(con_phi_expr_x_u_z, u) |
|
||||||
phi_jac_x = jacobian(con_phi_expr_x_u_z, x) |
|
||||||
phi_jac_z = jacobian(con_phi_expr_x_u_z, z) |
|
||||||
|
|
||||||
hess = hessian(con_phi_expr[0], r)[0] |
|
||||||
for i in range(1, nphi): |
|
||||||
hess = vertcat(hess, hessian(con_phi_expr[i], r)[0]) |
|
||||||
|
|
||||||
r_jac_u = jacobian(con_r_expr, u) |
|
||||||
r_jac_x = jacobian(con_r_expr, x) |
|
||||||
|
|
||||||
constraint_phi = \ |
|
||||||
Function(fun_name, [x, u, z, p], \ |
|
||||||
[con_phi_expr_x_u_z, \ |
|
||||||
vertcat(transpose(phi_jac_u), \ |
|
||||||
transpose(phi_jac_x)), \ |
|
||||||
transpose(phi_jac_z), \ |
|
||||||
hess, vertcat(transpose(r_jac_u), \ |
|
||||||
transpose(r_jac_x))]) |
|
||||||
|
|
||||||
constraint_phi.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
# change directory back |
|
||||||
os.chdir(cwd) |
|
||||||
|
|
||||||
return |
|
@ -1,98 +0,0 @@ |
|||||||
# |
|
||||||
# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
# |
|
||||||
# This file is part of acados. |
|
||||||
# |
|
||||||
# The 2-Clause BSD License |
|
||||||
# |
|
||||||
# Redistribution and use in source and binary forms, with or without |
|
||||||
# modification, are permitted provided that the following conditions are met: |
|
||||||
# |
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer. |
|
||||||
# |
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer in the documentation |
|
||||||
# and/or other materials provided with the distribution. |
|
||||||
# |
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
# SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR PROFITS OR BUSINESS |
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
# POSSIBILITY OF SUCH DAMAGE. |
|
||||||
# |
|
||||||
|
|
||||||
import os |
|
||||||
import casadi as ca |
|
||||||
from .utils import ALLOWED_CASADI_VERSIONS, casadi_length, casadi_version_warning |
|
||||||
|
|
||||||
def generate_c_code_discrete_dynamics( model, opts ): |
|
||||||
|
|
||||||
casadi_version = ca.CasadiMeta.version() |
|
||||||
casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
|
||||||
|
|
||||||
if casadi_version not in (ALLOWED_CASADI_VERSIONS): |
|
||||||
casadi_version_warning(casadi_version) |
|
||||||
|
|
||||||
# load model |
|
||||||
x = model.x |
|
||||||
u = model.u |
|
||||||
p = model.p |
|
||||||
phi = model.disc_dyn_expr |
|
||||||
model_name = model.name |
|
||||||
nx = casadi_length(x) |
|
||||||
|
|
||||||
if isinstance(phi, ca.MX): |
|
||||||
symbol = ca.MX.sym |
|
||||||
elif isinstance(phi, ca.SX): |
|
||||||
symbol = ca.SX.sym |
|
||||||
else: |
|
||||||
Exception("generate_c_code_disc_dyn: disc_dyn_expr must be a CasADi expression, you have type: {}".format(type(phi))) |
|
||||||
|
|
||||||
# assume nx1 = nx !!! |
|
||||||
lam = symbol('lam', nx, 1) |
|
||||||
|
|
||||||
# generate jacobians |
|
||||||
ux = ca.vertcat(u,x) |
|
||||||
jac_ux = ca.jacobian(phi, ux) |
|
||||||
# generate adjoint |
|
||||||
adj_ux = ca.jtimes(phi, ux, lam, True) |
|
||||||
# generate hessian |
|
||||||
hess_ux = ca.jacobian(adj_ux, ux) |
|
||||||
|
|
||||||
## change directory |
|
||||||
code_export_dir = opts["code_export_directory"] |
|
||||||
if not os.path.exists(code_export_dir): |
|
||||||
os.makedirs(code_export_dir) |
|
||||||
|
|
||||||
cwd = os.getcwd() |
|
||||||
os.chdir(code_export_dir) |
|
||||||
model_dir = model_name + '_model' |
|
||||||
if not os.path.exists(model_dir): |
|
||||||
os.mkdir(model_dir) |
|
||||||
model_dir_location = os.path.join('.', model_dir) |
|
||||||
os.chdir(model_dir_location) |
|
||||||
|
|
||||||
# set up & generate Functions |
|
||||||
fun_name = model_name + '_dyn_disc_phi_fun' |
|
||||||
phi_fun = ca.Function(fun_name, [x, u, p], [phi]) |
|
||||||
phi_fun.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_dyn_disc_phi_fun_jac' |
|
||||||
phi_fun_jac_ut_xt = ca.Function(fun_name, [x, u, p], [phi, jac_ux.T]) |
|
||||||
phi_fun_jac_ut_xt.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_dyn_disc_phi_fun_jac_hess' |
|
||||||
phi_fun_jac_ut_xt_hess = ca.Function(fun_name, [x, u, lam, p], [phi, jac_ux.T, hess_ux]) |
|
||||||
phi_fun_jac_ut_xt_hess.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
os.chdir(cwd) |
|
@ -1,124 +0,0 @@ |
|||||||
# |
|
||||||
# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
# |
|
||||||
# This file is part of acados. |
|
||||||
# |
|
||||||
# The 2-Clause BSD License |
|
||||||
# |
|
||||||
# Redistribution and use in source and binary forms, with or without |
|
||||||
# modification, are permitted provided that the following conditions are met: |
|
||||||
# |
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer. |
|
||||||
# |
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer in the documentation |
|
||||||
# and/or other materials provided with the distribution. |
|
||||||
# |
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
# POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
# |
|
||||||
|
|
||||||
import os |
|
||||||
from casadi import * |
|
||||||
from .utils import ALLOWED_CASADI_VERSIONS, is_empty, casadi_version_warning |
|
||||||
|
|
||||||
def generate_c_code_explicit_ode( model, opts ): |
|
||||||
|
|
||||||
casadi_version = CasadiMeta.version() |
|
||||||
casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
|
||||||
if casadi_version not in (ALLOWED_CASADI_VERSIONS): |
|
||||||
casadi_version_warning(casadi_version) |
|
||||||
|
|
||||||
|
|
||||||
generate_hess = opts["generate_hess"] |
|
||||||
code_export_dir = opts["code_export_directory"] |
|
||||||
|
|
||||||
# load model |
|
||||||
x = model.x |
|
||||||
u = model.u |
|
||||||
p = model.p |
|
||||||
f_expl = model.f_expl_expr |
|
||||||
model_name = model.name |
|
||||||
|
|
||||||
## get model dimensions |
|
||||||
nx = x.size()[0] |
|
||||||
nu = u.size()[0] |
|
||||||
|
|
||||||
if isinstance(f_expl, casadi.MX): |
|
||||||
symbol = MX.sym |
|
||||||
elif isinstance(f_expl, casadi.SX): |
|
||||||
symbol = SX.sym |
|
||||||
else: |
|
||||||
raise Exception("Invalid type for f_expl! Possible types are 'SX' and 'MX'. Exiting.") |
|
||||||
## set up functions to be exported |
|
||||||
Sx = symbol('Sx', nx, nx) |
|
||||||
Sp = symbol('Sp', nx, nu) |
|
||||||
lambdaX = symbol('lambdaX', nx, 1) |
|
||||||
|
|
||||||
fun_name = model_name + '_expl_ode_fun' |
|
||||||
|
|
||||||
## Set up functions |
|
||||||
expl_ode_fun = Function(fun_name, [x, u, p], [f_expl]) |
|
||||||
|
|
||||||
vdeX = jtimes(f_expl,x,Sx) |
|
||||||
vdeP = jacobian(f_expl,u) + jtimes(f_expl,x,Sp) |
|
||||||
|
|
||||||
fun_name = model_name + '_expl_vde_forw' |
|
||||||
|
|
||||||
expl_vde_forw = Function(fun_name, [x, Sx, Sp, u, p], [f_expl, vdeX, vdeP]) |
|
||||||
|
|
||||||
adj = jtimes(f_expl, vertcat(x, u), lambdaX, True) |
|
||||||
|
|
||||||
fun_name = model_name + '_expl_vde_adj' |
|
||||||
expl_vde_adj = Function(fun_name, [x, lambdaX, u, p], [adj]) |
|
||||||
|
|
||||||
if generate_hess: |
|
||||||
S_forw = vertcat(horzcat(Sx, Sp), horzcat(DM.zeros(nu,nx), DM.eye(nu))) |
|
||||||
hess = mtimes(transpose(S_forw),jtimes(adj, vertcat(x,u), S_forw)) |
|
||||||
hess2 = [] |
|
||||||
for j in range(nx+nu): |
|
||||||
for i in range(j,nx+nu): |
|
||||||
hess2 = vertcat(hess2, hess[i,j]) |
|
||||||
|
|
||||||
fun_name = model_name + '_expl_ode_hess' |
|
||||||
expl_ode_hess = Function(fun_name, [x, Sx, Sp, lambdaX, u, p], [adj, hess2]) |
|
||||||
|
|
||||||
## generate C code |
|
||||||
if not os.path.exists(code_export_dir): |
|
||||||
os.makedirs(code_export_dir) |
|
||||||
|
|
||||||
cwd = os.getcwd() |
|
||||||
os.chdir(code_export_dir) |
|
||||||
model_dir = model_name + '_model' |
|
||||||
if not os.path.exists(model_dir): |
|
||||||
os.mkdir(model_dir) |
|
||||||
model_dir_location = os.path.join('.', model_dir) |
|
||||||
os.chdir(model_dir_location) |
|
||||||
fun_name = model_name + '_expl_ode_fun' |
|
||||||
expl_ode_fun.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_expl_vde_forw' |
|
||||||
expl_vde_forw.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_expl_vde_adj' |
|
||||||
expl_vde_adj.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
if generate_hess: |
|
||||||
fun_name = model_name + '_expl_ode_hess' |
|
||||||
expl_ode_hess.generate(fun_name, casadi_opts) |
|
||||||
os.chdir(cwd) |
|
||||||
|
|
||||||
return |
|
@ -1,116 +0,0 @@ |
|||||||
# |
|
||||||
# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
# |
|
||||||
# This file is part of acados. |
|
||||||
# |
|
||||||
# The 2-Clause BSD License |
|
||||||
# |
|
||||||
# Redistribution and use in source and binary forms, with or without |
|
||||||
# modification, are permitted provided that the following conditions are met: |
|
||||||
# |
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer. |
|
||||||
# |
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer in the documentation |
|
||||||
# and/or other materials provided with the distribution. |
|
||||||
# |
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
# POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
# |
|
||||||
|
|
||||||
import os |
|
||||||
from casadi import SX, MX, Function, transpose, vertcat, horzcat, hessian, CasadiMeta |
|
||||||
from .utils import ALLOWED_CASADI_VERSIONS, casadi_version_warning |
|
||||||
|
|
||||||
|
|
||||||
def generate_c_code_external_cost(model, stage_type, opts): |
|
||||||
|
|
||||||
casadi_version = CasadiMeta.version() |
|
||||||
casadi_opts = dict(mex=False, casadi_int="int", casadi_real="double") |
|
||||||
|
|
||||||
if casadi_version not in (ALLOWED_CASADI_VERSIONS): |
|
||||||
casadi_version_warning(casadi_version) |
|
||||||
|
|
||||||
x = model.x |
|
||||||
p = model.p |
|
||||||
|
|
||||||
if isinstance(x, MX): |
|
||||||
symbol = MX.sym |
|
||||||
else: |
|
||||||
symbol = SX.sym |
|
||||||
|
|
||||||
if stage_type == 'terminal': |
|
||||||
suffix_name = "_cost_ext_cost_e_fun" |
|
||||||
suffix_name_hess = "_cost_ext_cost_e_fun_jac_hess" |
|
||||||
suffix_name_jac = "_cost_ext_cost_e_fun_jac" |
|
||||||
u = symbol("u", 0, 0) |
|
||||||
ext_cost = model.cost_expr_ext_cost_e |
|
||||||
custom_hess = model.cost_expr_ext_cost_custom_hess_e |
|
||||||
|
|
||||||
elif stage_type == 'path': |
|
||||||
suffix_name = "_cost_ext_cost_fun" |
|
||||||
suffix_name_hess = "_cost_ext_cost_fun_jac_hess" |
|
||||||
suffix_name_jac = "_cost_ext_cost_fun_jac" |
|
||||||
u = model.u |
|
||||||
ext_cost = model.cost_expr_ext_cost |
|
||||||
custom_hess = model.cost_expr_ext_cost_custom_hess |
|
||||||
|
|
||||||
elif stage_type == 'initial': |
|
||||||
suffix_name = "_cost_ext_cost_0_fun" |
|
||||||
suffix_name_hess = "_cost_ext_cost_0_fun_jac_hess" |
|
||||||
suffix_name_jac = "_cost_ext_cost_0_fun_jac" |
|
||||||
u = model.u |
|
||||||
ext_cost = model.cost_expr_ext_cost_0 |
|
||||||
custom_hess = model.cost_expr_ext_cost_custom_hess_0 |
|
||||||
|
|
||||||
# set up functions to be exported |
|
||||||
fun_name = model.name + suffix_name |
|
||||||
fun_name_hess = model.name + suffix_name_hess |
|
||||||
fun_name_jac = model.name + suffix_name_jac |
|
||||||
|
|
||||||
# generate expression for full gradient and Hessian |
|
||||||
full_hess, grad = hessian(ext_cost, vertcat(u, x)) |
|
||||||
|
|
||||||
if custom_hess is not None: |
|
||||||
full_hess = custom_hess |
|
||||||
|
|
||||||
ext_cost_fun = Function(fun_name, [x, u, p], [ext_cost]) |
|
||||||
ext_cost_fun_jac_hess = Function( |
|
||||||
fun_name_hess, [x, u, p], [ext_cost, grad, full_hess] |
|
||||||
) |
|
||||||
ext_cost_fun_jac = Function( |
|
||||||
fun_name_jac, [x, u, p], [ext_cost, grad] |
|
||||||
) |
|
||||||
|
|
||||||
# generate C code |
|
||||||
code_export_dir = opts["code_export_directory"] |
|
||||||
if not os.path.exists(code_export_dir): |
|
||||||
os.makedirs(code_export_dir) |
|
||||||
|
|
||||||
cwd = os.getcwd() |
|
||||||
os.chdir(code_export_dir) |
|
||||||
gen_dir = model.name + '_cost' |
|
||||||
if not os.path.exists(gen_dir): |
|
||||||
os.mkdir(gen_dir) |
|
||||||
gen_dir_location = "./" + gen_dir |
|
||||||
os.chdir(gen_dir_location) |
|
||||||
|
|
||||||
ext_cost_fun.generate(fun_name, casadi_opts) |
|
||||||
ext_cost_fun_jac_hess.generate(fun_name_hess, casadi_opts) |
|
||||||
ext_cost_fun_jac.generate(fun_name_jac, casadi_opts) |
|
||||||
|
|
||||||
os.chdir(cwd) |
|
||||||
return |
|
@ -1,131 +0,0 @@ |
|||||||
# |
|
||||||
# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
# |
|
||||||
# This file is part of acados. |
|
||||||
# |
|
||||||
# The 2-Clause BSD License |
|
||||||
# |
|
||||||
# Redistribution and use in source and binary forms, with or without |
|
||||||
# modification, are permitted provided that the following conditions are met: |
|
||||||
# |
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer. |
|
||||||
# |
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer in the documentation |
|
||||||
# and/or other materials provided with the distribution. |
|
||||||
# |
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
# POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
# |
|
||||||
|
|
||||||
import os |
|
||||||
from casadi import * |
|
||||||
from .utils import ALLOWED_CASADI_VERSIONS, is_empty, casadi_version_warning |
|
||||||
|
|
||||||
def generate_c_code_gnsf( model, opts ): |
|
||||||
|
|
||||||
casadi_version = CasadiMeta.version() |
|
||||||
casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
|
||||||
if casadi_version not in (ALLOWED_CASADI_VERSIONS): |
|
||||||
casadi_version_warning(casadi_version) |
|
||||||
|
|
||||||
model_name = model.name |
|
||||||
code_export_dir = opts["code_export_directory"] |
|
||||||
|
|
||||||
# set up directory |
|
||||||
if not os.path.exists(code_export_dir): |
|
||||||
os.makedirs(code_export_dir) |
|
||||||
|
|
||||||
cwd = os.getcwd() |
|
||||||
os.chdir(code_export_dir) |
|
||||||
model_dir = model_name + '_model' |
|
||||||
if not os.path.exists(model_dir): |
|
||||||
os.mkdir(model_dir) |
|
||||||
model_dir_location = os.path.join('.', model_dir) |
|
||||||
os.chdir(model_dir_location) |
|
||||||
|
|
||||||
# obtain gnsf dimensions |
|
||||||
get_matrices_fun = model.get_matrices_fun |
|
||||||
phi_fun = model.phi_fun |
|
||||||
|
|
||||||
size_gnsf_A = get_matrices_fun.size_out(0) |
|
||||||
gnsf_nx1 = size_gnsf_A[1] |
|
||||||
gnsf_nz1 = size_gnsf_A[0] - size_gnsf_A[1] |
|
||||||
gnsf_nuhat = max(phi_fun.size_in(1)) |
|
||||||
gnsf_ny = max(phi_fun.size_in(0)) |
|
||||||
gnsf_nout = max(phi_fun.size_out(0)) |
|
||||||
|
|
||||||
# set up expressions |
|
||||||
# if the model uses MX because of cost/constraints |
|
||||||
# the DAE can be exported as SX -> detect GNSF in Matlab |
|
||||||
# -> evaluated SX GNSF functions with MX. |
|
||||||
u = model.u |
|
||||||
|
|
||||||
if isinstance(u, casadi.MX): |
|
||||||
symbol = MX.sym |
|
||||||
else: |
|
||||||
symbol = SX.sym |
|
||||||
|
|
||||||
y = symbol("y", gnsf_ny, 1) |
|
||||||
uhat = symbol("uhat", gnsf_nuhat, 1) |
|
||||||
p = model.p |
|
||||||
x1 = symbol("gnsf_x1", gnsf_nx1, 1) |
|
||||||
x1dot = symbol("gnsf_x1dot", gnsf_nx1, 1) |
|
||||||
z1 = symbol("gnsf_z1", gnsf_nz1, 1) |
|
||||||
dummy = symbol("gnsf_dummy", 1, 1) |
|
||||||
empty_var = symbol("gnsf_empty_var", 0, 0) |
|
||||||
|
|
||||||
## generate C code |
|
||||||
fun_name = model_name + '_gnsf_phi_fun' |
|
||||||
phi_fun_ = Function(fun_name, [y, uhat, p], [phi_fun(y, uhat, p)]) |
|
||||||
phi_fun_.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_gnsf_phi_fun_jac_y' |
|
||||||
phi_fun_jac_y = model.phi_fun_jac_y |
|
||||||
phi_fun_jac_y_ = Function(fun_name, [y, uhat, p], phi_fun_jac_y(y, uhat, p)) |
|
||||||
phi_fun_jac_y_.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_gnsf_phi_jac_y_uhat' |
|
||||||
phi_jac_y_uhat = model.phi_jac_y_uhat |
|
||||||
phi_jac_y_uhat_ = Function(fun_name, [y, uhat, p], phi_jac_y_uhat(y, uhat, p)) |
|
||||||
phi_jac_y_uhat_.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_gnsf_f_lo_fun_jac_x1k1uz' |
|
||||||
f_lo_fun_jac_x1k1uz = model.f_lo_fun_jac_x1k1uz |
|
||||||
f_lo_fun_jac_x1k1uz_eval = f_lo_fun_jac_x1k1uz(x1, x1dot, z1, u, p) |
|
||||||
|
|
||||||
# avoid codegeneration issue |
|
||||||
if not isinstance(f_lo_fun_jac_x1k1uz_eval, tuple) and is_empty(f_lo_fun_jac_x1k1uz_eval): |
|
||||||
f_lo_fun_jac_x1k1uz_eval = [empty_var] |
|
||||||
|
|
||||||
f_lo_fun_jac_x1k1uz_ = Function(fun_name, [x1, x1dot, z1, u, p], |
|
||||||
f_lo_fun_jac_x1k1uz_eval) |
|
||||||
f_lo_fun_jac_x1k1uz_.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_gnsf_get_matrices_fun' |
|
||||||
get_matrices_fun_ = Function(fun_name, [dummy], get_matrices_fun(1)) |
|
||||||
get_matrices_fun_.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
# remove fields for json dump |
|
||||||
del model.phi_fun |
|
||||||
del model.phi_fun_jac_y |
|
||||||
del model.phi_jac_y_uhat |
|
||||||
del model.f_lo_fun_jac_x1k1uz |
|
||||||
del model.get_matrices_fun |
|
||||||
|
|
||||||
os.chdir(cwd) |
|
||||||
|
|
||||||
return |
|
@ -1,139 +0,0 @@ |
|||||||
# |
|
||||||
# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
# |
|
||||||
# This file is part of acados. |
|
||||||
# |
|
||||||
# The 2-Clause BSD License |
|
||||||
# |
|
||||||
# Redistribution and use in source and binary forms, with or without |
|
||||||
# modification, are permitted provided that the following conditions are met: |
|
||||||
# |
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer. |
|
||||||
# |
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer in the documentation |
|
||||||
# and/or other materials provided with the distribution. |
|
||||||
# |
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
# POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
# |
|
||||||
|
|
||||||
import os |
|
||||||
from casadi import * |
|
||||||
from .utils import ALLOWED_CASADI_VERSIONS, is_empty, casadi_length, casadi_version_warning |
|
||||||
|
|
||||||
def generate_c_code_implicit_ode( model, opts ): |
|
||||||
|
|
||||||
casadi_version = CasadiMeta.version() |
|
||||||
casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
|
||||||
if casadi_version not in (ALLOWED_CASADI_VERSIONS): |
|
||||||
casadi_version_warning(casadi_version) |
|
||||||
|
|
||||||
generate_hess = opts["generate_hess"] |
|
||||||
code_export_dir = opts["code_export_directory"] |
|
||||||
|
|
||||||
## load model |
|
||||||
x = model.x |
|
||||||
xdot = model.xdot |
|
||||||
u = model.u |
|
||||||
z = model.z |
|
||||||
p = model.p |
|
||||||
f_impl = model.f_impl_expr |
|
||||||
model_name = model.name |
|
||||||
|
|
||||||
## get model dimensions |
|
||||||
nx = casadi_length(x) |
|
||||||
nu = casadi_length(u) |
|
||||||
nz = casadi_length(z) |
|
||||||
|
|
||||||
## generate jacobians |
|
||||||
jac_x = jacobian(f_impl, x) |
|
||||||
jac_xdot = jacobian(f_impl, xdot) |
|
||||||
jac_u = jacobian(f_impl, u) |
|
||||||
jac_z = jacobian(f_impl, z) |
|
||||||
|
|
||||||
## generate hessian |
|
||||||
x_xdot_z_u = vertcat(x, xdot, z, u) |
|
||||||
|
|
||||||
if isinstance(x, casadi.MX): |
|
||||||
symbol = MX.sym |
|
||||||
else: |
|
||||||
symbol = SX.sym |
|
||||||
|
|
||||||
multiplier = symbol('multiplier', nx + nz) |
|
||||||
|
|
||||||
ADJ = jtimes(f_impl, x_xdot_z_u, multiplier, True) |
|
||||||
HESS = jacobian(ADJ, x_xdot_z_u) |
|
||||||
|
|
||||||
## Set up functions |
|
||||||
p = model.p |
|
||||||
fun_name = model_name + '_impl_dae_fun' |
|
||||||
impl_dae_fun = Function(fun_name, [x, xdot, u, z, p], [f_impl]) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z' |
|
||||||
impl_dae_fun_jac_x_xdot_z = Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_z]) |
|
||||||
|
|
||||||
# fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z' |
|
||||||
# impl_dae_fun_jac_x_xdot = Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_z]) |
|
||||||
|
|
||||||
# fun_name = model_name + '_impl_dae_jac_x_xdot_u' |
|
||||||
# impl_dae_jac_x_xdot_u = Function(fun_name, [x, xdot, u, z, p], [jac_x, jac_xdot, jac_u, jac_z]) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u_z' |
|
||||||
impl_dae_fun_jac_x_xdot_u_z = Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_u, jac_z]) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u' |
|
||||||
impl_dae_fun_jac_x_xdot_u = Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_u]) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_jac_x_xdot_u_z' |
|
||||||
impl_dae_jac_x_xdot_u_z = Function(fun_name, [x, xdot, u, z, p], [jac_x, jac_xdot, jac_u, jac_z]) |
|
||||||
|
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_hess' |
|
||||||
impl_dae_hess = Function(fun_name, [x, xdot, u, z, multiplier, p], [HESS]) |
|
||||||
|
|
||||||
# generate C code |
|
||||||
if not os.path.exists(code_export_dir): |
|
||||||
os.makedirs(code_export_dir) |
|
||||||
|
|
||||||
cwd = os.getcwd() |
|
||||||
os.chdir(code_export_dir) |
|
||||||
model_dir = model_name + '_model' |
|
||||||
if not os.path.exists(model_dir): |
|
||||||
os.mkdir(model_dir) |
|
||||||
model_dir_location = os.path.join('.', model_dir) |
|
||||||
os.chdir(model_dir_location) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_fun' |
|
||||||
impl_dae_fun.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z' |
|
||||||
impl_dae_fun_jac_x_xdot_z.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_jac_x_xdot_u_z' |
|
||||||
impl_dae_jac_x_xdot_u_z.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u_z' |
|
||||||
impl_dae_fun_jac_x_xdot_u_z.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u' |
|
||||||
impl_dae_fun_jac_x_xdot_u.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
if generate_hess: |
|
||||||
fun_name = model_name + '_impl_dae_hess' |
|
||||||
impl_dae_hess.generate(fun_name, casadi_opts) |
|
||||||
|
|
||||||
os.chdir(cwd) |
|
@ -1,113 +0,0 @@ |
|||||||
# |
|
||||||
# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, |
|
||||||
# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, |
|
||||||
# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, |
|
||||||
# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl |
|
||||||
# |
|
||||||
# This file is part of acados. |
|
||||||
# |
|
||||||
# The 2-Clause BSD License |
|
||||||
# |
|
||||||
# Redistribution and use in source and binary forms, with or without |
|
||||||
# modification, are permitted provided that the following conditions are met: |
|
||||||
# |
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer. |
|
||||||
# |
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, |
|
||||||
# this list of conditions and the following disclaimer in the documentation |
|
||||||
# and/or other materials provided with the distribution. |
|
||||||
# |
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
# POSSIBILITY OF SUCH DAMAGE.; |
|
||||||
# |
|
||||||
|
|
||||||
import os |
|
||||||
from casadi import * |
|
||||||
from .utils import ALLOWED_CASADI_VERSIONS, casadi_length, casadi_version_warning |
|
||||||
|
|
||||||
def generate_c_code_nls_cost( model, cost_name, stage_type, opts ): |
|
||||||
|
|
||||||
casadi_version = CasadiMeta.version() |
|
||||||
casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double') |
|
||||||
|
|
||||||
if casadi_version not in (ALLOWED_CASADI_VERSIONS): |
|
||||||
casadi_version_warning(casadi_version) |
|
||||||
|
|
||||||
x = model.x |
|
||||||
p = model.p |
|
||||||
|
|
||||||
if isinstance(x, casadi.MX): |
|
||||||
symbol = MX.sym |
|
||||||
else: |
|
||||||
symbol = SX.sym |
|
||||||
|
|
||||||
if stage_type == 'terminal': |
|
||||||
middle_name = '_cost_y_e' |
|
||||||
u = symbol('u', 0, 0) |
|
||||||
cost_expr = model.cost_y_expr_e |
|
||||||
|
|
||||||
elif stage_type == 'initial': |
|
||||||
middle_name = '_cost_y_0' |
|
||||||
u = model.u |
|
||||||
cost_expr = model.cost_y_expr_0 |
|
||||||
|
|
||||||
elif stage_type == 'path': |
|
||||||
middle_name = '_cost_y' |
|
||||||
u = model.u |
|
||||||
cost_expr = model.cost_y_expr |
|
||||||
|
|
||||||
# set up directory |
|
||||||
code_export_dir = opts["code_export_directory"] |
|
||||||
if not os.path.exists(code_export_dir): |
|
||||||
os.makedirs(code_export_dir) |
|
||||||
|
|
||||||
cwd = os.getcwd() |
|
||||||
os.chdir(code_export_dir) |
|
||||||
gen_dir = cost_name + '_cost' |
|
||||||
if not os.path.exists(gen_dir): |
|
||||||
os.mkdir(gen_dir) |
|
||||||
gen_dir_location = os.path.join('.', gen_dir) |
|
||||||
os.chdir(gen_dir_location) |
|
||||||
|
|
||||||
# set up expressions |
|
||||||
cost_jac_expr = transpose(jacobian(cost_expr, vertcat(u, x))) |
|
||||||
|
|
||||||
ny = casadi_length(cost_expr) |
|
||||||
|
|
||||||
y = symbol('y', ny, 1) |
|
||||||
|
|
||||||
y_adj = jtimes(cost_expr, vertcat(u, x), y, True) |
|
||||||
y_hess = jacobian(y_adj, vertcat(u, x)) |
|
||||||
|
|
||||||
## generate C code |
|
||||||
suffix_name = '_fun' |
|
||||||
fun_name = cost_name + middle_name + suffix_name |
|
||||||
y_fun = Function( fun_name, [x, u, p], \ |
|
||||||
[ cost_expr ]) |
|
||||||
y_fun.generate( fun_name, casadi_opts ) |
|
||||||
|
|
||||||
suffix_name = '_fun_jac_ut_xt' |
|
||||||
fun_name = cost_name + middle_name + suffix_name |
|
||||||
y_fun_jac_ut_xt = Function(fun_name, [x, u, p], \ |
|
||||||
[ cost_expr, cost_jac_expr ]) |
|
||||||
y_fun_jac_ut_xt.generate( fun_name, casadi_opts ) |
|
||||||
|
|
||||||
suffix_name = '_hess' |
|
||||||
fun_name = cost_name + middle_name + suffix_name |
|
||||||
y_hess = Function(fun_name, [x, u, y, p], [ y_hess ]) |
|
||||||
y_hess.generate( fun_name, casadi_opts ) |
|
||||||
|
|
||||||
os.chdir(cwd) |
|
||||||
|
|
||||||
return |
|
||||||
|
|
@ -0,0 +1 @@ |
|||||||
|
|
@ -0,0 +1,216 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
|
||||||
|
from acados_template.utils import casadi_length |
||||||
|
from casadi import * |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
|
||||||
|
def check_reformulation(model, gnsf, print_info): |
||||||
|
|
||||||
|
## Description: |
||||||
|
# this function takes the implicit ODE/ index-1 DAE and a gnsf structure |
||||||
|
# to evaluate both models at num_eval random points x0, x0dot, z0, u0 |
||||||
|
# if for all points the relative error is <= TOL, the function will return:: |
||||||
|
# 1, otherwise it will give an error. |
||||||
|
|
||||||
|
TOL = 1e-14 |
||||||
|
num_eval = 10 |
||||||
|
|
||||||
|
# get dimensions |
||||||
|
nx = gnsf["nx"] |
||||||
|
nu = gnsf["nu"] |
||||||
|
nz = gnsf["nz"] |
||||||
|
nx1 = gnsf["nx1"] |
||||||
|
nx2 = gnsf["nx2"] |
||||||
|
nz1 = gnsf["nz1"] |
||||||
|
nz2 = gnsf["nz2"] |
||||||
|
n_out = gnsf["n_out"] |
||||||
|
|
||||||
|
# get model matrices |
||||||
|
A = gnsf["A"] |
||||||
|
B = gnsf["B"] |
||||||
|
C = gnsf["C"] |
||||||
|
E = gnsf["E"] |
||||||
|
c = gnsf["c"] |
||||||
|
|
||||||
|
L_x = gnsf["L_x"] |
||||||
|
L_xdot = gnsf["L_xdot"] |
||||||
|
L_z = gnsf["L_z"] |
||||||
|
L_u = gnsf["L_u"] |
||||||
|
|
||||||
|
A_LO = gnsf["A_LO"] |
||||||
|
E_LO = gnsf["E_LO"] |
||||||
|
B_LO = gnsf["B_LO"] |
||||||
|
c_LO = gnsf["c_LO"] |
||||||
|
|
||||||
|
I_x1 = range(nx1) |
||||||
|
I_x2 = range(nx1, nx) |
||||||
|
|
||||||
|
I_z1 = range(nz1) |
||||||
|
I_z2 = range(nz1, nz) |
||||||
|
|
||||||
|
idx_perm_f = gnsf["idx_perm_f"] |
||||||
|
|
||||||
|
# get casadi variables |
||||||
|
x = gnsf["x"] |
||||||
|
xdot = gnsf["xdot"] |
||||||
|
z = gnsf["z"] |
||||||
|
u = gnsf["u"] |
||||||
|
y = gnsf["y"] |
||||||
|
uhat = gnsf["uhat"] |
||||||
|
p = gnsf["p"] |
||||||
|
|
||||||
|
# create functions |
||||||
|
impl_dae_fun = Function("impl_dae_fun", [x, xdot, u, z, p], [model.f_impl_expr]) |
||||||
|
phi_fun = Function("phi_fun", [y, uhat, p], [gnsf["phi_expr"]]) |
||||||
|
f_lo_fun = Function( |
||||||
|
"f_lo_fun", [x[range(nx1)], xdot[range(nx1)], z, u, p], [gnsf["f_lo_expr"]] |
||||||
|
) |
||||||
|
|
||||||
|
# print(gnsf) |
||||||
|
# print(gnsf["n_out"]) |
||||||
|
|
||||||
|
for i_check in range(num_eval): |
||||||
|
# generate random values |
||||||
|
x0 = np.random.rand(nx, 1) |
||||||
|
x0dot = np.random.rand(nx, 1) |
||||||
|
z0 = np.random.rand(nz, 1) |
||||||
|
u0 = np.random.rand(nu, 1) |
||||||
|
|
||||||
|
if gnsf["ny"] > 0: |
||||||
|
y0 = L_x @ x0[I_x1] + L_xdot @ x0dot[I_x1] + L_z @ z0[I_z1] |
||||||
|
else: |
||||||
|
y0 = [] |
||||||
|
if gnsf["nuhat"] > 0: |
||||||
|
uhat0 = L_u @ u0 |
||||||
|
else: |
||||||
|
uhat0 = [] |
||||||
|
|
||||||
|
# eval functions |
||||||
|
p0 = np.random.rand(gnsf["np"], 1) |
||||||
|
f_impl_val = impl_dae_fun(x0, x0dot, u0, z0, p0).full() |
||||||
|
phi_val = phi_fun(y0, uhat0, p0) |
||||||
|
f_lo_val = f_lo_fun(x0[I_x1], x0dot[I_x1], z0[I_z1], u0, p0) |
||||||
|
|
||||||
|
f_impl_val = f_impl_val[idx_perm_f] |
||||||
|
# eval gnsf |
||||||
|
if n_out > 0: |
||||||
|
C_phi = C @ phi_val |
||||||
|
else: |
||||||
|
C_phi = np.zeros((nx1 + nz1, 1)) |
||||||
|
try: |
||||||
|
gnsf_val1 = ( |
||||||
|
A @ x0[I_x1] + B @ u0 + C_phi + c - E @ vertcat(x0dot[I_x1], z0[I_z1]) |
||||||
|
) |
||||||
|
# gnsf_1 = (A @ x[I_x1] + B @ u + C_phi + c - E @ vertcat(xdot[I_x1], z[I_z1])) |
||||||
|
except: |
||||||
|
import pdb |
||||||
|
|
||||||
|
pdb.set_trace() |
||||||
|
|
||||||
|
if nx2 > 0: # eval LOS: |
||||||
|
gnsf_val2 = ( |
||||||
|
A_LO @ x0[I_x2] |
||||||
|
+ B_LO @ u0 |
||||||
|
+ c_LO |
||||||
|
+ f_lo_val |
||||||
|
- E_LO @ vertcat(x0dot[I_x2], z0[I_z2]) |
||||||
|
) |
||||||
|
gnsf_val = vertcat(gnsf_val1, gnsf_val2).full() |
||||||
|
else: |
||||||
|
gnsf_val = gnsf_val1.full() |
||||||
|
# compute error and check |
||||||
|
rel_error = np.linalg.norm(f_impl_val - gnsf_val) / np.linalg.norm(f_impl_val) |
||||||
|
|
||||||
|
if rel_error > TOL: |
||||||
|
print("transcription failed rel_error > TOL") |
||||||
|
print("you are in debug mode now: import pdb; pdb.set_trace()") |
||||||
|
abs_error = gnsf_val - f_impl_val |
||||||
|
# T = table(f_impl_val, gnsf_val, abs_error) |
||||||
|
# print(T) |
||||||
|
print("abs_error:", abs_error) |
||||||
|
# error('transcription failed rel_error > TOL') |
||||||
|
# check = 0 |
||||||
|
import pdb |
||||||
|
|
||||||
|
pdb.set_trace() |
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
print("model reformulation checked: relative error <= TOL = ", str(TOL)) |
||||||
|
print(" ") |
||||||
|
check = 1 |
||||||
|
## helpful for debugging: |
||||||
|
# # use in calling function and compare |
||||||
|
# # compare f_impl(i) with gnsf_val1(i) |
||||||
|
# |
||||||
|
|
||||||
|
# nx = gnsf['nx'] |
||||||
|
# nu = gnsf['nu'] |
||||||
|
# nz = gnsf['nz'] |
||||||
|
# nx1 = gnsf['nx1'] |
||||||
|
# nx2 = gnsf['nx2'] |
||||||
|
# |
||||||
|
# A = gnsf['A'] |
||||||
|
# B = gnsf['B'] |
||||||
|
# C = gnsf['C'] |
||||||
|
# E = gnsf['E'] |
||||||
|
# c = gnsf['c'] |
||||||
|
# |
||||||
|
# L_x = gnsf['L_x'] |
||||||
|
# L_z = gnsf['L_z'] |
||||||
|
# L_xdot = gnsf['L_xdot'] |
||||||
|
# L_u = gnsf['L_u'] |
||||||
|
# |
||||||
|
# A_LO = gnsf['A_LO'] |
||||||
|
# |
||||||
|
# x0 = rand(nx, 1) |
||||||
|
# x0dot = rand(nx, 1) |
||||||
|
# z0 = rand(nz, 1) |
||||||
|
# u0 = rand(nu, 1) |
||||||
|
# I_x1 = range(nx1) |
||||||
|
# I_x2 = nx1+range(nx) |
||||||
|
# |
||||||
|
# y0 = L_x @ x0[I_x1] + L_xdot @ x0dot[I_x1] + L_z @ z0 |
||||||
|
# uhat0 = L_u @ u0 |
||||||
|
# |
||||||
|
# gnsf_val1 = (A @ x[I_x1] + B @ u + # C @ phi_current + c) - E @ [xdot[I_x1] z] |
||||||
|
# gnsf_val1 = gnsf_val1.simplify() |
||||||
|
# |
||||||
|
# # gnsf_val2 = A_LO @ x[I_x2] + gnsf['f_lo_fun'](x[I_x1], xdot[I_x1], z, u) - xdot[I_x2] |
||||||
|
# gnsf_val2 = A_LO @ x[I_x2] + gnsf['f_lo_fun'](x[I_x1], xdot[I_x1], z, u) - xdot[I_x2] |
||||||
|
# |
||||||
|
# |
||||||
|
# gnsf_val = [gnsf_val1 gnsf_val2] |
||||||
|
# gnsf_val = gnsf_val.simplify() |
||||||
|
# dyn_expr_f = dyn_expr_f.simplify() |
||||||
|
# import pdb; pdb.set_trace() |
||||||
|
|
||||||
|
return check |
@ -0,0 +1,278 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
|
||||||
|
from casadi import * |
||||||
|
from .check_reformulation import check_reformulation |
||||||
|
from .determine_input_nonlinearity_function import determine_input_nonlinearity_function |
||||||
|
from ..utils import casadi_length, print_casadi_expression |
||||||
|
|
||||||
|
|
||||||
|
def detect_affine_terms_reduce_nonlinearity(gnsf, acados_ocp, print_info): |
||||||
|
|
||||||
|
## Description |
||||||
|
# this function takes a gnsf structure with trivial model matrices (A, B, |
||||||
|
# E, c are zeros, and C is eye). |
||||||
|
# It detects all affine linear terms and sets up an equivalent model in the |
||||||
|
# GNSF structure, where all affine linear terms are modeled through the |
||||||
|
# matrices A, B, E, c and the linear output system (LOS) is empty. |
||||||
|
# NOTE: model is just taken as an argument to check equivalence of the |
||||||
|
# models within the function. |
||||||
|
|
||||||
|
model = acados_ocp.model |
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
print("====================================================================") |
||||||
|
print(" ") |
||||||
|
print("============ Detect affine-linear dependencies ==================") |
||||||
|
print(" ") |
||||||
|
print("====================================================================") |
||||||
|
print(" ") |
||||||
|
# symbolics |
||||||
|
x = gnsf["x"] |
||||||
|
xdot = gnsf["xdot"] |
||||||
|
u = gnsf["u"] |
||||||
|
z = gnsf["z"] |
||||||
|
|
||||||
|
# dimensions |
||||||
|
nx = gnsf["nx"] |
||||||
|
nu = gnsf["nu"] |
||||||
|
nz = gnsf["nz"] |
||||||
|
|
||||||
|
ny_old = gnsf["ny"] |
||||||
|
nuhat_old = gnsf["nuhat"] |
||||||
|
|
||||||
|
## Represent all affine dependencies through the model matrices A, B, E, c |
||||||
|
## determine A |
||||||
|
n_nodes_current = n_nodes(gnsf["phi_expr"]) |
||||||
|
|
||||||
|
for ii in range(casadi_length(gnsf["phi_expr"])): |
||||||
|
fii = gnsf["phi_expr"][ii] |
||||||
|
for ix in range(nx): |
||||||
|
var = x[ix] |
||||||
|
varname = var.name |
||||||
|
# symbolic jacobian of fii w.r.t. xi |
||||||
|
jac_fii_xi = jacobian(fii, var) |
||||||
|
if jac_fii_xi.is_constant(): |
||||||
|
# jacobian value |
||||||
|
jac_fii_xi_fun = Function("jac_fii_xi_fun", [x[1]], [jac_fii_xi]) |
||||||
|
# x[1] as input just to have a scalar input and call the function as follows: |
||||||
|
gnsf["A"][ii, ix] = jac_fii_xi_fun(0).full() |
||||||
|
else: |
||||||
|
gnsf["A"][ii, ix] = 0 |
||||||
|
if print_info: |
||||||
|
print( |
||||||
|
"phi(", |
||||||
|
str(ii), |
||||||
|
") is nonlinear in x(", |
||||||
|
str(ix), |
||||||
|
") = ", |
||||||
|
varname, |
||||||
|
) |
||||||
|
print(fii) |
||||||
|
print("-----------------------------------------------------") |
||||||
|
f_next = gnsf["phi_expr"] - gnsf["A"] @ x |
||||||
|
f_next = simplify(f_next) |
||||||
|
n_nodes_next = n_nodes(f_next) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print("\n") |
||||||
|
print(f"determined matrix A:") |
||||||
|
print(gnsf["A"]) |
||||||
|
print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") |
||||||
|
# assert(n_nodes_current >= n_nodes_next,'n_nodes_current >= n_nodes_next FAILED') |
||||||
|
gnsf["phi_expr"] = f_next |
||||||
|
|
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
|
||||||
|
## determine B |
||||||
|
n_nodes_current = n_nodes(gnsf["phi_expr"]) |
||||||
|
|
||||||
|
for ii in range(casadi_length(gnsf["phi_expr"])): |
||||||
|
fii = gnsf["phi_expr"][ii] |
||||||
|
for iu in range(nu): |
||||||
|
var = u[iu] |
||||||
|
varname = var.name |
||||||
|
# symbolic jacobian of fii w.r.t. ui |
||||||
|
jac_fii_ui = jacobian(fii, var) |
||||||
|
if jac_fii_ui.is_constant(): # i.e. hessian is structural zero: |
||||||
|
# jacobian value |
||||||
|
jac_fii_ui_fun = Function("jac_fii_ui_fun", [x[1]], [jac_fii_ui]) |
||||||
|
gnsf["B"][ii, iu] = jac_fii_ui_fun(0).full() |
||||||
|
else: |
||||||
|
gnsf["B"][ii, iu] = 0 |
||||||
|
if print_info: |
||||||
|
print(f"phi({ii}) is nonlinear in u(", str(iu), ") = ", varname) |
||||||
|
print(fii) |
||||||
|
print("-----------------------------------------------------") |
||||||
|
f_next = gnsf["phi_expr"] - gnsf["B"] @ u |
||||||
|
f_next = simplify(f_next) |
||||||
|
n_nodes_next = n_nodes(f_next) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print("\n") |
||||||
|
print(f"determined matrix B:") |
||||||
|
print(gnsf["B"]) |
||||||
|
print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") |
||||||
|
|
||||||
|
gnsf["phi_expr"] = f_next |
||||||
|
|
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
|
||||||
|
## determine E |
||||||
|
n_nodes_current = n_nodes(gnsf["phi_expr"]) |
||||||
|
k = vertcat(xdot, z) |
||||||
|
|
||||||
|
for ii in range(casadi_length(gnsf["phi_expr"])): |
||||||
|
fii = gnsf["phi_expr"][ii] |
||||||
|
for ik in range(casadi_length(k)): |
||||||
|
# symbolic jacobian of fii w.r.t. ui |
||||||
|
var = k[ik] |
||||||
|
varname = var.name |
||||||
|
jac_fii_ki = jacobian(fii, var) |
||||||
|
if jac_fii_ki.is_constant(): |
||||||
|
# jacobian value |
||||||
|
jac_fii_ki_fun = Function("jac_fii_ki_fun", [x[1]], [jac_fii_ki]) |
||||||
|
gnsf["E"][ii, ik] = -jac_fii_ki_fun(0).full() |
||||||
|
else: |
||||||
|
gnsf["E"][ii, ik] = 0 |
||||||
|
if print_info: |
||||||
|
print(f"phi( {ii}) is nonlinear in xdot_z({ik}) = ", varname) |
||||||
|
print(fii) |
||||||
|
print("-----------------------------------------------------") |
||||||
|
f_next = gnsf["phi_expr"] + gnsf["E"] @ k |
||||||
|
f_next = simplify(f_next) |
||||||
|
n_nodes_next = n_nodes(f_next) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print("\n") |
||||||
|
print(f"determined matrix E:") |
||||||
|
print(gnsf["E"]) |
||||||
|
print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") |
||||||
|
|
||||||
|
gnsf["phi_expr"] = f_next |
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
|
||||||
|
## determine constant term c |
||||||
|
|
||||||
|
n_nodes_current = n_nodes(gnsf["phi_expr"]) |
||||||
|
for ii in range(casadi_length(gnsf["phi_expr"])): |
||||||
|
fii = gnsf["phi_expr"][ii] |
||||||
|
if fii.is_constant(): |
||||||
|
# function value goes into c |
||||||
|
fii_fun = Function("fii_fun", [x[1]], [fii]) |
||||||
|
gnsf["c"][ii] = fii_fun(0).full() |
||||||
|
else: |
||||||
|
gnsf["c"][ii] = 0 |
||||||
|
if print_info: |
||||||
|
print(f"phi(", str(ii), ") is NOT constant") |
||||||
|
print(fii) |
||||||
|
print("-----------------------------------------------------") |
||||||
|
gnsf["phi_expr"] = gnsf["phi_expr"] - gnsf["c"] |
||||||
|
gnsf["phi_expr"] = simplify(gnsf["phi_expr"]) |
||||||
|
n_nodes_next = n_nodes(gnsf["phi_expr"]) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print("\n") |
||||||
|
print(f"determined vector c:") |
||||||
|
print(gnsf["c"]) |
||||||
|
print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") |
||||||
|
|
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
|
||||||
|
## determine nonlinearity & corresponding matrix C |
||||||
|
## Reduce dimension of phi |
||||||
|
n_nodes_current = n_nodes(gnsf["phi_expr"]) |
||||||
|
ind_non_zero = [] |
||||||
|
for ii in range(casadi_length(gnsf["phi_expr"])): |
||||||
|
fii = gnsf["phi_expr"][ii] |
||||||
|
fii = simplify(fii) |
||||||
|
if not fii.is_zero(): |
||||||
|
ind_non_zero = list(set.union(set(ind_non_zero), set([ii]))) |
||||||
|
gnsf["phi_expr"] = gnsf["phi_expr"][ind_non_zero] |
||||||
|
|
||||||
|
# C |
||||||
|
gnsf["C"] = np.zeros((nx + nz, len(ind_non_zero))) |
||||||
|
for ii in range(len(ind_non_zero)): |
||||||
|
gnsf["C"][ind_non_zero[ii], ii] = 1 |
||||||
|
gnsf = determine_input_nonlinearity_function(gnsf) |
||||||
|
n_nodes_next = n_nodes(gnsf["phi_expr"]) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
print("determined matrix C:") |
||||||
|
print(gnsf["C"]) |
||||||
|
print( |
||||||
|
"---------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print( |
||||||
|
"------------- Success: Affine linear terms detected -----------------------------" |
||||||
|
) |
||||||
|
print( |
||||||
|
"---------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print( |
||||||
|
f'reduced nonlinearity dimension n_out from {nx+nz} to {gnsf["n_out"]}' |
||||||
|
) |
||||||
|
print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") |
||||||
|
print(" ") |
||||||
|
print("phi now reads as:") |
||||||
|
print_casadi_expression(gnsf["phi_expr"]) |
||||||
|
|
||||||
|
## determine input of nonlinearity function |
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
|
||||||
|
gnsf["ny"] = casadi_length(gnsf["y"]) |
||||||
|
gnsf["nuhat"] = casadi_length(gnsf["uhat"]) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print( |
||||||
|
"-----------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
f"reduced input ny of phi from ", |
||||||
|
str(ny_old), |
||||||
|
" to ", |
||||||
|
str(gnsf["ny"]), |
||||||
|
) |
||||||
|
print( |
||||||
|
f"reduced input nuhat of phi from ", |
||||||
|
str(nuhat_old), |
||||||
|
" to ", |
||||||
|
str(gnsf["nuhat"]), |
||||||
|
) |
||||||
|
print( |
||||||
|
"-----------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
|
||||||
|
# if print_info: |
||||||
|
# print(f"gnsf: {gnsf}") |
||||||
|
|
||||||
|
return gnsf |
@ -0,0 +1,240 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com |
||||||
|
|
||||||
|
from casadi import Function, jacobian, SX, vertcat, horzcat |
||||||
|
|
||||||
|
from .determine_trivial_gnsf_transcription import determine_trivial_gnsf_transcription |
||||||
|
from .detect_affine_terms_reduce_nonlinearity import ( |
||||||
|
detect_affine_terms_reduce_nonlinearity, |
||||||
|
) |
||||||
|
from .reformulate_with_LOS import reformulate_with_LOS |
||||||
|
from .reformulate_with_invertible_E_mat import reformulate_with_invertible_E_mat |
||||||
|
from .structure_detection_print_summary import structure_detection_print_summary |
||||||
|
from .check_reformulation import check_reformulation |
||||||
|
|
||||||
|
|
||||||
|
def detect_gnsf_structure(acados_ocp, transcribe_opts=None): |
||||||
|
|
||||||
|
## Description |
||||||
|
# This function takes a CasADi implicit ODE or index-1 DAE model "model" |
||||||
|
# consisting of a CasADi expression f_impl in the symbolic CasADi |
||||||
|
# variables x, xdot, u, z, (and possibly parameters p), which are also part |
||||||
|
# of the model, as well as a model name. |
||||||
|
# It will create a struct "gnsf" containing all information needed to use |
||||||
|
# it with the gnsf integrator in acados. |
||||||
|
# Additionally it will create the struct "reordered_model" which contains |
||||||
|
# the permuted state vector and permuted f_impl, in which additionally some |
||||||
|
# functions, which were made part of the linear output system of the gnsf, |
||||||
|
# have changed signs. |
||||||
|
|
||||||
|
# Options: transcribe_opts is a Matlab struct consisting of booleans: |
||||||
|
# print_info: if extensive information on how the model is processed |
||||||
|
# is printed to the console. |
||||||
|
# generate_gnsf_model: if the neccessary C functions to simulate the gnsf |
||||||
|
# model with the acados implementation of the GNSF exploiting |
||||||
|
# integrator should be generated. |
||||||
|
# generate_gnsf_model: if the neccessary C functions to simulate the |
||||||
|
# reordered model with the acados implementation of the IRK |
||||||
|
# integrator should be generated. |
||||||
|
# check_E_invertibility: if the transcription method should check if the |
||||||
|
# assumption that the main blocks of the matrix gnsf.E are invertible |
||||||
|
# holds. If not, the method will try to reformulate the gnsf model |
||||||
|
# with a different model, such that the assumption holds. |
||||||
|
|
||||||
|
# acados_root_dir = getenv('ACADOS_INSTALL_DIR') |
||||||
|
|
||||||
|
## load transcribe_opts |
||||||
|
if transcribe_opts is None: |
||||||
|
print("WARNING: GNSF structure detection called without transcribe_opts") |
||||||
|
print(" using default settings") |
||||||
|
print("") |
||||||
|
transcribe_opts = dict() |
||||||
|
|
||||||
|
if "print_info" in transcribe_opts: |
||||||
|
print_info = transcribe_opts["print_info"] |
||||||
|
else: |
||||||
|
print_info = 1 |
||||||
|
print("print_info option was not set - default is true") |
||||||
|
|
||||||
|
if "detect_LOS" in transcribe_opts: |
||||||
|
detect_LOS = transcribe_opts["detect_LOS"] |
||||||
|
else: |
||||||
|
detect_LOS = 1 |
||||||
|
if print_info: |
||||||
|
print("detect_LOS option was not set - default is true") |
||||||
|
|
||||||
|
if "check_E_invertibility" in transcribe_opts: |
||||||
|
check_E_invertibility = transcribe_opts["check_E_invertibility"] |
||||||
|
else: |
||||||
|
check_E_invertibility = 1 |
||||||
|
if print_info: |
||||||
|
print("check_E_invertibility option was not set - default is true") |
||||||
|
|
||||||
|
## Reformulate implicit index-1 DAE into GNSF form |
||||||
|
# (Generalized nonlinear static feedback) |
||||||
|
gnsf = determine_trivial_gnsf_transcription(acados_ocp, print_info) |
||||||
|
gnsf = detect_affine_terms_reduce_nonlinearity(gnsf, acados_ocp, print_info) |
||||||
|
|
||||||
|
if detect_LOS: |
||||||
|
gnsf = reformulate_with_LOS(acados_ocp, gnsf, print_info) |
||||||
|
|
||||||
|
if check_E_invertibility: |
||||||
|
gnsf = reformulate_with_invertible_E_mat(gnsf, acados_ocp, print_info) |
||||||
|
|
||||||
|
# detect purely linear model |
||||||
|
if gnsf["nx1"] == 0 and gnsf["nz1"] == 0 and gnsf["nontrivial_f_LO"] == 0: |
||||||
|
gnsf["purely_linear"] = 1 |
||||||
|
else: |
||||||
|
gnsf["purely_linear"] = 0 |
||||||
|
|
||||||
|
structure_detection_print_summary(gnsf, acados_ocp) |
||||||
|
check_reformulation(acados_ocp.model, gnsf, print_info) |
||||||
|
|
||||||
|
## copy relevant fields from gnsf to model |
||||||
|
acados_ocp.model.get_matrices_fun = Function() |
||||||
|
dummy = acados_ocp.model.x[0] |
||||||
|
model_name = acados_ocp.model.name |
||||||
|
|
||||||
|
get_matrices_fun = Function( |
||||||
|
f"{model_name}_gnsf_get_matrices_fun", |
||||||
|
[dummy], |
||||||
|
[ |
||||||
|
gnsf["A"], |
||||||
|
gnsf["B"], |
||||||
|
gnsf["C"], |
||||||
|
gnsf["E"], |
||||||
|
gnsf["L_x"], |
||||||
|
gnsf["L_xdot"], |
||||||
|
gnsf["L_z"], |
||||||
|
gnsf["L_u"], |
||||||
|
gnsf["A_LO"], |
||||||
|
gnsf["c"], |
||||||
|
gnsf["E_LO"], |
||||||
|
gnsf["B_LO"], |
||||||
|
gnsf["nontrivial_f_LO"], |
||||||
|
gnsf["purely_linear"], |
||||||
|
gnsf["ipiv_x"] + 1, |
||||||
|
gnsf["ipiv_z"] + 1, |
||||||
|
gnsf["c_LO"], |
||||||
|
], |
||||||
|
) |
||||||
|
|
||||||
|
phi = gnsf["phi_expr"] |
||||||
|
y = gnsf["y"] |
||||||
|
uhat = gnsf["uhat"] |
||||||
|
p = gnsf["p"] |
||||||
|
|
||||||
|
jac_phi_y = jacobian(phi, y) |
||||||
|
jac_phi_uhat = jacobian(phi, uhat) |
||||||
|
|
||||||
|
phi_fun = Function(f"{model_name}_gnsf_phi_fun", [y, uhat, p], [phi]) |
||||||
|
acados_ocp.model.phi_fun = phi_fun |
||||||
|
acados_ocp.model.phi_fun_jac_y = Function( |
||||||
|
f"{model_name}_gnsf_phi_fun_jac_y", [y, uhat, p], [phi, jac_phi_y] |
||||||
|
) |
||||||
|
acados_ocp.model.phi_jac_y_uhat = Function( |
||||||
|
f"{model_name}_gnsf_phi_jac_y_uhat", [y, uhat, p], [jac_phi_y, jac_phi_uhat] |
||||||
|
) |
||||||
|
|
||||||
|
x1 = acados_ocp.model.x[gnsf["idx_perm_x"][: gnsf["nx1"]]] |
||||||
|
x1dot = acados_ocp.model.xdot[gnsf["idx_perm_x"][: gnsf["nx1"]]] |
||||||
|
if gnsf["nz1"] > 0: |
||||||
|
z1 = acados_ocp.model.z[gnsf["idx_perm_z"][: gnsf["nz1"]]] |
||||||
|
else: |
||||||
|
z1 = SX.sym("z1", 0, 0) |
||||||
|
f_lo = gnsf["f_lo_expr"] |
||||||
|
u = acados_ocp.model.u |
||||||
|
acados_ocp.model.f_lo_fun_jac_x1k1uz = Function( |
||||||
|
f"{model_name}_gnsf_f_lo_fun_jac_x1k1uz", |
||||||
|
[x1, x1dot, z1, u, p], |
||||||
|
[ |
||||||
|
f_lo, |
||||||
|
horzcat( |
||||||
|
jacobian(f_lo, x1), |
||||||
|
jacobian(f_lo, x1dot), |
||||||
|
jacobian(f_lo, u), |
||||||
|
jacobian(f_lo, z1), |
||||||
|
), |
||||||
|
], |
||||||
|
) |
||||||
|
|
||||||
|
acados_ocp.model.get_matrices_fun = get_matrices_fun |
||||||
|
|
||||||
|
size_gnsf_A = gnsf["A"].shape |
||||||
|
acados_ocp.dims.gnsf_nx1 = size_gnsf_A[1] |
||||||
|
acados_ocp.dims.gnsf_nz1 = size_gnsf_A[0] - size_gnsf_A[1] |
||||||
|
acados_ocp.dims.gnsf_nuhat = max(phi_fun.size_in(1)) |
||||||
|
acados_ocp.dims.gnsf_ny = max(phi_fun.size_in(0)) |
||||||
|
acados_ocp.dims.gnsf_nout = max(phi_fun.size_out(0)) |
||||||
|
|
||||||
|
# # dim |
||||||
|
# model['dim_gnsf_nx1'] = gnsf['nx1'] |
||||||
|
# model['dim_gnsf_nx2'] = gnsf['nx2'] |
||||||
|
# model['dim_gnsf_nz1'] = gnsf['nz1'] |
||||||
|
# model['dim_gnsf_nz2'] = gnsf['nz2'] |
||||||
|
# model['dim_gnsf_nuhat'] = gnsf['nuhat'] |
||||||
|
# model['dim_gnsf_ny'] = gnsf['ny'] |
||||||
|
# model['dim_gnsf_nout'] = gnsf['n_out'] |
||||||
|
|
||||||
|
# # sym |
||||||
|
# model['sym_gnsf_y'] = gnsf['y'] |
||||||
|
# model['sym_gnsf_uhat'] = gnsf['uhat'] |
||||||
|
|
||||||
|
# # data |
||||||
|
# model['dyn_gnsf_A'] = gnsf['A'] |
||||||
|
# model['dyn_gnsf_A_LO'] = gnsf['A_LO'] |
||||||
|
# model['dyn_gnsf_B'] = gnsf['B'] |
||||||
|
# model['dyn_gnsf_B_LO'] = gnsf['B_LO'] |
||||||
|
# model['dyn_gnsf_E'] = gnsf['E'] |
||||||
|
# model['dyn_gnsf_E_LO'] = gnsf['E_LO'] |
||||||
|
# model['dyn_gnsf_C'] = gnsf['C'] |
||||||
|
# model['dyn_gnsf_c'] = gnsf['c'] |
||||||
|
# model['dyn_gnsf_c_LO'] = gnsf['c_LO'] |
||||||
|
# model['dyn_gnsf_L_x'] = gnsf['L_x'] |
||||||
|
# model['dyn_gnsf_L_xdot'] = gnsf['L_xdot'] |
||||||
|
# model['dyn_gnsf_L_z'] = gnsf['L_z'] |
||||||
|
# model['dyn_gnsf_L_u'] = gnsf['L_u'] |
||||||
|
# model['dyn_gnsf_idx_perm_x'] = gnsf['idx_perm_x'] |
||||||
|
# model['dyn_gnsf_ipiv_x'] = gnsf['ipiv_x'] |
||||||
|
# model['dyn_gnsf_idx_perm_z'] = gnsf['idx_perm_z'] |
||||||
|
# model['dyn_gnsf_ipiv_z'] = gnsf['ipiv_z'] |
||||||
|
# model['dyn_gnsf_idx_perm_f'] = gnsf['idx_perm_f'] |
||||||
|
# model['dyn_gnsf_ipiv_f'] = gnsf['ipiv_f'] |
||||||
|
|
||||||
|
# # flags |
||||||
|
# model['dyn_gnsf_nontrivial_f_LO'] = gnsf['nontrivial_f_LO'] |
||||||
|
# model['dyn_gnsf_purely_linear'] = gnsf['purely_linear'] |
||||||
|
|
||||||
|
# # casadi expr |
||||||
|
# model['dyn_gnsf_expr_phi'] = gnsf['phi_expr'] |
||||||
|
# model['dyn_gnsf_expr_f_lo'] = gnsf['f_lo_expr'] |
||||||
|
|
||||||
|
return acados_ocp |
@ -0,0 +1,110 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com |
||||||
|
|
||||||
|
from casadi import * |
||||||
|
from ..utils import casadi_length, is_empty |
||||||
|
|
||||||
|
|
||||||
|
def determine_input_nonlinearity_function(gnsf): |
||||||
|
|
||||||
|
## Description |
||||||
|
# this function takes a structure gnsf and updates the matrices L_x, |
||||||
|
# L_xdot, L_z, L_u and CasADi vectors y, uhat of this structure as follows: |
||||||
|
|
||||||
|
# given a CasADi expression phi_expr, which may depend on the variables |
||||||
|
# (x1, x1dot, z, u), this function determines a vector y (uhat) consisting |
||||||
|
# of all components of (x1, x1dot, z) (respectively u) that enter phi_expr. |
||||||
|
# Additionally matrices L_x, L_xdot, L_z, L_u are determined such that |
||||||
|
# y = L_x * x + L_xdot * xdot + L_z * z |
||||||
|
# uhat = L_u * u |
||||||
|
# Furthermore the dimensions ny, nuhat, n_out are updated |
||||||
|
|
||||||
|
## y |
||||||
|
y = SX.sym('y', 0, 0) |
||||||
|
# components of x1 |
||||||
|
for ii in range(gnsf["nx1"]): |
||||||
|
if which_depends(gnsf["phi_expr"], gnsf["x"][ii])[0]: |
||||||
|
y = vertcat(y, gnsf["x"][ii]) |
||||||
|
# else: |
||||||
|
# x[ii] is not part of y |
||||||
|
# components of x1dot |
||||||
|
for ii in range(gnsf["nx1"]): |
||||||
|
if which_depends(gnsf["phi_expr"], gnsf["xdot"][ii])[0]: |
||||||
|
print(gnsf["phi_expr"], "depends on", gnsf["xdot"][ii]) |
||||||
|
y = vertcat(y, gnsf["xdot"][ii]) |
||||||
|
# else: |
||||||
|
# xdot[ii] is not part of y |
||||||
|
# components of z |
||||||
|
for ii in range(gnsf["nz1"]): |
||||||
|
if which_depends(gnsf["phi_expr"], gnsf["z"][ii])[0]: |
||||||
|
y = vertcat(y, gnsf["z"][ii]) |
||||||
|
# else: |
||||||
|
# z[ii] is not part of y |
||||||
|
## uhat |
||||||
|
uhat = SX.sym('uhat', 0, 0) |
||||||
|
# components of u |
||||||
|
for ii in range(gnsf["nu"]): |
||||||
|
if which_depends(gnsf["phi_expr"], gnsf["u"][ii])[0]: |
||||||
|
uhat = vertcat(uhat, gnsf["u"][ii]) |
||||||
|
# else: |
||||||
|
# u[ii] is not part of uhat |
||||||
|
## generate gnsf['phi_expr_fun'] |
||||||
|
# linear input matrices |
||||||
|
if is_empty(y): |
||||||
|
gnsf["L_x"] = [] |
||||||
|
gnsf["L_xdot"] = [] |
||||||
|
gnsf["L_u"] = [] |
||||||
|
gnsf["L_z"] = [] |
||||||
|
else: |
||||||
|
dummy = SX.sym("dummy_input", 0) |
||||||
|
L_x_fun = Function( |
||||||
|
"L_x_fun", [dummy], [jacobian(y, gnsf["x"][range(gnsf["nx1"])])] |
||||||
|
) |
||||||
|
L_xdot_fun = Function( |
||||||
|
"L_xdot_fun", [dummy], [jacobian(y, gnsf["xdot"][range(gnsf["nx1"])])] |
||||||
|
) |
||||||
|
L_z_fun = Function( |
||||||
|
"L_z_fun", [dummy], [jacobian(y, gnsf["z"][range(gnsf["nz1"])])] |
||||||
|
) |
||||||
|
L_u_fun = Function("L_u_fun", [dummy], [jacobian(uhat, gnsf["u"])]) |
||||||
|
|
||||||
|
gnsf["L_x"] = L_x_fun(0).full() |
||||||
|
gnsf["L_xdot"] = L_xdot_fun(0).full() |
||||||
|
gnsf["L_u"] = L_u_fun(0).full() |
||||||
|
gnsf["L_z"] = L_z_fun(0).full() |
||||||
|
gnsf["y"] = y |
||||||
|
gnsf["uhat"] = uhat |
||||||
|
|
||||||
|
gnsf["ny"] = casadi_length(y) |
||||||
|
gnsf["nuhat"] = casadi_length(uhat) |
||||||
|
gnsf["n_out"] = casadi_length(gnsf["phi_expr"]) |
||||||
|
|
||||||
|
return gnsf |
@ -0,0 +1,155 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
|
||||||
|
from casadi import * |
||||||
|
import numpy as np |
||||||
|
from ..utils import casadi_length, idx_perm_to_ipiv |
||||||
|
from .determine_input_nonlinearity_function import determine_input_nonlinearity_function |
||||||
|
from .check_reformulation import check_reformulation |
||||||
|
|
||||||
|
|
||||||
|
def determine_trivial_gnsf_transcription(acados_ocp, print_info): |
||||||
|
## Description |
||||||
|
# this function takes a model of an implicit ODE/ index-1 DAE and sets up |
||||||
|
# an equivalent model in the GNSF structure, with empty linear output |
||||||
|
# system and trivial model matrices, i.e. A, B, E, c are zeros, and C is |
||||||
|
# eye. - no structure is exploited |
||||||
|
|
||||||
|
model = acados_ocp.model |
||||||
|
# initial print |
||||||
|
print("*****************************************************************") |
||||||
|
print(" ") |
||||||
|
print(f"****** Restructuring {model.name} model ***********") |
||||||
|
print(" ") |
||||||
|
print("*****************************************************************") |
||||||
|
|
||||||
|
# load model |
||||||
|
f_impl_expr = model.f_impl_expr |
||||||
|
|
||||||
|
model_name_prefix = model.name |
||||||
|
|
||||||
|
# x |
||||||
|
x = model.x |
||||||
|
nx = acados_ocp.dims.nx |
||||||
|
# check type |
||||||
|
if isinstance(x[0], SX): |
||||||
|
isSX = True |
||||||
|
else: |
||||||
|
print("GNSF detection only works for SX CasADi type!!!") |
||||||
|
import pdb |
||||||
|
|
||||||
|
pdb.set_trace() |
||||||
|
# xdot |
||||||
|
xdot = model.xdot |
||||||
|
# u |
||||||
|
nu = acados_ocp.dims.nu |
||||||
|
if nu == 0: |
||||||
|
u = SX.sym("u", 0, 0) |
||||||
|
else: |
||||||
|
u = model.u |
||||||
|
|
||||||
|
nz = acados_ocp.dims.nz |
||||||
|
if nz == 0: |
||||||
|
z = SX.sym("z", 0, 0) |
||||||
|
else: |
||||||
|
z = model.z |
||||||
|
|
||||||
|
p = model.p |
||||||
|
nparam = acados_ocp.dims.np |
||||||
|
|
||||||
|
# avoid SX of size 0x1 |
||||||
|
if casadi_length(u) == 0: |
||||||
|
u = SX.sym("u", 0, 0) |
||||||
|
nu = 0 |
||||||
|
## initialize gnsf struct |
||||||
|
# dimensions |
||||||
|
gnsf = {"nx": nx, "nu": nu, "nz": nz, "np": nparam} |
||||||
|
gnsf["nx1"] = nx |
||||||
|
gnsf["nx2"] = 0 |
||||||
|
gnsf["nz1"] = nz |
||||||
|
gnsf["nz2"] = 0 |
||||||
|
gnsf["nuhat"] = nu |
||||||
|
gnsf["ny"] = 2 * nx + nz |
||||||
|
|
||||||
|
gnsf["phi_expr"] = f_impl_expr |
||||||
|
gnsf["A"] = np.zeros((nx + nz, nx)) |
||||||
|
gnsf["B"] = np.zeros((nx + nz, nu)) |
||||||
|
gnsf["E"] = np.zeros((nx + nz, nx + nz)) |
||||||
|
gnsf["c"] = np.zeros((nx + nz, 1)) |
||||||
|
gnsf["C"] = np.eye(nx + nz) |
||||||
|
gnsf["name"] = model_name_prefix |
||||||
|
|
||||||
|
gnsf["x"] = x |
||||||
|
gnsf["xdot"] = xdot |
||||||
|
gnsf["z"] = z |
||||||
|
gnsf["u"] = u |
||||||
|
gnsf["p"] = p |
||||||
|
|
||||||
|
gnsf = determine_input_nonlinearity_function(gnsf) |
||||||
|
|
||||||
|
gnsf["A_LO"] = [] |
||||||
|
gnsf["E_LO"] = [] |
||||||
|
gnsf["B_LO"] = [] |
||||||
|
gnsf["c_LO"] = [] |
||||||
|
gnsf["f_lo_expr"] = [] |
||||||
|
|
||||||
|
# permutation |
||||||
|
gnsf["idx_perm_x"] = range(nx) # matlab-style) |
||||||
|
gnsf["ipiv_x"] = idx_perm_to_ipiv(gnsf["idx_perm_x"]) # blasfeo-style |
||||||
|
gnsf["idx_perm_z"] = range(nz) |
||||||
|
gnsf["ipiv_z"] = idx_perm_to_ipiv(gnsf["idx_perm_z"]) |
||||||
|
gnsf["idx_perm_f"] = range((nx + nz)) |
||||||
|
gnsf["ipiv_f"] = idx_perm_to_ipiv(gnsf["idx_perm_f"]) |
||||||
|
|
||||||
|
gnsf["nontrivial_f_LO"] = 0 |
||||||
|
|
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
if print_info: |
||||||
|
print(f"Success: Set up equivalent GNSF model with trivial matrices") |
||||||
|
print(" ") |
||||||
|
if print_info: |
||||||
|
print( |
||||||
|
"-----------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"reduced input ny of phi from ", |
||||||
|
str(2 * nx + nz), |
||||||
|
" to ", |
||||||
|
str(gnsf["ny"]), |
||||||
|
) |
||||||
|
print( |
||||||
|
"reduced input nuhat of phi from ", str(nu), " to ", str(gnsf["nuhat"]) |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"-----------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
return gnsf |
@ -0,0 +1,43 @@ |
|||||||
|
# matlab to python |
||||||
|
|
||||||
|
% -> # |
||||||
|
|
||||||
|
; -> |
||||||
|
|
||||||
|
from casadi import * |
||||||
|
-> |
||||||
|
from casadi import * |
||||||
|
|
||||||
|
|
||||||
|
print\('(.*)'\) |
||||||
|
print('$1') |
||||||
|
|
||||||
|
print\(\['(.*)'\]\) |
||||||
|
print(f'$1') |
||||||
|
|
||||||
|
keyboard |
||||||
|
import pdb; pdb.set_trace() |
||||||
|
|
||||||
|
|
||||||
|
range((([^))]*)) |
||||||
|
range($1) |
||||||
|
|
||||||
|
\s*end |
||||||
|
-> |
||||||
|
nothing |
||||||
|
|
||||||
|
|
||||||
|
if (.*) |
||||||
|
if $1: |
||||||
|
|
||||||
|
else |
||||||
|
else: |
||||||
|
|
||||||
|
num2str |
||||||
|
str |
||||||
|
|
||||||
|
for ([a-z_]*) = |
||||||
|
for $1 in |
||||||
|
|
||||||
|
length\( |
||||||
|
len( |
@ -0,0 +1,394 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com |
||||||
|
|
||||||
|
from .determine_input_nonlinearity_function import determine_input_nonlinearity_function |
||||||
|
from .check_reformulation import check_reformulation |
||||||
|
from casadi import * |
||||||
|
from ..utils import casadi_length, idx_perm_to_ipiv, is_empty |
||||||
|
|
||||||
|
|
||||||
|
def reformulate_with_LOS(acados_ocp, gnsf, print_info): |
||||||
|
|
||||||
|
## Description: |
||||||
|
# This function takes an intitial transcription of the implicit ODE model |
||||||
|
# "model" into "gnsf" and reformulates "gnsf" with a linear output system |
||||||
|
# (LOS), containing as many states of the model as possible. |
||||||
|
# Therefore it might be that the state vector and the implicit function |
||||||
|
# vector have to be reordered. This reordered model is part of the output, |
||||||
|
# namely reordered_model. |
||||||
|
|
||||||
|
## import CasADi and load models |
||||||
|
model = acados_ocp.model |
||||||
|
|
||||||
|
# symbolics |
||||||
|
x = gnsf["x"] |
||||||
|
xdot = gnsf["xdot"] |
||||||
|
u = gnsf["u"] |
||||||
|
z = gnsf["z"] |
||||||
|
|
||||||
|
# dimensions |
||||||
|
nx = gnsf["nx"] |
||||||
|
nz = gnsf["nz"] |
||||||
|
|
||||||
|
# get model matrices |
||||||
|
A = gnsf["A"] |
||||||
|
B = gnsf["B"] |
||||||
|
C = gnsf["C"] |
||||||
|
E = gnsf["E"] |
||||||
|
c = gnsf["c"] |
||||||
|
|
||||||
|
A_LO = gnsf["A_LO"] |
||||||
|
|
||||||
|
y = gnsf["y"] |
||||||
|
|
||||||
|
phi_old = gnsf["phi_expr"] |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
print("=================================================================") |
||||||
|
print(" ") |
||||||
|
print("================ Detect Linear Output System ===============") |
||||||
|
print(" ") |
||||||
|
print("=================================================================") |
||||||
|
print(" ") |
||||||
|
## build initial I_x1 and I_x2_candidates |
||||||
|
# I_xrange( all components of x for which either xii or xdot_ii enters y): |
||||||
|
# I_LOS_candidates: the remaining components |
||||||
|
|
||||||
|
I_nsf_components = set() |
||||||
|
I_LOS_candidates = set() |
||||||
|
|
||||||
|
if gnsf["ny"] > 0: |
||||||
|
for ii in range(nx): |
||||||
|
if which_depends(y, x[ii])[0] or which_depends(y, xdot[ii])[0]: |
||||||
|
# i.e. xii or xiidot are part of y, and enter phi_expr |
||||||
|
if print_info: |
||||||
|
print(f"x_{ii} is part of x1") |
||||||
|
I_nsf_components = set.union(I_nsf_components, set([ii])) |
||||||
|
else: |
||||||
|
# i.e. neither xii nor xiidot are part of y, i.e. enter phi_expr |
||||||
|
I_LOS_candidates = set.union(I_LOS_candidates, set([ii])) |
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
for ii in range(nz): |
||||||
|
if which_depends(y, z[ii])[0]: |
||||||
|
# i.e. xii or xiidot are part of y, and enter phi_expr |
||||||
|
if print_info: |
||||||
|
print(f"z_{ii} is part of x1") |
||||||
|
I_nsf_components = set.union(I_nsf_components, set([ii + nx])) |
||||||
|
else: |
||||||
|
# i.e. neither xii nor xiidot are part of y, i.e. enter phi_expr |
||||||
|
I_LOS_candidates = set.union(I_LOS_candidates, set([ii + nx])) |
||||||
|
else: |
||||||
|
I_LOS_candidates = set(range((nx + nz))) |
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
print(f"I_LOS_candidates {I_LOS_candidates}") |
||||||
|
new_nsf_components = I_nsf_components |
||||||
|
I_nsf_eq = set([]) |
||||||
|
unsorted_dyn = set(range(nx + nz)) |
||||||
|
xdot_z = vertcat(xdot, z) |
||||||
|
|
||||||
|
## determine components of Linear Output System |
||||||
|
# determine maximal index set I_x2 |
||||||
|
# such that the components x(I_x2) can be written as a LOS |
||||||
|
Eq_map = [] |
||||||
|
while True: |
||||||
|
## find equations corresponding to new_nsf_components |
||||||
|
for ii in new_nsf_components: |
||||||
|
current_var = xdot_z[ii] |
||||||
|
var_name = current_var.name |
||||||
|
|
||||||
|
# print( unsorted_dyn) |
||||||
|
# print("np.nonzero(E[:,ii])[0]",np.nonzero(E[:,ii])[0]) |
||||||
|
I_eq = set.intersection(set(np.nonzero(E[:, ii])[0]), unsorted_dyn) |
||||||
|
if len(I_eq) == 1: |
||||||
|
i_eq = I_eq.pop() |
||||||
|
if print_info: |
||||||
|
print(f"component {i_eq} is associated with state {ii}") |
||||||
|
elif len(I_eq) > 1: # x_ii_dot occurs in more than 1 eq linearly |
||||||
|
# find the equation with least linear dependencies on |
||||||
|
# I_LOS_cancidates |
||||||
|
number_of_eq = 0 |
||||||
|
candidate_dependencies = np.zeros(len(I_eq), 1) |
||||||
|
I_x2_candidates = set.intersection(I_LOS_candidates, set(range(nx))) |
||||||
|
for eq in I_eq: |
||||||
|
depending_candidates = set.union( |
||||||
|
np.nonzero(E[eq, I_LOS_candidates])[0], |
||||||
|
np.nonzero(A[eq, I_x2_candidates])[0], |
||||||
|
) |
||||||
|
candidate_dependencies[number_of_eq] = +len(depending_candidates) |
||||||
|
number_of_eq += 1 |
||||||
|
number_of_eq = np.argmin(candidate_dependencies) |
||||||
|
i_eq = I_eq[number_of_eq] |
||||||
|
else: ## x_ii_dot does not occur linearly in any of the unsorted dynamics |
||||||
|
for j in unsorted_dyn: |
||||||
|
phi_eq_j = gnsf["phi_expr"][np.nonzero(C[j, :])[0]] |
||||||
|
if which_depends(phi_eq_j, xdot_z(ii))[0]: |
||||||
|
I_eq = set.union(I_eq, j) |
||||||
|
if is_empty(I_eq): |
||||||
|
I_eq = unsorted_dyn |
||||||
|
# find the equation with least linear dependencies on I_LOS_cancidates |
||||||
|
number_of_eq = 0 |
||||||
|
candidate_dependencies = np.zeros(len(I_eq), 1) |
||||||
|
I_x2_candidates = set.intersection(I_LOS_candidates, set(range(nx))) |
||||||
|
for eq in I_eq: |
||||||
|
depending_candidates = set.union( |
||||||
|
np.nonzero(E[eq, I_LOS_candidates])[0], |
||||||
|
np.nonzero(A[eq, I_x2_candidates])[0], |
||||||
|
) |
||||||
|
candidate_dependencies[number_of_eq] = +len(depending_candidates) |
||||||
|
number_of_eq += 1 |
||||||
|
number_of_eq = np.argmin(candidate_dependencies) |
||||||
|
i_eq = I_eq[number_of_eq] |
||||||
|
## add 1 * [xdot,z](ii) to both sides of i_eq |
||||||
|
if print_info: |
||||||
|
print( |
||||||
|
"adding 1 * ", |
||||||
|
var_name, |
||||||
|
" to both sides of equation ", |
||||||
|
i_eq, |
||||||
|
".", |
||||||
|
) |
||||||
|
gnsf["E"][i_eq, ii] = 1 |
||||||
|
i_phi = np.nonzero(gnsf["C"][i_eq, :]) |
||||||
|
if is_empty(i_phi): |
||||||
|
i_phi = len(gnsf["phi_expr"]) + 1 |
||||||
|
gnsf["C"][i_eq, i_phi] = 1 # add column to C with 1 entry |
||||||
|
gnsf["phi_expr"] = vertcat(gnsf["phi_expr"], 0) |
||||||
|
gnsf["phi_expr"][i_phi] = ( |
||||||
|
gnsf["phi_expr"](i_phi) |
||||||
|
+ gnsf["E"][i_eq, ii] / gnsf["C"][i_eq, i_phi] * xdot_z[ii] |
||||||
|
) |
||||||
|
if print_info: |
||||||
|
print( |
||||||
|
"detected equation ", |
||||||
|
i_eq, |
||||||
|
" to correspond to variable ", |
||||||
|
var_name, |
||||||
|
) |
||||||
|
I_nsf_eq = set.union(I_nsf_eq, {i_eq}) |
||||||
|
# remove i_eq from unsorted_dyn |
||||||
|
unsorted_dyn.remove(i_eq) |
||||||
|
Eq_map.append([ii, i_eq]) |
||||||
|
|
||||||
|
## add components to I_x1 |
||||||
|
for eq in I_nsf_eq: |
||||||
|
I_linear_dependence = set.union( |
||||||
|
set(np.nonzero(A[eq, :])[0]), set(np.nonzero(E[eq, :])[0]) |
||||||
|
) |
||||||
|
I_nsf_components = set.union(I_linear_dependence, I_nsf_components) |
||||||
|
# I_nsf_components = I_nsf_components[:] |
||||||
|
|
||||||
|
new_nsf_components = set.intersection(I_LOS_candidates, I_nsf_components) |
||||||
|
if is_empty(new_nsf_components): |
||||||
|
if print_info: |
||||||
|
print("new_nsf_components is empty") |
||||||
|
break |
||||||
|
# remove new_nsf_components from candidates |
||||||
|
I_LOS_candidates = set.difference(I_LOS_candidates, new_nsf_components) |
||||||
|
if not is_empty(Eq_map): |
||||||
|
# [~, new_eq_order] = sort(Eq_map(1,:)) |
||||||
|
# I_nsf_eq = Eq_map(2, new_eq_order ) |
||||||
|
for count, m in enumerate(Eq_map): |
||||||
|
m.append(count) |
||||||
|
sorted(Eq_map, key=lambda x: x[1]) |
||||||
|
new_eq_order = [m[2] for m in Eq_map] |
||||||
|
Eq_map = [Eq_map[i] for i in new_eq_order] |
||||||
|
I_nsf_eq = [m[1] for m in Eq_map] |
||||||
|
|
||||||
|
else: |
||||||
|
I_nsf_eq = [] |
||||||
|
|
||||||
|
I_LOS_components = I_LOS_candidates |
||||||
|
I_LOS_eq = sorted(set.difference(set(range(nx + nz)), I_nsf_eq)) |
||||||
|
I_nsf_eq = sorted(I_nsf_eq) |
||||||
|
|
||||||
|
I_x1 = set.intersection(I_nsf_components, set(range(nx))) |
||||||
|
I_z1 = set.intersection(I_nsf_components, set(range(nx, nx + nz))) |
||||||
|
I_z1 = set([i - nx for i in I_z1]) |
||||||
|
|
||||||
|
I_x2 = set.intersection(I_LOS_components, set(range(nx))) |
||||||
|
I_z2 = set.intersection(I_LOS_components, set(range(nx, nx + nz))) |
||||||
|
I_z2 = set([i - nx for i in I_z2]) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print(f"I_x1 {I_x1}, I_x2 {I_x2}") |
||||||
|
|
||||||
|
## permute x, xdot |
||||||
|
if is_empty(I_x1): |
||||||
|
x1 = [] |
||||||
|
x1dot = [] |
||||||
|
else: |
||||||
|
x1 = x[list(I_x1)] |
||||||
|
x1dot = xdot[list(I_x1)] |
||||||
|
if is_empty(I_x2): |
||||||
|
x2 = [] |
||||||
|
x2dot = [] |
||||||
|
else: |
||||||
|
x2 = x[list(I_x2)] |
||||||
|
x2dot = xdot[list(I_x2)] |
||||||
|
if is_empty(I_z1): |
||||||
|
z1 = [] |
||||||
|
else: |
||||||
|
z1 = z(I_z1) |
||||||
|
if is_empty(I_z2): |
||||||
|
z2 = [] |
||||||
|
else: |
||||||
|
z2 = z[list(I_z2)] |
||||||
|
|
||||||
|
I_x1 = sorted(I_x1) |
||||||
|
I_x2 = sorted(I_x2) |
||||||
|
I_z1 = sorted(I_z1) |
||||||
|
I_z2 = sorted(I_z2) |
||||||
|
gnsf["xdot"] = vertcat(x1dot, x2dot) |
||||||
|
gnsf["x"] = vertcat(x1, x2) |
||||||
|
gnsf["z"] = vertcat(z1, z2) |
||||||
|
gnsf["nx1"] = len(I_x1) |
||||||
|
gnsf["nx2"] = len(I_x2) |
||||||
|
gnsf["nz1"] = len(I_z1) |
||||||
|
gnsf["nz2"] = len(I_z2) |
||||||
|
|
||||||
|
# store permutations |
||||||
|
gnsf["idx_perm_x"] = I_x1 + I_x2 |
||||||
|
gnsf["ipiv_x"] = idx_perm_to_ipiv(gnsf["idx_perm_x"]) |
||||||
|
gnsf["idx_perm_z"] = I_z1 + I_z2 |
||||||
|
gnsf["ipiv_z"] = idx_perm_to_ipiv(gnsf["idx_perm_z"]) |
||||||
|
gnsf["idx_perm_f"] = I_nsf_eq + I_LOS_eq |
||||||
|
gnsf["ipiv_f"] = idx_perm_to_ipiv(gnsf["idx_perm_f"]) |
||||||
|
|
||||||
|
f_LO = SX.sym("f_LO", 0, 0) |
||||||
|
|
||||||
|
## rewrite I_LOS_eq as LOS |
||||||
|
if gnsf["n_out"] == 0: |
||||||
|
C_phi = np.zeros(gnsf["nx"] + gnsf["nz"], 1) |
||||||
|
else: |
||||||
|
C_phi = C @ phi_old |
||||||
|
if gnsf["nx1"] == 0: |
||||||
|
Ax1 = np.zeros(gnsf["nx"] + gnsf["nz"], 1) |
||||||
|
else: |
||||||
|
Ax1 = A[:, sorted(I_x1)] @ x1 |
||||||
|
if gnsf["nx1"] + gnsf["nz1"] == 0: |
||||||
|
lhs_nsf = np.zeros(gnsf["nx"] + gnsf["nz"], 1) |
||||||
|
else: |
||||||
|
lhs_nsf = E[:, sorted(I_nsf_components)] @ vertcat(x1, z1) |
||||||
|
n_LO = len(I_LOS_eq) |
||||||
|
B_LO = np.zeros((n_LO, gnsf["nu"])) |
||||||
|
A_LO = np.zeros((gnsf["nx2"] + gnsf["nz2"], gnsf["nx2"])) |
||||||
|
E_LO = np.zeros((n_LO, n_LO)) |
||||||
|
c_LO = np.zeros((n_LO, 1)) |
||||||
|
|
||||||
|
I_LOS_eq = list(I_LOS_eq) |
||||||
|
for eq in I_LOS_eq: |
||||||
|
i_LO = I_LOS_eq.index(eq) |
||||||
|
f_LO = vertcat(f_LO, Ax1[eq] + C_phi[eq] - lhs_nsf[eq]) |
||||||
|
print(f"eq {eq} I_LOS_components {I_LOS_components}, i_LO {i_LO}, f_LO {f_LO}") |
||||||
|
E_LO[i_LO, :] = E[eq, sorted(I_LOS_components)] |
||||||
|
A_LO[i_LO, :] = A[eq, I_x2] |
||||||
|
c_LO[i_LO, :] = c[eq] |
||||||
|
B_LO[i_LO, :] = B[eq, :] |
||||||
|
if casadi_length(f_LO) == 0: |
||||||
|
f_LO = SX.zeros((gnsf["nx2"] + gnsf["nz2"], 1)) |
||||||
|
f_LO = simplify(f_LO) |
||||||
|
gnsf["A_LO"] = A_LO |
||||||
|
gnsf["E_LO"] = E_LO |
||||||
|
gnsf["B_LO"] = B_LO |
||||||
|
gnsf["c_LO"] = c_LO |
||||||
|
gnsf["f_lo_expr"] = f_LO |
||||||
|
|
||||||
|
## remove I_LOS_eq from NSF type system |
||||||
|
gnsf["A"] = gnsf["A"][np.ix_(sorted(I_nsf_eq), sorted(I_x1))] |
||||||
|
gnsf["B"] = gnsf["B"][sorted(I_nsf_eq), :] |
||||||
|
gnsf["C"] = gnsf["C"][sorted(I_nsf_eq), :] |
||||||
|
gnsf["E"] = gnsf["E"][np.ix_(sorted(I_nsf_eq), sorted(I_nsf_components))] |
||||||
|
gnsf["c"] = gnsf["c"][sorted(I_nsf_eq), :] |
||||||
|
|
||||||
|
## reduce phi, C |
||||||
|
I_nonzero = [] |
||||||
|
for ii in range(gnsf["C"].shape[1]): # n_colums of C: |
||||||
|
print(f"ii {ii}") |
||||||
|
if not all(gnsf["C"][:, ii] == 0): # if column ~= 0 |
||||||
|
I_nonzero.append(ii) |
||||||
|
gnsf["C"] = gnsf["C"][:, I_nonzero] |
||||||
|
gnsf["phi_expr"] = gnsf["phi_expr"][I_nonzero] |
||||||
|
|
||||||
|
gnsf = determine_input_nonlinearity_function(gnsf) |
||||||
|
|
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
|
||||||
|
gnsf["nontrivial_f_LO"] = 0 |
||||||
|
if not is_empty(gnsf["f_lo_expr"]): |
||||||
|
for ii in range(casadi_length(gnsf["f_lo_expr"])): |
||||||
|
fii = gnsf["f_lo_expr"][ii] |
||||||
|
if not fii.is_zero(): |
||||||
|
gnsf["nontrivial_f_LO"] = 1 |
||||||
|
if not gnsf["nontrivial_f_LO"] and print_info: |
||||||
|
print("f_LO is fully trivial (== 0)") |
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print("") |
||||||
|
print( |
||||||
|
"---------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print( |
||||||
|
"------------- Success: Linear Output System (LOS) detected ----------------------" |
||||||
|
) |
||||||
|
print( |
||||||
|
"---------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print("") |
||||||
|
print( |
||||||
|
"==>> moved ", |
||||||
|
gnsf["nx2"], |
||||||
|
"differential states and ", |
||||||
|
gnsf["nz2"], |
||||||
|
" algebraic variables to the Linear Output System", |
||||||
|
) |
||||||
|
print( |
||||||
|
"==>> recuced output dimension of phi from ", |
||||||
|
casadi_length(phi_old), |
||||||
|
" to ", |
||||||
|
casadi_length(gnsf["phi_expr"]), |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print("Matrices defining the LOS read as") |
||||||
|
print(" ") |
||||||
|
print("E_LO =") |
||||||
|
print(gnsf["E_LO"]) |
||||||
|
print("A_LO =") |
||||||
|
print(gnsf["A_LO"]) |
||||||
|
print("B_LO =") |
||||||
|
print(gnsf["B_LO"]) |
||||||
|
print("c_LO =") |
||||||
|
print(gnsf["c_LO"]) |
||||||
|
|
||||||
|
return gnsf |
@ -0,0 +1,167 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com |
||||||
|
|
||||||
|
from casadi import * |
||||||
|
from .determine_input_nonlinearity_function import determine_input_nonlinearity_function |
||||||
|
from .check_reformulation import check_reformulation |
||||||
|
|
||||||
|
|
||||||
|
def reformulate_with_invertible_E_mat(gnsf, model, print_info): |
||||||
|
## Description |
||||||
|
# this function checks that the necessary condition to apply the gnsf |
||||||
|
# structure exploiting integrator to a model, namely that the matrices E11, |
||||||
|
# E22 are invertible holds. |
||||||
|
# if this is not the case, it will make these matrices invertible and add: |
||||||
|
# corresponding terms, to the term C * phi, such that the obtained model is |
||||||
|
# still equivalent |
||||||
|
|
||||||
|
# check invertibility of E11, E22 and reformulate if needed: |
||||||
|
ind_11 = range(gnsf["nx1"]) |
||||||
|
ind_22 = range(gnsf["nx1"], gnsf["nx1"] + gnsf["nz1"]) |
||||||
|
|
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
print("----------------------------------------------------") |
||||||
|
print("checking rank of E11 and E22") |
||||||
|
print("----------------------------------------------------") |
||||||
|
## check if E11, E22 are invertible: |
||||||
|
z_check = False |
||||||
|
if gnsf["nz1"] > 0: |
||||||
|
z_check = ( |
||||||
|
np.linalg.matrix_rank(gnsf["E"][np.ix_(ind_22, ind_22)]) != gnsf["nz1"] |
||||||
|
) |
||||||
|
|
||||||
|
if ( |
||||||
|
np.linalg.matrix_rank(gnsf["E"][np.ix_(ind_11, ind_11)]) != gnsf["nx1"] |
||||||
|
or z_check |
||||||
|
): |
||||||
|
# print warning (always) |
||||||
|
print(f"the rank of E11 or E22 is not full after the reformulation") |
||||||
|
print("") |
||||||
|
print( |
||||||
|
f"the script will try to reformulate the model with an invertible matrix instead" |
||||||
|
) |
||||||
|
print( |
||||||
|
f"NOTE: this feature is based on a heuristic, it should be used with care!!!" |
||||||
|
) |
||||||
|
|
||||||
|
## load models |
||||||
|
xdot = gnsf["xdot"] |
||||||
|
z = gnsf["z"] |
||||||
|
|
||||||
|
# # GNSF |
||||||
|
# get dimensions |
||||||
|
nx1 = gnsf["nx1"] |
||||||
|
x1dot = xdot[range(nx1)] |
||||||
|
|
||||||
|
k = vertcat(x1dot, z) |
||||||
|
for i in [1, 2]: |
||||||
|
if i == 1: |
||||||
|
ind = range(gnsf["nx1"]) |
||||||
|
else: |
||||||
|
ind = range(gnsf["nx1"], gnsf["nx1"] + gnsf["nz1"]) |
||||||
|
mat = gnsf["E"][np.ix_(ind, ind)] |
||||||
|
import pdb |
||||||
|
|
||||||
|
pdb.set_trace() |
||||||
|
while np.linalg.matrix_rank(mat) < len(ind): |
||||||
|
# import pdb; pdb.set_trace() |
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
print(f"the rank of E", str(i), str(i), " is not full") |
||||||
|
print( |
||||||
|
f"the algorithm will try to reformulate the model with an invertible matrix instead" |
||||||
|
) |
||||||
|
print( |
||||||
|
f"NOTE: this feature is not super stable and might need more testing!!!!!!" |
||||||
|
) |
||||||
|
for sub_max in ind: |
||||||
|
sub_ind = range(min(ind), sub_max) |
||||||
|
# regard the submatrix mat(sub_ind, sub_ind) |
||||||
|
sub_mat = gnsf["E"][sub_ind, sub_ind] |
||||||
|
if np.linalg.matrix_rank(sub_mat) < len(sub_ind): |
||||||
|
# reformulate the model by adding a 1 to last diagonal |
||||||
|
# element and changing rhs respectively. |
||||||
|
gnsf["E"][sub_max, sub_max] = gnsf["E"][sub_max, sub_max] + 1 |
||||||
|
# this means adding the term 1 * k(sub_max) to the sub_max |
||||||
|
# row of the l.h.s |
||||||
|
if len(np.nonzero(gnsf["C"][sub_max, :])[0]) == 0: |
||||||
|
# if isempty(find(gnsf['C'](sub_max,:), 1)): |
||||||
|
# add new nonlinearity entry |
||||||
|
gnsf["C"][sub_max, gnsf["n_out"] + 1] = 1 |
||||||
|
gnsf["phi_expr"] = vertcat(gnsf["phi_expr"], k[sub_max]) |
||||||
|
else: |
||||||
|
ind_f = np.nonzero(gnsf["C"][sub_max, :])[0] |
||||||
|
if len(ind_f) != 1: |
||||||
|
raise Exception("C is assumed to be a selection matrix") |
||||||
|
else: |
||||||
|
ind_f = ind_f[0] |
||||||
|
# add term to corresponding nonlinearity entry |
||||||
|
# note: herbey we assume that C is a selection matrix, |
||||||
|
# i.e. gnsf['phi_expr'](ind_f) is only entering one equation |
||||||
|
|
||||||
|
gnsf["phi_expr"][ind_f] = ( |
||||||
|
gnsf["phi_expr"][ind_f] |
||||||
|
+ k[sub_max] / gnsf["C"][sub_max, ind_f] |
||||||
|
) |
||||||
|
gnsf = determine_input_nonlinearity_function(gnsf) |
||||||
|
check_reformulation(model, gnsf, print_info) |
||||||
|
print("successfully reformulated the model with invertible matrices E11, E22") |
||||||
|
else: |
||||||
|
if print_info: |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"the rank of both E11 and E22 is naturally full after the reformulation " |
||||||
|
) |
||||||
|
print("==> model reformulation finished") |
||||||
|
print(" ") |
||||||
|
if (gnsf['nx2'] > 0 or gnsf['nz2'] > 0) and det(gnsf["E_LO"]) == 0: |
||||||
|
print( |
||||||
|
"_______________________________________________________________________________________________________" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print("TAKE CARE ") |
||||||
|
print("E_LO matrix is NOT regular after automatic transcription!") |
||||||
|
print("->> this means the model CANNOT be used with the gnsf integrator") |
||||||
|
print( |
||||||
|
"->> it probably means that one entry (of xdot or z) that was moved to the linear output type system" |
||||||
|
) |
||||||
|
print(" does not appear in the model at all (zero column in E_LO)") |
||||||
|
print(" OR: the columns of E_LO are linearly dependent ") |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
" SOLUTIONs: a) go through your model & check equations the method wanted to move to LOS" |
||||||
|
) |
||||||
|
print(" b) deactivate the detect_LOS option") |
||||||
|
print( |
||||||
|
"_______________________________________________________________________________________________________" |
||||||
|
) |
||||||
|
return gnsf |
@ -0,0 +1,174 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
# |
||||||
|
# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com |
||||||
|
|
||||||
|
from casadi import n_nodes |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
|
||||||
|
def structure_detection_print_summary(gnsf, acados_ocp): |
||||||
|
|
||||||
|
## Description |
||||||
|
# this function prints the most important info after determining a GNSF |
||||||
|
# reformulation of the implicit model "initial_model" into "gnsf", which is |
||||||
|
# equivalent to the "reordered_model". |
||||||
|
model = acados_ocp.model |
||||||
|
# # GNSF |
||||||
|
# get dimensions |
||||||
|
nx = gnsf["nx"] |
||||||
|
nu = gnsf["nu"] |
||||||
|
nz = gnsf["nz"] |
||||||
|
|
||||||
|
nx1 = gnsf["nx1"] |
||||||
|
nx2 = gnsf["nx2"] |
||||||
|
|
||||||
|
nz1 = gnsf["nz1"] |
||||||
|
nz2 = gnsf["nz2"] |
||||||
|
|
||||||
|
# np = gnsf['np'] |
||||||
|
n_out = gnsf["n_out"] |
||||||
|
ny = gnsf["ny"] |
||||||
|
nuhat = gnsf["nuhat"] |
||||||
|
|
||||||
|
# |
||||||
|
f_impl_expr = model.f_impl_expr |
||||||
|
n_nodes_initial = n_nodes(model.f_impl_expr) |
||||||
|
# x_old = model.x |
||||||
|
# f_impl_old = model.f_impl_expr |
||||||
|
|
||||||
|
x = gnsf["x"] |
||||||
|
z = gnsf["z"] |
||||||
|
|
||||||
|
phi_current = gnsf["phi_expr"] |
||||||
|
|
||||||
|
## PRINT SUMMARY -- STRUCHTRE DETECTION |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"*********************************************************************************************" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"****************** SUCCESS: GNSF STRUCTURE DETECTION COMPLETE !!! ***************" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"*********************************************************************************************" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
f"========================= STRUCTURE DETECTION SUMMARY ====================================" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print("-------- Nonlinear Static Feedback type system --------") |
||||||
|
print(" ") |
||||||
|
print(" successfully transcribed dynamic system model into GNSF structure ") |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"reduced dimension of nonlinearity phi from ", |
||||||
|
str(nx + nz), |
||||||
|
" to ", |
||||||
|
str(gnsf["n_out"]), |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"reduced input dimension of nonlinearity phi from ", |
||||||
|
2 * nx + nz + nu, |
||||||
|
" to ", |
||||||
|
gnsf["ny"] + gnsf["nuhat"], |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print(f"reduced number of nodes in CasADi expression of nonlinearity phi from {n_nodes_initial} to {n_nodes(phi_current)}\n") |
||||||
|
print("----------- Linear Output System (LOS) ---------------") |
||||||
|
if nx2 + nz2 > 0: |
||||||
|
print(" ") |
||||||
|
print(f"introduced Linear Output System of size ", str(nx2 + nz2)) |
||||||
|
print(" ") |
||||||
|
if nx2 > 0: |
||||||
|
print("consisting of the states:") |
||||||
|
print(" ") |
||||||
|
print(x[range(nx1, nx)]) |
||||||
|
print(" ") |
||||||
|
if nz2 > 0: |
||||||
|
print("and algebraic variables:") |
||||||
|
print(" ") |
||||||
|
print(z[range(nz1, nz)]) |
||||||
|
print(" ") |
||||||
|
if gnsf["purely_linear"] == 1: |
||||||
|
print(" ") |
||||||
|
print("Model is fully linear!") |
||||||
|
print(" ") |
||||||
|
if not all(gnsf["idx_perm_x"] == np.array(range(nx))): |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"--------------------------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print( |
||||||
|
"NOTE: permuted differential state vector x, such that x_gnsf = x(idx_perm_x) with idx_perm_x =" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print(gnsf["idx_perm_x"]) |
||||||
|
if nz != 0 and not all(gnsf["idx_perm_z"] == np.array(range(nz))): |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"--------------------------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print( |
||||||
|
"NOTE: permuted algebraic state vector z, such that z_gnsf = z(idx_perm_z) with idx_perm_z =" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print(gnsf["idx_perm_z"]) |
||||||
|
if not all(gnsf["idx_perm_f"] == np.array(range(nx + nz))): |
||||||
|
print(" ") |
||||||
|
print( |
||||||
|
"--------------------------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print( |
||||||
|
"NOTE: permuted rhs expression vector f, such that f_gnsf = f(idx_perm_f) with idx_perm_f =" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print(gnsf["idx_perm_f"]) |
||||||
|
## print GNSF dimensions |
||||||
|
print( |
||||||
|
"--------------------------------------------------------------------------------------------------------" |
||||||
|
) |
||||||
|
print(" ") |
||||||
|
print("The dimensions of the GNSF reformulated model read as:") |
||||||
|
print(" ") |
||||||
|
# T_dim = table(nx, nu, nz, np, nx1, nz1, n_out, ny, nuhat) |
||||||
|
# print( T_dim ) |
||||||
|
print(f"nx ", {nx}) |
||||||
|
print(f"nu ", {nu}) |
||||||
|
print(f"nz ", {nz}) |
||||||
|
# print(f"np ", {np}) |
||||||
|
print(f"nx1 ", {nx1}) |
||||||
|
print(f"nz1 ", {nz1}) |
||||||
|
print(f"n_out ", {n_out}) |
||||||
|
print(f"ny ", {ny}) |
||||||
|
print(f"nuhat ", {nuhat}) |
@ -0,0 +1,78 @@ |
|||||||
|
# Copyright (c) The acados authors. |
||||||
|
# |
||||||
|
# This file is part of acados. |
||||||
|
# |
||||||
|
# The 2-Clause BSD License |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer. |
||||||
|
# |
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
# this list of conditions and the following disclaimer in the documentation |
||||||
|
# and/or other materials provided with the distribution. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
# POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
|
||||||
|
from dataclasses import dataclass, field |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
|
||||||
|
@dataclass |
||||||
|
class ZoroDescription: |
||||||
|
""" |
||||||
|
Zero-Order Robust Optimization scheme. |
||||||
|
|
||||||
|
For advanced users. |
||||||
|
""" |
||||||
|
backoff_scaling_gamma: float = 1.0 |
||||||
|
fdbk_K_mat: np.ndarray = None |
||||||
|
unc_jac_G_mat: np.ndarray = None # default: an identity matrix |
||||||
|
P0_mat: np.ndarray = None |
||||||
|
W_mat: np.ndarray = None |
||||||
|
idx_lbx_t: list = field(default_factory=list) |
||||||
|
idx_ubx_t: list = field(default_factory=list) |
||||||
|
idx_lbx_e_t: list = field(default_factory=list) |
||||||
|
idx_ubx_e_t: list = field(default_factory=list) |
||||||
|
idx_lbu_t: list = field(default_factory=list) |
||||||
|
idx_ubu_t: list = field(default_factory=list) |
||||||
|
idx_lg_t: list = field(default_factory=list) |
||||||
|
idx_ug_t: list = field(default_factory=list) |
||||||
|
idx_lg_e_t: list = field(default_factory=list) |
||||||
|
idx_ug_e_t: list = field(default_factory=list) |
||||||
|
idx_lh_t: list = field(default_factory=list) |
||||||
|
idx_uh_t: list = field(default_factory=list) |
||||||
|
idx_lh_e_t: list = field(default_factory=list) |
||||||
|
idx_uh_e_t: list = field(default_factory=list) |
||||||
|
|
||||||
|
def process_zoro_description(zoro_description: ZoroDescription): |
||||||
|
zoro_description.nw, _ = zoro_description.W_mat.shape |
||||||
|
if zoro_description.unc_jac_G_mat is None: |
||||||
|
zoro_description.unc_jac_G_mat = np.eye(zoro_description.nw) |
||||||
|
zoro_description.nlbx_t = len(zoro_description.idx_lbx_t) |
||||||
|
zoro_description.nubx_t = len(zoro_description.idx_ubx_t) |
||||||
|
zoro_description.nlbx_e_t = len(zoro_description.idx_lbx_e_t) |
||||||
|
zoro_description.nubx_e_t = len(zoro_description.idx_ubx_e_t) |
||||||
|
zoro_description.nlbu_t = len(zoro_description.idx_lbu_t) |
||||||
|
zoro_description.nubu_t = len(zoro_description.idx_ubu_t) |
||||||
|
zoro_description.nlg_t = len(zoro_description.idx_lg_t) |
||||||
|
zoro_description.nug_t = len(zoro_description.idx_ug_t) |
||||||
|
zoro_description.nlg_e_t = len(zoro_description.idx_lg_e_t) |
||||||
|
zoro_description.nug_e_t = len(zoro_description.idx_ug_e_t) |
||||||
|
zoro_description.nlh_t = len(zoro_description.idx_lh_t) |
||||||
|
zoro_description.nuh_t = len(zoro_description.idx_uh_t) |
||||||
|
zoro_description.nlh_e_t = len(zoro_description.idx_lh_e_t) |
||||||
|
zoro_description.nuh_e_t = len(zoro_description.idx_uh_e_t) |
||||||
|
return zoro_description.__dict__ |
@ -0,0 +1,110 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) The acados authors. |
||||||
|
* |
||||||
|
* This file is part of acados. |
||||||
|
* |
||||||
|
* The 2-Clause BSD License |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* |
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer in the documentation |
||||||
|
* and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
* POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#ifndef ACADOS_DENSE_QP_DENSE_QP_DAQP_H_ |
||||||
|
#define ACADOS_DENSE_QP_DENSE_QP_DAQP_H_ |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
// blasfeo
|
||||||
|
#include "blasfeo/include/blasfeo_common.h" |
||||||
|
|
||||||
|
// daqp
|
||||||
|
#include "daqp/include/types.h" |
||||||
|
|
||||||
|
// acados
|
||||||
|
#include "acados/dense_qp/dense_qp_common.h" |
||||||
|
#include "acados/utils/types.h" |
||||||
|
|
||||||
|
|
||||||
|
typedef struct dense_qp_daqp_opts_ |
||||||
|
{ |
||||||
|
DAQPSettings* daqp_opts; |
||||||
|
int warm_start; |
||||||
|
} dense_qp_daqp_opts; |
||||||
|
|
||||||
|
|
||||||
|
typedef struct dense_qp_daqp_memory_ |
||||||
|
{ |
||||||
|
double* lb_tmp; |
||||||
|
double* ub_tmp; |
||||||
|
int* idxb; |
||||||
|
int* idxv_to_idxb; |
||||||
|
int* idxs; |
||||||
|
int* idxdaqp_to_idxs; |
||||||
|
|
||||||
|
double* Zl; |
||||||
|
double* Zu; |
||||||
|
double* zl; |
||||||
|
double* zu; |
||||||
|
double* d_ls; |
||||||
|
double* d_us; |
||||||
|
|
||||||
|
double time_qp_solver_call; |
||||||
|
int iter; |
||||||
|
DAQPWorkspace * daqp_work; |
||||||
|
|
||||||
|
} dense_qp_daqp_memory; |
||||||
|
|
||||||
|
// opts
|
||||||
|
acados_size_t dense_qp_daqp_opts_calculate_size(void *config, dense_qp_dims *dims); |
||||||
|
//
|
||||||
|
void *dense_qp_daqp_opts_assign(void *config, dense_qp_dims *dims, void *raw_memory); |
||||||
|
//
|
||||||
|
void dense_qp_daqp_opts_initialize_default(void *config, dense_qp_dims *dims, void *opts_); |
||||||
|
//
|
||||||
|
void dense_qp_daqp_opts_update(void *config, dense_qp_dims *dims, void *opts_); |
||||||
|
//
|
||||||
|
// memory
|
||||||
|
acados_size_t dense_qp_daqp_workspace_calculate_size(void *config, dense_qp_dims *dims, void *opts_); |
||||||
|
//
|
||||||
|
void *dense_qp_daqp_workspace_assign(void *config, dense_qp_dims *dims, void *raw_memory); |
||||||
|
//
|
||||||
|
acados_size_t dense_qp_daqp_memory_calculate_size(void *config, dense_qp_dims *dims, void *opts_); |
||||||
|
//
|
||||||
|
void *dense_qp_daqp_memory_assign(void *config, dense_qp_dims *dims, void *opts_, void *raw_memory); |
||||||
|
//
|
||||||
|
// functions
|
||||||
|
int dense_qp_daqp(void *config, dense_qp_in *qp_in, dense_qp_out *qp_out, void *opts_, void *memory_, void *work_); |
||||||
|
//
|
||||||
|
void dense_qp_daqp_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); |
||||||
|
//
|
||||||
|
void dense_qp_daqp_memory_reset(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); |
||||||
|
//
|
||||||
|
void dense_qp_daqp_config_initialize_default(void *config_); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} /* extern "C" */ |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif // ACADOS_DENSE_QP_DENSE_QP_DAQP_H_
|
@ -0,0 +1,207 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) The acados authors. |
||||||
|
* |
||||||
|
* This file is part of acados. |
||||||
|
* |
||||||
|
* The 2-Clause BSD License |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* |
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer in the documentation |
||||||
|
* and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
* POSSIBILITY OF SUCH DAMAGE.; |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
/// \addtogroup ocp_nlp
|
||||||
|
/// @{
|
||||||
|
/// \addtogroup ocp_nlp_cost ocp_nlp_cost
|
||||||
|
/// @{
|
||||||
|
/// \addtogroup ocp_nlp_cost_conl ocp_nlp_cost_conl
|
||||||
|
/// \brief This module implements convex-over-nonlinear costs of the form
|
||||||
|
/// \f$\min_{x,u,z} \psi(y(x,u,z,p) - y_{\text{ref}}, p)\f$,
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ACADOS_OCP_NLP_OCP_NLP_COST_CONL_H_ |
||||||
|
#define ACADOS_OCP_NLP_OCP_NLP_COST_CONL_H_ |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
// blasfeo
|
||||||
|
#include "blasfeo/include/blasfeo_common.h" |
||||||
|
|
||||||
|
// acados
|
||||||
|
#include "acados/ocp_nlp/ocp_nlp_cost_common.h" |
||||||
|
#include "acados/utils/external_function_generic.h" |
||||||
|
#include "acados/utils/types.h" |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* dims |
||||||
|
************************************************/ |
||||||
|
|
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
int nx; // number of states
|
||||||
|
int nz; // number of algebraic variables
|
||||||
|
int nu; // number of inputs
|
||||||
|
int ny; // number of outputs
|
||||||
|
int ns; // number of slacks
|
||||||
|
} ocp_nlp_cost_conl_dims; |
||||||
|
|
||||||
|
//
|
||||||
|
acados_size_t ocp_nlp_cost_conl_dims_calculate_size(void *config); |
||||||
|
//
|
||||||
|
void *ocp_nlp_cost_conl_dims_assign(void *config, void *raw_memory); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_dims_initialize(void *config, void *dims, int nx, int nu, int ny, int ns, int nz); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_dims_set(void *config_, void *dims_, const char *field, int* value); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_dims_get(void *config_, void *dims_, const char *field, int* value); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* model |
||||||
|
************************************************/ |
||||||
|
|
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
// slack penalty has the form z^T * s + .5 * s^T * Z * s
|
||||||
|
external_function_generic *conl_cost_fun; |
||||||
|
external_function_generic *conl_cost_fun_jac_hess; |
||||||
|
struct blasfeo_dvec y_ref; |
||||||
|
struct blasfeo_dvec Z; // diagonal Hessian of slacks as vector
|
||||||
|
struct blasfeo_dvec z; // gradient of slacks as vector
|
||||||
|
double scaling; |
||||||
|
} ocp_nlp_cost_conl_model; |
||||||
|
|
||||||
|
//
|
||||||
|
acados_size_t ocp_nlp_cost_conl_model_calculate_size(void *config, void *dims); |
||||||
|
//
|
||||||
|
void *ocp_nlp_cost_conl_model_assign(void *config, void *dims, void *raw_memory); |
||||||
|
//
|
||||||
|
int ocp_nlp_cost_conl_model_set(void *config_, void *dims_, void *model_, const char *field, void *value_); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* options |
||||||
|
************************************************/ |
||||||
|
|
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
bool gauss_newton_hess; // dummy options, we always use a gauss-newton hessian
|
||||||
|
} ocp_nlp_cost_conl_opts; |
||||||
|
|
||||||
|
//
|
||||||
|
acados_size_t ocp_nlp_cost_conl_opts_calculate_size(void *config, void *dims); |
||||||
|
//
|
||||||
|
void *ocp_nlp_cost_conl_opts_assign(void *config, void *dims, void *raw_memory); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_opts_initialize_default(void *config, void *dims, void *opts); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_opts_update(void *config, void *dims, void *opts); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_opts_set(void *config, void *opts, const char *field, void *value); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* memory |
||||||
|
************************************************/ |
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
struct blasfeo_dvec grad; // gradient of cost function
|
||||||
|
struct blasfeo_dvec *ux; // pointer to ux in nlp_out
|
||||||
|
struct blasfeo_dvec *tmp_ux; // pointer to ux in tmp_nlp_out
|
||||||
|
struct blasfeo_dmat *RSQrq; // pointer to RSQrq in qp_in
|
||||||
|
struct blasfeo_dvec *Z; // pointer to Z in qp_in
|
||||||
|
struct blasfeo_dvec *z_alg; ///< pointer to z in sim_out
|
||||||
|
struct blasfeo_dmat *dzdux_tran; ///< pointer to sensitivity of a wrt ux in sim_out
|
||||||
|
double fun; ///< value of the cost function
|
||||||
|
} ocp_nlp_cost_conl_memory; |
||||||
|
|
||||||
|
//
|
||||||
|
acados_size_t ocp_nlp_cost_conl_memory_calculate_size(void *config, void *dims, void *opts); |
||||||
|
//
|
||||||
|
void *ocp_nlp_cost_conl_memory_assign(void *config, void *dims, void *opts, void *raw_memory); |
||||||
|
//
|
||||||
|
double *ocp_nlp_cost_conl_memory_get_fun_ptr(void *memory_); |
||||||
|
//
|
||||||
|
struct blasfeo_dvec *ocp_nlp_cost_conl_memory_get_grad_ptr(void *memory_); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_memory_set_RSQrq_ptr(struct blasfeo_dmat *RSQrq, void *memory); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_memory_set_Z_ptr(struct blasfeo_dvec *Z, void *memory); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory_); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory_); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_memory_set_z_alg_ptr(struct blasfeo_dvec *z_alg, void *memory_); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_memory_set_dzdux_tran_ptr(struct blasfeo_dmat *dzdux_tran, void *memory_); |
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* workspace |
||||||
|
************************************************/ |
||||||
|
|
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
struct blasfeo_dmat W; // hessian of outer loss function
|
||||||
|
struct blasfeo_dmat W_chol; // cholesky factor of hessian of outer loss function
|
||||||
|
struct blasfeo_dmat Jt_ux; // jacobian of inner residual function
|
||||||
|
struct blasfeo_dmat Jt_ux_tilde; // jacobian of inner residual function plus gradient contribution of algebraic variables
|
||||||
|
struct blasfeo_dmat Jt_z; // jacobian of inner residual function wrt algebraic variables
|
||||||
|
struct blasfeo_dmat tmp_nv_ny; |
||||||
|
struct blasfeo_dvec tmp_ny; |
||||||
|
struct blasfeo_dvec tmp_2ns; |
||||||
|
} ocp_nlp_cost_conl_workspace; |
||||||
|
|
||||||
|
//
|
||||||
|
acados_size_t ocp_nlp_cost_conl_workspace_calculate_size(void *config, void *dims, void *opts); |
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* functions |
||||||
|
************************************************/ |
||||||
|
|
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_precompute(void *config_, void *dims_, void *model_, void *opts_, void *memory_, void *work_); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_config_initialize_default(void *config); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_initialize(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_update_qp_matrices(void *config_, void *dims, void *model_, void *opts_, void *memory_, void *work_); |
||||||
|
//
|
||||||
|
void ocp_nlp_cost_conl_compute_fun(void *config_, void *dims, void *model_, void *opts_, void *memory_, void *work_); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} /* extern "C" */ |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif // ACADOS_OCP_NLP_OCP_NLP_COST_CONL_H_
|
||||||
|
/// @}
|
||||||
|
/// @}
|
||||||
|
/// @}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue