YashsharmaPhD commited on
Commit
ae34a04
·
verified ·
1 Parent(s): dbcae0b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -121
app.py CHANGED
@@ -6,16 +6,16 @@ import tempfile
6
  import gradio as gr
7
  import time
8
 
9
- # Setup PyBullet
10
  p.connect(p.DIRECT)
11
  p.setAdditionalSearchPath(pybullet_data.getDataPath())
12
  p.setGravity(0, 0, -9.8)
13
  p.loadURDF("plane.urdf")
14
  robot = p.loadURDF("franka_panda/panda.urdf", basePosition=[0, 0, 0], useFixedBase=True)
15
 
16
- # Add a cube to pick (black color by default)
17
  cube_id = p.loadURDF("cube_small.urdf", basePosition=[0.6, 0, 0.02])
18
- p.changeVisualShape(cube_id, -1, rgbaColor=[0, 0, 0, 1]) # Change the cube color to black
19
 
20
  # Get joint indices
21
  def get_panda_joints(robot):
@@ -32,149 +32,134 @@ def get_panda_joints(robot):
32
 
33
  arm_joints, finger_joints = get_panda_joints(robot)
34
 
35
- # Add 3D debug labels to the robot's joints
36
- debug_labels = []
37
  def add_joint_labels():
38
- global debug_labels
39
- for i in debug_labels:
40
- p.removeUserDebugItem(i)
41
- debug_labels.clear()
42
- for idx in arm_joints:
43
- link_state = p.getLinkState(robot, idx)
44
- pos = link_state[0]
45
- lbl = f"J{arm_joints.index(idx)+1}"
46
- text_id = p.addUserDebugText(lbl, pos, textColorRGB=[1, 0, 0], textSize=1.2)
47
- debug_labels.append(text_id)
48
-
49
- # Change cube color dynamically
50
- def change_cube_color(color):
51
- color_map = {
52
- "Black": [0, 0, 0, 1],
53
- "Red": [1, 0, 0, 1],
54
- "Green": [0, 1, 0, 1],
55
- "Blue": [0, 0, 1, 1],
56
- "Yellow": [1, 1, 0, 1],
57
- "White": [1, 1, 1, 1]
58
- }
59
- p.changeVisualShape(cube_id, -1, rgbaColor=color_map[color])
60
-
61
- # Render image and info
62
- def render_sim(joint_values, gripper_val, camera_angles):
63
- # Apply joint controls
64
  for idx, tgt in zip(arm_joints, joint_values):
65
  p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=tgt)
66
 
67
- # Open/close gripper symmetrically
68
- if len(finger_joints) == 2:
69
- p.setJointMotorControl2(robot, finger_joints[0], p.POSITION_CONTROL, targetPosition=gripper_val)
70
- p.setJointMotorControl2(robot, finger_joints[1], p.POSITION_CONTROL, targetPosition=gripper_val)
71
-
72
- for _ in range(10): p.stepSimulation()
73
-
74
- # Refresh joint labels
75
- add_joint_labels()
76
-
77
- # Camera view
78
- width, height = 1280, 1280 # Increased resolution for clarity
79
- view_matrix = p.computeViewMatrixFromYawPitchRoll(camera_angles[0], camera_angles[1], camera_angles[2], [1.5, 0, 1], [0, 0, 0.5], [0, 0, 1])
80
- proj_matrix = p.computeProjectionMatrixFOV(60, width / height, 0.1, 3.1)
81
- _, _, img, _, _ = p.getCameraImage(width, height, view_matrix, proj_matrix)
82
- rgb = np.reshape(img, (height, width, 4))[:, :, :3]
83
-
84
- # Image to file
85
- fig, ax = plt.subplots(figsize=(5, 5))
 
 
 
86
  ax.imshow(rgb.astype(np.uint8))
87
  ax.axis("off")
88
  tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
89
- plt.savefig(tmp.name, bbox_inches='tight', dpi=200) # Increased DPI for sharper image
90
  plt.close()
91
 
92
- # Text output
93
- joint_text = "Joint Angles:\n" + "\n".join([f"J{i+1} = {v:.2f} rad" for i, v in enumerate(joint_values)])
94
- joint_text += f"\nGripper = {gripper_val:.3f} m"
95
- return tmp.name, joint_text
96
 
