sam133 commited on
Commit
833d580
Β·
1 Parent(s): e35c229

Remove: Delete mcp and cursor_pybullet_mcp implementation

Browse files
mcp/cursor_pybullet/README.md DELETED
@@ -1,103 +0,0 @@
1
- # Cursor-PyBullet MCP
2
-
3
- A Model-Controller-Provider (MCP) for connecting Cursor with PyBullet physics simulation.
4
-
5
- ## Features
6
-
7
- - Connect to PyBullet physics server
8
- - Create and control robots
9
- - Run physics simulations
10
- - Capture visualization frames
11
- - Monitor robot state
12
- - Apply control signals
13
-
14
- ## Installation
15
-
16
- ```bash
17
- pip install -e .
18
- ```
19
-
20
- ## Usage
21
-
22
- ```python
23
- from cursor_pybullet_mcp import CursorPyBulletMCP
24
-
25
- # Create MCP instance
26
- mcp = CursorPyBulletMCP()
27
-
28
- # Connect to PyBullet
29
- if mcp.connect():
30
- try:
31
- # Create ground
32
- mcp.create_ground()
33
-
34
- # Create robot
35
- robot_specs = {
36
- "body": {
37
- "dimensions": [1.0, 0.5, 0.3],
38
- "mass": 10.0
39
- },
40
- "wheels": [
41
- {
42
- "position": [0.5, 0.3, 0.15],
43
- "radius": 0.1,
44
- "width": 0.05
45
- },
46
- {
47
- "position": [0.5, -0.3, 0.15],
48
- "radius": 0.1,
49
- "width": 0.05
50
- },
51
- {
52
- "position": [-0.5, 0.3, 0.15],
53
- "radius": 0.1,
54
- "width": 0.05
55
- },
56
- {
57
- "position": [-0.5, -0.3, 0.15],
58
- "radius": 0.1,
59
- "width": 0.05
60
- }
61
- ]
62
- }
63
- mcp.create_robot(robot_specs)
64
-
65
- # Setup camera
66
- mcp.setup_camera()
67
-
68
- # Run simulation
69
- frames = mcp.run_simulation(duration_sec=5)
70
- print(f"Captured {len(frames)} frames")
71
-
72
- finally:
73
- # Always disconnect
74
- mcp.disconnect()
75
- ```
76
-
77
- ## Configuration
78
-
79
- The MCP can be configured using a JSON file:
80
-
81
- ```json
82
- {
83
- "physics": {
84
- "gravity": [0, 0, -9.81],
85
- "timestep": 1.0/240.0,
86
- "max_steps": 1000
87
- },
88
- "camera": {
89
- "width": 640,
90
- "height": 480,
91
- "fov": 60,
92
- "near": 0.1,
93
- "far": 100.0,
94
- "position": [2, 2, 2],
95
- "target": [0, 0, 0],
96
- "up": [0, 0, 1]
97
- }
98
- }
99
- ```
100
-
101
- ## License
102
-
103
- MIT License
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mcp/cursor_pybullet/__init__.py DELETED
@@ -1,4 +0,0 @@
1
- from .mcp import CursorPyBulletMCP
2
-
3
- __version__ = "1.0.0"
4
- __all__ = ["CursorPyBulletMCP"]
 
 
 
 
 
