Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Satellites #21

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
23 changes: 23 additions & 0 deletions examples/satellite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

include __DIR__ . '/../vendor/autoload.php';

use Andrmoel\AstronomyBundle\Events\SolarEclipse\SolarEclipse;
use Andrmoel\AstronomyBundle\Location;
use Andrmoel\AstronomyBundle\TimeOfInterest;

date_default_timezone_set('UTC');

$string = <<<END
ISS 109. 73.0 27.5 -2.0 v 402
1 25544U 98067A 19155.51091253 .00000344 00000-0 13620-4 0 9994
2 25544 51.6453 64.2093 0007540 13.2790 173.5287 15.51165870173281
END;

$TLEParser = \Andrmoel\AstronomyBundle\Parsers\ParserFactory::get(\Andrmoel\AstronomyBundle\Parsers\TLEParser::class, $string);
$tle = $TLEParser->getParsedData();

$T = TimeOfInterest::createFromString('2019-06-04 00:00:00')->getJulianCenturiesFromJ2000();
$kep = \Andrmoel\AstronomyBundle\Calculations\SatelliteCalc::twoLineElements2keplerianElements($tle, $T);

var_dump($kep);die();
83 changes: 83 additions & 0 deletions src/AstronomicalObjects/Satellite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace Andrmoel\AstronomyBundle\AstronomicalObjects;

class Satellite extends AstronomicalObject
{
/** @var string two line element */
private $tle = '';

// Satellite data
private $satelliteNo = 0;
private $classification = 0;
private $internationalId = 0;
private $revolutionNoAtEpoch = 0;

// Epoch of TLE data set
private $epoch = 0;

// Kepler parameters
private $inclination = 0;
private $raan = 0; // Right ascension of ascending node
private $eccentricity = 0;
private $aop = 0; // Argument of perigee
private $meanAnomaly = 0;
private $meanMotion = 0;

public function __construct($tle)
{
parent::__construct();

$this->tle = $tle;
$this->parseTLE();
}


/**
* Parse two line element
*/
private function parseTLE()
{
$valid = array(
1 => false, // Validate line 1
2 => false, // Validate line 2
);

$lines = explode("\n", $this->tle);
$lines = str_replace("\r", '', $lines);
foreach ($lines as $line) {
if (strlen($line) == 69) {
$lineNo = substr($line, 0, 1);
var_dump($lineNo); //TODO
switch ($lineNo) {
case '1':
$this->satelliteNo = trim(substr($line, 2, 5));
$this->classification = substr($line, 7, 1);
$this->internationalId = trim(substr($line, 9, 7));
$this->epoch = new TimeOfInterest();
$this->epoch->setTleEpoch(substr($line, 18, 14));

var_dump($this->epoch->getTimeString());
die();
$ftdmm = substr($line, 33, 9); //TODO
// TODO
$valid[1] = true;
break;
case '2':
$this->satelliteNo = trim(substr($line, 2, 5));
$this->inclination = doubleval(substr($line, 8, 8));
$this->raan = doubleval(substr($line, 17, 8));
$this->eccentricity = doubleval('0.' . substr($line, 26, 7));
$this->aop = doubleval(substr($line, 34, 8));
$this->meanAnomaly = doubleval(substr($line, 43, 8));
$this->meanMotion = doubleval(substr($line, 52, 11));
$this->revolutionNoAtEpoch = intval(substr($line, 63, 5));
$valid[2] = true;
break;
default:
break;
}
}
}
}
}
166 changes: 166 additions & 0 deletions src/Calculations/SatelliteCalc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<?php

namespace Andrmoel\AstronomyBundle\Calculations;

use Andrmoel\AstronomyBundle\AstronomicalObjects\Planets\Earth;
use Andrmoel\AstronomyBundle\Constants;
use Andrmoel\AstronomyBundle\Entities\TwoLineElements;
use Andrmoel\AstronomyBundle\Utils\AngleUtil;
use Andrmoel\AstronomyBundle\Utils\GeneralUtil;

