Index: /trunk/lib/FlairSensorActuator/src/Bldc.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Bldc.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/Bldc.cpp	(revision 340)
@@ -58,11 +58,4 @@
 }
 
-Bldc::Bldc(const Object *parent, string name, uint8_t motors_count)
-    : IODevice(parent, name) {
-  pimpl_ = new Bldc_impl(this, motors_count);
-  
-  SetIsReady(true);
-}
-
 Bldc::~Bldc() { delete pimpl_; }
 
Index: /trunk/lib/FlairSensorActuator/src/Bldc.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Bldc.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/Bldc.h	(revision 340)
@@ -51,16 +51,4 @@
   Bldc(const core::IODevice *parent, gui::Layout *layout, std::string name,
        uint8_t motors_count);
-
-  /*!
-  * \brief Constructor
-  *
-  * Construct a Bldc. \n
-  * This contructor must only be called for a simulated device.
-  *
-  * \param parent parent
-  * \param name name
-  * \param motors_count number of motors
-  */
-  Bldc(const core::Object *parent, std::string name, uint8_t motors_count);
 
   /*!
Index: /trunk/lib/FlairSensorActuator/src/Bldc_impl.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Bldc_impl.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/Bldc_impl.cpp	(revision 340)
@@ -84,12 +84,4 @@
 }
 
-Bldc_impl::Bldc_impl(Bldc *self, uint8_t motors_count) {
-  this->self = self;
-  this->motors_count = motors_count;
-  values = NULL;
-  button_test = NULL;
-  power = NULL;
-}
-
 Bldc_impl::~Bldc_impl() {
   if (values != NULL)
@@ -124,5 +116,5 @@
   for (int i = 0; i < motors_count; i++) {
     if (are_enabled) {
-      // Printf("%i %f %f\n",i,input->ValueNoMutex(i,0),power[i]);
+      //Printf("%i %f %f\n",i,input->ValueNoMutex(i,0),power[i]);
       values[i] = power[i] * Sat(input->ValueNoMutex(i, 0));
       // Printf("%i %f\n",i,values[i]);
Index: /trunk/lib/FlairSensorActuator/src/Camera.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Camera.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/Camera.cpp	(revision 340)
@@ -51,20 +51,6 @@
 }
 
-//This contructor must only be called for a simulated device.
-Camera::Camera(const IODevice *parent, std::string name)
-    : IODevice(parent, name) {
-  plot_tab = NULL;
-  main_tab = NULL;
-  tab = NULL;
-  sensor_tab = NULL;
-  setup_groupbox = NULL;
-
-  output = NULL;
-	logFormat=LogFormat::NONE;
-}
-
 Camera::~Camera() {
-  if (main_tab != NULL)
-    delete main_tab;
+  delete main_tab;
 }
 
@@ -94,9 +80,4 @@
 
 void Camera::UseDefaultPlot(const core::Image *image) {
-  if (tab == NULL) {
-    Err("not applicable for simulation part.\n");
-    return;
-  }
-
   plot_tab = new Tab(tab, "Picture");
   Picture *plot = new Picture(plot_tab->NewRow(), ObjectName(), image);
Index: /trunk/lib/FlairSensorActuator/src/Camera.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Camera.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/Camera.h	(revision 340)
@@ -52,15 +52,4 @@
   Camera(std::string name, uint16_t width,
          uint16_t height, core::Image::Type::Format format);
-
-  /*!
-  * \brief Constructor
-  *
-  * Construct a Camera. \n
-  * This contructor must only be called for a simulated device.
-  *
-  * \param parent parent
-  * \param name name
-  */
-  Camera(const core::IODevice *parent, std::string name);
 
   /*!
Index: /trunk/lib/FlairSensorActuator/src/Imu.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Imu.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/Imu.cpp	(revision 340)
@@ -49,16 +49,6 @@
 }
 
-Imu::Imu(const IODevice *parent,std::string name) : IODevice(parent, name) {
-  imuData = new ImuData(this);
-  mainTab = NULL;
-  tab = NULL;
-  sensorTab = NULL;
-  setupGroupbox = NULL;
-  rotation = NULL;
-}
-
 Imu::~Imu() {
-  if (mainTab != NULL)
-    delete mainTab;
+  delete mainTab;
 }
 
@@ -97,24 +87,12 @@
 
 void Imu::LockUserInterface(void) const {
-  if (sensorTab == NULL) {
-    Err("not applicable for simulation part.\n");
-    return;
-  }
   sensorTab->setEnabled(false);
 }
 
 void Imu::UnlockUserInterface(void) const {
-  if (sensorTab == NULL) {
-    Err("not applicable for simulation part.\n");
-    return;
-  }
   sensorTab->setEnabled(true);
 }
 
 void Imu::UseDefaultPlot(void) {
-  if (tab == NULL) {
-    Err("not applicable for simulation part.\n");
-    return;
-  }
 
   plotTab = new Tab(tab, "IMU");
@@ -126,6 +104,4 @@
   azPlot->AddCurve(imuData->Element(ImuData::RawAz));
 
-  if (plotTab == NULL)
-    plotTab = new Tab(tab, "IMU");
   gxPlot = new DataPlot1D(plotTab->NewRow(), "gyr_x", -500, 500);
   gxPlot->AddCurve(imuData->Element(ImuData::RawGxDeg));
@@ -135,6 +111,4 @@
   gzPlot->AddCurve(imuData->Element(ImuData::RawGzDeg));
 
-  if (plotTab == NULL)
-    plotTab = new Tab(tab, "IMU");
   mxPlot = new DataPlot1D(plotTab->NewRow(), "mag_x", -500, 500);
   mxPlot->AddCurve(imuData->Element(ImuData::RawMx));
Index: /trunk/lib/FlairSensorActuator/src/Imu.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Imu.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/Imu.h	(revision 340)
@@ -56,15 +56,4 @@
   */
   Imu(std::string name,bool needRotation=true);
-
-  /*!
-  * \brief Constructor
-  *
-  * Construct an Imu. \n
-  * This contructor must only be called for a simulated device.
-  *
-  * \param parent parent
-  * \param name name
-  */
-  Imu(const core::IODevice *parent, std::string name);
 
   /*!
Index: /trunk/lib/FlairSensorActuator/src/LaserRangeFinder.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/LaserRangeFinder.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/LaserRangeFinder.cpp	(revision 340)
@@ -49,15 +49,4 @@
 }
 
-LaserRangeFinder::LaserRangeFinder(const IODevice *parent, std::string name)
-    : IODevice(parent, name) {
-  plot_tab = NULL;
-  main_tab = NULL;
-  tab = NULL;
-  sensor_tab = NULL;
-  setup_groupbox = NULL;
-
-  output = NULL;
-}
-
 LaserRangeFinder::~LaserRangeFinder() {}
 
@@ -69,9 +58,4 @@
 
 void LaserRangeFinder::UseDefaultPlot(void) {
-  if (tab == NULL) {
-    Err("not applicable for simulation part.\n");
-    return;
-  }
-
   plot_tab = new Tab(tab, "Mesures");
   plot = new RangeFinderPlot(plot_tab->NewRow(), "plot", "x", -30, 30, "y", -30,
Index: /trunk/lib/FlairSensorActuator/src/LaserRangeFinder.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/LaserRangeFinder.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/LaserRangeFinder.h	(revision 340)
@@ -47,13 +47,5 @@
   */
   LaserRangeFinder(std::string name);
