diff --git a/include/publisher.h b/include/publisher.h
index bdeace3c019ad72e607209e7f7f30d34d75f4445..ebba97466a7e89e690742b3ca029221529682b3b 100644
--- a/include/publisher.h
+++ b/include/publisher.h
@@ -83,6 +83,10 @@ class Publisher
 
         virtual ~Publisher(){};
 
+        virtual void run() final;
+        virtual void stop() final;
+        virtual void loop() final;
+
         virtual void initialize(ros::NodeHandle& nh, const std::string& topic) = 0;
 
         virtual void publish() final;
@@ -109,6 +113,8 @@ class Publisher
         std::string prefix_;
         std::string topic_;
 
+        std::thread pub_thread_;
+
         // PROFILING
         unsigned int n_publish_;
         std::chrono::microseconds acc_duration_;
@@ -140,14 +146,7 @@ inline void Publisher::publish()
 
 inline bool Publisher::ready()
 {
-    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;
+    return true;
 }
 
 inline void Publisher::printProfiling(std::ostream &_stream) const
@@ -159,6 +158,35 @@ inline void Publisher::printProfiling(std::ostream &_stream) const
             << "\n\tmax time:             " << 1e-3 * max_duration_.count() << " ms" << std::endl;
 }
 
+inline void Publisher::run()
+{
+    pub_thread_ = std::thread(&Publisher::loop, this);
+}
+
+inline void Publisher::stop()
+{
+    pub_thread_.join();
+}
+
+inline void Publisher::loop()
+{
+    auto awake_time = std::chrono::system_clock::now();
+    auto period = std::chrono::duration<int,std::milli>((int)(period_*1e3));
+
+    WOLF_DEBUG("Started publisher ", name_, " loop");
+
+    while (ros::ok())
+    {
+        if (ready())
+            publish();
+
+        // relax to fit output rate
+        awake_time += period;
+        std::this_thread::sleep_until(awake_time);
+    }
+    WOLF_DEBUG("Publisher ", name_, " loop finished");
+}
+
 template<typename T>
 inline T Publisher::getParamWithDefault(const ParamsServer &_server,
                                         const std::string &_param_name,
diff --git a/src/node.cpp b/src/node.cpp
index faaa28aef701668e89e4efe6362afaef874eb37b..bacc721bef94027ad2e7cdb7961eada466dcfe21 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -19,6 +19,7 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
 //--------LICENSE_END--------
+#include <chrono>
 #include "node.h"
 #include "ros/time.h"
 #include "core/solver/factory_solver.h"
@@ -142,7 +143,8 @@ void WolfRosNode::solve()
 
 void WolfRosNode::solveLoop()
 {
-    ros::Rate solverRate(1/(solver_->getPeriod()+1e-9)); // 1ns added to allow pausing if rosbag paused if period==0
+    auto awake_time = std::chrono::system_clock::now();
+    auto period = std::chrono::duration<int,std::milli>((int)(solver_->getPeriod()*1e3+1)); // 1ms added to allow pausing if rosbag paused if period==0
     WOLF_DEBUG("Started solver loop");
 
     while (ros::ok())
@@ -153,7 +155,8 @@ void WolfRosNode::solveLoop()
             break;
 
         // relax to fit output rate
-        solverRate.sleep();
+        awake_time += period;
+        std::this_thread::sleep_until(awake_time);
     }
     WOLF_DEBUG("Solver loop finished");
 }
@@ -225,13 +228,12 @@ int main(int argc, char **argv)
     int policy=SCHED_FIFO;
     pthread_setschedparam(solver_thread.native_handle(), SCHED_FIFO, &Priority_Param);
 
+    // Init publishers threads
+    for(auto pub : wolf_node.publishers_)
+        pub->run();
+
     while (ros::ok())
     {
-        // publish periodically
-        for(auto pub : wolf_node.publishers_)
-            if (pub->ready())
-                pub->publish();
-
         // check that subscribers received data (every second)
         if ((ros::Time::now() - last_check).toSec() > 1)
         {
@@ -249,10 +251,16 @@ int main(int argc, char **argv)
         // relax to fit output rate
         loopRate.sleep();
     }
+
+    // Stop solver thread
     WOLF_DEBUG("Node is shutting down outside loop... waiting for the thread to stop...");
     solver_thread.join();
     WOLF_DEBUG("thread stopped.");
 
+    // Stop publishers threads
+    for(auto pub : wolf_node.publishers_)
+        pub->stop();
+
     // PROFILING ========================================
     wolf_node.createProfilingFile();