askuric HF Staff commited on
Commit
810bb77
Β·
1 Parent(s): fdfc751
Files changed (3) hide show
  1. README.md +4 -27
  2. app.py +37 -36
  3. planning_utils.py +16 -7
README.md CHANGED
@@ -11,33 +11,10 @@ pinned: false
11
 
12
  This space demonstrates a comparison between **capacity-aware real-time trajectory planning** and **TOPPRA** (Time-Optimal Path Parameterization with Reachability Analysis) for robotic manipulators.
13
 
14
- ## Features
15
-
16
- - 🎲 **Random Trajectory Generation**: Generate random Cartesian trajectories with configurable length
17
- - βš™οΈ **Capacity Scaling**: Test different robot capacity levels (0.1 to 1.0)
18
- - πŸ‘€ **Dual Robot Visualization**: Watch both algorithms execute simultaneously
19
- - **Left Robot**: Our capacity-aware approach
20
- - **Right Robot**: TOPPRA
21
- - πŸ“Š **Real-time Comparison Plots**:
22
- - Position vs Time
23
- - Velocity vs Time (with capacity limits)
24
- - Acceleration vs Time (with capacity limits)
25
- - Tracking Error comparison
26
-
27
- ## How to Use
28
-
29
- 1. **Configure Trajectory**:
30
- - Set the trajectory length (0.1m to 1.0m)
31
- - Set the robot capacity scale (0.1 to 1.0)
32
-
33
- 2. **Generate**: Click "Generate Random Trajectory" to create a new trajectory and compute both algorithms
34
-
35
- 3. **Visualize**:
36
- - View the dual robot animation in the MeshCat viewer
37
- - Click "Play Animation" to start the synchronized execution
38
- - Examine the comparison plots below
39
-
40
- 4. **Compare**: The info box shows timing comparisons between the two approaches
41
 
42
  ## Requirements
43
 
 
11
 
12
  This space demonstrates a comparison between **capacity-aware real-time trajectory planning** and **TOPPRA** (Time-Optimal Path Parameterization with Reachability Analysis) for robotic manipulators.
13
 
14
+ This space implements the paper:
15
+ **Online approach to near time-optimal task-space trajectory planning**
16
+ by Antun Skuric, Nicolas Torres Alberto, Lucas Joseph, Vincent Padois, David Daney
17
+ Link: https://inria.hal.science/hal-04576076
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  ## Requirements
20
 
app.py CHANGED
@@ -52,19 +52,19 @@ def create_comparison_plots(plot_data):
52
 
53
  # Position
54
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['x'], name='Ours',
55
- line=dict(color='#6C8EBF', width=2), showlegend=False), row=1, col=1)
56
  fig.add_trace(go.Scatter(x=toppra['t'], y=toppra['x'], name='TOPPRA',
57
- line=dict(color='#B85450', width=2), showlegend=False), row=1, col=1)
58
 
59
  # Velocity
60
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['dx'], name='Ours',
61
  line=dict(color='#6C8EBF', width=2), showlegend=False), row=1, col=2)
62
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['dx_max'], name='Ours Limits',
63
- line=dict(color='#6C8EBF', width=1, dash='dash'), showlegend=False), row=1, col=2)
64
  fig.add_trace(go.Scatter(x=toppra['t'], y=toppra['dx'], name='TOPPRA',
65
  line=dict(color='#B85450', width=2), showlegend=False), row=1, col=2)
66
  fig.add_trace(go.Scatter(x=toppra['t'], y=toppra['ds_max'], name='TOPPRA Limits',
67
- line=dict(color='#B85450', width=1, dash='dash'), showlegend=False), row=1, col=2)
68
 
69
  # Acceleration
70
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['ddx'], name='Ours',
@@ -102,16 +102,12 @@ def create_comparison_plots(plot_data):
102
 
103
  # Orientation Error
104
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['e_rot'], name='Ours',
105
- line=dict(color='#6C8EBF', width=2, dash='dot'), showlegend=False), row=3, col=2)
106
  fig.add_trace(go.Scatter(x=toppra['t'], y=toppra['e_rot'], name='TOPPRA',
107
- line=dict(color='#B85450', width=2, dash='dot'), showlegend=False), row=3, col=2)
108
 
109
 
110
  # Update axes
111
- # fig.update_xaxes(title_text="Time [s]", row=1, col=1)
112
- # fig.update_xaxes(title_text="Time [s]", row=1, col=2)
113
- # fig.update_xaxes(title_text="Time [s]", row=2, col=1)
114
- # fig.update_xaxes(title_text="Time [s]", row=2, col=2)
115
  fig.update_xaxes(title_text="Time [s]", row=3, col=1)
116
  fig.update_xaxes(title_text="Time [s]", row=3, col=2)
117
 
@@ -136,13 +132,18 @@ def animate_trajectory():
136
 
137
  t_max = anim_data['t_max']
138
 
139
- while animation_running:
 
 
140
  t0 = time.time()
141
 
142
  while animation_running and (time.time() - t0) < t_max:
143
  t_current = time.time() - t0
144
  planner.update_animation(t_current)
145
  time.sleep(0.01)
 
 
 
146
 
147
  def generate_and_compute(traj_length, capacity_scale, progress=gr.Progress()):
148
  """Generate trajectory and compute both algorithms"""
@@ -151,32 +152,32 @@ def generate_and_compute(traj_length, capacity_scale, progress=gr.Progress()):
151
 
152
  progress(0, desc="Generating trajectory...")
153
 
154
- try:
155
- result = planner.generate_trajectory(traj_length, capacity_scale, progress)
156
-
157
- info = f"""
158
- βœ… **Trajectory Generated Successfully**
159
-
160
- - **Waypoints**: {result['waypoints']}
161
- - **Trajectory Length**: {traj_length:.2f} m
162
- - **Capacity Scale**: {capacity_scale:.2f}
163
- - **TOPPRA Duration**: {result['toppra_duration']:.3f} s
164
- - **Ours Duration**: {result['ours_duration']:.3f} s
165
- - **Speedup**: {(result['toppra_duration'] / result['ours_duration']):.2f}x
166
- """
167
-
168
- progress(0.8, desc="Creating plots...")
169
-
170
- plot_data = planner.get_plot_data()
171
- plots = create_comparison_plots(plot_data)
172
-
173
- progress(1.0, desc="Done!")
174
-
175
- return info, plots, gr.update(interactive=True)
176
 
177
- except Exception as e:
178
- logging.error(f"Error generating trajectory: {e}")
179
- return f"❌ Error: {str(e)}", None, gr.update(interactive=False)
180
 
181
  def start_animation():
182
  """Start the animation"""
 
52
 
53
  # Position
54
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['x'], name='Ours',
55
+ line=dict(color='#6C8EBF', width=2), showlegend=True), row=1, col=1)
56
  fig.add_trace(go.Scatter(x=toppra['t'], y=toppra['x'], name='TOPPRA',
57
+ line=dict(color='#B85450', width=2), showlegend=True), row=1, col=1)
58
 
59
  # Velocity
60
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['dx'], name='Ours',
61
  line=dict(color='#6C8EBF', width=2), showlegend=False), row=1, col=2)
62
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['dx_max'], name='Ours Limits',
63
+ line=dict(color='#6C8EBF', width=1, dash='dash'), showlegend=True), row=1, col=2)
64
  fig.add_trace(go.Scatter(x=toppra['t'], y=toppra['dx'], name='TOPPRA',
65
  line=dict(color='#B85450', width=2), showlegend=False), row=1, col=2)
66
  fig.add_trace(go.Scatter(x=toppra['t'], y=toppra['ds_max'], name='TOPPRA Limits',
67
+ line=dict(color='#B85450', width=1, dash='dash'), showlegend=True), row=1, col=2)
68
 
69
  # Acceleration
70
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['ddx'], name='Ours',
 
102
 
103
  # Orientation Error
104
  fig.add_trace(go.Scatter(x=ours['t'], y=ours['e_rot'], name='Ours',
105
+ line=dict(color='#6C8EBF', width=2), showlegend=False), row=3, col=2)
106
  fig.add_trace(go.Scatter(x=toppra['t'], y=toppra['e_rot'], name='TOPPRA',
107
+ line=dict(color='#B85450', width=2), showlegend=False), row=3, col=2)
108
 
109
 
110
  # Update axes
 
 
 
 
111
  fig.update_xaxes(title_text="Time [s]", row=3, col=1)
112
  fig.update_xaxes(title_text="Time [s]", row=3, col=2)
113
 
 
132
 
133
  t_max = anim_data['t_max']
134
 
135
+ for i in range(10):
136
+ if not animation_running:
137
+ return
138
  t0 = time.time()
139
 
140
  while animation_running and (time.time() - t0) < t_max:
141
  t_current = time.time() - t0
142
  planner.update_animation(t_current)
143
  time.sleep(0.01)
144
+
145
+ animation_running = False
146
+
147
 
148
  def generate_and_compute(traj_length, capacity_scale, progress=gr.Progress()):
149
  """Generate trajectory and compute both algorithms"""
 
152
 
153
  progress(0, desc="Generating trajectory...")
154
 
155
+ # try:
156
+ result = planner.generate_trajectory(traj_length, capacity_scale, progress)
157
+
158
+ info = f"""
159
+ βœ… **Trajectory Generated Successfully**
160
+
161
+ - **Waypoints**: {result['waypoints']}
162
+ - **Trajectory Length**: {traj_length:.2f} m
163
+ - **Capacity Scale**: {capacity_scale:.2f}
164
+ - **TOPPRA Duration**: {result['toppra_duration']:.3f} s
165
+ - **Ours Duration**: {result['ours_duration']:.3f} s
166
+ - **Speedup**: {(result['toppra_duration'] / result['ours_duration']):.2f}x
167
+ """
168
+
169
+ progress(0.8, desc="Creating plots...")
170
+
171
+ plot_data = planner.get_plot_data()
172
+ plots = create_comparison_plots(plot_data)
173
+
174
+ progress(1.0, desc="Done!")
175
+
176
+ return info, plots, gr.update(interactive=True)
177
 
178
+ #except Exception as e:
179
+ # logging.error(f"Error generating trajectory: {e}")
180
+ # return f"❌ Error: {str(e)}", None, gr.update(interactive=False)
181
 
182
  def start_animation():
183
  """Start the animation"""
planning_utils.py CHANGED
@@ -892,6 +892,7 @@ def simulate_toppra(X_init, X_final, ts, qs, qds, qdds, q0, lims, scale, robot
892
  u = u/np.linalg.norm(u)
893
 
894
  # limtis calculation
 
895
  dq_max = scale*lims['dq_max']
896
  ddq_max = scale*lims['ddq_max']
897
  dddq_max = scale*lims['dddq_max']
@@ -1020,13 +1021,21 @@ def simulate_toppra(X_init, X_final, ts, qs, qds, qdds, q0, lims, scale, robot
1020
  data.ddds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=-V2@J_dot@ddq_c, x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c)
1021
  except:
1022
  print("except dds")
1023
- data.ds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dq_min, x_max=dq_max))
1024
- data.dds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c)
1025
- data.ddds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c)
1026
- data.ds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dq_min, x_max=dq_max))
1027
- data.dds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c)
1028
- data.ddds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c)
1029
-
 
 
 
 
 
 
 
 
1030
  data.t_toppra = ts
1031
  print('TOPPRA trajecotry simulation time',time.time() - s)
1032
  print(f'Trajectory duration: {data.t_toppra[-1]:0.4f} [s]')
 
892
  u = u/np.linalg.norm(u)
893
 
894
  # limtis calculation
895
+ scale = float(scale)
896
  dq_max = scale*lims['dq_max']
897
  ddq_max = scale*lims['ddq_max']
898
  dddq_max = scale*lims['dddq_max']
 
1021
  data.ddds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=-V2@J_dot@ddq_c, x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c)
1022
  except:
1023
  print("except dds")
1024
+ try:
1025
+ data.ds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dq_min, x_max=dq_max))
1026
+ data.dds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c)
1027
+ data.ddds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c)
1028
+ data.ds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dq_min, x_max=dq_max))
1029
+ data.dds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c)
1030
+ data.ddds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c)
1031
+ except:
1032
+ print("except dds 2")
1033
+ data.ds_max_list.append(data.ds_max_list[-1])
1034
+ data.dds_max_list.append(data.dds_max_list[-1])
1035
+ data.ddds_max_list.append(data.ddds_max_list[-1])
1036
+ data.ds_min_list.append(data.ds_min_list[-1])
1037
+ data.dds_min_list.append(data.dds_min_list[-1])
1038
+ data.ddds_min_list.append(data.ddds_min_list[-1])
1039
  data.t_toppra = ts
1040
  print('TOPPRA trajecotry simulation time',time.time() - s)
1041
  print(f'Trajectory duration: {data.t_toppra[-1]:0.4f} [s]')