Eigen C++ Assertion Failed - c++

I have an Eigen MatrixXd object, called v, and I am facing some problems when trying to access this matrix content. When I only print the content at the console (as in the code), works just as fine. When I try to use the content, the error shows up:
Assertion failed: (row >= 0 && row < rows() && col >= 0 && col < cols()), function operator(), file /usr/local/Cellar/eigen/3.2.4/include/eigen3/Eigen/src/Core/DenseCoeffsBase.h, line 337.
ChosenPoint ** points = new ChosenPoint*[width];
for (int i = 0; i < width; i++)
{
points[i] = new ChosenPoint[height];
for (int j = 0; j < height; j++)
{
points[i][j].setPoint(i, j, false);
points[i][j].setNumberOfFrames(numberOfFrames);
}
}
Matrix<double, 2, 1> v = (aT * a).inverse() * aT * b;
if (v.rows() == 2 && v.cols() == 1)
{
points[x][y].setFlow(v(0,0), v(1,0), frame);
}
And my ChosenPoint class:
typedef struct point
{
double x;
double y;
bool isValid;
} point;
class ChosenPoint
{
public:
ChosenPoint()
{
}
~ChosenPoint()
{
}
void setNumberOfFrames(int numberOfFrames)
{
this->flow = new point[numberOfFrames];
for (int i = 0; i < numberOfFrames; i++)
{
point f;
f.x = 0.0;
f.y = 0.0;
this->flow[i] = f;
}
}
void setPoint(int x, int y, bool isValid)
{
this->pt.x = (double) x;
this->pt.y = (double) y;
this->pt.isValid = isValid;
}
point getPoint()
{
return this->pt;
}
point* getFlow()
{
return this->flow;
}
void setFlow(double &xFlow, double &yFlow, int &position)
{
this->flow[position].x = xFlow;
this->flow[position].y = yFlow;
}
void updateFlow(int position)
{
this->flow[position].x = 2*this->flow[position].x;
this->flow[position].y = 2*this->flow[position].y;
}
void updateFlow(double xFlow, double yFlow, int position)
{
this->flow[position].x = xFlow;
this->flow[position].y = yFlow;
}
point pt;
point *flow;
};

My fault. The problem was with one of the other matrixes that I was using in the project, and took me a while to figure it out. Unfortunately, Eigen doesn`t seem to be really helpful when this happens:
I had 2 matrixes (A and B). The matrix with problem was A (somehow, some data was not loaded into the matrix). But when i multiplied A and B, it generated a new matrix C with some valid results (all my sanity checks were unuseful). I admit I don`t know a lot of Eigen.
Anyway, hope this is helpful for more people like me.

Related

Is there a faster way to calculate the inverse of a given nxn matrix?

