Base de conocimiento
Mapeo 3D de un objeto con sensor de fuerza y ServoCart (SDK de Python)
Código para mapear y visualizar un objeto palpándolo con el robot.
TEN EN CUENTA QUE ESTE CÓDIGO ES UN EJEMPLO O PLANTILLA Y NO DEBE CORRERSE TAL CUAL. ÚSALO COMO BASE Y AJÚSTALO PARA GARANTIZAR LA SEGURIDAD Y LA COMPATIBILIDAD CON TU ROBOT.
Lo que necesitas para correrlo:
- Un robot Fairino (este código se escribió con un FR5; los valores articulares y las posiciones cartesianas cambian según el modelo)
- Un sensor de fuerza/torque XJC
- Cualquier herramienta de extremo de brazo con una punta de precisión para palpar
- Paquetes de Python: numpy, matplotlib, time y el SDK de Fairino (disponible en la página de documentación de Fairino)
El programa principal (Grid_test.py) hace lo siguiente:
- A partir de una posición articular inicial, un tamaño y un número de ciclos (palpados por fila y por columna), se mueve a un punto suspendido sobre el objeto (los desplazamientos se calculan sobre el sistema de coordenadas de la base).
- Desde ese punto usa movimientos servoCart() para acercarse lentamente hasta encontrar una fuerza de resistencia: un contacto controlado con el objeto.
- Registra el punto de detección y manda ese dato a un archivo .txt.
El graficador (joint_torque_grapher.py) hace esto:
- Lee y procesa los valores de los archivos .txt.
- Muestra el resultado como un mapa de calor 3D con la forma aproximada del objeto palpado; la precisión depende del número de ciclos y del tamaño del mapa, como se ve abajo.

Código del programa principal de palpado (escrito para la versión 3.8.2):
from fairino import Robot
import time
START_POS = [29.74836540222168, -134.0897674560547, -89.1602554321289, -46.7747802734375, 89.99434661865234, 29.713558197021484]
START_CART = [459.6044006347656, 145.47499084472656, -23.17245864868164, 179.98126220703125, -0.017205478623509407, -89.9651870727539]
length = 200 # Length/width of a square grid in mm
def get_z_force(robot: Robot.RPC):
e, ft = robot.FT_GetForceTorqueRCS()
if e != 0:
print("Error getting force/torque:", e)
return False
return ft[2] # Z-axis force
def make_grid(robot: Robot.RPC, loops=20):
file_object = open(f"{loops}x{loops}_data.txt", "w") # open graph data file
robot.SetSpeed(40) # Set speed to 40%
# Loop over specified grid size and probe for depth
for i in range(loops):
for j in range(loops):
robot.MoveL(START_CART, tool=1, user=0, vel=100, offset_flag=1, offset_pos=[(i -(length / loops)), (j -(length / loops)), 0, 0, 0, 0]) # Go to probe prep
time.sleep(0.5)
# Use servo cart to slowly lower the tool until force is detected
for _ in range(400):
robot.ServoCart(1, [0, 0,-0.15, 0, 0, 0], vel=100)
time.sleep(0.008)
fz = get_z_force(robot)
if( fz is not False):
if(abs(fz) > 0.5):
coord = robot.GetActualTCPPose()[1][:3] # Get current TCP position of contact point
file_object.write(f"{[i for i in coord]} \n".replace('[', '').replace(']', '')) # Write to file
print(f"Force detected: {fz} at position {coord}")
break
else:
return False
robot.MoveL(robot.GetActualTCPPose()[1], tool=1, user=0, vel=100, offset_flag=1, offset_pos=[0, 0, 50, 0, 0, 0]) # Retract 50mm
def main():
robot = Robot.RPC('192.168.58.2')
robot.SetSpeed(20) # Set speed to 20%
robot.FT_SetZero(1) # Set force/torque sensor zero
robot.MoveJ(START_POS, tool=0, user=0, vel=50) # Move to start position
make_grid(robot, loops=10)
if name == "__main__":
main()Código del graficador (joint_torque_grapher.py):
import matplotlib.pyplot as plt
import numpy as np
data = np.loadtxt('10x10_data.txt', delimiter=',')
x = data[:, 0]
y = data[:, 1]
z = data[:, 2]
print(max(z) - min(z))
fig = plt.figure(figsize=(10, 8))
ax = plt.axes(122, projection='3d')
plt.xlim(min(x) - 100, max(x) + 100)
plt.ylim(min(y) - 100, max(y) + 100)
ax.set_xlabel('X Position')
ax.set_ylabel('Y Position')
ax.set_zlabel('Z Position')
ax_dims = max([max(x) - min(x), max(y) - min(y), max(z) - min(z)])
ax.set(zlim=(min(z), min(z) + ax_dims))
ax.set(xlim=(min(x), min(x) + ax_dims))
ax.set(ylim=(min(y), min(y) + ax_dims))
plt.title('3D Probe Data')
ax.plot_trisurf(x, y, z, linewidth=0.2, antialiased=False, cmap='coolwarm')
############################################
data = np.loadtxt('20x20_data.txt', delimiter=',')
x = data[:, 0]
y = data[:, 1]
z = data[:, 2]
ax2 = plt.axes(121, projection='3d')
plt.xlim(min(x) - 100, max(x) + 100)
plt.ylim(min(y) - 100, max(y) + 100)
ax2.set_xlabel('X Position')
ax2.set_ylabel('Y Position')
ax2.set_zlabel('Z Position')
ax_dims = max([max(x) - min(x), max(y) - min(y), max(z) - min(z)])
ax2.set(zlim=(min(z), min(z) + ax_dims))
ax2.set(xlim=(min(x), min(x) + ax_dims))
ax2.set(ylim=(min(y), min(y) + ax_dims))
plt.title('3D Probe Data')
ax2.plot_trisurf(x, y, z, linewidth=0.2, antialiased=False, cmap='coolwarm')
plt.show()Traducido de la documentación de Fairino. Ante cualquier duda de seguridad, valida contra el manual del equipo y con tu asesor antes de mover el robot.
¿Sigues atorado?
Escríbenos con el número de serie y lo que ya intentaste. Contesta alguien que ha instalado estos equipos.
Pedir soporte →