97
- # Smooth motion to input angles
98
  def move_to_input_angles(joint_str):
99
  try:
100
  target_angles = [float(x.strip()) for x in joint_str.split(",")]
101
  if len(target_angles) != 7:
102
  return None, "❌ Please enter exactly 7 joint angles."
103
 
104
- # Get current joint positions
105
  current = [p.getJointState(robot, idx)[0] for idx in arm_joints]
106
- steps = 100
107
- for i in range(steps):
108
- blend = [(1 - i/steps) * c + (i/steps) * t for c, t in zip(current, target_angles)]
109
  for idx, val in zip(arm_joints, blend):
110
  p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=val)
111
  p.stepSimulation()
112
- time.sleep(0.01)
113
-
114
- current_grip = p.getJointState(robot, finger_joints[0])[0]
115
- return render_sim(target_angles, current_grip, [0, 0, 0])
116
 
 
 
117
  except Exception as e:
118
- return None, f"Error: {str(e)}"
119
-
120
- # Gripper control
121
- def switch_gripper(gripper_type):
122
- print(f"Switching to gripper: {gripper_type}")
123
- return f"Switched to: {gripper_type}"
124
-
125
- # Gradio UI
126
- with gr.Blocks(title="Franka Arm Control with 7 DoF and Gripper Options") as demo:
127
- gr.Markdown("## 🤖 Franka 7-DOF Control\nUse the sliders to manipulate the robot arm.")
128
-
129
- # Gripper selection
130
- gripper_selector = gr.Dropdown(["Two-Finger", "Suction"], value="Two-Finger", label="Select Gripper")
131
- gripper_feedback = gr.Textbox(label="Gripper Status", interactive=False)
132
- gripper_selector.change(fn=switch_gripper, inputs=gripper_selector, outputs=gripper_feedback)
133
-
134
- # Multi-color option for the cube
135
- color_selector = gr.Dropdown(["Black", "Red", "Green", "Blue", "Yellow", "White"], value="Black", label="Select Cube Color")
136
- color_selector.change(fn=change_cube_color, inputs=color_selector, outputs=[])
137
-
138
- # 7 DoF sliders arranged in two rows
139
- joint_sliders = []
140
- with gr.Row():
141
- for i in range(4):
142
- joint_sliders.append(gr.Slider(-3.14, 3.14, value=0, label=f"Joint {i+1}"))
143
- with gr.Row():
144
- for i in range(4, 7):
145
- joint_sliders.append(gr.Slider(-3.14, 3.14, value=0, label=f"Joint {i+1}"))
146
- gripper = gr.Slider(0.0, 0.04, value=0.02, step=0.001, label="Gripper Opening")
147
-
148
- # Camera rotation sliders (for 3D view movement)
149
- with gr.Row():
150
- camera_yaw = gr.Slider(-180, 180, value=0, label="Camera Yaw")
151
- camera_pitch = gr.Slider(-90, 90, value=0, label="Camera Pitch")
152
- camera_roll = gr.Slider(-180, 180, value=0, label="Camera Roll")
153
-
154
- # Outputs
155
- with gr.Row():
156
- img_output = gr.Image(type="filepath", label="Simulation View")
157
- text_output = gr.Textbox(label="Joint States")
158
-
159
- # Live update
160
- def live_update(*vals):
161
- joints = list(vals[:-1])
162
- grip = vals[-1]
163
- camera_angles = [camera_yaw.value, camera_pitch.value, camera_roll.value]
164
- return render_sim(joints, grip, camera_angles)
165
 
166
- for s in joint_sliders + [gripper, camera_yaw, camera_pitch, camera_roll]:
167
- s.change(fn=live_update, inputs=joint_sliders + [gripper, camera_yaw, camera_pitch, camera_roll], outputs=[img_output, text_output])
168
 
169
- # Reset button
170
- def reset():
171
- return render_sim([0]*7, 0.02, [0, 0, 0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
- gr.Button("🔄 Reset Robot").click(fn=reset, inputs=[], outputs=[img_output, text_output])
 
174
 
175
- # Joint angles input box for user to input manually
176
- gr.Markdown("### 🧾 Enter Joint Angles (comma-separated)")
177
- joint_input = gr.Textbox(label="Joint Angles (7 values in radians)", placeholder="e.g. 0.0, -0.5, 0.3, -1.2, 0.0, 1.5, 0.8")
178
- gr.Button("▶️ Move to Angles").click(fn=move_to_input_angles, inputs=joint_input, outputs=[img_output, text_output])
 
 
179
 
180
  demo.launch(debug=True)
 
6
  import gradio as gr
7
  import time
8
 
9
+ # Initialize PyBullet
10
  p.connect(p.DIRECT)
11
  p.setAdditionalSearchPath(pybullet_data.getDataPath())
12
  p.setGravity(0, 0, -9.8)
13
  p.loadURDF("plane.urdf")
14
  robot = p.loadURDF("franka_panda/panda.urdf", basePosition=[0, 0, 0], useFixedBase=True)
15
 
16
+ # Add object (default: black cube)
17
  cube_id = p.loadURDF("cube_small.urdf", basePosition=[0.6, 0, 0.02])
18
+ p.changeVisualShape(cube_id, -1, rgbaColor=[0, 0, 0, 1])
19
 
20
  # Get joint indices
21
  def get_panda_joints(robot):
 
32
 
33
  arm_joints, finger_joints = get_panda_joints(robot)
34
 
 
 
35
  def add_joint_labels():
36
+ for i in range(len(arm_joints)):
37
+ pos = p.getLinkState(robot, arm_joints[i])[0]
38
+ p.addUserDebugText(f"J{i+1}", pos, textColorRGB=[1, 0, 0], textSize=1.2)
39
+
40
+ # Camera config (yaw, pitch, dist)
41
+ camera_angles = [45, -30, 1.5] # Default values
42
+ def render_sim(joint_values, gripper_val, cube_color):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  for idx, tgt in zip(arm_joints, joint_values):
44
  p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=tgt)
45
 
46
+ for _ in range(5):
47
+ for fj in finger_joints:
48
+ p.setJointMotorControl2(robot, fj, p.POSITION_CONTROL, targetPosition=gripper_val)
49
+ p.stepSimulation()
50
+
51
+ # Cube color update
52
+ p.changeVisualShape(cube_id, -1, rgbaColor=cube_color + [1])
53
+
54
+ # View camera
55
+ view_matrix = p.computeViewMatrixFromYawPitchRoll(
56
+ cameraTargetPosition=[0, 0, 0.5],
57
+ distance=camera_angles[2],
58
+ yaw=camera_angles[0],
59
+ pitch=camera_angles[1],
60
+ roll=0,
61
+ upAxisIndex=2,
62
+ )
63
+ proj_matrix = p.computeProjectionMatrixFOV(60, 1, 0.1, 3.1)
64
+ _, _, img, _, _ = p.getCameraImage(640, 640, view_matrix, proj_matrix)
65
+ rgb = np.reshape(img, (640, 640, 4))[:, :, :3]
66
+
67
+ fig, ax = plt.subplots()
68
  ax.imshow(rgb.astype(np.uint8))
69
  ax.axis("off")
70
  tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
71
+ plt.savefig(tmp.name, bbox_inches='tight', dpi=150)
72
  plt.close()
73
 
74
+ return tmp.name, f"Joint Angles: {[round(j,2) for j in joint_values]}, Gripper: {round(gripper_val, 3)}"
 
 
 
75
 
 
76
  def move_to_input_angles(joint_str):
77
  try:
78
  target_angles = [float(x.strip()) for x in joint_str.split(",")]
79
  if len(target_angles) != 7:
80
  return None, "❌ Please enter exactly 7 joint angles."
81
 
 
82
  current = [p.getJointState(robot, idx)[0] for idx in arm_joints]
83
+ for i in range(50):
84
+ blend = [(1 - i/50) * c + (i/50) * t for c, t in zip(current, target_angles)]
 
85
  for idx, val in zip(arm_joints, blend):
86
  p.setJointMotorControl2(robot, idx, p.POSITION_CONTROL, targetPosition=val)
87
  p.stepSimulation()
88
+ time.sleep(0.005)
 
 
 
89
 
90
+ grip = p.getJointState(robot, finger_joints[0])[0]
91
+ return render_sim(target_angles, grip, current_cube_color)
92
  except Exception as e:
93
+ return None, str(e)
94
+
95
+ # Pick and place
96
+ current_cube_color = [0, 0, 0] # Default black
97
+
98
+ def pick_and_place(position_str, approach_str, place_str):
99
+ position = [float(x) for x in position_str.split(",")]
100
+ approach = [float(x) for x in approach_str.split(",")]
101
+ place = [float(x) for x in place_str.split(",")]
102
+
103
+ move_to_input_angles(','.join(map(str, approach)))
104
+
105
+ for _ in range(30):
106
+ for fj in finger_joints:
107
+ p.setJointMotorControl2(robot, fj, p.POSITION_CONTROL, targetPosition=0.0)
108
+ p.stepSimulation()
109
+ time.sleep(0.01)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
+ move_to_input_angles(','.join([str(x + 0.1) for x in approach]))
112
+ move_to_input_angles(','.join(map(str, place)))
113
 
114
+ for _ in range(30):
115
+ for fj in finger_joints:
116
+ p.setJointMotorControl2(robot, fj, p.POSITION_CONTROL, targetPosition=0.04)
117
+ p.stepSimulation()
118
+ time.sleep(0.01)
119
+
120
+ return render_sim(place, 0.04, current_cube_color)
121
+
122
+ # UI
123
+ with gr.Blocks(title="Franka Arm Control with Pick & Place") as demo:
124
+ gr.Markdown("# 🤖 Franka 7-DOF + Pick & Place")
125
+
126
+ # Camera controls
127
+ yaw = gr.Slider(-180, 180, value=camera_angles[0], label="Yaw")
128
+ pitch = gr.Slider(-90, 90, value=camera_angles[1], label="Pitch")
129
+ dist = gr.Slider(0.5, 3.0, value=camera_angles[2], label="Camera Distance")
130
+
131
+ def update_camera(y, p_, d):
132
+ camera_angles[0], camera_angles[1], camera_angles[2] = y, p_, d
133
+ return "Camera updated"
134
+
135
+ gr.Button("🎥 Update Camera").click(update_camera, [yaw, pitch, dist], outputs=gr.Textbox(label="Status"))
136
+
137
+ # Cube color
138
+ cube_color_picker = gr.ColorPicker(label="Pick Cube Color", value="#000000")
139
+
140
+ def update_color(color_hex):
141
+ global current_cube_color
142
+ rgb = tuple(int(color_hex[i:i+2], 16)/255. for i in (1, 3, 5))
143
+ current_cube_color = list(rgb)
144
+ return f"Updated color to {rgb}"
145
+
146
+ cube_color_picker.change(fn=update_color, inputs=cube_color_picker, outputs=gr.Textbox(label="Color Info"))
147
+
148
+ # Manual joints + gripper
149
+ joint_sliders = [gr.Slider(-3.14, 3.14, value=0, label=f"Joint {i+1}") for i in range(7)]
150
+ gripper = gr.Slider(0.0, 0.04, value=0.02, step=0.001, label="Gripper")
151
+
152
+ def live_update(*vals):
153
+ return render_sim(list(vals[:-1]), vals[-1], current_cube_color)
154
 
155
+ for s in joint_sliders + [gripper]:
156
+ s.change(fn=live_update, inputs=joint_sliders + [gripper], outputs=[gr.Image(type="filepath"), gr.Textbox()])
157
 
158
+ # Pick and Place Inputs
159
+ gr.Markdown("## 🧠 Pick & Place Inputs")
160
+ pos_box = gr.Textbox(label="Position Angles")
161
+ approach_box = gr.Textbox(label="Approach Angles")
162
+ place_box = gr.Textbox(label="Place Angles")
163
+ gr.Button("🚚 Run Pick & Place").click(pick_and_place, [pos_box, approach_box, place_box], outputs=[gr.Image(type="filepath"), gr.Textbox()])
164
 
165
  demo.launch(debug=True)