diff --git a/hello_wolf/CMakeLists.txt b/hello_wolf/CMakeLists.txt
index b998b6f1c15ccb59d84e0a70ebbb6051a7301220..6fbf3ae196ae78568b75a1ef3664fbc11d5f6a73 100644
--- a/hello_wolf/CMakeLists.txt
+++ b/hello_wolf/CMakeLists.txt
@@ -24,9 +24,15 @@ SET(HDRS_PROCESSOR ${HDRS_PROCESSOR}
 
 add_library(hellowolf SHARED ${SRCS_HELLOWOLF})
 TARGET_LINK_LIBRARIES(hellowolf ${PROJECT_NAME})
+
 ADD_EXECUTABLE(hello_wolf hello_wolf.cpp)
 TARGET_LINK_LIBRARIES(hello_wolf ${PROJECT_NAME} hellowolf)
+
+ADD_EXECUTABLE(hello_wolf_autoconf hello_wolf_autoconf.cpp)
+TARGET_LINK_LIBRARIES(hello_wolf_autoconf ${PROJECT_NAME} hellowolf)
+
 add_library(sensor_odom SHARED ../src/sensor/sensor_odom_2D.cpp ../src/processor/processor_odom_2D.cpp)
 TARGET_LINK_LIBRARIES(sensor_odom ${PROJECT_NAME} hellowolf)
+
 add_library(range_bearing SHARED sensor_range_bearing.cpp processor_range_bearing.cpp)
-TARGET_LINK_LIBRARIES(range_bearing ${PROJECT_NAME} hellowolf)
\ No newline at end of file
+TARGET_LINK_LIBRARIES(range_bearing ${PROJECT_NAME} hellowolf)
diff --git a/hello_wolf/hello_wolf_autoconf.cpp b/hello_wolf/hello_wolf_autoconf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8fa710e3807b284298ab601a8b0f80c3dbe30ec3
--- /dev/null
+++ b/hello_wolf/hello_wolf_autoconf.cpp
@@ -0,0 +1,399 @@
+/**
+ * \file hello_wolf_autoconf.cpp
+ *
+ *  Created on: Jul 16, 2019
+ *      \author: jsola
+ */
+
+
+#include "core/common/wolf.h"
+
+#include "core/utils/params_server.hpp"
+#include "core/yaml/parser_yaml.hpp"
+
+#include "core/sensor/sensor_odom_2D.h"
+#include "core/processor/processor_odom_2D.h"
+
+#include "sensor_range_bearing.h"
+#include "processor_range_bearing.h"
+#include "capture_range_bearing.h"
+#include "feature_range_bearing.h"
+#include "factor_range_bearing.h"
+#include "landmark_point_2D.h"
+
+#include "core/ceres_wrapper/ceres_manager.h"
+
+int main()
+ {
+    /*
+     * ============= PROBLEM DEFINITION ==================
+     *
+     * We have a planar robot with a range-and-bearing sensor 'S' mounted at its front-left corner, looking forward:
+     *
+     *              ^ Y
+     *              |
+     *     ------------------S->        sensor at location (1,1) and orientation 0 degrees, that is, at pose (1,1,0).
+     *     |        |        |
+     *     |        +--------|--> X     robot axes X, Y
+     *     |                 |
+     *     -------------------
+     *
+     * The robot performs a straight trajectory with 3 keyframes 'KF', and observes 3 landmarks 'L'.
+     *
+     * The 3 robot keyframes, the 3 resulting sensor poses, and the 3 landmark positions can be sketched as follows
+     *
+     *             (1,2)   (2,2)   (3,2)        landmark positions in world frame
+     *              L1      L2      L3          LANDMARKS
+     *              | \     | \     |
+     *              |   \   |   \   |
+     *              |     \ |     \ |
+     *           (1,1,0) (2,1,0) (3,1,0)        sensor poses in world frame
+     *              S->     S->     S->         SENSOR
+     *           (1,1,0) (1,1,0) (1,1,0)        sensor poses in robot frame
+     *           /       /       /
+     *         /       /       /
+     *       /       /       /
+     *     KF1->---KF2->---KF3->                KEYFRAMES -- robot poses
+     *   (0,0,0) (1,0,0) (2,0,0)                keyframe poses in world frame
+     *      |
+     *      * prior                             Initial robot pose in world frame
+     *    (0,0,0)
+     *
+     * where:
+     *  the links '--'          are the motion factors,
+     *  the links '\' and '|'   are the landmark measurement factors, and
+     *  the links '/'           are the robot-to-sensor transforms.
+     *
+     * That is:
+     *   - KFs have ids '1', '2', '3'
+     *   - All KFs look East, so all theta = 0
+     *   - KFs are at poses (0,0, 0), (1,0, 0), and (2,0, 0)
+     *   - We set a prior at (0,0,0) on KF1 to render the system observable
+     *   - The range-and-bearing sensor is mounted at pose (1,1, 0) w.r.t. the robot's origin
+     *   - Lmks have ids '1', '2', '3'
+     *   - Lmks are at positions (1,2), (2,2), (3,2)
+     *   - Observations have ranges 1 or sqrt(2)
+     *   - Observations have bearings pi/2 or 3pi/4
+     *
+     * The robot starts at (0,0,0) with a map with no previously known landmarks.
+     * At each keyframe, it does:
+     *   - Create a motion factor to the previous keyframe
+     *   - Measure some landmarks. For each measurement,
+     *      - If the landmark is unknown, add it to the map and create an observation factor
+     *      - If the landmark is known, create an observation factor
+     *
+     * The landmarks observed at each keyframe are as follows:
+     *   - KF1: lmk  1
+     *   - KF2: lmks 1 and 2
+     *   - KF3: lmks 2 and 3
+     *
+     * After 3 keyframes, the problem is solved and the robot poses and landmark positions are optimized:
+     *   - First,  using the exact values as initial guess for the solver
+     *   - Second, using random values
+     * Both solutions must produce the same exact values as in the sketches above.
+     *
+     * Optionally, the user can opt to self-calibrate the sensor's orientation (see NOTE within the code around Line 151)
+     *
+     * (c) 2017 Joan Sola @ IRI-CSIC
+     */
+
+    // SET PROBLEM =======================================================
+
+    using namespace wolf;
+
+
+    // Config file to parse
+    std::string file = "/Users/jsola/dev/wolf_lib/core/hello_wolf/hello_wolf_config.yaml";
+    // string file = "/home/jcasals/catkin_ws/src/wolf_ros_wrapper/yaml/params_demo_quim.yaml";
+
+    // WOLF parser
+    parserYAML parser = parserYAML(file);
+    parser.parse();
+    paramsServer server = paramsServer(parser.getParams(), parser.sensorsSerialization(), parser.processorsSerialization());
+
+
+    // Wolf problem and solver
+    ProblemPtr problem                      = Problem::autoSetup(server);
+
+    ceres::Solver::Options options;
+    options.max_num_iterations              = 1000; // We depart far from solution, need a lot of iterations
+    CeresManagerPtr ceres                   = std::make_shared<CeresManager>(problem, options);
+
+    // sensor odometer 2D
+    IntrinsicsOdom2DPtr intrinsics_odo      = std::make_shared<IntrinsicsOdom2D>();
+    SensorBasePtr sensor_odo                = problem->installSensor("ODOM 2D", "sensor odo", Vector3s(0,0,0), intrinsics_odo);
+
+    // processor odometer 2D
+    ProcessorParamsOdom2DPtr params_odo     = std::make_shared<ProcessorParamsOdom2D>();
+    params_odo->voting_active               = true;
+    params_odo->time_tolerance              = 0.1;
+    params_odo->max_time_span               = 999;
+    params_odo->dist_traveled               = 0.95; // Will make KFs automatically every 1m displacement
+    params_odo->angle_turned                = 999;
+    params_odo->cov_det                     = 999;
+    params_odo->unmeasured_perturbation_std = 0.001;
+    ProcessorBasePtr processor              = problem->installProcessor("ODOM 2D", "processor odo", sensor_odo, params_odo);
+    ProcessorOdom2DPtr processor_odo        = std::static_pointer_cast<ProcessorOdom2D>(processor);
+
+    // sensor Range and Bearing
+    IntrinsicsRangeBearingPtr intrinsics_rb = std::make_shared<IntrinsicsRangeBearing>();
+    intrinsics_rb->noise_range_metres_std   = 0.1;
+    intrinsics_rb->noise_bearing_degrees_std = 1.0;
+    SensorBasePtr sensor_rb                 = problem->installSensor("RANGE BEARING", "sensor RB", Vector3s(1,1,0), intrinsics_rb);
+
+    // processor Range and Bearing
+    ProcessorParamsRangeBearingPtr params_rb = std::make_shared<ProcessorParamsRangeBearing>();
+    params_rb->voting_active                = false;
+    params_rb->time_tolerance               = 0.01;
+    ProcessorBasePtr processor_rb           = problem->installProcessor("RANGE BEARING", "processor RB", sensor_rb, params_rb);
+
+    // SELF CALIBRATION ===================================================
+
+    // NOTE: SELF-CALIBRATION OF SENSOR ORIENTATION
+    // Uncomment this line below to achieve sensor self-calibration (of the orientation only, since the position is not observable)
+    sensor_rb->getO()->unfix();
+
+    // NOTE: SELF-CALIBRATION OF SENSOR POSITION
+    // The position is however not observable, and thus self-calibration would not work. You can try uncommenting it too.
+    // sensor_rb->getP()->unfix();
+
+    // CONFIGURE ==========================================================
+
+    // Motion data
+    Vector2s motion_data(1.0, 0.0);                     // Will advance 1m at each keyframe, will not turn.
+    Matrix2s motion_cov = 0.1 * Matrix2s::Identity();
+
+    // landmark observations data
+    VectorXi ids;
+    VectorXs ranges, bearings;
+
+    // SET OF EVENTS =======================================================
+    std::cout << std::endl;
+    WOLF_TRACE("======== BUILD PROBLEM =======")
+
+    // We'll do 3 steps of motion and landmark observations.
+
+    // STEP 1 --------------------------------------------------------------
+
+    // initialize
+    TimeStamp   t(0.0);                     // t : 0.0
+    Vector3s    x(0,0,0);
+    Matrix3s    P = Matrix3s::Identity() * 0.1;
+    problem->setPrior(x, P, t, 0.5);             // KF1 : (0,0,0)
+
+    // observe lmks
+    ids.resize(1); ranges.resize(1); bearings.resize(1);
+    ids         << 1;                       // will observe Lmk 1
+    ranges      << 1.0;                     // see drawing
+    bearings    << M_PI/2;
+    CaptureRangeBearingPtr cap_rb = std::make_shared<CaptureRangeBearing>(t, sensor_rb, ids, ranges, bearings);
+    sensor_rb   ->process(cap_rb);          // L1 : (1,2)
+
+    // STEP 2 --------------------------------------------------------------
+    t += 1.0;                     // t : 1.0
+
+    // motion
+    CaptureOdom2DPtr cap_motion = std::make_shared<CaptureOdom2D>(t, sensor_odo, motion_data, motion_cov);
+    sensor_odo  ->process(cap_motion);      // KF2 : (1,0,0)
+
+    // observe lmks
+    ids.resize(2); ranges.resize(2); bearings.resize(2);
+    ids         << 1, 2;                    // will observe Lmks 1 and 2
+    ranges      << sqrt(2.0), 1.0;          // see drawing
+    bearings    << 3*M_PI/4, M_PI/2;
+    cap_rb      = std::make_shared<CaptureRangeBearing>(t, sensor_rb, ids, ranges, bearings);
+    sensor_rb   ->process(cap_rb);          // L1 : (1,2), L2 : (2,2)
+
+    // STEP 3 --------------------------------------------------------------
+    t += 1.0;                     // t : 2.0
+
+    // motion
+    cap_motion  ->setTimeStamp(t);
+    sensor_odo  ->process(cap_motion);      // KF3 : (2,0,0)
+
+    // observe lmks
+    ids.resize(2); ranges.resize(2); bearings.resize(2);
+    ids         << 2, 3;                    // will observe Lmks 2 and 3
+    ranges      << sqrt(2.0), 1.0;          // see drawing
+    bearings    << 3*M_PI/4, M_PI/2;
+    cap_rb      = std::make_shared<CaptureRangeBearing>(t, sensor_rb, ids, ranges, bearings);
+    sensor_rb   ->process(cap_rb);          // L1 : (1,2), L2 : (2,2), L3 : (3,2)
+    problem->print(1,0,1,0);
+
+    // SOLVE ================================================================
+
+    // SOLVE with exact initial guess
+    WOLF_TRACE("======== SOLVE PROBLEM WITH EXACT PRIORS =======")
+    std::string report = ceres->solve(wolf::SolverManager::ReportVerbosity::FULL);
+    WOLF_TRACE(report);                     // should show a very low iteration number (possibly 1)
+    problem->print(1,0,1,0);
+
+    // PERTURB initial guess
+    WOLF_TRACE("======== PERTURB PROBLEM PRIORS =======")
+    for (auto sen : problem->getHardware()->getSensorList())
+        for (auto sb : sen->getStateBlockVec())
+            if (sb && !sb->isFixed())
+                sb->setState(sb->getState() + VectorXs::Random(sb->getSize()) * 0.5);       // We perturb A LOT !
+    for (auto kf : problem->getTrajectory()->getFrameList())
+        if (kf->isKeyOrAux())
+            for (auto sb : kf->getStateBlockVec())
+                if (sb && !sb->isFixed())
+                    sb->setState(sb->getState() + VectorXs::Random(sb->getSize()) * 0.5);   // We perturb A LOT !
+    for (auto lmk : problem->getMap()->getLandmarkList())
+        for (auto sb : lmk->getStateBlockVec())
+            if (sb && !sb->isFixed())
+                sb->setState(sb->getState() + VectorXs::Random(sb->getSize()) * 0.5);       // We perturb A LOT !
+    problem->print(1,0,1,0);
+
+    // SOLVE again
+    WOLF_TRACE("======== SOLVE PROBLEM WITH PERTURBED PRIORS =======")
+    report = ceres->solve(wolf::SolverManager::ReportVerbosity::FULL);
+    WOLF_TRACE(report);                     // should show a very high iteration number (more than 10, or than 100!)
+    problem->print(1,0,1,0);
+
+    // GET COVARIANCES of all states
+    WOLF_TRACE("======== COVARIANCES OF SOLVED PROBLEM =======")
+    ceres->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS);
+    for (auto kf : problem->getTrajectory()->getFrameList())
+        if (kf->isKeyOrAux())
+        {
+            Eigen::MatrixXs cov;
+            kf->getCovariance(cov);
+            WOLF_TRACE("KF", kf->id(), "_cov = \n", cov);
+        }
+    for (auto lmk : problem->getMap()->getLandmarkList())
+        {
+            Eigen::MatrixXs cov;
+            lmk->getCovariance(cov);
+            WOLF_TRACE("L", lmk->id(), "_cov = \n", cov);
+        }
+    std::cout << std::endl;
+
+    WOLF_TRACE("======== FINAL PRINT FOR INTERPRETATION =======")
+    problem->print(4,1,1,1);
+
+    /*
+     * ============= FIRST COMMENT ON THE RESULTS ==================
+     *
+     * IF YOU SEE at the end of the printed problem the estimate for Lmk 3 as:
+     *
+     * L3 POINT 2D   <-- c8
+     *   Est,     x = ( 3 2 )
+     *   sb: Est
+     *
+     * it means WOLF SOLVED SUCCESSFULLY (L3 is effectively at location (3,2) ) !
+     *
+     * Side notes:
+     *
+     *  - Observe that all other KFs and Lmks are correct.
+     *
+     *  - Try self-calibrating the sensor orientation by uncommenting line 151 (well, around 151)
+     *
+     */
+
+    /*
+     * ============= DETAILED DESCRIPTION OF THE PRINTED RESULT ==================
+     *
+     * The line problem->print(4,1,1,1) produces a printout of the status of the WOLF problem.
+     * The full message is explained below.
+     *
+     * P: wolf tree status ---------------------
+        Hardware
+          S1 ODOM 2D                                    // Sensor 1, type ODOMETRY 2D.
+            Extr [Sta] = [ Fix( 0 0 ) Fix( 0 ) ]        // Static extrinsics, fixed position, fixed orientation (See notes 1 and 2 below)
+            Intr [Sta] = [ ]                            // Static intrinsics, but no intrinsics anyway
+            pm1 ODOM 2D                                 // Processor 1, type ODOMETRY 2D
+              o: C7 - F3                                // origin at Capture 7, Frame 3
+              l: C10 - F4                               // last at Capture 10, frame 4
+          S2 RANGE BEARING                              // Sensor 2, type RANGE and BEARING.
+            Extr [Sta] = [ Fix( 1 1 ) Est( 0 ) ]        // Static extrinsics, fixed position, estimated orientation (See notes 1 and 2 below)
+            Intr [Sta] = [ ]                            // Static intrinsics, but no intrinsics anyway
+            pt2 RANGE BEARING                           // Processor 2: type Range and Bearing
+        Trajectory
+          KF1  <-- c3                                   // KeyFrame 1, constrained by Factor 3
+            Est, ts=0,   x = ( -1.6e-13 9.4e-11  1.4e-10 ) // State is estimated; time stamp and state vector
+            sb: Est Est                                 // State's pos and orient are estimated
+            C1 FIX -> S- [  <--                         // Capture 1, type FIX or Absolute
+              f1 FIX  <--                               // Feature 1, type Fix
+                m = ( 0 0 0 )                           // The absolute measurement for this frame is (0,0,0) --> origin
+                c1 FIX --> A                            // Factor 1, type FIX, it is Absolute
+            CM2 ODOM 2D -> S1 [Sta, Sta]  <--           // Capture 2, type ODOM, from Sensor 1 (static extr and intr)
+            C5 RANGE BEARING -> S2 [Sta, Sta]  <--      // Capture 5, type R+B, from Sensor 2 (static extr and intr)
+              f2 RANGE BEARING  <--                     // Feature 2, type R+B
+                m = ( 1    1.57 )                       // The feature's measurement is 1m, 1.57rad
+                c2 RANGE BEARING --> L1                 // Factor 2 against Landmark 1
+          KF2  <-- c6
+            Est, ts=1,   x = ( 1       2.5e-10 1.6e-10 )
+            sb: Est Est
+            CM3 ODOM 2D -> S1 [Sta, Sta]  <--
+              f3 ODOM 2D  <--
+                m = ( 1 0 0 )
+                c3 ODOM 2D --> F1                       // Factor 3, type ODOM, against Frame 1
+            C9 RANGE BEARING -> S2 [Sta, Sta]  <--
+              f4 RANGE BEARING  <--
+                m = ( 1.41 2.36 )
+                c4 RANGE BEARING --> L1
+              f5 RANGE BEARING  <--
+                m = ( 1    1.57 )
+                c5 RANGE BEARING --> L2
+          KF3  <--
+            Est, ts=2,   x = ( 2       4.1e-10 1.7e-10 )
+            sb: Est Est
+            CM7 ODOM 2D -> S1 [Sta, Sta]  <--
+              f6 ODOM 2D  <--
+                m = ( 1 0 0 )
+                c6 ODOM 2D --> F2
+            C12 RANGE BEARING -> S2 [Sta, Sta]  <--
+              f7 RANGE BEARING  <--
+                m = ( 1.41 2.36 )
+                c7 RANGE BEARING --> L2
+              f8 RANGE BEARING  <--
+                m = ( 1    1.57 )
+                c8 RANGE BEARING --> L3
+          F4  <--
+            Est, ts=2,   x = ( 0.11   -0.045 0.26  )
+            sb: Est Est
+            CM10 ODOM 2D -> S1 [Sta, Sta]  <--
+        Map
+          L1 POINT 2D   <-- c2  c4                      // Landmark 1, constrained by Factors 2 and 4
+            Est,     x = ( 1 2 )                        // L4 state is estimated, state vector
+            sb: Est                                     // L4 has 1 state block estimated
+          L2 POINT 2D   <-- c5  c7
+            Est,     x = ( 2 2 )
+            sb: Est
+          L3 POINT 2D   <-- c8
+            Est,     x = ( 3 2 )
+            sb: Est
+        -----------------------------------------
+     *
+     * ============= GENERAL WOLF NOTES ==================
+     *
+     * Explanatory notes, general to the Wolf architecture design:
+     *
+     * (1): Sensor params (extrinsics and intrinsics) can be declared Dynamic or Static
+     *          Static:  they do not change with time --> stored in the Sensor
+     *          Dynamic: they change with time        --> stored in each Capture
+     *
+     * (2): General params can be declared Fixed or Estimated
+     *          Fixed:     they are used as constant values, never estimated
+     *          Estimated: they are estimated by the solver iteratively
+     *
+     * Therefore, in the case of Sensors, each block of parameters can be Static/Dynamic and Fixed/Estimated. This produces 4 combinations:
+     *
+     *         1 Fixed + Static : general case of calibrated sensor.
+     *              Example: rigidly fixed sensor with calibrated parameters
+     *              This is the case for the current example (the SensorRangeBearing we use is like this)
+     *
+     *         2 Estimated + Static : Wolf performs self-calibration.
+     *              Example: extrinsics self-calibration of a camera
+     *
+     *         3 Fixed + Dynamic : calibrated but variable parameters.
+     *              Example: pan and tilt camera extrinsics, known at every time through precise encoders
+     *
+     *         4 Estimated + Dynamic : Wolf will track those sensor parameters that evolve with time.
+     *              Example: IMU bias
+     *
+     */
+
+    return 0;
+}
diff --git a/hello_wolf/hello_wolf_config.yaml b/hello_wolf/hello_wolf_config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..58cafcd2d7b62d1ceb15ee56ddce2d5b2f3578c2
--- /dev/null
+++ b/hello_wolf/hello_wolf_config.yaml
@@ -0,0 +1,43 @@
+config:
+
+  problem:
+    frame structure: "PO"
+    dimension: 2
+    prior state: [0,0,0]
+    prior cov:   [[3,3],1,0,0,0,1,0,0,0,1]
+    
+ 
+  sensors:
+    -
+      type: "ODOM 2D"
+      name: "odom"
+
+    - 
+      type: "RANGE BEARING"
+      name: "rb"    
+      
+  processors:
+    -
+      type:           "ODOM 2D"
+      name:           "odom"
+      sensor name:    "odom"
+      voting active:  true
+      time tolerance: 0.1
+      max time span:  999
+      dist_traveled:  0.95
+      angle_turned:   999
+      cov_det:        999
+      unmeasured_perturbation_std: 0.001
+    
+    -
+      type: "RANGE BEARING"
+      name: "rb"
+      sensor name: "odom"
+    
+    
+files:
+    - "/Users/jsola/dev/wolf_lib/core/lib/libhellowolf.dylib"
+    - "/Users/jsola/dev/wolf_lib/core/lib/librange_bearing.dylib"
+    - "/Users/jsola/dev/wolf_lib/core/lib/libsensor_odom.dylib"
+  
+    
\ No newline at end of file