diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e8794fb4c1fefbc23ad65b2dfa8b3052db9663b..de2f6ef5b3dd9cdb90cdd0bad765687258995717 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@ if(COMMAND cmake_policy)
 endif(COMMAND cmake_policy)
 
 # The project name and the type of project
-PROJECT(wolf)
+PROJECT(laser_scan_utils)
 
 SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)
 SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib)
diff --git a/Findlaser_scan_utils.cmake b/Findlaser_scan_utils.cmake
index e54db6d717b09606e4bc3a60f281b614e56f1fbb..1af65b67e1dcd1d601bfcb19eabb40d14ab4a105 100644
--- a/Findlaser_scan_utils.cmake
+++ b/Findlaser_scan_utils.cmake
@@ -1,26 +1,26 @@
 #edit the following line to add the librarie's header files
 FIND_PATH(
-    wolf_INCLUDE_DIR
-    NAMES wolf.h
+    laser_scan_utils_INCLUDE_DIR
+    NAMES scan_params.h corners.h
     PATHS /usr/local/include/iri-algorithms
 )
 
 FIND_LIBRARY(
-    wolf_LIBRARY
-    NAMES wolf
+    laser_scan_utils_LIBRARY
+    NAMES laser_scan_utils
     PATHS /usr/lib /usr/local/lib /usr/local/lib/iri-algorithms) 
 
-IF (wolf_INCLUDE_DIR AND wolf_LIBRARY)
-   SET(wolf_FOUND TRUE)
-ENDIF (wolf_INCLUDE_DIR AND wolf_LIBRARY)
+IF (laser_scan_utils_INCLUDE_DIR AND laser_scan_utils_LIBRARY)
+   SET(laser_scan_utils_FOUND TRUE)
+ENDIF (laser_scan_utils_INCLUDE_DIR AND laser_scan_utils_LIBRARY)
 
-IF (wolf_FOUND)
-   IF (NOT wolf_FIND_QUIETLY)
-      MESSAGE(STATUS "Found wolf: ${wolf_LIBRARY}")
-   ENDIF (NOT wolf_FIND_QUIETLY)
-ELSE (wolf_FOUND)
-   IF (wolf_FIND_REQUIRED)
-      MESSAGE(FATAL_ERROR "Could not find wolf")
-   ENDIF (wolf_FIND_REQUIRED)
-ENDIF (wolf_FOUND)
+IF (laser_scan_utils_FOUND)
+   IF (NOT laser_scan_utils_FIND_QUIETLY)
+      MESSAGE(STATUS "Found laser_scan_utils: ${laser_scan_utils_LIBRARY}")
+   ENDIF (NOT laser_scan_utils_FIND_QUIETLY)
+ELSE (laser_scan_utils_FOUND)
+   IF (laser_scan_utils_FIND_REQUIRED)
+      MESSAGE(FATAL_ERROR "Could not find laser_scan_utils")
+   ENDIF (laser_scan_utils_FIND_REQUIRED)
+ENDIF (laser_scan_utils_FOUND)
 
diff --git a/README.txt b/README.txt
index e3c2f1883d36b0e4c1cb030151b78ef863de609e..a7c96da94dba84fbd320adef494ce7708cf45de5 100644
--- a/README.txt
+++ b/README.txt
@@ -1 +1 @@
-A Toolbox of 2D laser scan utilities, made at IRI (www.iri.upc.edu)
+A Toolbox with utilities for 2D laser scan processing, made at IRI (www.iri.upc.edu)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 16c175dcd0e2dc0f7469be464e633167d81c1d7e..882334166990292e128af0014a0d02ac00304d73 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,20 +1,13 @@
 
-#Start WOLF build
-MESSAGE("Starting WOLF CMakeLists ...")
+MESSAGE("Starting laser_scan_utils CMakeLists ...")
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 
 #find dependencies. 
-FIND_PACKAGE(Ceres QUIET) #Ceres is not required
-IF(Ceres_FOUND)
-    MESSAGE("Ceres Library FOUND: ceres_wrapper will be built.")
-ENDIF(Ceres_FOUND)
-
-FIND_PACKAGE(faramotics QUIET) #faramotics is not required
+FIND_PACKAGE(faramotics QUIET) #faramotics is only required for some tests
 IF(faramotics_FOUND)
 	FIND_PACKAGE(GLUT REQUIRED)
 	FIND_PACKAGE(pose_state_time REQUIRED)
-	FIND_LIBRARY(Assimp_LIBRARIES assimp HINTS /usr/local/lib NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH)
-    MESSAGE("Faramotics Library FOUND: test_ceres_laser will be built.")
+    MESSAGE("Faramotics Library FOUND: Tests requiring it will be built.")
 ENDIF(faramotics_FOUND)
 
 #include directories
@@ -22,87 +15,25 @@ INCLUDE_DIRECTORIES(.)
 IF(Ceres_FOUND)
     INCLUDE_DIRECTORIES(${CERES_INCLUDE_DIRS})
 ENDIF(Ceres_FOUND)
+IF(faramotics_FOUND)
+    INCLUDE_DIRECTORIES(${faramotics_INCLUDE_DIRS})
+ENDIF(faramotics_FOUND)
 
 #headers
 SET(HDRS
-    capture_base.h
-    capture_relative.h
-    capture_gps_fix.h
-    capture_laser_2D.h
-    capture_odom_2D.h
-    constraint_base.h
-    constraint_sparse.h
-    constraint_gps_2D.h
-    constraint_odom_2D_theta.h
-    constraint_odom_2D_complex_angle.h
-    feature_base.h
-    feature_corner_2D.h
-    feature_gps_fix.h
-    feature_odom_2D.h
-    frame_base.h
-    landmark_base.h
-    landmark_corner_2D.h
-    map_base.h
-    node_base.h
-    node_terminus.h
-    node_linked.h
-    sensor_base.h
-    sensor_laser_2D.h
-    sensor_odom_2D.h
-    sensor_gps_fix.h
-    state_base.h
-    state_point.h
-    state_complex_angle.h
-    time_stamp.h
-    trajectory_base.h
-    wolf.h
-    wolf_problem.h)
-    
+    corners.h
+    geometry.h
+    scan_params.h
+    types.h)
+
 #sources
 SET(SRCS
-    capture_base.cpp
-    capture_relative.cpp
-    capture_gps_fix.cpp
-    capture_laser_2D.cpp
-    capture_odom_2D.cpp
-    constraint_base.cpp
-    feature_base.cpp
-    feature_corner_2D.cpp
-    feature_gps_fix.cpp
-    feature_odom_2D.cpp
-    frame_base.cpp
-    landmark_base.cpp
-    landmark_corner_2D.cpp
-    map_base.cpp
-    node_base.cpp
-    node_terminus.cpp
-    sensor_base.cpp
-    sensor_laser_2D.cpp
-    sensor_odom_2D.cpp
-    sensor_gps_fix.cpp
-    state_base.cpp
-    state_complex_angle.cpp
-    time_stamp.cpp
-    trajectory_base.cpp
-    wolf_problem.cpp)
-
-#optional HDRS and SRCS
-IF (Ceres_FOUND)
-    SET(SRCS ${SRCS} ceres_wrapper/complex_angle_parametrization.cpp)
-    SET(HDRS ${HDRS} ceres_wrapper/complex_angle_parametrization.h)
-    SET(SRCS ${SRCS} ceres_wrapper/ceres_manager.cpp)
-    SET(HDRS ${HDRS} ceres_wrapper/ceres_manager.h)
-ENDIF(Ceres_FOUND)
-
+    corners.cpp
+    geometry.cpp)
+    
 # create the shared library
 ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
 
-#Link the created library with ceres
-IF (Ceres_FOUND)
-    TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${CERES_LIBRARIES})
-ENDIF(Ceres_FOUND)
-
-
 #install library
 INSTALL(TARGETS ${PROJECT_NAME}
       RUNTIME DESTINATION bin
@@ -113,7 +44,7 @@ INSTALL(TARGETS ${PROJECT_NAME}
 INSTALL(FILES ${HDRS} 
       DESTINATION include/iri-algorithms)
 
-INSTALL(FILES ../Findwolf.cmake DESTINATION ${CMAKE_ROOT}/Modules/)
+INSTALL(FILES ../Findlaser_scan_utils.cmake DESTINATION ${CMAKE_ROOT}/Modules/)
 
 #Build examples & tests
 MESSAGE("Building examples and tests.")
diff --git a/src/corners.cpp b/src/corners.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..900d42e3e7aa0d2c010f4523614515b8005fc163
--- /dev/null
+++ b/src/corners.cpp
@@ -0,0 +1,256 @@
+
+#include "corners.h"
+
+unsigned int laserscanutils::extractCorners(const laserscanutils::ScanParams & _params, const ExtractCornerParams & _alg_params, const Eigen::VectorXs & _ranges, std::list<Eigen::Vector4s> & _corner_list)
+{
+    //local variables
+    Eigen::MatrixXs points(3,_ranges.size());
+    double azimuth, cos_theta, theta;
+    Eigen::Vector3s corner;
+    Line line;
+    std::list<Line> line_list;
+    std::list<Line>::iterator line_it1, line_it2;
+    std::queue<unsigned int> jumps;
+
+    //init random generator
+    std::default_random_engine generator(1);
+    std::uniform_int_distribution<int> rand_window_overlapping(1,_alg_params.segment_window_size);
+    
+    //convert range polar data to cartesian points.
+    for (unsigned int ii = 0; ii<_ranges.size(); ii++)
+    {
+        azimuth = _params.angle_max_ - _params.angle_step_ * ii;
+        //std::cout << "  azimuth: " << azimuth << std::endl;
+        points.col(ii) << _ranges(ii)*cos(azimuth), _ranges(ii)*sin(azimuth), 1; //points.row0-> x coordinate, points.row1->y coordinate
+
+        if (ii > 0 && fabs(_ranges(ii)-_ranges(ii-1)) > _alg_params.max_distance)
+        {
+            // store jumps
+            jumps.push(ii);
+            // consider jumps as a corners
+            if (_ranges(ii) < _ranges(ii-1))
+                _corner_list.push_back(Eigen::Vector4s(points(0,ii),points(1,ii),0,0)); // TODO: compute orientation
+            else
+                _corner_list.push_back(Eigen::Vector4s(points(0,ii-1),points(1,ii-1),0,0));// TODO: compute orientation
+        }
+    }
+
+    //find line segments running over the scan
+    for (unsigned int ii = _alg_params.segment_window_size-1; ii<_ranges.size(); ii=ii+rand_window_overlapping(generator) )
+    {
+        unsigned int i_from = ii - _alg_params.segment_window_size + 1;
+
+        // update the jump to be checked
+        while (!jumps.empty() && i_from > jumps.front())
+            jumps.pop();
+
+        // check if there is a jump inside the window (not fitting if it is the case)
+        if (jumps.front() > i_from && jumps.front() <= ii)
+            continue;
+
+        //Found the best fitting line over points within the window [ii - segment_window_size + 1, ii]
+        //fitLine(i_from, ii, points, line);
+        fitLine(points.block(0,i_from, 3, ii-i_from+1), line);
+
+        //if error below stdev, add line to result set
+        if ( line.error < _params.range_std_dev_*_alg_params.k_sigmas )
+        {
+            line.first = i_from; 
+            line.last = ii;
+            line_list.push_back(line);
+        }
+    }
+
+    //std::cout << "Lines fitted: " << line_list.size() << std::endl;
+
+    // concatenating and corners only if more than 1 line
+    if ( line_list.size() > 1 )
+    {
+        // concatenate lines
+        line_it1 = line_list.begin();
+        line_it2 = line_it1;
+        line_it2 ++;
+        while ( line_it1 != line_list.end() )
+        {
+            // last of current line and first of next line too far
+            if (line_it2->first > line_it1->last + _alg_params.max_beam_distance)
+            {
+                //std::cout << "lines too far:\nlast of current: " << line_it1->last << " first of next: " << line_it2->first << std::endl;
+                line_it1 ++;
+                line_it2 = line_it1;
+                line_it2 ++;
+            }
+            else
+            {
+                //compute angle between lines 1 and 2
+                cos_theta = (line_it1->vector).dot(line_it2->vector) / ( (line_it1->vector).norm()*(line_it2->vector).norm() );
+                theta = acos (cos_theta);
+
+                //TODO: fabs? acos returns [0 PI]
+                if (theta > M_PI/2)
+                    theta -= M_PI;
+    //            std::cout << std::endl << "cos_theta: " << cos_theta << std::endl <<
+    //                                      "theta: " << theta << std::endl <<
+    //                                      "*index_it1: " << *index_it1 << std::endl <<
+    //                                      "*index_it2: " << *index_it2 << std::endl;
+    //                                       "   (*line_it1).dot(*line_it2): " << (*line_it1).dot(*line_it2) << std::endl <<
+    //                                       "   (*line_it1).norm()*(*line_it2).norm(): " << (*line_it1).norm()*(*line_it2).norm() << std::endl;
+
+
+                //Check angle threshold and consecutiveness of lines in the scan
+                if ( fabs(theta) < _alg_params.theta_max_parallel )
+                {
+                    Line new_line;
+                    //fitLine(line_it1->first, line_it2->last, points, new_line);
+                    fitLine(points.block(0,line_it1->first, 3, line_it2->last-line_it1->first+1), new_line);
+                    if ( new_line.error < _params.range_std_dev_*_alg_params.k_sigmas )
+                    {
+                        new_line.first = line_it1->first;
+                        new_line.last = line_it2->last;
+                        *line_it1 = new_line;
+                        line_it2 = line_list.erase(line_it2);
+
+//                      std::cout << "lines concatenated" << std::endl;
+//                      std::cout << "line 1: " << std::endl << line_it1->first << std::endl <<
+//                           line_it1->last << std::endl <<
+//                           line_it1->vector.transpose() << std::endl <<
+//                           line_it1->error << std::endl;
+//                      std::cout << "line 2: " << std::endl << line_it2->first << std::endl <<
+//                           line_it2->last << std::endl <<
+//                           line_it2->vector.transpose() << std::endl <<
+//                           line_it2->error << std::endl;
+//                      std::cout << "line resultant: "<< std::endl << new_line.first << std::endl <<
+//                          new_line.last << std::endl <<
+//                          new_line.vector.transpose() << std::endl <<
+//                          new_line.error << std::endl;
+                    }
+                    else
+                    {
+                        //update iterators
+                        line_it1 ++;
+                        line_it2 = line_it1;
+                        line_it2 ++;
+                    }
+                }
+                else
+                {
+                    //update iterators
+                    line_it1 ++;
+                    line_it2 = line_it1;
+                    line_it2 ++;
+                }
+            }
+        }
+
+        //std::cout << "Lines after concatenation: " << line_list.size() << std::endl;
+
+        // find corners over the line list
+        line_it1 = line_list.begin();
+        line_it2 = line_it1;
+        line_it2 ++;
+        while ( line_it1 != line_list.end() )
+        {   
+            // last of current line and first of next line too far
+            if (line_it2->first > line_it1->last + _alg_params.max_beam_distance)
+            {
+                //std::cout << "lines too far:\nlast of current: " << line_it1->last << " first of next: " << line_it2->first << std::endl;
+                line_it1 ++;
+                line_it2 = line_it1;
+                line_it2 ++;
+            }
+            else
+            {
+                //compute angle between lines 1 and 2
+                cos_theta = (line_it1->vector).dot(line_it2->vector) / ( (line_it1->vector).norm()*(line_it2->vector).norm() );
+                theta = acos (cos_theta);
+
+                //TODO: fabs? acos returns [0 PI]
+                if (theta > M_PI/2)
+                    theta -= M_PI;
+
+//              std::cout << std::endl << "cos_theta: " << cos_theta << std::endl <<
+//                                        "theta: " << theta << std::endl <<
+//                                        "line 1: " << line_it1->first << "-" << line_it1->last << std::endl <<
+//                                        "line 2: " << line_it2->first << "-" << line_it2->last << std::endl <<
+//                                        "   (*line_it1).dot(*line_it2): " << (line_it1->vector).dot(line_it2->vector) << std::endl <<
+//                                        "   (*line_it1).norm()*(*line_it2).norm(): " << (line_it1->vector).norm()*(line_it2->vector).norm() << std::endl;
+
+
+                //Check angle threshold and consecutiveness of lines in the scan
+                if ( fabs(theta) > _alg_params.theta_min ) //TODO: fabs? acos returns [0 PI]
+                {
+                    corner = (line_it1->vector).cross(line_it2->vector); //cross product between lines is the intersection
+                    corner = corner / corner(2); //normalize point to set last component to 1
+
+                    // Check if the corner is close to both lines ends
+                    if ( ( (points.col(line_it1->last) - corner).head(2).norm() < _alg_params.max_distance )
+                        && 
+                         ( (points.col(line_it2->first) - corner).head(2).norm() < _alg_params.max_distance ) )
+                    {
+                        Eigen::Vector3s v1 = (points.col(line_it1->first) - corner);
+                        Eigen::Vector3s v2 = (points.col(line_it2->last) - corner);
+                        v1 /= v1.norm();
+                        v2 /= v2.norm();
+
+                        //corner orientation
+                        if (v1(0) * v2(1) > v1(1) * v2(0))
+                            corner(2) = asin (v1(1));
+                        else
+                            corner(2) = asin (v2(1));
+
+//                      std::cout << "Detected corner!" << std::endl <<
+//                                   "\tcorner: " << corner.transpose() << std::endl <<
+//                                   "\tline 1 point: " << points.col(line_it1->first).transpose() << std::endl <<
+//                                   "\tline 2 point: " << points.col(line_it2->last).transpose() << std::endl <<
+//                                   "\tv1: " << v1.transpose() << std::endl <<
+//                                   "\tv2: " << v2.transpose() << std::endl;
+
+                        _corner_list.push_back(Eigen::Vector4s(corner(0),corner(1),corner(2),theta));
+                    }
+                }
+
+                //update iterators
+                if (line_it2 != line_list.end() )
+                    line_it2 ++;
+                else
+                {
+                    line_it1 ++;
+                    line_it2 = line_it1;
+                    line_it2 ++;
+                }
+            }
+        }
+    }
+
+    //std::cout << "Corners extracted: " << _corner_list.size() << std::endl;
+
+    // Erase duplicated corners
+    if ( _corner_list.size() > 1 )
+    {
+        // concatenate lines
+        std::list<Eigen::Vector4s>::iterator corner_it1 = _corner_list.begin();
+        std::list<Eigen::Vector4s>::iterator corner_it2 = corner_it1;
+        corner_it2 ++;
+        while ( corner_it1 != _corner_list.end() )
+        {
+            // Check if two corners are close enough
+            if ( (*corner_it1 - *corner_it2).head(2).norm() < _alg_params.max_distance )
+            {
+                // TODO: keep the one with larger lines
+                // compute the mean
+                *corner_it1 = (*corner_it1 + *corner_it2) / 2;
+                corner_it2 = _corner_list.erase(corner_it2);
+            }
+            else
+            {
+                corner_it1 ++;
+                corner_it2 = corner_it1;
+                corner_it2 ++;
+            }
+        }
+    }
+
+    //std::cout << "Corners after removing duplicates: " << _corner_list.size() << std::endl;
+
+    return _corner_list.size();
+}
diff --git a/src/corners.h b/src/corners.h
new file mode 100644
index 0000000000000000000000000000000000000000..e9597873ee71b5e88db08c9d72bca77f5bd5e91a
--- /dev/null
+++ b/src/corners.h
@@ -0,0 +1,50 @@
+
+#ifndef CORNERS_H_
+#define CORNERS_H_
+
+//std
+#include <list>
+#include <queue>
+#include <random>
+
+// Eigen ingludes
+#include <eigen3/Eigen/Geometry>
+
+//laserscanutils
+#include "types_laser_scan_utils.h"
+#include "scan_params.h"
+#include "geometry.h"
+
+namespace laserscanutils
+{
+    /** \brief Set of tunning parameters
+     * 
+     * Set of tunning parameters for corner extraction
+     * 
+     */
+    struct ExtractCornerParams
+    {
+        unsigned int segment_window_size; //number of points to fit lines in the first pass
+        ScalarT theta_min; //minimum theta between consecutive segments to detect corner. PI/6=0.52
+        ScalarT theta_max_parallel; //maximum theta between consecutive segments to fuse them in a single line.
+        ScalarT k_sigmas;//How many std_dev are tolerated to count that a point is supporting a line
+        unsigned int max_beam_distance;//max number of beams of distance between lines to consider corner or concatenation
+        ScalarT max_distance;//max distance between line ends to consider corner or concatenation
+    };
+    
+    /** \brief Extract corners from a given scan
+     * 
+     * Extract corners from a given scan. 
+     * Returns corners as a list of Vector-4, where each corner is parametrized as: 
+     *  - corner(0): x coordinate
+     *  - corner(1): y coordinate
+     *  - corner(2): ...
+     *  - corner(3): ...
+     * 
+     * TODO: use the struct Corner defined  at geometry.h to encode a corner
+     * 
+     */
+    unsigned int extractCorners(const laserscanutils::ScanParams & _params, const ExtractCornerParams & _alg_params, const Eigen::VectorXs & _ranges, std::list<Eigen::Vector4s> & _corner_list);
+}
+#endif
+
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
index 303cde79a90342327eaa65766f73d51034b1f390..741291947b7cd12e5d565a3b6e6da4d26e81dc35 100644
--- a/src/examples/CMakeLists.txt
+++ b/src/examples/CMakeLists.txt
@@ -1,47 +1,5 @@
-# NodeLinked class test
-ADD_EXECUTABLE(test_node_linked test_node_linked.cpp)
-TARGET_LINK_LIBRARIES(test_node_linked ${PROJECT_NAME})
-
-# numeric test
-ADD_EXECUTABLE(test_ceres_wrapper_numeric test_ceres_wrapper_numeric.cpp)
-TARGET_LINK_LIBRARIES(test_ceres_wrapper_numeric ${PROJECT_NAME})
-
-# jet test
-ADD_EXECUTABLE(test_ceres_wrapper_jet test_ceres_wrapper_jet.cpp)
-TARGET_LINK_LIBRARIES(test_ceres_wrapper_jet ${PROJECT_NAME})
-
-# jet individual blocks test
-ADD_EXECUTABLE(test_ceres_wrapper_jet_ind_block test_ceres_wrapper_jet_ind_block.cpp)
-TARGET_LINK_LIBRARIES(test_ceres_wrapper_jet_ind_block ${PROJECT_NAME})
-
-# jet test with 2 sensors
-ADD_EXECUTABLE(test_ceres_wrapper_jet_2_sensors test_ceres_wrapper_jet_2_sensors.cpp)
-TARGET_LINK_LIBRARIES(test_ceres_wrapper_jet_2_sensors ${PROJECT_NAME})
-
-# jet test manager
-ADD_EXECUTABLE(test_ceres_manager test_ceres_manager.cpp)
-TARGET_LINK_LIBRARIES(test_ceres_manager ${PROJECT_NAME})
-
-# Testing a full wolf tree avoiding template classes for NodeLinked derived classes
-ADD_EXECUTABLE(test_ceres_odom_batch test_ceres_odom_batch.cpp)
-TARGET_LINK_LIBRARIES(test_ceres_odom_batch ${PROJECT_NAME})
-
-# Testing a full wolf tree avoiding template classes for NodeLinked derived classes
-ADD_EXECUTABLE(test_ceres_odom_iterative test_ceres_odom_iterative.cpp)
-TARGET_LINK_LIBRARIES(test_ceres_odom_iterative ${PROJECT_NAME})
-
-# Building and populating the wolf tree 
-# ADD_EXECUTABLE(test_wolf_tree test_wolf_tree.cpp)
-# TARGET_LINK_LIBRARIES(test_wolf_tree ${PROJECT_NAME})
-
-# test ceres manager, wolf manager and wolf tree
-ADD_EXECUTABLE(test_ceres_manager_tree test_ceres_manager_tree.cpp)
-TARGET_LINK_LIBRARIES(test_ceres_manager_tree ${PROJECT_NAME})
-
-ADD_EXECUTABLE(test_capture_laser_2D test_capture_laser_2D.cpp)
-TARGET_LINK_LIBRARIES(test_capture_laser_2D ${PROJECT_NAME})
-
+# corner extraction test
 IF(faramotics_FOUND)
-	ADD_EXECUTABLE(test_ceres_laser test_ceres_laser.cpp)
-    TARGET_LINK_LIBRARIES(test_ceres_laser ${GLUT_glut_LIBRARY} ${pose_state_time_LIBRARIES} ${faramotics_LIBRARIES} ${PROJECT_NAME})
+    ADD_EXECUTABLE(test_extract_corners test_extract_corners.cpp)
+    TARGET_LINK_LIBRARIES(test_extract_corners ${GLUT_glut_LIBRARY} ${pose_state_time_LIBRARIES} ${faramotics_LIBRARIES} ${PROJECT_NAME})
 ENDIF(faramotics_FOUND)
\ No newline at end of file
diff --git a/src/examples/test_extract_corners.cpp b/src/examples/test_extract_corners.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..25bb5d1a54a5544c7c5e83fcacc850c630310c91
--- /dev/null
+++ b/src/examples/test_extract_corners.cpp
@@ -0,0 +1,158 @@
+//std includes
+#include <iostream>
+#include <random>
+
+//GLUT
+#include <GL/glut.h>
+
+//faramotics includes
+#include "faramotics/dynamicSceneRender.h"
+#include "faramotics/rangeScan2D.h"
+#include "btr-headers/pose3d.h"
+
+//laserscanutils
+#include "types_laser_scan_utils.h"
+#include "corners.h"
+
+//namespaces
+using namespace std;
+
+//function to travel around each model
+void motionCampus(unsigned int ii, Cpose3d & pose)
+{
+    if (ii<=40)
+    {
+        //pose.rt.setEuler( pose.rt.head()-2*M_PI/180., pose.rt.pitch(), pose.rt.roll() );
+        pose.pt(0) = pose.pt(0) + 0.1;
+    }
+    if ( (ii>40) && (ii<=80) )
+    {
+        pose.pt(0) = pose.pt(0) + 0.1;
+        pose.rt.setEuler(pose.rt.head(), pose.rt.pitch(), pose.rt.roll() + 0.01);
+    }
+    if ( (ii>80) && (ii<=120) )
+    {
+        pose.pt(0) = pose.pt(0) + 0.1;
+        pose.rt.setEuler(pose.rt.head(), pose.rt.pitch(), pose.rt.roll() - 0.015);
+    }
+    if ( (ii>120) && (ii<=170) )
+    {
+        pose.rt.setEuler( pose.rt.head()+1.8*M_PI/180., pose.rt.pitch(), pose.rt.roll() );
+        pose.moveForward(0.2);
+    }
+    if ( (ii>170) && (ii<=220) )
+    {
+        pose.rt.setEuler( pose.rt.head()-1.8*M_PI/180., pose.rt.pitch(), pose.rt.roll()-0.05*M_PI/180. );
+    }
+    if ( (ii>220) && (ii<=310) ) 
+    {
+        pose.pt(0) = pose.pt(0) + 0.1;
+    }
+    if ( (ii>310) && (ii<=487) ) 
+    {
+        pose.rt.setEuler( pose.rt.head()-1.*M_PI/180., pose.rt.pitch(), pose.rt.roll()+0.1*M_PI/180. );
+        pose.moveForward(0.1);
+    }
+    if ( (ii>487) && (ii<=582) ) 
+    {
+        pose.moveForward(0.2);
+    }
+    if ( (ii>582) && (ii<=700) ) 
+    {
+        pose.pt(2) = pose.pt(2) + 0.001;
+        pose.rt.setEuler( pose.rt.head()-1.*M_PI/180., pose.rt.pitch(), pose.rt.roll());
+        pose.moveForward(0.1);
+    }    
+}
+
+int main(int argc, char** argv)
+{
+	std::cout << "\n ========= Corner extraction test ===========\n";
+
+	// INITIALIZATION ============================================================================================
+
+	// Faramotics stuff
+	CdynamicSceneRender *myRender;
+	CrangeScan2D *myScanner;
+	Cpose3d viewPoint;
+	Cpose3d devicePose(2,8,0.2,0,0,0);
+	vector<float> myScan;
+	string modelFileName("/home/acoromin/dev/br/faramotics/models/campusNordUPC.obj");
+    
+    //laserscanutils
+    laserscanutils::ScanParams scan_params;
+    scan_params.angle_min_ = -M_PI/2;
+    scan_params.angle_max_ = M_PI/2;
+    scan_params.angle_step_ = M_PI/720;
+    scan_params.scan_time_ = 0.01;//not relevant
+    scan_params.range_min_ = 0.1;
+    scan_params.range_max_ = 30;
+    scan_params.range_std_dev_ = 0.01;
+
+    laserscanutils::ExtractCornerParams alg_params;
+    alg_params.segment_window_size = 8;
+    alg_params.theta_min = 0.4;
+    alg_params.theta_max_parallel = 0.1;
+    alg_params.k_sigmas = 3;
+    alg_params.max_beam_distance = 5;
+    alg_params.max_distance = 0.5;
+    
+    //init random generators
+    std::default_random_engine generator(1);
+    std::normal_distribution<laserscanutils::ScalarT> laser_range_noise(0.001, scan_params.range_std_dev_); 
+
+	//glut initialization
+	glutInit(&argc, argv);
+
+    //create a viewer for the 3D model and scan points
+	myRender = new CdynamicSceneRender(1200,700,90*M_PI/180,90*700.0*M_PI/(1200.0*180.0),0.2,100);
+	myRender->loadAssimpModel(modelFileName,true); //with wireframe
+    
+	//create scanner and load 3D model
+	myScanner = new CrangeScan2D(HOKUYO_UTM30LX_180DEG);//HOKUYO_UTM30LX_180DEG
+	myScanner->loadAssimpModel(modelFileName);
+
+	// START TRAJECTORY ============================================================================================
+	for (uint step=1; step < 1000; step++)
+	{
+		// moves the device position
+		motionCampus(step, devicePose);
+
+		//compute scan
+		myScan.clear();
+		myScanner->computeScan(devicePose,myScan);
+		vector<double> myScanDoubles(myScan.begin(), myScan.end());
+		Eigen::Map<Eigen::VectorXs> scan_reading(myScanDoubles.data(), 720);
+
+		//draws the device frame, scan hits and depth image
+		myRender->drawPoseAxis(devicePose);
+		myRender->drawScan(devicePose,myScan,180.*M_PI/180.,90.*M_PI/180.); //draw scan
+
+		// extract corners
+		std::list<Eigen::Vector4s> corner_list;
+		std::vector<double> corner_vector;
+		laserscanutils::extractCorners(scan_params, alg_params, scan_reading, corner_list);
+        
+        //draw corners
+		for (std::list<Eigen::Vector4s>::iterator corner_it = corner_list.begin(); corner_it != corner_list.end(); corner_it++ )
+		{
+			corner_vector.push_back(corner_it->x());
+			corner_vector.push_back(corner_it->y());
+		}
+		myRender->drawCorners(devicePose,corner_vector);
+
+		//Set view point and render the scene. Locate visualization view point, somewhere behind the device
+		viewPoint.setPose(devicePose);
+		viewPoint.rt.setEuler( viewPoint.rt.head(), viewPoint.rt.pitch()+20.*M_PI/180., viewPoint.rt.roll() );
+		viewPoint.moveForward(-5);
+		myRender->setViewPoint(viewPoint);
+		myRender->render();
+	}
+
+	//delete things
+	delete myRender;
+    delete myScanner;
+
+	//exit
+	return 0;
+}
diff --git a/src/geometry.cpp b/src/geometry.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a49c06ca52117aed1e8c62e922c19808621f32fb
--- /dev/null
+++ b/src/geometry.cpp
@@ -0,0 +1,27 @@
+
+#include "geometry.h"
+
+//void laserscanutils::fitLine(unsigned int _idx_from, unsigned int _idx_to, const Eigen::MatrixXs & _points, Line & _line)
+void laserscanutils::fitLine(const Eigen::MatrixXs & _points, Line & _line)
+{
+//     _line.first = _idx_from;
+//     _line.last = _idx_to;
+
+    //Found the best fitting line over points within the window. Build the system: A*line=[0 0 1]'. Matrix A = a_ij
+    //Eigen::Matrix3s AA = _points.block(0, _idx_from, 3, _idx_to-_idx_from+1) * _points.block(0, _idx_from, 3, _idx_to-_idx_from+1).transpose();
+    Eigen::Matrix3s AA = _points * _points.transpose();
+    AA.row(2) << 0,0,1;
+
+    //solve for line
+    _line.vector = AA.inverse().col(2);
+
+    // compute fitting error TODO or TOREVIEW ....
+//  _line.error = 0;
+//  for(unsigned int jj = _idx_from; jj<=_idx_to; jj++)
+//  _line.error += fabs( _line.vector(0)*_points(0,jj) + _line.vector(1)*_points(1,jj) + _line.vector(2)) / sqrt( _line.vector(0)*_line.vector(0) + _line.vector(1)*_line.vector(1) );
+//  _line.error /= (_idx_to-_idx_from+1);
+
+
+    //_line.error = (_points.block(0, _idx_from, 3, _idx_to-_idx_from+1).transpose() * _line.vector).array().abs().sum()/(_line.vector.head(2).norm()*(_idx_to-_idx_from+1));
+    _line.error = (_points.transpose() * _line.vector).array().abs().sum() / (_line.vector.head(2).norm()*_points.cols());
+}
diff --git a/src/geometry.h b/src/geometry.h
new file mode 100644
index 0000000000000000000000000000000000000000..433206961c9fed074c7ac4923369bc2c1e044aed
--- /dev/null
+++ b/src/geometry.h
@@ -0,0 +1,35 @@
+
+#ifndef GEOMETRY_H_
+#define GEOMETRY_H_
+
+//laserscanutils
+#include "types_laser_scan_utils.h"
+
+namespace laserscanutils
+{
+    struct Line
+    {
+        Eigen::Vector3s vector;
+        ScalarT error;
+        unsigned int first, last;
+        //TODO: add an Eigen::Map to the supporting points ... but who ensures memory allocation of such points ???
+    };
+    
+    struct Corner 
+    {
+        double x_; //x coordinate , meters
+        double y_; //y coordinate , meters
+        double orientation_; //counterclockwise from the X axis
+        double aperture_; //minor aperture of the corner
+    };
+    
+    /** \brief Find the best fittig line given a set of points
+     * 
+     * Find the best fittig line given a set of points
+     * Input points at each column of _points matrix
+     * 
+     **/
+    void fitLine(const Eigen::MatrixXs & _points, Line & _line);
+    
+}
+#endif
diff --git a/src/scan_params.h b/src/scan_params.h
new file mode 100644
index 0000000000000000000000000000000000000000..0493087287e1376fae44c5c83634073d6c484b9b
--- /dev/null
+++ b/src/scan_params.h
@@ -0,0 +1,21 @@
+
+#ifndef SCAN_PARAMS_H_
+#define SCAN_PARAMS_H_
+
+//laserscanutils
+#include "types_laser_scan_utils.h"
+
+namespace laserscanutils
+{
+    struct ScanParams
+    {
+        double angle_min_; //radians
+        double angle_max_; //radians
+        double angle_step_; //radians
+        double scan_time_; //time from the measuring the first ray up to measuring the last one, seconds
+        double range_min_; //meters 
+        double range_max_; //meters
+        double range_std_dev_; //standard deviation measurement noise in range, meters 
+    };
+}
+#endif
diff --git a/src/types.h b/src/types.h
new file mode 100644
index 0000000000000000000000000000000000000000..372b8b3d69944207ee39ede15996621e9dbfadb9
--- /dev/null
+++ b/src/types.h
@@ -0,0 +1,42 @@
+
+#ifndef TYPES_H_
+#define TYPES_H_
+
+//includes from Eigen lib
+#include <eigen3/Eigen/Dense>
+#include <eigen3/Eigen/Geometry>
+
+
+//namespace laserscanutils;
+
+//type scalar, in case working on 32-bit architectures , or benchmarking
+namespace laserscanutils
+{
+    //typedef float ScalarT;         // Use this for float, 32 bit precision
+    typedef double ScalarT;        // Use this for double, 64 bit precision
+    //typedef long double ScalarT;   // Use this for long double, 128 bit precision
+}
+
+// Eigen namespace extension using the above defined scalar
+namespace Eigen  
+{
+    // 1. Vectors and Matrices
+    typedef Matrix<laserscanutils::ScalarT, 2, 2> Matrix2s;                ///< 2x2 matrix of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 3, 3> Matrix3s;                ///< 3x3 matrix of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 4, 4> Matrix4s;                ///< 4x4 matrix of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, Dynamic, Dynamic> MatrixXs;    ///< variable size matrix of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, 1> Vector1s;                ///< 1-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 2, 1> Vector2s;                ///< 2-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 3, 1> Vector3s;                ///< 3-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 4, 1> Vector4s;                ///< 4-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, Dynamic, 1> VectorXs;          ///< variable size vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, 2> RowVector2s;             ///< 2-row-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, 3> RowVector3s;             ///< 3-row-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, 4> RowVector4s;             ///< 4-row-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, Dynamic> RowVectorXs;       ///< variable size row-vector of real scalar_t type
+
+    // 2. Quaternions and other rotation things
+    typedef Quaternion<laserscanutils::ScalarT> Quaternions;               ///< Quaternion of real scalar_t type
+    typedef AngleAxis<laserscanutils::ScalarT> AngleAxiss;                 ///< Angle-Axis of real scalar_t type
+}
+#endif
diff --git a/src/types_laser_scan_utils.h b/src/types_laser_scan_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f759dc0ff2353757512a5336bddfa8096a0d39c
--- /dev/null
+++ b/src/types_laser_scan_utils.h
@@ -0,0 +1,41 @@
+
+#ifndef TYPES_LASER_SCAN_UTILS_H_
+#define TYPES_LASER_SCAN_UTILS_H_
+
+//includes from Eigen lib
+#include <eigen3/Eigen/Dense>
+#include <eigen3/Eigen/Geometry>
+
+//namespace laserscanutils;
+
+//type scalar, in case working on 32-bit architectures , or benchmarking
+namespace laserscanutils
+{
+    //typedef float ScalarT;         // Use this for float, 32 bit precision
+    typedef double ScalarT;        // Use this for double, 64 bit precision
+    //typedef long double ScalarT;   // Use this for long double, 128 bit precision
+}
+
+// Eigen namespace extension using the above defined scalar
+namespace Eigen  
+{
+    // 1. Vectors and Matrices
+    typedef Matrix<laserscanutils::ScalarT, 2, 2> Matrix2s;                ///< 2x2 matrix of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 3, 3> Matrix3s;                ///< 3x3 matrix of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 4, 4> Matrix4s;                ///< 4x4 matrix of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, Dynamic, Dynamic> MatrixXs;    ///< variable size matrix of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, 1> Vector1s;                ///< 1-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 2, 1> Vector2s;                ///< 2-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 3, 1> Vector3s;                ///< 3-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 4, 1> Vector4s;                ///< 4-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, Dynamic, 1> VectorXs;          ///< variable size vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, 2> RowVector2s;             ///< 2-row-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, 3> RowVector3s;             ///< 3-row-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, 4> RowVector4s;             ///< 4-row-vector of real scalar_t type
+    typedef Matrix<laserscanutils::ScalarT, 1, Dynamic> RowVectorXs;       ///< variable size row-vector of real scalar_t type
+
+    // 2. Quaternions and other rotation things
+    typedef Quaternion<laserscanutils::ScalarT> Quaternions;               ///< Quaternion of real scalar_t type
+    typedef AngleAxis<laserscanutils::ScalarT> AngleAxiss;                 ///< Angle-Axis of real scalar_t type
+}
+#endif