Ошибка сегментации при попытке симулировать двойной маятник - PullRequest
0 голосов
/ 03 апреля 2020

Я пытаюсь создать программу для имитации двойного маятника, очень похожую на эту программу . Когда я запускаю этот код, у меня возникает ошибка сегмента, но я не могу найти причину.


#include <iostream>
#include <cmath>
#include <vector>

#define PI 3.14159265 // Pi
#define G 9.8 // Acceleration due to gravity
#define L1 1.0 // Pendulum 1 Length ( meters )
#define M1 1.0 // Pendulum 1 Mass ( kilograms )
#define L2 1.0 // Pendulum 2 Length ( meters )
#define M2 1.0 // Pendulum 2 Mass ( kilograms )
#define N 4 // Number of equations. Don't change

using namespace std;

void calculateDerivatives ( vector<float> &dydx , vector<float> &yIn )
{
   // Calculate derivatives and put them in dydx vector
   dydx.clear();
   float temp1 , temp2 , delta;

   delta = yIn[2] - yIn[0];

   // Calculate sins and cosines to lower computation cost
   float sD = sin ( delta );
   float cD = cos ( delta );
   float s2D = sin ( 2 * delta );

   dydx.push_back ( yIn[1] );

   temp1 = ( M2 * L1 * pow ( yIn[1] , 2 ) * (1 / 2) * s2D );
   temp1 += ( M2 * G * sin ( yIn[2] ) * cD );
   temp1 += ( M2 * L2 * pow ( yIn[3] , 2 ) * sD );
   temp1 -= ( ( M1 + M2 ) * G * sin ( yIn[0] ) ) / ( ( M1 + M2 ) * L1 - M2 *L1 * pow ( cD , 2 ) );
   dydx.push_back ( temp1 );

   dydx.push_back ( yIn[3] );

   temp2 = ( -M2 * L2 * pow ( yIn[3] , 2 ) * ( 1 / 2 ) * s2D );
   temp2 += ( M1 + M2 ) * G * sin ( yIn[0] ) * cD;
   temp2 -= ( M1 + M2 ) * L1 * pow ( yIn[1] , 2) * sD;
   temp2 -= ( ( M1 + M2 ) * G * sin ( yIn[2] ) ) / ( ( L2 / L1 ) * delta );
   dydx.push_back ( temp2 );
}

void doRungeKutta ( const float x , const float h , vector<float> &yIn , vector<float> &yOut )
{
   // Use the Runge Kutta method to solve the DE
   vector<float> dydx;
   vector<float> dydxt;
   vector<float> yt;
   vector< vector<float> > kuttas;

   // Step 1
   calculateDerivatives ( dydx , yIn );
   vector<float> temp;
   for ( int i = 0; i < N; i++ )
   {
      temp.push_back( h * dydx[i] );
      yt.push_back ( yIn[i] + ( 0.5 ) * temp[i] );
   }
   kuttas.push_back ( temp );

   // Step 2
   calculateDerivatives ( dydxt , yt );
   for ( int i = 0; i < N; i++ )
   {
      temp[i] = ( h * dydxt[i] );
      yt[i] = ( yIn[i] + ( 0.5 ) * temp[i] );
   }
   kuttas.push_back ( temp );

   // Step 3
   calculateDerivatives ( dydxt , yt );
   for ( int i = 0; i < N; i++ )
   {
      temp[i] = ( h * dydxt[i] );
      yt[i] = ( yIn[i] + temp[i] );
   }
   kuttas.push_back ( temp );

   // Step 4
   calculateDerivatives ( dydxt , yt );
   for ( int i = 0; i < N; i++ )
   {
      temp[i] = ( h * dydxt[i] );
      yOut.push_back ( yIn[i] + kuttas[0][i] / 6.0 + kuttas[1][i] / 3.0 + kuttas[2][i] / 3.0 + kuttas[3][i] / 6.0 );
   }

}

