📚 목차

Chapter 01

Monte Carlo 시뮬레이션이란?

Monte Carlo 시뮬레이션은 무작위 샘플링을 사용하여 복잡한 시스템의 확률적 결과를 예측하는 방법입니다. 이름은 도박으로 유명한 모나코의 Monte Carlo 카지노에서 유래했습니다.

🎲 핵심 아이디어

실제 세계에서는 모든 파라미터가 정확히 알려져 있지 않습니다. 추력, 항력계수, 발사각 등 모든 것에 불확실성이 있습니다. Monte Carlo는 이러한 불확실성을 가진 파라미터들을 무작위로 바꿔가며 시뮬레이션을 수천 번 반복하여, 가능한 결과의 분포를 얻습니다.

왜 Monte Carlo가 필요한가?

단일 시뮬레이션 Monte Carlo 시뮬레이션
고정된 파라미터 사용 확률적으로 변하는 파라미터
단일 결과값 결과의 분포 (평균, 표준편차)
"최대 고도는 250m" "최대 고도는 250±30m (95% 신뢰)"
최악/최선 시나리오 모름 극단적 결과 확률 계산 가능

Monte Carlo 시뮬레이션 흐름

1
불확실성 정의
각 파라미터의 불확실성 범위 설정 (예: 추력 ±15%)
2
파라미터 샘플링
확률 분포에서 무작위로 파라미터 값 추출
3
시뮬레이션 실행
샘플링된 파라미터로 전체 6DOF 시뮬레이션 수행
4
결과 기록
최대 고도, 최대 속도, 착지 위치 등 저장
5
반복 (N번)
1000번 이상 반복하여 통계적 유의성 확보
6
통계 분석
평균, 표준편차, 백분위수, 민감도 분석
Monte Carlo 메인 루프 MATLAB
N_MC = 1000;  % Monte Carlo 횟수

for i = 1:N_MC
    % 1. 파라미터 샘플링 (확률적)
    thrust_scale = 1.0 + (unc.thrust_3sig/3) * randn();
    Cd0 = nom.Cd0 * (1.0 + (unc.Cd0_3sig/3) * randn());
    
    % 2. 시뮬레이션 실행
    [apogee, max_speed, ...] = rocket_sim_core(thrust_scale, Cd0, ...);
    
    % 3. 결과 저장
    results.apogee(i) = apogee;
    results.max_speed(i) = max_speed;
end

% 4. 통계 분석
apogee_mean = mean(results.apogee);
apogee_std = std(results.apogee);
Chapter 02

불확실성 모델링

모든 물리적 파라미터에는 불확실성이 있습니다. 이를 3-sigma (3σ) 값으로 정의합니다.

3-Sigma 규칙

📊 정규분포와 3σ

정규분포에서:

  • 1σ 범위: 데이터의 68.3%가 포함
  • 2σ 범위: 데이터의 95.4%가 포함
  • 3σ 범위: 데이터의 99.7%가 포함

따라서 "추력 ±15% (3σ)"는 99.7%의 경우 추력이 공칭값의 85%~115% 사이라는 의미입니다.

\[ \text{표준편차} (\sigma) = \frac{\text{3σ 범위}}{3} \]

불확실성 파라미터

파라미터 공칭값 3σ 불확실성 설명
추력 스케일 1.0 ±15% 모터 성능 변동
항력계수 (Cd0) 0.224 ±20% 공력 불확실성
법선력 기울기 (CN_α) 12.0 ±15% 핀 효과 변동
발사각 86° ±2° 발사대 정렬 오차
질량 스케일 1.0 ±5% 제작 공차
풍속 0 0~3 m/s 균등분포
불확실성 정의 MATLAB
%% 불확실성 정의 (3-sigma 값)
unc.thrust_3sig = 0.15;       % 추력 ±15%
unc.Cd0_3sig = 0.20;          % Cd0 ±20%
unc.CN_alpha_3sig = 0.15;     % CN_alpha ±15%
unc.launch_angle_3sig = 2.0;  % 발사각 ±2°
unc.mass_3sig = 0.05;         % 질량 ±5%
unc.wind_max = 3.0;           % 최대 풍속 [m/s]

%% 공칭값
nom.Cd0 = 0.224;
nom.CN_alpha = 12.0;
nom.launch_angle = 86.0;
Chapter 03

확률 분포와 샘플링

불확실성을 모델링하기 위해 적절한 확률 분포를 선택하고 그로부터 무작위 값을 샘플링합니다.

