How do you fly the solar sail?

vonneuman

Orbinaut
Joined
Nov 8, 2009
Messages
254
Reaction score
1
Points
0
Location
Missouri S&T
I was attempting to fly the solar sail that comes with 2010 but I can't turn it. There is nothing in the Orbiter manual about how to fly it. It doesn't rotate or anything like that. Can someone help me?
 

Izack

Non sequitur
Addon Developer
Joined
Feb 4, 2010
Messages
6,665
Reaction score
13
Points
113
Location
The Wilderness, N.B.
Easy answer: You don't.

It was made to showcase the new radiation pressure feature, nothing more.

Of course, you can dock a Deltaglider to it, so maybe...:hmm:
 

River Crab

SpaceX Cheer Captain
Addon Developer
Donator
Joined
May 4, 2010
Messages
945
Reaction score
3
Points
18
Location
Washington, D.C. area
I believe it's just a demonstration of radiation pressure's ability to accelerate objects- turn on visual forces and look at the Delta Glider and you'll see.
If you want to turn, you can dock something to it, but I don't think there's any MFDs or anything to use with solar sails.
Someone correct me if I'm wrong.

Edit: what he said.
 

krashkart

Heliosynchronous Debris Field
Joined
Jun 17, 2010
Messages
96
Reaction score
0
Points
0
Location
Somewhere between points A and B
I wondered about that myself. I bet a Tranzit tug would provide enough oomph to rotate the sail around.


EDIT

