Exemplo n.º 1
0
 def __init__(self):
     self.azimuth = simactuators.PointToPointActuator(
         min_position=-45, max_position=45, speed=10, start_position=0
     )
     self.elevation = simactuators.PointToPointActuator(
         min_position=-69, max_position=45, speed=10, start_position=0
     )
     self.focus = simactuators.PointToPointActuator(
         min_position=0, max_position=13000, speed=200, start_position=0
     )
     self.mask_select = simactuators.PointToPointActuator(
         min_position=1, max_position=5, speed=1, start_position=1
     )
     self.mask_rotate = simactuators.CircularPointToPointActuator(speed=10)
    async def test_set_position(self):
        await self.check_set_position(start_position=3, end_position=4)
        await self.check_set_position(start_position=2, end_position=-5)

        # A move to the start position should have no effect.
        pos = 1
        actuator = simactuators.PointToPointActuator(
            min_position=pos - 1,
            max_position=pos + 1,
            start_position=pos,
            speed=2,
        )
        duration = actuator.set_position(pos)
        self.assertEqual(duration, 0)
        self.assertEqual(actuator.start_position, pos)
        self.assertEqual(actuator.end_position, pos)
        self.assertEqual(actuator.start_tai, actuator.end_tai)
        self.assertFalse(actuator.moving(actuator.start_tai))
        self.assertEqual(actuator.velocity(actuator.start_tai), 0)
        self.assertEqual(actuator.direction, simactuators.Direction.POSITIVE)

        # Check specifying an explicit start_tai;
        # pick a value different than the existing start_tai
        # so we can tell the difference.
        start_tai = actuator.start_tai + 5
        actuator.set_position(position=1, start_tai=start_tai)
        self.assertEqual(actuator.start_tai, start_tai)
    async def test_stop_default_tai(self):
        min_position = -10
        max_position = 10
        start_position = 3
        # Slow motion so plenty of time to stop
        speed = 0.1
        actuator = simactuators.PointToPointActuator(
            min_position=min_position,
            max_position=max_position,
            start_position=start_position,
            speed=speed,
        )
        end_position = 4
        duration = actuator.set_position(end_position)
        self.assertEqual(actuator.end_position, end_position)
        self.assertTrue(actuator.moving(salobj.current_tai()))
        # Let the actuator move for some arbitrary time
        # that is less than the remaining time
        sleep_time = 0.21
        self.assertGreater(duration, sleep_time)
        await asyncio.sleep(sleep_time)
        tai0 = salobj.current_tai()
        actuator.stop()
        time_slop = salobj.current_tai() - tai0
        self.assertAlmostEqual(tai0, actuator.end_tai, delta=time_slop)
        position_slop = time_slop * speed
        self.assertAlmostEqual(actuator.end_position,
                               actuator.position(tai0),
                               delta=position_slop)

        move_time = actuator.end_tai - actuator.start_tai
        self.assertGreater(move_time, 0)
        predicted_end_position = start_position + speed * move_time
        self.assertAlmostEqual(predicted_end_position,
                               actuator.end_position,
                               places=6)
        self.assertFalse(actuator.moving(actuator.end_tai))
        self.assertEqual(actuator.position(actuator.end_tai),
                         actuator.end_position)
        self.assertEqual(actuator.start_position, start_position)
        self.assertEqual(actuator.position(actuator.start_tai),
                         actuator.start_position)

        # Stopping a stopped actuator should have no effect
        # except updating end_tai. Sleep long enough
        # that we can see the end_tai change.
        await asyncio.sleep(0.1)
        old_start_tai = actuator.start_tai
        old_pos = actuator.end_position
        tai0 = salobj.current_tai()
        actuator.stop()
        time_slop = salobj.current_tai()
        self.assertEqual(actuator.start_tai, old_start_tai)
        self.assertEqual(actuator.start_position, start_position)
        self.assertEqual(actuator.end_position, old_pos)
        self.assertAlmostEqual(actuator.end_tai, tai0, delta=time_slop)
