openscvx 0.3.2.dev170__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of openscvx might be problematic. Click here for more details.
- openscvx/__init__.py +123 -0
- openscvx/_version.py +34 -0
- openscvx/algorithms/__init__.py +92 -0
- openscvx/algorithms/autotuning.py +24 -0
- openscvx/algorithms/base.py +351 -0
- openscvx/algorithms/optimization_results.py +215 -0
- openscvx/algorithms/penalized_trust_region.py +384 -0
- openscvx/config.py +437 -0
- openscvx/discretization/__init__.py +47 -0
- openscvx/discretization/discretization.py +236 -0
- openscvx/expert/__init__.py +23 -0
- openscvx/expert/byof.py +326 -0
- openscvx/expert/lowering.py +419 -0
- openscvx/expert/validation.py +357 -0
- openscvx/integrators/__init__.py +48 -0
- openscvx/integrators/runge_kutta.py +281 -0
- openscvx/lowered/__init__.py +30 -0
- openscvx/lowered/cvxpy_constraints.py +23 -0
- openscvx/lowered/cvxpy_variables.py +124 -0
- openscvx/lowered/dynamics.py +34 -0
- openscvx/lowered/jax_constraints.py +133 -0
- openscvx/lowered/parameters.py +54 -0
- openscvx/lowered/problem.py +70 -0
- openscvx/lowered/unified.py +718 -0
- openscvx/plotting/__init__.py +63 -0
- openscvx/plotting/plotting.py +756 -0
- openscvx/plotting/scp_iteration.py +299 -0
- openscvx/plotting/viser/__init__.py +126 -0
- openscvx/plotting/viser/animated.py +605 -0
- openscvx/plotting/viser/plotly_integration.py +333 -0
- openscvx/plotting/viser/primitives.py +355 -0
- openscvx/plotting/viser/scp.py +459 -0
- openscvx/plotting/viser/server.py +112 -0
- openscvx/problem.py +734 -0
- openscvx/propagation/__init__.py +60 -0
- openscvx/propagation/post_processing.py +104 -0
- openscvx/propagation/propagation.py +248 -0
- openscvx/solvers/__init__.py +51 -0
- openscvx/solvers/cvxpy.py +226 -0
- openscvx/symbolic/__init__.py +9 -0
- openscvx/symbolic/augmentation.py +630 -0
- openscvx/symbolic/builder.py +492 -0
- openscvx/symbolic/constraint_set.py +92 -0
- openscvx/symbolic/expr/__init__.py +222 -0
- openscvx/symbolic/expr/arithmetic.py +517 -0
- openscvx/symbolic/expr/array.py +632 -0
- openscvx/symbolic/expr/constraint.py +796 -0
- openscvx/symbolic/expr/control.py +135 -0
- openscvx/symbolic/expr/expr.py +720 -0
- openscvx/symbolic/expr/lie/__init__.py +87 -0
- openscvx/symbolic/expr/lie/adjoint.py +357 -0
- openscvx/symbolic/expr/lie/se3.py +172 -0
- openscvx/symbolic/expr/lie/so3.py +138 -0
- openscvx/symbolic/expr/linalg.py +279 -0
- openscvx/symbolic/expr/math.py +699 -0
- openscvx/symbolic/expr/spatial.py +209 -0
- openscvx/symbolic/expr/state.py +607 -0
- openscvx/symbolic/expr/stl.py +136 -0
- openscvx/symbolic/expr/variable.py +321 -0
- openscvx/symbolic/hashing.py +112 -0
- openscvx/symbolic/lower.py +760 -0
- openscvx/symbolic/lowerers/__init__.py +106 -0
- openscvx/symbolic/lowerers/cvxpy.py +1302 -0
- openscvx/symbolic/lowerers/jax.py +1382 -0
- openscvx/symbolic/preprocessing.py +757 -0
- openscvx/symbolic/problem.py +110 -0
- openscvx/symbolic/time.py +116 -0
- openscvx/symbolic/unified.py +420 -0
- openscvx/utils/__init__.py +20 -0
- openscvx/utils/cache.py +131 -0
- openscvx/utils/caching.py +210 -0
- openscvx/utils/printing.py +301 -0
- openscvx/utils/profiling.py +37 -0
- openscvx/utils/utils.py +100 -0
- openscvx-0.3.2.dev170.dist-info/METADATA +350 -0
- openscvx-0.3.2.dev170.dist-info/RECORD +79 -0
- openscvx-0.3.2.dev170.dist-info/WHEEL +5 -0
- openscvx-0.3.2.dev170.dist-info/licenses/LICENSE +201 -0
- openscvx-0.3.2.dev170.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import plotly.graph_objects as go
|
|
3
|
+
from plotly.subplots import make_subplots
|
|
4
|
+
|
|
5
|
+
from openscvx.algorithms import OptimizationResults
|
|
6
|
+
|
|
7
|
+
from .plotting import _get_var
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def plot_scp_iterations(
|
|
11
|
+
result: OptimizationResults,
|
|
12
|
+
state_names: list[str] | None = None,
|
|
13
|
+
control_names: list[str] | None = None,
|
|
14
|
+
cmap_name: str = "viridis",
|
|
15
|
+
show_propagation: bool = True,
|
|
16
|
+
):
|
|
17
|
+
"""Plot all SCP iterations overlaid with colormap-based coloring.
|
|
18
|
+
|
|
19
|
+
Shows the evolution of states and controls across SCP iterations. Early
|
|
20
|
+
iterations are dark, later iterations are bright (following the colormap).
|
|
21
|
+
This makes convergence visible at a glance.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
result: Optimization results containing iteration history
|
|
25
|
+
state_names: Optional list of state names to include. If None, plots all states.
|
|
26
|
+
control_names: Optional list of control names to include. If None, plots all controls.
|
|
27
|
+
cmap_name: Matplotlib colormap name (default: "viridis")
|
|
28
|
+
show_propagation: If True, show multi-shot propagation lines (default: True)
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Plotly figure with all iterations overlaid
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
>>> results = problem.solve()
|
|
35
|
+
>>> plot_scp_iterations(results, ["position", "velocity"]).show()
|
|
36
|
+
"""
|
|
37
|
+
import matplotlib.pyplot as plt
|
|
38
|
+
|
|
39
|
+
if not result.X:
|
|
40
|
+
raise ValueError("No iteration history available in result.X")
|
|
41
|
+
|
|
42
|
+
# Derive dimensions from result data
|
|
43
|
+
n_x = result.X[0].shape[1]
|
|
44
|
+
n_u = result.U[0].shape[1]
|
|
45
|
+
|
|
46
|
+
# Find time slice by looking for "time" state
|
|
47
|
+
time_slice = None
|
|
48
|
+
for state in result._states:
|
|
49
|
+
if state.name.lower() == "time":
|
|
50
|
+
time_slice = state._slice
|
|
51
|
+
break
|
|
52
|
+
|
|
53
|
+
# Extract multi-shot propagation trajectories
|
|
54
|
+
V_history = result.discretization_history if result.discretization_history else []
|
|
55
|
+
X_prop_history = []
|
|
56
|
+
if V_history and show_propagation:
|
|
57
|
+
i4 = n_x + n_x * n_x + 2 * n_x * n_u
|
|
58
|
+
for V in V_history:
|
|
59
|
+
pos_traj = []
|
|
60
|
+
for i_multi in range(V.shape[1]):
|
|
61
|
+
pos_traj.append(V[:, i_multi].reshape(-1, i4)[:, :n_x])
|
|
62
|
+
X_prop_history.append(np.array(pos_traj))
|
|
63
|
+
|
|
64
|
+
n_iterations = len(result.X)
|
|
65
|
+
if X_prop_history:
|
|
66
|
+
n_iterations = min(n_iterations, len(X_prop_history))
|
|
67
|
+
|
|
68
|
+
# Filter states and controls (exclude ctcs_aug and time)
|
|
69
|
+
states = [
|
|
70
|
+
s for s in result._states if "ctcs_aug" not in s.name.lower() and s.name.lower() != "time"
|
|
71
|
+
]
|
|
72
|
+
controls = list(result._controls) if result._controls else []
|
|
73
|
+
|
|
74
|
+
state_filter = set(state_names) if state_names else None
|
|
75
|
+
control_filter = set(control_names) if control_names else None
|
|
76
|
+
|
|
77
|
+
if state_filter and control_filter is None:
|
|
78
|
+
controls = []
|
|
79
|
+
if control_filter and state_filter is None:
|
|
80
|
+
states = []
|
|
81
|
+
if state_filter:
|
|
82
|
+
states = [s for s in states if s.name in state_filter]
|
|
83
|
+
if not states:
|
|
84
|
+
available = {s.name for s in result._states if "ctcs_aug" not in s.name.lower()}
|
|
85
|
+
raise ValueError(
|
|
86
|
+
f"No states matched filter {state_names}. Available: {sorted(available)}"
|
|
87
|
+
)
|
|
88
|
+
if control_filter:
|
|
89
|
+
controls = [c for c in controls if c.name in control_filter]
|
|
90
|
+
if not controls:
|
|
91
|
+
available = {c.name for c in result._controls}
|
|
92
|
+
raise ValueError(
|
|
93
|
+
f"No controls matched filter {control_names}. Available: {sorted(available)}"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
if not states and not controls:
|
|
97
|
+
raise ValueError("No states or controls to plot")
|
|
98
|
+
|
|
99
|
+
# Expand multi-dimensional variables to individual components
|
|
100
|
+
def expand_variables(variables):
|
|
101
|
+
expanded = []
|
|
102
|
+
for var in variables:
|
|
103
|
+
s = var._slice
|
|
104
|
+
start = s.start if isinstance(s, slice) else s
|
|
105
|
+
stop = s.stop if isinstance(s, slice) else start + 1
|
|
106
|
+
n_comp = (stop or start + 1) - (start or 0)
|
|
107
|
+
|
|
108
|
+
for i in range(n_comp):
|
|
109
|
+
expanded.append(
|
|
110
|
+
{
|
|
111
|
+
"name": f"{var.name}_{i}" if n_comp > 1 else var.name,
|
|
112
|
+
"idx": start + i,
|
|
113
|
+
"parent": var.name,
|
|
114
|
+
"comp": i,
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
return expanded
|
|
118
|
+
|
|
119
|
+
expanded_states = expand_variables(states)
|
|
120
|
+
expanded_controls = expand_variables(controls)
|
|
121
|
+
|
|
122
|
+
# Grid layout
|
|
123
|
+
n_states = len(expanded_states)
|
|
124
|
+
n_controls = len(expanded_controls)
|
|
125
|
+
n_state_cols = min(7, n_states) if n_states > 0 else 1
|
|
126
|
+
n_control_cols = min(3, n_controls) if n_controls > 0 else 1
|
|
127
|
+
n_state_rows = (n_states + n_state_cols - 1) // n_state_cols if n_states > 0 else 0
|
|
128
|
+
n_control_rows = (n_controls + n_control_cols - 1) // n_control_cols if n_controls > 0 else 0
|
|
129
|
+
total_rows = n_state_rows + n_control_rows
|
|
130
|
+
max_cols = max(n_state_cols, n_control_cols)
|
|
131
|
+
|
|
132
|
+
subplot_titles = [s["name"] for s in expanded_states] + [c["name"] for c in expanded_controls]
|
|
133
|
+
fig = make_subplots(
|
|
134
|
+
rows=total_rows,
|
|
135
|
+
cols=max_cols,
|
|
136
|
+
subplot_titles=subplot_titles,
|
|
137
|
+
vertical_spacing=0.08,
|
|
138
|
+
horizontal_spacing=0.05,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Get colormap
|
|
142
|
+
cmap = plt.get_cmap(cmap_name)
|
|
143
|
+
|
|
144
|
+
def iter_color(iter_idx):
|
|
145
|
+
rgba = cmap(iter_idx / max(n_iterations - 1, 1))
|
|
146
|
+
return f"rgb({int(rgba[0] * 255)},{int(rgba[1] * 255)},{int(rgba[2] * 255)})"
|
|
147
|
+
|
|
148
|
+
# Plot all iterations
|
|
149
|
+
for iter_idx in range(n_iterations):
|
|
150
|
+
X_nodes = result.X[iter_idx]
|
|
151
|
+
U_iter = result.U[iter_idx]
|
|
152
|
+
color = iter_color(iter_idx)
|
|
153
|
+
legend_group = f"iter_{iter_idx}"
|
|
154
|
+
show_legend_for_iter = True # Show legend for first trace of this iteration
|
|
155
|
+
|
|
156
|
+
t_nodes = (
|
|
157
|
+
X_nodes[:, time_slice].flatten()
|
|
158
|
+
if time_slice is not None
|
|
159
|
+
else np.linspace(0, result.t_final, X_nodes.shape[0])
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# States
|
|
163
|
+
for state_idx, state in enumerate(expanded_states):
|
|
164
|
+
row = (state_idx // n_state_cols) + 1
|
|
165
|
+
col = (state_idx % n_state_cols) + 1
|
|
166
|
+
idx = state["idx"]
|
|
167
|
+
|
|
168
|
+
# Multi-shot propagation lines
|
|
169
|
+
if X_prop_history and iter_idx < len(X_prop_history):
|
|
170
|
+
pos_traj = X_prop_history[iter_idx]
|
|
171
|
+
for j in range(pos_traj.shape[1]):
|
|
172
|
+
segment_times = pos_traj[:, j, time_slice].flatten()
|
|
173
|
+
segment_states = pos_traj[:, j, idx]
|
|
174
|
+
fig.add_trace(
|
|
175
|
+
go.Scatter(
|
|
176
|
+
x=segment_times,
|
|
177
|
+
y=segment_states,
|
|
178
|
+
mode="lines",
|
|
179
|
+
line={"color": color, "width": 1.5},
|
|
180
|
+
legendgroup=legend_group,
|
|
181
|
+
showlegend=show_legend_for_iter,
|
|
182
|
+
name=f"Iter {iter_idx}" if show_legend_for_iter else None,
|
|
183
|
+
hoverinfo="skip",
|
|
184
|
+
),
|
|
185
|
+
row=row,
|
|
186
|
+
col=col,
|
|
187
|
+
)
|
|
188
|
+
show_legend_for_iter = False
|
|
189
|
+
|
|
190
|
+
# Nodes
|
|
191
|
+
fig.add_trace(
|
|
192
|
+
go.Scatter(
|
|
193
|
+
x=t_nodes,
|
|
194
|
+
y=X_nodes[:, idx],
|
|
195
|
+
mode="markers",
|
|
196
|
+
marker={"color": color, "size": 5},
|
|
197
|
+
legendgroup=legend_group,
|
|
198
|
+
showlegend=show_legend_for_iter,
|
|
199
|
+
name=f"Iter {iter_idx}" if show_legend_for_iter else None,
|
|
200
|
+
hovertemplate=f"iter {iter_idx}<br>t=%{{x:.2f}}<br>y=%{{y:.3g}}<extra></extra>",
|
|
201
|
+
),
|
|
202
|
+
row=row,
|
|
203
|
+
col=col,
|
|
204
|
+
)
|
|
205
|
+
show_legend_for_iter = False
|
|
206
|
+
|
|
207
|
+
# Controls
|
|
208
|
+
for control_idx, control in enumerate(expanded_controls):
|
|
209
|
+
row = n_state_rows + (control_idx // n_control_cols) + 1
|
|
210
|
+
col = (control_idx % n_control_cols) + 1
|
|
211
|
+
idx = control["idx"]
|
|
212
|
+
|
|
213
|
+
fig.add_trace(
|
|
214
|
+
go.Scatter(
|
|
215
|
+
x=t_nodes,
|
|
216
|
+
y=U_iter[:, idx],
|
|
217
|
+
mode="markers",
|
|
218
|
+
marker={"color": color, "size": 5},
|
|
219
|
+
legendgroup=legend_group,
|
|
220
|
+
showlegend=show_legend_for_iter,
|
|
221
|
+
name=f"Iter {iter_idx}" if show_legend_for_iter else None,
|
|
222
|
+
hovertemplate=f"iter {iter_idx}<br>t=%{{x:.2f}}<br>y=%{{y:.3g}}<extra></extra>",
|
|
223
|
+
),
|
|
224
|
+
row=row,
|
|
225
|
+
col=col,
|
|
226
|
+
)
|
|
227
|
+
show_legend_for_iter = False
|
|
228
|
+
|
|
229
|
+
# Add bounds (once, using final iteration's time range)
|
|
230
|
+
t_nodes_final = (
|
|
231
|
+
result.X[-1][:, time_slice].flatten()
|
|
232
|
+
if time_slice is not None
|
|
233
|
+
else np.linspace(0, result.t_final, result.X[-1].shape[0])
|
|
234
|
+
)
|
|
235
|
+
t_min, t_max = t_nodes_final.min(), t_nodes_final.max()
|
|
236
|
+
|
|
237
|
+
for state_idx, state in enumerate(expanded_states):
|
|
238
|
+
row = (state_idx // n_state_cols) + 1
|
|
239
|
+
col = (state_idx % n_state_cols) + 1
|
|
240
|
+
parent = _get_var(result, state["parent"], result._states)
|
|
241
|
+
comp_idx = state["comp"]
|
|
242
|
+
|
|
243
|
+
for bound_val, bound_attr in [(parent.min, "min"), (parent.max, "max")]:
|
|
244
|
+
if bound_val is not None and np.isfinite(bound_val[comp_idx]):
|
|
245
|
+
fig.add_trace(
|
|
246
|
+
go.Scatter(
|
|
247
|
+
x=[t_min, t_max],
|
|
248
|
+
y=[bound_val[comp_idx], bound_val[comp_idx]],
|
|
249
|
+
mode="lines",
|
|
250
|
+
line={"color": "red", "width": 1.5, "dash": "dot"},
|
|
251
|
+
showlegend=False,
|
|
252
|
+
hoverinfo="skip",
|
|
253
|
+
),
|
|
254
|
+
row=row,
|
|
255
|
+
col=col,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
for control_idx, control in enumerate(expanded_controls):
|
|
259
|
+
row = n_state_rows + (control_idx // n_control_cols) + 1
|
|
260
|
+
col = (control_idx % n_control_cols) + 1
|
|
261
|
+
parent = _get_var(result, control["parent"], result._controls)
|
|
262
|
+
comp_idx = control["comp"]
|
|
263
|
+
|
|
264
|
+
for bound_val in [parent.min, parent.max]:
|
|
265
|
+
if bound_val is not None and np.isfinite(bound_val[comp_idx]):
|
|
266
|
+
fig.add_trace(
|
|
267
|
+
go.Scatter(
|
|
268
|
+
x=[t_min, t_max],
|
|
269
|
+
y=[bound_val[comp_idx], bound_val[comp_idx]],
|
|
270
|
+
mode="lines",
|
|
271
|
+
line={"color": "red", "width": 1.5, "dash": "dot"},
|
|
272
|
+
showlegend=False,
|
|
273
|
+
hoverinfo="skip",
|
|
274
|
+
),
|
|
275
|
+
row=row,
|
|
276
|
+
col=col,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
# Layout
|
|
280
|
+
fig.update_layout(
|
|
281
|
+
title_text="SCP Iterations",
|
|
282
|
+
template="plotly_dark",
|
|
283
|
+
showlegend=True,
|
|
284
|
+
legend={
|
|
285
|
+
"title": "Iterations",
|
|
286
|
+
"yanchor": "top",
|
|
287
|
+
"y": 0.99,
|
|
288
|
+
"xanchor": "left",
|
|
289
|
+
"x": 1.02,
|
|
290
|
+
"bgcolor": "rgba(0, 0, 0, 0.5)",
|
|
291
|
+
"itemclick": "toggle",
|
|
292
|
+
"itemdoubleclick": "toggleothers",
|
|
293
|
+
},
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
for col_idx in range(1, max_cols + 1):
|
|
297
|
+
fig.update_xaxes(title_text="Time (s)", row=total_rows, col=col_idx)
|
|
298
|
+
|
|
299
|
+
return fig
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Composable 3D visualization primitives using viser.
|
|
2
|
+
|
|
3
|
+
This module provides building blocks for creating interactive 3D trajectory
|
|
4
|
+
visualizations. The design philosophy is to give you useful primitives that
|
|
5
|
+
you can mix and match - not a monolithic plotting function that tries to
|
|
6
|
+
handle every case.
|
|
7
|
+
|
|
8
|
+
**Basic Pattern**:
|
|
9
|
+
1. Create a ``viser.ViserServer`` (use our helper, or make your own!)
|
|
10
|
+
2. Add static scene elements (obstacles, gates, ground planes, etc.)
|
|
11
|
+
3. Add animated elements - each returns ``(handle, update_callback)``
|
|
12
|
+
4. Wire up animation controls with your list of update callbacks
|
|
13
|
+
5. Call ``server.sleep_forever()`` to keep the visualization running
|
|
14
|
+
|
|
15
|
+
**Example - Building Your Own Visualization**::
|
|
16
|
+
|
|
17
|
+
from openscvx.plotting import viser
|
|
18
|
+
|
|
19
|
+
# Step 1: Create server (or just use viser.ViserServer() directly!)
|
|
20
|
+
server = viser.create_server(positions)
|
|
21
|
+
|
|
22
|
+
# Step 2: Add static elements
|
|
23
|
+
viser.add_gates(server, gate_vertices)
|
|
24
|
+
viser.add_ellipsoid_obstacles(server, centers, radii)
|
|
25
|
+
viser.add_ghost_trajectory(server, positions, colors)
|
|
26
|
+
|
|
27
|
+
# Step 3: Add animated elements (collect the update callbacks)
|
|
28
|
+
_, update_trail = viser.add_animated_trail(server, positions, colors)
|
|
29
|
+
_, update_marker = viser.add_position_marker(server, positions)
|
|
30
|
+
_, update_thrust = viser.add_thrust_vector(server, positions, thrust)
|
|
31
|
+
|
|
32
|
+
# Step 4: Wire up animation controls
|
|
33
|
+
viser.add_animation_controls(
|
|
34
|
+
server, time_array,
|
|
35
|
+
[update_trail, update_marker, update_thrust]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Step 5: Keep server running
|
|
39
|
+
server.sleep_forever()
|
|
40
|
+
|
|
41
|
+
**Available Primitives**:
|
|
42
|
+
- Server: ``create_server``, ``compute_velocity_colors``, ``compute_grid_size``
|
|
43
|
+
- Static: ``add_gates``, ``add_ellipsoid_obstacles``, ``add_glideslope_cone``,
|
|
44
|
+
``add_ghost_trajectory``
|
|
45
|
+
- Animated: ``add_animated_trail``, ``add_position_marker``, ``add_thrust_vector``,
|
|
46
|
+
``add_attitude_frame``, ``add_viewcone``, ``add_target_marker(s)``
|
|
47
|
+
- Plotly: ``add_animated_plotly_marker``, ``add_animated_vector_norm_plot``
|
|
48
|
+
- SCP iteration: ``add_scp_animation_controls``, ``add_scp_iteration_nodes``, etc.
|
|
49
|
+
|
|
50
|
+
For problem-specific examples (drones with viewcones, rockets with glideslope
|
|
51
|
+
constraints, etc.), see ``examples/plotting_viser.py``.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
# Server setup
|
|
55
|
+
# Animated components
|
|
56
|
+
from .animated import (
|
|
57
|
+
UpdateCallback,
|
|
58
|
+
add_animated_trail,
|
|
59
|
+
add_animation_controls,
|
|
60
|
+
add_attitude_frame,
|
|
61
|
+
add_position_marker,
|
|
62
|
+
add_target_marker,
|
|
63
|
+
add_target_markers,
|
|
64
|
+
add_thrust_vector,
|
|
65
|
+
add_viewcone,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Plotly integration
|
|
69
|
+
from .plotly_integration import (
|
|
70
|
+
add_animated_plotly_marker,
|
|
71
|
+
add_animated_plotly_vline,
|
|
72
|
+
add_animated_vector_norm_plot,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Static primitives
|
|
76
|
+
from .primitives import (
|
|
77
|
+
add_ellipsoid_obstacles,
|
|
78
|
+
add_gates,
|
|
79
|
+
add_ghost_trajectory,
|
|
80
|
+
add_glideslope_cone,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# SCP iteration visualization
|
|
84
|
+
from .scp import (
|
|
85
|
+
add_scp_animation_controls,
|
|
86
|
+
add_scp_ghost_iterations,
|
|
87
|
+
add_scp_iteration_attitudes,
|
|
88
|
+
add_scp_iteration_nodes,
|
|
89
|
+
add_scp_propagation_lines,
|
|
90
|
+
extract_propagation_positions,
|
|
91
|
+
)
|
|
92
|
+
from .server import compute_grid_size, compute_velocity_colors, create_server
|
|
93
|
+
|
|
94
|
+
__all__ = [
|
|
95
|
+
# Server
|
|
96
|
+
"create_server",
|
|
97
|
+
"compute_velocity_colors",
|
|
98
|
+
"compute_grid_size",
|
|
99
|
+
# Static primitives
|
|
100
|
+
"add_gates",
|
|
101
|
+
"add_ellipsoid_obstacles",
|
|
102
|
+
"add_glideslope_cone",
|
|
103
|
+
"add_ghost_trajectory",
|
|
104
|
+
# Animated components
|
|
105
|
+
"UpdateCallback",
|
|
106
|
+
"add_animated_trail",
|
|
107
|
+
"add_position_marker",
|
|
108
|
+
"add_target_marker",
|
|
109
|
+
"add_target_markers",
|
|
110
|
+
"add_thrust_vector",
|
|
111
|
+
"add_attitude_frame",
|
|
112
|
+
"add_viewcone",
|
|
113
|
+
# Animation controls
|
|
114
|
+
"add_animation_controls",
|
|
115
|
+
# Plotly integration
|
|
116
|
+
"add_animated_plotly_marker",
|
|
117
|
+
"add_animated_plotly_vline",
|
|
118
|
+
"add_animated_vector_norm_plot",
|
|
119
|
+
# SCP visualization
|
|
120
|
+
"add_scp_iteration_nodes",
|
|
121
|
+
"add_scp_iteration_attitudes",
|
|
122
|
+
"add_scp_ghost_iterations",
|
|
123
|
+
"extract_propagation_positions",
|
|
124
|
+
"add_scp_propagation_lines",
|
|
125
|
+
"add_scp_animation_controls",
|
|
126
|
+
]
|