-  /*!
-  * \brief Constructor
-  *
-  * Construct a UsRangeFinder. Simulation part.
-  *
-  * \param parent parent
-  * \param name name
-  */
-  LaserRangeFinder(const core::IODevice *parent, std::string name);
+ 
   /*!
   * \brief Destructor
Index: /trunk/lib/FlairSensorActuator/src/NmeaGps.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/NmeaGps.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/NmeaGps.cpp	(revision 340)
@@ -73,16 +73,7 @@
 }
 
-NmeaGps::NmeaGps(const IODevice *parent, std::string name) : IODevice(parent, name) {
-  gpsData = new GpsData(this);
-  mainTab = NULL;
-  tab = NULL;
-  sensorTab = NULL;
-}
-
 NmeaGps::~NmeaGps() {
-  if (mainTab != NULL) {
-    nmea_parser_destroy(&parser);
-    delete mainTab;
-  }
+  nmea_parser_destroy(&parser);
+  delete mainTab;
 }
 
Index: /trunk/lib/FlairSensorActuator/src/NmeaGps.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/NmeaGps.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/NmeaGps.h	(revision 340)
@@ -67,15 +67,4 @@
   NmeaGps(std::string name,
       NMEAFlags_t NMEAFlags);
-
-  /*!
-  * \brief Constructor
-  *
-  * Construct a NmeaGps. \n
-  * This contructor must only be called for a simulated device.
-  *
-  * \param parent parent
-  * \param name name
-  */
-  NmeaGps(const core::IODevice *parent, std::string name);
 
   /*!
Index: /trunk/lib/FlairSensorActuator/src/PressureSensor.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/PressureSensor.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/PressureSensor.cpp	(revision 340)
@@ -48,18 +48,6 @@
 }
 
-PressureSensor::PressureSensor(const IODevice *parent, std::string name)
-    : IODevice(parent, name) {
-  plot_tab = NULL;
-  main_tab = NULL;
-  tab = NULL;
-  sensor_tab = NULL;
-  setup_groupbox = NULL;
-
-  output = NULL;
-}
-
 PressureSensor::~PressureSensor() {
-  if (main_tab != NULL)
-    delete main_tab;
+  delete main_tab;
 }
 
@@ -73,9 +61,4 @@
 
 void PressureSensor::UseDefaultPlot(void) {
-  if (tab == NULL) {
-    Err("not applicable for simulation part.\n");
-    return;
-  }
-
   plot_tab = new Tab(tab, "Mesures");
   plot = new DataPlot1D(plot_tab->NewRow(), ObjectName(), 101000, 101500);
Index: /trunk/lib/FlairSensorActuator/src/PressureSensor.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/PressureSensor.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/PressureSensor.h	(revision 340)
@@ -49,14 +49,4 @@
   */
   PressureSensor(std::string name);
-
-  /*!
-  * \brief Constructor
-  *
-  * Construct a PressureSensor. Simulation part.
-  *
-  * \param parent parent
-  * \param name name
-  */
-  PressureSensor(const core::IODevice *parent, std::string name);
 
   /*!
Index: /trunk/lib/FlairSensorActuator/src/Servos.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Servos.cpp	(revision 340)
+++ /trunk/lib/FlairSensorActuator/src/Servos.cpp	(revision 340)
@@ -0,0 +1,66 @@
+// %flair:license{
+// This file is part of the Flair framework distributed under the
+// CECILL-C License, Version 1.0.
+// %flair:license}
+//  created:    2019/11/28
+//  filename:   Servos.cpp
+//
+//  author:     Guillaume Sanahuja
+//              Copyright Heudiasyc UMR UTC/CNRS 7253
+//
+//  version:    $Id: $
+//
+//  purpose:    Virtual class for servos
+//
+//
+/*********************************************************************/
+
+#include "Servos.h"
+#include "Servos_impl.h"
+#include <DoubleSpinBox.h>
+
+using std::string;
+using namespace flair::core;
+using namespace flair::gui;
+
+namespace flair {
+namespace actuator {
+
+Servos::Servos(const IODevice *parent, Layout *layout, string name,
+           uint8_t motors_count)
+    : IODevice(parent, name) {
+  pimpl_ = new Servos_impl(this, layout, name, motors_count);
+
+}
+
+Servos::~Servos() { delete pimpl_; }
+
+void Servos::UpdateFrom(const io_data *data) { pimpl_->UpdateFrom(data); }
+
+void Servos::LockUserInterface(void) const { pimpl_->LockUserInterface(); }
+
+void Servos::UnlockUserInterface(void) const { pimpl_->UnlockUserInterface(); }
+
+Layout *Servos::GetLayout(void) const { return (Layout *)pimpl_->layout; }
+
+void Servos::UseDefaultPlot(TabWidget *tabwidget) {
+  pimpl_->UseDefaultPlot(tabwidget);
+}
+
+uint8_t Servos::ServosCount(void) const { return pimpl_->servos_count; }
+
+bool Servos::AreEnabled(void) const { return pimpl_->are_enabled; }
+
+void Servos::SetEnabled(bool status) {
+  if (pimpl_->are_enabled != status) {
+    pimpl_->are_enabled = status;
+    if (pimpl_->are_enabled) {
+      LockUserInterface();
+    } else {
+      UnlockUserInterface();
+    }
+  }
+}
+
+} // end namespace sensor
+} // end namespace flair
Index: /trunk/lib/FlairSensorActuator/src/Servos.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Servos.h	(revision 340)
+++ /trunk/lib/FlairSensorActuator/src/Servos.h	(revision 340)
@@ -0,0 +1,134 @@
+// %flair:license{
+// This file is part of the Flair framework distributed under the
+// CECILL-C License, Version 1.0.
+// %flair:license}
+/*!
+ * \file Servos.h
+ * \brief Base class for servos
+ * \author Guillaume Sanahuja, Copyright Heudiasyc UMR UTC/CNRS 7253
+ * \date 2019/11/28
+ * \version 4.0
+ */
+
+#ifndef SERVOS_H
+#define SERVOS_H
+
+#include <IODevice.h>
+#include <stdint.h>
+
+namespace flair {
+namespace gui {
+class Layout;
+class TabWidget;
+}
+}
+
+class Servos_impl;
+
+namespace flair {
+namespace actuator {
+/*! \class Servos
+*
+* \brief Base class for brushless motors drivers
+*/
+class Servos : public core::IODevice {
+  friend class ::Servos_impl;
+
+public:
+  /*!
+  * \brief Constructor
+  *
+  * Construct a Servos.
+  *
+  * \param parent parent
+  * \param layout layout
+  * \param name name
+  * \param servos_count number of servos
+  */
+  Servos(const core::IODevice *parent, gui::Layout *layout, std::string name,
+       uint8_t servos_count);
+
+  /*!
+  * \brief Destructor
+  *
+  */
+  ~Servos();
+
+  /*!
+  * \brief Lock user interface
+  *
+  */
+  void LockUserInterface(void) const;
+
+  /*!
+  * \brief Unlock user interface
+  *
+  */
+  void UnlockUserInterface(void) const;
+
+  /*!
+  * \brief Use default plot
+  *
+  * \param tabwidget TabWidget to draw plots
+  */
+  void UseDefaultPlot(gui::TabWidget *tabwidget);
+
+
+  /*!
+  * \brief Servos count
+  *
+  * \return number of servos
+  */
+  uint8_t ServosCount(void) const;
+
+  /*!
+  * \brief Enable servos
+  *
+  * \param true to enable all servos
+  */
+  void SetEnabled(bool status);
+
+  /*!
+  * \brief Are servos enabled?
+  *
+  * \return true if servos are enabled
+  */
+  bool AreEnabled(void) const;
+
+  /*!
+  * \brief Layout
+  *
+  * This the same Layout as passed to the constructor
+  *
+  * \return a Layout
+  */
+  gui::Layout *GetLayout(void) const;
+
+ 
+protected:
+  
+
+private:
+  /*!
+  * \brief Update using provided datas
+  *
+  * Reimplemented from IODevice.
+  *
+  * \param data data from the parent to process
+  */
+  void UpdateFrom(const core::io_data *data);
+
+  /*!
+  * \brief Set servos position
+  *
+  * values size must be the same as ServosCount()
+  *
+  * \param position set servos position
+  */
+  virtual void SetServos(float *position) = 0;
+
+  class Servos_impl *pimpl_;
+};
+} // end namespace actuator
+} // end namespace flair
+#endif // SERVOS_H
Index: /trunk/lib/FlairSensorActuator/src/Servos_impl.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/Servos_impl.cpp	(revision 340)
+++ /trunk/lib/FlairSensorActuator/src/Servos_impl.cpp	(revision 340)
@@ -0,0 +1,145 @@
+// %flair:license{
+// This file is part of the Flair framework distributed under the
+// CECILL-C License, Version 1.0.
+// %flair:license}
+//  created:    2019/11/28
+//  filename:   Servos_impl.cpp
+//
+//  author:     Guillaume Sanahuja
+//              Copyright Heudiasyc UMR UTC/CNRS 7253
+//
+//  version:    $Id: $
+//
+//  purpose:    Virtual class for servos
+//
+//
+/*********************************************************************/
+#include "Servos_impl.h"
+#include "Servos.h"
+#include <GridLayout.h>
+#include <GroupBox.h>
+#include <DoubleSpinBox.h>
+#include <Matrix.h>
+#include <Label.h>
+#include <PushButton.h>
+#include <DataPlot1D.h>
+#include <TabWidget.h>
+#include <Tab.h>
+#include <sstream>
+
+using std::string;
+using std::ostringstream;
+using namespace flair::core;
+using namespace flair::gui;
+using namespace flair::actuator;
+
+Servos_impl::Servos_impl(Servos *self, Layout *layout, string name,
+                     uint8_t servos_count) {
+  this->self = self;
+  this->servos_count = servos_count;
+  this->layout = layout;
+  are_enabled = false;
+  tested_servo = -1;
+
+  values = (float *)malloc(servos_count * sizeof(float));
+
+  // station sol
+  GroupBox *groupbox = new GroupBox(layout->NewRow(), "Servos");
+  min_value = new DoubleSpinBox(groupbox->NewRow(), "min value:", -3.15, 3.15, .1, 2);
+  max_value =
+      new DoubleSpinBox(groupbox->LastRowLastCol(), "max value:", -3.15, 3.15, .1, 2);
+  test_value =
+      new DoubleSpinBox(groupbox->LastRowLastCol(), "test value:", -3.15, 3.15, 0.1);
+
+  int index = 0;
+  button_test = (PushButton **)malloc(servos_count * sizeof(PushButton *));
+  for (int i = 0; i < servos_count / 2; i++) {
+    for (int j = 0; j < 2; j++) {
+      ostringstream test_name;
+      test_name << "test servo " << index;
+      button_test[index] =
+          new PushButton(groupbox->At(2 + i, j), test_name.str());
+      index++;
+    }
+  }
+}
+
+Servos_impl::~Servos_impl() {
+  if (values != NULL)
+    free(values);
+  if (button_test != NULL)
+    free(button_test);
+}
+
+void Servos_impl::UseDefaultPlot(TabWidget *tab) {
+ 
+}
+
+void Servos_impl::UpdateFrom(const io_data *data) {
+  Matrix *input = (Matrix *)data;
+  bool is_motor_running = false;
+
+  if (values == NULL)
+    return; // nothing to do in simulator
+
+  if (input->Rows() != servos_count) {
+    self->Err("nb servos mismatch\n");
+    return;
+  }
+
+  input->GetMutex();
+  for (int i = 0; i < servos_count; i++) {
+    if (are_enabled) {
+      // Printf("%i %f %f\n",i,input->ValueNoMutex(i,0),power[i]);
+      values[i] =Sat(input->ValueNoMutex(i, 0));
+      // Printf("%i %f\n",i,values[i]);
+    } else {
+      values[i] = 0;
+    }
+    if(values[i] != 0) is_motor_running = true;
+  }
+  input->ReleaseMutex();
+  
+
+  for (int i = 0; i < servos_count; i++) {
+    if (button_test[i]->Clicked() == true) {
+      if (!are_enabled) {
+        tested_servo = i;
+        test_start_time = GetTime();
+        LockUserInterface();
+      } else {
+        self->Warn("testing servo is not possible when enabled\n");
+      }
+    }
+  }
+  if (tested_servo != -1) {
+    for (int i = 0; i < servos_count; i++) {
+      values[i] = 0;
+    }
+    values[tested_servo] = test_value->Value();
+
+    if (GetTime() > (test_start_time + 2 * 1000000000)) {
+      tested_servo = -1;
+      UnlockUserInterface();
+    }
+  }
+
+  self->SetServos(values);
+}
+
+float Servos_impl::Sat(float value) {
+  float result = value;
+
+  if (result < min_value->Value()) {
+    result = min_value->Value();
+  }
+  if (result > max_value->Value()) {
+    result = max_value->Value();
+  }
+
+  return result;
+}
+
+void Servos_impl::LockUserInterface(void) const { layout->setEnabled(false); }
+
+void Servos_impl::UnlockUserInterface(void) const { layout->setEnabled(true); }
Index: /trunk/lib/FlairSensorActuator/src/SimulatedBldc.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/SimulatedBldc.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/SimulatedBldc.h	(revision 340)
@@ -20,5 +20,4 @@
 class SharedMem;
 class IODevice;
