I'm trying to run a pca on an block of an eigen matrix.
The observation in the input matrix are in columns.
I want to save the eigen vectors as a matrix for later use.
But the matrix (m_pcaCoefs) "gets reinitialized" when I use it in another scope, inside the class of course.
I'm pretty sure I'm missing something on how eigen works !
class foo {
public:
using InputMatrixType = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>;
void computePca(InputMatrixType & inputMatrix)
{
// m_pcaCoefs is a private member of dense matrix type
size_t start = 1;
auto r = inputMatrix.rows();
auto c = inputMatrix.cols();
Eigen::Block<InputMatrixType> inputBlock
= inputMatrix.block( start, 0 ,r-start , c );
// center the data
m_pixelValueMeans = inputBlock.rowwise().mean();
inputBlock.colwise() -= m_pixelValueMeans;
// inputBlock is a d by n, where d is the number of observation
InputMatrixType cov = inputBlock * inputBlock.adjoint();
cov = cov / (c - 1);
Eigen::SelfAdjointEigenSolver<InputMatrixType> eig(cov);
InputMatrixType m_pcaCoefs = eig.eigenvectors();
// here m_pcaCoefs looks fine
std::cout << m_pcaCoefs.size() << std::endl; // output: 9
}
void print()
{
std::cout << m_pcaCoefs.size() << std::endl; // output: 0
}
protected:
InputMatrixType m_pcaCoefs;
}
int main()
{
foo test;
test.computePca(someMatrix); // outputs 9
test.print() // output 0
}
Any clue how to get the eigenvectors to be copied to m_pcaCoefs ?
InputMatrixType m_pcaCoefs = eig.eigenvectors();
this is not what you're thinking which is a member of your class.
you should just use:
m_pcaCoefs = eig.eigenvectors(); // use member m_pcaCoefs
Related
I do a lot of modeling and simulation and I am writing a sim_logger in CPP. The basics of it are this: a user constructs the class with a logging frequency and an output path. They can then "register" any number of variables which gives the logger a reference to the desired variable (its not incredibly safe right now but I'll work on that later, focused on the issue at hand). I've created a template type called "variable" which contains three things, T *var, T last_val, and string ID. My problem is this, whenever I set the last_val equivalent to the var, the last_val inside the variable does not actually change. I am setting this value in line 180 of sim_logger.h. I feel like this is a silly problem, probably due to some misunderstanding I have of pointers. However, I've tried several different things and cannot seem to solve this problem.
sim_logger.h
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <variant>
#include <type_traits>
#include <math.h>
pragma once
// a class to log simulation data
// specifically for logging time dependent differential functions
class sim_logger
{
private:
// a type that represents a variable
/*
meant to contain anything, but limited by the variadic type
"poly_var_types" below
*/
template <typename T>
struct variable
{
T *var; // pointer to the variable itself
T last_val; // the last value of the variable
std::string ident; // the identity of the variable
};
// a variadic type
template <typename ... T>
using poly_var_types = std::variant<T...>;
// defined variable types
// these are the typical types that are logged, feel free to add more
using var_types = poly_var_types<
variable<double>,
variable<float>
// variable<int>,
// variable<bool>,
// variable<std::string>
>;
// class members
std::vector<var_types> registered_variables; // container of all variables
std::ofstream file; // output file stream
double dt; // the logging time step in seconds
double clock = 0.0; // the logging clock in seconds
double last_sim_time = clock; // the last sim time for interp
bool is_time_to_log = false; // flag for log function
const double EPSILON = 0.000000001; // rounding error
// a linear interpolation method
// only returns floating point values
double lin_interp(double x, double x1, double x2, double y1, double y2)
{
return (y1+(x-x1)*((y2-y1)/(x2-x1)));
}
public:
// constructor which sets the logging frequency and output path
// log_dt is a floating point value in units of seconds
// path_to_file is a string representation of the desired output path
sim_logger(double log_dt, std::string path_to_file)
{
dt = log_dt;
file.open(path_to_file);
file << std::setprecision(16) << std::fixed;
}
// method to register a variable with the logger
template <typename T>
void register_variable(std::string ident, T *aVar)
{
variable<T> v;
v.ident = ident;
v.var = aVar;
registered_variables.push_back(v);
};
// a method to write the log file header and log sim time 0.0 data
void write_header_and_log_init_data()
{
// write header
file << "sim_time" << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
if (i == registered_variables.size()-1)
file << rv.ident << "\n";
else
file << rv.ident << " ";
}, registered_variables[i]);
}
// log all registered variables
file << clock << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
if (i == registered_variables.size()-1)
file << *rv.var << "\n";
else
file << *rv.var << " ";
}, registered_variables[i]);
}
}
// method to log all registered variables
void log_data(double sim_time)
{
// check the timing
if (sim_time > (clock + dt))
{
is_time_to_log = true;
}
// check if its time to log
if (is_time_to_log)
{
// update the clock
clock += dt;
// debug
std::cout << "\n";
// log all registered variables
file << clock << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
// instantiate the value to be logged
double log_val;
// debug
std::cout << rv.last_val << " " << *rv.var << std::endl;
// if sim time is even with clock time, log at time
if (fabs(sim_time - clock) < EPSILON)
// if (true)
{
log_val = *rv.var;
}
// if sim time is past clock time, interpolate
else
{
log_val = lin_interp(sim_time, last_sim_time,
clock, rv.last_val, *rv.var);
}
// if last variable in vector create new line
if (i == registered_variables.size()-1)
file << log_val << "\n";
// otherwise just whitespace
else
file << log_val << " ";
}, registered_variables[i]);
}
// debug
std::cout << "\n";
// reset flag
is_time_to_log = false;
}
// get all the last values
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
// have to get last value at every update call
// This works in scope but the memory does not actually change?
// I am very confuse.
rv.last_val = *rv.var;
// debug
std::cout << rv.last_val << " " << *rv.var << std::endl;
}, registered_variables[i]);
}
// set the last sim time
last_sim_time = sim_time;
}
};
main.cpp
include <iostream>
include "sim_logger.h"
int main()
{
sim_logger logger(0.1, "sim_logger/log.dat");
double test1 = 100.0;
double test2 = 100.0;
double test3 = 100.0;
logger.register_variable("test1", &test1);
logger.register_variable("test2", &test2);
logger.register_variable("test3", &test3);
logger.write_header_and_log_init_data();
double simTime = 0.0;
double simDt = 1.0 / 20.0;
for (int i = 0; i < 3; i++)
{
simTime += simDt;
test1 += 1.0;
test2 += 2.0;
test3 += 3.0;
logger.log_data(simTime);
}
return 0;
};
output
101 101
102 102
103 103
102 102
104 104
106 106
1.88705e-26 103
1.88705e-26 106
1.88705e-26 109
103 103
106 106
109 109
std::visit([&](auto rv)
rv is, effectively, a parameter to this function (the closure, for the purposes of this answer, is effectively a function).
As you know: in C++ function parameters get passed by value. For example, using a simple function:
void func(int x)
{
x=5;
}
This func can set x to 5 as often as it wants. Whatever actually gets passed in, by anyone that calls func(), will remain unaffected:
int z=7;
func(z);
z is still 7. Even though func set its parameter to 5. This is fundamental to C++:
std::visit([&](auto rv)
{
rv.last_val = *rv.var;
So, this sets rv.last_val. Great. But this has no effect on whatever gets passed into here.
}, registered_variables[i]);
The visited instance of this variant is still what it is. It hasn't changed. Why would it change? C++ does not work this way.
So, if your intent, here, is to modify registered_variables[i], it should be passed by reference:
std::visit([&](auto &rv)
Now, the object referenced by rv gets modified.
I am trying to solve a nonlinear system using Ceres Solver by Google. The example below comes from this page: http://terpconnect.umd.edu/~petersd/460/html/newtonex1z.html
I first create a class called MatlabExample, where I compute the residuals and jacobians:
class MatlabExample
: public SizedCostFunction<2,2> {
public:
virtual ~MatlabExample() {}
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
double x1 = parameters[0][0];
double x2 = parameters[0][1];
residuals[0] = 2*x1+x1*x2-2;
residuals[1] = 2*x2-x1*pow(x2,2)-2 ;
if (jacobians != NULL && jacobians[0] != NULL) {
jacobians[0][0] = 2+x2;
jacobians[0][1] = x1;
jacobians[1][0] = -pow(x2,2);
jacobians[1][1] = 2-2*x1*x2;
}
return true;
}
};
The main file is as follows:
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
double x[] = { 0.0,0.0 };
Problem problem;
CostFunction* cost_function = new MatlabExample;
problem.AddResidualBlock(cost_function, NULL, &x);
Solver::Options options;
options.minimizer_progress_to_stdout = true;
Solver::Summary summary;
Solve(options, &problem, &summary);
std::cout << summary.BriefReport() << "\n";
return 0;
}
When compiling, I got a Segmentation fault: 11 error. Any ideas?
You are accessing the jacobians array wrong. Here is why.
When you added the residual block, you told Ceres that the cost function only depends on one parameter block of size 2 and produces a residual of size 2.
The jacobians array is an array of row-major jacobians. One for each parameter block. So in this case it is of size 1, and contains a pointer to size 4 array that should contain a row major Jacobian.
Your Jacobian filling code should instead read
if (jacobians != NULL && jacobians[0] != NULL) {
jacobians[0][0] = 2+x2;
jacobians[0][1] = x1;
jacobians[0][2] = -pow(x2,2);
jacobians[0][3] = 2-2*x1*x2;
}
I am creating an instance after updating records to the vector vecData inside counter.cpp when I am trying to retrieve this data I am getting the value as 0
main.cpp
#include <iostream>
#include "counter.hpp"
#define MAX_PORTS 3
int main()
{
Counter *counter = new Counter(3);
counter->age = 1;
counter->id = 12;
counter->pincode = 123;
std::vector<Counter> counterData(MAX_PORTS);
counter->storeCounterData(counter,1);
counter->storeCounterData(counter,2);
counter->storeCounterData(counter,3);
counter->getCounterData(counterData);
// getCounterData here is not able to retrieve value updated in above vector `vecData`
Counter *count = new Counter(3);
count->getCounterData(counterData);
return 0;
}
counter.cpp
#include "counter.hpp"
#include <iostream>
#include <vector>
Counter::Counter()
{
}
Counter::Counter(int vecSize):vecData(vecSize)
{
}
void Counter::storeCounterData(Counter *counter,int user)
{
vecData[user].age = counter->age;
vecData[user].id = counter->id;
vecData[user].pincode = counter->pincode;
std::cout<<"vector size inside storeCounterData = "<<vecData.size()<<std::endl;
}
void Counter::getCounterData(std::vector<Counter> &counter)
{
counter = vecData;
std::cout<<"vector size inside getCounterData = "<<vecData.size()<<std::endl;
std::vector<Counter>::iterator it;
for( it = vecData.begin(); it != vecData.end(); ++it)
{
std::cout<<vecData[1].age<<std::endl;
std::cout<<vecData[1].id<<std::endl;
std::cout<<vecData[1].pincode<<std::endl;
}
}
counter.hpp
#include <vector>
class Counter
{
private:
std::vector<Counter> vecData; // vectors
public:
Counter();
Counter(int vecSize);
int age, id, pincode;
void storeCounterData(Counter *counter,int user);
void getCounterData(std::vector<Counter> &counter);
};
Output
./a.out vector size inside storeCounterData = 3
vector size inside storeCounterData = 3
vector size inside storeCounterData = 3
vector size inside getCounterData = 3
1 12 123
1 12 123
1 12 123
vector size inside getCounterData = 3
0 0 0
0 0 0
0 0 0
This is C++, don't use macros for constants:
#define MAX_PORTS 3
Use a const variable instead:
const int max_ports = 3;
Why are you creating this variable on the heap?
Counter *counter = new Counter(3);
counter->age = 1;
counter->id = 12;
counter->pincode = 123;
C++ is not Java or C#, don't do that. You are failing to delete those variables, so you leak memory. Don't do that. This is the correct way:
Counter counter(3);
counter.age = 1;
counter.id = 12;
counter.pincode = 123;
Then either change setCounterData to take a reference, or pass in the address of the object:
counter->storeCounterData(&counter,1);
You are indexing into the vector with the values 1, 2 and 3, but the vector only has three elements, so the correct indices are 0, 1, and 2. Doing vecData[user] when user==3 and vecData.size()==3 is a serious bug. Don't do that.
Why are you always accessing vecData[1] instead of using the iterator?
std::vector<Counter>::iterator it;
for( it = vecData.begin(); it != vecData.end(); ++it)
{
std::cout<<vecData[1].age<<std::endl;
std::cout<<vecData[1].id<<std::endl;
std::cout<<vecData[1].pincode<<std::endl;
}
You probably meant this:
std::vector<Counter>::iterator it;
for( it = vecData.begin(); it != vecData.end(); ++it)
{
std::cout<<it->age<<std::endl;
std::cout<<it->id<<std::endl;
std::cout<<it->pincode<<std::endl;
}
Or much simpler:
for (auto& c : vecData)
{
std::cout << c.age << std::endl;
std::cout << c.id << std::endl;
std::cout << c.pincode << std::endl;
}
(And notice how much easier it is to read that with spaces around the << operators).
when I am trying to retrieve this data I am getting the value as 0
The reason you always get 0 printed is because you are getting the data from an un-filled vector that just contains three new Counter objects:
Counter *count = new Counter(3);
count->getCounterData(counterData);
You haven't stored any values in count->vecData[1] so the values you print out are just the default values created by the Counter constructor, which fails to initialize its members:
Counter::Counter()
{
}
This means the member variables are just garbage. You happen to get zeros because your program has only just started so the heap happens to be full of zeros, but it's actually undefined behaviour to read those variables.
Your Counter class needs to initialize those members properly:
class Counter
{
private:
std::vector<Counter> vecData; // vectors
public:
Counter();
Counter(int vecSize);
int age = 0;
int id = 0;
int pincode = 0;
void storeCounterData(Counter *counter,int user);
void getCounterData(std::vector<Counter> &counter);
};
I'm new to C++ from a java/python/etc background, and am trying to teach myself OO programming before I have to take a class on it next semester.
I'm trying to make an animation system using SFML, but am having some trouble with one of my class variables; it keeps resetting to 0 after I increment it. I'll start with the code and follow with a log output I'm using to help figure out what's going on.
SOLUTION: Being new to C++, I was an idiot and returned a new instance of my class in my getter functions; using [class]& func()... instead of [class] func() solved this, but now I have some refactoring to do.
Code (header):
...
typedef std::vector<Frame> frameVect; // (Frame defined above)
typedef std::vector<double> dubVect;
...
class limbAnim
{
private:
int limbNum;
int numFrames;
int curFrame;
frameVect frames;
public:
limbAnim(int limb, int nFrames, frameVect F);
<getters/setters>
void incCurFrame();
dubVect incrementAnimation(dubVect curPos, double curRot);
}
Code (cpp):
... (include vector, ofstream, etc)
std::ofstream AnimLog("log.log")
typedef std::vector<Frame> frameVect; // (Frame defined above)
typedef std::vector<double> dubVect;
...
limbAnim::limbAnim(int limb, int nFrames, frameVect F)
{
limbNum = limb;
curFrame = 0;
numFrames = nFrames;
frames = F;
}
void limbAnim::incCurFrame()
{
curFrame=curFrame+1;
if (curFrame >= numFrames)
{
curFrame = 0;
AnimLog << "Greater than." << std::endl;
}
}
dubVect limbAnim::incrementAnimation(dubVect curPos, double curRot)
{
AnimLog << limbNum << ", " << numFrames << std::endl;
if (numFrames > 0)
{
AnimLog << curFrame << std::endl;
dubVect curStepP = frames[curFrame].getStepPos();
double curStepR = frames[curFrame].getStepRot();
curPos[0] = curPos[0] + curStepP[0];
curPos[1] = curPos[1] + curStepP[1];
curRot = curRot + curStepR;
incCurFrame();
AnimLog << "Incremented: " << curFrame << std::endl;
}
dubVect retV = curPos;
retV.push_back(curRot);
return retV;
}
So, my log output looks good since I'm testing with 2 frames on limbs 6 & 8, except those limbs' curFrame seems to reset to 0 after incrementing:
...
5, 0
6, 2
0
Incremented: 1
7, 0
8, 2
0
Incremented: 1
9, 0
...
5, 0
6, 2
0
Incremented: 1
7, 0
8, 2
0
Incremented: 1
9, 0
...(ad nauseam)
Edit: Code calling the increment function.
(main.cpp)
// (Outside main loop.)
Animation walk_anim(12, "assets/anim/walk.dat");
// (Inside main loop.)
for (int i=0; i<12; i++)
{
dubVect animDat = walk_anim.getLimbFrame(i).incrementAnimation(limbPos[i], curDegs[i]);
dubVect newPos = getDVect(animDat[0], animDat[1]);
double newRot = animDat[2];
curDegs[i] = newRot;
if (curDegs[i] >= 360)
curDegs[i] -=360;
limbPos[i] = newPos;
}
getLimbFrame
Animation::Animation(int lNum, string fName)
{
numLimbs = lNum;
fileName = fName;
// Fill up limbVect with correct # of empty frames.
for (int i=0; i<numLimbs; i++)
{
frameVect emptyFVect;
limbAnim LA(i, 0, emptyFVect);
limbFrames.push_back(LA);
}
// Boring .dat parsing, populates the 'frames' var of each limbAnim.
loadAnim();
}
limbAnim Animation::getLimbFrame(int index)
{
if (index < numLimbs)
{
return limbFrames[index];
}
}
Hopefully you're aware that your functions take arguments by value, so they work on a copy of something.
You carefully avoided to show the really interesting code parts where you call incrementAnimation, most likely it follows the same bad pattern as the other functions.
I suggest reading up on how to pass objects by reference and const reference -- and how function arguments work in C++.
I think you need to declare that member variable, with the static keyword, then you can say it is a class variable, where it will be the shared for every instance of your class. Like this:
static int curFrame;
Then you need to initialize it from outside de class. Have in mind that declaration, is a lot different to initialization.
You can read about it here and here
I have defined 2 functions in my class Matrix as follows (in Matrix.hpp)
static Matrix MCopy( Matrix &a );
static Matrix MatInvert( Matrix &x )
static double MatDet( Matrix &x ); // Matdef function
In my Matrix.Cpp file, I defined these functions as follows:
Matrix Matrix::MatCopy( Matrix &a )
{
Matrix P( a.getRow() , a.getCol() , Empty );
int j=0;
while( j != P.getRow() ){
int i=0;
while( i != P.getCol() ){
P(j,i)=a(j,i);
++i;
}
++j;
}
return P;
}
Matrix Matrix::MatInvert( Matrix &x )
{
Matrix aa = Matrix::MatCopy(x); // i got error message here
int n = aa.getCol();
Matrix ab(n,1,Empty);
Matrix ac(n,n,Empty);
Matrix ad(n,1,Empty);
if(MatLu(aa,ad)==-1){
assert( "singular Matrix" );
exit(1);
}
int i=0;
while( i != n ){
ab.fill(Zero);
ab (i,0)=1.0;
MatRuecksub(aa, ab,ac,ad,i);
++i;
}
return ac;
}
ok this is the my MatDef function
double Matrix::MatDet( Matrix &x )
{
double result;
double vorz[2] = {1.0, -1.0};
int n = x.getRow();
Matrix a = Matrix::MatCopy(x);
Matrix p( n, 1, Empty);
int i = MatLu(a, p);
if(i==-1){
result = 0.0;
}
else {
result = 1.0;
int j=0;
while(j != n){
result *= a( static_cast<int>(p(j,0)) ,j);
++j;
}
result *= vorz[i%2];
}
return result;
}
but when I compile this, I get an error telling me that:
line 306:no matching function for call to ‘Matrix::Matrix[Matrix]’:
note: candidates are: Matrix::Matrix[Matrix&]
note:in static member function ‘static double Matrix ::MatDet[Matrix&]’:
I can not understand what the problem is since I am new to C++ programming, so please help me in fixing this error.
Where I have used
Matrix aa = Matrix::MatCopy(x);
It shows same error message like line 306 but with different notes so I think MatDef is not a problem.
Please give your comments to solve this. Thanks!
If you have a class called A and it has a static function foo you would call it this way
A::foo();
Reading material
It seems that you are trying to access a variable of the class from a static member function of that class. Static member functions cannot access regular variables of the class.
You need to check the link that #Woot4Moo suggested:
non-static vs. static function and variable