File size: 9,211 Bytes
581790e 718d79d 581790e 85e8a2e 789a4c3 28d8725 718d79d 6111b0a 718d79d f6dacca 9a1ac54 f6dacca 9a1ac54 1d225fe 9a1ac54 f6dacca 3827efb 581790e 55b8cf4 9a1ac54 55b8cf4 6111b0a 9a1ac54 f6dacca 87933a4 ae34a04 87933a4 55b8cf4 6111b0a 55b8cf4 87933a4 55b8cf4 789a4c3 f6dacca 55b8cf4 789a4c3 87933a4 f6dacca 6111b0a f5d6cbd 55b8cf4 f5d6cbd 87933a4 f5d6cbd 87933a4 6111b0a f5d6cbd 55b8cf4 ae34a04 6111b0a 87933a4 cec7d8f ae34a04 cec7d8f ae34a04 fed0d1b 6111b0a 789a4c3 fed0d1b 55b8cf4 87933a4 fed0d1b 87933a4 fed0d1b cec7d8f ae34a04 fed0d1b 6111b0a ae34a04 fed0d1b 55b8cf4 87933a4 fed0d1b 87933a4 6111b0a 87933a4 55b8cf4 fed0d1b 576f97f 6111b0a 86611cc 55b8cf4 86611cc 55b8cf4 576f97f 55b8cf4 576f97f 1c8f6a7 86611cc 576f97f 1c8f6a7 86611cc 1c8f6a7 576f97f 86611cc 55b8cf4 576f97f 55b8cf4 6111b0a 55b8cf4 6111b0a 55b8cf4 6111b0a 55b8cf4 576f97f cec7d8f 6111b0a cec7d8f 6111b0a cec7d8f d7c02d7 576f97f cec7d8f 576f97f cec7d8f 6111b0a 55b8cf4 34d6946 86611cc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
import pybullet as p
import pybullet_data
import numpy as np
import matplotlib.pyplot as plt
import tempfile
import gradio as gr
import time
p.connect(p.DIRECT)
p.setAdditionalSearchPath(pybullet_data.getDataPath())
p.setGravity(0, 0, -9.8)
p.loadURDF("plane.urdf")
robot = p.loadURDF("franka_panda/panda.urdf", basePosition=[0, 0, 0], useFixedBase=True)
cube_id = p.loadURDF("cube_small.urdf", basePosition=[0.6, 0, 0.02])
p.changeVisualShape(cube_id, -1, rgbaColor=[0, 0, 0, 1])
def get_panda_joints(robot):
arm, fingers = [], []
for i in range(p.getNumJoints(robot)):
info = p.getJointInfo(robot, i)
name = info[1].decode()
joint_type = info[2]
if "finger" in name and joint_type == p.JOINT_PRISMATIC:
fingers.append(i)
elif joint_type == p.JOINT_REVOLUTE:
arm.append(i)
return arm, fingers
arm_joints, finger_joints = get_panda_joints(robot)
debug_labels = []
def add_joint_labels():
global debug_labels
for i in debug_labels:
p.removeUserDebugItem(i)
debug_labels.clear()
for idx in arm_joints:
link_state = p.getLinkState(robot, idx)
pos = link_state[0]
lbl = f"J{arm_joints.index(idx)+1}"
text_id = p.addUserDebugText(lbl, pos, textColorRGB=[1, 0, 0], textSize=1.2)
debug_labels.append(text_id)
def render_sim(joint_values, gripper_val, cam_xyz, target_xyz):
for idx, tgt in zip(arm_joints, joint_values):
p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=tgt)
if len(finger_joints) == 2:
for fj in finger_joints:
p.setJointMotorControl2(robot, fj, p.POSITION_CONTROL, targetPosition=gripper_val)
for _ in range(10): p.stepSimulation()
add_joint_labels()
width, height = 1280, 1280
view_matrix = p.computeViewMatrix(cam_xyz, target_xyz, [0, 0, 1])
proj_matrix = p.computeProjectionMatrixFOV(60, width / height, 0.1, 3.1)
_, _, img, _, _ = p.getCameraImage(width, height, view_matrix, proj_matrix)
rgb = np.reshape(img, (height, width, 4))[:, :, :3]
fig, ax = plt.subplots(figsize=(5, 5))
ax.imshow(rgb.astype(np.uint8))
ax.axis("off")
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
plt.savefig(tmp.name, bbox_inches='tight', dpi=200)
plt.close()
joint_text = "Joint Angles:\n" + "\n".join([f"J{i+1} = {v:.2f} rad" for i, v in enumerate(joint_values)])
joint_text += f"\nGripper = {gripper_val:.3f} m"
return tmp.name, joint_text
def move_to_input_angles(joint_str, cam_xyz, target_xyz):
try:
target_angles = [float(x.strip()) for x in joint_str.split(",")]
if len(target_angles) != 7:
return None, "β Please enter exactly 7 joint angles."
current = [p.getJointState(robot, idx)[0] for idx in arm_joints]
steps = 100
for i in range(steps):
blend = [(1 - i/steps) * c + (i/steps) * t for c, t in zip(current, target_angles)]
for idx, val in zip(arm_joints, blend):
p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=val)
p.stepSimulation()
time.sleep(0.01)
current_grip = p.getJointState(robot, finger_joints[0])[0]
return render_sim(target_angles, current_grip, cam_xyz, target_xyz)
except Exception as e:
return None, f"Error: {str(e)}"
def pick_and_place(position_str, approach_str, place_str, cam_xyz, target_xyz):
try:
position_angles = [float(x.strip()) for x in position_str.split(",")]
approach_angles = [float(x.strip()) for x in approach_str.split(",")]
place_angles = [float(x.strip()) for x in place_str.split(",")]
if len(position_angles) != 7 or len(approach_angles) != 7 or len(place_angles) != 7:
return None, "β All inputs must have 7 joint angles."
# Move to pre-grasp approach pose
move_to_input_angles(approach_str, cam_xyz, target_xyz)
# Grasping: move to actual grasp pose (over the object)
steps = 50
for i in range(steps):
interpolated = [(1 - i/steps) * approach_angles[j] + (i/steps) * position_angles[j] for j in range(7)]
for idx, val in zip(arm_joints, interpolated):
p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=val)
p.stepSimulation()
time.sleep(0.01)
# Close the gripper to grasp
for _ in range(30):
for fj in finger_joints:
p.setJointMotorControl2(robot, fj, p.POSITION_CONTROL, targetPosition=0.0) # Closed
p.stepSimulation()
time.sleep(0.01)
# Lift object slightly from grasp position
lifted_angles = [a + 0.1 for a in position_angles] # Add a small lift to each joint
for i in range(steps):
lifted_pose = [(1 - i/steps) * position_angles[j] + (i/steps) * lifted_angles[j] for j in range(7)]
for idx, val in zip(arm_joints, lifted_pose):
p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=val)
p.stepSimulation()
time.sleep(0.01)
# Move to place location
move_to_input_angles(place_str, cam_xyz, target_xyz)
# Release the gripper
for _ in range(30):
for fj in finger_joints:
p.setJointMotorControl2(robot, fj, p.POSITION_CONTROL, targetPosition=0.04) # Open
p.stepSimulation()
time.sleep(0.01)
return render_sim(place_angles, 0.04, cam_xyz, target_xyz)
except Exception as e:
return None, f"Error: {str(e)}"
# Copy current joint angles
def copy_current_joint_angles(*vals):
return ", ".join([f"{v:.4f}" for v in vals])
with gr.Blocks(title="Franka Arm with 3D Camera Control") as demo:
gr.Markdown("## π€ Franka Robot with Camera + Joint Control")
# Joint and gripper sliders
joint_sliders = []
with gr.Row():
for i in range(4):
joint_sliders.append(gr.Slider(-3.14, 3.14, value=0, label=f"Joint {i+1}"))
with gr.Row():
for i in range(4, 7):
joint_sliders.append(gr.Slider(-3.14, 3.14, value=0, label=f"Joint {i+1}"))
gripper = gr.Slider(0.0, 0.04, value=0.02, step=0.001, label="Gripper")
# Compact camera + target controls
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("**Camera Position**", elem_id="camera-position-label")
cam_x = gr.Slider(-3, 3, value=1.5, label="X")
cam_y = gr.Slider(-3, 3, value=0.0, label="Y")
cam_z = gr.Slider(-1, 3, value=1.0, label="Z")
with gr.Column(scale=1):
gr.Markdown("**Target Point**", elem_id="target-point-label")
tgt_x = gr.Slider(-1, 1, value=0.0, label="X")
tgt_y = gr.Slider(-1, 1, value=0.0, label="Y")
tgt_z = gr.Slider(0, 2, value=0.5, label="Z")
# Live image + output
with gr.Row():
img_output = gr.Image(type="filepath", label="Simulation View")
text_output = gr.Textbox(label="Joint States", lines=10)
# Live simulation update
def live_update(*vals):
joints = list(vals[:7])
grip = vals[7]
cam = [vals[8], vals[9], vals[10]]
tgt = [vals[11], vals[12], vals[13]]
return render_sim(joints, grip, cam, tgt)
sliders = joint_sliders + [gripper, cam_x, cam_y, cam_z, tgt_x, tgt_y, tgt_z]
for s in sliders:
s.change(fn=live_update, inputs=sliders, outputs=[img_output, text_output])
gr.Button("π Reset Robot").click(
fn=lambda: render_sim([0]*7, 0.02, [1.5, 0, 1.0], [0, 0, 0.5]),
inputs=[], outputs=[img_output, text_output]
)
# Move to angles box
gr.Markdown("### βοΈ Move Robot to Custom Joint Angles")
joint_input_box = gr.Textbox(label="Enter 7 Joint Angles (comma-separated)")
gr.Button("βΆοΈ Move to Angles").click(
fn=lambda s, x, y, z, tx, ty, tz: move_to_input_angles(s, [x, y, z], [tx, ty, tz]),
inputs=[joint_input_box, cam_x, cam_y, cam_z, tgt_x, tgt_y, tgt_z],
outputs=[img_output, text_output]
)
# Pick and Place section
gr.Markdown("### π§Ύ Pick and Place Input (3 sets of joint angles)")
with gr.Row():
position_input = gr.Textbox(label="Object Position Angles")
gr.Button("π Copy").click(fn=copy_current_joint_angles, inputs=joint_sliders, outputs=position_input)
with gr.Row():
approach_input = gr.Textbox(label="Approach Angles")
gr.Button("π Copy").click(fn=copy_current_joint_angles, inputs=joint_sliders, outputs=approach_input)
with gr.Row():
place_input = gr.Textbox(label="Place Angles")
gr.Button("π Copy").click(fn=copy_current_joint_angles, inputs=joint_sliders, outputs=place_input)
gr.Button("π€ Perform Pick and Place").click(
fn=lambda p, a, pl, x, y, z, tx, ty, tz: pick_and_place(p, a, pl, [x, y, z], [tx, ty, tz]),
inputs=[position_input, approach_input, place_input, cam_x, cam_y, cam_z, tgt_x, tgt_y, tgt_z],
outputs=[img_output, text_output]
)
demo.launch(debug=True)
|