Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion App/app.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#include "simulation2D.hpp"
#include "numerical_eq.hpp"
// #include "simulation3D.hpp"

#include <memory>

#undef DEBUG

int main(){



/*
NUMERICAL TESTS FIRST
*/
#ifdef DEBUG
RunTests();
#endif

/*
SIMULATION APP
Expand Down
54 changes: 44 additions & 10 deletions App/pendulum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,26 @@ SinglePendulum::SinglePendulum(float x0, float y0, double m, double l, double in
//Calculate initial cartesian coordinates based on polar coordinates values
x = x0 + ( l * sin(theta));
y = y0 - ( l * cos(theta));

//Save initial values;
this->init_theta = glm::radians(init_theta);
this->init_thetadot = glm::radians(init_thetadot);

}

void SinglePendulum::displayParameters(){
void SinglePendulum::ResetValues(){

theta = init_theta;
thetadot = init_thetadot;
}

std::cout << "Single Pendulum parameters: \n";
void SinglePendulum::UpdateCartesianCoordinates(){

x = x0 + ( l * sin(theta));
y = y0 - ( l * cos(theta));
}


double SinglePendulum::getKinematicEnergy(){
return (0.5 * m * pow(l,2) * pow(thetadot,2));
}
Expand All @@ -30,6 +42,8 @@ double SinglePendulum::getPotencialEnergy(){
}




DoublePendulum::DoublePendulum( float x0, float y0, double m1, double m2, double l1, double l2, double init_theta1,double init_theta2,double init_thetadot1, double init_thetadot2)
:m1(m1), m2(m2), l1(l1), l2(l2),theta1(glm::radians(init_theta1)), theta2(glm::radians(init_theta2)), thetadot1(init_thetadot1), thetadot2(init_thetadot2), x0(x0), y0(y0)
{
Expand All @@ -41,6 +55,13 @@ DoublePendulum::DoublePendulum( float x0, float y0, double m1, double m2, double
x2 = x0 + ( l1 * sin(theta1)) + ( l2 * sin(theta2));
y2 = y0 - ( l1 * cos(theta1)) - ( l2 * cos(theta2));

//Save initial values;
this->init_theta1 = glm::radians(init_theta1);
this->init_thetadot1 = glm::radians(init_thetadot1);
this->init_theta2 = glm::radians(init_theta2);
this->init_thetadot2 = glm::radians(init_thetadot2);


}


Expand All @@ -56,16 +77,30 @@ double DoublePendulum::getPotencialEnergy(){
);
}

void DoublePendulum::displayParameters(){
void DoublePendulum::ResetValues(){

std::cout << "Double Pendulum parameters: \n";
theta1 = init_theta1;
thetadot1 = init_thetadot1;
theta2 = init_theta2;
thetadot2 = init_thetadot2;

}

void ResetPendulum(SinglePendulum& pendulum){}
void DoublePendulum::UpdateCartesianCoordinates(){

void ResetPendulum(DoublePendulum& pendulum){}
x1 = x0 + ( l1 * sin(theta1));
y1 = y0 - ( l1 * cos(theta1));

x2 = x0 + ( l1 * sin(theta1)) + ( l2 * sin(theta2));
y2 = y0 - ( l1 * cos(theta1)) - ( l2 * cos(theta2));
}


/*
===============================================================
Single Pendulum numerical calculations
===============================================================
*/
void SimulatePendulumApprox(SinglePendulum& pendulum){

//Calculate properties in polar coordinates
Expand Down Expand Up @@ -136,7 +171,9 @@ void SimulatePendulumRK4(SinglePendulum& pendulum){
}

/*
Helpfull functions for double pendulum calculation
===============================================================
Double Pendulum numerical calculations
===============================================================
*/

double calculateThetaddot2(double l1, double l2, double m1, double m2, double theta1, double theta2, double thetadot1, double thetadot2){
Expand Down Expand Up @@ -190,9 +227,6 @@ void SimulatePendulumEuler(DoublePendulum& pendulum){
pendulum.y2 = pendulum.y0 - ( pendulum.l1 * cos(pendulum.theta1)) - ( pendulum.l2 * cos(pendulum.theta2));
}

/*
Posible to not create another double variables
*/
void SimulatePendulumHeun(DoublePendulum& pendulum){

//Calculate thetaddots for k1
Expand Down
21 changes: 16 additions & 5 deletions App/pendulum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ struct SinglePendulum{
float x0,y0;
float x,y;

//Save initial values
double init_theta;
double init_thetadot;

SinglePendulum(float x0, float y0, double m, double l, double init_theta, double init_thetadot);

double getKinematicEnergy();
double getPotencialEnergy();

void displayParameters();
void ResetValues();
void UpdateCartesianCoordinates();

};

Expand All @@ -38,20 +43,26 @@ struct DoublePendulum{
float x1,y1;
float x2,y2;


//Save initial values;
double init_theta1;
double init_thetadot1;
double init_theta2;
double init_thetadot2;


DoublePendulum( float x0, float y0, double m1, double m2, double l1, double l2, double init_theta1,
double init_theta2,double init_thetadot1, double init_thetadot2);

double getPotencialEnergy();
double getKinematicEnergy();

void displayParameters();
void ResetValues();
void UpdateCartesianCoordinates();


};

void ResetPendulum(SinglePendulum& pendulum);
void ResetPendulum(DoublePendulum& pendulum);

/*
Single Pendulum
*/
Expand Down
131 changes: 74 additions & 57 deletions App/simulation2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,10 @@ void Simulation2D::run(){
const char* pendulumNumericEq2[] = { "Euler Method", "Heun's method (Modified Euler Method)", "Runge-Kutta Method (RK4)"};
int pendulumNumericEqIndex2 = 0;

double degrees = 0.0, degrees2 = 0.0, degrees3 = 0.0;

bool isSimulationRunning = false;

/*
TODO - OPTIMIZE THIS!!!!!!!!!!!!
*/


//ImPlot parameters for plots

Expand Down Expand Up @@ -218,24 +217,21 @@ void Simulation2D::run(){

FPSTimer::GetTimer()->StartFrame();



//Event handler - in the future
window->onEvents();

/*
==============================================================
PHYSICS CALCULATION
==============================================================
*/


if(isSimulationRunning == true){


//Single Pendulum
if(pendulumTypesIndex == 0){

/*
==============================================================
PHYSICS CALCULATION
==============================================================
*/

switch (pendulumNumericEqIndex)
{
case 0: SimulatePendulumApprox(single); break;
Expand All @@ -256,33 +252,17 @@ void Simulation2D::run(){
updatePlotData(pot, Ep_data, 1000);
updatePlotData(kin, Ek_data, 1000);
updatePlotData(kin + pot, Ec_data, 1000);


/*
==============================================================
GRAPHICS ADJUSTMENTS
==============================================================
*/
singleLine.setPositions( xg, yg, 0.0f, xg + (single.x * scaleX), yg + (single.y * scaleY), 0.0f);
singleLineMesh.UpdateData(singleLine.getVerticesArrayData(), singleLine.getVerticesArraySize());

singleCircle.generatePoints(xg + (single.x * scaleX), yg + (single.y * scaleY), 25.0f, segments);
singleCircleMesh.UpdateData(singleCircle.getVerticesArrayData(), singleCircle.getVerticesArraySize());


//Trails data
updateTrailData(xg + (single.x * scaleX), yg + (single.y * scaleY), trailPositions, 10000);
trailPositionsVBO.UpdateData(trailPositions, 10000 * 2 * sizeof(float));

}

//Double Pendulum
if(pendulumTypesIndex == 1){

/*
==============================================================
PHYSICS CALCULATION
==============================================================
*/

switch (pendulumNumericEqIndex2)
{
case 0: SimulatePendulumEuler(pendulum);; break;
Expand All @@ -304,14 +284,37 @@ void Simulation2D::run(){
updatePlotData(kin, Ek2_data, 1000);
updatePlotData(kin + pot, Ec2_data, 1000);


//Trails data
updateTrailData(xg + (pendulum.x1 * scaleX), yg + (pendulum.y1 * scaleY), doubleTrailPostions, 10000);
doubleTrailPostionsVBO.UpdateData(doubleTrailPostions, 10000 * 2 * sizeof(float));

updateTrailData(xg + (pendulum.x2 * scaleX), yg + (pendulum.y2 * scaleY), doubleTrailPostions2, 10000);
doubleTrailPostionsVBO2.UpdateData(doubleTrailPostions2, 10000 * 2 * sizeof(float));


}

}

/*
==============================================================
GRAPHICS ADJUSTMENTS
==============================================================
*/

if(pendulumTypesIndex == 0){

singleLine.setPositions( xg, yg, 0.0f, xg + (single.x * scaleX), yg + (single.y * scaleY), 0.0f);
singleLineMesh.UpdateData(singleLine.getVerticesArrayData(), singleLine.getVerticesArraySize());

singleCircle.generatePoints(xg + (single.x * scaleX), yg + (single.y * scaleY), 25.0f, segments);
singleCircleMesh.UpdateData(singleCircle.getVerticesArrayData(), singleCircle.getVerticesArraySize());


/*
==============================================================
GRAPHICS ADJUSTMENTS
==============================================================
*/

}

if(pendulumTypesIndex == 1){

doubleLine1.setPositions(xg, yg, 0.0f, xg + (pendulum.x1 * scaleX), yg + (pendulum.y1 * scaleY), 0.0f);
doubleLine1Mesh.UpdateData(doubleLine1.getVerticesArrayData(), doubleLine1.getVerticesArraySize());
Expand All @@ -326,15 +329,6 @@ void Simulation2D::run(){

circleMesh1.UpdateData(circle1.getVerticesArrayData(), circle1.getVerticesArraySize());
circleMesh2.UpdateData(circle2.getVerticesArrayData(), circle2.getVerticesArraySize());

updateTrailData(xg + (pendulum.x1 * scaleX), yg + (pendulum.y1 * scaleY), doubleTrailPostions, 10000);
doubleTrailPostionsVBO.UpdateData(doubleTrailPostions, 10000 * 2 * sizeof(float));

updateTrailData(xg + (pendulum.x2 * scaleX), yg + (pendulum.y2 * scaleY), doubleTrailPostions2, 10000);
doubleTrailPostionsVBO2.UpdateData(doubleTrailPostions2, 10000 * 2 * sizeof(float));

}

}


Expand Down Expand Up @@ -405,10 +399,19 @@ void Simulation2D::run(){
ImGui::SameLine();
if (ImGui::Button("Reset")){

if(pendulumTypesIndex == 0)
ResetPendulum(single);
if(pendulumTypesIndex == 1)
ResetPendulum(pendulum);
if(pendulumTypesIndex == 0){
single.ResetValues();
single.UpdateCartesianCoordinates();
std::fill(&trailPositions[0], &trailPositions[(10000 * 2) - 1], 0.0f);
}
else{
pendulum.ResetValues();
pendulum.UpdateCartesianCoordinates();
std::fill(&doubleTrailPostions[0], &doubleTrailPostions[(10000 * 2) - 1], 0.0f);
std::fill(&doubleTrailPostions2[0], &doubleTrailPostions2[(10000 * 2) - 1], 0.0f);
}

isSimulationRunning = false;
}

if (ImGui::Combo("Choose pendulum", &pendulumTypesIndex, pendulumTypes, IM_ARRAYSIZE(pendulumTypes))) {
Expand All @@ -427,8 +430,14 @@ void Simulation2D::run(){

ImGui::Text("Change parameters");
ImGui::InputDouble("Mass", &single.m, 0.01, 3.0, "%.2f");
ImGui::InputDouble("Rod length", &single.l, 0.01, 3.0, "%.2f");
ImGui::InputDouble("Thetha", &single.theta, 0.01, 3.0, "%.2f");

if(ImGui::InputDouble("Rod length", &single.l, 0.01, 3.0, "%.2f"))
single.UpdateCartesianCoordinates();
if (ImGui::InputDouble("Theta (degrees)", &degrees, 0.0, 360.0, "%.2f")) {
single.theta = glm::radians(degrees);
single.UpdateCartesianCoordinates();
}



ImGui::Text("Actual data");
Expand Down Expand Up @@ -460,14 +469,22 @@ void Simulation2D::run(){
if (ImGui::Combo("Numerical method", &pendulumNumericEqIndex2, pendulumNumericEq2, IM_ARRAYSIZE(pendulumNumericEq2))) {
printf("Selected: %s\n", pendulumNumericEq2[pendulumNumericEqIndex2]);
}

ImGui::PushID(0);

ImGui::Text("Change parameters");
ImGui::InputDouble("Rod length", &pendulum.l1, 0.01, 3.0, "%.2f");
ImGui::InputDouble("Rod length", &pendulum.l2, 0.01, 3.0, "%.2f");
ImGui::InputDouble("Thetha 1", &pendulum.theta1, 0.01, 3.0, "%.2f");
ImGui::InputDouble("Thetha 2", &pendulum.theta2, 0.01, 3.0, "%.2f");
if(ImGui::InputDouble("Rod length 1", &pendulum.l1, 0.01, 3.0, "%.2f") || ImGui::InputDouble("Rod length 2", &pendulum.l2, 0.01, 5.0, "%.2f")){
pendulum.UpdateCartesianCoordinates();
}

if (ImGui::InputDouble("Theta 1 (degrees)", &degrees2, 0.0, 360.0, "%.2f")) {
pendulum.theta1 = glm::radians(degrees2);
pendulum.UpdateCartesianCoordinates();
}
if (ImGui::InputDouble("Theta 2 (degrees)", &degrees3, 0.0, 360.0, "%.2f")) {
pendulum.theta2 = glm::radians(degrees3);
pendulum.UpdateCartesianCoordinates();
}


ImGui::Text("Actual data");
Expand Down
Loading