Exemplo n.º 4
0
    def __init__(
        self,
        initial_state,
        initial_elevation=0,
        elevation_velocity=3,
        azimuth_velocity=3,
        azimuth_acceleration=1,
    ):
        self.elevation_actuator = simactuators.PointToPointActuator(
            min_position=0,
            max_position=90,
            speed=elevation_velocity,
            start_position=initial_elevation,
        )
        self.azimuth_actuator = simactuators.CircularTrackingActuator(
            max_velocity=azimuth_velocity,
            max_acceleration=azimuth_acceleration,
            dtmax_track=0,
        )
        self.telemetry_interval = 0.2  # seconds
        self.telemetry_loop_task = utils.make_done_future()
        self.elevation_done_task = utils.make_done_future()
        self.azimuth_done_task = utils.make_done_future()

        # Add do methods for unsupported commands
        for name in (
            "closeLouvers",
            "closeShutter",
            "crawlAz",
            "crawlEl",
            "exitFault",
            "openShutter",
            "park",
            "resetDrivesAz",
            "setLouvers",
            "setOperationalMode",
            "setTemperature",
            "setZeroAz",
        ):
            setattr(self, f"do_{name}", self._unsupportedCommand)
        super().__init__(name="MTDome", index=None, initial_state=initial_state)
Exemplo n.º 5
0
 def __init__(self, base_positions, mirror_positions, pivot, min_length,
              max_length, speed):
     if len(base_positions) != 6:
         raise ValueError(
             f"base_positions={base_positions} must have 6 elements")
     for pos in base_positions:
         if len(pos) != 3:
             raise ValueError(
                 f"base_positions={base_positions}; each item must have 3 elements"
             )
     if len(mirror_positions) != 6:
         raise ValueError(
             f"mirror_positions={mirror_positions} must have 6 elements")
     for pos in mirror_positions:
         if len(pos) != 3:
             raise ValueError(
                 f"mirror_positions={mirror_positions}; each item must have 3 elements"
             )
     if len(pivot) != 3:
         raise ValueError(f"pivot={pivot} must have 3 elements")
     self.base_positions = [np.array(pos) for pos in base_positions]
     # Positions of mirror actuator ends and pivot at orientation zero.
     self.neutral_mirror_positions = [
         np.array(pos) for pos in mirror_positions
     ]
     self.neutral_pivot = np.array(pivot, dtype=float)
     # Information commanded by the `move` command.
     self.cmd_pos = np.zeros(3, dtype=float)
     self.cmd_xyzrot = np.zeros(3, dtype=float)
     self.cmd_mirror_positions = [np.array(pos) for pos in mirror_positions]
     self.neutral_actuator_lengths = self.compute_actuator_lengths(
         mirror_positions=mirror_positions, absolute=True)
     self.actuators = [
         simactuators.PointToPointActuator(
             min_position=min_length,
             max_position=max_length,
             start_position=0,
             speed=speed,
         ) for actuator_length in self.neutral_actuator_lengths
     ]
    async def test_stop_specified_tai(self):
        min_position = -10
        max_position = 10
        start_position = 3
        # Slow motion so plenty of time to stop
        speed = 0.1
        actuator = simactuators.PointToPointActuator(
            min_position=min_position,
            max_position=max_position,
            start_position=start_position,
            speed=speed,
        )
        end_position = 4
        start_tai = 12.1  # arbitrary
        duration = actuator.set_position(end_position, start_tai=start_tai)
        self.assertEqual(actuator.end_position, end_position)
        predicted_duration = (end_position - start_position) / speed
        self.assertAlmostEqual(duration, predicted_duration)
        end_tai = start_tai + duration
        self.assertAlmostEqual(actuator.end_tai, end_tai)
        self.assertFalse(actuator.moving(tai=start_tai - 0.001))
        self.assertFalse(actuator.moving(tai=end_tai + 0.001))
        self.assertTrue(actuator.moving(tai=start_tai + 0.001))
        self.assertTrue(actuator.moving(tai=end_tai - 0.001))

        # Let the actuator move for some arbitrary time
        # that is less than the remaining time
        stop_dtime = 0.21
        stop_tai = stop_dtime + start_tai
        self.assertGreater(duration, stop_dtime)
        actuator.stop(tai=stop_tai)

        self.assertEqual(actuator.end_tai, stop_tai)
        self.assertFalse(actuator.moving(tai=start_tai - 0.001))
        self.assertFalse(actuator.moving(tai=stop_tai + 0.001))
        self.assertTrue(actuator.moving(tai=start_tai + 0.001))
        self.assertTrue(actuator.moving(tai=stop_tai - 0.001))
        self.assertEqual(actuator.end_tai, stop_tai)
        predicted_end_position = start_position + speed * stop_dtime
        self.assertAlmostEqual(actuator.end_position, predicted_end_position)