-class Matrix;
 }
 namespace gui {
Index: /trunk/lib/FlairSensorActuator/src/SimulatedServos.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/SimulatedServos.cpp	(revision 340)
+++ /trunk/lib/FlairSensorActuator/src/SimulatedServos.cpp	(revision 340)
@@ -0,0 +1,72 @@
+// %flair:license{
+// This file is part of the Flair framework distributed under the
+// CECILL-C License, Version 1.0.
+// %flair:license}
+//  created:    2019/11/28
+//  filename:   SimulatedServos.cpp
+//
+//  author:     Guillaume Sanahuja
+//              Copyright Heudiasyc UMR UTC/CNRS 7253
+//
+//  version:    $Id: $
+//
+//  purpose:    Class for a simulation servos
+//
+//
+/*********************************************************************/
+#ifdef CORE2_64
+
+#include "SimulatedServos.h"
+#include <FrameworkManager.h>
+#include <SharedMem.h>
+#include <Matrix.h>
+#include <sstream>
+#include <string.h>
+
+using std::string;
+using std::ostringstream;
+using namespace flair::core;
+using namespace flair::gui;
+
+namespace flair {
+namespace actuator {
+
+SimulatedServos::SimulatedServos(const IODevice *parent, Layout *layout, string name,
+                   uint8_t servos_count, uint32_t modelId,uint32_t deviceId)
+    : Servos(parent, layout, name, servos_count) {
+  shmem =
+      new SharedMem(this, ShMemName(modelId, deviceId), servos_count * sizeof(float)+sizeof(Time));
+
+  
+  buf=(char*)malloc(servos_count * sizeof(float)+sizeof(Time));
+  if(buf==NULL) {
+    Err("error creating buffer\n");
+    return;
+  }
+  SetIsReady(true);
+}
+
+SimulatedServos::~SimulatedServos() {
+  if(buf!=NULL) free(buf);
+}
+
+string SimulatedServos::ShMemName(uint32_t modelId,uint32_t deviceId) {
+  ostringstream dev_name;
+  dev_name << "simu" <<  modelId << "_servos_" << deviceId;
+  return dev_name.str().c_str();
+}
+
+void SimulatedServos::SetServos(float *position) {
+  float *values=(float*)buf;
+  for (int i = 0; i < ServosCount(); i++) values[i] = position[i];
+  Time time=GetTime();
+  memcpy(buf+ServosCount() * sizeof(float),&time,sizeof(Time));
+
+  shmem->Write(buf, ServosCount() * sizeof(float)+sizeof(Time));
+
+}
+
+} // end namespace sensor
+} // end namespace flair
+
+#endif
Index: /trunk/lib/FlairSensorActuator/src/SimulatedServos.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/SimulatedServos.h	(revision 340)
+++ /trunk/lib/FlairSensorActuator/src/SimulatedServos.h	(revision 340)
@@ -0,0 +1,73 @@
+// %flair:license{
+// This file is part of the Flair framework distributed under the
+// CECILL-C License, Version 1.0.
+// %flair:license}
+/*!
+ * \file SimulatedServos.h
+ * \brief Class for a simulation servos
+ * \author Guillaume Sanahuja, Copyright Heudiasyc UMR UTC/CNRS 7253
+ * \date 2019/11/28
+ * \version 4.0
+ */
+
+#ifndef SIMULATEDSERVOS_H
+#define SIMULATEDSERVOS_H
+
+#include <Servos.h>
+
+namespace flair {
+namespace core {
+class SharedMem;
+class IODevice;
+}
+}
+
+namespace flair {
+namespace actuator {
+/*! \class SimulatedServos
+*
+* \brief Class for a simulation bldc
+*
+*/
+class SimulatedServos : public Servos {
+public:
+  /*!
+  * \brief Constructor
+  *
+  * Construct a SimulatedServos
+  *
+  * \param parent parent
+  * \param layout layout
+  * \param name name
+  * \param servos_count number of servos
+  * \param modelId Model id
+  * \param deviceId Bldc id of the Model
+  */
+  SimulatedServos(const core::IODevice *parent, gui::Layout *layout, std::string name,
+           uint8_t servos_count, uint32_t modelId,uint32_t deviceId);
+
+  /*!
+  * \brief Destructor
+  *
+  */
+  ~SimulatedServos();
+
+private:
+  /*!
+  * \brief Set servos positions
+  *
+  * Reimplemented from Servos. \n
+  * Values size must be the same as ServosCount()
+  *
+  * \param positions positions values
+  */
+  void SetServos(float *positions);
+  
+  std::string ShMemName(uint32_t modelId,uint32_t deviceId);
+  core::SharedMem *shmem;
+  char *buf;
+
+};
+} // end namespace actuator
+} // end namespace flair
+#endif // SIMULATEDSERVOS_H
Index: /trunk/lib/FlairSensorActuator/src/UsRangeFinder.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/UsRangeFinder.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/UsRangeFinder.cpp	(revision 340)
@@ -49,17 +49,5 @@
 }
 
