상담문의

[HEEDS] Heeds 를 이용한 현가장치의 parameter 최적화, 기능 소개

2026-07-23

 


1. 현가링크를 고려한 서스펜션과 이것을 단순화한 Reduced Order Model 


 자동차의 현가장치는 타이어, upper control arm, lower control arm, tie rod 등과 같이 복잡한 다물체로 구성되어 있습니다. 현가링크를 고려한 다물체 동역학 문제는 비선형성이 높은 미분방정식을 풀어야 하며, 일반적으로 대수 미분방정식 해법에 의해 풀이됩니다. 만약 현가링크를 무시한 저차의 선형미분방정식으로 같은 물리 모델을 정식화 할 수 있으면, 빠른 해석속도를 필요로 하는 HILS 에서 실시간 동역학해석이 가능하게 됩니다. 아래와 같이 비선형 미분방정식을 선형화하여 저차의 미분방정식으로 풀이하는 방법을 소개하며, 두 모델의 등가화를 위해 파라미터 스터디를 수행하는 과정을 설명하겠습니다. 


저차의 선형모델(A, B, C, D matrix)


2. 저차의 선형모델(A, B, C, D matrix 추출) 


저차의 선형모델의 경우 y'=f(x,y) 형태의 도함수가 정의됩니다. 따라서 ode45 와 같은 Runge Kutta 방법에 의한 미분방정식 풀이가 비교적 수월하게 수행됩니다. 이 형태의 미분방정식을 수치적으로 계산할 경우 파라미터 스터디를 반복하여 수행할 수 있으며, 최적의 파라미터를 도출하는데 유용하게 활용할 수 있습니다. 아래 그림은 적절히 변수추정을 하여 A, B, C, D matrix 를 추출하였으며, 이때의 계단응답을 그래프로 도시하였습니다. 변수추정은 수작업으로 진행했기 때문에 현가링크를 고려한 비선형 모델과 정확하게 일치하도록 추정하는 것은 불가능하였습니다




3. Simcenter Heeds 를 이용한 최적화 수행 


Simcenter Heeds 를 통해 변수추정을 수행할 경우, 먼저 input 과 output 변수를 정의 해야합니다. Input 은 design parameter 로 정의되며, 여기서는 현가장치의 스프링상수, 댐퍼, 타이어의 스프링 상수로 정의할 수 있습니다. Output 은 sprung mass 와 unsprung mass 의 변위로 정의 할 수 있으며, 사전에 정의된 커브와 어느정도 일치하는지를 목적함수로 셋팅하여 최적화를 수행합니다. Design parameter 를 정의하고 나서, reference value 로 현가링크를 고려한 비선형모델의 데이터를 가져옵니다.  이로써 최적화를 수행하면, design parameter를 최적화 하여 실시간 해석모델에 적합한 저차모델을 생성할 수 있습니다.

Simcenter Heeds 에서 정의한 design parameter

비선형모델의 변위를 reference value 로 사용

Sprung mass 변위의 최적화 

최적화 수행 후, 목적함수의 변화 추이 (0에 가까워질수록 error 가 감소함)

변수추정 최적화를 통해 얻은 최종 파라미터 (Ks, Cs, Kt)


4. 결 론 

Simcenter Heeds 를 통해 변수추정을 수행하였습니다. 변수추정을 수행하기 위해 input 및 output 파라미터를 정의하였으며, design parameter 로 현가장치의 스프링 상수와 댐핑 계수, 타이어의 스프링 상수를 정의하였습니다. 현가링크를 고려한 비선형모델의 데이터를 reference value 로 하여 그 정합성을 비교하였으며 최적의 파라미터를 추출할 수 있었습니다. 

<파이썬 코드>

import numpy as np
from scipy.integrate import odeint

# Define the parameters

ms = 240.0       # sprung mass (kg)

mu = 36.0        # unsprung mass (kg)

Kt = 160000.0    # tire stiffness (N/m)

Ks = 16000.0     # suspension stiffness (N/m)

Cs = 980.0       # damping coefficient (Ns/m)