정규분포 (Normal Distribution)

📈 가우시안 분포

대부분의 물리적 파라미터는 정규분포를 따릅니다. 평균(μ) 주변에 값이 집중되고, 멀어질수록 확률이 감소합니다.

\[ f(x) = \frac{1}{\sigma\sqrt{2\pi}} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) \]

MATLAB에서 정규분포 샘플링:

정규분포 샘플링 MATLAB
% randn()은 표준정규분포 (μ=0, σ=1)에서 샘플링
x = randn();  % -∞ ~ +∞ 범위의 값

% 원하는 분포로 변환: X = μ + σ * randn()
% 3σ 불확실성을 σ로 변환: σ = 3σ값 / 3

% 예: 추력 스케일 (공칭=1.0, 3σ=±15%)
sigma_thrust = unc.thrust_3sig / 3;  % 0.15/3 = 0.05
thrust_scale = 1.0 + sigma_thrust * randn();

% 예: Cd0 (공칭=0.224, 3σ=±20%)
Cd0 = nom.Cd0 * (1.0 + (unc.Cd0_3sig/3) * randn());

균등분포 (Uniform Distribution)

풍속이나 풍향처럼 특정 범위 내에서 모든 값이 동등하게 가능한 경우 사용합니다.

\[ f(x) = \begin{cases} \frac{1}{b-a} & a \leq x \leq b \\ 0 & \text{otherwise} \end{cases} \]
균등분포 샘플링 MATLAB
% rand()는 [0, 1) 범위의 균등분포

% 풍속: 0 ~ 3 m/s
wind_speed = unc.wind_max * rand();  % [0, 3)

% 풍향: 0 ~ 2π rad (모든 방향 동등)
wind_dir = 2*pi * rand();  % [0, 2π)

난수 시드 (Random Seed)

⚠️
재현 가능성

rng('shuffle')은 현재 시간을 기반으로 시드를 설정합니다. 결과를 재현하려면 rng(42)와 같이 고정 시드를 사용하세요.

난수 시드 설정 MATLAB
% 매번 다른 결과
rng('shuffle');

% 재현 가능한 결과
rng(42);  % 시드 = 42
Chapter 04

바람 모델

바람은 로켓 비행에 큰 영향을 미칩니다. 단순화된 일정 바람 모델을 사용합니다.

바람 벡터

💨 바람의 표현

바람은 풍속(speed)과 풍향(direction)으로 정의됩니다. NED 좌표계에서 바람 벡터:

\[ \vec{W}_I = \begin{bmatrix} W \cos(\theta_{wind}) \\ W \sin(\theta_{wind}) \\ 0 \end{bmatrix} \]

여기서:

상대 속도

공력은 공기에 대한 상대 속도에 의해 결정됩니다:

\[ \vec{V}_{rel} = \vec{V}_{body} - \vec{W}_{body} \]

바람을 Body frame으로 변환해야 합니다:

\[ \vec{W}_{body} = \mathbf{R}_{I \to B} \cdot \vec{W}_I \]
바람 모델 구현 MATLAB
% 바람 벡터 (관성계, NED)
wind_I = [wind_speed * cos(wind_dir); ...
          wind_speed * sin(wind_dir); ...
          0];

% Body frame으로 변환
wind_B = R_I2B * wind_I;

% 상대 속도 계산
V_rel = vel - wind_B;
V = norm(V_rel);

% 받음각 계산 (상대 속도 기준!)
alpha = atan2(V_rel(3), V_rel(1));
beta = atan2(V_rel(2), V_rel(1));
💡
바람의 영향

맞바람은 받음각을 증가시켜 항력을 높이고 고도를 낮춥니다. 측풍은 옆미끄럼각(β)을 만들어 착지점을 이동시킵니다.

Chapter 05

통계 분석

Monte Carlo 결과를 분석하여 시스템의 성능과 신뢰성을 평가합니다.

기본 통계량

📊 주요 통계량

  • 평균 (Mean, μ): 결과의 중심 경향
  • 표준편차 (Standard Deviation, σ): 결과의 퍼짐 정도
  • 범위 (Range): 최솟값 ~ 최댓값
  • 백분위수 (Percentile): 특정 비율 이하의 값