class SatelliteCalc
{
public static function twoLineElements2keplerianElements(TwoLineElements $tle, float $T): array
{
$T0 = $tle->getEpoch()->getJulianCenturiesFromJ2000();
$M0 = $tle->getMeanAnomaly();
$n = $tle->getMeanMotion();
$d1mm = $tle->get1thDerivativeOfMeanMotion();
$d2mm = $tle->get2ndDerivativeOfMeanMotion();
$e = $tle->getEccentricity();

$dT = $T - $T0;

$M = self::getMeanAnomaly($tle, $dT);

$a = self::getSemiMajorAxis($tle, $dT);

var_dump($a);
die();

$E = self::getEccentricAnomaly($M0, $e);


var_dump("ECCC", $E);
die();
// TODO ...
return [];
}

private static function getMeanAnomaly(TwoLineElements $tle, float $dT): float
{
$M0 = $tle->getMeanAnomaly();
$n = $tle->getMeanMotion();
$d1mm = $tle->get1thDerivativeOfMeanMotion();
$d2mm = $tle->get2ndDerivativeOfMeanMotion();

$M = $M0
+ $n * $dT
+ $d1mm * pow($dT, 2)
+ $d2mm * pow($dT, 3);

return $M;
}

public static function getTrueAnomaly(TwoLineElements $tle): float
{
$e = $tle->getEccentricity();
$E = self::getEccentricAnomaly($tle);

$ERad = deg2rad($E);

$ThetaRad = 2 * atan(
sqrt((1 + $e) / (1 - $e)) * tan($ERad / 2)
);

$Theta = rad2deg($ThetaRad);

return $Theta;
}

public static function getEccentricAnomaly(TwoLineElements $tle): float
{
$M = $tle->getMeanAnomaly();
$e = $tle->getEccentricity();
$MRad = deg2rad($M);

$Ei = $M + 0.85 * $e * GeneralUtil::sign(sin($MRad));

do {
$EiRad = deg2rad($Ei);

$Ej = $Ei - ($Ei - $e * sin($EiRad) - $M) / (1 - $e * cos($EiRad));
$Ei = $Ej;
} while (abs($Ei - $Ej) > 1e-8);

$Ei = AngleUtil::normalizeAngle($Ei);

return $Ei;
}

private static function getSemiMajorAxis(TwoLineElements $tle, float $dT): float
{
$n = $tle->getMeanMotion();
$nRad = deg2rad($n);
$d1mm = $tle->get1thDerivativeOfMeanMotion();
$d2mm = $tle->get2ndDerivativeOfMeanMotion();

$mu0 = sqrt(Constants::GRAVITATIONAL_PARAMETER);

$a0 = pow($mu0 / $n, 2 / 3);

var_dump($a1);die();

$a = pow($GM, 1 / 3) / pow((2 * $n * pi()) / 86400, 2 / 3);

return $a;
}

public static function getRightAscensionOfAscendingNode(TwoLineElements $tle, float $dT): float
{
$iRad = deg2rad($i);

$dOmega = -9.9641 * pow(Earth::RADIUS / $a, 3.5) * (cos($iRad) / (pow(1 - pow($e, 2), 2)));
$Omega = $Omega0 + $dOmega * $dT;

return $Omega;
}

public static function getArgumentOfPerigee(TwoLineElements $tle, float $dT): float
{
$iRad = deg2rad($i);

$dOmega = 4.98 * pow(Earth::RADIUS / $a, 3.5) * ((5 * pow(cos($iRad), 2) - 1) / pow(1 - pow($e, 2), 2));
$omega = $omega0 + $dOmega * $dT;

return $omega;
}

public static function getPerifocalCoordinateSystem(TwoLineElements $tle): array
{
$TRad = deg2rad($trueAnomaly);

$k = ($a * (1 - pow($e, 2))) / (1 + $e * cos($TRad));

$x = $k * cos($TRad);
$y = $k * sin($TRad);
$z = 0;

return [$x, $y, $z];
}

public static function fofo(): array
{
$x0 = 0;
$y0 = 0;

$aopRad = deg2rad($aop);
$raanRad = deg2rad($raan);
$iRad = deg2rad($i);

// Rotation matrix
$Px = cos($aopRad) * cos($raanRad) - sin($aopRad) * sin($raanRad) * cos($iRad);
$Py = cos($aopRad) * sin($raanRad) + sin($aopRad) * cos($raanRad) * cos($iRad);
$Pz = sin($aopRad) * sin($iRad);

$Qx = -sin($aopRad) * cos($raanRad) - cos($aopRad) * sin($raanRad) * cos($iRad);
$Qy = -sin($aopRad) * sin($raanRad) + cos($aopRad) * cos($raanRad) * cos($iRad);
$Qz = cos($aopRad) * sin($iRad);

$x = $Px * $x0 + $Qx * $y0;
$y = $Py * $x0 + $Qy * $y0;
$z = $Pz * $x0 + $Qz * $y0;

return [$x, $y, $z];
}
}
1 change: 1 addition & 0 deletions src/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ class Constants
// 299792.458 km/s
public const LIGHT_SPEED_AU = 17314463348.4; // Speed of light in 10^-8 AU/day
public const CONSTANT_OF_ABERRATION = 0.0056932; // degrees
public const GRAVITATIONAL_PARAMETER = 3.986005e14;
}
13 changes: 13 additions & 0 deletions src/Entities/KeplerianElements.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Andrmoel\AstronomyBundle\Entities;