-UsRangeFinder::UsRangeFinder(const IODevice *parent, std::string name)
-    : IODevice(parent, name) {
-  plot_tab = NULL;
-  main_tab = NULL;
-  tab = NULL;
-  sensor_tab = NULL;
-  setup_groupbox = NULL;
-
-  output = NULL;
-}
-
 UsRangeFinder::~UsRangeFinder() {
-  if (main_tab != NULL)
     delete main_tab;
 }
@@ -76,9 +64,4 @@
 
 void UsRangeFinder::UseDefaultPlot(void) {
-  if (tab == NULL) {
-    Err("not applicable for simulation part.\n");
-    return;
-  }
-
   plot_tab = new Tab(tab, "Mesures");
   plot = new DataPlot1D(plot_tab->NewRow(), ObjectName(), 0, 2);
Index: /trunk/lib/FlairSensorActuator/src/UsRangeFinder.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/UsRangeFinder.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/UsRangeFinder.h	(revision 340)
@@ -49,15 +49,5 @@
   */
   UsRangeFinder(std::string name);
-
-  /*!
-  * \brief Constructor
-  *
-  * Construct a UsRangeFinder. Simulation part.
-  *
-  * \param parent parent
-  * \param name name
-  */
-  UsRangeFinder(const core::IODevice *parent, std::string name);
-
+  
   /*!
   * \brief Destructor
Index: /trunk/lib/FlairSensorActuator/src/V4LCamera.cpp
===================================================================
--- /trunk/lib/FlairSensorActuator/src/V4LCamera.cpp	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/V4LCamera.cpp	(revision 340)
@@ -33,4 +33,31 @@
 #define DEFAULT_V4L_BUFFERS 4
 
+#define CHANNEL_NUMBER 1
+#define CLEAR(x) memset (&(x), 0, sizeof (x))
+#define DEFAULT_V4L_WIDTH  640
+#define DEFAULT_V4L_HEIGHT 480
+#define CV_CAP_PROP_POS_MSEC       0
+#define CV_CAP_PROP_POS_FRAMES     1
+#define CV_CAP_PROP_POS_AVI_RATIO  2
+#define CV_CAP_PROP_FRAME_WIDTH    3
+#define CV_CAP_PROP_FRAME_HEIGHT   4
+#define CV_CAP_PROP_FPS            5
+#define CV_CAP_PROP_FOURCC         6
+#define CV_CAP_PROP_FRAME_COUNT    7
+#define CV_CAP_PROP_FORMAT         8
+#define CV_CAP_PROP_MODE           9
+#define CV_CAP_PROP_BRIGHTNESS    10
+#define CV_CAP_PROP_CONTRAST      11
+#define CV_CAP_PROP_SATURATION    12
+#define CV_CAP_PROP_HUE           13
+#define CV_CAP_PROP_GAIN          14
+#define CV_CAP_PROP_CONVERT_RGB   15
+#define CV_CAP_PROP_SHARPNESS     16
+#define CV_CAP_PROP_EXPOSURE      17
+#define CV_CAP_PROP_AUTOGAIN      18
+#define CV_CAP_PROP_AWB           19
+
+#define HAVE_CAMV4L2
+
 using std::string;
 using namespace flair::core;
@@ -39,5 +66,520 @@
 namespace flair {
 namespace sensor {
-
+  
+  V4LCamera::V4LCamera(string name,
+                     uint8_t camera_index, uint16_t width, uint16_t height,
+                     Image::Type::Format format, uint8_t priority)
+    : Thread(getFrameworkManager(), name, priority),
+      Camera(name, width, height, format) {
+  
+    string deviceName="/dev/video"+std::to_string(camera_index);
+    device = open(deviceName.c_str(), O_RDWR | O_NONBLOCK);
+    if (device == -1) {
+        Thread::Err("Cannot open %s\n",deviceName.c_str());
+    } else {
+        Printf("V4LCamera %s, opened %s\n",name.c_str(),deviceName.c_str());
+    }
+
+    /* w/o memset some parts  arent initialized - AKA: Fill it with zeros so it is clean */
+   memset(&capture,0,sizeof(CvCaptureCAM_V4L));
+   /* Present the routines needed for V4L funtionality.  They are inserted as part of
+      the standard set of cv calls promoting transparency.  "Vector Table" insertion. */
+   capture.FirstCapture = 1;
+   capture.deviceHandle = device;
+  
+     PALETTE_YUYV = 0;
+     PALETTE_UYVY= 0;
+    
+   n_buffers = 0;
+   if (_capture_V4L2 (&capture) == -1) {
+     Thread::Err("_capture_V4L2 failed\n");
+   }
+  
+if (icvSetPropertyCAM_V4L(&capture, CV_CAP_PROP_FRAME_WIDTH, width)<0)
+    Thread::Err("cvSetCaptureProperty error\n");
+  if (icvSetPropertyCAM_V4L(&capture, CV_CAP_PROP_FRAME_HEIGHT, height)<0)
+    Thread::Err("cvSetCaptureProperty error\n");
+
+  if (format == Image::Type::Format::UYVY) {
+    if (icvSetPropertyCAM_V4L(&capture, CV_CAP_PROP_FORMAT, V4L2_PIX_FMT_UYVY)<0)
+      Thread::Err("cvSetCaptureProperty error\n");
+  } else if (format == Image::Type::Format::YUYV) {
+    if (icvSetPropertyCAM_V4L(&capture, CV_CAP_PROP_FORMAT, V4L2_PIX_FMT_YUYV) <
+        0)
+      Thread::Err("cvSetCaptureProperty error\n");
+  } else {
+    Thread::Err("format not supported\n");
+  }
+    // ground station
+    gain = new DoubleSpinBox(GetGroupBox()->NewRow(), "gain:", 0, 1, 0.1);
+    exposure = new DoubleSpinBox(GetGroupBox()->LastRowLastCol(), "exposure:", 0,1, 0.1);
+    bright = new DoubleSpinBox(GetGroupBox()->LastRowLastCol(), "bright:", 0, 1, 0.1);
+    contrast = new DoubleSpinBox(GetGroupBox()->LastRowLastCol(), "contrast:", 0,1, 0.1);
+    hue = new DoubleSpinBox(GetGroupBox()->LastRowLastCol(), "hue:", 0, 1, 0.1);
+    sharpness = new DoubleSpinBox(GetGroupBox()->LastRowLastCol(), "sharpness:", 0, 1, 0.1);
+    sat = new DoubleSpinBox(GetGroupBox()->LastRowLastCol(), "saturation:", 0, 1,0.1);
+    autogain = new CheckBox(GetGroupBox()->NewRow(), "autogain:");
+    autoexposure = new CheckBox(GetGroupBox()->LastRowLastCol(), "autoexposure:");
+    awb = new CheckBox(GetGroupBox()->LastRowLastCol(), "awb:");
+    fps = new Label(GetGroupBox()->NewRow(), "fps");
+
+    hasProblems=false;
+}
+
+V4LCamera::~V4LCamera() {
+    for (int n_buffers = 0; n_buffers < nbBuffers; n_buffers++) {
+       //FreeFunction((char*)buffers[n_buffers].start);
+   }
+    SafeStop();
+    Join();
+}
+int V4LCamera::icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture,
+                                  int property_id, double value ){
+    static int width = 0, height = 0;
+    int retval;
+
+    /* initialization */
+    retval = 0;
+
+    /* two subsequent calls setting WIDTH and HEIGHT will change
+       the video size */
+    /* the first one will return an error, though. */
+
+    switch (property_id) {
+    case CV_CAP_PROP_FRAME_WIDTH:
+        width = value;
+        if(width !=0 && height != 0) {
+            retval = icvSetVideoSize( capture, width, height);
+            width = height = 0;
+        }
+        break;
+    case CV_CAP_PROP_FRAME_HEIGHT:
+        height = value;
+        if(width !=0 && height != 0) {
+            retval = icvSetVideoSize( capture, width, height);
+            width = height = 0;
+        }
+        break;
+    case CV_CAP_PROP_FORMAT:
+
+	capture->form.fmt.pix.pixelformat = (unsigned long)value; 
+ 	retval == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
+	if ((unsigned long)value != capture->form.fmt.pix.pixelformat)
+   		retval=-1;
+
+	
+	PALETTE_YUYV = 0;
+	PALETTE_UYVY= 0;
+	
+
+	if ((unsigned long)value== V4L2_PIX_FMT_YUYV)
+	{
+		PALETTE_YUYV = 1;
+	}
+	if ((unsigned long)value== V4L2_PIX_FMT_UYVY)
+	{
+		PALETTE_UYVY = 1;
+	}
+	
+
+	break;
+    case CV_CAP_PROP_BRIGHTNESS:
+    case CV_CAP_PROP_CONTRAST:
+    case CV_CAP_PROP_SATURATION:
+    case CV_CAP_PROP_HUE:
+    case CV_CAP_PROP_GAIN:
+    case CV_CAP_PROP_SHARPNESS:
+    case CV_CAP_PROP_EXPOSURE:
+    case CV_CAP_PROP_AUTOGAIN:
+    case CV_CAP_PROP_AWB:
+        retval = icvSetControl(capture, property_id, value);
+        break;
+    default:
+        fprintf(stderr,
+                "HIGHGUI ERROR: V4L: setting property #%d is not supported\n",
+                property_id);
+    }
+
+    /* return the the status */
+    return retval;
+}
+int V4LCamera::icvSetControl (CvCaptureCAM_V4L* capture,
+                          int property_id, double value) {
+  
+  /* limitation of the input value */
+  if (value < 0.0) {
+    value = 0.0;
+  } else if (value > 1.0) {
+    value = 1.0;
+  }
+
+
+    /* default value for min and max */
+    int v4l2_min = 0;
+    int v4l2_max = 255;
+
+    /* initialisations */
+    CLEAR (capture->control);
+
+    /* set which control we want to set */
+    switch (property_id) {
+
+    case CV_CAP_PROP_BRIGHTNESS:
+        capture->control.id = V4L2_CID_BRIGHTNESS;
+        break;
+    case CV_CAP_PROP_CONTRAST:
+        capture->control.id = V4L2_CID_CONTRAST;
+        break;
+    case CV_CAP_PROP_SATURATION:
+        capture->control.id = V4L2_CID_SATURATION;
+        break;
+    case CV_CAP_PROP_HUE:
+        capture->control.id = V4L2_CID_HUE;
+        break;
+    case CV_CAP_PROP_GAIN:
+        capture->control.id = V4L2_CID_GAIN;
+        break;
+    case CV_CAP_PROP_SHARPNESS:
+        capture->control.id = V4L2_CID_SHARPNESS;
+        break;
+    case CV_CAP_PROP_EXPOSURE:
+        capture->control.id = V4L2_CID_EXPOSURE;
+        break;
+    case CV_CAP_PROP_AUTOGAIN:
+        capture->control.id = V4L2_CID_AUTOGAIN;
+        break;
+    case CV_CAP_PROP_AWB:
+        capture->control.id = V4L2_CID_AUTO_WHITE_BALANCE;
+	break;
+    default:
+        fprintf(stderr,
+                "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n",
+                property_id);
+        return -1;
+    }
+
+    /* get the min and max values */
+    if (-1 == xioctl (capture->deviceHandle,
+                      VIDIOC_G_CTRL, &capture->control)) {
+//          perror ("VIDIOC_G_CTRL for getting min/max values");
+          return -1;
+    }
+
+    /* get the min/max values */
+    switch (property_id) {
+
+    case CV_CAP_PROP_BRIGHTNESS:
+        v4l2_min = capture->v4l2_brightness_min;
+        v4l2_max = capture->v4l2_brightness_max;
+        break;
+    case CV_CAP_PROP_CONTRAST:
+        v4l2_min = capture->v4l2_contrast_min;
+        v4l2_max = capture->v4l2_contrast_max;
+        break;
+    case CV_CAP_PROP_SATURATION:
+        v4l2_min = capture->v4l2_saturation_min;
+        v4l2_max = capture->v4l2_saturation_max;
+        break;
+    case CV_CAP_PROP_HUE:
+        v4l2_min = capture->v4l2_hue_min;
+        v4l2_max = capture->v4l2_hue_max;
+        break;
+    case CV_CAP_PROP_GAIN:
+        v4l2_min = capture->v4l2_gain_min;
+        v4l2_max = capture->v4l2_gain_max;
+	break;
+    case CV_CAP_PROP_SHARPNESS:
+        v4l2_min = capture->v4l2_sharpness_min;
+        v4l2_max = capture->v4l2_sharpness_max;
+	break;
+    case CV_CAP_PROP_EXPOSURE:
+        v4l2_min = capture->v4l2_exposure_min;
+        v4l2_max = capture->v4l2_exposure_max;
+        break;
+    case CV_CAP_PROP_AUTOGAIN:
+        v4l2_min = capture->v4l2_autogain_min;
+        v4l2_max = capture->v4l2_autogain_max;
+        break;
+    case CV_CAP_PROP_AWB:
+        v4l2_min = capture->v4l2_awb_min;
+        v4l2_max = capture->v4l2_awb_max;
+        break;
+    }
+
+    /* initialisations */
+    CLEAR (capture->control);
+
+    /* set which control we want to set */
+    switch (property_id) {
+
+    case CV_CAP_PROP_BRIGHTNESS:
+        capture->control.id = V4L2_CID_BRIGHTNESS;
+        break;
+    case CV_CAP_PROP_CONTRAST:
+        capture->control.id = V4L2_CID_CONTRAST;
+        break;
+    case CV_CAP_PROP_SATURATION:
+        capture->control.id = V4L2_CID_SATURATION;
+        break;
+    case CV_CAP_PROP_HUE:
+        capture->control.id = V4L2_CID_HUE;
+        break;
+    case CV_CAP_PROP_GAIN:
+        capture->control.id = V4L2_CID_GAIN;
+        break;
+   case CV_CAP_PROP_SHARPNESS:
+        capture->control.id = V4L2_CID_SHARPNESS;
+        break;
+    case CV_CAP_PROP_EXPOSURE:
+        capture->control.id = V4L2_CID_EXPOSURE;
+        break;
+    case CV_CAP_PROP_AUTOGAIN:
+        capture->control.id = V4L2_CID_AUTOGAIN;
+        break;
+    case CV_CAP_PROP_AWB:
+        capture->control.id = V4L2_CID_AUTO_WHITE_BALANCE;
+        break;
+    default:
+        fprintf(stderr,
+                "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n",
+                property_id);
+        return -1;
+    }
+
+    /* set the value we want to set to the scaled the value */
+    capture->control.value = (int)(value * (v4l2_max - v4l2_min) + v4l2_min);
+
+    /* The driver may clamp the value or return ERANGE, ignored here */
+    if (-1 == xioctl (capture->deviceHandle,
+                      VIDIOC_S_CTRL, &capture->control) && errno != ERANGE) {
+        perror ("VIDIOC_S_CTRL");
+        return -1;
+    }
+
+  /* all was OK */
+  return 0;
+
+}
+int V4LCamera::_capture_V4L2 (CvCaptureCAM_V4L *capture)
+{
+   int detect_v4l2 = 0;
+
+   detect_v4l2 = try_init_v4l2(capture);
+
+   if (detect_v4l2 != 1) {
+       /* init of the v4l2 device is not OK */
+       return -1;
+   }
+
+   /* Init V4L2 control variables */
+   capture->v4l2_brightness = 0;
+   capture->v4l2_contrast = 0;
+   capture->v4l2_saturation = 0;
+   capture->v4l2_hue = 0;
+   capture->v4l2_gain = 0;
+   capture->v4l2_sharpness = 0;
+   capture->v4l2_exposure = 0;
+   capture->v4l2_autogain = 0;
+   capture->v4l2_awb = 0;
+
+   capture->v4l2_brightness_min = 0;
+   capture->v4l2_contrast_min = 0;
+   capture->v4l2_saturation_min = 0;
+   capture->v4l2_hue_min = 0;
+   capture->v4l2_gain_min = 0;
+   capture->v4l2_sharpness_min = 0;
+   capture->v4l2_exposure_min = 0;
+   capture->v4l2_autogain_min = 0;
+   capture->v4l2_awb_min = 0;
+
+   capture->v4l2_brightness_max = 0;
+   capture->v4l2_contrast_max = 0;
+   capture->v4l2_saturation_max = 0;
+   capture->v4l2_hue_max = 0;
+   capture->v4l2_gain_max = 0;
+   capture->v4l2_sharpness_max = 0;
+   capture->v4l2_exposure_max = 0;
+   capture->v4l2_autogain_max = 0;
+   capture->v4l2_awb_max = 0;
+     
+  
+   if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
+      /* Nope. */
+      fprintf( stderr, "HIGHGUI ERROR: V4L2: device is unable to capture video memory.\n");
+      
+      return -1;
+   }
+
+  
+
+   /* Find Window info */
+   CLEAR (capture->form);
+   capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        
+   if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
+       fprintf( stderr, "HIGHGUI ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
+       
+       return -1;
+   }
+
+  
+
+   if (autosetup_capture_mode_v4l2(capture) == -1)
+       return -1;
+
+   icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT);
+
+   unsigned int min;
+
+   /* Buggy driver paranoia. */
+   min = capture->form.fmt.pix.width * 2;
+
+   if (capture->form.fmt.pix.bytesperline < min)
+       capture->form.fmt.pix.bytesperline = min;
+
+   min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
+ 
+   if (capture->form.fmt.pix.sizeimage < min)
+       capture->form.fmt.pix.sizeimage = min;
+
+   return 1;
+}
+int V4LCamera::icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
+
+
+
+    CLEAR (capture->crop);
+    capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    capture->crop.c.left       = 0; 
+    capture->crop.c.top        = 0; 
+    capture->crop.c.height     = h*24;
+    capture->crop.c.width      = w*24;
+
+    /* set the crop area, but don't exit if the device don't support croping */
+    xioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop);
+
+    CLEAR (capture->form);
+    capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+    /* read the current setting, mainly to retreive the pixelformat information */
+    xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form);
+
+    /* set the values we want to change */
+    capture->form.fmt.pix.width = w; 
+    capture->form.fmt.pix.height = h;
+    capture->form.fmt.win.chromakey = 0;
+    capture->form.fmt.win.field = V4L2_FIELD_ANY;
+    capture->form.fmt.win.clips = 0;
+    capture->form.fmt.win.clipcount = 0;
+    capture->form.fmt.pix.field = V4L2_FIELD_ANY;
+
+    /* ask the device to change the size
+     * don't test if the set of the size is ok, because some device
+     * don't allow changing the size, and we will get the real size
+     * later */
+    xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
+
+    /* try to set framerate to 30 fps */
+    struct v4l2_streamparm setfps;  
+    memset (&setfps, 0, sizeof(struct v4l2_streamparm));
+    setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    setfps.parm.capture.timeperframe.numerator = 1;
+    setfps.parm.capture.timeperframe.denominator = 30;
+    xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
+
+    /* we need to re-initialize some things, like buffers, because the size has
+     * changed */
+    capture->FirstCapture = 1;
+
+    /* Get window info again, to get the real value */
+    if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form))
+    {
+      fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n");
+
+      
+
+      return 0;
+    }
+
+    return 0;
+
+  
+
+   
+  return 0;
+
+}
+int V4LCamera::try_palette_v4l2(CvCaptureCAM_V4L* capture, unsigned long colorspace)
+{
+  CLEAR (capture->form);
+
+  capture->form.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  capture->form.fmt.pix.pixelformat = colorspace;
+  capture->form.fmt.pix.field       = V4L2_FIELD_ANY;
+  capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH;
+  capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT;
+  
+  if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form))
+      return -1;
+
+  
+  if (colorspace != capture->form.fmt.pix.pixelformat)
+    return -1;
+  else
+    return 0;
+}
+int V4LCamera::autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture)
+{
+  if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0) {
+    PALETTE_YUYV = 1;
+  } else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0) {
+    PALETTE_UYVY = 1;
+  } else {
+	fprintf(stderr, "HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
+   
+    return -1;
+  }
+  
+  return 0;
+
+}
+
+
+
+int V4LCamera::try_init_v4l2(CvCaptureCAM_V4L* capture)
+{
+
+  // if detect = -1 then unable to open device
+  // if detect = 0 then detected nothing
+  // if detect = 1 then V4L2 device 
+  int detect = 0;
+
+
+  if (detect == 0)
+  {
+    CLEAR (capture->cap);
+    if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
+    {
+      detect = 0;
+
+      
+    }
+      else
+    {
+      CLEAR (capture->capability);
+      capture->capability.type = capture->cap.capabilities;
+     
+      /* Query channels number */
+      if (-1 != xioctl (capture->deviceHandle, VIDIOC_G_INPUT, &capture->capability.channels))
+      {
+        detect = 1;
+      }
+    }
+  }
+
+  return detect;
+
+}
+/*
 V4LCamera::V4LCamera(string name,
                      uint8_t camera_index, uint16_t width, uint16_t height,
@@ -221,5 +763,362 @@
   close(device);
 }
-
+*/
+int V4LCamera::v4l2_alloc_buffers (CvCaptureCAM_V4L *capture, char *deviceName)
+{
+   CLEAR (capture->req);
+   
+   unsigned int buffer_number = DEFAULT_V4L_BUFFERS;
+
+   try_again:
+   
+   capture->req.count = buffer_number;
+   capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+   capture->req.memory = V4L2_MEMORY_MMAP;
+
+   if (-1 == xioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
+   {
+       if (EINVAL == errno)
+       {
+         fprintf (stderr, "%s does not support memory mapping\n", deviceName);
+       } else {
+         perror ("VIDIOC_REQBUFS");
+       }
+       /* free capture, and returns an error code */
+       
+       return -1;
+   }
+
+   if (capture->req.count < buffer_number)
+   {
+       if (buffer_number == 1)
+       {
+           fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
+
+           /* free capture, and returns an error code */
+           
+           return -1;
+       } else {
+         buffer_number--;
+	 fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
+	 
+	 goto try_again;
+       }
+   }
+
+   for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
+   {
+       struct v4l2_buffer buf;
+
+       CLEAR (buf);
+
+       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf.memory = V4L2_MEMORY_MMAP;
+       buf.index = n_buffers;
+
+       if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
+           perror ("VIDIOC_QUERYBUF");
+       
+           /* free capture, and returns an error code */
+           
+           return -1;
+       }
+
+       capture->buffers[n_buffers].length = buf.length;
+       capture->buffers[n_buffers].start =
+         mmap (NULL /* start anywhere */,
+               buf.length,
+               PROT_READ | PROT_WRITE /* required */,
+               MAP_SHARED /* recommended */,
+               capture->deviceHandle, buf.m.offset);
+
+       if (MAP_FAILED == capture->buffers[n_buffers].start) {
+           perror ("mmap");
+       
+           /* free capture, and returns an error code */
+           
+           return -1;
+       }
+
+
+   }
+
+   /* Set up Image data */
+   /*
+   cvInitImageHeader( &capture->frame,
+                      cvSize( capture->captureWindow.width,
+                              capture->captureWindow.height ),
+                      IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );*/
+   /* Allocate space for RGBA data */
+   capture->imageSize=capture->form.fmt.pix.width*capture->form.fmt.pix.height*2;
+   capture->imageData = AllocFunction(capture->imageSize);
+   Printf("cmem allocated %i at %x\n",capture->imageSize,capture->imageData);
+   
+   return 1;
+};
+int V4LCamera::cvGrabFrame(CvCaptureCAM_V4L* capture) {
+
+   if (capture->FirstCapture) { 
+      /* Some general initialization must take place the first time through */
+
+      /* This is just a technicality, but all buffers must be filled up before any
+         staggered SYNC is applied.  SO, filler up. (see V4L HowTo) */
+
+
+	v4l2_alloc_buffers (capture, NULL);
+
+        for (capture->bufferIndex = 0;
+             capture->bufferIndex < ((int)capture->req.count);
+             ++capture->bufferIndex)
+        {
+
+          struct v4l2_buffer buf;
+
+          CLEAR (buf);
+
+          buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+          buf.memory      = V4L2_MEMORY_MMAP;
+          buf.index       = (unsigned long)capture->bufferIndex;
+
+          if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
+              perror ("VIDIOC_QBUF");
+              return 0;
+          }
+        }
+
+        /* enable the streaming */
+        capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        if (-1 == xioctl (capture->deviceHandle, VIDIOC_STREAMON,
+                          &capture->type)) {
+            /* error enabling the stream */
+            perror ("VIDIOC_STREAMON");
+            return 0;
+        }
+
+      
+
+
+      /* preparation is ok */
+      capture->FirstCapture = 0;
+   }
+
+
+
+     mainloop_v4l2(capture);
+
+
+
+   return(1);
+}
+void V4LCamera::mainloop_v4l2(CvCaptureCAM_V4L* capture) {
+    unsigned int count;
+
+    count = 1;
+
+    while (count-- > 0) {
+        for (;;) {
+            fd_set fds;
+            struct timeval tv;
+            int r;
+
+            FD_ZERO (&fds);
+            FD_SET (capture->deviceHandle, &fds);
+
+            /* Timeout. */
+            tv.tv_sec = 2;
+            tv.tv_usec = 0;
+
+            r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
+
+            if (-1 == r) {
+                if (EINTR == errno)
+                    continue;
+
+                perror ("select");
+            }
+
+            if (0 == r) {
+                fprintf (stderr, "select timeout\n");
+
+                /* end the infinite loop */
+                break;
+            }
+
+            if (read_frame_v4l2 (capture))
+                break;
+        }
+    }
+}
+int V4LCamera::read_frame_v4l2(CvCaptureCAM_V4L* capture) {
+    struct v4l2_buffer buf;
+
+    CLEAR (buf);
+
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buf.memory = V4L2_MEMORY_MMAP;
+
+    if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
+        switch (errno) {
+        case EAGAIN:
+            return 0;
+
+        case EIO:
+            /* Could ignore EIO, see spec. */
+
+            /* fall through */
+
+        default:
+            /* display the error and stop processing */
+            perror ("VIDIOC_DQBUF");
+            return 1;
+        }
+   }
+
+   if(buf.index >= capture->req.count) {
+     Thread::Err("buf.index >= capture->req.count\n");
+   }
+   
+
+   capture->bufferIndex = buf.index;
+
+
+   if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
+       perror ("VIDIOC_QBUF");
+
+   return 1;
+}
+void V4LCamera::Run(void) {
+  Time cam_time, new_time, fpsNow, fpsPrev;
+  //IplImage *img; // raw image
+  int fpsCounter = 0;
+
+  // init image old
+  if (!cvGrabFrame(&capture)) {
+    Printf("Could not grab a frame\n");
+  }
+  cam_time = GetTime();
+  fpsPrev = cam_time;
+
+  while (!ToBeStopped()) {
+    
+   
+    // fps counter
+    fpsCounter++;
+    if (fpsCounter == 100) {
+      fpsNow = GetTime();
+      fps->SetText("fps: %.1f",
+       fpsCounter / ((float)(fpsNow - fpsPrev) / 1000000000.));
+      fpsCounter = 0;
+      fpsPrev = fpsNow;
+    }
+
+    // cam properties
+    if (gain->ValueChanged() == true && autogain->Value() == false)
+      SetGain(gain->Value());
+    if (exposure->ValueChanged() == true && autoexposure->Value() == false)
+      SetExposure(exposure->Value());
+    if (bright->ValueChanged() == true)
+      SetBrightness(bright->Value());
+    if (sat->ValueChanged() == true)
+      SetSaturation(sat->Value());
+    if (contrast->ValueChanged() == true)
+      SetContrast(contrast->Value());
+    if (hue->ValueChanged() == true)
+      SetHue(hue->Value());
+    //if (sharpness->ValueChanged() == true)
+    //  cvSetCaptureProperty(capture, CV_CAP_PROP_SHARPNESS, sharpness->Value());
+    if (autogain->ValueChanged() == true) {
+      if (autogain->Value() == true) {
+        gain->setEnabled(false);
+      } else {
+        gain->setEnabled(true);
+        SetGain(gain->Value());
+      }
+      SetAutoGain(autogain->Value());
+    }
+    if (autoexposure->ValueChanged() == true) {
+      if (autoexposure->Value() == true) {
+        exposure->setEnabled(false);
+      } else {
+        exposure->setEnabled(true);
+        SetExposure(exposure->Value());
+      }
+      SetAutoExposure(autoexposure->Value());
+    }
+    //if (awb->ValueChanged() == true)
+    //  cvSetCaptureProperty(capture, CV_CAP_PROP_AWB, awb->Value());
+   
+    // cam pictures
+    cvRetrieveRawFrame(&capture);
+    if (!cvGrabFrame(&capture)) {
+      Printf("Could not grab a frame\n");
+    }
+    new_time = GetTime();
+        
+    //check for ps3eye deconnection in hds uav
+    if(new_time-cam_time>100*1000*1000) {
+      Thread::Warn("delta trop grand\n");
+      hasProblems=true;
+    }
+
+    output->GetMutex();
+    
+    output->buffer=capture.imageData;
+    output->ReleaseMutex();
+   
+    output->SetDataTime(cam_time);
+    ProcessUpdate(output);
+    cam_time = new_time;
+  }
+
+  //cvReleaseCapture(&capture);
+}
+
+void V4LCamera::cvRetrieveRawFrame( CvCaptureCAM_V4L* capture) {
+
+
+
+
+   /* Now get what has already been captured as a IplImage return */
+
+   /* First, reallocate imageData if the frame size changed */
+
+
+/*
+    if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width)
+       || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
+           if (PALETTE_YUYV == 1 || PALETTE_UYVY == 1)
+           {
+                cvFree(&capture->frame.imageData);
+                cvInitImageHeader( &capture->frame,
+                cvSize( capture->form.fmt.pix.width,
+                capture->form.fmt.pix.height ),
+                IPL_DEPTH_8U,2, IPL_ORIGIN_TL, 4 );
+                capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
+           }else
+           {
+              fprintf( stderr,
+                 "HIGHGUI ERROR: V4L: raw output not supported for this palette\n");
+           }
+
+    }
+
+ */
+
+
+    if (PALETTE_YUYV == 1){
+         memcpy((char *)capture->imageData,
+             (char *)capture->buffers[capture->bufferIndex].start,
+             capture->imageSize);
+    }
+    if (PALETTE_UYVY == 1){
+        memcpy((char *)capture->imageData,
+             (char *)capture->buffers[capture->bufferIndex].start,
+             capture->imageSize);
+    }
+  
+ 
+
+   
+}
 int V4LCamera::QueueBuffer(int index) {
     struct v4l2_buffer buf;
Index: /trunk/lib/FlairSensorActuator/src/V4LCamera.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/V4LCamera.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/V4LCamera.h	(revision 340)
@@ -163,4 +163,64 @@
   char* frame;
   int nbBuffers;
+  
+    typedef struct CvCaptureCAM_V4L
+{
+    int deviceHandle;
+    int bufferIndex;
+    int FirstCapture;
+    struct video_capability capability;
+    struct video_window     captureWindow;
+    struct video_picture    imageProperties; 
+    struct video_mbuf       memoryBuffer;
+    struct video_mmap       *mmaps;
+    char *memoryMap;
+    //IplImage frame;
+char *imageData;
+int imageSize;
+
+   /* V4L2 variables */
+   buffer buffers[MAX_V4L_BUFFERS + 1];
+   struct v4l2_capability cap;
+   struct v4l2_input inp;
+   struct v4l2_format form;
+   struct v4l2_crop crop;
+   struct v4l2_cropcap cropcap;
+   struct v4l2_requestbuffers req;
+   struct v4l2_jpegcompression compr;
+   struct v4l2_control control;
+   enum v4l2_buf_type type;
+   struct v4l2_queryctrl queryctrl;
+   struct v4l2_querymenu querymenu;
+
+   /* V4L2 control variables */
+   int v4l2_brightness, v4l2_brightness_min, v4l2_brightness_max;
+   int v4l2_contrast, v4l2_contrast_min, v4l2_contrast_max;
+   int v4l2_saturation, v4l2_saturation_min, v4l2_saturation_max;
+   int v4l2_sharpness, v4l2_sharpness_min, v4l2_sharpness_max;
+   int v4l2_exposure, v4l2_exposure_min, v4l2_exposure_max;
+   int v4l2_hue, v4l2_hue_min, v4l2_hue_max;
+   int v4l2_gain, v4l2_gain_min, v4l2_gain_max;
+   int v4l2_autogain, v4l2_autogain_min, v4l2_autogain_max;
+   int v4l2_awb, v4l2_awb_min, v4l2_awb_max;
+
+
+
+} CvCaptureCAM_V4L;
+
+CvCaptureCAM_V4L capture;
+int _capture_V4L2 (CvCaptureCAM_V4L *capture);
+int try_init_v4l2(CvCaptureCAM_V4L* capture);
+int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture);
+int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h);
+int try_palette_v4l2(CvCaptureCAM_V4L* capture, unsigned long colorspace);
+int  PALETTE_YUYV,PALETTE_UYVY;
+int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture,int property_id, double value );
+int icvSetControl (CvCaptureCAM_V4L* capture,int property_id, double value) ;
+int cvGrabFrame(CvCaptureCAM_V4L* capture);
+int v4l2_alloc_buffers (CvCaptureCAM_V4L *capture, char *deviceName);
+void mainloop_v4l2(CvCaptureCAM_V4L* capture);
+int read_frame_v4l2(CvCaptureCAM_V4L* capture);
+void cvRetrieveRawFrame( CvCaptureCAM_V4L* capture);
+unsigned int n_buffers ;
 };
 } // end namespace sensor
