Update app.py
Browse files
app.py
CHANGED
|
@@ -5,6 +5,13 @@ import matplotlib.pyplot as plt
|
|
| 5 |
import tempfile
|
| 6 |
import gradio as gr
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
def get_panda_joints(robot):
|
| 9 |
revolute = []
|
| 10 |
finger = []
|
|
@@ -18,36 +25,61 @@ def get_panda_joints(robot):
|
|
| 18 |
revolute.append(i)
|
| 19 |
return revolute, finger
|
| 20 |
|
| 21 |
-
# We will keep the simulation running globally
|
| 22 |
-
physicsClient = p.connect(p.DIRECT)
|
| 23 |
-
p.setAdditionalSearchPath(pybullet_data.getDataPath())
|
| 24 |
-
p.setGravity(0, 0, -9.8)
|
| 25 |
-
p.loadURDF("plane.urdf")
|
| 26 |
-
robot = p.loadURDF("franka_panda/panda.urdf", basePosition=[0, 0, 0])
|
| 27 |
arm_joints, finger_joints = get_panda_joints(robot)
|
| 28 |
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
|
|
|
| 32 |
p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=tgt)
|
| 33 |
|
| 34 |
for fj in finger_joints:
|
| 35 |
-
p.setJointMotorControl2(robot, fj, p.POSITION_CONTROL, targetPosition=
|
| 36 |
|
| 37 |
for _ in range(10):
|
| 38 |
p.stepSimulation()
|
| 39 |
|
|
|
|
|
|
|
| 40 |
view_matrix = p.computeViewMatrix([1.5, 0, 1], [0, 0, 0.5], [0, 0, 1])
|
| 41 |
-
proj_matrix = p.computeProjectionMatrixFOV(60,
|
| 42 |
-
_, _, img, _, _ = p.getCameraImage(
|
| 43 |
-
rgb = np.reshape(img, (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
|
| 46 |
-
plt.
|
|
|
|
| 47 |
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
return tmp.name, joint_text
|
| 50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
demo = gr.Interface(
|
| 52 |
fn=update_robot,
|
| 53 |
inputs=[
|
|
@@ -58,13 +90,17 @@ demo = gr.Interface(
|
|
| 58 |
gr.Slider(0.0, 0.04, value=0.02, step=0.001, label="Gripper Opening")
|
| 59 |
],
|
| 60 |
outputs=[
|
| 61 |
-
gr.Image(type="filepath", label="Live Simulation View"),
|
| 62 |
gr.Textbox(label="Live Joint States")
|
| 63 |
],
|
| 64 |
-
live=True,
|
| 65 |
-
title="Live Robot Control",
|
| 66 |
-
description="
|
| 67 |
)
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
if __name__ == "__main__":
|
| 70 |
demo.launch()
|
|
|
|
| 5 |
import tempfile
|
| 6 |
import gradio as gr
|
| 7 |
|
| 8 |
+
# Setup
|
| 9 |
+
physicsClient = p.connect(p.DIRECT)
|
| 10 |
+
p.setAdditionalSearchPath(pybullet_data.getDataPath())
|
| 11 |
+
p.setGravity(0, 0, -9.8)
|
| 12 |
+
p.loadURDF("plane.urdf")
|
| 13 |
+
robot = p.loadURDF("franka_panda/panda.urdf", basePosition=[0, 0, 0])
|
| 14 |
+
|
| 15 |
def get_panda_joints(robot):
|
| 16 |
revolute = []
|
| 17 |
finger = []
|
|
|
|
| 25 |
revolute.append(i)
|
| 26 |
return revolute, finger
|
| 27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
arm_joints, finger_joints = get_panda_joints(robot)
|
| 29 |
|
| 30 |
+
# Common function to simulate and render
|
| 31 |
+
def render_sim(joint_values, gripper_val):
|
| 32 |
+
# Set joint positions
|
| 33 |
+
for idx, tgt in zip(arm_joints[:4], joint_values):
|
| 34 |
p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=tgt)
|
| 35 |
|
| 36 |
for fj in finger_joints:
|
| 37 |
+
p.setJointMotorControl2(robot, fj, p.POSITION_CONTROL, targetPosition=gripper_val)
|
| 38 |
|
| 39 |
for _ in range(10):
|
| 40 |
p.stepSimulation()
|
| 41 |
|
| 42 |
+
# Camera
|
| 43 |
+
width, height = 512, 512
|
| 44 |
view_matrix = p.computeViewMatrix([1.5, 0, 1], [0, 0, 0.5], [0, 0, 1])
|
| 45 |
+
proj_matrix = p.computeProjectionMatrixFOV(60, width / height, 0.1, 3.1)
|
| 46 |
+
_, _, img, _, _ = p.getCameraImage(width, height, view_matrix, proj_matrix)
|
| 47 |
+
rgb = np.reshape(img, (height, width, 4))[:, :, :3]
|
| 48 |
+
|
| 49 |
+
# Annotate with labels
|
| 50 |
+
fig, ax = plt.subplots(figsize=(5, 5))
|
| 51 |
+
ax.imshow(rgb.astype(np.uint8))
|
| 52 |
+
ax.axis("off")
|
| 53 |
+
# Approx joint label positions (you may tweak)
|
| 54 |
+
labels = ["J1", "J2", "J3", "J4"]
|
| 55 |
+
positions = [(180, 400), (220, 320), (260, 240), (300, 160)]
|
| 56 |
+
for label, pos in zip(labels, positions):
|
| 57 |
+
ax.text(*pos, label, color="red", fontsize=12, fontweight="bold")
|
| 58 |
|
| 59 |
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
|
| 60 |
+
plt.savefig(tmp.name, bbox_inches='tight')
|
| 61 |
+
plt.close()
|
| 62 |
|
| 63 |
+
# Joint info
|
| 64 |
+
joint_text = (
|
| 65 |
+
f"Joint Angles:\n"
|
| 66 |
+
f"J1 = {joint_values[0]:.2f} rad\n"
|
| 67 |
+
f"J2 = {joint_values[1]:.2f} rad\n"
|
| 68 |
+
f"J3 = {joint_values[2]:.2f} rad\n"
|
| 69 |
+
f"J4 = {joint_values[3]:.2f} rad\n"
|
| 70 |
+
f"Gripper = {gripper_val:.3f} m"
|
| 71 |
+
)
|
| 72 |
return tmp.name, joint_text
|
| 73 |
|
| 74 |
+
# Main control
|
| 75 |
+
def update_robot(j1, j2, j3, j4, gripper):
|
| 76 |
+
return render_sim([j1, j2, j3, j4], gripper)
|
| 77 |
+
|
| 78 |
+
# Reset button
|
| 79 |
+
def reset_robot():
|
| 80 |
+
return render_sim([0, 0, 0, 0], 0.02)
|
| 81 |
+
|
| 82 |
+
# Interface
|
| 83 |
demo = gr.Interface(
|
| 84 |
fn=update_robot,
|
| 85 |
inputs=[
|
|
|
|
| 90 |
gr.Slider(0.0, 0.04, value=0.02, step=0.001, label="Gripper Opening")
|
| 91 |
],
|
| 92 |
outputs=[
|
| 93 |
+
gr.Image(type="filepath", label="Live Simulation View (with Joint Labels)"),
|
| 94 |
gr.Textbox(label="Live Joint States")
|
| 95 |
],
|
| 96 |
+
live=True,
|
| 97 |
+
title="Live Robot Control with Joint Labeling",
|
| 98 |
+
description="Control 4 joints and gripper. Click Reset to restore default position.",
|
| 99 |
)
|
| 100 |
|
| 101 |
+
# Add Reset Button
|
| 102 |
+
demo.add_component("button", "Reset", variant="secondary", elem_id="reset_btn")
|
| 103 |
+
demo.load(reset_robot, None, [demo.outputs[0], demo.outputs[1]], trigger="reset_btn")
|
| 104 |
+
|
| 105 |
if __name__ == "__main__":
|
| 106 |
demo.launch()
|