From 69215ad17e6c85129330cb4037a0480f865b337b Mon Sep 17 00:00:00 2001 From: Jonathan Frey Date: Thu, 17 Apr 2025 17:30:59 +0200 Subject: [PATCH 1/3] Batch solvers, only use verbose when creating first solver --- .../acados_template/acados_template/acados_ocp_batch_solver.py | 3 ++- .../acados_template/acados_template/acados_sim_batch_solver.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interfaces/acados_template/acados_template/acados_ocp_batch_solver.py b/interfaces/acados_template/acados_template/acados_ocp_batch_solver.py index 6f75d164e2..6f9068ed58 100644 --- a/interfaces/acados_template/acados_template/acados_ocp_batch_solver.py +++ b/interfaces/acados_template/acados_template/acados_ocp_batch_solver.py @@ -77,7 +77,8 @@ def __init__(self, ocp: AcadosOcp, N_batch_max: int, json_file=json_file, build=n==0 if build else False, generate=n==0 if generate else False, - verbose=verbose) + verbose=verbose if n==0 else False, + ) for n in range(self.N_batch_max)] self.__shared_lib = self.ocp_solvers[0].shared_lib diff --git a/interfaces/acados_template/acados_template/acados_sim_batch_solver.py b/interfaces/acados_template/acados_template/acados_sim_batch_solver.py index 5d0ac0d466..0893f8d731 100644 --- a/interfaces/acados_template/acados_template/acados_sim_batch_solver.py +++ b/interfaces/acados_template/acados_template/acados_sim_batch_solver.py @@ -70,7 +70,8 @@ def __init__(self, sim: AcadosSim, N_batch: int, num_threads_in_batch_solve: Uni json_file=json_file, build=n==0 if build else False, generate=n==0 if generate else False, - verbose=verbose) + verbose=verbose if n==0 else False, + ) for n in range(self.N_batch)] self.__shared_lib = self.sim_solvers[0].shared_lib From 96018c2b32ba82ff4157ca974bac1b73b291b2d9 Mon Sep 17 00:00:00 2001 From: Jonathan Frey Date: Thu, 17 Apr 2025 17:47:59 +0200 Subject: [PATCH 2/3] add verbose to make_consistent to avoid printing warnings about GN Hessian --- .../acados_template/acados_multiphase_ocp.py | 4 +- .../acados_template/acados_ocp.py | 37 ++++++++++--------- .../acados_template/acados_ocp_solver.py | 8 ++-- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/interfaces/acados_template/acados_template/acados_multiphase_ocp.py b/interfaces/acados_template/acados_template/acados_multiphase_ocp.py index 6df5df8176..9282eb8528 100644 --- a/interfaces/acados_template/acados_template/acados_multiphase_ocp.py +++ b/interfaces/acados_template/acados_template/acados_multiphase_ocp.py @@ -256,7 +256,7 @@ def set_phase(self, ocp: AcadosOcp, phase_idx: int) -> None: return - def make_consistent(self) -> None: + def make_consistent(self, verbose: bool = True) -> None: self.N_horizon = sum(self.N_list) self.solver_options.N_horizon = self.N_horizon # NOTE: to not change options when making ocp consistent @@ -330,7 +330,7 @@ def make_consistent(self) -> None: print(f"Phase {i} contains non-default initial fields: {nondefault_fields}, which will be ignored.") print(f"Calling make_consistent for phase {i}.") - ocp.make_consistent(is_mocp_phase=True) + ocp.make_consistent(is_mocp_phase=True, verbose=verbose) self.dummy_ocp_list.append(ocp) diff --git a/interfaces/acados_template/acados_template/acados_ocp.py b/interfaces/acados_template/acados_template/acados_ocp.py index f1be8b93b5..4aa465568e 100644 --- a/interfaces/acados_template/acados_template/acados_ocp.py +++ b/interfaces/acados_template/acados_template/acados_ocp.py @@ -898,7 +898,7 @@ def _make_consistent_simulation(self): raise ValueError("Wrong value for sim_method_jac_reuse. Should be either int or array of ints of shape (N,).") - def make_consistent(self, is_mocp_phase=False) -> None: + def make_consistent(self, is_mocp_phase: bool=False, verbose: bool=True) -> None: """ Detect dimensions, perform sanity checks """ @@ -941,23 +941,24 @@ def make_consistent(self, is_mocp_phase=False) -> None: self._make_consistent_cost_terminal() # GN check - gn_warning_0 = (opts.N_horizon > 0 and cost.cost_type_0 == 'EXTERNAL' and opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and is_empty(model.cost_expr_ext_cost_custom_hess_0)) - gn_warning_path = (opts.N_horizon > 0 and cost.cost_type == 'EXTERNAL' and opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and is_empty(model.cost_expr_ext_cost_custom_hess)) - gn_warning_terminal = (cost.cost_type_e == 'EXTERNAL' and opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and is_empty(model.cost_expr_ext_cost_custom_hess_e)) - if any([gn_warning_0, gn_warning_path, gn_warning_terminal]): - external_cost_types = [] - if gn_warning_0: - external_cost_types.append('cost_type_0') - if gn_warning_path: - external_cost_types.append('cost_type') - if gn_warning_terminal: - external_cost_types.append('cost_type_e') - print("\nWARNING: Gauss-Newton Hessian approximation with EXTERNAL cost type not well defined!\n" - f"got cost_type EXTERNAL for {', '.join(external_cost_types)}, hessian_approx: 'GAUSS_NEWTON'.\n" - "With this setting, acados will proceed computing the exact Hessian for the cost term and no Hessian contribution from constraints and dynamics.\n" - "If the external cost is a linear least squares cost, this coincides with the Gauss-Newton Hessian.\n" - "Note: There is also the option to use the external cost module with a numerical Hessian approximation (see `ext_cost_num_hess`).\n" - "OR the option to provide a symbolic custom Hessian approximation (see `cost_expr_ext_cost_custom_hess`).\n") + if verbose: + gn_warning_0 = (opts.N_horizon > 0 and cost.cost_type_0 == 'EXTERNAL' and opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and is_empty(model.cost_expr_ext_cost_custom_hess_0)) + gn_warning_path = (opts.N_horizon > 0 and cost.cost_type == 'EXTERNAL' and opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and is_empty(model.cost_expr_ext_cost_custom_hess)) + gn_warning_terminal = (cost.cost_type_e == 'EXTERNAL' and opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and is_empty(model.cost_expr_ext_cost_custom_hess_e)) + if any([gn_warning_0, gn_warning_path, gn_warning_terminal]): + external_cost_types = [] + if gn_warning_0: + external_cost_types.append('cost_type_0') + if gn_warning_path: + external_cost_types.append('cost_type') + if gn_warning_terminal: + external_cost_types.append('cost_type_e') + print("\nWARNING: Gauss-Newton Hessian approximation with EXTERNAL cost type not well defined!\n" + f"got cost_type EXTERNAL for {', '.join(external_cost_types)}, hessian_approx: 'GAUSS_NEWTON'.\n" + "With this setting, acados will proceed computing the exact Hessian for the cost term and no Hessian contribution from constraints and dynamics.\n" + "If the external cost is a linear least squares cost, this coincides with the Gauss-Newton Hessian.\n" + "Note: There is also the option to use the external cost module with a numerical Hessian approximation (see `ext_cost_num_hess`).\n" + "OR the option to provide a symbolic custom Hessian approximation (see `cost_expr_ext_cost_custom_hess`).\n") # cost integration if opts.N_horizon > 0: diff --git a/interfaces/acados_template/acados_template/acados_ocp_solver.py b/interfaces/acados_template/acados_template/acados_ocp_solver.py index eb8f585b5d..e3b3bf6f63 100644 --- a/interfaces/acados_template/acados_template/acados_ocp_solver.py +++ b/interfaces/acados_template/acados_template/acados_ocp_solver.py @@ -90,7 +90,7 @@ def shared_lib(self,): return self.__shared_lib @classmethod - def generate(cls, acados_ocp: Union[AcadosOcp, AcadosMultiphaseOcp], json_file: str, simulink_opts=None, cmake_builder: CMakeBuilder = None): + def generate(cls, acados_ocp: Union[AcadosOcp, AcadosMultiphaseOcp], json_file: str, simulink_opts=None, cmake_builder: CMakeBuilder = None, verbose=True): """ Generates the code for an acados OCP solver, given the description in acados_ocp. :param acados_ocp: type Union[AcadosOcp, AcadosMultiphaseOcp] - description of the OCP for acados @@ -112,7 +112,7 @@ def generate(cls, acados_ocp: Union[AcadosOcp, AcadosMultiphaseOcp], json_file: acados_ocp.simulink_opts = simulink_opts # make consistent - acados_ocp.make_consistent() + acados_ocp.make_consistent(verbose=verbose) # module dependent post processing if acados_ocp.solver_options.integrator_type == 'GNSF': @@ -225,11 +225,11 @@ def __init__(self, acados_ocp: Union[AcadosOcp, AcadosMultiphaseOcp, None], json if generate: if json_file is not None: acados_ocp.json_file = json_file - self.generate(acados_ocp, json_file=acados_ocp.json_file, simulink_opts=simulink_opts, cmake_builder=cmake_builder) + self.generate(acados_ocp, json_file=acados_ocp.json_file, simulink_opts=simulink_opts, cmake_builder=cmake_builder, verbose=verbose) json_file = acados_ocp.json_file else: if acados_ocp is not None: - acados_ocp.make_consistent() + acados_ocp.make_consistent(verbose=verbose) # load json, store options in object with open(json_file, 'r') as f: From 0e6152c6924f1a17ccfa95d9568fedcf8c1c2d11 Mon Sep 17 00:00:00 2001 From: Jonathan Frey Date: Thu, 17 Apr 2025 18:03:38 +0200 Subject: [PATCH 3/3] add verbose to docstring --- interfaces/acados_template/acados_template/acados_ocp_solver.py | 1 + 1 file changed, 1 insertion(+) diff --git a/interfaces/acados_template/acados_template/acados_ocp_solver.py b/interfaces/acados_template/acados_template/acados_ocp_solver.py index e3b3bf6f63..2f443f0377 100644 --- a/interfaces/acados_template/acados_template/acados_ocp_solver.py +++ b/interfaces/acados_template/acados_template/acados_ocp_solver.py @@ -100,6 +100,7 @@ def generate(cls, acados_ocp: Union[AcadosOcp, AcadosMultiphaseOcp], json_file: :param cmake_builder: type :py:class:`~acados_template.builders.CMakeBuilder` generate a `CMakeLists.txt` and use the `CMake` pipeline instead of a `Makefile` (`CMake` seems to be the better option in conjunction with `MS Visual Studio`); default: `None` + :param verbose: indicating if warnings are printed """ acados_ocp.code_export_directory = os.path.abspath(acados_ocp.code_export_directory)