Tudat / tudat

NOTE: This Tudat version is no longer supported. See https://docs.tudat.space/en/stable/ and https://github.com/tudat-team/tudat-bundle for the new version
BSD 3-Clause "New" or "Revised" License
87 stars 143 forks source link

Problem with custom termination settings #630

Closed liampieters closed 4 years ago

liampieters commented 4 years ago

Hi everyone, Im having an issue implementing a custom termination condition that stops the propagation of two Earth-orbiting objects when the dot product of their relative position and relative velocity drops below zero (physically meaning they start moving away from each other).

Below is my function that checks when the dot product of two vectors drops below zero. When it does, the function returns a 'boolian', since the class 'customTerminationCondition' requires a std::function< bool( const double ) > as input. Next to the 'const double time', Im also adding 2 dependent variables as input (rel. position and rel. velocity). These would preferably be of type 'vector', so that I can easily access the values inside and compute the dot product. However, the relative position and relative velocity are not of type 'vector', but are shared pointers to the class 'SingleDependentVariableSaveSettings'. Text continues below the code.

`// Function that returns
// dot product of two vector array.
bool dotProductStopCondition(const double time , vector<double> a , vector<double> b)
{
    double product = 0;
    // Loop for calculate cot product
    for (int i = 0; i < a.size() ; i++)
        product = product + a[i] * b[i];

    if ( product < 0 ) {
    return true;
    } else {
        return false;
    }
}`

The relative position and relative velocity are of Type: SingleDependentVariableSaveSettings. How do I access these types? I want to input them in my 'dotProductStopCondition' to find at what time the two objects start moving away from each other. Below is the code where I call the dotProductFunction inside my int main() function (line 345 in my file). I use std:bind() and std::placeholders to add more inputs to the function, as the online tudat documentation on custom termination settings tell me to. Finally I input the stopcondition in the customTerminationSettings. Text continues below code.

`// Define termination conditions
        std::shared_ptr< SingleDependentVariableSaveSettings > relVelocityDependentVariable =
                std::make_shared< SingleDependentVariableSaveSettings >( relative_velocity_dependent_variable, "Debris", "Asterix" );
        std::shared_ptr< SingleDependentVariableSaveSettings > relPositionDependentVariable =
                std::make_shared< SingleDependentVariableSaveSettings >( relative_position_dependent_variable, "Debris", "Asterix" );

        std::function< bool( const double , vector <double> , vector <double>  ) > stopConditionInteraction =
               std::bind( &dotProductStopCondition, std::placeholders::_1 , &relVelocityDependentVariable, &relPositionDependentVariable );

        std::shared_ptr< PropagationTerminationSettings > terminationSettingsInteraction =
               std::make_shared< PropagationCustomTerminationSettings >( stopConditionInteraction );`

The program tells me there is no viable conversion between SingleDependentSaveSettings and vector. So my question is:

How can I access the values inside the 2 dependent variables to compute my StopCondition and find the time at which the dot product becomes negative? I hope my question is clear, thank you very much for your time!! Any help is massively appreciated. The full code file is located here: https://github.com/liampieters/SpaceDebris/blob/master/SpaceDebris.cpp

Thanks, Liam

liampieters commented 4 years ago

@MarieFayolle

DominicDirkx commented 4 years ago

Hi Liam,

A few points:

I would recommend one of two approaches:

Let us know if this helps you to progress in resolving your issue,

Best,

Dominic

liampieters commented 4 years ago

Hi Dominic,

Thanks for the fast reply! I chose option 2 and added the bodyMap to the termination function. It now works perfectly. For other people wondering what I changed, here is my updated termination function:

`// Function that return
// dot product of two vector array.
bool dotProductStopCondition(const double time , const tudat::simulation_setup::NamedBodyMap& bodyMap)
{
        using namespace tudat;
        using namespace tudat::simulation_setup;

        std::function < Eigen::Vector6d() > stateLaserFunction = std::bind(&Body::getState, bodyMap.at( "Asterix" ) );
        std::function < Eigen::Vector6d() > stateDebrisFunction = std::bind(&Body::getState, bodyMap.at( "Debris" ) );
        Eigen::Vector6d stateLaser = stateLaserFunction();
        Eigen::Vector6d stateDebris = stateDebrisFunction();
        Eigen::VectorXd relativePosition = stateDebris.segment(0,3) - stateLaser.segment(0,3);
        Eigen::VectorXd relativeVelocity = stateDebris.segment(3,3) - stateLaser.segment(3,3);

        double product = relativePosition.dot(relativeVelocity);

        if ( product > 0 ) {
        return true;
        } else {
            return false;
        }
}`

I then called it in the int main() function as follows:


std::function< bool(const double) > checkStopCondition = std::bind( &dotProductStopCondition, std::placeholders::_1 , bodyMap);

        std::shared_ptr< PropagationTerminationSettings > terminationSettingsInteraction =
              std::make_shared< PropagationCustomTerminationSettings >( checkStopCondition ) ;

Thanks again!

Best, Liam

DominicDirkx commented 4 years ago

Hi Liam,

Good to hear. Note that the intermediate step:

 std::function < Eigen::Vector6d() > stateLaserFunction = std::bind(&Body::getState, bodyMap.at( "Asterix" ) );
std::function < Eigen::Vector6d() > stateDebrisFunction = std::bind(&Body::getState, bodyMap.at( "Debris" ) );

is not needed. You can simply do:


Eigen::Vector6d stateLaser = bodyMap.at( "Asterix" )->getState( );
Eigen::Vector6d stateDebris = bodyMap.at( "Debris" )->getState( );

Dominic