Index: /trunk/lib/FlairSensorActuator/src/unexported/Bldc_impl.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/unexported/Bldc_impl.h	(revision 339)
+++ /trunk/lib/FlairSensorActuator/src/unexported/Bldc_impl.h	(revision 340)
@@ -40,5 +40,4 @@
   Bldc_impl(flair::actuator::Bldc *self, flair::gui::Layout *layout,
             std::string name, uint8_t motors_count);
-  Bldc_impl(flair::actuator::Bldc *self, uint8_t motors_count); // simulation
   ~Bldc_impl();
   void UpdateFrom(const flair::core::io_data *data);
Index: /trunk/lib/FlairSensorActuator/src/unexported/Servos_impl.h
===================================================================
--- /trunk/lib/FlairSensorActuator/src/unexported/Servos_impl.h	(revision 340)
+++ /trunk/lib/FlairSensorActuator/src/unexported/Servos_impl.h	(revision 340)
@@ -0,0 +1,62 @@
+// %flair:license{
+// This file is part of the Flair framework distributed under the
+// CECILL-C License, Version 1.0.
+// %flair:license}
+//  created:    2019/11/28
+//  filename:   Servos_impl.h
+//
+//  author:     Guillaume Sanahuja
+//              Copyright Heudiasyc UMR UTC/CNRS 7253
+//
+//  version:    $Id: $
+//
+//  purpose:    Virtual class for servos
+//
+//
+/*********************************************************************/
+
+#ifndef SERVOS_IMPL_H
+#define SERVOS_IMPL_H
+
+#include <IODevice.h>
+#include <stdint.h>
+
+namespace flair {
+namespace gui {
+class DoubleSpinBox;
+class Layout;
+class Label;
+class DataPlot1D;
+class TabWidget;
+class PushButton;
+}
+namespace actuator {
+class Servos;
+}
+}
+
+class Servos_impl {
+public:
+  Servos_impl(flair::actuator::Servos *self, flair::gui::Layout *layout,
+            std::string name, uint8_t servos_count);
+  ~Servos_impl();
+  void UpdateFrom(const flair::core::io_data *data);
+  void LockUserInterface(void) const;
+  void UnlockUserInterface(void) const;
+  bool are_enabled;
+  void UseDefaultPlot(flair::gui::TabWidget *tab);
+  uint8_t servos_count;
+  flair::gui::Layout *layout;
+
+private:
+  float *values;
+  float Sat(float value);
+  flair::actuator::Servos *self;
+  flair::gui::DoubleSpinBox *min_value, *max_value, *test_value;
+  flair::gui::DataPlot1D *plots;
+  flair::gui::PushButton **button_test;
+  flair::core::Time test_start_time;
+  int tested_servo; //=-1 if no servo is tested
+};
+
+#endif // SERVOS_IMPL_H
