diff --git a/model/leo-circular-orbit-mobility-model.cc b/model/leo-circular-orbit-mobility-model.cc new file mode 100644 index 0000000..06da884 --- /dev/null +++ b/model/leo-circular-orbit-mobility-model.cc @@ -0,0 +1,181 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include "math.h" + +#include "ns3/double.h" +#include "ns3/simulator.h" + +#include "leo-circular-orbit-mobility-model.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("LeoCircularOrbitMobilityModel"); + +NS_OBJECT_ENSURE_REGISTERED (LeoCircularOrbitMobilityModel); + +TypeId +LeoCircularOrbitMobilityModel::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::LeoCircularOrbitMobilityModel") + .SetParent () + .SetGroupName ("Leo") + .AddAttribute ("Altitude", + "A height from the earth's surface in meters", + DoubleValue (1000.0), + MakeDoubleAccessor (&LeoCircularOrbitMobilityModel::SetAltitude, + &LeoCircularOrbitMobilityModel::GetAltitude), + MakeDoubleChecker ()) + .AddAttribute ("Inclination", + "The inclination of the orbital plane in degrees", + DoubleValue (10.0), + MakeDoubleAccessor (&LeoCircularOrbitMobilityModel::SetInclination, + &LeoCircularOrbitMobilityModel::GetInclination), + MakeDoubleChecker ()) + .AddAttribute ("Latitude", + "The latitude at which the orital plane intersects the equatorial plane in degrees", + DoubleValue (10.0), + MakeDoubleAccessor (&LeoCircularOrbitMobilityModel::SetLatitude, + &LeoCircularOrbitMobilityModel::GetLatitude), + MakeDoubleChecker ()) + .AddAttribute ("Offset", + "The relative offset of the satellite along the orbital plane from the equatorial plane in degrees", + DoubleValue (0.0), + MakeDoubleAccessor (&LeoCircularOrbitMobilityModel::SetOffset, + &LeoCircularOrbitMobilityModel::GetOffset), + MakeDoubleChecker ()) + ; + return tid; +} + +LeoCircularOrbitMobilityModel::LeoCircularOrbitMobilityModel() : MobilityModel () +{ + NS_LOG_FUNCTION_NOARGS (); +} + +LeoCircularOrbitMobilityModel::~LeoCircularOrbitMobilityModel() +{ +} + +Vector3D +CrossProduct (const Vector3D &l, const Vector3D &r) +{ + return Vector3D (l.y * r.z - l.z * r.y, + l.z * r.x - l.x * r.z, + l.x * r.y - l.y * r.x); +} + +Vector3D +Product (const double &l, const Vector3D &r) +{ + return Vector3D (l * r.x, + l * r.y, + l * r.z); +} + +double +DotProduct (const Vector3D &l, const Vector3D &r) +{ + return (l.x* r.x) + (l.y*r.y) + (l.z*r.z); +} + +double +LeoCircularOrbitMobilityModel::GetSpeed () const +{ + return sqrt (LEO_EARTH_GM / m_orbitHeight); +} + +Vector +LeoCircularOrbitMobilityModel::DoGetVelocity () const +{ + Vector3D heading = CrossProduct (PlaneNorm (), DoGetPosition ()); + // TODO + return Product (GetSpeed (), heading); +} + +Vector3D +LeoCircularOrbitMobilityModel::PlaneNorm () const +{ + return Vector3D (sin (-m_inclination) * cos (m_latitude), + sin (-m_inclination) * sin (m_latitude), + cos (m_inclination)); +} + +double +LeoCircularOrbitMobilityModel::GetProgress (Time t) const +{ + // TODO use nanos or ms instead? does it give higher precision? + return 2 * M_PI * ((GetSpeed () * t.GetSeconds ()) / LEO_EARTH_RAD_M); +} + +Vector3D +LeoCircularOrbitMobilityModel::RotatePlane (double a, const Vector3D &x) const +{ + Vector3D n = PlaneNorm (); + + // TODO optimize? + return Product (DotProduct (n, x), n) + + Product (cos (a), CrossProduct (CrossProduct (n, x), n)) + + Product (sin (a), CrossProduct (n, x)); +} + +Vector +LeoCircularOrbitMobilityModel::DoGetPosition (void) const +{ + Vector3D x = Product (m_orbitHeight, Vector3D (cos (m_inclination) * cos (m_latitude), + cos (m_inclination) * sin (m_latitude), + sin (m_inclination))); + + return RotatePlane (GetProgress (Simulator::Now ()), x); +} + +void +LeoCircularOrbitMobilityModel::DoSetPosition (const Vector &position) +{ + NS_ASSERT_MSG (false, "Can not set position of satellite on circular orbit"); +} + +double LeoCircularOrbitMobilityModel::GetAltitude () const +{ + return m_orbitHeight - LEO_EARTH_RAD_M; +} + +void LeoCircularOrbitMobilityModel::SetAltitude (double h) +{ + m_orbitHeight = LEO_EARTH_RAD_M + h; + m_plane = PlaneNorm (); +} + +double LeoCircularOrbitMobilityModel::GetLatitude () const +{ + return m_latitude / M_PI * 180.0; +} + +void LeoCircularOrbitMobilityModel::SetLatitude (double lat) +{ + m_latitude = lat / 180 * M_PI; + m_plane = PlaneNorm (); +} + +double LeoCircularOrbitMobilityModel::GetOffset () const +{ + return (m_offset / M_PI) * 180; +} + +void LeoCircularOrbitMobilityModel::SetOffset (double off) +{ + m_offset = (off / 180) * M_PI; +} + +double LeoCircularOrbitMobilityModel::GetInclination () const +{ + return (m_inclination / M_PI) * 180.0; +} + +void LeoCircularOrbitMobilityModel::SetInclination (double incl) +{ + NS_ASSERT_MSG (incl != 0.0, "Plane must not be orthogonal to axis"); + m_inclination = (incl / 180) * M_PI; + m_plane = PlaneNorm (); +} + +}; diff --git a/model/leo-circular-orbit-mobility-model.h b/model/leo-circular-orbit-mobility-model.h new file mode 100644 index 0000000..95b6fd2 --- /dev/null +++ b/model/leo-circular-orbit-mobility-model.h @@ -0,0 +1,107 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#ifndef LEO_CIRCULAR_ORBIT_MOBILITY_MODEL_H +#define LEO_CIRCULAR_ORBIT_MOBILITY_MODEL_H + +#include "ns3/vector.h" +#include "ns3/object.h" +#include "ns3/log.h" +#include "ns3/mobility-model.h" +#include "ns3/nstime.h" + +#define LEO_EARTH_RAD_M 6371009.0 +#define LEO_EARTH_GM 3.98600436e14 + +namespace ns3 { + +/** + * \ingroup leo + * \brief Keep track of the orbital postion and velocity of a satellite. + * + * This uses simple circular orbits based on the inclination of the orbital + * plane and the height of the satellite. + */ +class LeoCircularOrbitMobilityModel : public MobilityModel +{ +public: + /** + * Register this type with the TypeId system. + * \return the object TypeId + */ + static TypeId GetTypeId (void); + LeoCircularOrbitMobilityModel (); + virtual ~LeoCircularOrbitMobilityModel (); + + /** + * km/s + */ + double GetSpeed () const; + + double GetAltitude () const; + void SetAltitude (double h); + + double GetLatitude () const; + void SetLatitude (double lat); + + double GetOffset () const; + void SetOffset (double off); + + double GetInclination () const; + void SetInclination (double incl); + +private: + + /** + * Orbit height in m + */ + double m_orbitHeight; + + /** + * Inclination in rad + */ + double m_inclination; + + /** + * Latitude in rad + */ + double m_latitude; + + /** + * Offset on the orbital plane in rad + */ + double m_offset; + + /** + * Normal vector of orbital plane. + */ + Vector3D m_plane; + + /** + * \return the current position. + */ + virtual Vector DoGetPosition (void) const; + /** + * \param position the position to set. + */ + virtual void DoSetPosition (const Vector &position); + /** + * \return the current velocity. + */ + virtual Vector DoGetVelocity (void) const; + + /** + * Get the normal vector of the orbital plane + */ + Vector3D PlaneNorm () const; + + double GetProgress (Time t) const; + + /** + * Advances a satellite by a degrees on the orbital plane + */ + Vector3D RotatePlane (double a, const Vector3D &x) const; +}; + +} + +#endif diff --git a/test/leo-orbit-test-suite.cc b/test/leo-orbit-test-suite.cc new file mode 100644 index 0000000..4ac017e --- /dev/null +++ b/test/leo-orbit-test-suite.cc @@ -0,0 +1,35 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include "ns3/core-module.h" +#include "ns3/node-container.h" +#include "ns3/test.h" + +#include "../model/leo-circular-orbit-mobility-model.h" + +using namespace ns3; + +class LeoOrbitSpeedTestCase : public TestCase +{ +public: + LeoOrbitSpeedTestCase () : TestCase ("Test speed for 0 altitude") {} + virtual ~LeoOrbitSpeedTestCase () {} + +private: + virtual void DoRun (void) + { + Ptr mob = CreateObject (); + mob->SetAttribute ("Altitude", DoubleValue (0.0)); + + NS_TEST_ASSERT_MSG_EQ ((uint64_t) mob->GetSpeed (), (uint64_t) 7909.79, "Unexpected velocity at earths surface"); + } +}; + +class LeoOrbitTestSuite : TestSuite +{ +public: + LeoOrbitTestSuite() : TestSuite ("leo-orbit", UNIT) { + AddTestCase (new LeoOrbitSpeedTestCase, TestCase::QUICK); + } +}; + +static LeoOrbitTestSuite leoOrbitTestSuite; diff --git a/wscript b/wscript index 6bb79a4..25f239f 100644 --- a/wscript +++ b/wscript @@ -16,6 +16,7 @@ def build(bld): 'helper/ground-node-helper.cc', 'helper/satellite-node-helper.cc', 'model/leo.cc', + 'model/leo-circular-orbit-mobility-model.cc', 'model/leo-mock-channel.cc', 'model/leo-mock-net-device.cc', 'model/leo-propagation-loss-model.cc', @@ -33,6 +34,7 @@ def build(bld): 'test/isl-propagation-test-suite.cc', 'test/isl-test-suite.cc', 'test/leo-anim-test-suite.cc', + 'test/leo-orbit-test-suite.cc', 'test/leo-input-fstream-container-test-suite.cc', 'test/leo-mobility-test-suite.cc', 'test/leo-mock-channel-test-suite.cc', @@ -52,6 +54,7 @@ def build(bld): 'helper/ground-node-helper.h', 'helper/satellite-node-helper.h', 'model/leo.h', + 'model/leo-circular-orbit-mobility-model.h', 'model/leo-mock-channel.h', 'model/leo-mock-net-device.h', 'model/leo-oneweb-constants.h',