How to properly read a Point Cloud File in C++ and ROS - c++

I just started using the Point Cloud Library and as a start I would like to read a point cloud from file. I followed the tutorial related to that. This is just a small example of a major CMake project I am building. Just slightly different from the tutorial I divided the project to make it more CMake suitable. The CMake runs well and the project seems to be organized. However when I try to run the project I get the following /home/emanuele/catkin_ws/src/map_ros/src/pointcloud_reader_node.cpp:6:10: fatal error: ../map_ros/include/cloud.h: No such file or directory #include "../map_ros/include/cloud.h"
error::Cloud::readPCloud(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) and I don't know how to explain this error.
Below the snippet of code I am using:
cloud.h
#ifndef CLOUD_H
#define CLOUD_H
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <sensor_msgs/PointCloud2.h>
#include <string>
class Cloud
{
public:
void readPCloud(std::string filename);
private:
std::string path;
};
#endif// CLOUD_H
cloud.cpp
#include "cloud.h"
void Cloud::readPCloud(std::string filename)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if(pcl::io::loadPCDFile<pcl::PointXYZ> (filename, *cloud) == -1) // load point cloud file
{
PCL_ERROR("Could not read the file");
return;
}
std::cout<<"Loaded"<<cloud->width * cloud->height
<<"data points from filename with the following fields: "
<<std::endl;
for(size_t i = 0; i < cloud->points.size(); ++i)
std::cout << " " << cloud->points[i].x
<< " " << cloud->points[i].y
<< " " << cloud->points[i].z << std::endl;
}
pointcloud_reader_node.cpp
#include <ros/ros.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include "../map_ros/include/cloud.h"
using namespace std;
int main()
{
std::string fstring = "/home/to/Desktop/file.pcd";
Cloud p;
p.readPCloud(fstring); // <-- Error Here
return 0;
}
Also for completeness I am adding the CMake file below:
cmake_minimum_required(VERSION 2.8.3)
project(map_ros)
add_compile_options(-std=c++11)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
find_package(catkin REQUIRED COMPONENTS
// ....
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS
// ......
)
###########
## Build ##
###########
include_directories(${catkin_INCLUDE_DIRS})
add_executable(pointcloud_reader_node src/pointcloud_reader_node.cpp ${SRCS})
target_link_libraries(pointcloud_reader_node ${catkin_LIBRARIES})

I have figured out the problem to my question some time ago but wanted to share it in case someone has my same problem.
So there were two issues coming at the same time that made me think it was a CMake problem only:
1) catkin_make was not properly compiling not because of CMake as I thought for a long time, but because the cache file catkin_ws.workspace was causing problem to CMake itself. So the first solution to this problem was to erase the cache file catkin_ws.workspace and do a fresh compile. All CMake issues disappeared.
2) Second problem: The correct pseudo code for reading the point-cloud it was like:
main()
{
init node
create pointcloud publisher
create rate object with 1 second duration
load point cloud from file
while(ros::ok())
{
rate.sleep
publish point cloud message
}
}
And I realized nothing was being published on the input and the callback was executed.
Below the complete code that reads point-cloud from file and gives an output of all points to a .txt file. I hope this can be helpful to anyone who may encounter this problem:
test.cpp
#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl/io/pcd_io.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
void loadFromFile(std::string filename)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if(pcl::io::loadPCDFile<pcl::PointXYZ> (filename, *cloud) == -1) // load point cloud file
{
PCL_ERROR("Could not read the file");
return;
}
std::cout<<"Loaded"<<cloud->width * cloud->height
<<"data points from /home/to/Desktop/point_cloud/yourFile.pcd with the following fields: "
<<std::endl;
// Write entire point clouds to a .txt file
std::ofstream myfile;
myfile.open ("/home/to/Desktop/exampleCloud.txt");
if (myfile.is_open()) {
for(size_t i = 0; i < cloud->points.size(); ++i)
myfile << " " << cloud->points[i].x
<< " " << cloud->points[i].y
<< " " << cloud->points[i].z << std::endl;
myfile.close();
}
}
int main (int argc, char** argv)
{
// Initialize ROS
ros::init (argc, argv, "pcl_tutorial_cloud");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<sensor_msgs::PointCloud2>("output", 1000);
ros::Rate loop_rate(1);
loadFromFile("/home/to/Desktop/yourFile.pcd");
int count = 0;
while(ros::ok())
{
sensor_msgs::PointCloud2 pcloud2;
pub.publish(pcloud2);
ros::spinOnce();
loop_rate.sleep();
count ++;
}
return 0;
}
Here is the result after running :
1) catkin_make
2) rosrun yourProject test

