hvoss-techfak commited on
Commit
66f720d
·
1 Parent(s): cd7ef06

performance changes

Browse files
Files changed (1) hide show
  1. app.py +59 -19
app.py CHANGED
@@ -96,6 +96,37 @@ class IKServer:
96
 
97
  self._register_routes()
98
  logger.info("Server ready.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  # ---------- Cache ----------
101
  def _evict_lru(self, is_urdf=False):
@@ -347,7 +378,7 @@ class IKServer:
347
  frames.append({"vertices": verts.tolist(), "faces": faces.tolist()})
348
  return frames
349
 
350
- def solve_agent(self, payload):
351
  mand, opt, sub = self._build_agent_objectives(payload)
352
  start = time.time()
353
  best_angles, obj_val, steps = self.solver.solve(
@@ -360,18 +391,20 @@ class IKServer:
360
  )
361
  self.best_angles = best_angles[-1].copy()
362
  self.initial_rotations = self.best_angles.copy()
363
- self.animation_frames_agent = self._frames_from_angles(best_angles, False)
364
- print(f"Solved in {time.time()-start:.2f}s over {steps} steps. Obj: {obj_val:.6f}")
365
- self.agent_solve_counter += 1 # added
 
 
366
  return {
367
  "solve_time": time.time()-start,
368
  "iterations": steps,
369
  "objective": obj_val,
370
  "frames": len(self.animation_frames_agent),
371
- "solve_id": self.agent_solve_counter, # added
372
  }
373
 
374
- def solve_urdf(self, payload):
375
  mand, opt, sub = self._build_urdf_objectives(payload)
376
  start = time.time()
377
  best_angles, obj_val, steps = self.urdf_solver.solve(
@@ -384,17 +417,17 @@ class IKServer:
384
  )
385
  self.urdf_best_angles = best_angles[-1].copy()
386
  self.urdf_initial_rotations = self.urdf_best_angles.copy()
387
- self.animation_frames_urdf = self._frames_from_angles(best_angles, True)
388
- print(
389
- f"Solved in {time.time() - start:.2f}s over {steps} steps. Obj: {obj_val:.6f}"
390
- )
391
- self.urdf_solve_counter += 1 # added
392
  return {
393
  "solve_time": time.time()-start,
394
  "iterations": steps,
395
  "objective": obj_val,
396
  "frames": len(self.animation_frames_urdf),
397
- "solve_id": self.urdf_solve_counter, # added
398
  }
399
 
400
  # ---------- Housekeeping ----------
@@ -467,6 +500,8 @@ class IKServer:
467
  model = payload.get("model","agent").lower()
468
  return_mode = payload.get("frames_mode", "auto")
469
  num_steps = int(payload.get("num_steps", self.args.num_steps)) # NEW
 
 
470
  self._cleanup()
471
  with self.solve_lock:
472
  try:
@@ -474,21 +509,25 @@ class IKServer:
474
  self.configure_urdf(payload.get("controlled_bones", []),
475
  payload.get("end_effector", self.urdf_current_end_effector),
476
  num_steps=num_steps)
477
- result = self.solve_urdf(payload); result["model"]="pepper"; result["num_steps"] = num_steps
478
- if return_mode == "all" or (return_mode == "auto" and payload.get("subpoints",1) > 1):
479
- frames = list(self.animation_frames_urdf) # ensure fresh list
 
 
480
  else:
481
- frames = [self.animation_frames_urdf[-1].copy()] if hasattr(self.animation_frames_urdf[-1],'copy') else [dict(self.animation_frames_urdf[-1])]
482
  result["frames_data"] = frames
483
  else:
484
  self.configure_agent(payload.get("controlled_bones", []),
485
  payload.get("end_effector", self.current_end_effector),
486
  num_steps=num_steps)
487
- result = self.solve_agent(payload); result["model"]="agent"; result["num_steps"] = num_steps
488
- if return_mode == "all" or (return_mode == "auto" and payload.get("subpoints",1) > 1):
 
 
489
  frames = list(self.animation_frames_agent)
490
  else:
491
- frames = [self.animation_frames_agent[-1].copy()] if hasattr(self.animation_frames_agent[-1],'copy') else [dict(self.animation_frames_agent[-1])]
492
  result["frames_data"] = frames
493
  return JSONResponse({"status":"ok","result":result})
494
  except Exception as e:
@@ -518,6 +557,7 @@ def main():
518
  parser.add("--learning_rate", type=float, default=0.2)
519
  parser.add("--subpoints", type=int, default=1)
520
  parser.add("--api_port", type=int, default=17861)
 
521
  args = parser.parse_args()
522
 
523
  download_and_setup_files()
 
96
 
97
  self._register_routes()
98
  logger.info("Server ready.")
99
+ # NEW warmup thread to JIT both solvers early
100
+ if getattr(self.args, 'warmup', True):
101
+ threading.Thread(target=self._warmup_all, daemon=True).start()
102
+
103
+ # ---- Warmup helpers (NEW) ----
104
+ def _warmup_agent(self):
105
+ try:
106
+ mand = [DistanceObjTraj(target_points=np.array([0.0,0.2,0.35]), bone_name=self.current_end_effector, use_head=True, weight=1.0)]
107
+ opt = [BoneZeroRotationObj(weight=0.01)]
108
+ _ = self.solver.solve(initial_rotations=self.initial_rotations, learning_rate=self.args.learning_rate,
109
+ mandatory_objective_functions=tuple(mand), optional_objective_functions=tuple(opt),
110
+ ik_points=1, verbose=False)
111
+ logger.info("Agent warmup complete")
112
+ except Exception as e:
113
+ logger.warning(f"Agent warmup failed: {e}")
114
+ def _warmup_urdf(self):
115
+ try:
116
+ mand = [DistanceObjTraj(target_points=np.array([0.3,0.3,0.35]), bone_name=self.urdf_current_end_effector, use_head=True, weight=1.0)]
117
+ opt = [BoneZeroRotationObj(weight=0.01)]
118
+ _ = self.urdf_solver.solve(initial_rotations=self.urdf_initial_rotations, learning_rate=self.args.learning_rate,
119
+ mandatory_objective_functions=tuple(mand), optional_objective_functions=tuple(opt),
120
+ ik_points=1, verbose=False)
121
+ logger.info("URDF warmup complete")
122
+ except Exception as e:
123
+ logger.warning(f"URDF warmup failed: {e}")
124
+ def _warmup_all(self):
125
+ t0 = time.time()
126
+ logger.info("Starting background warmup...")
127
+ self._warmup_agent()
128
+ self._warmup_urdf()
129
+ logger.info(f"Warmup finished in {time.time()-t0:.2f}s")
130
 
131
  # ---------- Cache ----------
132
  def _evict_lru(self, is_urdf=False):
 
378
  frames.append({"vertices": verts.tolist(), "faces": faces.tolist()})
379
  return frames
380
 
381
+ def solve_agent(self, payload, last_only=False):
382
  mand, opt, sub = self._build_agent_objectives(payload)
383
  start = time.time()
384
  best_angles, obj_val, steps = self.solver.solve(
 
391
  )
392
  self.best_angles = best_angles[-1].copy()
393
  self.initial_rotations = self.best_angles.copy()
394
+ if last_only:
395
+ self.animation_frames_agent = self._frames_from_angles([best_angles[-1]], False)
396
+ else:
397
+ self.animation_frames_agent = self._frames_from_angles(best_angles, False)
398
+ self.agent_solve_counter += 1
399
  return {
400
  "solve_time": time.time()-start,
401
  "iterations": steps,
402
  "objective": obj_val,
403
  "frames": len(self.animation_frames_agent),
404
+ "solve_id": self.agent_solve_counter,
405
  }
406
 
407
+ def solve_urdf(self, payload, last_only=False):
408
  mand, opt, sub = self._build_urdf_objectives(payload)
409
  start = time.time()
410
  best_angles, obj_val, steps = self.urdf_solver.solve(
 
417
  )
418
  self.urdf_best_angles = best_angles[-1].copy()
419
  self.urdf_initial_rotations = self.urdf_best_angles.copy()
420
+ if last_only:
421
+ self.animation_frames_urdf = self._frames_from_angles([best_angles[-1]], True)
422
+ else:
423
+ self.animation_frames_urdf = self._frames_from_angles(best_angles, True)
424
+ self.urdf_solve_counter += 1
425
  return {
426
  "solve_time": time.time()-start,
427
  "iterations": steps,
428
  "objective": obj_val,
429
  "frames": len(self.animation_frames_urdf),
430
+ "solve_id": self.urdf_solve_counter,
431
  }
432
 
433
  # ---------- Housekeeping ----------
 
500
  model = payload.get("model","agent").lower()
501
  return_mode = payload.get("frames_mode", "auto")
502
  num_steps = int(payload.get("num_steps", self.args.num_steps)) # NEW
503
+ subpoints = int(payload.get("subpoints",1))
504
+ last_only = (return_mode != 'all' and subpoints == 1)
505
  self._cleanup()
506
  with self.solve_lock:
507
  try:
 
509
  self.configure_urdf(payload.get("controlled_bones", []),
510
  payload.get("end_effector", self.urdf_current_end_effector),
511
  num_steps=num_steps)
512
+ result = self.solve_urdf(payload, last_only=last_only); result["model"]="pepper"; result["num_steps"] = num_steps
513
+ if last_only:
514
+ frames = list(self.animation_frames_urdf) # only one frame
515
+ elif return_mode == "all" or (return_mode == "auto" and subpoints > 1):
516
+ frames = list(self.animation_frames_urdf)
517
  else:
518
+ frames = [self.animation_frames_urdf[-1]]
519
  result["frames_data"] = frames
520
  else:
521
  self.configure_agent(payload.get("controlled_bones", []),
522
  payload.get("end_effector", self.current_end_effector),
523
  num_steps=num_steps)
524
+ result = self.solve_agent(payload, last_only=last_only); result["model"]="agent"; result["num_steps"] = num_steps
525
+ if last_only:
526
+ frames = list(self.animation_frames_agent)
527
+ elif return_mode == "all" or (return_mode == "auto" and subpoints > 1):
528
  frames = list(self.animation_frames_agent)
529
  else:
530
+ frames = [self.animation_frames_agent[-1]]
531
  result["frames_data"] = frames
532
  return JSONResponse({"status":"ok","result":result})
533
  except Exception as e:
 
557
  parser.add("--learning_rate", type=float, default=0.2)
558
  parser.add("--subpoints", type=int, default=1)
559
  parser.add("--api_port", type=int, default=17861)
560
+ parser.add("--warmup", action='store_true', default=True, help="Enable background JIT warmup")
561
  args = parser.parse_args()
562
 
563
  download_and_setup_files()