docs: def from_config(config, strict=True, sync=True, use_dummy_io=False, **extra):
      """ Returns a :class:`~pypot.robot.robot.Robot` instance created from a configuration dictionnary.
  
          :param dict config: robot configuration dictionary
          :param bool strict: make sure that all ports, motors are availaible.
          :param bool sync: choose if automatically starts the synchronization loops
  
          For details on how to write such a configuration dictionnary, you should refer to the section :ref:`config_file`.
  
          """
      logger.info('Loading config... ', extra={'config': config})
  
      alias = config['motorgroups']
  
      # Instatiate the different motor controllers
      controllers = []
      for c_name, c_params in config['controllers'].items():
          motor_names = sum([_motor_extractor(alias, name)
                             for name in c_params['attached_motors']], [])
  
          attached_motors = [motor_from_confignode(config, name)
                             for name in motor_names]
  
          # at least one of the motor is set as broken
          if [m for m in attached_motors if m._broken]:
              strict = False
  
          attached_ids = [m.id for m in attached_motors]
          if not use_dummy_io:
              dxl_io = dxl_io_from_confignode(config, c_params, attached_ids, strict)
  
              check_motor_eprom_configuration(config, dxl_io, motor_names)
  
              logger.info('Instantiating controller on %s with motors %s',
                          dxl_io.port, motor_names,
                          extra={'config': config})
  
              syncloop = (c_params['syncloop'] if 'syncloop' in c_params
                          else 'BaseDxlController')
              SyncLoopCls = getattr(pypot.dynamixel.syncloop, syncloop)
  
              c = SyncLoopCls(dxl_io, attached_motors)
              controllers.append(c)
          else:
              controllers.append(DummyController(attached_motors))
  
      try:
          robot = Robot(motor_controllers=controllers, sync=sync)
      except RuntimeError:
          for c in controllers:
              c.io.close()
  
          raise
  
      make_alias(config, robot)
  
      # Create all sensors and attached them
      try:
          if 'sensors' in config and not use_dummy_io:
              sensors = []
              for s_name in config['sensors'].keys():
                  if s_name in extra and extra[s_name] == 'dummy':
                      config['sensors'][s_name]['type'] = 'Dummy{}'.format(s_name.capitalize())
  
                  sensor = sensor_from_confignode(config, s_name, robot)
                  setattr(robot, s_name, sensor)
                  sensors.append(sensor)
                  robot.sensors.append(sensor)
  
              [s.start() for s in sensors if hasattr(s, 'start')]
  
      # If anything goes wrong when adding sensors
      # We have to make sure we close the robot properly
      # Otherwise trying to open it again will fail.
      except Exception:
          robot.close()
          raise
  
      logger.info('Loading complete!',
                  extra={'config': config})
  
      return robot