Exemple #1
0
def move_walls_after(seconds: int) -> None:
    robot = Supervisor()
    timestep = robot.getBasicTimeStep()
    walls = [
        webots_utils.node_from_def(robot, 'west_moving_wall'),
        webots_utils.node_from_def(robot, 'west_moving_triangle'),
        webots_utils.node_from_def(robot, 'east_moving_wall'),
        webots_utils.node_from_def(robot, 'east_moving_triangle'),
    ]

    if controller_utils.get_robot_mode() == 'comp':
        # Interact with the supervisor "robot" to wait for the start of the match.
        while robot.getCustomData() != 'start':
            robot.step(int(timestep))

    # wait for the walls to start moving in ms
    robot.step(seconds * 1000)

    print('Moving arena walls')  # noqa: T001
    for wall in walls:
        wall.setVelocity(LINEAR_DOWNWARDS)

    # wait for the walls to reach their final location
    robot.step(1000)

    for wall in walls:
        wall.resetPhysics()
Exemple #2
0
class LightingController:
    def __init__(self, duration: float, cue_stack: List[LightingEffect]) -> None:
        self._robot = Supervisor()
        self.timestep = self._robot.getBasicTimeStep()
        self.start_offset: float = 0

        self.duration = duration
        self.cue_stack = cue_stack

        self.ambient_node = webots_utils.node_from_def(self._robot, 'AMBIENT')

        self.luminosity_fade = LuminosityFade(0, 0, 0.35, 0.35)
        self.lighting_fades: List[LightFade] = []

        # fetch all nodes used in effects, any missing nodes will be flagged here
        self.light_nodes: Dict[str, Node] = {}
        for cue in cue_stack:
            for light in cue.lighting:
                if self.light_nodes.get(light.light_def) is None:
                    self.light_nodes[light.light_def] = webots_utils.node_from_def(
                        self._robot,
                        light.light_def,
                    )

    def set_node_luminosity(self, node: Node, luminosity: float) -> None:
        node.getField('luminosity').setSFFloat(luminosity)

    def set_node_intensity(self, node: Node, intensity: float) -> None:
        node.getField('intensity').setSFFloat(intensity)

    def set_node_colour(self, node: Node, colour: Tuple[float, float, float]) -> None:
        node.getField('color').setSFColor(list(colour))

    def get_current_luminosity(self) -> float:
        return self.ambient_node.getField('luminosity').getSFFloat()

    def get_current_lighting_values(self, light_def: str) -> ArenaLighting:
        light = self.light_nodes[light_def]
        return ArenaLighting(
            light_def,
            light.getField('intensity').getSFFloat(),
            light.getField('color').getSFColor(),  # type: ignore
        )

    def increment_colour(
        self,
        colour: Tuple[float, float, float],
        step: Tuple[float, float, float],
    ) -> Tuple[float, float, float]:
        return tuple(colour[i] + step[i] for i in range(3))  # type: ignore

    def current_match_time(self) -> float:
        return self._robot.getTime() - self.start_offset

    def remaining_match_time(self) -> float:
        return self.duration - self.current_match_time()

    def start_lighting_effect(self, effect: LightingEffect) -> None:
        print(  # noqa: T001
            f"Running lighting effect: {effect.name} @ {self.current_match_time()}",
        )

        if effect.fade_time is None:
            self.set_node_luminosity(self.ambient_node, effect.luminosity)
            for light in effect.lighting:
                self.set_node_intensity(self.light_nodes[light.light_def], light.intensity)
                self.set_node_colour(self.light_nodes[light.light_def], light.colour)

            print(f"Lighting effect '{effect.name}' complete")  # noqa: T001

        else:
            steps = int((effect.fade_time * 1000) / self.timestep)

            # get starting values
            current_luminosity = self.get_current_luminosity()
            luminosity_step = (effect.luminosity - current_luminosity) / steps
            self.luminosity_fade = LuminosityFade(
                steps,
                luminosity_step,
                current_luminosity,
                effect.luminosity,
            )

            for light in effect.lighting:
                # get starting values
                (
                    _,
                    current_intensity,
                    current_colour,
                ) = self.get_current_lighting_values(light.light_def)

                # figure out steps of each value
                intensity_step = (light.intensity - current_intensity) / steps
                colour_step: Tuple[float, float, float] = tuple(  # type: ignore
                    light.colour[i] - current_colour[i]
                    for i in range(3)
                )

                # add fade to queue to have steps processed
                self.lighting_fades.append(LightFade(
                    self.light_nodes[light.light_def],
                    steps,
                    intensity_step,
                    colour_step,
                    current_intensity,
                    current_colour,
                    light,
                ))

    def do_lighting_step(self) -> None:
        if self.luminosity_fade.remaining_steps != 0:
            self.luminosity_fade.current_luminosity += self.luminosity_fade.luminosity_step
            self.luminosity_fade.remaining_steps -= 1

            if self.luminosity_fade.remaining_steps == 0:  # final step
                self.luminosity_fade.current_luminosity = self.luminosity_fade.final_luminosity

            self.set_node_luminosity(
                self.ambient_node,
                self.luminosity_fade.current_luminosity,
            )

        for fade in self.lighting_fades:
            if fade.remaining_steps > 1:
                fade.current_intensity += fade.intensity_step
                fade.current_colour = self.increment_colour(
                    fade.current_colour,
                    fade.colour_step,
                )
                fade.remaining_steps -= 1

                self.set_node_intensity(fade.light, fade.current_intensity)
                self.set_node_colour(fade.light, fade.current_colour)
            else:
                self.set_node_intensity(fade.light, fade.effect.intensity)
                self.set_node_colour(fade.light, fade.effect.colour)

                print(f"Lighting effect for '{fade.effect.light_def}' complete")  # noqa: T001

                self.lighting_fades.remove(fade)  # remove completed fade

    def schedule_lighting(self) -> None:
        if controller_utils.get_robot_mode() != 'comp':
            return

        print('Scheduled cues:')  # noqa: T001
        for cue in self.cue_stack:
            print(cue)  # noqa: T001

        # run pre-start snap changes
        for cue in self.cue_stack.copy():
            if cue.start_time == 0 and cue.fade_time is None:
                self.start_lighting_effect(cue)
                self.cue_stack.remove(cue)

        # Interact with the supervisor "robot" to wait for the start of the match.
        while self._robot.getCustomData() != 'start':
            self._robot.step(int(self.timestep))

        self.start_offset = self._robot.getTime()

        while self.cue_stack:
            for cue in self.cue_stack.copy():
                if (
                    cue.start_time >= 0 and
                    self.current_match_time() >= cue.start_time
                ):  # cue relative to start
                    self.start_lighting_effect(cue)
                    self.cue_stack.remove(cue)
                elif (
                    cue.start_time < 0 and
                    self.remaining_match_time() <= -(cue.start_time)
                ):  # cue relative to end
                    self.start_lighting_effect(cue)
                    self.cue_stack.remove(cue)

            self.do_lighting_step()
            self._robot.step(int(self.timestep))