Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Programming a double pendulum
Forum Updated to NodeBB v4.3 + New Features

Programming a double pendulum

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 2 Posters 379 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E Offline
    E Offline
    Erdem
    wrote on 26 Dec 2018, 20:17 last edited by
    #1

    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 ?

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on 26 Dec 2018, 20:38 last edited by
      #2

      @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));

      E 1 Reply Last reply 26 Dec 2018, 20:54
      2
      • mrjjM mrjj
        26 Dec 2018, 20:38

        @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));

        E Offline
        E Offline
        Erdem
        wrote on 26 Dec 2018, 20:54 last edited by
        #3

        @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

        mrjjM 1 Reply Last reply 26 Dec 2018, 21:03
        0
        • E Erdem
          26 Dec 2018, 20:54

          @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

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on 26 Dec 2018, 21:03 last edited by
          #4

          @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

          1 Reply Last reply
          4

          1/4

          26 Dec 2018, 20:17

          • Login

          • Login or register to search.
          1 out of 4
          • First post
            1/4
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved