Initialize Hayden project repository

This commit is contained in:
deamonkai
2026-03-28 11:22:16 -05:00
commit 595c63b934
11 changed files with 525 additions and 0 deletions

128
.gitignore vendored Normal file
View File

@@ -0,0 +1,128 @@
# ------------------------------
# OS
# ------------------------------
.DS_Store
.AppleDouble
.LSOverride
Icon?
._*
.Spotlight-V100
.Trashes
# ------------------------------
# Editor / IDE
# ------------------------------
.vscode/
!.vscode/extensions.json
!.vscode/settings.json
.idea/
*.iml
*.swp
*.swo
*~
# ------------------------------
# Environment / Secrets
# ------------------------------
.env
.env.*
!.env.example
!.env.sample
*.pem
*.p12
*.key
# ------------------------------
# Logs / Runtime
# ------------------------------
*.log
logs/
*.pid
*.pid.lock
*.seed
# ------------------------------
# Archives / Temp
# ------------------------------
*.tmp
*.temp
*.bak
*.orig
*.rej
*.zip
*.tar
*.gz
*.tgz
*.7z
# ------------------------------
# Dependency directories
# ------------------------------
node_modules/
vendor/
# ------------------------------
# Build outputs / caches
# ------------------------------
dist/
build/
out/
coverage/
.cache/
.tmp/
tmp/
# Python
__pycache__/
*.py[cod]
*.egg-info/
.venv/
venv/
.pytest_cache/
.mypy_cache/
.ruff_cache/
# JavaScript / TypeScript
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
.next/
.nuxt/
.svelte-kit/
.parcel-cache/
*.tsbuildinfo
# Java / Kotlin
.gradle/
.classpath
.project
.settings/
*.class
# Rust
/target/
# Go
bin/
*.test
# Terraform
.terraform/
*.tfstate
*.tfstate.*
.terraform.lock.hcl
# ------------------------------
# Testing artifacts
# ------------------------------
junit.xml
coverage.xml
htmlcov/
# ------------------------------
# Local database / sqlite
# ------------------------------
*.sqlite
*.sqlite3
*.db

75
MEMORY.md Normal file
View File

@@ -0,0 +1,75 @@
# MEMORY
This file is the durable handoff for AI agents working in this repository. Keep it short, factual, and current. If it ever drifts from the source docs or code, update this file to match the real source of truth.
## Working With the Operator
The operator has ADHD. This means:
They may squirrel down tangential paths — if the conversation drifts far from the task at hand, gently reframe by summarizing where we started, what we've done, and what's still open.
Periodic big-picture reviews help — when a session gets deep into details, proactively offer a summary of the larger context (current priorities, what's in-flight, what's blocked).
Keep TODO.md and this file updated — these are the external memory that bridges sessions. If something important is discussed but not captured, it's lost.
Be direct about scope creep — if a "quick fix" is turning into a multi-file refactor, flag it. Help them decide: do it now, or capture it and come back.
## Guardrails
- Treat `/docs` as authoritative for assignment requirements and parameter values.
- Do not invent missile or target thrust, mass, drag, or geometry tables. Transcribe them from the source packet and note what was extracted.
- Preserve SI units unless a document explicitly states otherwise.
- Keep [`code/Interceptor_3DOF.m`](./code/Interceptor_3DOF.m) as the primary entry point unless there is an intentional repo-wide refactor.
- Do not describe the model as runnable until all `XX` placeholders are replaced and `getRho.m` exists.
- Record every meaningful assumption, extracted constant, unresolved issue, and verification result here.
- Use exact dates in status notes.
- Do not store secrets, tokens, or personal data in this file.
## Current Snapshot
- Date: `2026-03-28`
- Project: MATLAB 3DOF interceptor-versus-target engagement assignment for AERO 3220 Spring 2026.
- Source docs reviewed:
- `docs/AERO 3220 3DOF Information Spring 26.pdf`
- `docs/Atmosphere Model SI Units.pdf`
- `docs/Missile and Target Data for 3DOF Spring 26.pdf`
- Assignment baseline confirmed from the handout:
- Velocity pursuit guidance gain = `0.5`
- Blind range = `2 m`
- Acquisition range = `5000 m`
- Lateral acceleration limit = `40 g`
- Velocity-pursuit guidance start delay = `0.5 s` after missile launch
- Terminal proportional-navigation gain = `4`
- Commit time = `50 s`
- Missile initial elevation angle = `40 deg`
- Required plots confirmed:
- Target/missile vertical-plane trajectories
- Target speed versus time
- Missile speed versus time
- Missile Mach number versus time
- Missile acceleration magnitude versus time since missile launch
## Code Status
- [`code/Interceptor_3DOF.m`](./code/Interceptor_3DOF.m) drives the integration loop, plotting, and CSV export.
- [`code/T3dxdt.m`](./code/T3dxdt.m), [`code/M3dxdt.m`](./code/M3dxdt.m), and [`code/getGuidance.m`](./code/getGuidance.m) still contain `XX` placeholders.
- `getRho.m` is referenced by the driver and both dynamics functions, but the file is missing.
- [`code/getMD.m`](./code/getMD.m) exists and computes miss distance at the point of closest approach.
- The missile/target data PDF appears image-based; a future agent should log the extraction method used when those tables are transcribed.
## Next Actions
1. Implement `getRho.m` from the atmosphere-model PDF.
2. Transcribe missile and target geometry, thrust, mass, and drag data from the missile/target packet.
3. Replace all remaining `XX` placeholders with sourced values.
4. Run the MATLAB model and verify the required plots and CSV outputs.
## Update Protocol For Agents
After any meaningful change, update:
- `Current Snapshot` if assumptions, sourced values, or operating context changed.
- `Code Status` if files were added, edited, or made runnable.
- `Next Actions` so the current critical path stays accurate.
- `Change Log` with a short dated note.
## Change Log
- `2026-03-28`: Created `README.md` and `MEMORY.md` from the `/docs` PDFs and current MATLAB code. Confirmed the repo is still an incomplete assignment skeleton with unresolved placeholders and a missing `getRho.m`.

