Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

satposition.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1999 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the MASH Research
00017  *      Group at the University of California Berkeley.
00018  * 4. Neither the name of the University nor of the Research Group may be
00019  *    used to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * Contributed by Tom Henderson, UCB Daedalus Research Group, June 1999
00035  * Modified to use period_ and offer isascending(), Lloyd Wood, March 2000. */
00036 
00037 #ifndef lint
00038 static const char rcsid[] =
00039     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/satellite/satposition.cc,v 1.8 2000/06/21 17:44:10 tomh Exp $";
00040 #endif
00041 
00042 #include "satposition.h"
00043 #include "satgeometry.h"
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include <math.h>
00047 
00048 static class TermSatPositionClass : public TclClass {
00049 public:
00050         TermSatPositionClass() : TclClass("Position/Sat/Term") {}
00051         TclObject* create(int argc, const char*const* argv) {
00052                 if (argc == 5) {
00053                         float a, b;
00054                         sscanf(argv[4], "%f %f", &a, &b);
00055                         return (new TermSatPosition(a, b));
00056                 } else
00057                         return (new TermSatPosition);
00058         }
00059 } class_term_sat_position;
00060 
00061 static class PolarSatPositionClass : public TclClass {
00062 public:
00063         PolarSatPositionClass() : TclClass("Position/Sat/Polar") {}
00064         TclObject* create(int argc, const char*const* argv) {
00065                 if (argc == 5) {
00066                         float a = 0, b = 0, c = 0, d = 0, e = 0;
00067                         sscanf(argv[4], "%f %f %f %f %f", &a, &b, &c, &d, &e);
00068                         return (new PolarSatPosition(a, b, c, d, e));
00069                 }
00070                 else {
00071                         return (new PolarSatPosition);
00072                 }
00073         }
00074 } class_polarsatposition;
00075 
00076 static class GeoSatPositionClass : public TclClass {
00077 public:
00078         GeoSatPositionClass() : TclClass("Position/Sat/Geo") {}
00079         TclObject* create(int argc, const char*const* argv) {
00080                 if (argc == 5) 
00081                         return (new GeoSatPosition(double(atof(argv[4]))));
00082                 else 
00083                         return (new GeoSatPosition);
00084         }
00085 } class_geosatposition;
00086 
00087 static class SatPositionClass : public TclClass {
00088 public:
00089         SatPositionClass() : TclClass("Position/Sat") {}
00090         TclObject* create(int, const char*const*) {
00091                         printf("Error:  do not instantiate Position/Sat\n");
00092                         return (0);
00093         }
00094 } class_satposition;
00095 
00096 double SatPosition::time_advance_ = 0;
00097 
00098 SatPosition::SatPosition() : node_(0)  
00099 {
00100         bind("time_advance_", &time_advance_);
00101 }
00102 
00103 int SatPosition::command(int argc, const char*const* argv) {     
00104         //Tcl& tcl = Tcl::instance();
00105         if (argc == 2) {
00106         }
00107         if (argc == 3) {
00108                 if(strcmp(argv[1], "setnode") == 0) {
00109                         node_ = (Node*) TclObject::lookup(argv[2]);
00110                         if (node_ == 0)
00111                                 return TCL_ERROR;
00112                         return TCL_OK;
00113                 }
00114         }
00115         return (TclObject::command(argc, argv));
00116 }
00117 
00119 // class TermSatPosition
00121 
00122 // Specify initial coordinates.  Default coordinates place the terminal
00123 // on the Earth's surface at 0 deg lat, 0 deg long.
00124 TermSatPosition::TermSatPosition(double Theta, double Phi)  {
00125         initial_.r = EARTH_RADIUS;
00126         period_ = EARTH_PERIOD; // seconds
00127         set(Theta, Phi);
00128         type_ = POSITION_SAT_TERM;
00129 }
00130 
00131 //
00132 // Convert user specified latitude and longitude to our spherical coordinates
00133 // Latitude is in the range (-90, 90) with neg. values -> south
00134 // Initial_.theta is stored from 0 to PI (spherical)
00135 // Longitude is in the range (-180, 180) with neg. values -> west
00136 // Initial_.phi is stored from 0 to 2*PI (spherical)
00137 //
00138 void TermSatPosition::set(double latitude, double longitude)
00139 {
00140         if (latitude < -90 || latitude > 90)
00141                 fprintf(stderr, "TermSatPosition:  latitude out of bounds %f\n",
00142                    latitude);
00143         if (longitude < -180 || longitude > 180)
00144                 fprintf(stderr, "TermSatPosition: longitude out of bounds %f\n",
00145                     longitude);
00146         initial_.theta = DEG_TO_RAD(90 - latitude);
00147         if (longitude < 0)
00148                 initial_.phi = DEG_TO_RAD(360 + longitude);
00149         else
00150                 initial_.phi = DEG_TO_RAD(longitude);
00151 }
00152 
00153 coordinate TermSatPosition::coord()
00154 {
00155         coordinate current;
00156 
00157         current.r = initial_.r;
00158         current.theta = initial_.theta;
00159         current.phi = fmod((initial_.phi + 
00160             (fmod(NOW + time_advance_,period_)/period_) * 2*PI), 2*PI);
00161 
00162 #ifdef POINT_TEST
00163         current = initial_; // debug option to stop earth's rotation
00164 #endif
00165         return current;
00166 }
00167 
00169 // class PolarSatPosition
00171 
00172 PolarSatPosition::PolarSatPosition(double altitude, double Inc, double Lon, 
00173     double Alpha, double Plane) : next_(0), plane_(0) {
00174         set(altitude, Lon, Alpha, Inc);
00175         bind("plane_", &plane_);
00176         if (Plane) 
00177                 plane_ = int(Plane);
00178         type_ = POSITION_SAT_POLAR;
00179 }
00180 
00181 //
00182 // Since it is easier to compute instantaneous orbit position based on a
00183 // coordinate system centered on the orbit itself, we keep initial coordinates
00184 // specified in terms of the satellite orbit, and convert to true spherical 
00185 // coordinates in coord().
00186 // Initial satellite position is specified as follows:
00187 // initial_.theta specifies initial angle with respect to "ascending node"
00188 // i.e., zero is at equator (ascending)-- this is the $alpha parameter in Otcl
00189 // initial_.phi specifies East longitude of "ascending node"  
00190 // -- this is the $lon parameter in OTcl
00191 // Note that with this system, only theta changes with time
00192 //
00193 void PolarSatPosition::set(double Altitude, double Lon, double Alpha, double Incl)
00194 {
00195         if (Altitude < 0) {
00196                 fprintf(stderr, "PolarSatPosition:  altitude out of \
00197                    bounds: %f\n", Altitude);
00198                 exit(1);
00199         }
00200         initial_.r = Altitude + EARTH_RADIUS; // Altitude in km above the earth
00201         if (Alpha < 0 || Alpha >= 360) {
00202                 fprintf(stderr, "PolarSatPosition:  alpha out of bounds: %f\n", 
00203                     Alpha);
00204                 exit(1);
00205         }
00206         initial_.theta = DEG_TO_RAD(Alpha);
00207         if (Lon < -180 || Lon > 180) {
00208                 fprintf(stderr, "PolarSatPosition:  lon out of bounds: %f\n", 
00209                     Lon);
00210                 exit(1);
00211         }
00212         if (Lon < 0)
00213                 initial_.phi = DEG_TO_RAD(360 + Lon);
00214         else
00215                 initial_.phi = DEG_TO_RAD(Lon);
00216         if (Incl < 0 || Incl > 180) {
00217                 // retrograde orbits = (90 < Inclination < 180)
00218                 fprintf(stderr, "PolarSatPosition:  inclination out of \
00219                     bounds: %f\n", Incl); 
00220                 exit(1);
00221         }
00222         inclination_ = DEG_TO_RAD(Incl);
00223         // XXX: can't use "num = pow(initial_.r,3)" here because of linux lib
00224         double num = initial_.r * initial_.r * initial_.r;
00225         period_ = 2 * PI * sqrt(num/MU); // seconds
00226 }
00227 
00228 
00229 //
00230 // The initial coordinate has the following properties:
00231 // theta: 0 < theta < 2 * PI (essentially, this specifies initial position)  
00232 // phi:  0 < phi < 2 * PI (longitude of ascending node)
00233 // Return a coordinate with the following properties (i.e. convert to a true
00234 // spherical coordinate):
00235 // theta:  0 < theta < PI
00236 // phi:  0 < phi < 2 * PI
00237 //
00238 coordinate PolarSatPosition::coord()
00239 {
00240         coordinate current;
00241         double partial;  // fraction of orbit period completed
00242         partial = 
00243             (fmod(NOW + time_advance_, period_)/period_) * 2*PI; //rad
00244         double theta_cur, phi_cur, theta_new, phi_new;
00245 
00246         // Compute current orbit-centric coordinates:
00247         // theta_cur adds effects of time (orbital rotation) to initial_.theta
00248         theta_cur = fmod(initial_.theta + partial, 2*PI);
00249         phi_cur = initial_.phi;
00250         // Reminder:  theta_cur and phi_cur are temporal translations of 
00251         // initial parameters and are NOT true spherical coordinates.
00252         //
00253         // Now generate actual spherical coordinates,
00254         // with 0 < theta_new < PI and 0 < phi_new < 360
00255 
00256         if (inclination_ < PI) {
00257                 // asin returns value between -PI/2 and PI/2, so 
00258                 // theta_new guaranteed to be between 0 and PI
00259                 theta_new = PI/2 - asin(sin(inclination_) * sin(theta_cur));
00260                 // if theta_new is between PI/2 and 3*PI/2, must correct
00261                 // for return value of atan()
00262                 if (theta_cur > PI/2 && theta_cur < 3*PI/2)
00263                         phi_new = atan(cos(inclination_) * tan(theta_cur)) + 
00264                             phi_cur + PI;
00265                 else
00266                         phi_new = atan(cos(inclination_) * tan(theta_cur)) + 
00267                             phi_cur;
00268                 phi_new = fmod(phi_new + 2*PI, 2*PI);
00269         } else 
00270                 printf("ERROR:  inclination_ > PI\n");
00271         
00272         current.r = initial_.r;
00273         current.theta = theta_new;
00274         current.phi = phi_new;
00275         return current;
00276 }
00277 
00278 
00279 //
00280 // added by Lloyd Wood, 27 March 2000.
00281 // allows us to distinguish between satellites that are ascending (heading north)
00282 // and descending (heading south).
00283 //
00284 bool PolarSatPosition::isascending()
00285 {       
00286         double partial = (fmod(NOW + time_advance_, period_)/period_) * 2*PI; //rad
00287         double theta_cur = fmod(initial_.theta + partial, 2*PI);
00288         if ((theta_cur > PI/2)&&(theta_cur < 3*PI/2)) {
00289                 return 0;
00290         } else {
00291                 return 1;
00292         }
00293 }
00294 
00295 int PolarSatPosition::command(int argc, const char*const* argv) {     
00296         Tcl& tcl = Tcl::instance();
00297         if (argc == 2) {
00298         }
00299         if (argc == 3) {
00300                 if (strcmp(argv[1], "set_next") == 0) {
00301                         next_ = (PolarSatPosition *) TclObject::lookup(argv[2]);
00302                         if (next_ == 0) {
00303                                 tcl.resultf("no such object %s", argv[2]);
00304                                 return (TCL_ERROR);
00305                         }
00306                         return (TCL_OK);
00307                 }
00308         }
00309         return (SatPosition::command(argc, argv));
00310 }
00311 
00313 // class GeoSatPosition
00315 
00316 GeoSatPosition::GeoSatPosition(double longitude) 
00317 {
00318         initial_.r = EARTH_RADIUS + GEO_ALTITUDE;
00319         initial_.theta = PI/2;
00320         set(longitude);
00321         type_ = POSITION_SAT_GEO;
00322         period_ = EARTH_PERIOD;
00323 }
00324 
00325 coordinate GeoSatPosition::coord()
00326 {
00327         coordinate current;
00328         current.r = initial_.r;
00329         current.theta = initial_.theta;
00330         double fractional = 
00331             (fmod(NOW + time_advance_, period_)/period_) *2*PI; // rad
00332         current.phi = fmod(initial_.phi + fractional, 2*PI);
00333         return current;
00334 }
00335 
00336 //
00337 // Longitude is in the range (0, 180) with negative values -> west
00338 //
00339 void GeoSatPosition::set(double longitude)
00340 {
00341         if (longitude < -180 || longitude > 180)
00342                 fprintf(stderr, "GeoSatPosition:  longitude out of bounds %f\n",
00343                     longitude);
00344         if (longitude < 0)
00345                 initial_.phi = DEG_TO_RAD(360 + longitude);
00346         else
00347                 initial_.phi = DEG_TO_RAD(longitude);
00348 }

Generated on Tue Apr 20 12:14:31 2004 for NS2.26SourcesOriginal by doxygen 1.3.3