Exemplo n.º 7
0
    def __init__(
        self,
        port,
        door_time=1,
        az_vel=6,
        home_az=10,
        home_az_overshoot=1,
        home_az_vel=1,
    ):
        # If port == 0 then this will be updated to the actual port
        # in `start`, right after the TCP/IP server is created.
        self.port = port
        self.door_time = door_time
        self.az_vel = az_vel
        self.high_speed = 5
        self.coast = 0.5
        self.tolerance = 1.0
        self.home_az = home_az
        self.home_az_overshoot = home_az_overshoot
        self.home_az_vel = home_az_vel
        self.encoder_counts_per_360 = 4018143232
        self.az_actuator = simactuators.CircularPointToPointActuator(
            speed=az_vel)
        self.az_move_timeout = 120
        self.watchdog_reset_time = 600
        self.dropout_timer = 5
        self.reverse_delay = 4
        self.main_door_encoder_closed = 118449181478
        self.main_door_encoder_opened = 8287616388
        self.dropout_door_encoder_closed = 5669776578
        self.dropout_door_encoder_opened = 5710996184
        self.door_move_timeout = 360
        self.door_actuators = {
            enum: simactuators.PointToPointActuator(
                min_position=0,
                max_position=100,
                start_position=0,
                speed=100 / door_time,
            )
            for enum in Door
        }

        self._homing_task = salobj.make_done_future()
        self.rain_sensor_enabled = True
        self.rain_detected = False
        self.cloud_sensor_enabled = True
        self.clouds_detected = False
        self.scb_link_ok = True
        self.auto_shutdown_enabled = False
        self.estop_active = False
        # Name of a command to report as failed once, the next time it is seen,
        # or None if no failures. Used to test CSC handling of failed commands.
        self.fail_command = None

        self.last_rot_right = None
        self.log = logging.getLogger("MockDomeController")
        self.server = None

        # Dict of command: (has_argument, function).
        # The function is called with:
        # * No arguments, if `has_argument` False.
        # * The argument as a string, if `has_argument` is True.
        self.dispatch_dict = {
            "?": (False, self.do_short_status),
            "+": (False, self.do_full_status),
            "ST": (False, self.do_stop),
            "CL": (False, functools.partial(self.do_close_doors, Door.Main)),
            "OP": (False, functools.partial(self.do_open_doors, Door.Main)),
            "UP": (False, functools.partial(self.do_close_doors,
                                            Door.Dropout)),
            "DN": (False, functools.partial(self.do_open_doors, Door.Dropout)),
            "SC": (
                False,
                functools.partial(self.do_close_doors,
                                  Door.Main | Door.Dropout),
            ),
            "SO": (
                False,
                functools.partial(self.do_open_doors,
                                  Door.Main | Door.Dropout),
            ),
            "HM": (False, self.do_home),
            "MV": (True, self.do_set_cmd_az),
        }
    def test_constructor(self):
        min_position = -1
        max_position = 5
        start_position = 3
        speed = 1.5
        for good_start_position in (start_position, min_position,
                                    max_position):
            with self.subTest(good_start_position=good_start_position):
                tai0 = salobj.current_tai()
                actuator = simactuators.PointToPointActuator(
                    min_position=min_position,
                    max_position=max_position,
                    start_position=good_start_position,
                    speed=speed,
                )
                time_slop = salobj.current_tai() - tai0
                self.assertAlmostEqual(actuator.start_tai,
                                       tai0,
                                       delta=time_slop)
                self.assertEqual(actuator.start_position, good_start_position)
                self.assertEqual(actuator.end_position,
                                 actuator.start_position)
                self.assertEqual(actuator.start_tai, actuator.end_tai)
                self.assertEqual(actuator.direction,
                                 simactuators.Direction.POSITIVE)
                for dt in (-1, 0, 1):
                    tai = actuator.start_tai + dt
                    self.assertEqual(actuator.position(tai),
                                     good_start_position)
                    self.assertEqual(actuator.velocity(tai), 0)
                    self.assertFalse(actuator.moving(tai))
                    predicted_remaining_time = 0 if dt >= 0 else -dt
                    self.assertAlmostEqual(actuator.remaining_time(tai),
                                           predicted_remaining_time)

                self.assertEqual(actuator.position(), good_start_position)
                self.assertEqual(actuator.velocity(), 0)
                self.assertFalse(actuator.moving())
                self.assertEqual(actuator.remaining_time(), 0)

        for bad_min_position in (max_position, max_position + 0.001):
            with self.subTest(bad_min_position=bad_min_position):
                with self.assertRaises(ValueError):
                    simactuators.PointToPointActuator(
                        min_position=bad_min_position,
                        max_position=max_position,
                        start_position=max_position,
                        speed=speed,
                    )

        for bad_max_position in (min_position, min_position - 0.001):
            with self.subTest(bad_max_position=bad_max_position):
                with self.assertRaises(ValueError):
                    simactuators.PointToPointActuator(
                        min_position=min_position,
                        max_position=bad_max_position,
                        start_position=min_position,
                        speed=speed,
                    )

        for bad_pos in (min_position - 0.001, max_position + 0.001):
            with self.subTest(bad_pos=bad_pos):
                with self.assertRaises(ValueError):
                    simactuators.PointToPointActuator(
                        min_position=min_position,
                        max_position=max_position,
                        start_position=bad_pos,
                        speed=speed,
                    )

        for bad_speed in (0, -0.001):
            with self.subTest(bad_speed=bad_speed):
                with self.assertRaises(ValueError):
                    simactuators.PointToPointActuator(
                        min_position=min_position,
                        max_position=max_position,
                        start_position=start_position,
                        speed=bad_speed,
                    )
    async def check_set_position(self, start_position, end_position):
        if start_position == end_position:
            raise ValueError("start_position must not equal end_position")
        min_position = min(start_position, end_position) - 1
        max_position = max(start_position, end_position) + 1
        # Make the move take a reasonable amount of time
        speed = 2.0 / abs(end_position - start_position)
        actuator = simactuators.PointToPointActuator(
            min_position=min_position,
            max_position=max_position,
            start_position=start_position,
            speed=speed,
        )
        # Sleep a bit so actuator.start_tai will change by a noticeable amount
        # as a result of the set_position command.
        await asyncio.sleep(0.1)
        # Keep track of how long it takes to call `set_position`
        # so we know how picky to be when testing `start_tai`.
        tai0 = salobj.current_tai()
        duration = actuator.set_position(end_position)
        remaining_time = actuator.remaining_time()
        time_slop = salobj.current_tai() - tai0
        predicted_duration = abs(end_position - start_position) / speed
        self.assertAlmostEqual(duration, predicted_duration)
        self.assertAlmostEqual(actuator.start_tai, tai0, delta=time_slop)
        self.assertAlmostEqual(remaining_time, duration, delta=time_slop)
        self.assertAlmostEqual(actuator.start_tai + predicted_duration,
                               actuator.end_tai,
                               places=6)
        self.assertEqual(actuator.end_position, end_position)
        predicted_direction = (simactuators.Direction.POSITIVE
                               if end_position >= start_position else
                               simactuators.Direction.NEGATIVE)
        self.assertEqual(actuator.direction, predicted_direction)
        predicted_speed = speed * predicted_direction

        # The actuator should not be moving before or after the move
        # (but remaining_time is > 0 before the move).
        for tai in (
                actuator.start_tai - 1,
                actuator.start_tai,
                actuator.end_tai,
                actuator.end_tai + 1,
        ):
            self.assertFalse(actuator.moving(tai))
            self.assertEqual(actuator.velocity(tai), 0)
            predicted_remaining_time = (actuator.end_tai -
                                        tai if actuator.end_tai > tai else 0)
            self.assertAlmostEqual(actuator.remaining_time(tai),
                                   predicted_remaining_time)

        # The actuator should be moving during the move.
        for tai in (
                actuator.start_tai + 0.001,
            (actuator.start_tai + actuator.end_tai) / 2,
                actuator.end_tai - 0.001,
        ):
            self.assertTrue(actuator.moving(tai))
            self.assertEqual(actuator.velocity(tai), predicted_speed)
            predicted_remaining_time = actuator.end_tai - tai
            self.assertAlmostEqual(actuator.remaining_time(tai),
                                   predicted_remaining_time)

        # Try moving out of bounds.
        for bad_end_position in (
                min_position - 1,
                min_position - 0.0001,
                max_position + 0.0001,
                max_position + 1,
        ):
            with self.assertRaises(ValueError):
                actuator.set_position(bad_end_position)