t0 = 1.0         # road input start time (s)

g = 9.81         # gravity (m/s^2) - not used in original MATLAB equation

 

# Define the system of ODEs for 2-DOF quarter car vibration

# Z[0]: sprung mass displacement, zs

# Z[1]: sprung mass velocity, zs_dot

# Z[2]: unsprung mass displacement, zu

# Z[3]: unsprung mass velocity, zu_dot

def quarter_car_dynamics(Z, t, ms, mu, Kt, Ks, Cs, t0):

    zs, zs_dot, zu, zu_dot = Z

 

    # Road displacement input

    if t > t0:

        Zr = 0.01

        # Zr = 0.05 * np.sin(0.25 * t**2)

    else:

        Zr = 0.0

 

    # MATLAB equivalent:

    # A1 = Z(2)

    # A2 = -Ks*(Z(1)-Z(3)) - Cs*(Z(2)-Z(4))

    # A3 = Z(4)

    # A4 = Ks*(Z(1)-Z(3)) + Cs*(Z(2)-Z(4)) - Kt*(Z(3)-Zr)

 

    dzs_dt = zs_dot

    dzs_dot_dt = (-Ks * (zs - zu) - Cs * (zs_dot - zu_dot)) / ms

 

    dzu_dt = zu_dot

    dzu_dot_dt = (

        Ks * (zs - zu)

        + Cs * (zs_dot - zu_dot)

        - Kt * (zu - Zr)

    ) / mu

 

    return [dzs_dt, dzs_dot_dt, dzu_dt, dzu_dot_dt]

 

# Initial conditions

zs0 = 0.0       # initial sprung mass displacement (m)

zs_dot0 = 0.0   # initial sprung mass velocity (m/s)

zu0 = 0.0       # initial unsprung mass displacement (m)

zu_dot0 = 0.0   # initial unsprung mass velocity (m/s)

 

initial_conditions = [zs0, zs_dot0, zu0, zu_dot0]

 

# Time points

t = np.linspace(0, 4, 4000)  # simulate for 10 seconds with 201 points

 

# Solve the ODE

solution = odeint(

    quarter_car_dynamics,

    initial_conditions,

    t,

    args=(ms, mu, Kt, Ks, Cs, t0)

)

 

# Extract results from the solution

# Unit conversion

m_to_mm = 1000.0

 

# Extract results from the solution

sprung_displacement = solution[:, 0] * m_to_mm      # m -> mm

sprung_velocity = solution[:, 1] * m_to_mm          # m/s -> mm/s

unsprung_displacement = solution[:, 2] * m_to_mm    # m -> mm

unsprung_velocity = solution[:, 3] * m_to_mm        # m/s -> mm/s

 

output_filename = 'Output.txt'

 

try:

    with open(output_filename, 'w') as f:

        f.write(

            "Time (s)\t"

            "Sprung Displacement (m)\t"

            "Sprung Velocity (m/s)\t"

            "Unsprung Displacement (m)\t"

            "Unsprung Velocity (m/s)\t"

            "Road Input (m)\n"

        )

 

        for i in range(len(t)):

            time = t[i]

 

            if time > t0:

                road_input = 0.01

                # road_input = 0.05 * np.sin(0.25 * time**2)

            else:

                road_input = 0.0

 

            f.write(

                f"{time:.4f}\t"

                f"{sprung_displacement[i]:.6f}\t"

                f"{sprung_velocity[i]:.6f}\t"

                f"{unsprung_displacement[i]:.6f}\t"

                f"{unsprung_velocity[i]:.6f}\t"

                f"{road_input:.6f}"

            )

 

            if i < len(t) - 1:

                f.write("\n")

 

    print(f"Calculation results saved to {output_filename}")

 

except Exception as e:

    print(f"An error occurred while saving the file: {e}")


댓글 없음

댓글 쓰기

이런자료는 어때요?
캐디언스 시스템
(주) 캐디언스시스템

서울본사 : 서울시 금천구 가산디지털 1로 212, 코오롱디지털타워애스턴 1006호