diff --git a/include/node.h b/include/node.h
index 4e599aa5612080129cb5ae1afaeaf511a5e65dd0..cf719c85d4050abf9301c242e5c514ad16333b37 100644
--- a/include/node.h
+++ b/include/node.h
@@ -64,6 +64,10 @@ class WolfRosNode
     protected:
         // solver
         SolverManagerPtr solver_;
+        bool compute_cov_;
+        SolverManager::CovarianceBlocksToBeComputed cov_enum_;
+        ros::Time last_cov_stamp_;
+        double cov_period_;
 
         // transforms
         tf::TransformBroadcaster tfb_;
diff --git a/include/publisher.h b/include/publisher.h
index d962d61abe3c4f0f43fd0230a81863540cbb2418..778becdb237ed933f6592a02d3d4fdfefd49fd04 100644
--- a/include/publisher.h
+++ b/include/publisher.h
@@ -48,7 +48,8 @@ class Publisher
                   const ParamsServer& _server,
                   const ProblemPtr _problem) :
                       problem_(_problem),
-                      last_publish_time_(ros::Time(0)),
+                      first_publish_time_(ros::Time(0)),
+                      last_n_period_(0),
                       prefix_("ROS publisher/" + _unique_name)
         {
             period_ = _server.getParam<double>(prefix_ + "/period");
@@ -72,20 +73,30 @@ class Publisher
         ProblemPtr problem_;
         ros::Publisher publisher_;
         double period_;
-        ros::Time last_publish_time_;
+        ros::Time first_publish_time_;
+        long unsigned int last_n_period_;
         std::string prefix_;
         std::string topic_;
 };
 
 inline void Publisher::publish()
 {
-    last_publish_time_ = ros::Time::now();
+    if (last_n_period_ == 0)
+        first_publish_time_ = ros::Time::now();
+
     publishDerived();
 }
 
 inline bool Publisher::ready()
 {
-    return (ros::Time::now() - last_publish_time_).toSec() > period_;
+    long unsigned int n_period = (long unsigned int)((ros::Time::now() - first_publish_time_).toSec() / period_);
+    if (n_period > last_n_period_)
+    {
+        last_n_period_ = n_period;
+        return true;
+    }
+
+    return false;
 }
 
 inline std::string Publisher::getTopic() const
diff --git a/include/publisher_pose.h b/include/publisher_pose.h
index dff4bac7531ea8fccf2c580fae43532f03aab046..890b6dd86a9f9153eee8730af897468660e57bc2 100644
--- a/include/publisher_pose.h
+++ b/include/publisher_pose.h
@@ -13,6 +13,7 @@
  **************************/
 #include <ros/ros.h>
 #include <geometry_msgs/PoseArray.h>
+#include <geometry_msgs/PoseWithCovarianceStamped.h>
 #include <visualization_msgs/Marker.h>
 #include <tf/transform_listener.h>
 
