Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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.
    0_1545855285675_double Pendulum.PNG

    In the picture above you can see the result of the calculation for val1 in teh command window.

    can somebody help ?


  • Lifetime Qt Champion

    @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


  • Lifetime Qt Champion

    @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


Log in to reply