pcl visualizer What's the meaning of getViewerPose - point-cloud-library

I don't quite understand what pose is returned by pcl::visualization::PCLVisualizer::getViewerPose. Is this pose relative to the viewer? or something else? If yes, how is the initial pose of the viewer defined?

Based on the code, the getViewerPose is just retrieving camera pose.
pcl::visualization::PCLVisualizer::getViewerPose (int viewport)
{
Eigen::Affine3f ret (Eigen::Affine3f::Identity ());
rens_->InitTraversal ();
vtkRenderer* renderer = nullptr;
if (viewport == 0)
viewport = 1;
int viewport_i = 1;
while ((renderer = rens_->GetNextItem ()))
{
if (viewport_i == viewport)
{
vtkCamera& camera = *renderer->GetActiveCamera ();
Eigen::Vector3d pos, x_axis, y_axis, z_axis;
camera.GetPosition (pos[0], pos[1], pos[2]);
camera.GetViewUp (y_axis[0], y_axis[1], y_axis[2]);
camera.GetFocalPoint (z_axis[0], z_axis[1], z_axis[2]);
z_axis = (z_axis - pos).normalized ();
x_axis = y_axis.cross (z_axis).normalized ();
ret.translation () = pos.cast<float> ();
ret.linear ().col (0) << x_axis.cast<float> ();
ret.linear ().col (1) << y_axis.cast<float> ();
ret.linear ().col (2) << z_axis.cast<float> ();
return ret;
}
viewport_i ++;
}
return ret;
}

Related

When finding cycles in undirected graphs, why can't we just keep track of previous parent node while using BFS traversal

Basically when we use DFS we just check if the adjacent nodes for a newly visited node have been already visited and they are not the parent node which made the DFS call for this node. If this is the case cycle is present.
I was using similar thing for BFS while keeping track of previous parent node and my logic doesn't seem to work. The test case on which my code is failing is too big to understand the problem. Can anyone let me know where my logic is broken? Thank you in advance
bool bfs(vector<int> adj[], bool isVisited[], int s, int V)
{
queue<int> q;
q.push(s);
isVisited[s] = true;
int parent = s;
int prevParent = -1;
while(q.empty() == false)
{
int u = q.front();
prevParent = parent;
parent = u;
q.pop();
for(int i = 0 ; i < adj[u].size() ; i++)
{
if(isVisited[adj[u][i]] == false)
{
isVisited[adj[u][i]] = true;
q.push(adj[u][i]);
// parent[][i]] = u;
}
else
{
if(adj[u][i] != prevParent)
return true;
}
}
}
return false;
}
bool isCycle(int V, vector<int> adj[]) {
// Code here
bool isVisited[V] = {false};
for(int i = 0 ; i < V ; i++)
{
if(isVisited[i] == false)
if(bfs(adj, isVisited, i, V) == true)
{
return true;
}
}
return false;
}

Is my binary tree program reaching an overflow/recursive maximum?