@@ -21,16 +22,17 @@ namespace wolf
 
 class PublisherPose: public Publisher
 {
-        bool pose_array_, marker_;
+        bool pose_array_, marker_, pose_with_cov_;
 
         geometry_msgs::PoseArray pose_array_msg_;
         visualization_msgs::Marker marker_msg_;
+        geometry_msgs::PoseWithCovarianceStamped pose_with_cov_msg_;
         std_msgs::ColorRGBA marker_color_;
         bool extrinsics_;
         SensorBasePtr sensor_;
         std::string frame_id_, map_frame_id_;
 
-        ros::Publisher pub_pose_array_, pub_marker_;
+        ros::Publisher pub_pose_array_, pub_marker_, pub_pose_with_cov_;
 
     public:
         PublisherPose(const std::string& _unique_name,
@@ -44,7 +46,7 @@ class PublisherPose: public Publisher
 
         void publishDerived() override;
 
-        void publishPose(const geometry_msgs::Pose pose, const ros::Time& stamp);
+        void publishPose();
 
     protected:
 
diff --git a/include/visualizer.h b/include/visualizer.h
index 988da90a5400cd9e06b443a8b5aaf012cae22584..21b89f94d9082a91d27dded1c75a812a9554938e 100644
--- a/include/visualizer.h
+++ b/include/visualizer.h
@@ -66,7 +66,7 @@ class Visualizer
 
     // Options
     std::string map_frame_id_;
-    bool        viz_factors_, viz_landmarks_, viz_trajectory_, viz_overlapped_factors_;
+    bool        viz_overlapped_factors_;
     double      viz_scale_, factors_width_, factors_absolute_height_, landmark_text_z_offset_, landmark_width_, landmark_length_, frame_width_, frame_length_;
     std_msgs::ColorRGBA frame_color_, factor_abs_color_, factor_motion_color_, factor_loop_color_, factor_lmk_color_, factor_geom_color_;
 
diff --git a/src/node.cpp b/src/node.cpp
index 34a456b4d212edad06f786ca95ee8b164d1add65..c08711d2e3533e68b020b9ef5bdba093b29d4095 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -39,6 +39,13 @@ WolfRosNode::WolfRosNode()
     // SOLVER
     ROS_INFO("Creating solver...");
     solver_ = FactorySolver::create("SolverCeres", problem_ptr_, server);
+    // covariance
+    compute_cov_ = server.getParam<bool>("solver/compute_cov");
+    if (compute_cov_)
+    {
+        cov_enum_   = (SolverManager::CovarianceBlocksToBeComputed)server.getParam<int>("solver/cov_enum");
+        cov_period_ = server.getParam<double>("solver/cov_period");
+    }
 
     // ROS SUBSCRIBERS
     ROS_INFO("Creating subscribers...");
@@ -82,9 +89,26 @@ void WolfRosNode::solve()
         ROS_INFO("================ solve ==================");
 
     std::string report = solver_->solve();
-    // if (!report.empty()){
-    //     std::cout << report << std::endl;
-    // }
+
+    if (!report.empty())
+    {
+        std::cout << report << std::endl;
+        //problem_ptr_->print(4,1,1,1);
+    }
+
+    if (compute_cov_ and (ros::Time::now() - last_cov_stamp_).toSec() > cov_period_)
+    {
+        auto start = std::chrono::high_resolution_clock::now();
+        if (solver_->computeCovariances(cov_enum_))
+        {
+            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - start);
+            last_cov_stamp_ = ros::Time::now();
+            if (solver_->getVerbosity() != SolverManager::ReportVerbosity::QUIET)
+                ROS_INFO("Covariances computed successfully! It took %li microseconds", duration.count());
+        }
+        else if (solver_->getVerbosity() != SolverManager::ReportVerbosity::QUIET)
+            ROS_WARN("Failed to compute covariances");
+    }
 }
 
 void WolfRosNode::visualize()
@@ -94,7 +118,7 @@ void WolfRosNode::visualize()
     viz_->visualize(problem_ptr_);
     auto stop     = std::chrono::high_resolution_clock::now();
     auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
-    std::cout << "Visualize took " << duration.count() << " microseconds" << std::endl;
+    //std::cout << "Visualize took " << duration.count() << " microseconds" << std::endl;
 }
 
 bool WolfRosNode::updateTf()