I'm working on a program that requires calculating the inverse of an 8x8 matrix as fast as possible. Here's the code I wrote:
class matrix
{
public:
int w, h;
std::vector<std::vector<float>> cell;
matrix(int width, int height)
{
w = width;
h = height;
cell.resize(width);
for (int i = 0; i < cell.size(); i++)
{
cell[i].resize(height);
}
}
};
matrix transponseMatrix(matrix M)
{
matrix A(M.h, M.w);
for (int i = 0; i < M.h; i++)
{
for (int j = 0; j < M.w; j++)
{
A.cell[i][j] = M.cell[j][i];
}
}
return A;
}
float getMatrixDeterminant(matrix M)
{
if (M.w != M.h)
{
std::cout << "ERROR! Matrix isn't of nXn type.\n";
return NULL;
}
float determinante = 0;
if (M.w == 1)
{
determinante = M.cell[0][0];
}
if (M.w == 2)
{
determinante = M.cell[0][0] * M.cell[1][1] - M.cell[1][0] * M.cell[0][1];
}
else
{
for (int i = 0; i < M.w; i++)
{
matrix A(M.w - 1, M.h - 1);
int cy = 0;
for (int y = 1; y < M.h; y++)
{
int cx = 0;
for (int x = 0; x < M.w; x++)
{
if (x != i)
{
A.cell[cx][cy] = M.cell[x][y];
cx++;
}
}
cy++;
}
determinante += M.cell[i][0] * pow(-1, i + 0) * getMatrixDeterminant(A);
}
}
return determinante;
}
float getComplementOf(matrix M, int X, int Y)
{
float det;
if (M.w != M.h)
{
std::cout << "ERROR! Matrix isn't of nXn type.\n";
return NULL;
}
if (M.w == 2)
{
det = M.cell[1 - X][1 - Y];
}
else
{
matrix A(M.w - 1, M.h - 1);
int cy = 0;
for (int y = 0; y < M.h; y++)
{
if (y != Y)
{
int cx = 0;
for (int x = 0; x < M.w; x++)
{
if (x != X)
{
A.cell[cx][cy] = M.cell[x][y];
cx++;
}
}
cy++;
}
}
det = getMatrixDeterminant(A);
}
return (pow(-1, X + Y) * det);
}
matrix invertMatrix(matrix M)
{
matrix A(M.w, M.h);
float det = getMatrixDeterminant(M);
if (det == 0)
{
std::cout << "ERROR! Matrix inversion impossible (determinant is equal to 0).\n";
return A;
}
for (int i = 0; i < M.h; i++)
{
for (int j = 0; j < M.w; j++)
{
A.cell[j][i] = getComplementOf(M, j, i) / det;
}
}
A = transponseMatrix(A);
return A;
}
While it does work, it does so way too slowly for my purposes, managing to calculate an 8x8 matrix's inverse about 6 times per second.
I've tried searching for more efficient ways to invert a matrix but was unsuccessfull in finding solutions for matrices of these dimensions.
However I did find conversations in which people claimed that for matrices below 50x50 or even 1000x1000 time shouldn't be a problem, so I was wondering if I have missed something, either a faster method or some unnecessary calculations in my code.
Does anyone have experience regarding this and/or advice?
Sorry for broken english.
Your implementation have problems as others commented on the question. The largest bottleneck is the algorithm itself, calculating tons of determinants.(It's O(n!)!)
If you want a simple implementation, just implement Gaussian elimination. See finding the inverse of a matrix and the pseudo code at Wikipedia. It'll perform fast enough for small sizes such as 8x8.
If you want a complex but more efficient implementation, use a library that is optimized for LU decomposition(Gaussian elimination), QR decomposition, etc.(Such as LAPACK or OpenCV.)

xutility stack overflow in _get_second()

I'm trying to make a code to implement the direct type 2 realisation structure from Digital Signal Processing in C++.
So what I have is this for a class and of course a header that belongs to it:
#include "DirectType2.h"
DirectType2::DirectType2()
{
}
DirectType2::DirectType2(vector<double> inputBCoefficients, vector<double> inputACoefficients)
{
inputXFunction = inputACoefficients;
inputYFunction = inputBCoefficients;
}
void DirectType2::setInputFunctions(vector<double> inputA, vector<double> inputB)
{
inputXFunction = inputA;
inputYFunction = inputB;
}
vector<double> DirectType2::getInputXFunction()
{
return inputXFunction;
}
vector<double> DirectType2::getInputYFunction()
{
return inputYFunction;
}
double DirectType2::xOfNFunction(unsigned int n)
{
double sum = 0;
for (unsigned int i = 1; i <= n || i < inputXFunction.size(); i++)
{
sum += inputXFunction[i] * xOfNFunction(n - i);
}
double x = inputXFunction[0] + sum;
return x;
}
double DirectType2::wOfNFunction(unsigned int n)
{
double w = 0;
double sum = 0;
for (unsigned int i = 1; (i < n || i < inputXFunction.size()); i++)
{
sum -= inputXFunction[i] * wOfNFunction(n - i);
}
w = inputXFunction[1] - sum;
return w;
}
double DirectType2::yOfNFunction(unsigned int n)
{
double y = 0;
for (unsigned int i = 0; i < n || i < inputYFunction.size(); i++)
{
y += inputYFunction[i] * wOfNFunction(n - i);
}
return y;
}
DirectType2::~DirectType2()
{
}
My source file looks like this:
#include <iostream>
#include "DirectType2.h"
using namespace std;
int main()
{
double myDoubleY[] = { 0.01031, 0.06188, 0.1547, 0.2063, 0.1547, 0.06188, 0.01031 };
double myDoubleX[] = { 1, -1.188, 1.305, -0.6743, 0.2635, -0.05175, 0.005023 };
vector<double> yFunction(myDoubleY, myDoubleY + sizeof(myDoubleY) / sizeof(double));
vector<double> xFunction(myDoubleX, myDoubleX + sizeof(myDoubleX) / sizeof(double));
DirectType2 port(yFunction, xFunction);
cout << "y(n) med n = 6 bliver: " << port.yOfNFunction(6) << endl;
return 0;
}
Now my issue is that when I run this code, a file called "xutility" pops up and throws this exception:
Unhandled exception at 0x01284B77 in Portefølje 2 - forsøg 2.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x00E02F64).
Now of course I understand that it is a stack overflow that happens, but I dont understand why it opens this file and throws an exception from it, seeings as I don't really feel like I ever use this file..
The code snippet that throws the exception is:
const _Ty2& _Get_second() const noexcept
{ // return const reference to second
return (_Myval2);
}
and if I try to let the code continue it says this:
Exception thrown at 0x01284B77 in Portefølje 2 - forsøg 2.exe: 0xC0000005:
Access violation writing location 0x00E00FB4.
Edit:
In the header I have defined two vectors called inputXFunction and inputYFunction both set to contain doubles.
Each of your for-loops should use && instead of || as you need both conditions to be met in order to continue accessing the arrays safely. E.g.:
for (unsigned int i = 1; (i < n && i < inputXFunction.size()); i++)
{
sum -= inputXFunction[i] * wOfNFunction(n - i);
}
instead of:
for (unsigned int i = 1; (i < n || i < inputXFunction.size()); i++)
{
sum -= inputXFunction[i] * wOfNFunction(n - i);
}

