3
3
from matplotlib .patches import Patch
4
4
from matplotlib .widgets import Slider , Button , CheckButtons
5
5
from matplotlib import rc
6
- rc ('animation' , html = 'html5' )
6
+
7
+ rc ("animation" , html = "html5" )
7
8
8
9
from jsrm .systems import planar_pcs_num , planar_pcs_sym
9
10
from pathlib import Path
24
25
"G" : 1e3 * jnp .ones ((num_segments ,)),
25
26
}
26
27
params ["D" ] = 1e-3 * jnp .diag (
27
- (jnp .repeat (jnp .array ([[1e0 , 1e3 , 1e3 ]]), num_segments , axis = 0 )
28
- * params ["l" ][:, None ]).flatten ()
28
+ (
29
+ jnp .repeat (jnp .array ([[1e0 , 1e3 , 1e3 ]]), num_segments , axis = 0 )
30
+ * params ["l" ][:, None ]
31
+ ).flatten ()
29
32
)
30
33
strain_selector = jnp .ones ((3 * num_segments ,), dtype = bool )
31
34
35
+
32
36
# === Chargement des fonctions Jacobiennes ===
33
37
def get_fwd_kine_fn (jacobian_type ):
34
38
if jacobian_type == "symbolic" :
35
- sym_exp_filepath = Path (jsrm .__file__ ).parent / "symbolic_expressions" / f"planar_pcs_ns-{ num_segments } .dill"
39
+ sym_exp_filepath = (
40
+ Path (jsrm .__file__ ).parent
41
+ / "symbolic_expressions"
42
+ / f"planar_pcs_ns-{ num_segments } .dill"
43
+ )
36
44
_ , fwd , _ , _ = planar_pcs_sym .factory (sym_exp_filepath , strain_selector )
37
45
else :
38
46
_ , fwd , _ , _ = planar_pcs_num .factory (
39
- num_segments , strain_selector ,
47
+ num_segments ,
48
+ strain_selector ,
40
49
integration_type = "gauss-legendre" ,
41
50
param_integration = 5 ,
42
- jacobian_type = jacobian_type
51
+ jacobian_type = jacobian_type ,
43
52
)
44
53
return fwd
45
54
55
+
46
56
FwdKine_autodiff_fn = get_fwd_kine_fn ("autodiff" )
47
57
FwdKine_explicit_fn = get_fwd_kine_fn ("explicit" )
48
58
FwdKine_symbolic_fn = get_fwd_kine_fn ("symbolic" )
@@ -54,10 +64,13 @@ def get_fwd_kine_fn(jacobian_type):
54
64
55
65
# === eps discret ===
56
66
eps_options = [None , 1e-6 , 1e-5 , 1e-4 , 1e-3 , 1e-2 , 1e-1 ]
57
- eps_labels = ['None' ] + [f'1e-{ i } ' for i in range (6 , 0 , - 1 )]
67
+ eps_labels = ["None" ] + [f"1e-{ i } " for i in range (6 , 0 , - 1 )]
68
+
69
+
58
70
def get_eps_from_slider ():
59
71
return eps_options [int (eps_slider .val )]
60
72
73
+
61
74
# === Variables physiques ===
62
75
borne_kappa = 1e-3
63
76
nb_kappa = 51
@@ -72,10 +85,11 @@ def get_eps_from_slider():
72
85
# === Tracé principal ===
73
86
fig , axs = plt .subplots (2 , figsize = (15 , 8 ))
74
87
88
+
75
89
def FwdKine_plot (eps_list , s , sigma_x , sigma_y , fig , axs ):
76
90
for ax in axs :
77
91
ax .clear ()
78
- ax .ticklabel_format (style = ' sci' , axis = ' both' , scilimits = (0 , 0 ))
92
+ ax .ticklabel_format (style = " sci" , axis = " both" , scilimits = (0 , 0 ))
79
93
ax .set_xlabel ("kappa (bending strain)" )
80
94
ax .set_ylabel ("Fwd Kinematics components" )
81
95
@@ -87,41 +101,66 @@ def FwdKine_plot(eps_list, s, sigma_x, sigma_y, fig, axs):
87
101
FwdKine_auto .append (FwdKine_autodiff_fn (params , q , s , ** FwdKine_kwargs ))
88
102
FwdKine_exp .append (FwdKine_explicit_fn (params , q , s , ** FwdKine_kwargs ))
89
103
FwdKine_symb .append (FwdKine_symbolic_fn (params , q , s , ** FwdKine_kwargs ))
90
- FwdKine_auto , FwdKine_exp , FwdKine_symb = jnp .stack (FwdKine_auto ), jnp .stack (FwdKine_exp ), jnp .stack (FwdKine_symb )
104
+ FwdKine_auto , FwdKine_exp , FwdKine_symb = (
105
+ jnp .stack (FwdKine_auto ),
106
+ jnp .stack (FwdKine_exp ),
107
+ jnp .stack (FwdKine_symb ),
108
+ )
91
109
92
110
for i in range (2 ):
93
111
if eps is not None :
94
- axs [i ].axvline (eps , color = 'red' , linestyle = ':' , linewidth = 2 , alpha = (i_eps + 1 )/ len (eps_list ), label = f'+/-eps={ eps :.2e} ' )
95
- axs [i ].axvline (- eps , color = 'red' , linestyle = ':' , linewidth = 2 , alpha = (i_eps + 1 )/ len (eps_list ))
112
+ axs [i ].axvline (
113
+ eps ,
114
+ color = "red" ,
115
+ linestyle = ":" ,
116
+ linewidth = 2 ,
117
+ alpha = (i_eps + 1 ) / len (eps_list ),
118
+ label = f"+/-eps={ eps :.2e} " ,
119
+ )
120
+ axs [i ].axvline (
121
+ - eps ,
122
+ color = "red" ,
123
+ linestyle = ":" ,
124
+ linewidth = 2 ,
125
+ alpha = (i_eps + 1 ) / len (eps_list ),
126
+ )
96
127
97
128
for j_type in list_of_type_of_jacobian :
98
- FwdKine = {"symbolic" : FwdKine_symb , "explicit" : FwdKine_exp , "autodiff" : FwdKine_auto }[j_type ]
129
+ FwdKine = {
130
+ "symbolic" : FwdKine_symb ,
131
+ "explicit" : FwdKine_exp ,
132
+ "autodiff" : FwdKine_auto ,
133
+ }[j_type ]
99
134
axs [i ].plot (
100
- kappa_values , FwdKine [:, i ],
135
+ kappa_values ,
136
+ FwdKine [:, i ],
101
137
marker = jacobian_markers [j_type ],
102
- label = f' FwdKine_{ j_type } ' ,
138
+ label = f" FwdKine_{ j_type } " ,
103
139
color = jacobian_colors [j_type ],
104
- alpha = (i_eps + 1 ) / len (eps_list ),
105
- markerfacecolor = ' none' ,
106
- markeredgecolor = jacobian_colors [j_type ]
140
+ alpha = (i_eps + 1 ) / len (eps_list ),
141
+ markerfacecolor = " none" ,
142
+ markeredgecolor = jacobian_colors [j_type ],
107
143
)
108
- axs [i ].set_title (f' FwdKine[{ i } ]' )
144
+ axs [i ].set_title (f" FwdKine[{ i } ]" )
109
145
axs [i ].grid (True )
110
146
111
- fig .suptitle (f"Fwd Kinematics components as a function of kappa\n s = { s :.3f} , sigma_x = { sigma_x :.3f} , sigma_y = { sigma_y - 1 :.3f} " )
147
+ fig .suptitle (
148
+ f"Fwd Kinematics components as a function of kappa\n s = { s :.3f} , sigma_x = { sigma_x :.3f} , sigma_y = { sigma_y - 1 :.3f} "
149
+ )
112
150
param_legend = 0.85
113
151
fig .tight_layout (rect = [0 , 0 , param_legend , 1 ])
114
152
115
153
handles , labels = axs [0 ].get_legend_handles_labels ()
116
154
# Supprimer doublons
117
155
unique = dict (zip (labels , handles ))
118
156
handles , labels = list (unique .values ()), list (unique .keys ())
119
- handles += [Patch (facecolor = ' white' )]
120
- labels += [f' s = { s :.2f} ' ]
157
+ handles += [Patch (facecolor = " white" )]
158
+ labels += [f" s = { s :.2f} " ]
121
159
if fig .legends :
122
160
for leg in fig .legends :
123
161
leg .remove ()
124
- fig .legend (handles , labels , loc = 'center left' , bbox_to_anchor = (param_legend , 0.5 ))
162
+ fig .legend (handles , labels , loc = "center left" , bbox_to_anchor = (param_legend , 0.5 ))
163
+
125
164
126
165
# === Valeurs initiales ===
127
166
initial_s = float (params ["l" ][0 ] / 2 )
@@ -132,10 +171,36 @@ def FwdKine_plot(eps_list, s, sigma_x, sigma_y, fig, axs):
132
171
FwdKine_plot ([eps_options [0 ]], initial_s , initial_sigma_x , initial_sigma_y , fig , axs )
133
172
134
173
# === Sliders ===
135
- s_slider = Slider (plt .axes ([0.2 , 0.01 , 0.65 , 0.03 ]), 's' , float (s_values [0 ]), float (s_values [- 1 ]), valinit = initial_s )
136
- sigma_x_slider = Slider (plt .axes ([0.2 , 0.05 , 0.65 , 0.03 ]), 'sigma_x' , float (sigma_x_values [0 ]), float (sigma_x_values [- 1 ]), valinit = initial_sigma_x )
137
- sigma_y_slider = Slider (plt .axes ([0.2 , 0.09 , 0.65 , 0.03 ]), 'sigma_y' , float (sigma_y_values [0 ]), float (sigma_y_values [- 1 ]), valinit = initial_sigma_y )
138
- eps_slider = Slider (plt .axes ([0.2 , 0.13 , 0.65 , 0.03 ]), 'eps (log scale)' , 0 , len (eps_options )- 1 , valinit = 0 , valstep = 1 )
174
+ s_slider = Slider (
175
+ plt .axes ([0.2 , 0.01 , 0.65 , 0.03 ]),
176
+ "s" ,
177
+ float (s_values [0 ]),
178
+ float (s_values [- 1 ]),
179
+ valinit = initial_s ,
180
+ )
181
+ sigma_x_slider = Slider (
182
+ plt .axes ([0.2 , 0.05 , 0.65 , 0.03 ]),
183
+ "sigma_x" ,
184
+ float (sigma_x_values [0 ]),
185
+ float (sigma_x_values [- 1 ]),
186
+ valinit = initial_sigma_x ,
187
+ )
188
+ sigma_y_slider = Slider (
189
+ plt .axes ([0.2 , 0.09 , 0.65 , 0.03 ]),
190
+ "sigma_y" ,
191
+ float (sigma_y_values [0 ]),
192
+ float (sigma_y_values [- 1 ]),
193
+ valinit = initial_sigma_y ,
194
+ )
195
+ eps_slider = Slider (
196
+ plt .axes ([0.2 , 0.13 , 0.65 , 0.03 ]),
197
+ "eps (log scale)" ,
198
+ 0 ,
199
+ len (eps_options ) - 1 ,
200
+ valinit = 0 ,
201
+ valstep = 1 ,
202
+ )
203
+
139
204
140
205
def on_slider_change (s_val , sigma_x_val , sigma_y_val ):
141
206
s = float (s_val )
@@ -145,28 +210,41 @@ def on_slider_change(s_val, sigma_x_val, sigma_y_val):
145
210
FwdKine_plot ([eps_val ], s , sigma_x , sigma_y , fig , axs )
146
211
fig .canvas .draw_idle ()
147
212
213
+
148
214
def update_sliders (_ ):
149
215
on_slider_change (s_slider .val , sigma_x_slider .val , sigma_y_slider .val )
150
216
217
+
151
218
s_slider .on_changed (update_sliders )
152
219
sigma_x_slider .on_changed (update_sliders )
153
220
sigma_y_slider .on_changed (update_sliders )
154
221
eps_slider .on_changed (update_sliders )
155
222
156
223
# === Boutons et CheckBoxes ===
157
224
reset_ax = plt .axes ([0.87 , 0.6 , 0.1 , 0.05 ])
158
- reset_button = Button (reset_ax , 'Reset sliders' )
159
- reset_button .on_clicked (lambda event : (s_slider .reset (), sigma_x_slider .reset (), sigma_y_slider .reset (), eps_slider .reset ()))
225
+ reset_button = Button (reset_ax , "Reset sliders" )
226
+ reset_button .on_clicked (
227
+ lambda event : (
228
+ s_slider .reset (),
229
+ sigma_x_slider .reset (),
230
+ sigma_y_slider .reset (),
231
+ eps_slider .reset (),
232
+ )
233
+ )
160
234
161
235
check_ax = plt .axes ([0.87 , 0.7 , 0.12 , 0.15 ])
162
- check = CheckButtons (check_ax , jacobian_types , [True ]* len (jacobian_types ))
236
+ check = CheckButtons (check_ax , jacobian_types , [True ] * len (jacobian_types ))
163
237
check_ax .set_title ("Jacobian types" )
164
238
239
+
165
240
def on_check (label ):
166
241
global list_of_type_of_jacobian
167
- list_of_type_of_jacobian = [jacobian_types [i ] for i , v in enumerate (check .get_status ()) if v ]
242
+ list_of_type_of_jacobian = [
243
+ jacobian_types [i ] for i , v in enumerate (check .get_status ()) if v
244
+ ]
168
245
update_sliders (None )
169
246
247
+
170
248
check .on_clicked (on_check )
171
249
172
250
plt .show ()
0 commit comments