@@ -177,7 +201,7 @@ void WolfRosNode::broadcastTf()
 
 void WolfRosNode::solveLoop()
 {
-    ros::Rate solverRate(1/solver_->getPeriod());
+    ros::Rate solverRate(1/(solver_->getPeriod()+1e-9)); // 1ns added to allow pausing if rosbag paused
     WOLF_DEBUG("Started solver loop");
 
     while (ros::ok())
@@ -208,6 +232,12 @@ int main(int argc, char **argv)
 
     // Solver thread
     std::thread solver_thread(&WolfRosNode::solveLoop, &wolf_node);
+    // set priority
+    struct sched_param Priority_Param; //struct to set priority
+    int priority = 99;
+    Priority_Param.sched_priority = priority;
+    int policy=SCHED_FIFO;
+    pthread_setschedparam(solver_thread.native_handle(), SCHED_FIFO, &Priority_Param);
 
     while (ros::ok())
     {
@@ -219,7 +249,7 @@ int main(int argc, char **argv)
         auto start3 = std::chrono::high_resolution_clock::now();
         if ((ros::Time::now() - last_viz_time).toSec() >= wolf_node.viz_period_)
         {
-            std::cout << "Last Viz since/viz_period_ " << (ros::Time::now() - last_viz_time).toSec() << " / " << wolf_node.viz_period_ << std::endl;
+            //std::cout << "Last Viz since/viz_period_ " << (ros::Time::now() - last_viz_time).toSec() << " / " << wolf_node.viz_period_ << std::endl;
             wolf_node.visualize();
             last_viz_time = ros::Time::now();
         }
diff --git a/src/publisher_pose.cpp b/src/publisher_pose.cpp
index 11fc3937928ac16df25970ceb80e7f187a4aac4b..7d4a6d4695df29a2f0e9459c2a7a1f6b6555dac4 100644
--- a/src/publisher_pose.cpp
+++ b/src/publisher_pose.cpp
@@ -15,16 +15,23 @@ PublisherPose::PublisherPose(const std::string& _unique_name,
                              const ProblemPtr _problem) :
         Publisher(_unique_name, _server, _problem)
 {
-    pose_array_ = _server.getParam<bool>(prefix_ + "/pose_array_msg");
-    marker_     = _server.getParam<bool>(prefix_ + "/marker_msg");
-    if (marker_)
-    {
+    try{
+        std::cout << "PublisherPose: taking user defined marker color...\n";
         Eigen::Vector4d col = _server.getParam<Eigen::Vector4d>(prefix_ + "/marker_color");
         marker_color_.r = col(0);
         marker_color_.g = col(1);
         marker_color_.b = col(2);
         marker_color_.a = col(3);
     }
+    catch(...)
+    {
+        std::cout << "PublisherPose: using default marker color: RED\n";
+        marker_color_.r = 1;
+        marker_color_.g = 0;
+        marker_color_.b = 0;
+        marker_color_.a = 1;
+    }
+
     extrinsics_     = _server.getParam<bool>(prefix_ + "/extrinsics");
     if (extrinsics_)
         sensor_ = _problem->getSensor(_server.getParam<std::string>(prefix_ + "/sensor"));
@@ -37,40 +44,47 @@ void PublisherPose::initialize(ros::NodeHandle& nh, const std::string& topic)
     nh.param<std::string>("map_frame_id", map_frame_id_, "map");
 
     // initialize msg and publisher
-    if (pose_array_)
-    {
-        pose_array_msg_.header.frame_id = frame_id_;
 
-        pub_pose_array_ = nh.advertise<geometry_msgs::PoseArray>(topic + "_pose_array", 1);
-    }
-    if (marker_)
-    {
-        marker_msg_.header.frame_id = frame_id_;
-        marker_msg_.type = visualization_msgs::Marker::LINE_STRIP;
-        marker_msg_.action = visualization_msgs::Marker::ADD;
-        marker_msg_.ns = "trajectory";
-        marker_msg_.scale.x = 0.1;
-        marker_msg_.color = marker_color_;
-        marker_msg_.pose.orientation = tf::createQuaternionMsgFromYaw(0);
-
-        pub_marker_ = nh.advertise<visualization_msgs::Marker>(topic + "_marker", 1);
-    }
+    // POSE ARRAY
+    pose_array_msg_.header.frame_id = frame_id_;
+
+    pub_pose_array_ = nh.advertise<geometry_msgs::PoseArray>(topic + "_pose_array", 1);
+
+    // MARKER
+    marker_msg_.header.frame_id = frame_id_;
+    marker_msg_.type = visualization_msgs::Marker::LINE_STRIP;
+    marker_msg_.action = visualization_msgs::Marker::ADD;
+    marker_msg_.ns = "trajectory";
+    marker_msg_.scale.x = 0.1;
+    marker_msg_.color = marker_color_;
+    marker_msg_.pose.orientation = tf::createQuaternionMsgFromYaw(0);
+
+    pub_marker_ = nh.advertise<visualization_msgs::Marker>(topic + "_marker", 1);
+
+    // POSE WITH COV
+    pose_with_cov_msg_.header.frame_id = frame_id_;
+
+    pub_pose_with_cov_ = nh.advertise<geometry_msgs::PoseWithCovarianceStamped>(topic + "_pose_with_cov", 1);
 }
 
 void PublisherPose::publishDerived()
 {
+    if (pub_pose_array_.getNumSubscribers() == 0 and
+        pub_marker_.getNumSubscribers() == 0 and
+        pub_pose_with_cov_.getNumSubscribers() == 0 )
+        return;
+
     VectorComposite current_state = problem_->getState("PO");
     TimeStamp loc_ts = problem_->getTimeStamp();
 
     // state not ready
     if (current_state.count('P') == 0 or
         current_state.count('O') == 0 or
-        loc_ts == TimeStamp(0))
+        not loc_ts.ok())
     {
         return;
     }
 
-
     // fill vector and quaternion
     Eigen::Vector3d p = Eigen::Vector3d::Zero();
     Eigen::Quaterniond q;
@@ -119,36 +133,62 @@ void PublisherPose::publishDerived()
         q = q_frame_ * q;
     }
 
+    // Covariance
+    Eigen::MatrixXd cov(6,6);
+    auto KF = problem_->getLastFrame();
+    bool success(true);
+    success = success && problem_->getCovarianceBlock(KF->getP(), KF->getP(), cov, 0, 0);
+    success = success && problem_->getCovarianceBlock(KF->getP(), KF->getO(), cov, 0, 3);
+    success = success && problem_->getCovarianceBlock(KF->getO(), KF->getP(), cov, 3, 0);
+    success = success && problem_->getCovarianceBlock(KF->getO(), KF->getO(), cov, 3, 3);
+
+    if (success)
+    {
+        if (problem_->getDim() == 2)
+            throw std::runtime_error("not implemented");
+        else
+            std::copy(cov.data(), cov.data() + cov.size(), pose_with_cov_msg_.pose.covariance.data());
+    }
+    else
+    {
+        //WOLF_WARN("Last KF covariance could not be recovered, using the previous one");
+        //pose_with_cov_msg_.pose.covariance[0] = -1; // not valid
+    }
+
     // Fill Pose msg
-    geometry_msgs::Pose pose_msg;
-    pose_msg.position.x = p(0);
-    pose_msg.position.y = p(1);
-    pose_msg.position.z = p(2);
-
-    pose_msg.orientation.x = q.x();
-    pose_msg.orientation.y = q.y();
-    pose_msg.orientation.z = q.z();
-    pose_msg.orientation.w = q.w();
-    publishPose(pose_msg, ros::Time(loc_ts.getSeconds(), loc_ts.getNanoSeconds()));
+    pose_with_cov_msg_.header.stamp = ros::Time(loc_ts.getSeconds(), loc_ts.getNanoSeconds());
+    pose_with_cov_msg_.pose.pose.position.x = p(0);
+    pose_with_cov_msg_.pose.pose.position.y = p(1);
+    pose_with_cov_msg_.pose.pose.position.z = p(2);
+
+    pose_with_cov_msg_.pose.pose.orientation.x = q.x();
+    pose_with_cov_msg_.pose.pose.orientation.y = q.y();
+    pose_with_cov_msg_.pose.pose.orientation.z = q.z();
+    pose_with_cov_msg_.pose.pose.orientation.w = q.w();
+    publishPose();
 }
 
-void PublisherPose::publishPose(const geometry_msgs::Pose pose, const ros::Time& stamp)
+void PublisherPose::publishPose()
 {
     // fill msgs and publish
-    if (pose_array_)
+    if (pub_pose_array_.getNumSubscribers() != 0)
     {
-        pose_array_msg_.header.stamp = stamp;
-        pose_array_msg_.poses.push_back(pose);
+        pose_array_msg_.header.stamp = pose_with_cov_msg_.header.stamp;
+        pose_array_msg_.poses.push_back(pose_with_cov_msg_.pose.pose);
 
         pub_pose_array_.publish(pose_array_msg_);
     }
-    if (marker_)
+    if (pub_marker_.getNumSubscribers() != 0)
     {
-        marker_msg_.header.stamp = stamp;
-        marker_msg_.points.push_back(pose.position);
+        marker_msg_.header.stamp = pose_with_cov_msg_.header.stamp;
+        marker_msg_.points.push_back(pose_with_cov_msg_.pose.pose.position);
 
         pub_marker_.publish(marker_msg_);
     }
+    if (pub_pose_with_cov_.getNumSubscribers() != 0)
+    {
+        pub_pose_with_cov_.publish(pose_with_cov_msg_);
+    }
 }
 
 bool PublisherPose::listenTf()
diff --git a/src/visualizer.cpp b/src/visualizer.cpp
index c99231cd08d4c1084b6645ca11d4b5bad905be4d..af2aad32b34f231ff5f5f3824e7ff5d0883684a8 100644
--- a/src/visualizer.cpp
+++ b/src/visualizer.cpp
@@ -11,16 +11,8 @@ Visualizer::Visualizer() :
 
 void Visualizer::initialize(ros::NodeHandle& nh)
 {
-    // init publishers ---------------------------------------------------
-    factors_publisher_      = nh.advertise<visualization_msgs::MarkerArray>("factors", 1);
-    landmarks_publisher_    = nh.advertise<visualization_msgs::MarkerArray>("landmarks", 1);
-    trajectory_publisher_   = nh.advertise<visualization_msgs::MarkerArray>("trajectory", 1);
-
     // Load options ---------------------------------------------------
-    nh.param<bool>(         "viz_factors",              viz_factors_,               true);
     nh.param<bool>(         "viz_overlapped_factors",   viz_overlapped_factors_,    false);
-    nh.param<bool>(         "viz_landmarks",            viz_landmarks_,             true);
-    nh.param<bool>(         "viz_trajectory",           viz_trajectory_,            true);
     // viz parameters
     nh.param<std::string>(  "map_frame_id",             map_frame_id_,              "map");
     nh.param<double>(       "viz_scale",                viz_scale_,                 1);
@@ -62,6 +54,11 @@ void Visualizer::initialize(ros::NodeHandle& nh)
     nh.param<float>(        "factor_geom_color_b",      factor_geom_color_.b,       1.0);
     nh.param<float>(        "factor_geom_color_a",      factor_geom_color_.a,       1);
 
+    // init publishers ---------------------------------------------------
+    factors_publisher_      = nh.advertise<visualization_msgs::MarkerArray>("factors", 1);
+    landmarks_publisher_    = nh.advertise<visualization_msgs::MarkerArray>("landmarks", 1);
+    trajectory_publisher_   = nh.advertise<visualization_msgs::MarkerArray>("trajectory", 1);
+
     // init markers ---------------------------------------------------
     // factor markers message
     factor_marker_.type = visualization_msgs::Marker::LINE_LIST;
@@ -119,11 +116,11 @@ void Visualizer::initialize(ros::NodeHandle& nh)
 
 void Visualizer::visualize(const ProblemPtr problem)
 {
-    if (viz_factors_)
+    if (factors_publisher_.getNumSubscribers() != 0)
         publishFactors(problem);
-    if (viz_landmarks_)
+    if (landmarks_publisher_.getNumSubscribers() != 0)
         publishLandmarks(problem);
-    if (viz_trajectory_)
+    if (trajectory_publisher_.getNumSubscribers() != 0)
         publishTrajectory(problem);
 }