diff --git a/src/liboncilla-hw/synchronization/SBCPQueue.cpp b/src/liboncilla-hw/synchronization/SBCPQueue.cpp
index 3a507b7..266ff56 100644
--- a/src/liboncilla-hw/synchronization/SBCPQueue.cpp
+++ b/src/liboncilla-hw/synchronization/SBCPQueue.cpp
@@ -1,283 +1,307 @@
 /***
  * \file SBCPQueue.cpp
  *
  *  \date Jun 27, 2013
  *  \author Alexandre Tuleu
  */
 
 #include "SBCPQueue.h"
 
 #include <biorob-cpp/log/Logger.h>
 
 #include <libsbcp/utils/Config.h>
 
 #include <liboncilla-hw/config/Config.h>
 
 namespace liboncilla {
 namespace hw {
 
 SBCPQueue::SBCPQueue(const Config & config) 
 	: Queue(config.Main().SBCPPriority(), true)
 	, d_bus() {
 	sbcp::Config sbcpConfig;
 	sbcpConfig.LoadAllFiles();
 
 	// create links to the 4 motorboards
 	unsigned int requiredFrameSize = 4;   // 4 consecutive packets send at oncefrom roboard to master communication board
 	unsigned int requiredPacketSize = 32; // Size of the biggest packet you will send, the actual maximum might be higher
 
 	d_bus = sbcpConfig.OpenDefaultBusWithFrame(requiredFrameSize,
 	                                           requiredPacketSize);
 
 	if (!d_bus) {
 		throw std::runtime_error("SBCPQueue::SBCPQueue() Can't load bus due to missing configuration.");
 	} else {
 		log(debug, "Bus Workflow: ", d_bus->CurrentWorkflow());
 	}
 
 	const MotorDriverGroup & devices = config.Motors().Devices();
 	const BrushlessParameterGroup & motorConfig = config.Motors().Params();
 	int16_t timestep = config.Main().Timestep();
 
 	d_motordrivers[rci::oncilla::LEFT_FORE] = 
 		OpenAndConfigureMotorDriver(devices.LeftFore(), motorConfig, timestep);
 	d_motordrivers[rci::oncilla::RIGHT_FORE] = 
 		OpenAndConfigureMotorDriver(devices.RightFore(), motorConfig, timestep);
 	d_motordrivers[rci::oncilla::LEFT_HIND] = 
 		OpenAndConfigureMotorDriver(devices.LeftHind(), motorConfig, timestep);
 	d_motordrivers[rci::oncilla::RIGHT_HIND] = 
 		OpenAndConfigureMotorDriver(devices.RightHind(), motorConfig, timestep);
 
 }
 
 SBCPQueue::~SBCPQueue() {
 }
 
 void SBCPQueue::DownstreamData() {
 	for (MotorAndEncoderByL1L2::const_iterator motAndEnc = d_motAndEncByL1L2.begin(); 
 	     motAndEnc != d_motAndEncByL1L2.end();
 	     ++motAndEnc) {
 		motAndEnc->second.motor->GoalPosition().Set(motAndEnc->first->nodeToQueueJointPosition());
 	}
 }
 
 void SBCPQueue::UpstreamData() {
 	for (MotorAndEncoderByL1L2::const_iterator motAndEnc = d_motAndEncByL1L2.begin(); 
 	     motAndEnc != d_motAndEncByL1L2.end();
 	     ++motAndEnc) {
 		uint16_t pos(motAndEnc->second.encoder->PositionAndStatus().Get() & 0x3fff);
 		uint16_t status((motAndEnc->second.encoder->PositionAndStatus().Get() & 0xc000) >> 14);
 		int16_t motPos(motAndEnc->second.motor->PresentPosition().Get());
 		motAndEnc->first->queueToNodeJointPosition(pos, status, motPos);
 	}
 
 	for (MotorDriverByL0::const_iterator mdv = d_mdvByL0.begin();
 	     mdv != d_mdvByL0.end();
 	     ++mdv) {
 		if (mdv->second == NULL) {
 			// TODO: Throw? std::cout << "SBCPQueue::InitializeIO: Ignoring motor driver "<<md->second<<std::endl;
 		} else {
 			mdv->first->queueToNodeForces(mdv->second->Force(0).Get(),
 			                              mdv->second->Force(1).Get(), 
 			                              mdv->second->Force(2).Get());
 		}
 	}
 
 	for (MagneticEncoderByL3::const_iterator enc = d_encByL3.begin();
 	     enc != d_encByL3.end(); 
 	     ++enc) {
 		if (enc->second == NULL) {
 			// TODO: Throw? std::cout << "SBCPQueue::InitializeIO: Ignoring motor driver "<<md->second<<std::endl;
 		} else {
 			enc->first->queueToNodeJointPosition(enc->second->PositionAndStatus().Get() & 0x3fff,
 			                                     (enc->second->PositionAndStatus().Get() & 0xc000) >> 14);
 		}
 	}
 }
 
 void SBCPQueue::PerformIO() {
 	sbcp::ScheduledWorkflow & w = this->d_bus->Scheduled();
 
 	// Start transfer
 	w.StartTransfers();
 
 	// Wait for transfer to complete
 	w.WaitForTransfersCompletion();
 }
 
 void SBCPQueue::InitializeIO() {
 	// Enable scheduled woirkflow
 	sbcp::ScheduledWorkflow & w = this->d_bus->Scheduled();
 
 	// Append devices to transfer
 	for (MotordriverByLeg::iterator md = d_motordrivers.begin();
 	     md != d_motordrivers.end(); 
 	     ++md) {
 
 		if (md->second == NULL) {
 			log(debug, "SBCPQueue::InitializeIO: Ignoring motor driver ",
 			    LegPrefix(md->first) );
 		} else {
 			log( debug,  "Appending scheduled device " , LegPrefix(md->first) );
 			w.AppendScheduledDevice(std::tr1::static_pointer_cast<sbcp::Device>(md->second));
 		}
 	}
 }
 
 void SBCPQueue::DeinitializeIO() {
 	// Disable scheduled woirkflow
 	this->d_bus->Lazy();
 }
 
 void SBCPQueue::RegisterL0(rci::oncilla::Leg l, const L0::Ptr & node) {
 	// check if this map contains this leg
 	MotordriverByLeg::const_iterator fi = d_motordrivers.find(l);
 	if (fi == d_motordrivers.end()) {
 		throw(std::runtime_error("Failed to open motordriver, upon initialization of this Queue, for motordriver "
 		                         + LegPrefix(l)));
 	}
 
 	d_mdvByL0[node] = fi->second;
 }
 
 void SBCPQueue::RegisterL1(rci::oncilla::Leg l, const L1L2::Ptr & node) {
 	bool isLeftLeg =
 			((l == rci::oncilla::LEFT_FORE) || (l == rci::oncilla::LEFT_HIND)) ?
 					true : false;
 	bool isHip = true;
 
 	//check if this map contains this leg
 	MotordriverByLeg::const_iterator fi = d_motordrivers.find(l);
 	if (fi == d_motordrivers.end() || !fi->second) {
 		throw(std::runtime_error("Failed to open motordriver earlier, upon initialization of this Queue, for motordriver "
 		                         + LegPrefix(l)));
 	}
 
 	node->initialize(isLeftLeg, isHip,
 	                 fi->second->Motor1().PositionLimit().Get() & 0x7fff,
 	                 fi->second->Motor1().PresentPosition().Get());
 	
 	/// \todo hardcoded mapping, could be configurable
 	MotorAndEncoder m1;
 	m1.motor = &(fi->second->Motor1());
 	m1.encoder = &(fi->second->Q1());
 
 	d_motAndEncByL1L2[node] = m1;
 }
 
 void SBCPQueue::RegisterL2(rci::oncilla::Leg l, const L1L2::Ptr & node) {
 	bool isRightLeg = ((l == rci::oncilla::RIGHT_FORE) || (l == rci::oncilla::RIGHT_HIND)) ? true 
 	                                                                                       : false;
 	bool isHip = false;
 
 	//check if this map contains this leg
 	MotordriverByLeg::const_iterator fi = d_motordrivers.find(l);
 	if (fi == d_motordrivers.end() || !fi->second) {
 		throw(std::runtime_error("Failed to open motordriver earlier, upon initialization of this Queue, for motordriver "
 		                         + LegPrefix(l)));
 	}
 
 
 	node->initialize(isRightLeg, 
 	                 isHip,
 	                 fi->second->Motor2().PositionLimit().Get() & 0x7fff,
 	                 fi->second->Motor2().PresentPosition().Get());
 
 	/// \todo hardcoded mapping, could be configurable
 	MotorAndEncoder m2;
 	m2.motor = &(fi->second->Motor2());
 	m2.encoder = &(fi->second->Q2());
 
 	d_motAndEncByL1L2[node] = m2;
 }
 
 void SBCPQueue::RegisterL3(rci::oncilla::Leg l, const L3::Ptr & node) {
 	//check if this map contains this leg
 	MotordriverByLeg::const_iterator fi = d_motordrivers.find(l);
 	if (fi == d_motordrivers.end() || !fi->second) {
 		throw(std::runtime_error("Failed to open motordriver, upon initialization of this Queue, for motordriver "
 		                         + LegPrefix(l)));
 	}
 
 	d_encByL3[node] = &(fi->second->Q3());
 }
 
+bool AllMotorsCalibrated(const sbcp::amarsi::MotorDriver::Ptr & mdv) {
+	return mdv->Motor1().RuntimeCalibrated() && mdv->Motor2().RuntimeCalibrated();
+ }
+
+void SBCPQueue::CalibrateMotorDrivers() {
+	typedef std::set< sbcp::amarsi::MotorDriver::Ptr> SetOfMDV;
+	
+	SetOfMDV uncalibrated;
+	for(MotordriverByLeg::const_iterator mdv = d_motordrivers.begin();
+	    mdv != d_motordrivers.end();
+	    ++mdv) {
+		if (!mdv->second) {
+			continue;
+		}
+		if (AllMotorsCalibrated(mdv->second)) {
+			log(debug, LegPrefix(mdv->first), " motors are already runtime calibrated");
+		} else {
+			log(debug, "Calibrating ", LegPrefix(mdv->first), " motors");
+			mdv->second->CalibrateMotors();
+			uncalibrated.insert(mdv->second);
+		}
+	}
+
+
+	while(!uncalibrated.empty()) {
+		usleep(1e5);
+		SetOfMDV toTest = uncalibrated;
+		for(SetOfMDV::const_iterator mdv = toTest.begin();
+		    mdv != toTest.end();
+		    ++mdv) {
+			if(AllMotorsCalibrated(*mdv)) {
+				log(debug,"All motor of board ", (int)(*mdv)->ID(), " calibrated");
+				uncalibrated.erase(*mdv);
+			}
+		}
+
+	}
+
+	log(debug, "All motors calibrated");
+
+}
+
 sbcp::amarsi::MotorDriver::Ptr 
 SBCPQueue::OpenAndConfigureMotorDriver(const MotorDriverSection & def, 
                                        const BrushlessParameterGroup & params,
                                        int16_t expectedTsInMs) {
 	log(debug, "SBCPQueue::OpenAndConfigureMotorDriver()");
 	
 
 	if (!d_bus) {
 		throw std::logic_error("SBCPQueue::d_bus private member should be initialized in"
 		                       "constructor. Please report this internal bug");
 	}
 
     this->d_bus->Lazy();
 
 	sbcp::amarsi::MotorDriver::Ptr res = d_bus->OpenDevice< sbcp::amarsi::MotorDriver > (def.BoardID());
 
 	if (!res) {
 		// board is just not here, buit we will throw later if it is required.
 		log(debug, "Could not find an AMARSi motordriver board with ID ", (int)def.BoardID(), "on the bus");
 		return res;
 	}
 
-    bool m1Calibrated(GetCalibrationStatus(res->Motor1(),1));
-	bool m2Calibrated(GetCalibrationStatus(res->Motor2(),2));
-	if(! (m1Calibrated || m2Calibrated)){
-		res->CalibrateMotors();
-	} else {
-		log(debug, "Motor already calibrated");
-	}
-
-	while(!(m1Calibrated && m2Calibrated)){
-		usleep(1e5);
-		m1Calibrated = GetCalibrationStatus(res->Motor1(), 1);
-		m2Calibrated = GetCalibrationStatus(res->Motor2(), 2);
-	}
-	log(debug, "Motor calibrated");
 
 	SetMotorParameters(params, def.M1Params(), expectedTsInMs, res->Motor1());
 	SetMotorParameters(params, def.M2Params(), expectedTsInMs, res->Motor2());
 
 	return res;
 }
 
 void SBCPQueue::SetMotorParameters(const BrushlessParameterGroup & paramGroup,
                                    const std::string & paramName, int16_t expectedTsInMs,
                                    sbcp::amarsi::MotorDriver::Motor & motor) {
 	log(debug, "SBCPQueue::SetMotorParameters()" );
 	//due to a bad design of biorob-cpp dynamic section we should do this
 	std::tr1::shared_ptr<BrushlessParameterSection> params =
 		const_cast<BrushlessParameterGroup &>(paramGroup).SubSection(paramName);
 	
 	if (!params) {
 		throw std::runtime_error("Unknown motor parameter group '" + paramName + "'");
 	}
 
 	motor.MotorControlMode().Set(sbcp::amarsi::MotorDriver::Motor::SMOOTH_POSITION);
 
 	motor.PGain().Set(params->PGain());
 	motor.IGain().Set(params->IGain());
 	motor.DGain().Set(params->DGain());
 
 	motor.Stiffness().Set(params->Stiffness());
 	motor.Damping().Set(params->Damping());
 	motor.Preload().Set(params->PreCompression());
 
 	motor.MaxTorque().Set(params->MaxTorque());
 	motor.MaxSpeed().Set(params->MaxSpeed());
 	motor.MaxAcceleration().Set(params->MaxAcceleration());
 
 	motor.SmoothPositionUpdate().Set(expectedTsInMs);
 }
 
-bool SBCPQueue::GetCalibrationStatus(sbcp::amarsi::MotorDriver::Motor & m, int number) {
-	uint16_t val(m.MotorControlMode().Get());
-	return val & (1 << 9);
-}
 
 } /* namespace hw */
 } /* namespace liboncilla */