Related

How to compile/run a cpp file in mac

I downloaded a webcam_face_pose_ex.cpp file from GitHub and now i want to compile and run it on my mac.
#include <dlib/opencv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing/render_face_detections.h>
#include <dlib/image_processing.h>
#include <dlib/gui_widgets.h>
#include <X11/Xlib.h>
using namespace dlib;
using namespace std;
int main()
{
try
{
cv::VideoCapture cap(0);
if (!cap.isOpened())
{
cerr << "Unable to connect to camera" << endl;
return 1;
}
image_window win;
// Load face detection and pose estimation models.
frontal_face_detector detector = get_frontal_face_detector();
shape_predictor pose_model;
deserialize("shape_predictor_68_face_landmarks.dat") >> pose_model;
// Grab and process frames until the main window is closed by the user.
while(!win.is_closed())
{
// Grab a frame
cv::Mat temp;
if (!cap.read(temp))
{
break;
}
// Turn OpenCV's Mat into something dlib can deal with. Note that this just
// wraps the Mat object, it doesn't copy anything. So cimg is only valid as
// long as temp is valid. Also don't do anything to temp that would cause it
// to reallocate the memory which stores the image as that will make cimg
// contain dangling pointers. This basically means you shouldn't modify temp
// while using cimg.
cv_image<bgr_pixel> cimg(temp);
// Detect faces
std::vector<rectangle> faces = detector(cimg);
// Find the pose of each face.
std::vector<full_object_detection> shapes;
for (unsigned long i = 0; i < faces.size(); ++i)
shapes.push_back(pose_model(cimg, faces[i]));
// Display it all on the screen
win.clear_overlay();
win.set_image(cimg);
win.add_overlay(render_face_detections(shapes));
}
}
catch(serialization_error& e)
{
cout << "You need dlib's default face landmarking model file to run this example." << endl;
cout << "You can get it from the following URL: " << endl;
cout << " http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2" << endl;
cout << endl << e.what() << endl;
}
catch(exception& e)
{
cout << e.what() << endl;
}
}
I tried g++ webcam_face_pose_ex.cpp command but I get:
webcam_face_pose_ex.cpp:30:10: fatal error: 'dlib/opencv.h' file not found
#include <dlib/opencv.h>
^~~~~~~~~~~~~~~
1 error generated.
Was Wondering what I could do to fix this?
The Example File Is Not Meant to be Compiled Using g++
Read the following to learn a bit about the -I flag and #include statements:
The webcam_face_pose_ex.cpp is part of a larger project and you won't be able to compile it on its own because it depends on other files. The #include directive specifies that in order to compile this program, code from the file specified by #includemust be compiled first. This means the entire dlib must be downloaded before compiling webcam_face_pose_ex.cpp. This project also requires opencv2 so we can download it and place the opencv2 folder in the dlib project folder.
Now we can open terminal and change directory into the dlib project folder and compile the file using the following command:
g++ -I. examples/webcam_face_pose_ex.cpp
Note we're specifying the directory of where to find the files specified by #include using the -I parameter as -I. this means to search the current working directory for the files. There it will find the dlib folder and dlib/opencv.h.
How ever, this isn't enough. When you execute the command, you'll encounter an error opencv2/opencv_modules.hpp: No such file or directory.
Solution
The dlib project documentation states that the examples should be built using cmake. Make sure to use cmake to compile the examples.