53
README.md Normal file
View File

@@ -0,0 +1,53 @@
# Hayden Project
Hayden Project is a MATLAB 3DOF interceptor-versus-target engagement simulation repository for the AERO 3220 Spring 2026 coursework. The project is driven by the PDFs in [`docs/`](./docs) and implemented through the MATLAB files in [`code/`](./code).
## What The Docs Define
- [`docs/AERO 3220 3DOF Information Spring 26.pdf`](./docs/AERO%203220%203DOF%20Information%20Spring%2026.pdf) defines the assignment, required plots, and evaluation settings.
- [`docs/Atmosphere Model SI Units.pdf`](./docs/Atmosphere%20Model%20SI%20Units.pdf) provides the SI-unit atmosphere equations for temperature, pressure, density, acoustic speed, and Mach number.
- [`docs/Missile and Target Data for 3DOF Spring 26.pdf`](./docs/Missile%20and%20Target%20Data%20for%203DOF%20Spring%2026.pdf) is the source packet for the missile and target geometry, propulsion, and drag data that must be transcribed into the simulation.
## Assignment Baseline
The course handout specifies these evaluation values:
- Velocity pursuit guidance gain: `0.5`
- Blind range: `2 m`
- Acquisition range: `5000 m`
- Lateral acceleration limit: `40 g`
- Time after missile launch to initiate velocity-pursuit guidance: `0.5 s`
- Terminal proportional-navigation gain: `4`
- Commit time: `50 s`
- Missile initial elevation angle: `40 deg`
The required outputs are:
- Target and missile trajectories in the vertical plane (`x` vs `z`)
- Target speed versus time
- Missile speed versus time
- Missile Mach number versus time
- Missile acceleration magnitude versus time since missile launch
## Current Code State
- [`code/Interceptor_3DOF.m`](./code/Interceptor_3DOF.m) is the top-level driver script and writes `Ttrajectory.csv` and `Mtrajectory.csv`.
- [`code/T3dxdt.m`](./code/T3dxdt.m) and [`code/M3dxdt.m`](./code/M3dxdt.m) contain the target and interceptor dynamics models.
- [`code/getGuidance.m`](./code/getGuidance.m) holds the guidance-law logic.
- [`code/getMD.m`](./code/getMD.m) computes miss distance near the point of closest approach.
At the moment, the repository is a partially completed assignment skeleton rather than a finished simulation:
- Multiple required values are still marked as `XX`.
- `getRho.m` is referenced by the code but is not present in the repository.
- The missile/target data packet still needs to be fully transcribed into MATLAB arrays and constants.
## Working Expectations
- Keep units in SI unless a source document explicitly states otherwise.
- Treat `/docs` as the authoritative source for assignment requirements and parameter values.
- Record assumptions, extracted tables, unresolved issues, and verification status in [`MEMORY.md`](./MEMORY.md).
## For AI Agents
Read [`MEMORY.md`](./MEMORY.md) before making changes. Use it as the project's durable handoff for assumptions, sourced values, open work, and guardrails, and update it after any meaningful change so the next agent can continue without re-discovering context.

