import numpy as np import plotly.graph_objects as go import gradio as gr from scipy.spatial.distance import euclidean from scipy.optimize import minimize # Define the robot's arm lengths (6-DOF) L = np.array([1, 1, 1, 1, 1, 1]) # Lengths of each arm segment # Forward kinematics: Compute the end-effector position given joint angles def forward_kinematics(theta): theta = np.array(theta) x = L[0] * np.cos(theta[0]) + L[1] * np.cos(theta[0] + theta[1]) + L[2] * np.cos(theta[0] + theta[1] + theta[2]) + \ L[3] * np.cos(theta[0] + theta[1] + theta[2] + theta[3]) + L[4] * np.cos(theta[0] + theta[1] + theta[2] + theta[3] + theta[4]) + \ L[5] * np.cos(theta[0] + theta[1] + theta[2] + theta[3] + theta[4] + theta[5]) y = L[0] * np.sin(theta[0]) + L[1] * np.sin(theta[0] + theta[1]) + L[2] * np.sin(theta[0] + theta[1] + theta[2]) + \ L[3] * np.sin(theta[0] + theta[1] + theta[2] + theta[3]) + L[4] * np.sin(theta[0] + theta[1] + theta[2] + theta[3] + theta[4]) + \ L[5] * np.sin(theta[0] + theta[1] + theta[2] + theta[3] + theta[4] + theta[5]) z = L[0] * np.sin(theta[0]) + L[1] * np.sin(theta[0] + theta[1]) + L[2] * np.sin(theta[0] + theta[1] + theta[2]) + \ L[3] * np.sin(theta[0] + theta[1] + theta[2] + theta[3]) + L[4] * np.sin(theta[0] + theta[1] + theta[2] + theta[3] + theta[4]) + \ L[5] * np.sin(theta[0] + theta[1] + theta[2] + theta[3] + theta[4] + theta[5]) return np.array([x, y, z]) # Objective function: Minimize the distance between the end-effector and the target def objective_function(theta, target): end_effector = forward_kinematics(theta) return euclidean(end_effector, target) # Find the shortest path (joint angles) to reach the target def find_shortest_path(initial_angles, target): result = minimize(objective_function, initial_angles, args=(target,), method='BFGS') return result.x # Gradio interface def robot_pathfinder(target_x, target_y, target_z): target = np.array([target_x, target_y, target_z]) initial_angles = np.array([0, 0, 0, 0, 0, 0]) # Initial joint angles optimal_angles = find_shortest_path(initial_angles, target) # Compute joint positions for visualization joint_positions = [] joint_positions.append([0, 0, 0]) # Base position for i in range(len(L)): x = joint_positions[-1][0] + L[i] * np.cos(np.sum(optimal_angles[:i+1])) y = joint_positions[-1][1] + L[i] * np.sin(np.sum(optimal_angles[:i+1])) z = joint_positions[-1][2] + L[i] * np.sin(np.sum(optimal_angles[:i+1])) joint_positions.append([x, y, z]) # Create 3D plot using Plotly fig = go.Figure() # Add robot arm segments for i in range(len(joint_positions) - 1): fig.add_trace(go.Scatter3d( x=[joint_positions[i][0], joint_positions[i+1][0]], y=[joint_positions[i][1], joint_positions[i+1][1]], z=[joint_positions[i][2], joint_positions[i+1][2]], mode='lines+markers', line=dict(color='blue', width=5), marker=dict(size=5) )) # Add target point fig.add_trace(go.Scatter3d( x=[target[0]], y=[target[1]], z=[target[2]], mode='markers', marker=dict(color='red', size=10) )) # Set layout fig.update_layout( scene=dict( xaxis=dict(range=[-5, 5]), yaxis=dict(range=[-5, 5]), zaxis=dict(range=[-5, 5]), aspectmode='cube' ), title="6-DOF Robot Arm Pathfinding in 3D" ) return fig # Gradio app iface = gr.Interface( fn=robot_pathfinder, inputs=[ gr.Number(label="Target X-coordinate"), gr.Number(label="Target Y-coordinate"), gr.Number(label="Target Z-coordinate") ], outputs=gr.Plot(), # Use Plotly for 3D visualization live=True, title="6-DOF Robot Shortest Path Finder in 3D", description="Enter target coordinates (x, y, z) to find the shortest path for a 6-DOF robot arm in 3D space." ) # Launch the app if __name__ == "__main__": iface.launch(server_name="0.0.0.0", server_port=7860)