There is a Solar Sail MFD at Orbithangar (added on July of '06): [ame="http://www.orbithangar.com/searchid.php?ID=2529"]SolarSail_MFD[/ame]

And a somewhat reflective solar sail: [ame="http://www.orbithangar.com/searchid.php?ID=2984"]Solar Sail II[/ame]

Haven't tried either one.

EDIT EDIT

Question is, will the sail tug the tug? :hmm:
 
Last edited:

Linguofreak

Well-known member
Joined
May 10, 2008
Messages
5,038
Reaction score
1,275
Points
188
Location
Dallas, TX
A couple comments:

You can steer the sail by using the scenario editor to directly manipulate your orientation.

You *cannot* steer it (at least not very well) with a docked craft because of the orientation of the docking port: The other craft will shift the center of gravity and the sail will keep slewing around on you.

Without an MFD and autopilot I find the sail very hard to control so as to do what I want with it. The 2006 MFD probably won't help, since it wasn't based on the O2010 light pressure handling code.
 

vonneuman

Orbinaut
Joined
Nov 8, 2009
Messages
254
Reaction score
1
Points
0
Location
Missouri S&T
thanks guys

---------- Post added at 04:26 AM ---------- Previous post was at 02:50 AM ----------

Ok say I use the solar sail and have a delta glider docked to it so I can maneuver it. How do I plan a flight with it? Because I don't think that a solar sail is to practical for rendezvous.
 
Last edited:

Andy44

owner: Oil Creek Astronautix
Addon Developer
Joined
Nov 22, 2007
Messages
7,620
Reaction score
7
Points
113
Location
In the Mid-Atlantic states
thanks guys

---------- Post added at 04:26 AM ---------- Previous post was at 02:50 AM ----------

Ok say I use the solar sail and have a delta glider docked to it so I can maneuver it. How do I plan a flight with it? Because I don't think that a solar sail is to practical for rendezvous.

Well, like he said, it's not very practical to navigate with a DG docked to it, since the docked vessel is off-center and the light pressure produces a moment arm, causing the sail to start to tumble.
 

tblaxland

O-F Administrator
Administrator
Addon Developer
Webmaster
Joined
Jan 1, 2008
Messages
7,320
Reaction score
25
Points
113
Location
Sydney, Australia
More significantly (IMHO), the solar sail only weighs 100 kg, so adding a 20 t Delta-glider to it significantly reduces the available acceleration.
 

jinglesassy

New member
Joined
Mar 23, 2009
Messages
900
Reaction score
0
Points
0
Location
Look behind you.
More significantly (IMHO), the solar sail only weighs 100 kg, so adding a 20 t Delta-glider to it significantly reduces the available acceleration.

So what you are saying is we need a 500 t solar sail? Whos gonna model this beast and make it an addon?
 

krashkart

Heliosynchronous Debris Field
Joined
Jun 17, 2010
Messages
96
Reaction score
0
Points
0
Location
Somewhere between points A and B
With the Lua console you can reduce the empty mass of the DG and kludge the propellant masses to where you might only have a couple hundred kilos of RCS fuel. Not sure if anything can be done about the docking arrangements... I will take a look into that now.
 

Hartmann

Member
Joined
Dec 3, 2007
Messages
191
Reaction score
0
Points
16
Location
Barcelona
Orbiter 2010 need A constant thrust MFD navigation tool for use in solar sails and ion engines. Use ion engines for example is very difficult because a spacecraft need a constant orientation during long periods of time.

here is the theory

http://www.ugcs.caltech.edu/~diedrich/solarsails/intro/tacking.html

Travelling away from the sun:
sailmch1.gif

Travelling towards the sun:

sailmch2.gif
 
Last edited:

mc_

New member
Joined
Jan 22, 2010
Messages
342
Reaction score
0
Points
0
Location
South-Western Siberia
I guess, someone should make a "request" on this MFD. It is another one "good thing we don't have in Orbiter".

//"someone" means "someone with good english" :lol: And I already have one "addon request" (SSTO VTOVL), so its your turn.
 

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,891
Reaction score
2,141
Points
203
Location
between the planets
I guess, someone should make a "request" on this MFD. It is another one "good thing we don't have in Orbiter".

I already tried to encourage people several times to make one, since I really want one, for several years now. I even started doing one myself, but I ran into a wall of math that was way too high for me to jump. The problems are quite complex.
There is the low-thrust flight planer, which isn't an MFD but an external app, but it doesn't work quite correctly yet. (well, it works quite nice for one burn, but it's still quite a challenge getting into orbit around something).
 

mc_

New member
Joined
Jan 22, 2010
Messages
342
Reaction score
0
Points
0
Location
South-Western Siberia
Orbiter 2010 simulates radiation pessure, and many future engine concepts are low-thrust, so, a "low-thrust MFD" is a good idea anyway.

Maybe, its time for another try?
 

N_Molson

Addon Developer
Addon Developer
Donator
Joined
Mar 5, 2010
Messages
9,295
Reaction score
3,266
Points
203
Location
Toulouse
Concerning the solar sail itself, the code suggest it's an unifinished project. The sail was planned to be steerable, there is code for animations.

I have no time for that now but it should be easy to add a RCS system, which would allow to orient it.

Code:
// ==============================================================
//                 ORBITER MODULE: SolarSail
//                  Part of the ORBITER SDK
//             Copyright (C) 2007 Martin Schweiger
//                   All rights reserved
//
// SolarSail.cpp
// Control module for SolarSail vessel class
// ==============================================================

#define ORBITER_MODULE

#include "SolarSail.h"
#include "meshres.h"

// ==============================================================
// Some vessel parameters
// ==============================================================
const double SAIL_RADIUS = 500.0;

// Calculate lift coefficient [Cl] as a function of aoa (angle of attack) over -Pi ... Pi
// Implemented here as a piecewise linear function
double LiftCoeff (double aoa)
{
    int i;
    const int nlift = 9;
    static const double AOA[nlift] = {-180*RAD,-60*RAD,-30*RAD,-1*RAD,15*RAD,20*RAD,25*RAD,60*RAD,180*RAD};
    static const double CL[nlift]  = {       0,      0,   -0.1,     0,   0.2,  0.25,   0.2,     0,      0};
    static const double SCL[nlift] = {(CL[1]-CL[0])/(AOA[1]-AOA[0]), (CL[2]-CL[1])/(AOA[2]-AOA[1]),
                                      (CL[3]-CL[2])/(AOA[3]-AOA[2]), (CL[4]-CL[3])/(AOA[4]-AOA[3]),
                                      (CL[5]-CL[4])/(AOA[5]-AOA[4]), (CL[6]-CL[5])/(AOA[6]-AOA[5]),
                                      (CL[7]-CL[6])/(AOA[7]-AOA[6]), (CL[8]-CL[7])/(AOA[8]-AOA[7])};
    for (i = 0; i < nlift-1 && AOA[i+1] < aoa; i++);
    return CL[i] + (aoa-AOA[i])*SCL[i];
}

// distance between two vertices
inline double Dst (const NTVERTEX *v1, const NTVERTEX *v2)
{
    double dx = v1->x - v2->x;
    double dy = v1->y - v2->y;
    double dz = v1->z - v2->z;
    return sqrt (dx*dx + dy*dy + dz*dz);
}

inline VECTOR3 Nml (const NTVERTEX *v1, const NTVERTEX *v2, const NTVERTEX *v3)
{
    float dx1 = v2->x - v1->x,   dx2 = v3->x - v1->x;
    float dy1 = v2->y - v1->y,   dy2 = v3->y - v1->y;
    float dz1 = v2->z - v1->z,   dz2 = v3->z - v1->z;

    return _V(dy1*dz2 - dy2*dz1, dz1*dx2 - dz2*dx1, dx1*dy2 - dx2*dy1);
}

inline VECTOR3 crossp (const NTVERTEX *v1, const NTVERTEX *v2)
{
    return _V(v1->y*v2->z - v2->y*v1->z, v1->z*v2->x - v2->z*v1->x, v1->x*v2->y - v2->x*v1->y);
}

// --------------------------------------------------------------
// One-time global setup across all instances
// --------------------------------------------------------------
void SolarSail::GlobalSetup()
{
    SolarSail::hMeshTpl = oapiLoadMeshGlobal ("SolarSail");
    oapiSetMeshProperty (SolarSail::hMeshTpl, MESHPROPERTY_MODULATEMATALPHA, 1);
    SetupElasticity (hMeshTpl);
}

// --------------------------------------------------------------
// Set up the dynamic elastic sail deformation code
// --------------------------------------------------------------
void SolarSail::SetupElasticity (MESHHANDLE hMesh)
{
    MESHGROUP *sail = oapiMeshGroup (hMesh, GRP_sail1);
    // all sail segments have the same mesh structure, so segment 1 represents all 4
    DWORD nvtx = sail->nVtx/2; // scan front side only
    DWORD nidx = sail->nIdx/2; // scan front side only
    DWORD ntri = nidx/3;
    WORD *idx = sail->Idx;
    NTVERTEX *vtx = sail->Vtx;
    DWORD i, j, k, m, nj, nk;

    // generate node neighbour graph
    sail_vbuf = new VECTOR3[nvtx];
    nbhr = new NBHR[nvtx];
    for (i = 0; i < nvtx; i++) {
        nbhr[i].nnd = 0;
        nbhr[i].fix = (vtx[i].x == 0 || vtx[i].y == 0);
    }

    for (i = 0; i < ntri; i++) {
        WORD *tri = idx+(i*3);
        for (j = 0; j < 3; j++) {
            nj = tri[j];
            for (k = 0; k < 3; k++) {
                if (j == k) continue;
                nk = tri[k];
                for (m = 0; m < nbhr[nj].nnd; m++)
                    if (nbhr[nj].nd[m] == nk) break; // already in neighbour list
                if (m == nbhr[nj].nnd) {
                    if (nbhr[nj].nnd == MAXNBHR) 
                        strcpy (oapiDebugString(), "Problems!");
                    else {
                        nbhr[nj].nd[m] = nk;
                        nbhr[nj].dst0[m] = Dst (vtx+nj, vtx+nk);
                        nbhr[nj].nnd++;
                    }
                }
            }
        }
    }
    sail_nvtx = nvtx;
    sail_ntri = ntri;
}

// --------------------------------------------------------------
// Constructor
// --------------------------------------------------------------
SolarSail::SolarSail (OBJHANDLE hVessel, int flightmodel)
: VESSEL3 (hVessel, flightmodel)
{
    int i;

    hMesh = NULL;
    mf = _V(0,0,0);
    DefineAnimations();
    for (i = 0; i < 4; i++)
        paddle_rot[i] = paddle_vis[i] = 0.5;
}

// --------------------------------------------------------------
// Define animation sequences for moving parts
// --------------------------------------------------------------
void SolarSail::DefineAnimations ()
{
    int i;

    // Steering paddle animations
    static UINT PaddleGrp[4] = {GRP_paddle1, GRP_paddle2, GRP_paddle3, GRP_paddle4};

    static MGROUP_ROTATE Paddle0 (0, PaddleGrp+0, 1, _V(0,0,0), _V(0,1,0), (float)(180.0*RAD));
    static MGROUP_ROTATE Paddle1 (0, PaddleGrp+1, 1, _V(0,0,0), _V(1,0,0), (float)(180.0*RAD));
    static MGROUP_ROTATE Paddle2 (0, PaddleGrp+2, 1, _V(0,0,0), _V(0,1,0), (float)(180.0*RAD));
    static MGROUP_ROTATE Paddle3 (0, PaddleGrp+3, 1, _V(0,0,0), _V(1,0,0), (float)(180.0*RAD));
    static MGROUP_ROTATE *Paddle[4] = {&Paddle0, &Paddle1, &Paddle2, &Paddle3};

    for (i = 0; i < 4; i++) {
        anim_paddle[i] = CreateAnimation(0.5);
        AddAnimationComponent (anim_paddle[i], 0, 1, Paddle[i]);
    }
}

// --------------------------------------------------------------
// Update sail nodal displacements
// --------------------------------------------------------------
void SolarSail::UpdateSail (const VECTOR3 *rpressure)
{
    // A kind of poor man's finite element code. Should eventually be done properly!
    
    static int sailidx = 0;

    const double elast = 1e-1;
    const double pscale = 1e3;
    DWORD i, j;
    NBHR *nb;
    NTVERTEX *vi, *vj;
    VECTOR3 dv, F, nm;
    static VECTOR3 *nml = 0;
    static DWORD *nsd = 0;
    double dst;

    sailidx = ++sailidx % 4;
    MESHGROUP *sail = oapiMeshGroup (hMesh, sailidx);

    for (i = 0; i < sail_nvtx; i++) {
        F = _V(0,0,rpressure->z*pscale); // note - should be calculated for LOCAL normal
        vi = sail->Vtx+i;
        nb = nbhr+i;
        if (nb->fix) {
            sail_vbuf[i] = _V(0,0,0);
            continue;
        }
        for (j = 0; j < nb->nnd; j++) {
            vj = sail->Vtx+nb->nd[j];
            dv.x = vj->x - vi->x;
            dv.y = vj->y - vi->y;
            dv.z = vj->z - vi->z;
            dst = length(dv);
            if (dst > nb->dst0[j]) { // is stretched
                F += dv*(elast/nb->dst0[j]);
            }
        }
        sail_vbuf[i] = F;
    }
    for (i = 0; i < sail_nvtx; i++) {
        sail->Vtx[i].x += (float)sail_vbuf[i].x;
        sail->Vtx[i].y += (float)sail_vbuf[i].y;
        sail->Vtx[i].z += (float)sail_vbuf[i].z;
    }
    for (i = 0; i < sail_nvtx; i++) {
        sail->Vtx[i+sail_nvtx].x += (float)sail_vbuf[i].x;
        sail->Vtx[i+sail_nvtx].y += (float)sail_vbuf[i].y;
        sail->Vtx[i+sail_nvtx].z += (float)sail_vbuf[i].z;
    }

    // calculate smooth normals - surely this could be done more efficiently!
    if (!nml) {
        nml = new VECTOR3[sail_nvtx];
        nsd = new DWORD[sail_nvtx];
    }
    memset (nml, 0, sail_nvtx*sizeof(VECTOR3));
    memset (nsd, 0, sail_nvtx*sizeof(DWORD));
    for (i = 0; i < sail_ntri; i++) {
        WORD *idx = sail->Idx + i*3;
        nm = Nml(sail->Vtx + *idx, sail->Vtx + *(idx+1), sail->Vtx + *(idx+2));
        for (j = 0; j < 3; j++) {
            nml[*(idx+j)] += unit(nm);
            nsd[*(idx+j)]++;
        }
    }
    for (i = 0; i < sail_nvtx; i++) {
        sail->Vtx[i].nx = (float)nml[i].x/nsd[i];
        sail->Vtx[i].ny = (float)nml[i].y/nsd[i];
        sail->Vtx[i].nz = (float)nml[i].z/nsd[i];
    }
    for (i = 0; i < sail_nvtx; i++) {
        sail->Vtx[i+sail_nvtx].nx = -(float)nml[i].x/nsd[i];
        sail->Vtx[i+sail_nvtx].ny = -(float)nml[i].y/nsd[i];
        sail->Vtx[i+sail_nvtx].nz = -(float)nml[i].z/nsd[i];
    }
}

// --------------------------------------------------------------
// Low-level steering: adjust the position of a paddle
// --------------------------------------------------------------
void SolarSail::SetPaddle (int p, double pos)
{
    paddle_rot[p] = pos;
}

// ==============================================================
// Overloaded callback functions
// ==============================================================

// --------------------------------------------------------------
// Set the capabilities of the vessel class
// --------------------------------------------------------------
void SolarSail::clbkSetClassCaps (FILEHANDLE cfg)
{
    // physical specs
    SetSize (SAIL_RADIUS*2.0);
    SetEmptyMass (100.0);
    SetCW (0.3, 0.3, 0.6, 0.9);
    SetWingAspect (0.7);
    SetWingEffectiveness (2.5);
    SetCrossSections (_V(10.5,15.0,5.8));
    SetRotDrag (_V(0.6,0.6,0.35));
    if (GetFlightModel() >= 1) {
        SetPitchMomentScale (1e-4);
        SetYawMomentScale (1e-4);
    }
    SetPMI (_V(3e3,3e3,6e3));
    SetTrimScale (0.05);
    SetCameraOffset (_V(0,0.8,0));
    SetLiftCoeffFunc (LiftCoeff);
    SetDockParams (_V(0,1.3,-1), _V(0,1,0), _V(0,0,-1));
    SetTouchdownPoints (_V(0,-1.5,2), _V(-1,-1.5,-1.5), _V(1,-1.5,-1.5));

    // visual specs
    AddMesh (hMeshTpl);
}

// --------------------------------------------------------------
// Frame pre-update
// --------------------------------------------------------------
void SolarSail::clbkPreStep (double simt, double simdt, double mjd)
{
    // calculate solar pressure on steering paddles
    int i;
    const double paddle_area = 7812.5;
    const double albedo = 2.0;
    static VECTOR3 ppos[4] = {
        _V(0,-550,0), _V(-550,0,0), _V(0,550,0), _V(550,0,0)
    };
    VECTOR3 nml;
    for (i = 0; i < 4; i++) {
        double phi = (paddle_rot[i]-0.5)*PI;
        double sphi = sin(phi), cphi = cos(phi);
        if (i%2 == 0) nml = _V(-sphi,0,cphi);
        else          nml = _V(0,sphi,cphi);
        double f = dotp (mf, nml);
        if (f < 0) {
            nml = -nml;
            f = -f;
        }
        f *= paddle_area*albedo;
        AddForce (nml*f, ppos[i]);
    }
}

// --------------------------------------------------------------
// Frame update
// --------------------------------------------------------------
void SolarSail::clbkPostStep (double simt, double simdt, double mjd)
{
    int i;

    if (hMesh) UpdateSail (&mf);

    for (i = 0; i < 4; i++) {
        if (paddle_vis[i] != paddle_rot[i])
            SetAnimation (anim_paddle[i], paddle_vis[i] = paddle_rot[i]);
    }
}

// --------------------------------------------------------------
// Implement effects of radiation pressure
// --------------------------------------------------------------
void SolarSail::clbkGetRadiationForce (const VECTOR3 &mflux, VECTOR3 &F, VECTOR3 &pos)
{
    mf = mflux;                   // store flux value
    const double albedo = 2.0;    // fully reflective
    const double area = SAIL_RADIUS*SAIL_RADIUS*PI;

    // The sail is oriented normal to the vessel z-axis.
    // Therefore only the z-component of the radiation momentum flux contributes
    // to change the sail's momentum (Fresnel reflection)
    double mom = mflux.z * albedo *area;
    F = _V(0,0,mom);
    pos = _V(0,0,0);        // don't induce torque
}

// --------------------------------------------------------------
// Create SolarSail visual
// --------------------------------------------------------------
void SolarSail::clbkVisualCreated (VISHANDLE vis, int refcount)
{
    hMesh = GetMesh (vis, 0);
}

// --------------------------------------------------------------
// Destroy SolarSail visual
// --------------------------------------------------------------
void SolarSail::clbkVisualDestroyed (VISHANDLE vis, int refcount)
{
    hMesh = NULL;
}

// --------------------------------------------------------------
// Respond to generic messages
// --------------------------------------------------------------
int SolarSail::clbkGeneric (int msgid, int prm, void *context)
{
    switch (msgid) {
    case VMSG_LUAINTERPRETER:
        return Lua_InitInterpreter (context);
    case VMSG_LUAINSTANCE:
        return Lua_InitInstance (context);
    }
    return 0;
}

// --------------------------------------------------------------
// Static member initialisations
// --------------------------------------------------------------
MESHHANDLE SolarSail::hMeshTpl = NULL;
NBHR *SolarSail::nbhr = NULL;
VECTOR3 *SolarSail::sail_vbuf = NULL;
DWORD SolarSail::sail_nvtx = 0;
DWORD SolarSail::sail_ntri = 0;

// ==============================================================
// API callback interface
// ==============================================================

// --------------------------------------------------------------
// Global initialisation
// --------------------------------------------------------------

DLLCLBK void InitModule (HINSTANCE hModule)
{
    SolarSail::GlobalSetup();
}

// --------------------------------------------------------------
// Vessel initialisation
// --------------------------------------------------------------
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
    return new SolarSail (hvessel, flightmodel);
}

// --------------------------------------------------------------
// Vessel cleanup
// --------------------------------------------------------------
DLLCLBK void ovcExit (VESSEL *vessel)
{
    if (vessel) delete (SolarSail*)vessel;
}
 

Linguofreak

Well-known member
Joined
May 10, 2008
Messages
5,038
Reaction score
1,275
Points
188
Location
Dallas, TX
Actually, most of the suggestions I've heard for steering solar sails involve manipulating the sail-lines, and possibly side-sails to the main sail, rather than an RCS system.
 

N_Molson

Addon Developer
Addon Developer
Donator
Joined
Mar 5, 2010
Messages
9,295
Reaction score
3,266
Points
203
Location
Toulouse
Of course, but that's much much harder to code in C++ :p
 

mc_

New member
Joined
Jan 22, 2010
Messages
342
Reaction score
0
Points
0
Location
South-Western Siberia
I suggest, a "solar sail autopilot" must hold determined angle to sun, and work properly even on high time accelerations (x100 or even x1000).
 
Top