Correct way to make library with priv / public header and pass cv::Mat

I need to make a .so or .a library and different headers, one of them to be shared with users to compile my main program (and link, in the code, processmatinlibrary_pub.h) and other to use in definitions and separated to the main code (processmatinlibrary.h).
When I use the public header (whitout some private definitions of methods), some times, depending on the structure of my program, I get segmentation faults or opencv assertions, below I paste my code, it could be dowloaded from https://github.com/eld1e6o/TestErrorOnLibrary
Here is my code and some comments
Files to create my main program, that uses functions on my library
This is the main function, I use it to check the library with public header
I get some segmentation faults depending on the structure of my program
I can force errors commenting #defines
#define _MAKE_ASSERT_OPENCV 1
#define _MAKE_SEGFAULT_ 1
*If I change the public header to the private header, I have not problems:
#include "processmatinlibrary.h" it works but the headers are not cshared
Instead of
#include "processmatinlibrary_pub.h"
It seems that is a stack problem and I need to define the library or the headers in the right way
Main.cpp
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include "processmatinlibrary_pub.h" //If I change this header to #include "processmatinlibrary.h" it works but the headers are not cshared
using namespace std;
using namespace cv;
#define _MAKE_ASSERT_OPENCV 1
//#define _MAKE_SEGFAULT_ 1
void testEmpty(cv::Mat test_img, std::string msg)
{
cout << "* Check empty " << msg ;
if(test_img.empty())
{
cout << ": Image is Empty " << endl;
exit(1);
}
else cout << ": Image is not empty " << endl;
}
int main(int argc, char* argv[])
{
// Classify and get probabilities
Mat test_img = imread(argv[1], CV_LOAD_IMAGE_COLOR);
testEmpty(test_img, "After load image");
cv::resize(test_img, test_img, cv::Size(256, 256));
cout << " After resize " << endl;
testEmpty(test_img, "Before initialize library ");
ProcessMatInLibrary matToLibrary;
#ifdef _MAKE_SEGFAULT_
return 0; // If I comment this line, I got a segmentation fault: Segmentation Fault (`core' generated)
#endif
testEmpty(test_img, "After initialize library ");
bool b = matToLibrary.flip(test_img);
testEmpty(test_img, "After use function in library ");
cout << "In main " << endl;
/*
* If I define _MAKE_ASSERT_OPENCV, I got errors
OpenCV(3.4.1) Error: Assertion failed (0 <= _dims && _dims <= 32) in setSize, file /home/diego/Code/opencv/modules/core/src/matrix.cpp, line 209
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(3.4.1) /home/diego/Code/opencv/modules/core/src/matrix.cpp:209: error: (-215) 0 <= _dims && _dims <= 32 in function setSize
*/
#ifndef _MAKE_ASSERT_OPENCV
imshow("Test before close", test_img); //If i comment this two lines, I got segmentation faults (OpenCV exception)
waitKey(0);
#endif
}
processmathlibrary_pub.h
This is my public header, used to define functions as publics
#ifndef PROCESSMATINLIBRARY_H
#define PROCESSMATINLIBRARY_H
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui.hpp>
class ProcessMatInLibrary
{
public:
ProcessMatInLibrary();
bool flip(cv::Mat image);
bool myTest(cv::Mat one);
};
#endif // PROCESSMATINLIBRARY_H
Files to create my library
processmathinlibrary.cpp
#include "processmatinlibrary.h"
using namespace std;
using namespace cv;
#include <iostream>
ProcessMatInLibrary::ProcessMatInLibrary()
{
cout << "Initialized " << endl;
}
bool ProcessMatInLibrary::flip(cv::Mat image)
{
cout << "** Inside Library: " << endl;
if(image.empty())
{
cout << " Image is empty" << endl;
return false;
}
cout << " Image is not empty " << endl;
// return false;
Mat image2;
cv::flip(image, image2, 0);
imshow("Image in library", image);
imshow("Image2 in library", image2);
waitKey(0);
cout << "Inside Library: Image is not empty" << endl;
return true;
}
bool ProcessMatInLibrary::myTest(cv::Mat one)
{
one.copyTo(_img);
}
processmathlibrary.h
This is my private header, used to compile my library, it only differs on private declarations
#ifndef PROCESSMATINLIBRARY_LIB_H
#define PROCESSMATINLIBRARY_LIB_H
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui.hpp>
class ProcessMatInLibrary
{
public:
ProcessMatInLibrary();
bool flip(cv::Mat image);
bool myTest(cv::Mat one);
private:
cv::Mat _img;
};
#endif // PROCESSMATINLIBRARY_LIB_H
How to compile all of this
CMakeLists.txt
Note that I have defined other PATH for OpenCV library, maybe there is an error to compile in the default PATH, I cannot check that
find_package(OpenCV REQUIRED) is working
cmake_minimum_required(VERSION 2.8.12)
project(test_pub_priv)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -O3 -std=c++11")
#set(OpenCV_INCLUDE_DIRS "./include/")
find_package(OpenCV REQUIRED)
message(" ** Test with public private libraries ** ")
include_directories(${OpenCV_INCLUDE_DIRS})
aux_source_directory(./src SRC_LIST)
include_directories(./hpp SRC_LIST)
FILE(GLOB_RECURSE LibFiles "./hpp/*.h")
add_custom_target(headers SOURCES ${LibFiles})
add_library(myFramework ${SRC_LIST} )
add_executable(test_pub_priv ./examples/Main.cpp)
target_link_libraries(test_pub_priv ${OpenCV_LIBS} myFramework)
My question and problem is: What is the right way to pass a cv::Mat as argument trough library with one private header to the library and other (public header) to be shared?
Complete code can be seen here:
https://github.com/eld1e6o/TestErrorOnLibrary
Thanks!