diff --git a/src/liboncilla-hw/synchronization/SBCPQueue.h b/src/liboncilla-hw/synchronization/SBCPQueue.h
index 628f9da..c50fc8f 100644
--- a/src/liboncilla-hw/synchronization/SBCPQueue.h
+++ b/src/liboncilla-hw/synchronization/SBCPQueue.h
@@ -1,82 +1,80 @@
 /*
  * \file SBCPQueue.h
  *
  *  \date Jun 27, 2013
  *  \author Alexandre Tuleu
  */
 
 #pragma once
 
 #include "Queue.h"
 #include <liboncilla-hw/nodes/Nodes.h>
 
 #include <libsbcp/bus/Bus.h>
 #include <libsbcp/bus/ScheduledWorkflow.h>
 #include <libsbcp/devices/amarsi/MotorDriver.h>
 
 namespace liboncilla {
 namespace hw {
 
 class Config;
 class BrushlessParameterGroup;
 class MotorDriverSection;
 
 class SBCPQueue : public Queue {
 public:
 	SBCPQueue(const liboncilla::hw::Config & config);
 	virtual ~SBCPQueue();
 
 	virtual void DownstreamData();
 	virtual void UpstreamData();
 	virtual void PerformIO();
 	virtual void InitializeIO();
 	virtual void DeinitializeIO();
 
 	void RegisterL0(rci::oncilla::Leg l, const L0::Ptr & node);
 	void RegisterL1(rci::oncilla::Leg l, const L1L2::Ptr & node);
 	void RegisterL2(rci::oncilla::Leg l, const L1L2::Ptr & node);
 	void RegisterL3(rci::oncilla::Leg l, const L3::Ptr & node);
 
 	void CalibrateMotorDrivers();
 
 private:
 	//std::tr1::shared_ptr<sbcp::amarsi::MotorDriver> d_motordrivers[4];
 
 	typedef std::map<liboncilla::hw::L0::Ptr, sbcp::amarsi::MotorDriver::Ptr> MotorDriverByL0;
 
 	struct MotorAndEncoder {
 		sbcp::amarsi::MotorDriver::Motor * motor;
 		sbcp::amarsi::MotorDriver::MagneticEncoder * encoder;
 	};
 
 	typedef std::map<liboncilla::hw::L1L2::Ptr, MotorAndEncoder> MotorAndEncoderByL1L2;
 	typedef std::map<liboncilla::hw::L3::Ptr,
 			sbcp::amarsi::MotorDriver::MagneticEncoder *> MagneticEncoderByL3;
 
 	typedef std::map<rci::oncilla::Leg, sbcp::amarsi::MotorDriver::Ptr> MotordriverByLeg;
 
 	void SetMotorParameters(const BrushlessParameterGroup & paramGroup,
 	                        const std::string & paramName, 
 	                        int16_t expectedTsInMs,
 	                        sbcp::amarsi::MotorDriver::Motor & motor);
 
 	sbcp::amarsi::MotorDriver::Ptr 
 	OpenAndConfigureMotorDriver(const MotorDriverSection & def,
 	                            const BrushlessParameterGroup & config, 
 	                            int16_t expectedTsInMs);
 
 
-    inline bool GetCalibrationStatus(sbcp::amarsi::MotorDriver::Motor &, int);
-
 	MotorDriverByL0 d_mdvByL0;
 	MotorAndEncoderByL1L2 d_motAndEncByL1L2;
 	MagneticEncoderByL3 d_encByL3;
 
 	MotordriverByLeg d_motordrivers;
 
 	std::tr1::shared_ptr<sbcp::Bus> d_bus;
 };
 
 } /* namespace hw */
 } /* namespace liboncilla */
 
