Skip to content

Commit a90569c

Browse files
authored
Merge pull request #86 from Ipuch/main
enhanced live animation
2 parents 4e19516 + 400a50c commit a90569c

File tree

1 file changed

+72
-4
lines changed

1 file changed

+72
-4
lines changed

pyorerun/live_animation.py

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ class LiveModelAnimation:
1616
----------
1717
counter : int
1818
A counter to keep track of the number of updates.
19-
model : BiorbdModel
20-
The biorbd model to animate.
19+
model_updater : ModelUpdater
20+
An instance of ModelUpdater to handle model updates.
21+
model : AbstractModel
22+
The model to animate.
2123
q : np.ndarray
2224
The current joint angles.
2325
dof_sliders : list
@@ -41,6 +43,10 @@ def __init__(self, model_updater: ModelUpdater, with_q_charts: bool = False):
4143
"""
4244

4345
self.counter = 0
46+
self.use_degrees = False
47+
self.root = None
48+
self._btn_toggle_units = None
49+
4450
self.model_updater = model_updater
4551
self.model = self.model_updater.model
4652

@@ -109,19 +115,81 @@ def rerun(self, name: str = None):
109115
self.create_window_with_sliders()
110116

111117
def create_window_with_sliders(self):
112-
root = tk.Tk()
118+
self.root = tk.Tk()
119+
root = self.root
113120
root.title("Degree of Freedom q Sliders")
114121

115122
for i in range(self.model.nb_q):
116123
self.update_functions.append(lambda event, idx=i: self.update_viewer(event, idx))
124+
117125
dof_slider_label = ttk.Label(root, text=f"q{i} - {self.model.dof_names[i]}: ", anchor="w")
118126
dof_slider_label.grid(row=i, column=0, padx=10, pady=5, sticky="w")
119127

120128
self.dof_sliders.append(
121129
ttk.Scale(root, from_=-5, to=5, orient="horizontal", command=self.update_functions[i], length=200)
122130
)
123131
self.dof_sliders[i].grid(row=i, column=1, padx=30, pady=5)
124-
self.dof_slider_values.append(ttk.Label(root, text="0"))
132+
133+
self.dof_slider_values.append(ttk.Label(root, text=self._format_value_for_ui(0.0)))
125134
self.dof_slider_values[i].grid(row=i, column=2, padx=10, pady=5)
126135

136+
base_row = self.model.nb_q
137+
btn_copy = ttk.Button(root, text="Copy q", command=self._copy_q_values())
138+
btn_copy.grid(row=base_row, column=0, padx=10, pady=10, sticky="ew")
139+
140+
self._btn_toggle_units = ttk.Button(root, text="Switch rad/deg", command=self._toggle_units)
141+
self._btn_toggle_units.grid(row=base_row, column=1, padx=10, pady=10, sticky="ew")
142+
143+
btn_reset = ttk.Button(root, text="Reset all", command=self._reset_all)
144+
btn_reset.grid(row=base_row, column=2, padx=10, pady=10, sticky="ew")
145+
127146
root.mainloop()
147+
148+
def _format_value_for_ui(self, value_rad: float) -> str:
149+
if self.use_degrees:
150+
return f"{np.degrees(value_rad):.2f}°"
151+
return f"{value_rad:.2f} rad"
152+
153+
def _update_value_label(self, idx: int):
154+
val_rad = float(self.dof_sliders[idx].get())
155+
self.dof_slider_values[idx].config(text=self._format_value_for_ui(val_rad))
156+
157+
def _toggle_units(self):
158+
self.use_degrees = not self.use_degrees
159+
# rafraîchir toutes les étiquettes de valeurs
160+
for i in range(self.model.nb_q):
161+
self._update_value_label(i)
162+
163+
def _copy_q_values(self):
164+
if self.root is None:
165+
return
166+
if self.use_degrees:
167+
values = [float(np.degrees(self.dof_sliders[i].get())) for i in range(self.model.nb_q)]
168+
unit = "deg"
169+
else:
170+
values = [float(self.dof_sliders[i].get()) for i in range(self.model.nb_q)]
171+
unit = "rad"
172+
173+
text = ", ".join(f"{v:.6f}" for v in values) + f" [{unit}]"
174+
self.root.clipboard_clear()
175+
self.root.clipboard_append(text)
176+
177+
def _reset_all(self):
178+
self.q[:] = 0.0
179+
for i, s in enumerate(self.dof_sliders):
180+
s.configure(command=None)
181+
s.set(0.0)
182+
self._update_value_label(i)
183+
s.configure(command=self.update_functions[i])
184+
185+
self.counter += 1
186+
rr.set_time(timeline="step", sequence=self.counter)
187+
self.update_model(self.q)
188+
if self.with_q_charts:
189+
self.update_trajectories(self.q)
190+
191+
def fetch_and_update_slider_value(self, event, dof_index: int) -> tuple[int, float]:
192+
the_dof_idx = dof_index
193+
val_rad = float(self.dof_sliders[the_dof_idx].get())
194+
self.dof_slider_values[the_dof_idx].config(text=self._format_value_for_ui(val_rad))
195+
return the_dof_idx, val_rad

0 commit comments

Comments
 (0)