From 7f2be8394fc500d5e5e3208b8f8c581fdb727935 Mon Sep 17 00:00:00 2001 From: jiaxi <1761475917@qq.com> Date: Tue, 16 Dec 2025 17:22:54 +0800 Subject: [PATCH 1/5] feat(animation): add fram_idx support --- .gitignore | 4 ++++ pogema/svg_animation/animation_drawer.py | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f076c83 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +.vscode +build +*.egg-info diff --git a/pogema/svg_animation/animation_drawer.py b/pogema/svg_animation/animation_drawer.py index 46d0db5..16e9658 100644 --- a/pogema/svg_animation/animation_drawer.py +++ b/pogema/svg_animation/animation_drawer.py @@ -12,6 +12,7 @@ class AnimationConfig: static: bool = False show_agents: bool = True egocentric_idx: typing.Optional[int] = None + frame_idx: typing.Optional[int] = None uid: typing.Optional[str] = None save_every_idx_episode: typing.Optional[int] = 1 show_grid_lines: bool = True @@ -113,10 +114,12 @@ def create_animation(self, grid_holder: GridHolder): agents = [] targets = [] + if gh.config.static and gh.config.frame_idx is not None: + gh.history = [[agent_states[gh.config.frame_idx]] for agent_states in gh.history] if gh.config.show_agents: agents = self.create_agents(gh) targets = self.create_targets(gh) - + if not gh.config.static: self.animate_agents(agents, gh) self.animate_targets(targets, gh) @@ -126,7 +129,6 @@ def create_animation(self, grid_holder: GridHolder): drawing.add_element(line) for obj in [*obstacles, *agents, *targets]: drawing.add_element(obj) - if gh.config.egocentric_idx is not None: field_of_view = self.create_field_of_view(grid_holder=gh) if not gh.config.static: @@ -143,7 +145,6 @@ def fix_point(x, y, length): @staticmethod def check_in_radius(x1, y1, x2, y2, r) -> bool: return x2 - r <= x1 <= x2 + r and y2 - r <= y1 <= y2 + r - @staticmethod def create_grid_lines(grid_holder: GridHolder, render_width, render_height): gh = grid_holder From ebd34f35932e979cfa38de6265a07fd733afeab6 Mon Sep 17 00:00:00 2001 From: jiaxi <1761475917@qq.com> Date: Tue, 16 Dec 2025 18:08:09 +0800 Subject: [PATCH 2/5] feat(frame): add funciton --- pogema/svg_animation/animation_drawer.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pogema/svg_animation/animation_drawer.py b/pogema/svg_animation/animation_drawer.py index 16e9658..8a69798 100644 --- a/pogema/svg_animation/animation_drawer.py +++ b/pogema/svg_animation/animation_drawer.py @@ -115,11 +115,12 @@ def create_animation(self, grid_holder: GridHolder): targets = [] if gh.config.static and gh.config.frame_idx is not None: - gh.history = [[agent_states[gh.config.frame_idx]] for agent_states in gh.history] + self.create_frame_view(gh) + if gh.config.show_agents: agents = self.create_agents(gh) targets = self.create_targets(gh) - + if not gh.config.static: self.animate_agents(agents, gh) self.animate_targets(targets, gh) @@ -145,6 +146,7 @@ def fix_point(x, y, length): @staticmethod def check_in_radius(x1, y1, x2, y2, r) -> bool: return x2 - r <= x1 <= x2 + r and y2 - r <= y1 <= y2 + r + @staticmethod def create_grid_lines(grid_holder: GridHolder, render_width, render_height): gh = grid_holder @@ -178,6 +180,11 @@ def create_field_of_view(grid_holder): ) return result + + def create_frame_view(self, grid_holder): + gh: GridHolder = grid_holder + frame_idx = gh.config.frame_idx + gh.history = [[agent_states[gh.config.frame_idx]] for agent_states in gh.history] def animate_field_of_view(self, view, grid_holder): gh: GridHolder = grid_holder From 87f8692b208ca9860142da14ee2801f55d80c6cb Mon Sep 17 00:00:00 2001 From: jiaxi <1761475917@qq.com> Date: Tue, 16 Dec 2025 20:59:47 +0800 Subject: [PATCH 3/5] fixed(frame):fixed unasync frame render bug due to is_active function --- pogema/svg_animation/animation_drawer.py | 73 ++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/pogema/svg_animation/animation_drawer.py b/pogema/svg_animation/animation_drawer.py index 8a69798..77f1c2d 100644 --- a/pogema/svg_animation/animation_drawer.py +++ b/pogema/svg_animation/animation_drawer.py @@ -114,22 +114,25 @@ def create_animation(self, grid_holder: GridHolder): agents = [] targets = [] - if gh.config.static and gh.config.frame_idx is not None: - self.create_frame_view(gh) - if gh.config.show_agents: agents = self.create_agents(gh) targets = self.create_targets(gh) - - if not gh.config.static: + if gh.config.static: + agents = self.create_static_agents(gh) + if gh.config.egocentric_idx is not None: + obstacles = self.create_static_obstacles(obstacles= obstacles, grid_holder=gh) + self.create_frame_view(gh) + else: self.animate_agents(agents, gh) self.animate_targets(targets, gh) + if gh.config.show_grid_lines: grid_lines = self.create_grid_lines(gh, render_width, render_height) for line in grid_lines: drawing.add_element(line) for obj in [*obstacles, *agents, *targets]: drawing.add_element(obj) + if gh.config.egocentric_idx is not None: field_of_view = self.create_field_of_view(grid_holder=gh) if not gh.config.static: @@ -324,6 +327,39 @@ def create_obstacles(self, grid_holder): return result + def create_static_obstacles(self, obstacles, grid_holder): + gh: GridHolder = grid_holder + frame_idx = gh.config.frame_idx + result = [] + seen = set() + + for step_idx, agent_state in enumerate(gh.history[gh.config.egocentric_idx][:frame_idx + 1]): + ego_x, ego_y = agent_state.get_xy() + for i in range(gh.height): + for j in range(gh.width): + x, y = self.fix_point(i, j, gh.width) + if gh.obstacles[x][y]: + if self.check_in_radius(x, y, ego_x, ego_y, gh.obs_radius): + seen.add((x, y)) + for i in range(gh.height): + for j in range(gh.width): + x, y = self.fix_point(i, j, gh.width) + + if gh.obstacles[x][y]: + obs_settings = { + 'x': gh.svg_settings.draw_start + i * gh.svg_settings.scale_size - gh.svg_settings.r, + 'y': gh.svg_settings.draw_start + j * gh.svg_settings.scale_size - gh.svg_settings.r, + 'height': gh.svg_settings.r * 2, + } + if (x, y) in seen: + obs_settings.update(opacity=1.0) + else: + obs_settings.update(opacity=gh.svg_settings.shaded_opacity) + + result.append(RectangleHref(**obs_settings)) + + return result + def animate_obstacles(self, obstacles, grid_holder): gh: GridHolder = grid_holder obstacle_idx = 0 @@ -375,6 +411,33 @@ def create_agents(self, grid_holder): return agents + def create_static_agents(self, grid_holder): + agents = [] + gh: GridHolder = grid_holder + ego_idx = grid_holder.config.egocentric_idx + frame_idx = grid_holder.config.frame_idx + + static_positions = [state[frame_idx].get_xy() for state in grid_holder.history] + for idx, (x, y) in enumerate(static_positions): + circle_settings = { + 'cx': gh.svg_settings.draw_start + y * gh.svg_settings.scale_size, + 'cy': gh.svg_settings.draw_start + (grid_holder.width - x - 1) * gh.svg_settings.scale_size, + 'r': gh.svg_settings.r, 'fill': grid_holder.colors[idx], 'class': 'agent', + } + + if ego_idx is not None: + ego_x, ego_y = static_positions[ego_idx] + is_out_of_radius = not self.check_in_radius(x, y, ego_x, ego_y, grid_holder.obs_radius) + circle_settings['fill'] = gh.svg_settings.ego_other_color + if idx == ego_idx: + circle_settings['fill'] = gh.svg_settings.ego_color + elif is_out_of_radius and gh.svg_settings.egocentric_shaded: + circle_settings['opacity'] = gh.svg_settings.shaded_opacity + + agents.append(Circle(**circle_settings)) + + return agents + @staticmethod def create_targets(grid_holder): gh: GridHolder = grid_holder From 90b460f4ff8129f7e7a1c814a22e2f9327c85cb0 Mon Sep 17 00:00:00 2001 From: Alexey Skrynnik Date: Fri, 19 Dec 2025 11:23:16 +0300 Subject: [PATCH 4/5] Delete .gitignore remove unrelated changes from the pull request --- .gitignore | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f076c83..0000000 --- a/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.DS_Store -.vscode -build -*.egg-info From 23e5418d9e3a61fbf4c7e0105ad47fb1cc981bac Mon Sep 17 00:00:00 2001 From: jiaxi <1761475917@qq.com> Date: Sun, 18 Jan 2026 20:39:12 +0800 Subject: [PATCH 5/5] (fixed): update AnimationConfig with static_frame_idx --- pogema/svg_animation/animation_drawer.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pogema/svg_animation/animation_drawer.py b/pogema/svg_animation/animation_drawer.py index 77f1c2d..9c5a2f9 100644 --- a/pogema/svg_animation/animation_drawer.py +++ b/pogema/svg_animation/animation_drawer.py @@ -9,10 +9,9 @@ @dataclass class AnimationConfig: directory: str = 'renders/' - static: bool = False show_agents: bool = True egocentric_idx: typing.Optional[int] = None - frame_idx: typing.Optional[int] = None + static_frame_idx: typing.Optional[int] = None uid: typing.Optional[str] = None save_every_idx_episode: typing.Optional[int] = 1 show_grid_lines: bool = True @@ -117,7 +116,7 @@ def create_animation(self, grid_holder: GridHolder): if gh.config.show_agents: agents = self.create_agents(gh) targets = self.create_targets(gh) - if gh.config.static: + if gh.config.static_frame_idx is not None: agents = self.create_static_agents(gh) if gh.config.egocentric_idx is not None: obstacles = self.create_static_obstacles(obstacles= obstacles, grid_holder=gh) @@ -135,7 +134,7 @@ def create_animation(self, grid_holder: GridHolder): if gh.config.egocentric_idx is not None: field_of_view = self.create_field_of_view(grid_holder=gh) - if not gh.config.static: + if gh.config.static_frame_idx is None: self.animate_obstacles(obstacles=obstacles, grid_holder=gh) self.animate_field_of_view(field_of_view, gh) drawing.add_element(field_of_view) @@ -186,8 +185,8 @@ def create_field_of_view(grid_holder): def create_frame_view(self, grid_holder): gh: GridHolder = grid_holder - frame_idx = gh.config.frame_idx - gh.history = [[agent_states[gh.config.frame_idx]] for agent_states in gh.history] + frame_idx = gh.config.static_frame_idx + gh.history = [[agent_states[frame_idx]] for agent_states in gh.history] def animate_field_of_view(self, view, grid_holder): gh: GridHolder = grid_holder @@ -329,7 +328,7 @@ def create_obstacles(self, grid_holder): def create_static_obstacles(self, obstacles, grid_holder): gh: GridHolder = grid_holder - frame_idx = gh.config.frame_idx + frame_idx = gh.config.static_frame_idx result = [] seen = set() @@ -415,7 +414,7 @@ def create_static_agents(self, grid_holder): agents = [] gh: GridHolder = grid_holder ego_idx = grid_holder.config.egocentric_idx - frame_idx = grid_holder.config.frame_idx + frame_idx = grid_holder.config.static_frame_idx static_positions = [state[frame_idx].get_xy() for state in grid_holder.history] for idx, (x, y) in enumerate(static_positions):