Solved Programming a double pendulum
-
Hi guys,
I try to programm a double pendulum using Qt. So far I have written a Pendel class which contains all properties needed.
Pendel.h
#ifndef PENDEL_H #define PENDEL_H #include <QGraphicsObject> class Pendel : public QGraphicsObject { Q_OBJECT Q_ENUMS(pendelSetup) public: enum pendelSetup {firstPendel = 1, secondePendel = 2}; Pendel(QGraphicsItem *parent = nullptr); ~Pendel(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); // public methods void setPendelPtr(Pendel *); void originsSetup(int, int, int); QPointF getOrigins(); // Length getter and setter int getLength(); void setLength(int); // Phi getter and setter int getPhi(); void setPhi(int); // Phi_dot getter int getPhi_dot(); // Phi_ddot getter int getPhi_ddot(); // Mass getter and setter int getMass(); void setMass(int); // Gravity getter and setter int getGravity(); void setGravity(int); public slots: void adjustAngle(int); void calcAcc1(); void calcAcc2(); signals: void angleChanged(int); void angleChanged(); private: int length = 80; int phi = 0; int phi_dot = 0; int phi_ddot = 0; int mass = 1; int gravity = 1; Pendel *other = nullptr; QPointF origins; }; #endif // PENDEL_H
Pendel.cpp
#include "pendel.h" #include <QPainter> #include <QtMath> #include <QDebug> Pendel::Pendel(QGraphicsItem *parent) : QGraphicsObject(parent) { setTransformOriginPoint(5,0); } Pendel::~Pendel() { } QRectF Pendel::boundingRect() const { return QRect(0,0, 10,length); } void Pendel::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { painter->setPen(QPen(Qt::black,3)); painter->drawLine(5,0, 5,length); painter->setBrush(Qt::black); painter->drawEllipse(0,length-5, 10,10); } // public methods void Pendel::setPendelPtr(Pendel *ptr) { if(other != ptr) { other = ptr; } } void Pendel::originsSetup(int setUp = firstPendel, int xv = 0, int yv = 0) { if(setUp == firstPendel) { origins.setX(xv); origins.setY(yv); } if(setUp == secondePendel) { origins.setX(xv+qSin(other->getPhi()*M_PI/180)*other->getLength()); origins.setY(yv+qCos(other->getPhi()*M_PI/180)*other->getLength()); } } QPointF Pendel::getOrigins() { return origins; } // Length getter and setter int Pendel::getLength() { return length; } void Pendel::setLength(int l) { if (length != l) { length = l; } } // Phi getter and setter int Pendel::getPhi() { return phi; } void Pendel::setPhi(int p) { if(phi != p) { phi = p; emit angleChanged(p); } } // Phi_dot getter int Pendel::getPhi_dot() { return phi_dot; } // Phi_ddot getter int Pendel::getPhi_ddot() { return phi_ddot; } // Mass getter and setter int Pendel::getMass() { return mass; } void Pendel::setMass(int m) { if(mass != m) { mass = m; } } // Gravity getter and setter int Pendel::getGravity() { return gravity; } void Pendel::setGravity(int g) { if(gravity != g) { gravity = g; } } //public slots void Pendel::adjustAngle(int p) { setPhi(p); setRotation(p); emit angleChanged(); } void Pendel::calcAcc1() { double val1 = -other->getMass()/(mass + other->getMass())*(other->getLength()/length); qDebug() << val1; double val2 = other->getPhi_ddot()*qCos((phi-other->getPhi())*M_PI/180); double val3 = qPow(other->getPhi_dot(),2)*qSin((phi-other->getPhi())*M_PI/180); double val4 = gravity/length*qSin(phi*M_PI/180); phi_ddot += val1*(val2+val3)-val4; phi_dot += phi_ddot; phi += phi_dot; setRotation(phi); } void Pendel::calcAcc2() { double val1 = -other->getLength()/length; double val2 = other->getPhi_ddot()*qCos((other->getPhi()-phi)*M_PI/180); double val3 = qPow(other->getPhi_dot(),2)*qSin((other->getPhi()-phi)*M_PI/180); double val4 = gravity/length*qSin(phi); phi_ddot += val1*(val2-val3)-val4; phi_dot += phi_ddot; phi += phi_dot; setRotation(phi); }
MainWindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class QGraphicsScene; class Pendel; class QTimer; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); public slots: void updatePos(); void returnPendel1Prop(); void returnPendel2Prop(); private: Ui::MainWindow *ui; QGraphicsScene *scene; QTimer *timer; Pendel *pendel1, *pendel2; }; #endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include "pendel.h" #include <QGraphicsScene> #include <QTimer> #include <QtMath> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), scene(new QGraphicsScene(this)), timer(new QTimer(this)), pendel1(new Pendel), pendel2(new Pendel) { // general setUp ui->setupUi(this); ui->graphicsView->setScene(scene); ui->spinBox->setRange(-900,900); ui->spinBox_2->setRange(-900,900); timer->setInterval(1000); // pendel setup pendel1->setParent(this); pendel1->setLength(50); pendel1->setPendelPtr(pendel2); pendel1->originsSetup(Pendel::firstPendel, 0, 0); pendel2->setParent(this); pendel2->setPendelPtr(pendel1); pendel2->originsSetup(Pendel::secondePendel, pendel1->getOrigins().x(), pendel1->getOrigins().y()); pendel2->setPos(pendel2->getOrigins().x(), pendel2->getOrigins().y()); scene->addItem(pendel1); scene->addItem(pendel2); // connect instruction connect(ui->spinBox, SIGNAL(valueChanged(int)), pendel1, SLOT(adjustAngle(int))); connect(ui->spinBox_2, SIGNAL(valueChanged(int)), pendel2, SLOT(adjustAngle(int))); connect(pendel1, SIGNAL(angleChanged()), this, SLOT(updatePos())); connect(ui->pushButton, SIGNAL(clicked()), timer, SLOT(start())); connect(timer, SIGNAL(timeout()), pendel1, SLOT(calcAcc1())); connect(timer, SIGNAL(timeout()), pendel2, SLOT(calcAcc2())); } MainWindow::~MainWindow() { delete ui; } // public slots void MainWindow::updatePos() { int angle = pendel1->getPhi(); double xKoo = pendel1->getOrigins().x()+qSin(angle*M_PI/180)*pendel1->getLength(); double yKoo = pendel1->getOrigins().y()+qCos(angle*M_PI/180)*pendel1->getLength(); pendel2->setPos(-xKoo, yKoo); } void MainWindow::returnPendel1Prop() { qDebug() << "Phi1: " << pendel1->getPhi(); qDebug() << "Phi_dot1: " << pendel1->getPhi_dot(); qDebug() << "Phi_ddot1: " << pendel1->getPhi_ddot(); qDebug() << "Mass1: " << pendel1->getMass(); qDebug() << "length: " << pendel1->getLength() << "\n"; } void MainWindow::returnPendel2Prop() { qDebug() << "Phi2: " << pendel2->getPhi(); qDebug() << "Phi_dot2: " << pendel2->getPhi_dot(); qDebug() << "Phi_ddot2: " << pendel2->getPhi_ddot(); qDebug() << "Mass2: " << pendel2->getMass(); qDebug() << "length: " << pendel2->getLength() << "\n"; }
My idea so far is to start the oscillation by clicking the PushButton adjusting the angles of the both pendulums. To achiev the motion of the pendulums I have embedded the equaltion of Motion of pendulum system into the methods
calcAcc1 and calcAcc2.
When I click the PushButton nothing happens. To see what happens within the methods I have i have embedded the instruction
qDebug() << val1;
into pendel.cpp//calcAcc1().
The Result of the calculation is zero and i don't know why.
In the picture above you can see the result of the calculation for val1 in teh command window.
can somebody help ?
-
@Erdem said in Programming a double pendulum:
The Result of the calculation is zero and i don't know why.
double val1 = -other->getMass()/(mass + other->getMass())*(other->getLength()/length);
Its get truncated to int. is my guess.
getMass returns int amount others.Try
double val1 = -other->getMass()/double((mass + other->getMass()))*(other->getLength()/double(length)); -
@mrjj Thank you for your advice.
But now val2 results zero.
And there I already tried the same but nothing. Can you maybe explaine the reason for this behaviour or link the respective homegape -
@Erdem
http://www.informit.com/articles/article.aspx?p=352857&seqNum=4"The / operator divides its first operand by the second. For example, 1000 / 5 evaluates to 200. If both operands are integers, the result is the integer portion of the quotient. For example, 17 / 3 is 5, with the fractional part discarded."
Its a standard c++ type thing.
more info here
https://stackoverflow.com/questions/36266370/division-in-c