Vector.push_back(...) read access violation

I don't know why but my program triggers a breakpoint on a line on the first iterations of 2 embedded loops here is the line:
pointerHolder->linkedVertices.push_back(&sphereApproximation.vertices.back());
Here is the section within which this resides (the line is near the bottom):
static const vertice holder[6] = { vertice(0,r,0,0), vertice(r,0,0,0), vertice(0,0,r,0), vertice(0,-r,0,0), vertice(-r,0,0,0), vertice(0,0,-r,0) };
std::vector<vertice> vertices (holder, holder + (sizeof(holder) / sizeof(vertice)));
shape sphereApproximation = shape(0, vertices);
int count;
for (int i = 0; i < 6; i++) {
count = i;
for (int t = 0; t < 5; t++) {
if (count == 5) {
count = 0;
}
else {
count++;
}
if (t != 2) {
sphereApproximation.vertices[i].linkedVertices.push_back(&sphereApproximation.vertices[count]);
}
}
}
bool * newConnection = new bool[pow(sphereApproximation.vertices.size(), 2) - sphereApproximation.vertices.size()]();
vertice * pointerHolder;
for (int i = 0; i < sphereApproximation.vertices.size(); i++) {
for (int t = 0; t < sphereApproximation.vertices[i].linkedVertices.size(); t++) {
if (!newConnection[(i * (sphereApproximation.vertices.size() - 1)) + t]) {
pointerHolder = sphereApproximation.vertices[i].linkedVertices[t];
sphereApproximation.vertices.push_back(newVertice(&sphereApproximation.vertices[i], pointerHolder, accuracyIterator + 1));
for (int q = 0; q < pointerHolder->linkedVertices.size(); q++) {
if (pointerHolder->linkedVertices[q] == &sphereApproximation.vertices[i]) {
pointerHolder->linkedVertices.erase(pointerHolder->linkedVertices.begin() + q);
break;
}
}
sphereApproximation.vertices[i].linkedVertices.erase(sphereApproximation.vertices[i].linkedVertices.begin() + t);
sphereApproximation.vertices[i].linkedVertices.push_back(&sphereApproximation.vertices.back());
std::cout << "gets here" << std::endl;
pointerHolder->linkedVertices.push_back(&sphereApproximation.vertices.back());
std::cout << "does not get here" << std::endl;
sphereApproximation.vertices.back().linkedVertices.push_back(&sphereApproximation.vertices[i]);
sphereApproximation.vertices.back().linkedVertices.push_back(pointerHolder);
}
}
}
I know the declaration for the newVertice(...) subroutine is missing, but I thought it was rather unnecessary, all that needs to be known is that its return type is vertice and it does return a vertice as I have tested. Here are the declerations of the structs I'm using:
struct vertice {
int accuracy;
double x, y, z;
std::vector<vertice*> linkedVertices;
vertice(double x, double y, double z, std::vector<vertice*> linkedVertices) {
this->x = x;
this->y = y;
this->z = z;
this->linkedVertices = linkedVertices;
}
vertice(double x, double y, double z, int accuracy) {
this->x = x;
this->y = y;
this->z = z;
this->accuracy = accuracy;
}
};
struct shape {
double center;
std::vector<vertice> vertices;
shape(double center, std::vector<vertice> vertices) {
this->center = center;
this->vertices = vertices;
}
};
If I've failed to provide anything please drop a comment and I shall amend my question.