mcp/cursor_pybullet/config.json DELETED
@@ -1,176 +0,0 @@
1
- {
2
- "name": "Cursor-PyBullet MCP",
3
- "version": "1.0.0",
4
- "description": "Model-Controller-Provider for connecting Cursor with PyBullet physics simulation",
5
- "type": "python",
6
- "entry_point": "cursor_pybullet_mcp.py",
7
- "dependencies": {
8
- "pybullet": "3.2.5",
9
- "numpy": "1.24.3",
10
- "Pillow": "10.0.0"
11
- },
12
- "config": {
13
- "physics": {
14
- "gravity": [0, 0, -9.81],
15
- "timestep": 1.0/240.0,
16
- "max_steps": 1000
17
- },
18
- "camera": {
19
- "width": 640,
20
- "height": 480,
21
- "fov": 60,
22
- "near": 0.1,
23
- "far": 100.0,
24
- "position": [2, 2, 2],
25
- "target": [0, 0, 0],
26
- "up": [0, 0, 1]
27
- },
28
- "robot": {
29
- "default_body": {
30
- "dimensions": [1.0, 0.5, 0.3],
31
- "mass": 10.0,
32
- "color": [0.8, 0.2, 0.2, 1.0]
33
- },
34
- "default_wheel": {
35
- "radius": 0.1,
36
- "width": 0.05,
37
- "mass": 1.0,
38
- "color": [0.2, 0.2, 0.2, 1.0]
39
- }
40
- },
41
- "simulation": {
42
- "capture_interval": 100,
43
- "default_duration": 7
44
- }
45
- },
46
- "commands": {
47
- "connect": {
48
- "description": "Connect to PyBullet physics server",
49
- "returns": "boolean"
50
- },
51
- "disconnect": {
52
- "description": "Disconnect from PyBullet physics server",
53
- "returns": "void"
54
- },
55
- "create_ground": {
56
- "description": "Create a ground plane",
57
- "returns": "boolean"
58
- },
59
- "create_robot": {
60
- "description": "Create a robot from specifications",
61
- "parameters": {
62
- "body": {
63
- "dimensions": "array[3]",
64
- "mass": "float"
65
- },
66
- "wheels": "array of wheel specifications"
67
- },
68
- "returns": "boolean"
69
- },
70
- "run_simulation": {
71
- "description": "Run the simulation and capture frames",
72
- "parameters": {
73
- "duration_sec": "float",
74
- "capture_interval": "integer"
75
- },
76
- "returns": "array of base64 encoded frames"
77
- },
78
- "get_robot_state": {
79
- "description": "Get current state of the robot",
80
- "returns": {
81
- "position": "array[3]",
82
- "orientation": "array[4]",
83
- "linear_velocity": "array[3]",
84
- "angular_velocity": "array[3]"
85
- }
86
- },
87
- "apply_control": {
88
- "description": "Apply control signals to the robot",
89
- "parameters": {
90
- "wheel_velocities": "array of float"
91
- },
92
- "returns": "boolean"
93
- }
94
- },
95
- "events": {
96
- "simulation_started": {
97
- "description": "Emitted when simulation starts",
98
- "data": {
99
- "timestamp": "string",
100
- "config": "object"
101
- }
102
- },
103
- "simulation_step": {
104
- "description": "Emitted on each simulation step",
105
- "data": {
106
- "step": "integer",
107
- "total_steps": "integer",
108
- "robot_state": "object"
109
- }
110
- },
111
- "frame_captured": {
112
- "description": "Emitted when a frame is captured",
113
- "data": {
114
- "step": "integer",
115
- "frame": "string (base64)"
116
- }
117
- },
118
- "simulation_ended": {
119
- "description": "Emitted when simulation ends",
120
- "data": {
121
- "timestamp": "string",
122
- "total_frames": "integer",
123
- "final_state": "object"
124
- }
125
- },
126
- "error": {
127
- "description": "Emitted when an error occurs",
128
- "data": {
129
- "error": "string",
130
- "timestamp": "string",
131
- "context": "object"
132
- }
133
- }
134
- },
135
- "examples": {
136
- "basic_usage": {
137
- "description": "Basic example of using the MCP",
138
- "code": {
139
- "connect": true,
140
- "create_ground": true,
141
- "create_robot": {
142
- "body": {
143
- "dimensions": [1.0, 0.5, 0.3],
144
- "mass": 10.0
145
- },
146
- "wheels": [
147
- {
148
- "position": [0.5, 0.3, 0.15],
149
- "radius": 0.1,
150
- "width": 0.05
151
- },
152
- {
153
- "position": [0.5, -0.3, 0.15],
154
- "radius": 0.1,
155
- "width": 0.05
156
- },
157
- {
158
- "position": [-0.5, 0.3, 0.15],
159
- "radius": 0.1,
160
- "width": 0.05
161
- },
162
- {
163
- "position": [-0.5, -0.3, 0.15],
164
- "radius": 0.1,
165
- "width": 0.05
166
- }
167
- ]
168
- },
169
- "run_simulation": {
170
- "duration_sec": 5,
171
- "capture_interval": 100
172
- }
173
- }
174
- }
175
- }
176
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mcp/cursor_pybullet/mcp.py DELETED
@@ -1,248 +0,0 @@
1
- import pybullet as p
2
- import pybullet_data
3
- import numpy as np
4
- import json
5
- import base64
6
- import io
7
- from PIL import Image
8
- import time
9
- import os
10
- from typing import Dict, List, Optional, Union, Any
11
-
12
- class CursorPyBulletMCP:
13
- """Cursor-PyBullet MCP implementation"""
14
-
15
- def __init__(self, config_path: Optional[str] = None):
16
- """Initialize the MCP with optional config file"""
17
- self.physics_client = None
18
- self.robot_id = None
19
- self.wheel_ids = []
20
- self.joint_ids = []
21
- self.config = self._load_config(config_path)
22
- self.camera_setup = self.config.get("camera", {
23
- 'width': 640,
24
- 'height': 480,
25
- 'fov': 60,
26
- 'near': 0.1,
27
- 'far': 100.0
28
- })
29
-
30
- def _load_config(self, config_path: Optional[str]) -> Dict:
31
- """Load configuration from file or use defaults"""
32
- if config_path and os.path.exists(config_path):
33
- with open(config_path, 'r') as f:
34
- return json.load(f)
35
- return {
36
- "physics": {
37
- "gravity": [0, 0, -9.81],
38
- "timestep": 1.0/240.0,
39
- "max_steps": 1000
40
- },
41
- "camera": {
42
- "width": 640,
43
- "height": 480,
44
- "fov": 60,
45
- "near": 0.1,
46
- "far": 100.0,
47
- "position": [2, 2, 2],
48
- "target": [0, 0, 0],
49
- "up": [0, 0, 1]
50
- }
51
- }
52
-
53
- def connect(self) -> bool:
54
- """Connect to PyBullet physics server"""
55
- try:
56
- self.physics_client = p.connect(p.DIRECT)
57
- p.setAdditionalSearchPath(pybullet_data.getDataPath())
58
- p.setGravity(*self.config["physics"]["gravity"])
59
- p.setRealTimeSimulation(0)
60
- print("βœ… Connected to PyBullet physics server")
61
- return True
62
- except Exception as e:
63
- print(f"❌ Failed to connect to PyBullet: {str(e)}")
64
- return False
65
-
66
- def disconnect(self) -> None:
67
- """Disconnect from PyBullet physics server"""
68
- if self.physics_client is not None:
69
- p.disconnect(self.physics_client)
70
- print("βœ… Disconnected from PyBullet physics server")
71
-
72
- def create_ground(self) -> bool:
73
- """Create a ground plane"""
74
- try:
75
- ground_id = p.createCollisionShape(p.GEOM_PLANE)
76
- p.createMultiBody(0, ground_id)
77
- print("βœ… Created ground plane")
78
- return True
79
- except Exception as e:
80
- print(f"❌ Failed to create ground: {str(e)}")
81
- return False
82
-
83
- def create_robot(self, robot_specs: Dict) -> bool:
84
- """Create a robot from specifications"""
85
- try:
86
- # Create body
87
- body_specs = robot_specs["body"]
88
- body_collision = p.createCollisionShape(
89
- p.GEOM_BOX,
90
- halfExtents=[d/2 for d in body_specs["dimensions"]]
91
- )
92
- body_visual = p.createVisualShape(
93
- p.GEOM_BOX,
94
- halfExtents=[d/2 for d in body_specs["dimensions"]],
95
- rgbaColor=body_specs.get("color", [0.8, 0.2, 0.2, 1])
96
- )
97
- self.robot_id = p.createMultiBody(
98
- baseMass=body_specs["mass"],
99
- baseCollisionShapeIndex=body_collision,
100
- baseVisualShapeIndex=body_visual,
101
- basePosition=[0, 0, body_specs["dimensions"][2]/2]
102
- )
103
-
104
- # Create wheels
105
- self.wheel_ids = []
106
- self.joint_ids = []
107
- for i, wheel_spec in enumerate(robot_specs["wheels"]):
108
- pos_x, pos_y, pos_z = wheel_spec["position"]
109
-
110
- # Create wheel
111
- wheel_collision = p.createCollisionShape(
112
- p.GEOM_CYLINDER,
113
- radius=float(wheel_spec["radius"]),
114
- height=float(wheel_spec["width"])
115
- )
116
- wheel_visual = p.createVisualShape(
117
- p.GEOM_CYLINDER,
118
- radius=float(wheel_spec["radius"]),
119
- length=float(wheel_spec["width"]),
120
- rgbaColor=wheel_spec.get("color", [0.2, 0.2, 0.2, 1])
121
- )
122
- wheel_id = p.createMultiBody(
123
- baseMass=wheel_spec.get("mass", 1.0),
124
- baseCollisionShapeIndex=wheel_collision,
125
- baseVisualShapeIndex=wheel_visual,
126
- basePosition=[float(pos_x), float(pos_y), float(pos_z)]
127
- )
128
- self.wheel_ids.append(wheel_id)
129
-
130
- # Create joint
131
- joint_id = p.createConstraint(
132
- self.robot_id,
133
- wheel_id,
134
- p.JOINT_POINT2POINT,
135
- [0, 0, 0],
136
- [float(pos_x), float(pos_y), float(pos_z)],
137
- [0, 0, 0]
138
- )
139
- self.joint_ids.append(joint_id)
140
-
141
- print(f"βœ… Created robot with {len(self.wheel_ids)} wheels")
142
- return True
143
- except Exception as e:
144
- print(f"❌ Failed to create robot: {str(e)}")
145
- return False
146
-
147
- def setup_camera(self) -> bool:
148
- """Setup camera for visualization"""
149
- try:
150
- camera_config = self.config["camera"]
151
- self.view_matrix = p.computeViewMatrix(
152
- cameraEyePosition=camera_config["position"],
153
- cameraTargetPosition=camera_config["target"],
154
- cameraUpVector=camera_config["up"]
155
- )
156
- self.proj_matrix = p.computeProjectionMatrixFOV(
157
- fov=camera_config["fov"],
158
- aspect=float(camera_config["width"]) / camera_config["height"],
159
- nearVal=camera_config["near"],
160
- farVal=camera_config["far"]
161
- )
162
- print("βœ… Camera setup completed")
163
- return True
164
- except Exception as e:
165
- print(f"❌ Failed to setup camera: {str(e)}")
166
- return False
167
-
168
- def capture_frame(self) -> Optional[str]:
169
- """Capture a frame from the simulation"""
170
- try:
171
- camera_config = self.config["camera"]
172
- _, _, rgb, _, _ = p.getCameraImage(
173
- width=camera_config["width"],
174
- height=camera_config["height"],
175
- viewMatrix=self.view_matrix,
176
- projectionMatrix=self.proj_matrix,
177
- renderer=p.ER_BULLET_HARDWARE_OPENGL
178
- )
179
-
180
- # Convert to base64
181
- img = Image.fromarray(rgb)
182
- buffered = io.BytesIO()
183
- img.save(buffered, format="PNG")
184
- return base64.b64encode(buffered.getvalue()).decode()
185
- except Exception as e:
186
- print(f"❌ Failed to capture frame: {str(e)}")
187
- return None
188
-
189
- def run_simulation(self, duration_sec: float = 7, capture_interval: int = 100) -> List[str]:
190
- """Run the simulation and capture frames"""
191
- try:
192
- frames = []
193
- num_steps = int(duration_sec * 240) # 240 Hz simulation
194
-
195
- for step in range(num_steps):
196
- p.stepSimulation()
197
-
198
- if step % capture_interval == 0:
199
- frame = self.capture_frame()
200
- if frame:
201
- frames.append(frame)
202
- print(f"Captured frame at step {step}/{num_steps}")
203
-
204
- if step % 100 == 0:
205
- print(f"Simulation step {step}/{num_steps}")
206
-
207
- return frames
208
- except Exception as e:
209
- print(f"❌ Simulation failed: {str(e)}")
210
- return []
211
-
212
- def get_robot_state(self) -> Optional[Dict[str, Any]]:
213
- """Get current state of the robot"""
214
- try:
215
- if self.robot_id is None:
216
- return None
217
-
218
- pos, quat = p.getBasePositionAndOrientation(self.robot_id)
219
- vel, ang_vel = p.getBaseVelocity(self.robot_id)
220
-
221
- return {
222
- "position": pos,
223
- "orientation": quat,
224
- "linear_velocity": vel,
225
- "angular_velocity": ang_vel
226
- }
227
- except Exception as e:
228
- print(f"❌ Failed to get robot state: {str(e)}")
229
- return None
230
-
231
- def apply_control(self, wheel_velocities: List[float]) -> bool:
232
- """Apply control signals to the robot"""
233
- try:
234
- if len(wheel_velocities) != len(self.wheel_ids):
235
- raise ValueError("Number of wheel velocities must match number of wheels")
236
-
237
- for wheel_id, velocity in zip(self.wheel_ids, wheel_velocities):
238
- p.setJointMotorControl2(
239
- wheel_id,
240
- 0, # joint index
241
- p.VELOCITY_CONTROL,
242
- targetVelocity=velocity,
243
- force=100
244
- )
245
- return True
246
- except Exception as e:
247
- print(f"❌ Failed to apply control: {str(e)}")
248
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mcp/cursor_pybullet/record_simulation.py DELETED
@@ -1,105 +0,0 @@
1
- import cv2
2
- import numpy as np
3
- import base64
4
- from io import BytesIO
5
- from PIL import Image
6
- import time
7
- from mcp import CursorPyBulletMCP
8
-
9
- def base64_to_frame(base64_string):
10
- """Convert base64 string to numpy array for OpenCV"""
11
- img_data = base64.b64decode(base64_string)
12
- img = Image.open(BytesIO(img_data))
13
- return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
14
-
15
- def main():
16
- # Create MCP instance
17
- mcp = CursorPyBulletMCP()
18
-
19
- # Connect to PyBullet
20
- if not mcp.connect():
21
- print("Failed to connect to PyBullet")
22
- return
23
-
24
- try:
25
- # Create ground
26
- if not mcp.create_ground():
27
- print("Failed to create ground")
28
- return
29
-
30
- # Create robot
31
- robot_specs = {
32
- "body": {
33
- "dimensions": [1.0, 0.5, 0.3],
34
- "mass": 10.0,
35
- "color": [0.8, 0.2, 0.2, 1.0] # Red color
36
- },
37
- "wheels": [
38
- {
39
- "position": [0.5, 0.3, 0.15],
40
- "radius": 0.1,
41
- "width": 0.05,
42
- "color": [0.2, 0.2, 0.2, 1.0], # Dark gray
43
- "mass": 1.0
44
- },
45
- {
46
- "position": [0.5, -0.3, 0.15],
47
- "radius": 0.1,
48
- "width": 0.05,
49
- "color": [0.2, 0.2, 0.2, 1.0],
50
- "mass": 1.0
51
- },
52
- {
53
- "position": [-0.5, 0.3, 0.15],
54
- "radius": 0.1,
55
- "width": 0.05,
56
- "color": [0.2, 0.2, 0.2, 1.0],
57
- "mass": 1.0
58
- },
59
- {
60
- "position": [-0.5, -0.3, 0.15],
61
- "radius": 0.1,
62
- "width": 0.05,
63
- "color": [0.2, 0.2, 0.2, 1.0],
64
- "mass": 1.0
65
- }
66
- ]
67
- }
68
-
69
- if not mcp.create_robot(robot_specs):
70
- print("Failed to create robot")
71
- return
72
-
73
- # Setup camera
74
- if not mcp.setup_camera():
75
- print("Failed to setup camera")
76
- return
77
-
78
- # Get camera settings
79
- width = mcp.config["camera"]["width"]
80
- height = mcp.config["camera"]["height"]
81
-
82
- # Setup video writer
83
- fourcc = cv2.VideoWriter_fourcc(*'mp4v')
84
- out = cv2.VideoWriter('simulation.mp4', fourcc, 30.0, (width, height))
85
-
86
- # Run simulation with more frequent frame capture
87
- print("Starting simulation recording...")
88
- frames = mcp.run_simulation(duration_sec=10, capture_interval=10) # Capture every 10 steps
89
-
90
- # Convert frames to video
91
- for i, frame_base64 in enumerate(frames):
92
- frame = base64_to_frame(frame_base64)
93
- out.write(frame)
94
- print(f"Processed frame {i+1}/{len(frames)}")
95
-
96
- # Release video writer
97
- out.release()
98
- print("βœ… Video saved as 'simulation.mp4'")
99
-
100
- finally:
101
- # Always disconnect
102
- mcp.disconnect()
103
-
104
- if __name__ == "__main__":
105
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mcp/cursor_pybullet/setup.py DELETED
@@ -1,25 +0,0 @@
1
- from setuptools import setup, find_packages
2
-
3
- setup(
4
- name="cursor_pybullet_mcp",
5
- version="1.0.0",
6
- packages=find_packages(),
7
- install_requires=[
8
- "pybullet>=3.2.5",
9
- "numpy>=1.24.3",
10
- "Pillow>=10.0.0",
11
- "opencv-python>=4.8.0"
12
- ],
13
- author="Your Name",
14
- author_email="your.email@example.com",
15
- description="Cursor-PyBullet MCP for robot simulation",
16
- long_description=open("README.md").read(),
17
- long_description_content_type="text/markdown",
18
- url="https://github.com/yourusername/cursor_pybullet_mcp",
19
- classifiers=[
20
- "Programming Language :: Python :: 3",
21
- "License :: OSI Approved :: MIT License",
22
- "Operating System :: OS Independent",
23
- ],
24
- python_requires=">=3.7",
25
- )