diff --git a/src/liboncilla-hw/synchronization/Synchronizer.cpp b/src/liboncilla-hw/synchronization/Synchronizer.cpp
index cd081c0..f3a4176 100644
--- a/src/liboncilla-hw/synchronization/Synchronizer.cpp
+++ b/src/liboncilla-hw/synchronization/Synchronizer.cpp
@@ -1,217 +1,217 @@
 #include "Synchronizer.h"
 #include <sys/mman.h>
 #include <signal.h>
 #include <errno.h>
 
 #include <liboncilla-hw/xenomai-utils/Utils.h>
 
 #include <liboncilla-hw/config/Config.h>
 
 namespace liboncilla {
 namespace hw {
 
 Synchronizer::Synchronizer(const Config & config)
 	: rci::oncilla::Synchronizer("Oncilla HW Synchronizer")
 	, d_timestep(config.Main().Timestep() * 1.0e-3)
 	, d_priority(config.Main().MainPriority())
 	, d_sbcpQueue(config)
 	, d_rbioQueue(config.Main().RBIOPriority()) {
 
 	CheckMainConfig(config.Main());
 
 	Init();
 
 	//TODO bad bad pratice new queue should be added automatically to this list.
 	d_queues.push_back(&d_sbcpQueue);
 	d_queues.push_back(&d_rbioQueue);
 }
 
 void Synchronizer::Init() {
 
 	InitRT();
 	InitModules();
 }
 
 void Synchronizer::InitRT() {
 
 	xeno_call(rt_task_shadow, NULL, NULL, d_priority, T_FPU);
 }
 
 void Synchronizer::CheckPriority(unsigned int p, const std::string & name) {
 	if (p > 99) {
 		std::ostringstream os;
 		os << "Unsupported " << name << " of " << p
 		   << " only value between 0 and 99 are supported";
 		throw std::runtime_error(os.str());
 	}
 }
 
 void Synchronizer::CheckMainConfig(const MainSection& config) {
 	std::ostringstream os;
 	if (config.Timestep() < 2) {
 		os << "Unsupported timestep of " << config.Timestep()
 		   << " ms. It should be >= 2ms";
 		throw std::runtime_error(os.str());
 	}
 
 	CheckPriority(config.MainPriority(), "main priority");
 	CheckPriority(config.SBCPPriority(), "sbcp priority");
 	CheckPriority(config.RBIOPriority(), "rbio priority");
 }
 
 void Synchronizer::InitModules() {
 
 }
 
 Synchronizer::~Synchronizer() {
 }
 
 void Synchronizer::calibrateIfNeeded() {
-
+	d_sbcpQueue.CalibrateMotorDrivers();
 }
 
 bool Synchronizer::start() {
 	d_firstStepped = false;
 
 	RT_EVENT * e = new RT_EVENT();
 	xeno_call(rt_event_create, e, Queue::EventName, 0, EV_PRIO);
 	d_event = NativeHolder<RT_EVENT>(e);
 
 	for (ListOfQueue::const_iterator q = d_queues.begin();
 	     q != d_queues.end();
 	     ++q) {
 		(*q)->StartTask();
 	}
 	d_idleQueueMask = Queue::AllQueueMask();
 
 	bool res = rci::oncilla::Synchronizer::start();
 
 	xeno_call(rt_task_set_periodic, NULL, TM_NOW, d_timestep * 1e9);
 
 	return res;
 }
 
 bool Synchronizer::stop() {
 	for (ListOfQueue::const_iterator q = d_queues.begin(); 
 	     q != d_queues.end();
 	     ++q) {
 		(*q)->StopTask();
 	}
 	d_event = NativeHolder<RT_EVENT>();
 
 	return rci::Synchronizer::stop();
 }
 
 double Synchronizer::lastProcessTimeStep() const {
 	if (!d_firstStepped) {
 		return 0.0;
 	}
 	return d_timestep * (d_overruns + 1);
 }
 
 void Synchronizer::ProcessAsyncPrimpl() {
 	for (ListOfQueue::const_iterator q = d_queues.begin();
 	     q != d_queues.end();
 	     ++q) {
 		if (IsFinished(**q)) {
 			(*q)->DownstreamData();
 		}
 	}
 	WakeIdleQueues();
 	d_firstStepped = true;
 }
 
 void Synchronizer::WaitForProcessAsyncPrimpl() {
 	int res;
 
 	unsigned int maxTrials(20);
 
 	while (true) {
 		res = rt_task_wait_period(&d_overruns);
 		if (res != 0 && res != -ETIMEDOUT) {
 			xeno_throw_error_from(rt_task_wait_period, res);
 		}
 
 		FetchIdleQueues();
 		//we ensure that all sbcp communication are done !
 		if (IsFinished(d_sbcpQueue)) {
 			break;
 		}
 
 		--maxTrials;
 		if (maxTrials == 0) {
 			std::ostringstream os;
 			os << "SBCP communication did not finished after " << maxTrials
 			   << " timesteps. We abort everything";
 			throw std::runtime_error(os.str());
 		}
 	}
 
 	for (ListOfQueue::const_iterator q = d_queues.begin();
 	     q != d_queues.end();
 	     ++q) {
 		if (IsFinished(**q)) {
 			(*q)->UpstreamData();
 		}
 	}
 
 }
 
 void Synchronizer::RegisterTrunk(const Trunk::Ptr& node) {
 	/// \todo implement
 }
 
 void Synchronizer::RegisterL0(rci::oncilla::Leg l, const L0::Ptr& node) {
 	d_rbioQueue.RegisterL0(l, node);
 	d_sbcpQueue.RegisterL0(l, node);
 }
 
 void Synchronizer::RegisterL1(rci::oncilla::Leg l, const L1L2::Ptr& node) {
 	if (!node) {
 		std::ostringstream os;
 		os << "Ignoring L1 node of leg " << l << ". Is it connected?";
 		throw std::runtime_error(os.str());
 	}
 	d_sbcpQueue.RegisterL1(l, node);
 }
 
 void Synchronizer::RegisterL2(rci::oncilla::Leg l, const L1L2::Ptr& node) {
 	if (!node) {
 		
 		std::ostringstream os;
 		os << "Ignoring L2 node of leg " << l << ". Is it connected?";
 		throw std::runtime_error(os.str());
 	}
 	d_sbcpQueue.RegisterL2(l, node);
 }
 
 void Synchronizer::RegisterL3(rci::oncilla::Leg l, const L3::Ptr& node) {
 	if (!node) {
 		std::ostringstream os;
 		os << "Ignoring L3 node of leg " << l << ". Is it connected?";
 		throw std::runtime_error(os.str());
 	}
 	d_sbcpQueue.RegisterL3(l, node);
 }
 
 void Synchronizer::WakeIdleQueues() {
 	xeno_call(rt_event_signal, d_event.get(), d_idleQueueMask);
 }
 
 void Synchronizer::FetchIdleQueues() {
 	xeno_call(rt_event_wait,
 	          d_event.get(), 
 	          0,
 	          &d_idleQueueMask, 
 	          EV_ANY, 
 	          TM_NONBLOCK);
 	d_idleQueueMask ^= Queue::AllQueueMask();
 }
 
 bool Synchronizer::IsFinished(const Queue& q) {
 	return q.Mask() & d_idleQueueMask;
 }
 
 } //namespace hw
 } //namespace liboncilla