#include <iostream>
using namespace std;
struct Node{
bool flag;
char letter;
Node* left;
Node* right;
};
typedef Node* Nodeptr;
int stop = 0;
void splitString(string sequence, Nodeptr branch){
//cout << sequence << " ";
//cout << sequence.size() << endl;
if(stop == 20) return;
else stop++;
if(sequence.size() == 1){
branch->flag = true;
branch->letter = sequence[0];
}
else{
int half = sequence.size()/2;
Node* left = new Node;
Node* right = new Node;
branch->flag = false;
branch->left = left;
branch->right = right;
splitString(sequence.substr(0, half), left);
splitString(sequence.substr(half), right);
}
return;
}
void print(Nodeptr root){
if(root->flag)
cout << root->letter;
else{
print(root->left);
print(root->right);
}
return;
}
int main() {
std::cout << "Hello World!\n";
Nodeptr tree = new Node;
splitString("Heaven on ", tree);
print(tree);
//the above two lines run fine
Nodeptr tree2 = new Node;
splitString("Heaven on E", tree2); //this code will run fine
//print(tree2); //this code will give me an EXITED, SEGMENTATION FAULT error
}
Considering that the two lines:
splitString("Heaven on ", tree);
print(tree);
run fine, but these do not:
splitString("Heaven on E", tree2);
//print(tree2); //this code will give me an EXITED, SEGMENTATION FAULT error
I come to think that I have reached the maximum recursion depth. I reviewed my code for the building and traversing the binary tree but I cannot find any problems there. What is the reason for the error? Thanks!
For two reason:
you are using a global, which is a very bad practice, and for example in this case you are not resetting it after the first splitString
you are not managing the case where the string has 0 as size, in the right way
This is a possible implementation of splitString which works (without globals):
void splitString(string sequence, Nodeptr branch){
if(sequence.size() == 1){
branch->flag = true;
branch->letter = sequence[0];
}
else if (sequence.size() > 1){
int half = sequence.size()/2;
Node* left = new Node;
Node* right = new Node;
branch->flag = false;
branch->left = left;
branch->right = right;
splitString(sequence.substr(0, half), left);
splitString(sequence.substr(half), right);
}
else {
branch->flag = true;
branch->letter = '\0';
}
}
There is surely a better way to do this, and i'll encourage you to change the data structor in order to makes it happen (for example don't use the flag to mark the leaves of the tree, just check if there is left is been set or is nullptr)

StoreProhibitedCause Exception with linked list on ESP8266