\[ \mu = \frac{1}{N} \sum_{i=1}^{N} x_i \]
\[ \sigma = \sqrt{\frac{1}{N-1} \sum_{i=1}^{N} (x_i - \mu)^2} \]
통계량 계산 MATLAB
% 기본 통계
apogee_mean = mean(results.apogee);
apogee_std = std(results.apogee);

fprintf('평균: %.1f m\n', apogee_mean);
fprintf('표준편차: %.1f m\n', apogee_std);
fprintf('범위: %.1f ~ %.1f m\n', min(results.apogee), max(results.apogee));

% 3σ 범위 (99.7% 신뢰구간)
fprintf('3σ 범위: %.1f ~ %.1f m\n', ...
        apogee_mean - 3*apogee_std, ...
        apogee_mean + 3*apogee_std);

% 특정 값 이상 확률
percentile_340 = sum(results.apogee >= 339.57) / N_MC * 100;
fprintf('339.57m 이상 확률: %.1f%%\n', percentile_340);

누적분포함수 (CDF)

CDF는 특정 값 이하일 확률을 보여줍니다:

\[ F(x) = P(X \leq x) = \frac{\text{x 이하인 샘플 수}}{N} \]
CDF 플롯 MATLAB
% 경험적 CDF 계산
[f, x] = ecdf(results.apogee);

% 플롯
plot(x, f*100, 'b-', 'LineWidth', 2);
xlabel('최대 고도 [m]');
ylabel('누적 확률 [%]');
title('최대 고도 CDF');

히스토그램

결과의 분포를 시각화합니다:

히스토그램 플롯 MATLAB
histogram(results.apogee, 30, ...
          'FaceColor', [0.3 0.6 0.9], ...
          'EdgeColor', 'w');
hold on;

% 평균선
xline(apogee_mean, 'r-', 'LineWidth', 2);

% ±3σ 범위
xline(apogee_mean - 3*apogee_std, 'r--');
xline(apogee_mean + 3*apogee_std, 'r--');

% 비교값
xline(249, 'g-', 'OpenRocket');
xline(339.57, 'm-', '실측');
Chapter 06

민감도 분석

민감도 분석은 어떤 파라미터가 결과에 가장 큰 영향을 미치는지 파악하는 과정입니다.

상관계수 (Correlation Coefficient)

📈 피어슨 상관계수

두 변수 사이의 선형 관계 강도를 -1에서 +1 사이로 나타냅니다.

  • +1: 완벽한 양의 상관 (같이 증가)
  • 0: 상관 없음
  • -1: 완벽한 음의 상관 (반대로 변화)
\[ r_{xy} = \frac{\sum_{i=1}^{N}(x_i - \bar{x})(y_i - \bar{y})} {\sqrt{\sum_{i=1}^{N}(x_i - \bar{x})^2} \sqrt{\sum_{i=1}^{N}(y_i - \bar{y})^2}} \]
민감도 분석 MATLAB
param_names = {'추력', 'Cd0', 'CN_alpha', '발사각', '질량', '풍속'};
param_data = [params.thrust_scale, params.Cd0, params.CN_alpha, ...
              params.launch_angle, params.mass_scale, params.wind_speed];

correlations = zeros(6, 1);
for i = 1:6
    r = corrcoef(param_data(:,i), results.apogee);
    correlations(i) = r(1,2);
    fprintf('  %s: %.3f\n', param_names{i}, correlations(i));
end

% 막대 그래프로 시각화
barh(correlations);
set(gca, 'YTickLabel', param_names);
xlabel('상관계수');
title('민감도 분석');

결과 해석 예시

파라미터 상관계수 해석
추력 +0.85 추력↑ → 고도↑ (강한 양의 상관)
Cd0 (항력계수) -0.72 항력↑ → 고도↓ (강한 음의 상관)
질량 -0.45 질량↑ → 고도↓ (중간 음의 상관)
발사각 +0.15 약한 영향
풍속 -0.08 거의 영향 없음
💡
민감도 분석 활용

민감도가 높은 파라미터 (|r| > 0.5)에 집중하세요:

  • 제조 공차를 줄이거나
  • 더 정확한 측정을 수행하거나
  • 설계를 변경하여 민감도를 낮추세요
Chapter 07

MEX 컴파일과 가속

Monte Carlo 시뮬레이션은 수천 번의 반복이 필요하므로 속도가 중요합니다. MEX (MATLAB Executable)로 컴파일하면 C/C++ 수준의 속도를 얻을 수 있습니다.

⚡ MEX란?

