Source code for pymycar.SuspensionKinematic.double_whisbone

"""
Suspension: Double Wishbone
===========================

This module provides functions to analyze and simulate the behavior of a double wishbone suspension system. The double wishbone suspension is a type of vehicle suspension design that uses two wishbone-shaped arms (or control arms) to locate the wheel. This type of suspension is widely used in various vehicles, from road cars to competition vehicles.

"""

###############################################################################
# Import necessary libraries
# --------------------------
import os
import numpy as np


###############################################################################
# Import from pymycar package
# ---------------------------
from pymycar.files import prepare_simulation, save_results_2_txt
from pymycar.Logger.library_versions import logger_suspension_kinematics
from pymycar.SuspensionKinematic.functions import solve, generate_wheel_center_heights
from pymycar.SuspensionKinematic.suspension_files import saved_defined_geometry # save_data
from pymycar.SuspensionKinematic.functions import get_wheel

[docs] def double_whisbone_base(data, max_height_increase, max_height_decrease, height_step, save_to_txt=True, result_folder_name="results", path = None): """ Computes and solves the geometric constraints for a double wishbone suspension system. The function generates different wheel center heights based on input constraints, then calculates the residuals for a non-linear optimization problem to find the correct configuration of the suspension system. Parameters ---------- data : dict A dictionary containing the initial measurements and reference points for the suspension system. Expected keys include: - 'wheel_center': The initial wheel center position. - 'uca_outer': The outer UCA (Upper Control Arm) position. - 'UCA_FRONT': The front reference point for the UCA. - 'UCA_REAR': The rear reference point for the UCA. - 'lca_outer': The outer LCA (Lower Control Arm) position. - 'LCA_FRONT': The front reference point for the LCA. - 'LCA_REAR': The rear reference point for the LCA. - 'tierod_outer': The outer tierod position. - 'TIEROD_INNER': The inner reference point for the tierod. max_height_increase : float Maximum increase in wheel center height for the analysis. max_height_decrease : float Maximum decrease in wheel center height for the analysis. height_step : float Step size for incrementing and decrementing the wheel center height. save_to_txt : bool, optional If True, the results will be saved to a text file. Default is True. result_folder_name : str, optional The name of the folder where results will be saved. Default is "results". path : str, optional The path where the results folder will be created. If None, the current working directory is used. Default is None. Returns ------- solution : dict A dictionary with the optimized suspension parameters and their values: - 'UCA_FRONT': The front UCA position. - 'UCA_REAR': The rear UCA position. - 'LCA_FRONT': The front LCA position. - 'LCA_REAR': The rear LCA position. - 'TIEROD_INNER': The inner tierod position. - 'uca_outer': Optimized outer UCA positions. - 'lca_outer': Optimized outer LCA positions. - 'tierod_outer': Optimized outer tierod positions. - 'wheel_center': Optimized wheel center positions. - 'index_reference': Index reference for the wheel center heights. Notes ----- The function utilizes an optimization algorithm to solve for the configuration of the suspension system that satisfies the geometric constraints. The geometric model assumes a double wishbone suspension layout with specific reference points for each component. .. code-block:: # # /// # \-/ # UCA_REAR* # / # / # ----------- / # | | / # | | *----------*UCA_FRONT # | | uca_outer /⁻\ # | | /// # | | # | wheel center # | * | tierod_outer # | | *--------------------*TIEROD_INNER # | | # | | # | | lca_outer # | | *------------*LCA_REAR # ----------- \ /⁻\ # \ /// # \ # *LCA_FRONT # /⁻\ # /// +-----------------+--------------------------+--------+ | Points Name | Description | Type | +=================+==========================+========+ | wheel center | Center of the Wheel | mobile | +-----------------+--------------------------+--------+ | UCA FRONT | Upper Control Arm Front | fixed | +-----------------+--------------------------+--------+ | UCA REAR | Upper Control Arm Rear | fixed | +-----------------+--------------------------+--------+ | uca outer | Upper Control Arm Outer | mobile | +-----------------+--------------------------+--------+ | LCA FRONT | Lower Control Arm Front | fixed | +-----------------+--------------------------+--------+ | LCA REAR | Lower Control Arm Rear | fixed | +-----------------+--------------------------+--------+ | lca outer | Lower Control Arm Outer | mobile | +-----------------+--------------------------+--------+ | TIEROD INNER | Inner Tie Rod | fixed | +-----------------+--------------------------+--------+ | tierod outer | Outer Tie Rod | mobile | +-----------------+--------------------------+--------+ """ if path is None: path = os.getcwd() prepare_simulation(path, result_folder_name) logger_suspension_kinematics(data, max_height_increase, max_height_decrease, height_step, save_to_txt, result_folder_name, path) wheel, index = generate_wheel_center_heights( data["wheel_center"], max_height_increase, max_height_decrease, height_step) def get_L(): L = np.array([ data["uca_outer"] - data["UCA_FRONT"], data["uca_outer"] - data["UCA_REAR"], data["lca_outer"] - data["LCA_FRONT"], data["lca_outer"] - data["LCA_REAR"], data["tierod_outer"] - data["TIEROD_INNER"], data["tierod_outer"] - data["uca_outer"], data["tierod_outer"] - data["lca_outer"], data["lca_outer"] - data["uca_outer"], data["wheel_center"] - data["uca_outer"], data["wheel_center"] - data["lca_outer"], data["wheel_center"] - data["tierod_outer"], ]) return L L_squared = np.linalg.norm(get_L(), axis=1)**2 def jacobian(x, _): J = np.zeros([len(x), len(x)]) # EQ0 (1) J[0, 0] = 2 * (x[0] - data["UCA_FRONT"][0]) J[0, 1] = 2 * (x[1] - data["UCA_FRONT"][1]) J[0, 2] = 2 * (x[2] - data["UCA_FRONT"][2]) # EQ1 (1) J[1, 0] = 2 * (x[0] - data["UCA_REAR"][0]) J[1, 1] = 2 * (x[1] - data["UCA_REAR"][1]) J[1, 2] = 2 * (x[2] - data["UCA_REAR"][2]) # EQ2 (2) J[2, 3] = 2 * (x[3] - data["LCA_FRONT"][0]) J[2, 4] = 2 * (x[4] - data["LCA_FRONT"][1]) J[2, 5] = 2 * (x[5] - data["LCA_FRONT"][2]) # EQ3 (2) J[3, 3] = 2 * (x[3] - data["LCA_REAR"][0]) J[3, 4] = 2 * (x[4] - data["LCA_REAR"][1]) J[3, 5] = 2 * (x[5] - data["LCA_REAR"][2]) # EQ4 (3) J[4, 6] = 2 * (x[6] - data["TIEROD_INNER"][0]) J[4, 7] = 2 * (x[7] - data["TIEROD_INNER"][1]) J[4, 8] = 2 * (x[8] - data["TIEROD_INNER"][2]) # EQ5 (3 1) J[5, 0] = 2 * (x[0] - x[6]) J[5, 1] = 2 * (x[1] - x[7]) J[5, 2] = 2 * (x[2] - x[8]) J[5, 6] = -2 * (x[0] - x[6]) J[5, 7] = -2 * (x[1] - x[7]) J[5, 8] = -2 * (x[2] - x[8]) # EQ6 (3, 2) J[6, 3] = 2 * (x[3] - x[6]) J[6, 4] = 2 * (x[4] - x[7]) J[6, 5] = 2 * (x[5] - x[8]) J[6, 6] = -2 * (x[3] - x[6]) J[6, 7] = -2 * (x[4] - x[7]) J[6, 8] = -2 * (x[5] - x[8]) # EQ7 (2, 1) J[7, 0] = 2 * (x[0] - x[3]) J[7, 1] = 2 * (x[1] - x[4]) J[7, 2] = 2 * (x[2] - x[5]) J[7, 3] = -2 * (x[0] - x[3]) J[7, 4] = -2 * (x[1] - x[4]) J[7, 5] = -2 * (x[2] - x[5]) # EQ8 (4, 1) J[8, 0] = 2 * (x[0] - x[9]) J[8, 1] = 2 * (x[1] - x[10]) J[8, 2] = 2 * (x[2] - x[11]) J[8, 9] = -2 * (x[0] - x[9]) J[8, 10] = -2 * (x[1] - x[10]) J[8, 11] = -2 * (x[2] - x[11]) # EQ9 (4, 2) J[9, 3] = 2 * (x[3] - x[9]) J[9, 4] = 2 * (x[4] - x[10]) J[9, 5] = 2 * (x[5] - x[11]) J[9, 9] = -2 * (x[3] - x[9]) J[9, 10] = -2 * (x[4] - x[10]) J[9, 11] = -2 * (x[5] - x[11]) # EQ10 (4, 3) J[10, 6] = 2 * (x[6] - x[9]) J[10, 7] = 2 * (x[7] - x[10]) J[10, 8] = 2 * (x[8] - x[11]) J[10, 9] = -2 * (x[6] - x[9]) J[10, 10] = -2 * (x[7] - x[10]) J[10, 11] = -2 * (x[8] - x[11]) # EQ11 J[11, 11] = -1 return J def residual(vars, wheel_center_z): uca_outer, lca_outer, tierod_outer, wheel_center = vars[ 0:3], vars[3:6], vars[6:9], vars[9:12] diff = np.array([ uca_outer - data["UCA_FRONT"], uca_outer - data["UCA_REAR"], lca_outer - data["LCA_FRONT"], lca_outer - data["LCA_REAR"], tierod_outer - data["TIEROD_INNER"], tierod_outer - uca_outer, tierod_outer - lca_outer, lca_outer - uca_outer, wheel_center - uca_outer, wheel_center - lca_outer, wheel_center - tierod_outer, ]) F = np.linalg.norm(diff, axis=1)**2 - L_squared return np.append(F, np.array([-wheel_center[2] + wheel_center_z])) initial_guess = [data["uca_outer"], data["lca_outer"], data["tierod_outer"], data["wheel_center"]] solution_save = solve(wheel, index, initial_guess, residual, jacobian=jacobian) solution = { "UCA_FRONT": data["UCA_FRONT"], "UCA_REAR": data["UCA_REAR"], "LCA_FRONT": data["LCA_FRONT"], "LCA_REAR": data["LCA_REAR"], "TIEROD_INNER": data["TIEROD_INNER"], "uca_outer": solution_save[:, 0:3], "lca_outer": solution_save[:, 3:6], "tierod_outer": solution_save[:, 6:9], "wheel_center": solution_save[:, 9:12], "index_reference": index } wheel_variables = get_wheel(solution) if save_to_txt: saved_defined_geometry(data, os.path.join(result_folder_name, "input_geometry.suspgeo")) save_results_2_txt(wheel_variables, os.path.join(result_folder_name, "wheel_variables.suspvar")) return solution, wheel_variables
[docs] def double_whisbone_configuration_1(data, max_height_increase, max_height_decrease, height_step, save_to_txt=True, result_folder_name="results", path=None): """ Computes and solves the geometric constraints for a double wishbone suspension system. The function generates different wheel center heights based on input constraints, then calculates the residuals for a non-linear optimization problem to find the correct configuration of the suspension system. Parameters ---------- Data : dict A dictionary containing the initial measurements and reference points for the suspension system. Expected keys include: - 'wheel_center': The initial wheel center position. - 'uca_outer': The outer UCA (Upper Control Arm) position. - 'UCA_FRONT': The front reference point for the UCA. - 'UCA_REAR': The rear reference point for the UCA. - 'lca_outer': The outer LCA (Lower Control Arm) position. - 'LCA_FRONT': The front reference point for the LCA. - 'LCA_REAR': The rear reference point for the LCA. - 'tierod_outer': The outer tierod position. - 'TIEROD_INNER': The inner reference point for the tierod. max_height_increase : float Maximum increase in wheel center height for the analysis. max_height_decrease : float Maximum decrease in wheel center height for the analysis. height_step : float Step size for incrementing and decrementing the wheel center height. save_to_txt : bool, optional If True, the results will be saved to a text file. Default is True. Returns ------- solution : dict A dictionary with the optimized suspension parameters and their values: - 'UCA_FRONT': The front UCA position. - 'UCA_REAR': The rear UCA position. - 'LCA_FRONT': The front LCA position. - 'LCA_REAR': The rear LCA position. - 'TIEROD_INNER': The inner tierod position. - 'uca_outer': Optimized outer UCA positions. - 'lca_outer': Optimized outer LCA positions. - 'tierod_outer': Optimized outer tierod positions. - 'wheel_center': Optimized wheel center positions. - 'index_reference': Index reference for the wheel center heights. Notes ----- The function utilizes an optimization algorithm to solve for the configuration of the suspension system that satisfies the geometric constraints. The geometric model assumes a double wishbone suspension layout with specific reference points for each component. .. code-block:: # # /// # \-/ # UCA_REAR* # / # / # ----------- / # | | / # | | *----------*UCA_FRONT # | | uca_outer /⁻\ # | | /// # | | * U_SPRING_MOUNT # | wheel center / # | * | tierod_outer . # | | *-------------/------*TIEROD_INNER # | | . # | | / # | | lca_outer . # | | *-----------/-*LCA_REAR # | | \ . /⁻\ # ----------- \ / /// # \ . # \ * l_spring_mount # \ # *LCA_FRONT # /⁻\ # /// +-----------------+--------------------------+--------+ | Points Name | Description | Type | +=================+==========================+========+ | wheel center | Center of the Wheel | mobile | +-----------------+--------------------------+--------+ | UCA FRONT | Upper Control Arm Front | fixed | +-----------------+--------------------------+--------+ | UCA REAR | Upper Control Arm Rear | fixed | +-----------------+--------------------------+--------+ | uca outer | Upper Control Arm Outer | mobile | +-----------------+--------------------------+--------+ | LCA FRONT | Lower Control Arm Front | fixed | +-----------------+--------------------------+--------+ | LCA REAR | Lower Control Arm Rear | fixed | +-----------------+--------------------------+--------+ | lca outer | Lower Control Arm Outer | mobile | +-----------------+--------------------------+--------+ | TIEROD INNER | Inner Tie Rod | fixed | +-----------------+--------------------------+--------+ | tierod outer | Outer Tie Rod | mobile | +-----------------+--------------------------+--------+ | Spring/Damper | Supensión Superior | mobile | | Upper Mount | | | +-----------------+--------------------------+--------+ | Spring/Damper | Supensión Inferior | mobile | | Lower Mount | | | +-----------------+--------------------------+--------+ """ if path is None: path = os.getcwd() prepare_simulation(path, result_folder_name) logger_suspension_kinematics(data, max_height_increase, max_height_decrease, height_step, save_to_txt, result_folder_name, path) wheel, index = generate_wheel_center_heights( data["wheel_center"], max_height_increase, max_height_decrease, height_step) def get_L(): L = np.array([ data["uca_outer"] - data["UCA_FRONT"], data["uca_outer"] - data["UCA_REAR"], data["lca_outer"] - data["LCA_FRONT"], data["lca_outer"] - data["LCA_REAR"], data["tierod_outer"] - data["TIEROD_INNER"], data["tierod_outer"] - data["uca_outer"], data["tierod_outer"] - data["lca_outer"], data["lca_outer"] - data["uca_outer"], data["wheel_center"] - data["uca_outer"], data["wheel_center"] - data["lca_outer"], data["wheel_center"] - data["tierod_outer"], data["l_spring_mount"] - data["LCA_FRONT"], data["l_spring_mount"] - data["LCA_REAR"], data["l_spring_mount"] - data["lca_outer"], ]) return L L_squared = np.linalg.norm(get_L(), axis=1)**2 def residual(vars, wheel_center_z): uca_outer, lca_outer, tierod_outer, wheel_center, l_spring_mount = vars[ 0:3], vars[3:6], vars[6:9], vars[9:12], vars[12:15] diff = np.array([ uca_outer - data["UCA_FRONT"], uca_outer - data["UCA_REAR"], lca_outer - data["LCA_FRONT"], lca_outer - data["LCA_REAR"], tierod_outer - data["TIEROD_INNER"], tierod_outer - uca_outer, tierod_outer - lca_outer, lca_outer - uca_outer, wheel_center - uca_outer, wheel_center - lca_outer, wheel_center - tierod_outer, l_spring_mount - data["LCA_FRONT"], l_spring_mount - data["LCA_REAR"], l_spring_mount - lca_outer, ]) F = np.linalg.norm(diff, axis=1)**2 - L_squared return np.append(F, np.array([wheel_center[2] - wheel_center_z])) initial_guess = [data["uca_outer"], data["lca_outer"], data["tierod_outer"], data["wheel_center"], data["l_spring_mount"]] solution_save = solve(wheel, index, initial_guess, residual, jacobian=None) solution = { "UCA_FRONT": data["UCA_FRONT"], "UCA_REAR": data["UCA_REAR"], "LCA_FRONT": data["LCA_FRONT"], "LCA_REAR": data["LCA_REAR"], "TIEROD_INNER": data["TIEROD_INNER"], "U_SPRING_MOUNT": data["U_SPRING_MOUNT"], "uca_outer": solution_save[:, 0:3], "lca_outer": solution_save[:, 3:6], "tierod_outer": solution_save[:, 6:9], "wheel_center": solution_save[:, 9:12], "l_spring_mount": solution_save[:, 12:15], "index_reference": index } wheel_variables = get_wheel(solution) if save_to_txt: saved_defined_geometry(data, os.path.join(result_folder_name, "input_geometry.suspgeo")) save_results_2_txt(wheel_variables, os.path.join(result_folder_name, "wheel_variables.suspvar")) return solution, wheel_variables
[docs] def double_whisbone_configuration_2(data, max_height_increase, max_height_decrease, height_step, save_to_txt=True, result_folder_name="results", path=None): """ Computes and solves the geometric constraints for a double wishbone suspension system. The function generates different wheel center heights based on input constraints, then calculates the residuals for a non-linear optimization problem to find the correct configuration of the suspension system. Parameters ---------- data : dict A dictionary containing the initial measurements and reference points for the suspension system. Expected keys include: - 'wheel_center': The initial wheel center position. - 'uca_outer': The outer UCA (Upper Control Arm) position. - 'UCA_FRONT': The front reference point for the UCA. - 'UCA_REAR': The rear reference point for the UCA. - 'lca_outer': The outer LCA (Lower Control Arm) position. - 'LCA_FRONT': The front reference point for the LCA. - 'LCA_REAR': The rear reference point for the LCA. - 'tierod_outer': The outer tierod position. - 'TIEROD_INNER': The inner reference point for the tierod. - 'push_rod_outer': The outer push rod position. - 'push_rod_inner': The inner push rod position. - 'ROCKER_PIVOT': The rocker pivot position. - 'ROCKER_PIVOT_AXIS': The rocker pivot axis position. - 'l_spring_mount': The lower spring mount position. - 'U_SPRING_MOUNT': The upper spring mount position. max_height_increase : float Maximum increase in wheel center height for the analysis. max_height_decrease : float Maximum decrease in wheel center height for the analysis. height_step : float Step size for incrementing and decrementing the wheel center height. save_to_txt : bool, optional If True, the results will be saved to a text file. Default is True. result_folder_name : str, optional The name of the folder where results will be saved. Default is "results". path : str, optional The path where the results folder will be created. If None, the current working directory is used. Default is None. Returns ------- solution : dict A dictionary with the optimized suspension parameters and their values: - 'UCA_FRONT': The front UCA position. - 'UCA_REAR': The rear UCA position. - 'LCA_FRONT': The front LCA position. - 'LCA_REAR': The rear LCA position. - 'TIEROD_INNER': The inner tierod position. - 'uca_outer': Optimized outer UCA positions. - 'lca_outer': Optimized outer LCA positions. - 'tierod_outer': Optimized outer tierod positions. - 'wheel_center': Optimized wheel center positions. - 'push_rod_outer': Optimized outer push rod positions. - 'push_rod_inner': Optimized inner push rod positions. - 'l_spring_mount': Optimized lower spring mount positions. - 'index_reference': Index reference for the wheel center heights. Notes ----- The function utilizes an optimization algorithm to solve for the configuration of the suspension system that satisfies the geometric constraints. The geometric model assumes a double wishbone suspension layout with specific reference points for each component. .. code-block:: # l_spring_mount # *-\/\/\/\/\/\/\/\/\/\/\--* U_SPRING_MOUNT # /// /| /⁻\ # \-/ pushrod inner* | *ROCKER PIVOT AXIS /// # uca_rear* / \| / # / / *ROCKER PIVOT # / / /⁻\ # ----------- / pushrod outer* /// # | | / # | | *----------*uca_front # | | uca_outer /⁻\ # | | /// # | | # | wheel center # | * | tierod_outer # | | *--------------------*tierod_inner # | | # | | # | | lca_outer # | | *------------*lca_rear # ----------- \ /⁻\ # \ /// # \ # *lca_front # /⁻\ # /// +-----------------+--------------------------+--------+ | Points Name | Description | Type | +=================+==========================+========+ | wheel center | Center of the Wheel | mobile | +-----------------+--------------------------+--------+ | UCA FRONT | Upper Control Arm Front | fixed | +-----------------+--------------------------+--------+ | UCA REAR | Upper Control Arm Rear | fixed | +-----------------+--------------------------+--------+ | uca outer | Upper Control Arm Outer | mobile | +-----------------+--------------------------+--------+ | LCA FRONT | Lower Control Arm Front | fixed | +-----------------+--------------------------+--------+ | LCA REAR | Lower Control Arm Rear | fixed | +-----------------+--------------------------+--------+ | lca outer | Lower Control Arm Outer | mobile | +-----------------+--------------------------+--------+ | TIEROD INNER | Inner Tie Rod | fixed | +-----------------+--------------------------+--------+ | tierod outer | Outer Tie Rod | mobile | +-----------------+--------------------------+--------+ | pushrod outer | Pushrod Exterior | mobile | +-----------------+--------------------------+--------+ | pushrod inner | Pushrod Interior | mobile | +-----------------+--------------------------+--------+ | ROCKER PIVOT | Rocker pivot | fixed | +-----------------+--------------------------+--------+ | ROCKER PIVOT | Rocker pivot axis | fixed | | AXIS | | | +-----------------+--------------------------+--------+ | U SPRING MOUNT | Spring/damper | fixed | | | Upper Mount | | +-----------------+--------------------------+--------+ | l spring mount | Spring/Damper | mobile | | | Lower Mount | | +-----------------+--------------------------+--------+ """ if path is None: path = os.getcwd() prepare_simulation(path, result_folder_name) logger_suspension_kinematics(data, max_height_increase, max_height_decrease, height_step, save_to_txt, result_folder_name, path) wheel, index = generate_wheel_center_heights( data["wheel_center"], max_height_increase, max_height_decrease, height_step) def get_L(): L = np.array([ data["uca_outer"] - data["UCA_FRONT"], data["uca_outer"] - data["UCA_REAR"], data["lca_outer"] - data["LCA_FRONT"], data["lca_outer"] - data["LCA_REAR"], data["tierod_outer"] - data["TIEROD_INNER"], data["tierod_outer"] - data["uca_outer"], data["tierod_outer"] - data["lca_outer"], data["lca_outer"] - data["uca_outer"], data["wheel_center"] - data["uca_outer"], data["wheel_center"] - data["lca_outer"], data["wheel_center"] - data["tierod_outer"], data["push_rod_outer"] - data["UCA_FRONT"], data["push_rod_outer"] - data["UCA_REAR"], data["push_rod_outer"] - data["uca_outer"], data["push_rod_inner"] - data["push_rod_outer"], data["push_rod_inner"] - data["ROCKED_PIVOT"], data["push_rod_inner"] - data["ROCKED_PIVOT_AXIS"], data["l_spring_mount"] - data["UCA_FRONT"], data["l_spring_mount"] - data["ROCKED_PIVOT"], data["l_spring_mount"] - data["push_rod_inner"], ]) return L L_squared = np.linalg.norm(get_L(), axis=1)**2 def residual(vars, wheel_center_z): uca_outer = vars[0:3] lca_outer = vars[3:6] tierod_outer = vars[6:9] wheel_center = vars[9:12] push_rod_outer = vars[12:15] push_rod_inner = vars[15:18] l_spring_mount = vars[18:21] diff = np.array([ uca_outer - data["UCA_FRONT"], uca_outer - data["UCA_REAR"], lca_outer - data["LCA_FRONT"], lca_outer - data["LCA_REAR"], tierod_outer - data["TIEROD_INNER"], tierod_outer - uca_outer, tierod_outer - lca_outer, lca_outer - uca_outer, wheel_center - uca_outer, wheel_center - lca_outer, wheel_center - tierod_outer, push_rod_outer - data["UCA_FRONT"], push_rod_outer - data["UCA_REAR"], push_rod_outer - uca_outer, push_rod_inner - push_rod_outer, push_rod_inner - data["ROCKED_PIVOT"], push_rod_inner - data["ROCKED_PIVOT_AXIS"], l_spring_mount - data["UCA_FRONT"], l_spring_mount - data["ROCKED_PIVOT"], l_spring_mount - push_rod_inner, ]) F = np.linalg.norm(diff, axis=1)**2 - L_squared return np.append(F, np.array([-wheel_center[2] + wheel_center_z])) initial_guess = [data["uca_outer"], data["lca_outer"], data["tierod_outer"], data["wheel_center"], data["push_rod_outer"] , data["push_rod_inner"], data["l_spring_mount"]] solution_save = solve(wheel, index, initial_guess, residual, jacobian=None) solution = { "UCA_FRONT": data["UCA_FRONT"], "UCA_REAR": data["UCA_REAR"], "LCA_FRONT": data["LCA_FRONT"], "LCA_REAR": data["LCA_REAR"], "TIEROD_INNER": data["TIEROD_INNER"], "ROCKED_PIVOT": data["ROCKED_PIVOT"], "ROCKED_PIVOT_AXIS": data["ROCKED_PIVOT_AXIS"], "U_SPRING_MOUNT": data["U_SPRING_MOUNT"], "uca_outer": solution_save[:, 0:3], "lca_outer": solution_save[:, 3:6], "tierod_outer": solution_save[:, 6:9], "wheel_center": solution_save[:, 9:12], "push_rod_outer": solution_save[:, 12:15], "push_rod_inner": solution_save[:, 15:18], "l_spring_mount": solution_save[:, 18:21], "index_reference": index } wheel_variables = get_wheel(solution) if save_to_txt: saved_defined_geometry(data, os.path.join(result_folder_name, "input_geometry.suspgeo")) save_results_2_txt(wheel_variables, os.path.join(result_folder_name, "wheel_variables.suspvar")) return solution, wheel_variables