I have implemented a linked list class as follows for storage of sensor data readings.
(Note the total code is ~4000 lines so I can't provide it all, hopefully this gives an idea of what's done).
struct DataItem {
String _dataType;
float _dataArray[dataArraySize_const];
float _calibratedData = -1.0;
float _rawData = -1.0;
DataItem *_next;
uint8_t _dataArraySize = dataArraySize_const;
float *_calibrationParameters;
uint8_t _numCalibrationParameters;
};
class DataContainer {
public:
DataContainer() {
_head = NULL;
_tail = NULL;
};
DataItem* addDataItem(String dataTypeIn, float calibrationParameters[10], uint8_t numberOfCalibrationParameters) {
DataItem *temp = new DataItem;
temp->_dataType = dataTypeIn;
temp->_calibratedData = -1.0;
temp->_rawData = -1.0;
for (uint8_t i = 0; i < dataArraySize_const; i++) { temp->_dataArray[i] = 0; } //Setting all the data array to 0
temp->_calibrationParameters = calibrationParameters;
temp->_numCalibrationParameters = numberOfCalibrationParameters;
temp->_next = NULL;
if(_head == NULL) {
_head = temp;
_tail = temp;
temp = NULL;
}
else {
_tail->_next = temp;
_tail = temp;
}
return temp;
};
uint8_t setDataValue(String dataType, float value, uint8_t arrayIndex) {
DataItem *temp = new DataItem;
temp = _head;
Serial.println("Addresses: ");
while(temp != NULL) {
Serial.print("temp address: 0x");
Serial.println((unsigned long)temp, HEX);
Serial.print("head address: 0x");
Serial.println((unsigned long)_head, HEX);
Serial.print("temp add address: 0x");
Serial.println((unsigned long)&temp, HEX);
if (temp->_dataType == dataType) { break; }
else if (temp == NULL) { return 1; }
temp = temp->_next;
}
temp->_dataArray[arrayIndex] = value;
float sum = 0.0;
for (uint8_t i = 0; i < dataArraySize_const; i++) {
sum += temp->_dataArray[i];
}
temp->_rawData = sum/dataArraySize_const;
Serial.println("Pre calibration");
this->calibrate(temp);
Serial.println("Finished calibration");
return 0;
};
void calibrate(DataItem *temp) {
temp->_calibratedData = temp->_calibrationParameters[0];
for (uint8_t i = 1; i <= temp->_numCalibrationParameters; i++) {
temp->_calibratedData += temp->_calibrationParameters[i] * pow(temp->_rawData, i);
}
}
uint8_t setCalibrationParameters(String dataType, float calibrationParameters[10]) {
DataItem *temp = new DataItem;
temp = _head;
while(temp != NULL) {
if (temp->_dataType == dataType) { break; }
else if (temp == NULL) { return 1; }
temp = temp->_next;
}
temp->_calibrationParameters = calibrationParameters;
return 0;
};
private:
DataItem *_head, *_tail;
};
uint8_t numUsedCalibrationParameters = 10;
float calibrationParam[numUsedCalibrationParameters] = {0,1,0,0,0,0,0,0,0,0};
uint8_t dataArrayPosition = 0;
uint8_t dataArraySize = 10;
void setup(void) {
Serial.begin(115200);
Serial.setDebugOutput(false);
delay(20);
Serial.println("\n\nbegin");
pinMode(A0, INPUT);
dataContainer.addDataItem("ADC",calibrationParam,numUsedCalibrationParameters);
void loop(void) {
dataContainer.setDataValue("ADC", analogRead(A0), dataArrayPosition);
if (dataArrayPosition < dataArraySize) { ++dataArrayPosition; }
else { dataArrayPosition = 0; }
delay(100);
}
After around 31000 loops (just under 2^15 which is suspicious to me), I get a StoreProhibitedCause Exception. If I comment out dataContainer.setDataValue("ADC", analogRead(A0), dataArrayPosition);, I no longer get the exception. I suspect it's some way that I have implemented the linked list and it has a memory issue but I have tried printing out the addresses of everything and it doesn't look like anything is running away.
Exception:
Exception (29):
epc1=0x4000df64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
>>>stack>>>
ctx: sys
sp: 3fffec10 end: 3fffffb0 offset: 01a0
3fffedb0: 4024576b 3fff0b08 00000002 40245700
.....
===================== SOLVED =====================
DataItem *temp = new DataItem; should be DataItem *temp; for setDataValue() and setCalibrationParameters().
Otherwise it keeps on creating new structs for every addition.
DataItem *temp = new DataItem; should be DataItem *temp; for setDataValue() and setCalibrationParameters().
Otherwise it keeps on creating new structs for every addition.
(I can't mark it solved without having an answer).

Pointer back and next for a node

I'm new to C++. I'm now trying to create a class with back and forth pointer. My code is listed below:
#include<iostream>
using namespace std;
class Node
{
public:
Node(int d, Node*k = NULL, Node*q = NULL) :data(d), back(k), next(q){};
int data;
Node*next; // point to next value on the list
Node*back; // point to back value on the list
};
int main()
{
int n;
Node*p = NULL;
Node*k = NULL; //k is back
while (cin >> n)
{
p = new Node(n,k);
p->back->next = p;
k = p;
}
for (; p; p = p->back)
cout << p->data << "->";
cout << "*\n";
system("pause");
}
However, I always have this error: "Access violation writing location"
I wonder if anybody have a solution ? Thanks
In the first iteration of the loop p->back is NULL. You get the access violation because you dereference it. Write this instead:
while (cin >> n)
{
p = new Node(n,k);
if (p->back != NULL) // p->back == NULL in the first iteration
p->back->next = p;
k = p;
}

QSignalSpy to capture a reference argument

It is not possible to capture an argument that has been passed as reference with a QSignalSpy:
QSignalSpy spy( myObject, SIGNAL(foo(int&)));
...
int& i=spy.at(0).at(0).value<int&>();
Since a QVariant can not contain a reference member. Plain logic.
But are there other solutions to check the passed-in argument?
Since Qt 5, we can simply connect to a lambda function, which makes the use of the QSignalSpy unnecessary:
std::vector<Value> values;
QObject::connect(myObject, &MyObject::foo,
[&](const auto &value)
{ values.emplace_back(value); });
myObject.somethingCausingFoo();
ASSERT_EQ(1u, values.size());
EXPECT_EQ(expectedValue, values.at(0));
An "ugly solution" would be to hack the fairly simple QSignalSpy code in order to handle the reference passed arguments. I provide a minimal working example for int reference arguments. The only changes were made to initArgs and appendArgs functions.
Notice that with this approach you will only be able to check the value of the passed argument by reference. You will not be able to change it's value.
In the initArgs function we check if we have references by argument and we populate the shouldreinterpret list.
void initArgs(const QMetaMethod &member)
{
QList<QByteArray> params = member.parameterTypes();
for (int i = 0; i < params.count(); ++i) {
int tp = QMetaType::type(params.at(i).constData());
if (tp == QMetaType::Void)
{
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
params.at(i).constData());
// Check if we have a reference by removing the & from the parameter name
QString argString(params.at(i).constData());
argString.remove("&");
tp = QMetaType::type(argString.toStdString().c_str());
if (tp != QMetaType::Void)
shouldReinterpret << true;
}
else
shouldReinterpret << false;
args << tp;
}
}
and the appendArgs function, where we reinterpret the passed by reference arguments:
void appendArgs(void **a)
{
QList<QVariant> list;
for (int i = 0; i < args.count(); ++i) {
QMetaType::Type type = static_cast<QMetaType::Type>(args.at(i));
if (shouldReinterpret.at(i))
{
switch (type)
{
case QMetaType::Int:
list << QVariant(type, &(*reinterpret_cast<int*>(a[i + 1])));
break;
// Do the same for other types
}
}
else
list << QVariant(type, a[i + 1]);
}
append(list);
}
Complete code for reference:
class MySignalSpy: public QObject, public QList<QList<QVariant> >
{
public:
MySignalSpy(QObject *obj, const char *aSignal)
{
#ifdef Q_CC_BOR
const int memberOffset = QObject::staticMetaObject.methodCount();
#else
static const int memberOffset = QObject::staticMetaObject.methodCount();
#endif
Q_ASSERT(obj);
Q_ASSERT(aSignal);
if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE) {
qWarning("QSignalSpy: Not a valid signal, use the SIGNAL macro");
return;
}
QByteArray ba = QMetaObject::normalizedSignature(aSignal + 1);
const QMetaObject *mo = obj->metaObject();
int sigIndex = mo->indexOfMethod(ba.constData());
if (sigIndex < 0) {
qWarning("QSignalSpy: No such signal: '%s'", ba.constData());
return;
}
if (!QMetaObject::connect(obj, sigIndex, this, memberOffset,
Qt::DirectConnection, 0)) {
qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
return;
}
sig = ba;
initArgs(mo->method(sigIndex));
}
inline bool isValid() const { return !sig.isEmpty(); }
inline QByteArray signal() const { return sig; }
int qt_metacall(QMetaObject::Call call, int methodId, void **a)
{
methodId = QObject::qt_metacall(call, methodId, a);
if (methodId < 0)
return methodId;
if (call == QMetaObject::InvokeMetaMethod) {
if (methodId == 0) {
appendArgs(a);
}
--methodId;
}
return methodId;
}
private:
void initArgs(const QMetaMethod &member)
{
QList<QByteArray> params = member.parameterTypes();
for (int i = 0; i < params.count(); ++i) {
int tp = QMetaType::type(params.at(i).constData());
if (tp == QMetaType::Void)
{
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
params.at(i).constData());
QString argString(params.at(i).constData());
argString.remove("&");
tp = QMetaType::type(argString.toStdString().c_str());
if (tp != QMetaType::Void)
shouldReinterpret << true;
}
else
shouldReinterpret << false;
args << tp;
}
}
void appendArgs(void **a)
{
QList<QVariant> list;
for (int i = 0; i < args.count(); ++i) {
QMetaType::Type type = static_cast<QMetaType::Type>(args.at(i));
if (shouldReinterpret.at(i))
{
switch (type)
{
case QMetaType::Int:
int k = (*reinterpret_cast<int*>(a[i + 1]));
list << QVariant(type, &k);
break;
}
}
else
list << QVariant(type, a[i + 1]);
}
append(list);
}
// the full, normalized signal name
QByteArray sig;
// holds the QMetaType types for the argument list of the signal
QList<int> args;
// Holds the indexes of the arguments that
QList<bool> shouldReinterpret;
};

Resources