c++ loading dylib functions at runtime error

So I'm trying to load a .dylib file at runtime in c++ and calling a function within it. It does not seem to be any problem loading the file but when i try to create a function-pointer to the "print" function it's result is NULL.
Here is my code:
/* main.cpp */
#include <iostream>
#include <string>
#include <dlfcn.h>
#include "test.hpp"
int main(int argc, const char * argv[]) {
std::string path = argv[0];
std::size_t last = path.find_last_of("/");
// get path to execution folder
path = path.substr(0, last)+"/";
const char * filename = (path+"dylibs/libtest.dylib").c_str();
// open libtest.dylib
void* dylib = dlopen(filename, RTLD_LAZY);
if (dylib == NULL) {
std::cout << "unable to load " << filename << " Library!" << std::endl;
return 1;
}
// get print function from libtest.dylib
void (*print)(const char * str)= (void(*)(const char*))dlsym(dylib, "print");
if (print == NULL) {
std::cout << "unable to load " << filename << " print function!" << std::endl;
dlclose(dylib);
return 2;
}
// test the print function
print("Herro Word!");
dlclose(dylib);
return 0;
}
test dylib headerfile
/* test.hpp */
#ifndef test_hpp
#define test_hpp
void print(const char * str);
#endif
the dylib c++ file
#include <iostream>
#include "test.hpp"
void print(const char * str) {
std::cout << str << std::endl;
}
the output when running is:
unable to load /Users/usr/Library/Developer/Xcode/DerivedData/project/Build/Products/Debug/dylibs/libtest.dylib print function!
Program ended with exit code: 2
I am quite new to c++ and have never loaded dylibs before. Any help would be much appreciated!
Try qualifying the print function declaration with extern "C" to get around the name mangling that is likely going on.
Here's a nice article on the topic: http://www.tldp.org/HOWTO/C++-dlopen/theproblem.html (solution discussion on page following)

tesseract APIs with OpenMp: sometimes segmentation faults, sometimes not