int main( int argc , char *argv[] )
{
   int steps;
   float time_min , time_max , sTheta1 , sTheta2 , sAngVel1 , sAngVel2;
   float degRad = PI / 180;
   vector<float> yIn , yOut , times , theta1 , theta2 , angVel1 , angVel2;

   // Get command line inputs
   time_min = atof ( argv[1] );
   time_max = atof ( argv[2] );
   sTheta1 = atof ( argv[3] );
   sAngVel1 = atof ( argv[4] );
   sTheta2 = atof ( argv[5] );
   sAngVel2 = atof ( argv[6] );
   steps = atoi ( argv[7] );

   int h = ( time_max - time_min ) / ( steps - 1 );
   for ( int i = 0; i < steps; i++ )
   {
      times[i] = time_min + h * i;
   }

   theta1.push_back( sTheta1 * degRad );
   theta2.push_back( sTheta2 * degRad );
   angVel1.push_back( sAngVel1 );
   angVel2.push_back( sAngVel2 );

   cout << times[0] << " " << theta1[0] << " "
        << angVel1[0] << " " << theta2[0] << " " << angVel2[0];

   for ( int i = 0; i < ( steps - 1 ); i++ )
   {
      yIn.push_back( theta1[i] );
      yIn.push_back( angVel1[i] );
      yIn.push_back( theta2[i] );
      yIn.push_back( angVel2[i] );

      doRungeKutta ( times[i] , h , yIn , yOut );

      theta1.push_back( yOut[0] );
      angVel1.push_back( yOut[1] );
      theta2.push_back( yOut[2] );
      angVel2.push_back( yOut[3] );
      cout << times[i + 1] << " " << theta1[i + 1] << " "
           << angVel1[i + 1] << " " << theta2[i + 1] << " " << angVel2[i + 1];

   }

   return 0;
}


Извините, что так долго, я просто понятия не имею, что это вызывает, поэтому я не смог не сокращайте это до проблемной части. Я перебирал код снова и снова, ища какую-то ошибку, которую я мог совершить, объявляя массивы или получая доступ к чему-то за пределами границ, но я не могу найти свою ошибку.

Запуск GDB я получаю это:

$ g++ dp.cpp
$ ./a.out 0 10 90 0 90 0 1000
Segmentation fault (core dumped)
$ gdb a.out
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...(no debugging symbols found)...done.
(gdb) run 0 10 90 0 90 0 1000
Starting program: a.out 0 10 90 0 90 0 1000

Program received signal SIGSEGV, Segmentation fault.
0x0000000008001743 in doRungeKutta(float, float, std::vector<float, std::allocator<float> >&, std::vector<float, std::allocator<float> >&) ()
(gdb) where
#0  0x0000000008001743 in doRungeKutta(float, float, std::vector<float, std::allocator<float> >&, std::vector<float, std::allocator<float> >&) ()
#1  0x0000000008001c8a in main ()
(gdb)

Что мне не помогло. Я попытался найти в функции doRungeKutta, чтобы найти проблему, увы, я не смог ее найти.

РЕДАКТИРОВАТЬ: Использование векторов вместо выделения памяти. Однако segfault по-прежнему происходит с тем же выводом GDB.

1 Ответ

1 голос
/ 03 апреля 2020

Здесь есть одна ошибка:

void doRungeKutta ( const float x , const float h , vector<float> &yIn , vector<float> &yOut )
{
   //...
   vector< vector<float> > kuttas;

   // Step 1
   calculateDerivatives ( dydx , yIn );
   //...
   kuttas.push_back ( temp );  // Here is the first one

   // Step 2
   calculateDerivatives ( dydxt , yt );
   //.. 
   kuttas.push_back ( temp );  // Here is the second one

   // Step 3
   calculateDerivatives ( dydxt , yt );
   //...   
   kuttas.push_back ( temp ); // Here is the third one

   // Step 4
   calculateDerivatives ( dydxt , yt );
   for ( int i = 0; i < N; i++ )
   {
      temp[i] = ( h * dydxt[i] );
      yOut.push_back ( yIn[i] + kuttas[0][i] / 6.0 + kuttas[1][i] / 3.0 + kuttas[2][i] 
                  / 3.0 + kuttas[3][i] / 6.0 );  // <-- Error -- there is no kutta[3]
   }
}

Вектор kuttas имеет размер 3, но вы пытаетесь получить доступ к kutta[3], что является выходом за пределы допустимого диапазона. Таким образом, перезапись памяти и неопределенное поведение.

У вас также есть другие ошибки, например, некоторые из этих элементов vector, имеющие значения -inf, но очевидная ошибка - указанная.

...