|
32 | 32 | TARGET_POSITION = [5, 0, 0.5] |
33 | 33 |
|
34 | 34 |
|
35 | | -def show_xpos_history(history: list[float]) -> None: |
| 35 | +def show_xpos_history( |
| 36 | + history: list[float], |
| 37 | + *, |
| 38 | + save: bool = True, |
| 39 | + show: bool = True, |
| 40 | +) -> None: |
36 | 41 | # Initialize world to get the background |
37 | 42 | mj.set_mjcb_control(None) |
38 | 43 | world = OlympicArena( |
@@ -110,33 +115,43 @@ def show_xpos_history(history: list[float]) -> None: |
110 | 115 | correct_collision_with_floor=False, |
111 | 116 | ) |
112 | 117 |
|
113 | | - last_value = None |
114 | | - for i in range(len(pos_data)): |
115 | | - position = pos_data[i] |
116 | | - if last_value is not None: |
117 | | - distance = np.abs(np.array(position - last_value)) / 2 |
118 | | - else: |
119 | | - distance = np.array((0.01, 0.01, 0.01)) |
120 | | - last_value = position |
121 | | - |
122 | | - distance_as_size: str = ( |
123 | | - f'"{(distance[0] + 0.01):.2f} 0.05 {(distance[2] + 0.01):.2f}"' |
| 118 | + # Draw the path of the robot |
| 119 | + for i in range(1, len(pos_data)): |
| 120 | + # Get the two points to draw the distance between |
| 121 | + pos_i = pos_data[i] |
| 122 | + pos_j = pos_data[i - 1] |
| 123 | + |
| 124 | + # Size of the box to represent the distance |
| 125 | + distance = pos_i - pos_j |
| 126 | + minimum_size = 0.05 |
| 127 | + geom_size = np.array([ |
| 128 | + max(abs(distance[0]) / 2, minimum_size), |
| 129 | + max(abs(distance[1]) / 2, minimum_size), |
| 130 | + max(abs(distance[2]) / 2, minimum_size), |
| 131 | + ]) |
| 132 | + geom_size_str: str = f"{geom_size[0]} {geom_size[1]} {geom_size[2]}" |
| 133 | + |
| 134 | + # Position the box in the middle of the two points |
| 135 | + half_way_point = (pos_i + pos_j) / 2 |
| 136 | + geom_pos_str = ( |
| 137 | + f"{half_way_point[0]} {half_way_point[1]} {half_way_point[2]}" |
124 | 138 | ) |
125 | 139 |
|
126 | 140 | path_box = rf""" |
127 | 141 | <mujoco> |
128 | 142 | <worldbody> |
129 | 143 | <geom name="yellow_sphere" |
130 | 144 | type="box" |
131 | | - size={distance_as_size} |
| 145 | + pos="{geom_pos_str}" |
| 146 | + size="{geom_size_str}" |
132 | 147 | rgba="1 1 0 0.9" |
133 | 148 | /> |
134 | 149 | </worldbody> |
135 | 150 | </mujoco> |
136 | 151 | """ |
137 | 152 | world.spawn( |
138 | 153 | mj.MjSpec.from_string(path_box), |
139 | | - position=position + (adjustment * 1.25), |
| 154 | + position=(adjustment * 1.25), |
140 | 155 | correct_collision_with_floor=False, |
141 | 156 | ) |
142 | 157 |
|
@@ -188,5 +203,11 @@ def show_xpos_history(history: list[float]) -> None: |
188 | 203 | # Title |
189 | 204 | plt.title("Robot Path in XY Plane") |
190 | 205 |
|
| 206 | + # Save the figure |
| 207 | + if save: |
| 208 | + fig_path = DATA / "robot_path.png" |
| 209 | + plt.savefig(fig_path, bbox_inches="tight", dpi=300) |
| 210 | + |
191 | 211 | # Show results |
192 | | - plt.show() |
| 212 | + if show: |
| 213 | + plt.show() |
0 commit comments