MEX는 MATLAB 코드를 컴파일하여 바이너리 실행 파일로 변환한 것입니다. 인터프리터 오버헤드가 없어 10~100배 빠릅니다.

MATLAB vs MEX 비교

특성 MATLAB MEX
실행 방식 인터프리터 네이티브 코드
속도 기준 (1x) 10~100x 빠름
디버깅 쉬움 어려움
개발 시간 빠름 컴파일 필요
파일 확장자 .m .mexw64 (Windows)

MATLAB Coder

MATLAB Coder는 MATLAB 코드를 C/C++ 코드로 자동 변환하는 도구입니다.

1
MATLAB 코드 작성
rocket_sim_core.m
2
Coder 호환성 확보
%#codegen 프래그마 추가
3
codegen 명령 실행
codegen rocket_sim_core -args {...}
4
MEX 파일 생성
rocket_sim_core_mex.mexw64
Chapter 08

MATLAB Coder 사용법

1단계: 코드 준비

MEX 컴파일을 위해 코드가 몇 가지 규칙을 따라야 합니다:

✅ Coder 호환성 요구사항

  • 동적 메모리 할당 제한 (배열 크기 미리 알려야 함)
  • 일부 MATLAB 함수 사용 불가 (eval, assignin 등)
  • 셀 배열, 구조체 필드 동적 접근 제한
  • %#codegen 프래그마로 호환성 검사
Coder 호환 함수 선언 MATLAB
function [apogee, max_speed, ...] = rocket_sim_core(thrust_scale, ...)
%#codegen  % ← 이 주석이 Coder 호환성 검사 활성화

% Coder 호환: 배열 크기 명시적 초기화
pos = zeros(3, 1);
vel = zeros(3, 1);
quat = zeros(4, 1);

% int32로 타입 명시
N_steps = int32(floor(t_end / dt)) + 1;

2단계: 빌드 스크립트

MEX 빌드 스크립트 MATLAB
%% 입력 타입 정의 (샘플 값)
thrust_scale = 1.0;
Cd0 = 0.15;
CN_alpha = 12.0;
launch_angle = 86.0;
mass_scale = 1.0;
wind_speed = 0.0;
wind_dir = 0.0;
Q_force = 1.0;
Q_moment = 0.01;
dt = 0.002;
t_end = 20.0;

%% codegen 설정
cfg = coder.config('mex');
cfg.GenerateReport = true;      % HTML 리포트 생성
cfg.ReportPotentialDifferences = false;

% 최적화 설정
cfg.SaturateOnIntegerOverflow = false;  % 오버플로 체크 해제
cfg.IntegrityChecks = false;             % 범위 체크 해제
cfg.ResponsivenessChecks = false;        % 응답성 체크 해제

%% 컴파일
input_args = {thrust_scale, Cd0, CN_alpha, launch_angle, mass_scale, ...
              wind_speed, wind_dir, Q_force, Q_moment, dt, t_end};

codegen('rocket_sim_core', '-config', cfg, '-args', input_args);

3단계: 사용

MEX 파일 사용 MATLAB
% MEX 버전 호출 (함수명에 _mex 접미사)
[apogee, time, speed, mach, impact, dx, dy] = ...
    rocket_sim_core_mex(1.0, 0.15, 12.0, 86.0, 1.0, ...
                        0.0, 0.0, 1.0, 0.01, 0.002, 20.0);

% MATLAB 버전과 동일한 인터페이스!
⚠️
주의사항

MEX 파일은 컴파일된 플랫폼에서만 실행됩니다. Windows에서 컴파일한 .mexw64는 Mac/Linux에서 사용할 수 없습니다.

Chapter 09

코드 최적화 기법

MEX 외에도 MATLAB 코드 자체를 최적화할 수 있습니다.

1. 배열 사전 할당

배열 사전 할당 MATLAB
% ❌ 나쁜 예: 루프에서 배열 크기 증가
for i = 1:N
    results(i) = compute(i);  % 매번 메모리 재할당!
end

% ✅ 좋은 예: 미리 할당
results = zeros(N, 1);  % 한 번만 할당
for i = 1:N
    results(i) = compute(i);
end

2. 벡터화

벡터화 연산 MATLAB
% ❌ 나쁜 예: for 루프
for i = 1:N
    y(i) = x(i)^2 + 2*x(i) + 1;
end

% ✅ 좋은 예: 벡터화 (훨씬 빠름)
y = x.^2 + 2*x + 1;

