-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem with gripper movement #15
Comments
Hi, |
Hi, Best, |
Hi, frankly thanks for your project. In the end, I figure out some way to control the robot arm and gripper at the same time in multithreading.
I don't no why but it actually works. Thanks again for your contribution. Best regards, |
I just realized that I forgot to release the GIL when the gripper is controlled. This explains why the functions are blocking in threads but not in processes. 0ef80ab fixes this issue. I will push a new version (v0.11.1) with the fix included. Can you test if this solves the issue? |
Hello @TimSchneider42 , Thank you for your quick and helpful reply, as well as your support! It seems that the threading issue still persists in the latest version (v0.11.1). Following is the text code example: import time
import numpy as np
import threading
from franky import Robot, Gripper, CartesianMotion, Affine
# Initialize robot and gripper
robot = Robot("172.16.3.1")
robot.relative_dynamics_factor = 0.05
gripper = Gripper("172.16.3.1")
GRIPPER_SPEED = 0.1
GRIPPER_FORCE = 20
# Initial pose
init_tcp_pos = np.array([0.36131644, -0.02966702, 0.26901625])
init_tcp_quat = np.array([1.0, 0., 0., 0.]) # Initial quaternion
# Reciprocal motion range
pose_range_min = np.array([0.36131644 - 0.1, -0.02966702 - 0.1, 0.26901625 - 0.1])
pose_range_max = np.array([0.36131644, -0.02966702, 0.26901625])
# Gripper reciprocal motion control
def gripper_control():
"""Control gripper open/close"""
while True:
current_time = time.time()
# Gripper reciprocal motion: open and close every 2 seconds
if int(current_time) % 4 < 2: # 2s cycle for reciprocation
gripper_target_width = 0.02
else:
gripper_target_width = 0.08
gripper.move_async(gripper_target_width, GRIPPER_SPEED)
# Print gripper state
gripper_width = gripper.width
print(f"[{time.time()}] Gripper Width: {gripper_width}")
time.sleep(0.1)
# Robot reciprocal motion control
def robot_control():
"""Control robot reciprocal motion"""
while True:
current_time = time.time()
# Control robot motion based on time
t = (current_time % 10) / 5 # 5 seconds for a reciprocal cycle
if t < 1:
target_pos = pose_range_min + t * (pose_range_max - pose_range_min)
else:
target_pos = pose_range_max - (t - 1) * (pose_range_max - pose_range_min)
target_tcp_motion = CartesianMotion(Affine(target_pos, init_tcp_quat))
robot.move(target_tcp_motion, asynchronous=True)
# Print robot state
robot_state = robot.current_cartesian_state.pose.end_effector_pose.__getstate__()
print(f"[{time.time()}] Arm State: Position: {robot_state[0]}, Quaternion: {robot_state[1]}")
time.sleep(0.05)
if __name__ == "__main__":
init_motion = CartesianMotion(Affine(init_tcp_pos, init_tcp_quat))
robot.move(init_motion, asynchronous=False)
# Start gripper control thread
gripper_thread = threading.Thread(target=gripper_control, daemon=True)
gripper_thread.start()
# Start robot motion control thread
robot_thread = threading.Thread(target=robot_control, daemon=True)
robot_thread.start()
# Keep the main thread running
while True:
time.sleep(1) The log shows that the arm control thread and the print current state thread are getting blocked when the gripper is moving. Everything works fine when I comment out the gripper control command |
Just to confirm, with multiprocessing you do not have this issue? |
@Xiaoyao-Li, I just realized something. It is possible that the future object returned by move_async gets destroyed and that is why everything is hanging. As a workaround, could you try to retain all of them? E.g. # Gripper reciprocal motion control
def gripper_control():
"""Control gripper open/close"""
futures = []
while True:
current_time = time.time()
# Gripper reciprocal motion: open and close every 2 seconds
if int(current_time) % 4 < 2: # 2s cycle for reciprocation
gripper_target_width = 0.02
else:
gripper_target_width = 0.08
futures.append(gripper.move_async(gripper_target_width, GRIPPER_SPEED))
# Print gripper state
gripper_width = gripper.width
print(f"[{time.time()}] Gripper Width: {gripper_width}")
time.sleep(0.1) It is not a permanent solution but I would be curious if it solves the problem. I will try to think of a better solution. The problem is that we do not really use the gripper ourselves because we use different grippers, so I never really tested it. Best, |
…trolling the Gripper as it otherwise might block python during garbage collection. Addresses #15.
@Xiaoyao-Li, I implemented a solution for the future issue in version 0.11.2. Could you give it a go and let me know if it works? |
Sorry for the late test and reply. I think your assumption is right. I tested the provided solution under v0.11.1 without destroying the returned future object, and the issue was resolved. I also successfully tested it on v0.11.2, where the thread-blocking issue was reliably fixed, and calling Really appreciate your work! If you need any further testing with Franka Panda gripper, feel free to assign it to me. 🤖🚀 Best, |
Thanks for testing and letting me know @Xiaoyao-Li! Also, I appreciate the offer. Might come back to it later on :) |
Hello, I try to use franky to manipulate franka panda and collect data from it. I wrote this ROS node. I separate gripper control, robot movement control and data collection into 3 threads. I found problem when I use gripper.open_async and gripper.grasp_async as I would block other 2 threads and I could only use other 2 threads after open gripper and grasp gripper is done.
`#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
from franky import *
import franky
import threading
from std_msgs.msg import Int16, Float32
from teng_arduino.msg import TwistGripper
import pyrealsense2 as rs
import numpy as np
import pickle
import copy
import traceback
import os
from scipy.spatial.transform import Rotation
import open3d as o3d
def visualize_point_cloud(points):
"""
Visualize the point cloud using Open3D.
:param points: The Nx3 numpy array of point cloud coordinates.
"""
# Convert points to Open3D point cloud
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
def quaternion_to_euler(q):
class FrankaRobotController:
def init(self):
rospy.init_node('franka_robot_controller')
robot_ip = rospy.get_param('~robot_ip')
self.robot = Robot(robot_ip)
self.robot.recover_from_errors()
self.robot.relative_dynamics_factor = 0.05
self.robot.velocity_rel = 0.4
self.robot.acceleration_rel = 0.2
self.robot.jerk_rel = 0.02
self.gripper = franky.Gripper(robot_ip)
self.gripper_speed = 0.02
self.gripper_force = 5
print('Connecting to robot at {}'.format(robot_ip))
if name == 'main':
controller = FrankaRobotController()
controller.run()`
The text was updated successfully, but these errors were encountered: