cduss commited on
Commit
030090b
·
1 Parent(s): 46a132f
Files changed (1) hide show
  1. app.py +142 -21
app.py CHANGED
@@ -100,15 +100,26 @@ def create_app():
100
  url: 'http://localhost:8000',
101
  connected: false,
102
  controlling: false,
 
 
 
 
103
  request: async function(endpoint, method = 'GET', body = null) {{
104
  try {{
105
  const options = {{
106
  method: method,
107
  headers: {{'Content-Type': 'application/json'}},
108
  }};
109
- if (body) options.body = JSON.stringify(body);
 
 
 
110
  const response = await fetch(window.reachyApi.url + endpoint, options);
111
- if (!response.ok) throw new Error(`HTTP ${{response.status}}`);
 
 
 
 
112
  return await response.json();
113
  }} catch (error) {{
114
  console.error('API Error:', error);
@@ -146,6 +157,18 @@ def create_app():
146
  const antennas = state.antennas_position || [0, 0];
147
  const motorMode = state.control_mode || 'unknown';
148
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  return [
150
  statusMsg,
151
  `Motor Mode: ${motorMode}`,
@@ -266,28 +289,107 @@ def create_app():
266
  """)
267
  )
268
 
269
- # Slider change handlers
270
- all_sliders = [head_x, head_y, head_z, head_roll, head_pitch, head_yaw,
271
- body_yaw, antenna_left, antenna_right]
272
-
273
- slider_js = wrap_js("""
274
- async (x, y, z, roll, pitch, yaw, bodyYaw, antLeft, antRight) => {
275
- if (!window.reachyApi.connected) return;
276
- window.reachyApi.controlling = true;
277
- try {
278
- await window.reachyApi.request('/api/move/set_target', 'POST', {
279
- target_head_pose: {x, y, z, roll, pitch, yaw},
280
- target_body_yaw: bodyYaw,
281
- target_antennas: [antLeft, antRight]
282
- });
283
- } catch (error) {
284
- console.error('Set target error:', error);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  }
286
- }
287
- """)
288
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  for slider in all_sliders:
290
- slider.input(fn=None, inputs=all_sliders, outputs=[], js=slider_js)
291
  slider.release(
292
  fn=None,
293
  inputs=[],
@@ -320,12 +422,30 @@ def create_app():
320
  }
321
 
322
  try {
 
 
 
323
  const state = await window.reachyApi.request('/api/state/full?with_control_mode=true&with_head_pose=true&with_body_yaw=true&with_antenna_positions=true');
324
  const headPose = state.head_pose || {};
325
  const bodyYaw = state.body_yaw || 0;
326
  const antennas = state.antennas_position || [0, 0];
327
  const motorMode = state.control_mode || 'unknown';
328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  return [
330
  'Connected',
331
  `Motor Mode: ${motorMode}`,
@@ -341,6 +461,7 @@ def create_app():
341
  ];
342
  } catch (error) {
343
  window.reachyApi.connected = false;
 
344
  return ['Connection lost', 'Disconnected', 0, 0, 0, 0, 0, 0, 0, 0, 0];
345
  }
346
  }
 
100
  url: 'http://localhost:8000',
101
  connected: false,
102
  controlling: false,
103
+ isRefreshing: false,
104
+ currentHeadPose: {{ x: 0, y: 0, z: 0, roll: 0, pitch: 0, yaw: 0 }},
105
+ currentBodyYaw: 0,
106
+ currentAntennas: [0, 0],
107
  request: async function(endpoint, method = 'GET', body = null) {{
108
  try {{
109
  const options = {{
110
  method: method,
111
  headers: {{'Content-Type': 'application/json'}},
112
  }};
113
+ if (body) {{
114
+ options.body = JSON.stringify(body);
115
+ console.log('Request body:', JSON.stringify(body, null, 2));
116
+ }}
117
  const response = await fetch(window.reachyApi.url + endpoint, options);
118
+ if (!response.ok) {{
119
+ const errorText = await response.text();
120
+ console.error('API Error Response:', errorText);
121
+ throw new Error(`HTTP ${{response.status}}: ${{errorText}}`);
122
+ }}
123
  return await response.json();
124
  }} catch (error) {{
125
  console.error('API Error:', error);
 
157
  const antennas = state.antennas_position || [0, 0];
158
  const motorMode = state.control_mode || 'unknown';
159
 
160
+ // Initialize current state
161
+ window.reachyApi.currentHeadPose = {
162
+ x: headPose.x || 0,
163
+ y: headPose.y || 0,
164
+ z: headPose.z || 0,
165
+ roll: headPose.roll || 0,
166
+ pitch: headPose.pitch || 0,
167
+ yaw: headPose.yaw || 0
168
+ };
169
+ window.reachyApi.currentBodyYaw = bodyYaw;
170
+ window.reachyApi.currentAntennas = [antennas[0] || 0, antennas[1] || 0];
171
+
172
  return [
173
  statusMsg,
174
  `Motor Mode: ${motorMode}`,
 
289
  """)
290
  )
291
 
292
+ # Head pose slider handlers - individual handlers like in working control panel
293
+ def create_pose_handler(key):
294
+ return wrap_js(f"""
295
+ async (value) => {{
296
+ if (!window.reachyApi.connected) return;
297
+ if (window.reachyApi.isRefreshing) return;
298
+ window.reachyApi.controlling = true;
299
+ window.reachyApi.currentHeadPose.{key} = value;
300
+ try {{
301
+ await window.reachyApi.request('/api/move/set_target', 'POST', {{
302
+ target_head_pose: window.reachyApi.currentHeadPose,
303
+ target_body_yaw: window.reachyApi.currentBodyYaw,
304
+ target_antennas: window.reachyApi.currentAntennas
305
+ }});
306
+ }} catch (error) {{
307
+ console.error('Set target error:', error);
308
+ }}
309
+ }}
310
+ """)
311
+
312
+ head_x.input(fn=None, inputs=[head_x], outputs=[], js=create_pose_handler('x'))
313
+ head_y.input(fn=None, inputs=[head_y], outputs=[], js=create_pose_handler('y'))
314
+ head_z.input(fn=None, inputs=[head_z], outputs=[], js=create_pose_handler('z'))
315
+ head_roll.input(fn=None, inputs=[head_roll], outputs=[], js=create_pose_handler('roll'))
316
+ head_pitch.input(fn=None, inputs=[head_pitch], outputs=[], js=create_pose_handler('pitch'))
317
+ head_yaw.input(fn=None, inputs=[head_yaw], outputs=[], js=create_pose_handler('yaw'))
318
+
319
+ # Body yaw handler
320
+ body_yaw.input(
321
+ fn=None,
322
+ inputs=[body_yaw],
323
+ outputs=[],
324
+ js=wrap_js("""
325
+ async (value) => {
326
+ if (!window.reachyApi.connected) return;
327
+ if (window.reachyApi.isRefreshing) return;
328
+ window.reachyApi.controlling = true;
329
+ window.reachyApi.currentBodyYaw = value;
330
+ try {
331
+ await window.reachyApi.request('/api/move/set_target', 'POST', {
332
+ target_head_pose: window.reachyApi.currentHeadPose,
333
+ target_body_yaw: window.reachyApi.currentBodyYaw,
334
+ target_antennas: window.reachyApi.currentAntennas
335
+ });
336
+ } catch (error) {
337
+ console.error('Set target error:', error);
338
+ }
339
  }
340
+ """)
341
+ )
342
 
343
+ # Antenna handlers
344
+ antenna_left.input(
345
+ fn=None,
346
+ inputs=[antenna_left],
347
+ outputs=[],
348
+ js=wrap_js("""
349
+ async (value) => {
350
+ if (!window.reachyApi.connected) return;
351
+ if (window.reachyApi.isRefreshing) return;
352
+ window.reachyApi.controlling = true;
353
+ window.reachyApi.currentAntennas[0] = value;
354
+ try {
355
+ await window.reachyApi.request('/api/move/set_target', 'POST', {
356
+ target_head_pose: window.reachyApi.currentHeadPose,
357
+ target_body_yaw: window.reachyApi.currentBodyYaw,
358
+ target_antennas: window.reachyApi.currentAntennas
359
+ });
360
+ } catch (error) {
361
+ console.error('Set target error:', error);
362
+ }
363
+ }
364
+ """)
365
+ )
366
+
367
+ antenna_right.input(
368
+ fn=None,
369
+ inputs=[antenna_right],
370
+ outputs=[],
371
+ js=wrap_js("""
372
+ async (value) => {
373
+ if (!window.reachyApi.connected) return;
374
+ if (window.reachyApi.isRefreshing) return;
375
+ window.reachyApi.controlling = true;
376
+ window.reachyApi.currentAntennas[1] = value;
377
+ try {
378
+ await window.reachyApi.request('/api/move/set_target', 'POST', {
379
+ target_head_pose: window.reachyApi.currentHeadPose,
380
+ target_body_yaw: window.reachyApi.currentBodyYaw,
381
+ target_antennas: window.reachyApi.currentAntennas
382
+ });
383
+ } catch (error) {
384
+ console.error('Set target error:', error);
385
+ }
386
+ }
387
+ """)
388
+ )
389
+
390
+ # Release handler to stop controlling
391
+ all_sliders = [head_x, head_y, head_z, head_roll, head_pitch, head_yaw, body_yaw, antenna_left, antenna_right]
392
  for slider in all_sliders:
 
393
  slider.release(
394
  fn=None,
395
  inputs=[],
 
422
  }
423
 
424
  try {
425
+ // Set flag to prevent input handlers from triggering during update
426
+ window.reachyApi.isRefreshing = true;
427
+
428
  const state = await window.reachyApi.request('/api/state/full?with_control_mode=true&with_head_pose=true&with_body_yaw=true&with_antenna_positions=true');
429
  const headPose = state.head_pose || {};
430
  const bodyYaw = state.body_yaw || 0;
431
  const antennas = state.antennas_position || [0, 0];
432
  const motorMode = state.control_mode || 'unknown';
433
 
434
+ // Update current state
435
+ window.reachyApi.currentHeadPose = {
436
+ x: headPose.x || 0,
437
+ y: headPose.y || 0,
438
+ z: headPose.z || 0,
439
+ roll: headPose.roll || 0,
440
+ pitch: headPose.pitch || 0,
441
+ yaw: headPose.yaw || 0
442
+ };
443
+ window.reachyApi.currentBodyYaw = bodyYaw;
444
+ window.reachyApi.currentAntennas = [antennas[0] || 0, antennas[1] || 0];
445
+
446
+ // Clear flag after a short delay
447
+ setTimeout(() => { window.reachyApi.isRefreshing = false; }, 100);
448
+
449
  return [
450
  'Connected',
451
  `Motor Mode: ${motorMode}`,
 
461
  ];
462
  } catch (error) {
463
  window.reachyApi.connected = false;
464
+ window.reachyApi.isRefreshing = false;
465
  return ['Connection lost', 'Disconnected', 0, 0, 0, 0, 0, 0, 0, 0, 0];
466
  }
467
  }