class KeplerianElements
{
private $eccentricity = 0.0;
private $semimajorAxis = 0.0;
private $inclination = 0.0;
private $longitudeOfAscNode = 0.0;
private $argumentOfPeriapsis = 0.0;
private $trueAnomaly = 0.0;
}
74 changes: 74 additions & 0 deletions src/Entities/TwoLineElements.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Andrmoel\AstronomyBundle\Entities;

use Andrmoel\AstronomyBundle\TimeOfInterest;

class TwoLineElements
{
const EPHEMERIS_TYPE_SGP4 = 0;
const EPHEMERIS_TYPE_SGP = 1;
// const EPHEMERIS_TYPE_SGP4 = 2;
const EPHEMERIS_TYPE_SDP4 = 3;
const EPHEMERIS_TYPE_SGP8 = 4;
const EPHEMERIS_TYPE_SDP8 = 5;

private $satelliteNo = '';
private $classification = '';
private $internationalDesignator = '';
private $epoch = null;
private $d1MeanMotion = 0.0;
private $d2MeanMotion = 0.0;
private $BSTARDragTerm = 0.0;
private $ephemerisType = '';
private $setNumber = 0;
private $inclination = 0.0;
private $rightAscensionOfAscendingNode = 0.0;
private $eccentricity = 0.0;
private $argumentOfPerigee = 0.0;
private $meanAnomaly = 0.0;
private $meanMotion = 0.0;
private $revolutionNoAtEpoch = 0;

public function __construct(array $tleData)
{
foreach ($tleData as $var => $value) {
$this->$var = $value;
}
}

public static function createFromTLEData(array $tleData)
{

}

public function getEpoch(): TimeOfInterest
{
return $this->epoch;
}

public function get1thDerivativeOfMeanMotion(): float
{
return $this->d1MeanMotion;
}

public function get2ndDerivativeOfMeanMotion(): float
{
return $this->d2MeanMotion;
}

public function getEccentricity(): float
{
return $this->eccentricity;
}

public function getMeanAnomaly(): float
{
return $this->meanAnomaly;
}

public function getMeanMotion(): float
{
return $this->meanMotion;
}
}
Loading