3. Coder 호환 보간 함수

interp1은 Coder에서 제한이 있어 직접 구현합니다:

Coder 호환 선형 보간 MATLAB
function yi = interp1_coder(x, y, xi)
    % 선형 보간 (Coder 호환)
    n = length(x);
    
    % 경계 처리
    if xi <= x(1)
        yi = y(1);
        return;
    end
    if xi >= x(n)
        yi = y(n);
        return;
    end
    
    % 구간 찾기
    idx = 1;
    for k = 1:n-1
        if xi >= x(k) && xi < x(k+1)
            idx = k;
            break;
        end
    end
    
    % 선형 보간
    t = (xi - x(idx)) / (x(idx+1) - x(idx));
    yi = y(idx) + t * (y(idx+1) - y(idx));
end

4. Coder 호환 대기 모델

atmosisa 대신 직접 구현합니다:

ISA 대기 모델 MATLAB
function [rho, a] = atmos_isa(alt)
    % ISA 대기 모델 (Coder 호환)
    T0 = 288.15;      % 해수면 온도 [K]
    P0 = 101325;      % 해수면 압력 [Pa]
    L = 0.0065;       % 기온 감률 [K/m]
    R = 287.058;      % 기체 상수 [J/(kg·K)]
    g = 9.81;         % 중력 [m/s²]
    gamma = 1.4;      % 비열비
    
    T = T0 - L * alt;
    P = P0 * (T / T0)^(g / (R * L));
    rho = P / (R * T);
    a = sqrt(gamma * R * T);
end
Chapter 10

결과 해석

Monte Carlo 결과를 실측 데이터와 비교하여 모델의 정확성을 평가합니다.

실측값 매칭 분석

실측값(339.57m)과 가장 가까운 Monte Carlo 케이스를 찾아 어떤 조건이 필요한지 분석합니다:

최적 매칭 케이스 찾기 MATLAB
target_apogee = 339.57;

% 가장 가까운 케이스 찾기
[~, best_idx] = min(abs(results.apogee - target_apogee));

% 시그마 편차 계산
thrust_sigma = (params.thrust_scale(best_idx) - 1.0) / (unc.thrust_3sig/3);
Cd0_sigma = (params.Cd0(best_idx) - nom.Cd0) / (nom.Cd0 * unc.Cd0_3sig/3);

fprintf('추력 스케일: %.3f (%+.2fσ)\n', params.thrust_scale(best_idx), thrust_sigma);
fprintf('Cd0: %.4f (%+.2fσ)\n', params.Cd0(best_idx), Cd0_sigma);

해석 예시

🔍 분석 결과

실측값 339.57m에 도달하려면:

  • 추력: 공칭값보다 +1.5σ (약 7.5% 높음)
  • 항력계수: 공칭값보다 -1.8σ (약 12% 낮음)
  • 질량: 공칭값보다 -0.5σ (약 2.5% 가벼움)

이는 공칭 모델이 보수적(항력 과대, 추력 과소 추정)임을 시사합니다.

📊
결론

Monte Carlo 시뮬레이션은 단순히 "최대 고도는 Xm"가 아니라 "최대 고도는 X±Ym (95% 신뢰도)"와 같은 확률적 예측을 가능하게 합니다. 이는 안전성 분석과 설계 최적화에 필수적입니다.

📥 코드 다운로드

Monte Carlo 시뮬레이션과 MEX 빌드에 필요한 모든 파일을 다운로드하세요.

Summary

핵심 요약

🎲 Monte Carlo 핵심

  1. 불확실성을 3σ 값으로 정의
  2. 정규분포/균등분포에서 파라미터 샘플링
  3. 1000회 이상 시뮬레이션 반복
  4. 결과의 평균, 표준편차, 분포 분석
  5. 민감도 분석으로 핵심 파라미터 식별

⚡ MEX 가속 핵심

  • %#codegen 프래그마로 호환성 확보
  • 배열 크기 명시적 선언
  • Coder 비호환 함수 직접 구현
  • codegen으로 MEX 파일 생성
  • 10~50배 속도 향상 달성

📊 핵심 수식

  • 샘플링: \(x = \mu + \sigma \cdot \text{randn()}\)
  • 상관계수: \(r = \frac{\text{Cov}(X,Y)}{\sigma_X \sigma_Y}\)
  • 상대속도: \(\vec{V}_{rel} = \vec{V}_{body} - \vec{W}_{body}\)