I'm writing a small demo with tesseract APIs to run in parallel via OpenMp; it is basically an example taken from tesseract APIs usage page, with some openmp flavour added on it.
The executable takes two arguments: a tif file and an integer for the page to be ocrized.
I'm compiling like this:
clang-omp++ -o tessapi-quality tessapi-quality.cpp -<TESSERACT_FLAGS> -O3 -fopenmp -g.
The problem I'm facing is that it works most of the time, but one over five - more or less - it throws a seg fault.
I tried and debug with gdb, but couldn't find out, 'cause it dies sometimes on a tesseract baseapi function, sometimes on another.
Unfortunately I cannot install valgrind on the machine where I'm working on now.
I'm aware that it's not handy to be tested from anyone who has not tesseract installed, but maybe I'm missing something big in the code and you can help me just taking a look.
This is the code:
#include <stdlib.h>
#include <iostream>
#include <leptonica/allheaders.h>
#include <omp.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <tesseract/api/baseapi.h>
void getCompImage(const char* filename, int page){
Pix* image;
Pixa** pixa;
int** blockids;
image = pixReadTiff(filename, page);
int num_threads = 4;
omp_set_num_threads(num_threads);
#pragma omp parallel
{
tesseract::TessBaseAPI *papi = new tesseract::TessBaseAPI();
if (papi->Init(NULL, "eng")) {
#pragma omp critical
{
std::cout << "Could not initialize tesseract " << '\n';
}
exit(1);
}
papi->SetImage(image);
Boxa* boxes = papi->GetComponentImages(tesseract::RIL_TEXTLINE, true, pixa, blockids);
#pragma omp barrier
#pragma omp for schedule(static)
for (int i = 0; i < boxes->n; i++) {
BOX* box = boxaGetBox(boxes, i, L_CLONE);
papi->SetRectangle(box->x, box->y, box->w, box->h);
char* ocrResult = papi->GetUTF8Text();
int my_thread = omp_get_thread_num();
#pragma omp critical
{
std::cout << "Thread: " << my_thread << " Page: " << page << " Box[" << i << "] text: " << ocrResult << "\n";
}
}
// Destroy used object and release memory
papi->End();
}
pixDestroy(&image);
}
int main(int argc, char *argv[])
{
if (argc != 3){
printf("Type the (tiff) file name to OCRize\n"
"Then the page in the file to OCRize (first page=0, second=1 etc..)\n\n");
exit(-1);
}
int page = atoi(argv[2]);
getCompImage(argv[1], page);
return 0;
}

mkdir() returns -1 when launched through Finder

I have a simple program that makes a directory when it is executed:
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(){
if(int a = mkdir("abc",0700)){
std::cout << "Failed to create: " << a << std::endl;
}
else{
std::cout << "Created." << std::endl;
}
}
It behaves differently for two different use cases:
Running the compiled binary through Terminal
Output: Created.
Launching this program via Finder with double click.
Output: Failed to create: -1
How do I make this so that launching this program via Finder creates the folder abc without using Cocoa framework (compiles with g++ only)?
Thanks to Wooble for pointing it out in the comment section that the problem is due to the working directory. When I launched it through Finder, the current working directory was my home directory.
Below is how I address the problem:
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libproc.h>
int main(int argc, char** argv){
// Gets and prints out the current directory
char cwd[1024];
getcwd(cwd, sizeof(cwd));
std::cout << "Current Working Directory: " << cwd << std::endl;
// Above is not necessary
// Changes working directory to directory that contains executable
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
if(proc_pidpath (getpid(), pathbuf, sizeof(pathbuf)) > 0){ // Gets the executable path
std::string s(pathbuf);
s = s.substr(0,s.find_last_of('/')); // Removes executable name from path
std::cout << "Executable Path: " << s << std::endl;
chdir(s.c_str()); // Changes working directory
}
if(int a = mkdir("abc",0700)){
std::cout << "Failed to create: " << a << std::endl;
}
else{
std::cout << "Created." << std::endl;
}
}