Source code for pypot.robot.controller

import time

from math import copysign

from ..utils.stoppablethread import StoppableLoopThread


[docs]class AbstractController(StoppableLoopThread): """ Abstract class for motor/sensor controller. The controller role is to synchronize the reading/writing of a set of instances with their "hardware" equivalent through an :class:`~pypot.robot.io.AbstractIO` object. It is defined as a :class:`~pypot.utils.stoppablethread.StoppableLoopThread` where each loop update synchronizes values from the "software" objects with their "hardware" equivalent. To define your Controller, you need to define the :meth:`~pypot.utils.stoppablethread.StoppableLoopThread.update` method. This method will be called at the predefined frequency. An exemple of how to do it can be found in :class:`~pypot.dynamixel.controller.BaseDxlController`. """ def __init__(self, io, sync_freq): """ :param io: IO used to communicate with the hardware motors :type io: :class:`~pypot.robot.io.AbstractIO` :param float sync_freq: synchronization frequency """ StoppableLoopThread.__init__(self, sync_freq) self.io = io
[docs] def start(self): StoppableLoopThread.start(self) self.wait_to_start()
[docs] def close(self): """ Cleans and closes the controller. """ self.stop() if self.io is not None: self.io.close()
[docs]class MotorsController(AbstractController): """ Abstract class for motors controller. The controller synchronizes the reading/writing of a set of motor instances with their "hardware". Each update loop synchronizes values from the "software" :class:`~pypot.dynamixel.motor.DxlMotor` with their "hardware" equivalent. """ def __init__(self, io, motors, sync_freq=50): """ :param io: IO used to communicate with the hardware motors :type io: :class:`~pypot.robot.io.AbstractIO` :param list motors: list of motors attached to the controller :param float sync_freq: synchronization frequency """ AbstractController.__init__(self, io, sync_freq) self.motors = motors
[docs]class DummyController(MotorsController): def __init__(self, motors): MotorsController.__init__(self, None, motors) self.max_speed = 360.0 # degree per second.
[docs] def setup(self): self.last_update = time.time() for m in self.motors: m.__dict__['moving_speed'] = 0.0 m.__dict__['present_position'] = 0.0 m.__dict__['goal_position'] = 0.0
[docs] def update(self): delta_t = time.time() - self.last_update for m in self.motors: # acceleration infinite, present_speed always equal moving_speed delta_pos = m.__dict__['goal_position'] - m.__dict__['present_position'] # degree # degree par second, assumed absolute speed = (m.__dict__['moving_speed'] if m.__dict__['moving_speed'] != 0.0 else self.max_speed) delta_pos_effective = copysign(speed * delta_t, delta_pos) if abs(delta_pos_effective) >= abs(delta_pos): m.__dict__['present_position'] = m.__dict__['goal_position'] else: m.__dict__['present_position'] += delta_pos_effective self.last_update = time.time()
[docs]class SensorsController(AbstractController): """ Abstract class for sensors controller. The controller frequently pulls new data from a "real" sensor and updates its corresponding software instance. """ def __init__(self, io, sensors, sync_freq=50.): """ :param io: IO used to communicate with the hardware motors :type io: :class:`~pypot.robot.io.AbstractIO` :param list sensors: list of sensors attached to the controller :param float sync_freq: synchronization frequency """ AbstractController.__init__(self, io, sync_freq) self.sensors = sensors