148
code/Interceptor_3DOF.m Normal file
View File

@@ -0,0 +1,148 @@
%% * Interceptor 3DOF*
%% Executive
clear all; clc;
t0 = 0; % Initial time. Target launch time.
tCommit = XX.; % Commit time (sec)
sigEl = 0; % Missile elevation angle standard deviation
maxTime = 150; % estimated maximum engagement time in sec
dt = 0.01; % integration interval (sec)
maxNum = maxTime/dt; % maximum number of steps in integration loop
simTime(1) = t0;
%% Target initial conditions
Tp0 = [75000; 0; 0 ];
Tspeed0 = 1.e-06;
QE = 63; LOF = -180; % Quadrant elevation and line-of-fire in degrees. LOF measured from x-axis.
Tv0 = Tspeed0*[cosd(QE)*cosd(LOF); cosd(QE)*sind(LOF); sind(QE)];%initial velocity vector in ENU frame
targetState = [Tp0; Tv0]; % initial target state vector (position & velocity) 6 states
Target_speed(1,:) = norm(targetState(4:6));
TxDot = T3dxdt(t0,targetState);
Toutput_vector(1,:)= [t0,targetState',TxDot(4:6)'];
%% Missile initial conditions
Mp0 = [0; 0; 0]; % Missile initial position in ENU frame (m)
Mspeed0 = 1.e-06;% Missile initial speed in ENU frame (m/sec); must be non-zero for unit vector calculation.
Maz = XX; Mel = XX; % Missile launch azimuth and elevation (deg).
Mv0 = Mspeed0*[cosd(Mel)*cosd(Maz); cosd(Mel)*sind(Maz); sind(Mel)];%initial velocity vector in ENU frame
missileState = [Mp0; Mv0]; % Missile state vector in ENU frame (m. and m/sec.)
Moutput_vector(1,:)= [t0,missileState', 0, 0, 0];
missileSpeed(1,:) = [t0,norm(missileState(4:6))];
Mmach(1) = 0.;
%% Trajectory Computation Loops
Tt = t0;
for ind = 2:maxNum
% Get Target State Vector
[Ttime,Tx]=ode45(@T3dxdt,[Tt Tt+dt],targetState);% x and time are values of xVector at t+dt
Tt = Ttime(end); % last element in the "time" vector
targetState = Tx(end,:); % last row in the "x" array. state at time(end).
TxDot = T3dxdt(Tt,targetState'); % find velocity and acceleration using dxdt; target xdot
Toutput_vector(ind, :)= [Tt,targetState,TxDot(4:6)'];% xDot(4:6) is acceleration
Target_speed(ind,:) = norm(targetState(4:6));
Trange = norm(targetState(1:3));
Mt = Tt-tCommit-dt; % Missile time. Clock starts at missile launch (tCommit).
Mmach(ind) = Mmach(1);
missileSpeed(ind,:) = missileSpeed(1,:);
Moutput_vector(ind, :)= Moutput_vector(1, :);
simTime(ind) = Tt; %Simulation time.
% Get Missile State Vector
if Mt >= 0
% [Mtime,Mx]=ode45(@(t,x)M3dxdt(t,x,targetState),[Mt Mt+dt], missileState);% x and time are values of xVector at t+dt
[Mtime,Mx]=ode45(@(Mt,x)M3dxdt(Mt,x,targetState),[Mt Mt+dt], missileState);% x and time are values of xVector at t+dt
Mt = Mtime(end); % last element in the "time" vector
missileState = Mx(end,:); % last row in the "x" array. state at time(end).
MxDot = M3dxdt(Mt,missileState',targetState); % find velocity and acceleration using dxdt; missile xdot
[acousticSpeed,rho] = getRho(missileState);
Mspeed = norm(missileState(4:6));
Mmach(ind) = Mspeed/acousticSpeed;
missileSpeed(ind,:) = [Tt,norm(missileState(4:6))];
missileAccel(ind,:) = [Mt,norm(MxDot(4:6))];
Moutput_vector(ind, :)= [Mt,missileState,MxDot(4:6)'];% xDot(4:6) is acceleration
% Compute Relative Data
relOutput(ind,:) = [Tt,targetState(1:3),missileState(1:3)];
Toutput(ind,:) = [Tt,targetState];
relState = targetState-missileState; % Relative state vector (target-missile).
relRange(ind) = norm(targetState(1:3)-missileState(1:3));
vClosing(ind) = dot(relState(4:6)',relState(1:3)/norm(relState(1:3))); % Closing speed
if relRange(ind)<10
dt = 0.0001;
end
% disp(relRange(ind));
if targetState(3)<=0 || vClosing(ind)>0
break
end
end
end
missDist = getMD(vClosing(1:ind),simTime(1:ind),relRange(1:ind));
disp(missDist);
%% Plot and write results
figure(6)
clf
axis equal;
grid on;
hold on;
title('Target and Missile Trajectories')
plot(Toutput_vector(:,2),Toutput_vector(:,4),'r','linewidth',2);
plot(Moutput_vector(:,2),Moutput_vector(:,4),'b','linewidth',2);
xlabel('Downrange (m)')
ylabel('Altitude (m)')
hold on;
grid on;
figure(2)
%axis equal;
grid on;
hold on;
xlim([0 90000]);
ylim([-5000 5000]);
zlim([0 12000]);
plot3(Toutput_vector(:,2),Toutput_vector(:,3),Toutput_vector(:,4),'r','linewidth',2);
plot3(Moutput_vector(:,2),Moutput_vector(:,3),Moutput_vector(:,4),'b','linewidth',2);
hold on;
grid on;
figure(3)
clf
grid on;
plot(missileAccel(:,1),missileAccel(:,2),'k','linewidth',2);
title('Missile Acceleration Magnitude')
xlabel('Time Since Missile Launch (sec)')
ylabel('Missile Acceleration (m/sec^2)')
grid on;
figure(4)
clf
grid on;
plot(missileSpeed(:,1),missileSpeed(:,2),'k','linewidth',2);
title('Missile Speed versus Time')
xlabel('Time Since Target Launch (sec)')
ylabel('Missile Speed (m/sec)')
grid on;
figure(5)
clf
grid on;
plot(simTime(:),vClosing(:),'k','linewidth',2);
title('Closing Speed versus Time')
xlabel('Time Since Target Launch (sec)')
ylabel('Closing Speed (m/sec)')
grid on;
figure(1)
clf
grid on;
plot(simTime(:),Target_speed(:),'k','linewidth',2);
title('Target Speed versus Time')
xlabel('Time (sec)')
ylabel('Target Speed (m/sec)')
grid on;
figure(7)
clf
grid on;
plot(simTime(:),Mmach(:),'k','linewidth',2);
title('Missile Mach Number versus Time')
xlabel('Time (sec)')
ylabel('Missile Mach Number')
grid on;
writematrix(Toutput_vector,'Ttrajectory.csv');
writematrix(Moutput_vector,'Mtrajectory.csv');

39
code/M3dxdt.m Normal file
View File

@@ -0,0 +1,39 @@
function MxDot = M3dxdt(Mt,missileState,targetState)
%% Missile is a 120 mm Rocket with an IR Seeker
% Compute Missile xDot = [velocity; acceleration]'
g = 9.8066; % acceleration due to gravity
gravity = [0; 0; -g]; % gravity vector
diameter = 0.120; % missile diameter in m.
S = XX; % reference area in m^2
[acousticSpeed,rho] = getRho(missileState);
Mspeed = norm(missileState(4:6));
mach = Mspeed/acousticSpeed;
timeCurve = [XX]'; %seconds
thrustCurve = [XX]'; % Newtons
massCurve = [XX]'; % kg
machCurve = [XX];
dragCurve = [XX];
machCurveB = [XX];
dragCurveB = [XX];
if(Mt<=timeCurve(end-1))
Cd = interp1(machCurveB,dragCurveB,mach,'linear','extrap');
else
Cd = interp1(machCurve,dragCurve,mach,'linear','extrap');
end
mass = interp1(timeCurve,massCurve,Mt,'linear','extrap');
thrust = interp1(timeCurve,thrustCurve,Mt,'linear','extrap');
%Compute acceleration --------------------------------------------
if Mspeed<=20
step = 0;
else
step = 1;
end
dragAccel = -0.5*rho*Cd*S*missileState(4:6)*norm(missileState(4:6))/mass;% drag acceleration in m/sec^2
thrustAccel = thrust*missileState(4:6)/(mass*(norm(missileState(4:6))));
guideAccel = getGuidance(Mt,missileState,targetState);
accel = dragAccel + thrustAccel + gravity*step + guideAccel; % total acceleration
MxDot = [missileState(4:6);accel];
end

34
code/T3dxdt.m Normal file
View File

@@ -0,0 +1,34 @@
function TxDot = T3dxdt(t,x)
%% Threat is a 240 mm Rocket
% Compute Rocket xDot = [velocity; acceleration]'
g = 9.8066; % acceleration due to gravity
gravity = [0; 0; -g]; % gravity vector
diameter = 0.24; % missile diameter in m.
S = XX; % reference area in m^2
[acousticSpeed,rho] = getRho(x);
mach = norm(x(4:6))/acousticSpeed;
timeCurve = [XX]'; %seconds
thrustCurve = [XX]'; % Newtons
massCurve = [XX]'; % kg
machCurve = [XX];
dragCurve = [XX];
machCurveB = [XX];
dragCurveB = [XX];
if(t<=timeCurve(end-1))
Cd = interp1(machCurveB,dragCurveB,mach,'linear','extrap');
else
Cd = interp1(machCurve,dragCurve,mach,'linear','extrap');
end
mass = interp1(timeCurve,massCurve,t,'linear','extrap');
thrust = interp1(timeCurve,thrustCurve,t,'linear','extrap');
%Compute acceleration --------------------------------------------
dragAccel = -0.5*rho*Cd*S*x(4:6)*norm(x(4:6))/mass;% drag acceleration in m/sec^2
thrustAccel = thrust*x(4:6)/(mass*(norm(x(4:6))));
accel = dragAccel + thrustAccel + gravity; % total acceleration
TxDot = [x(4:6);accel];
end

41
code/getGuidance.m Normal file
View File

@@ -0,0 +1,41 @@
function [guideAccel] = getGuidance(Mt,missileState,targetState)
% This function computes the acceleration command to the missile required to
% intercept a target
% Compute proportional navigation (PN) guidance command
PNGain = 0; % PN guidance gain
KVP = XX;
blindRng = XX; %Seeker blind range (m)
acqRng = XX; % Acquisition Range (m)
g = 9.8066; % Acceleration due to gravity (m/sec^2)
gLimit = XX.; % Lateral acceleration limit in gees
relState = targetState' - missileState;
relRng = relState(1:3);
relVel = relState(4:6);
mslVel = missileState(4:6);
% Velocity pursuit guidance
if Mt>XX
nHat = cross(mslVel,relRng);
accelCmdVP = KVP*cross(nHat,mslVel/norm(mslVel))/norm(relRng);
else
accelCmdVP = [0; 0; 0];
end
if norm(accelCmdVP)>gLimit*g
accelCmdVP = gLimit*g*accelCmdVP/norm(accelCmdVP);
end
% LOSR is line-of-sight rate
LOSR = cross(relRng,relVel)/dot(relRng,relRng);
if norm(relRng)<acqRng
PNGain = XX;
accelCmdVP = [0; 0; 0];
end
%accelCmd = -PNGain*norm(relVel)*cross(relRng/norm(relRng),LOSR);
accelCmd = -PNGain*norm(relVel)*cross(mslVel/norm(mslVel),LOSR);
if norm(accelCmd)>gLimit*g
accelCmd = gLimit*g*accelCmd/norm(accelCmd);
end
guideAccel = accelCmd + accelCmdVP;
disp(norm(accelCmdVP));
if norm(relRng)<blindRng
guideAccel = [0;0;0];
end
end

7
code/getMD.m Normal file
View File

@@ -0,0 +1,7 @@
function missDist = getMD(vClosing,simTime,relRange)
%Algorithm to compute PCA (point of closest approach).
delVc = vClosing(end)-vClosing(end-1);
delT = simTime(end)-simTime(end-1);
tMiss = -vClosing(end-1)*(delT/delVc);
missDist = abs(relRange(end-1)+vClosing(end-1)*tMiss);
end

Binary file not shown.

Binary file not shown.

Binary file not shown.