# Getting Started with OOTK
Welcome to the Orbital Object Toolkit (OOTK)! This guide will help you get started with orbital mechanics programming, whether you're a beginner or an experienced developer new to this library.
---
## Table of Contents
1. [What is OOTK?](#what-is-ootk)
2. [Installation](#installation)
3. [Your First Satellite](#your-first-satellite)
4. [Understanding Coordinates](#understanding-coordinates)
5. [Working with Sensors](#working-with-sensors)
6. [Common Use Cases](#common-use-cases)
7. [Next Steps](#next-steps)
---
## What is OOTK?
OOTK (Orbital Object Toolkit) is a comprehensive library for orbital mechanics calculations in TypeScript/JavaScript. Think of it as your Swiss Army knife for:
- **Tracking satellites** from TLE data
- **Predicting satellite passes** over ground stations
- **Converting between coordinate systems** (latitude/longitude, ECI, ECF)
- **Calculating orbital parameters** (altitude, velocity, period)
- **Determining orbits from observations**
- **Planning orbital maneuvers**
### Who is this for?
- Web developers building satellite tracking applications
- Researchers doing orbital mechanics analysis
- Students learning astrodynamics
- Hobbyists interested in space and satellites
### What makes OOTK different?
- **Type-safe**: Uses TypeScript for catching errors at compile time
- **Unit types**: Prevents mixing degrees with radians, kilometers with meters
- **Browser-friendly**: Works in web browsers and Node.js
- **Comprehensive**: Everything from simple tracking to advanced orbit determination
---
## Installation
### Prerequisites
You'll need:
- **Node.js** (version 14 or higher)
- **npm** (comes with Node.js)
### Install OOTK
```bash
npm install ootk
```
### Verify Installation
Create a test file `test.js`:
```javascript
import { Earth } from 'ootk';
console.log('Earth radius:', Earth.radiusMean, 'km');
```
Run it:
```bash
node test.js
```
You should see: `Earth radius: 6371 km`
### TypeScript Setup (Optional but Recommended)
If using TypeScript:
```bash
npm install --save-dev typescript @types/node
```
Create `tsconfig.json`:
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true
}
}
```
---
## Your First Satellite
Let's track the International Space Station (ISS)!
### Step 1: Get TLE Data
TLE (Two-Line Element) sets describe a satellite's orbit. You can get them from:
-
-
-
Example ISS TLE:
```
ISS (ZARYA)
1 25544U 98067A 24028.54545847 .00031576 00000-0 57240-3 0 9991
2 25544 51.6418 292.2590 0002595 167.5319 252.0460 15.49326324436741
```
### Step 2: Create a Satellite Object
```typescript
import { Satellite, TleLine1, TleLine2 } from 'ootk';
// ISS TLE data
const tle1 = '1 25544U 98067A 24028.54545847 .00031576 00000-0 57240-3 0 9991' as TleLine1;
const tle2 = '2 25544 51.6418 292.2590 0002595 167.5319 252.0460 15.49326324436741' as TleLine2;
// Create satellite object
const iss = new Satellite({ tle1, tle2 });
console.log('ISS created successfully!');
```
### Step 3: Get Current Position
```typescript
// Get position now
const eci = iss.eci();
console.log('Position (ECI):');
console.log(' X:', eci.position.x, 'km');
console.log(' Y:', eci.position.y, 'km');
console.log(' Z:', eci.position.z, 'km');
console.log('Velocity (ECI):');
console.log(' X:', eci.velocity.x, 'km/s');
console.log(' Y:', eci.velocity.y, 'km/s');
console.log(' Z:', eci.velocity.z, 'km/s');
```
**Output Example:**
```
Position (ECI):
X: 3590.123 km
Y: -5234.789 km
Z: 2100.456 km
Velocity (ECI):
X: 4.567 km/s
Y: 3.210 km/s
Z: 5.432 km/s
```
### Step 4: Get Latitude/Longitude
```typescript
const lla = iss.lla();
console.log('Latitude:', lla.lat, '°');
console.log('Longitude:', lla.lon, '°');
console.log('Altitude:', lla.alt, 'km');
```
**Output Example:**
```
Latitude: 23.456 °
Longitude: -45.678 °
Altitude: 418.234 km
```
### Step 5: Get Orbital Parameters
```typescript
console.log('Orbital Parameters:');
console.log(' Inclination:', iss.inclination, '°');
console.log(' Eccentricity:', iss.eccentricity);
console.log(' Period:', iss.period, 'minutes');
console.log(' Apogee:', iss.apogee, 'km');
console.log(' Perigee:', iss.perigee, 'km');
```
**Congratulations!** You've just tracked your first satellite with OOTK!
---
## Understanding Coordinates
OOTK uses several coordinate systems. Here's a simple explanation:
### 1. Geodetic (Latitude/Longitude/Altitude)
**What**: The coordinates you're familiar with from maps.
**When to use**: Displaying positions on a map, human-readable locations.
```typescript
const lla = iss.lla();
// { lat: 23.456°, lon: -45.678°, alt: 418 km }
```
### 2. ECI (Earth-Centered Inertial)
**What**: X, Y, Z coordinates in a non-rotating reference frame.
**When to use**: Physics calculations, propagating orbits.
```typescript
const eci = iss.eci();
// { position: {x, y, z}, velocity: {x, y, z} }
```
### 3. ECF (Earth-Centered Fixed)
**What**: X, Y, Z coordinates that rotate with Earth.
**When to use**: Ground station calculations, terrain modeling.
```typescript
const ecf = iss.ecf();
// { position: {x, y, z}, velocity: {x, y, z} }
```
### Quick Conversions
```typescript
// Satellite gives you all of them:
const lla = satellite.lla(); // Geodetic
const eci = satellite.eci(); // ECI
const ecf = satellite.ecf(); // ECF
const j2000 = satellite.toJ2000(); // J2000 (specific ECI frame)
```
---
## Working with Sensors
A "sensor" in OOTK is a ground station or observation point that tracks satellites.
### Create a Sensor
Let's create a sensor for Cape Cod:
```typescript
import { Sensor, Degrees, Kilometers } from 'ootk';
const capeCod = new Sensor({
lat: 41.754785 as Degrees,
lon: -70.539151 as Degrees,
alt: 0.060966 as Kilometers,
minEl: 5 as Degrees, // Don't track below 5° elevation
maxEl: 85 as Degrees, // Don't track above 85°
minRng: 0 as Kilometers,
maxRng: 5000 as Kilometers // Maximum tracking range
});
```
**Note**: The `as Degrees` and `as Kilometers` are TypeScript type casts that ensure you're using the right units.
### Calculate Look Angles
Get Range, Azimuth, Elevation from sensor to satellite:
```typescript
const rae = capeCod.rae(iss);
console.log('Range:', rae.rng, 'km');
console.log('Azimuth:', rae.az, '° (0=North, 90=East)');
console.log('Elevation:', rae.el, '° (0=horizon, 90=zenith)');
console.log('Range Rate:', rae.rngRate, 'km/s');
```
**Interpretation**:
- **Range**: Distance to satellite
- **Azimuth**: Which direction to point (compass heading)
- **Elevation**: How high to look up
- **Range Rate**: How fast distance is changing (negative = approaching)
### Check Visibility
```typescript
const isVisible = capeCod.isSatInFov(iss);
if (isVisible) {
console.log('ISS is currently visible from Cape Cod!');
const rae = capeCod.rae(iss);
console.log('Look', rae.az.toFixed(1), '° at', rae.el.toFixed(1), '° elevation');
} else {
console.log('ISS is not visible right now.');
}
```
### Predict Passes
Find when satellite will be visible:
```typescript
// Calculate passes over next 24 hours, checking every 10 seconds
const passes = capeCod.calculatePasses(10, iss, {
startDate: new Date(),
lengthDays: 1
});
console.log(`Found ${passes.length} passes in the next 24 hours:`);
passes.forEach((pass, index) => {
console.log(`\nPass ${index + 1}:`);
console.log(' Rise:', pass.rise.toLocaleString());
console.log(' Peak:', pass.culmination.toLocaleString());
console.log(' Set:', pass.set.toLocaleString());
console.log(' Max Elevation:', pass.maxEl.toFixed(1), '°');
console.log(' Duration:', (pass.duration / 60).toFixed(1), 'minutes');
});
```
**Output Example**:
```
Found 3 passes in the next 24 hours:
Pass 1:
Rise: 1/28/2024, 6:23:45 PM
Peak: 1/28/2024, 6:28:12 PM
Set: 1/28/2024, 6:32:51 PM
Max Elevation: 45.3 °
Duration: 9.1 minutes
Pass 2:
Rise: 1/28/2024, 8:01:23 PM
Peak: 1/28/2024, 8:05:45 PM
Set: 1/28/2024, 8:10:12 PM
Max Elevation: 78.6 °
Duration: 8.8 minutes
...
```
---
## Common Use Cases
### 1. Real-Time Satellite Tracker
```typescript
import { Satellite, TleLine1, TleLine2 } from 'ootk';
class SatelliteTracker {
private satellite: Satellite;
constructor(tle1: TleLine1, tle2: TleLine2) {
this.satellite = new Satellite({ tle1, tle2 });
}
getCurrentPosition() {
const lla = this.satellite.lla();
return {
latitude: lla.lat,
longitude: lla.lon,
altitude: lla.alt
};
}
getVelocity() {
const eci = this.satellite.eci();
const speed = Math.sqrt(
eci.velocity.x ** 2 +
eci.velocity.y ** 2 +
eci.velocity.z ** 2
);
return speed; // km/s
}
}
// Usage
const tracker = new SatelliteTracker(tle1, tle2);
setInterval(() => {
const pos = tracker.getCurrentPosition();
const speed = tracker.getVelocity();
console.log(
`Lat: ${pos.latitude.toFixed(2)}°, ` +
`Lon: ${pos.longitude.toFixed(2)}°, ` +
`Alt: ${pos.altitude.toFixed(1)} km, ` +
`Speed: ${speed.toFixed(2)} km/s`
);
}, 1000); // Update every second
```
### 2. Ground Station Pass Predictor
```typescript
import { Sensor, Satellite, Degrees, Kilometers } from 'ootk';
function predictPasses(
sensorLat: number,
sensorLon: number,
sensorAlt: number,
tle1: TleLine1,
tle2: TleLine2,
days: number = 7
) {
const sensor = new Sensor({
lat: sensorLat as Degrees,
lon: sensorLon as Degrees,
alt: sensorAlt as Kilometers,
minEl: 10 as Degrees, // Only show passes above 10°
maxEl: 90 as Degrees,
minRng: 0 as Kilometers,
maxRng: 5000 as Kilometers
});
const satellite = new Satellite({ tle1, tle2 });
const passes = sensor.calculatePasses(30, satellite, {
startDate: new Date(),
lengthDays: days
});
return passes.map(pass => ({
riseTime: pass.rise,
setTime: pass.set,
peakTime: pass.culmination,
maxElevation: pass.maxEl,
durationMinutes: pass.duration / 60
}));
}
// Usage
const myPasses = predictPasses(
40.7128, // New York City latitude
-74.0060, // longitude
0.010, // altitude (km)
isstle1,
isstle2,
7 // next 7 days
);
console.log('Upcoming passes:', myPasses);
```
### 3. Multi-Satellite Tracker
```typescript
class MultiSatelliteTracker {
private satellites: Map = new Map();
addSatellite(name: string, tle1: TleLine1, tle2: TleLine2) {
this.satellites.set(name, new Satellite({ tle1, tle2 }));
}
getAllPositions() {
const positions = {};
this.satellites.forEach((sat, name) => {
const lla = sat.lla();
positions[name] = {
lat: lla.lat,
lon: lla.lon,
alt: lla.alt
};
});
return positions;
}
findVisible(sensorLat: number, sensorLon: number) {
const sensor = new Sensor({
lat: sensorLat as Degrees,
lon: sensorLon as Degrees,
alt: 0 as Kilometers,
minEl: 5 as Degrees,
maxEl: 85 as Degrees,
minRng: 0 as Kilometers,
maxRng: 5000 as Kilometers
});
const visible = [];
this.satellites.forEach((sat, name) => {
if (sensor.isSatInFov(sat)) {
const rae = sensor.rae(sat);
visible.push({
name,
azimuth: rae.az,
elevation: rae.el,
range: rae.rng
});
}
});
return visible;
}
}
// Usage
const tracker = new MultiSatelliteTracker();
tracker.addSatellite('ISS', isstle1, isstle2);
tracker.addSatellite('HUBBLE', hubbleTle1, hubbleTle2);
tracker.addSatellite('GPS-1', gpsTle1, gpsTle2);
// Get all positions
const allPositions = tracker.getAllPositions();
console.log(allPositions);
// Find what's visible from your location
const visibleSats = tracker.findVisible(40.7128, -74.0060);
console.log('Currently visible:', visibleSats);
```
### 4. Satellite Position at Specific Time
```typescript
import { Satellite, EpochUTC } from 'ootk';
const satellite = new Satellite({ tle1, tle2 });
// Position at a specific time
const specificDate = new Date('2024-12-31T00:00:00Z');
const eci = satellite.eci(specificDate);
const lla = satellite.lla(specificDate);
console.log('Position on New Year 2024:');
console.log(' Lat:', lla.lat, '°');
console.log(' Lon:', lla.lon, '°');
console.log(' Alt:', lla.alt, 'km');
```
### 5. Calculate Orbit Period
```typescript
function analyzeSatellite(tle1: TleLine1, tle2: TleLine2) {
const sat = new Satellite({ tle1, tle2 });
console.log('Orbital Analysis:');
console.log(' Period:', sat.period.toFixed(2), 'minutes');
console.log(' Apogee:', sat.apogee.toFixed(1), 'km');
console.log(' Perigee:', sat.perigee.toFixed(1), 'km');
console.log(' Inclination:', sat.inclination.toFixed(2), '°');
console.log(' Eccentricity:', sat.eccentricity.toFixed(6));
// Classify orbit
const avgAlt = (sat.apogee + sat.perigee) / 2;
let orbitType;
if (avgAlt < 2000) orbitType = 'LEO (Low Earth Orbit)';
else if (avgAlt < 35786) orbitType = 'MEO (Medium Earth Orbit)';
else if (Math.abs(avgAlt - 35786) < 100) orbitType = 'GEO (Geostationary)';
else orbitType = 'HEO (High Earth Orbit)';
console.log(' Classification:', orbitType);
// Orbits per day
const orbitsPerDay = (24 * 60) / sat.period;
console.log(' Orbits per day:', orbitsPerDay.toFixed(2));
}
analyzeSatellite(isstle1, isstle2);
```
---
## Next Steps
### Beginner Level
Now that you understand the basics:
1. **Try different satellites**: Get TLEs from
2. **Change sensor locations**: Track from your city
3. **Experiment with times**: Look at positions in the past or future
4. **Build a web interface**: Display positions on a map
### Intermediate Level
Ready for more? Explore:
1. **Different propagators**: Try `RungeKutta4Propagator` for higher accuracy
2. **Coordinate transformations**: Convert between J2000, TEME, ITRF
3. **Time systems**: Work with UTC, GPS time, Julian dates
4. **Force models**: Add gravity harmonics, drag, solar radiation pressure
See the [User Guide](./user-guide.md) sections:
- [Orbit Propagation](./user-guide.md#orbit-propagation)
- [Coordinate Systems](./user-guide.md#coordinate-systems)
- [Time Systems](./user-guide.md#time-systems)
### Advanced Level
For advanced orbital mechanics:
1. **Initial Orbit Determination**: Determine orbits from observations
2. **Maneuver Planning**: Calculate delta-v for orbit changes
3. **Covariance Propagation**: Track uncertainty in orbits
4. **Custom Propagators**: Create your own propagation methods
See the [User Guide](./user-guide.md) sections:
- [Initial Orbit Determination](./user-guide.md#initial-orbit-determination)
- [Maneuvers](./user-guide.md#maneuvers)
- [Force Models](./user-guide.md#force-models)
- [Advanced Topics](./user-guide.md#advanced-topics)
---
## Troubleshooting
### Common Issues
#### 1. "Cannot find module 'ootk'"
**Problem**: Import error
**Solution**: Make sure you've installed OOTK:
```bash
npm install ootk
```
And that your `package.json` has `"type": "module"` for ES modules.
#### 2. Type errors with numbers
**Problem**: TypeScript complains about number types
**Solution**: Cast to appropriate types:
```typescript
// Wrong
const lat = 41.7;
// Correct
const lat = 41.7 as Degrees;
```
#### 3. Satellite position seems wrong
**Problem**: Position doesn't match expected values
**Solutions**:
- Check TLE is current (TLEs expire quickly, especially for LEO)
- Verify the time (use `new Date()` for current time)
- Ensure TLE lines are correct (no extra spaces or truncation)
#### 4. No passes found
**Problem**: `calculatePasses()` returns empty array
**Solutions**:
- Increase `lengthDays` parameter (satellite may not pass for several days)
- Lower `minEl` on sensor (try 0 degrees)
- Increase `maxRng` on sensor
- Check satellite orbit (geostationary satellites don't "pass")
### Getting Help
- **Documentation**: See [User Guide](./user-guide.md)
- **Examples**: Check `/examples` folder in repository
- **Issues**:
- **Discussions**:
---
## Quick Reference
### Essential Imports
```typescript
// Basic tracking
import { Satellite, TleLine1, TleLine2 } from 'ootk';
// Sensors
import { Sensor, Degrees, Kilometers } from 'ootk';
// Advanced
import {
Satellite,
Sensor,
EpochUTC,
J2000,
ClassicalElements,
RungeKutta4Propagator,
ForceModel
} from 'ootk';
```
### Common Patterns
```typescript
// Create satellite
const sat = new Satellite({ tle1, tle2 });
// Get position now
const lla = sat.lla();
const eci = sat.eci();
// Get position at specific time
const date = new Date('2024-12-31T00:00:00Z');
const llaFuture = sat.lla(date);
// Create sensor
const sensor = new Sensor({
lat: latitude as Degrees,
lon: longitude as Degrees,
alt: altitude as Kilometers,
minEl: 5 as Degrees,
maxEl: 85 as Degrees,
minRng: 0 as Kilometers,
maxRng: 5000 as Kilometers
});
// Check visibility
const visible = sensor.isSatInFov(sat);
// Get look angles
const rae = sensor.rae(sat);
// Find passes
const passes = sensor.calculatePasses(30, sat, {
startDate: new Date(),
lengthDays: 7
});
```
---
## Example Projects to Build
### 1. ISS Notifier
Build a program that alerts you when the ISS will pass overhead.
**Skills**: Satellite tracking, pass prediction, notifications
### 2. Satellite Constellation Visualizer
Display multiple satellites on a map in real-time.
**Skills**: Multi-satellite tracking, web development, visualization
### 3. Ground Station Planner
Determine the best location for a ground station to maximize satellite contact time.
**Skills**: Sensor placement, pass analysis, optimization
### 4. Orbit Comparator
Compare different satellites' orbits and find close approaches.
**Skills**: Coordinate transformations, distance calculations
### 5. TLE Age Checker
Monitor a catalog of TLEs and alert when they're getting old.
**Skills**: TLE parsing, date handling, automation
---
## Resources
### Where to Get TLE Data
- **CelesTrak**: (free, no account needed)
- **Space-Track**: (free account required)
- **KeepTrack API**: (simple REST API)
### Learning More
- **Orbital Mechanics**: "Fundamentals of Astrodynamics" by Bate, Mueller, White
- **SGP4**: "Revisiting Spacetrack Report #3" by Vallado et al.
- **OOTK Repository**:
- **Full Documentation**: [User Guide](./user-guide.md)
### Related Projects
- **KeepTrack**:
- **satellite.js**: Alternative JavaScript satellite library
- **Skyfield**: Python satellite library
---
## Congratulations
You're now ready to start building with OOTK. Start simple with satellite tracking, then explore more advanced features as you need them.
**Happy coding!**
If you build something cool with OOTK, consider sharing it with the community!
---
**License**: AGPL-3.0
**Version**: 5.1.1
**Last Updated**: January 2024