Debugging a bad_alloc error c++

When I run my code everything seems to be working fine but after a certain number of timesteps (usually ~100, but a different number each time) I get the error:
"terminate called after throwing an instance of 'std::bad_alloc' "
Not really sure how to go about debugging this as it doesn't happen at the same point each time the code runs. I will post my code but it's quite long and is admittedly a bit of a mess (this is my first real attempt at writing a program in c++), but I will try and explain the structure and where I would expect the most likely place for the origin of the error to be.
The basic structure is that I have an array of "birds" (a class I define) that choose how to update themselves at every time step by some quite complicated calculation. In doing so it regularly calls the function getVisualState to update a linked list that every bird stores as its "visual state". I believe this is the only time I allocate any memory dynamically during the simulation, so I guess there's a pretty good chance this is the source of the error. The function Bird::resetVisualState() should clear the allocated memory after it's been used (but it doesn't seem like I am running out of memory, at least monitoring it in the task manager).
If anyone can see anything they think may be the source of the problem that would be fantastic, or if not just any suggestions for how I should actually debug this!
#include <iostream>
#include <cmath>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <ctime>
#include <vector>
#include <algorithm>
#include <fstream>
#include "birdClasses.h"
using namespace std;
/*
nBirds, nSteps, nF, v, dt, birdRad defined in "birdClasses.h"
*/
//define other parameters.
const int nSensors = 20;
const int nMoves = 3; //no. possible moves at each step.
double dTheta = 15*M_PI/180.0; //angle that birds can change their orientation by in a timestep.
double moves[nMoves] = {-dTheta, 0, dTheta}; //possible moves.
double noise = 0.0;
double initBoxX = 20, initBoxY = 20; //size of initial box particles are placed in.
double sensorFrac[nSensors];
double sensorRef[nSensors];
double sensorRange = 2*M_PI/((double)nSensors);
int counter = 0;
int nps = numStates(nMoves,nF);
int *possibleStates = new int[nps];
//variables to record positions and orientations.
double xPositions[nSteps][nBirds], yPositions[nSteps][nBirds], orientations[nSteps][nBirds];
//array to keep track of which collisions are possible.
int couldCollide[nF][nBirds][nBirds];
//function prototypes
bool checkCollision(int i, int nFut, Bird *birds, double xi, double yi);
unsigned long int getVisualState(Bird *birdList, int nFut, int i, double cX, double cY, double cAng);
void updateTree(double exploreX, double exploreY, double exploreO, Bird *bird, int bn, int nFut);
int main()
{
sensorRef[0] = sensorRange;
for(int u=1; u<nSensors; u++) sensorRef[u] = sensorRef[u-1] + sensorRange;
//set up GSL random number generator.
const gsl_rng_type * Tr;
gsl_rng * RNG;
gsl_rng_env_setup();
Tr = gsl_rng_default;
RNG = gsl_rng_alloc (Tr);
gsl_rng_set(RNG,time(NULL));
//set up output
ofstream output("output.txt");
//initialize birds in a box randomly, all with the same orientation.
Bird birdList[nBirds];
for(int i=0; i<nBirds; i++) {
birdList[i].set_position(gsl_ran_flat(RNG,0,initBoxX),gsl_ran_flat(RNG,0,initBoxY));
}
//ACTUAL CODE
int uniqueVisStates[nMoves];
double cX, cY, fX, fY, exploreX, exploreY, exploreO;
//main time step loop
for(int ts=0; ts<nSteps; ts++) {
//save current positions
for(int i=0; i<nBirds; i++) {
xPositions[ts][i] = birdList[i].get_xPos();
yPositions[ts][i] = birdList[i].get_yPos();
orientations[ts][i] = birdList[i].get_orientation();
birdList[i].updateFuture();
}
//update list of possible collisions.
for(int nFut=0; nFut<nF; nFut++) {
for(int i=0; i<nBirds; i++) {
cX = birdList[i].get_xPos(); cY = birdList[i].get_yPos();
counter = 0;
for(int j=0; j<nBirds; j++) {
if(i==j) {
continue;
} else {
fX = birdList[j].get_futureX(nFut); fY = birdList[j].get_futureY(nFut);
if((cX-fX)*(cX-fX)+(cY-fY)*(cY-fY) < ((nFut+1)*v*dt+2*birdRad)*((nFut+1)*v*dt+2*birdRad)) {
couldCollide[nFut][i][counter]=j;
counter++;
}
}
}
if(counter < nBirds) couldCollide[nFut][i][counter]=-1;
}
}
//loop over birds to choose how they update their orientation.
for(int bn=0; bn<nBirds; bn++) {
//loop over possible moves bird can make NOW.
for(int l=0; l<nMoves; l++) {
uniqueVisStates[l]=0;
}
for(int mn=0; mn<nMoves; mn++) {
for(int l=0; l<nps; l++) {
possibleStates[l]=0;
}
counter = 0;
exploreO = birdList[bn].get_orientation() + moves[mn];
exploreX = birdList[bn].get_xPos() + cos(exploreO)*v*dt;
exploreY = birdList[bn].get_yPos() + sin(exploreO)*v*dt;
updateTree(exploreX,exploreY,exploreO,&birdList[0],bn,0);
vector<int> visStates (possibleStates,possibleStates+counter);
vector<int>::iterator it;
sort (visStates.begin(),visStates.end());
it = unique(visStates.begin(),visStates.end());
uniqueVisStates[mn] = distance(visStates.begin(),it);
}
int maxInd = 0, maxVal = uniqueVisStates[0];
for(int h=1; h<nMoves; h++) {
if(uniqueVisStates[h] > maxVal) {
maxInd = h; maxVal = uniqueVisStates[h];
} else if(uniqueVisStates[h]==maxVal) {
if(abs(moves[h])<abs(moves[maxInd])) {
maxInd = h;
}
}
}
birdList[bn].update_Orientation(moves[maxInd]);
birdList[bn].update_Pos(birdList[bn].get_xPos()+cos(birdList[bn].get_orientation())*v*dt,birdList[bn].get_yPos()+sin(birdList[bn].get_orientation())*v*dt);
}
for(int bn=0; bn<nBirds; bn++) birdList[bn].finishUpdate();
cout << ts << "\n";
}
//OUTPUT DATA INTO A TEXT FILE.
for(int ts=0; ts<(nSteps-1); ts++) {
for(int bn=0; bn<nBirds; bn++) {
output << xPositions[ts][bn] << " " << yPositions[ts][bn] << " " << orientations[ts][bn] << "\n";
}
}
delete[] possibleStates;
return 0;
}
bool checkCollision(int i, int nFut, Bird *birds, double xi, double yi) {
int cond = 1; int index, counti=0;
while(cond) {
index = couldCollide[nFut][i][counti];
if(index==-1) break;
double xj = birds[index].get_futureX(nFut);
double yj = birds[index].get_futureY(nFut);
if((xi-xj)*(xi-xj)+(yi-yj)*(yi-yj) < 4*birdRad*birdRad) {
return 1;
}
counti++;
if(counti==nBirds) break;
}
return 0;
}
unsigned long int getVisualState(Bird *birdList, int nFut, int i, double cX, double cY, double cAng) {
//finds the visual state of bird i based on its current "exploring position" and the predicted positions of other birds at timestep nFut.
//visual state is defined by discretizing the bird's field of view into nSensors (relative to current orientation) and creating a vector of
//0s and 1s depending on whether each sensor is < half covered or not. This is then converted to an integer (as we are actually interested only
//in the number of unique visual states.
double relX, relY, relDist, dAng, s, dTheta, ang1, ang2;
//clear current visual state.
birdList[i].resetVisualState();
for(int j=0; j<nBirds; j++) {
if(i==j) continue;
relX = birdList[j].get_futureX(nFut)-cX;
relY = birdList[j].get_futureY(nFut)-cY;
relDist = sqrt(relX*relX+relY*relY);
dAng = acos((cos(cAng)*relX+sin(cAng)*relY)/relDist);
dTheta = atan(birdRad/relDist);
s = cos(cAng)*relY - sin(cAng)*relX;
if( s<0 ) dAng = 2*M_PI-dAng;
ang1 = dAng - dTheta; ang2 = dAng + dTheta;
if( ang1 < 0 ) {
birdList[i].addInterval(0,ang2);
birdList[i].addInterval(2*M_PI+ang1,2*M_PI);
} else if( ang2 > 2*M_PI ) {
birdList[i].addInterval(0,fmod(ang2,2*M_PI));
birdList[i].addInterval(ang1,2*M_PI);
} else {
birdList[i].addInterval(ang1,ang2);
}
}
Node *sI = birdList[i].get_visualState();
birdList[i].cleanUp(sI);
int ind1, ind2;
for(int k=0; k<nSensors; k++) sensorFrac[k]=0.0; //initialize.
while(sI->next->next != 0) {
ang1 = sI->value; ang2 = sI->next->value;
ind1 = floor(ang1/sensorRange); ind2 = floor(ang2/sensorRange);
if(ind2==nSensors) ind2--; //this happens if ang2 = 2pi (which can happen a lot).
if(ind1==ind2) {
sensorFrac[ind1] += (ang2-ang1)/sensorRange;
} else if(ind2-ind1==1) {
sensorFrac[ind1] += (sensorRef[ind1]-ang1)/sensorRange;
sensorFrac[ind2] += (ang2-sensorRef[ind1])/sensorRange;
} else {
sensorFrac[ind1] += (sensorRef[ind1]-ang1)/sensorRange;
sensorFrac[ind2] += (ang2-sensorRef[ind2-1])/sensorRange;
for(int y=ind1+1;y<ind2;y++) sensorFrac[y] = 1.0;
}
sI=sI->next->next;
}
//do final interval separately.
ang1 = sI->value; ang2 = sI->next->value;
ind1 = floor(ang1/sensorRange); ind2 = floor(ang2/sensorRange);
if(ind2==nSensors) ind2--; //this happens if ang2 = 2pi (which can happen a lot).
if(ind1==ind2) {
sensorFrac[ind1] += (ang2-ang1)/sensorRange;
} else if(ind2-ind1==1) {
sensorFrac[ind1] += (sensorRef[ind1]-ang1)/sensorRange;
sensorFrac[ind2] += (ang2-sensorRef[ind1])/sensorRange;
} else {
sensorFrac[ind1] += (sensorRef[ind1]-ang1)/sensorRange;
sensorFrac[ind2] += (ang2-sensorRef[ind2-1])/sensorRange;
for(int y=ind1+1;y<ind2;y++) sensorFrac[y] = 1.0;
}
int output = 0, multiplier = 1;
for(int y=0; y<nSensors; y++) {
if(sensorFrac[y]>0.5) output += multiplier;
multiplier *= 2;
}
return output;
}
void updateTree(double exploreX, double exploreY, double exploreO, Bird *bird, int bn, int nFut) {
double o,x,y;
if(checkCollision(bn,nFut,bird,exploreX,exploreY)) return;
int vs = getVisualState(bird,nFut,bn,exploreX,exploreY,exploreO);
possibleStates[counter] = vs;
counter++;
if(nFut < (nF-1)) {
for(int m=0; m<nMoves; m++) {
o = exploreO + moves[m];
x = exploreX + cos(o)*v*dt;
y = exploreY + sin(o)*v*dt;
updateTree(x,y,o,bird,bn,nFut+1);
}
} else {
return;
}
}
"birdClasses.h":
#ifndef BIRDCLASSES_H_INCLUDED
#define BIRDCLASSES_H_INCLUDED
#include <iostream>
#include <cmath>
using namespace std;
//DEFINE SOME GLOBAL PARAMETERS OF THE SIMULATION
const int nBirds = 50;
const int nF = 6; //number of future timesteps to consider.
const int nSteps = 200;
const double v = 20, dt = 0.1, birdRad = 0.2;
int numStates(int numMoves, int nFut) {
int num = 1; int multiplier = numMoves;
for(int i=1; i<nFut; i++) {
num += multiplier;
multiplier *= numMoves;
}
return num;
}
//Node class is just for a linked list (used in constructing the visual states),
class Node {
public:
int identifier; // 0 is left side of interval, 1 is right side
double value; //angular value.
Node *next; //pointer to the next interval.
void display(Node *start);
};
//printout linked list if necessary (mainly for debugging purposes).
void Node::display(Node *start) {
if(start != 0) {
double inter = start->value;
cout << inter << " ";
display(start->next);
}
}
//bird class.
class Bird {
double currX, currY;
double updatedX, updatedY;
double currOrientation;
double futureX[nF], futureY[nF];
Node *visualState;
public:
Bird() {
currOrientation=0.0; currX = 0.0; currY = 0.0;
visualState = new Node;
visualState->value = 0.0;
visualState->next = new Node;
visualState->next->value = 0.0;
visualState->next->next = 0;
}
Bird(double x, double y, double o) {
currX = x; currY = y; currOrientation = o;
visualState = new Node;
visualState->value = 0.0;
visualState->next = new Node;
visualState->next->value = 0.0;
visualState->next->next = 0;
}
void set_position(double x, double y) {
currX = x; currY = y;
}
double get_xPos() {
return currX;
}
double get_yPos() {
return currY;
}
double get_orientation() {
return currOrientation;
}
double get_futureX(int ts) {
return futureX[ts];
}
double get_futureY(int ts) {
return futureY[ts];
}
//return pointer to first node.
Node* get_visualState() {
return visualState;
}
void updateFuture() {
//use current orientation and position to update future positions.
for(int i=0; i<nF; i++) {
futureX[i] = currX + v*(i+1)*cos(currOrientation)*dt;
futureY[i] = currY + v*(i+1)*sin(currOrientation)*dt;
}
}
void update_Pos(double x, double y) {
updatedX = x;
updatedY = y;
}
//run this after all birds have updated positions:
void finishUpdate() {
currX = updatedX;
currY = updatedY;
}
void update_Orientation(double o) {
currOrientation += o;
}
//add the interval defined by [l r] to the visual state.
void addInterval(double l, double r) {
int placed = 0; double cL = 0.0; double cR = 0.0;
if(visualState->value==0.0 && visualState->next->value==0.0) { //then this is first interval to place.
visualState->value = l;
visualState->next->value = r;
placed = 1;
return;
}
Node *curr_L = visualState;
Node *prev_L = visualState;
while(placed==0) {
cL = curr_L->value;
cR = curr_L->next->value;
if(l<cL && r<cL) { //add new interval before this one.
Node *newRoot = new Node;
newRoot->value = l;
newRoot->identifier = 0;
newRoot->next = new Node;
newRoot->next->value = r;
newRoot->next->next = curr_L;
if(curr_L == visualState) {
visualState = newRoot;
} else {
prev_L->next->next = newRoot;
}
placed = 1;
} else if(l <= cL && r >= cR) {
curr_L->value = l;
curr_L->next->value = r;
placed = 1;
} else if(l <= cL && r <= cR) {
curr_L->value = l;
placed = 1;
} else if(l >= cL && r <= cR) {
placed = 1; //dont need to do anything.
} else if(l >= cL && l<=cR && r >= cR) {
curr_L->next->value = r;
placed = 1;
}
if(l > cR && r > cR) {
if(curr_L->next->next != 0) {
prev_L = curr_L;
curr_L = curr_L->next->next;
} else {
Node *newEndL = new Node;
newEndL->value = l;
newEndL->identifier = 0;
newEndL->next = new Node;
newEndL->next->value = r;
newEndL->next->identifier = 1;
newEndL->next->next = 0;
curr_L->next->next = newEndL;
placed = 1;
}
}
}
}
//remove any overlaps.
void cleanUp(Node *start) {
Node *NP, *NNP; NP = start->next->next;
if(NP==0) return;
NNP = start->next->next->next->next;
double cL = start->value, cR = start->next->value, nL = start->next->next->value, nR = start->next->next->next->value;
if(nL < cR) {
if(nR > cR) {
start->next->value = nR;
}
start->next->next = NNP;
}
if(NNP!=0) cleanUp(NP);
}
//reset the visual state.
void resetVisualState() {
Node *cNode = visualState;
Node *nNode = visualState->next;
while(nNode != 0) {
delete cNode;
cNode = nNode;
nNode = nNode->next;
}
delete cNode;
delete nNode;
visualState = new Node;
visualState->identifier = 0;
visualState->value = 0.0;
visualState->next = new Node;
visualState->next->identifier = 1;
visualState->next->value = 0.0;
visualState->next->next = 0;
return;
}
};
#endif // BIRDCLASSES_H_INCLUDED
or if not just any suggestions for how I should actually debug this!
You can try to set catchpoint in gdb to catch std::bad_alloc exception:
(gdb) catch throw bad_alloc
(See Setting Catchpoints)
If you are able to reproduce this bad_alloc in gdb you can then look at bt to see possible reason of this exception.
I think this is a logic bug and not necessarily memory related.
In void addInterval(double l, double r) you declare
Node *curr_L = visualState;
Node *prev_L = visualState;
These pointers will now point to whatever the member visualState is pointing to.
later on you are changing visualState to point to a newly created Node
Node *newRoot = new Node;
// ....
if(curr_L == visualState) {
visualState = newRoot;
but your pointers curr_L and prev_L will still point to whatever visualState was pointing to before. The only time you change those pointers is at
if(curr_L->next->next != 0) {
prev_L = curr_L;
curr_L = curr_L->next->next;
which is the same as
if(WHATEVER_VISUAL_STATE_USED_TO_POINT_TO->next->next != 0) {
prev_L = curr_L;
curr_L = curr_L->next->next;
Is this your intention? You can follow the assignment of curr_L by looking for *curr_L = * in your editor.
I would suggest testing your code on a small data sample and make sure your code follows your intentions. Use a debugger or trace outputs. Use
valgrind if you have access to it, I think you will appreciate valgrind.

Unpredictable pointer behavior

At the moment I am building a cloth physics app using OpenFrameworks. I'm new to C++, for a heads up.
In my app, two 'neighbor' particle objects are passed to a spring object as pointers. As a test, I have the spring object draw lines between the two particles (between their 3d vector positions). For some reason, these lines are different every time I run the program, even though no random values are involved. When I cout the values of the particle positions from the spring struct, they often are ridiculous values like -4.15301e-12. I'm following example code almost verbatim, so I'm not really sure where I'm going wrong.
Here is the example code I'm following:
https://sites.google.com/site/ofauckland/examples/17-cloth-physics
Here is my Spring struct:
#pragma once
#include "ofMain.h"
#include "Particle.h"
struct Spring {
float k, restLength;
Particle *a, *b;
ofVec3f posA, posB;
Spring(Particle *a, Particle *b, float k = .2) : a(a), b(b), k(k) {
restLength = (b->pos - a->pos).length();
}
void update() {
posA = a->pos;
posB = b->pos;
}
void draw() {
ofSetLineWidth(5);
ofSetColor(0, 255, 0);
ofLine(posA.x, posA.y, posB.x, posB.y);
}
};
The particle struct:
#pragma once
#include "ofMain.h"
struct Particle {
ofVec3f pos;
Particle(ofVec3f pos) : pos(pos) {
}
void update() {
}
void draw() {
ofSetColor(ofRandom(255), 0, 0);
ofFill();
ofCircle(pos.x, pos.y, 3);
}
};
And this is where I pass the two particles to the spring as pointers:
#pragma once
#include "ofMain.h"
#include "Particle.h"
#include "Spring.h"
struct Petal {
float maxWidth, spacing;
vector<Particle> particles;
vector<Spring> springs;
Petal(float maxWidth, float spacing) : maxWidth(maxWidth), spacing(spacing) {
setupPoints();
}
void setupPoints() {
float x = 0;
float y = 0;
for(int r = 1; r <= maxWidth; r++) {
x = (int)(r / 2) * -spacing;
y += spacing;
for(int c = 1; c <= r; c++) {
ofVec3f pos = ofVec3f(x, y, 0);
Particle p(pos);
particles.push_back(p);
x+=spacing;
}
}
for(int r = maxWidth; r > 0; r--) {
x = (int)(r / 2) * -spacing;
y += spacing;
for(int c = 1; c <= r; c++) {
ofVec3f pos = ofVec3f(x, y, 0);
Particle p(pos);
particles.push_back(p);
x+=spacing;
}
}
//find neighbors
for(int i = 0; i < particles.size(); i++) {
Spring s(&particles[i], &particles[findNeighbor(i)]);
springs.push_back(s);
}
}
int findNeighbor(int pIndex) {
float leastDist = 0;
float leastDistIndex = 0;
for(int i = 0; i < particles.size(); i++) {
if(i != pIndex) {
float distance = particles[pIndex].pos.distance(particles[i].pos);
if(abs(distance) < abs(leastDist) || leastDist == 0) {
leastDist = distance;
leastDistIndex = i;
}
}
}
return leastDistIndex;
}
void update() {
for(int i = 0; i < particles.size(); i++) {
particles[i].update();
}
for(int s = 0; s < springs.size(); s++) {
springs[s].update();
}
}
void draw() {
for(int i = 0; i < particles.size(); i++) {
particles[i].draw();
}
for(int s = 0; s < springs.size(); s++) {
springs[s].draw();
}
}
};
This is what happens. What's strange is that some of the springs seem to be in the correct position.
Please let me know if I can clarify something.
Thanks!
Your particles vector holds Particles by value, and the vector can copy and move these values around. When you pass Particles as pointers to the Spring, you are passing the address of something that might not be there at some point in the future. I am not sure if this is the problem, but it certainly is something that needs fixing.