Compare commits

...

4 Commits

Author SHA1 Message Date
qlin1806
35131ed59e attempt to merge newer changes 2024-08-21 16:35:22 -07:00
fe5bb31873 bug fix hand initialization 2024-08-20 19:26:34 +09:00
e2f7830e01 bug fix hand initialization 2024-08-20 19:16:23 +09:00
75e00b3111 general bug fix 2024-08-19 15:30:30 +09:00
5 changed files with 87 additions and 80 deletions

View File

@@ -244,22 +244,22 @@ install(TARGETS
##### PYBIND11 LIBRARY ROBOT_DYNAMICS ##### ##### PYBIND11 LIBRARY ROBOT_DYNAMICS #####
ament_python_install_package(${PROJECT_NAME}) ament_python_install_package(${PROJECT_NAME})
pybind11_add_module(_qros_franka_robot_dynamic SHARED pybind11_add_module(_qros_franka_robot_dynamics_py SHARED
src/robot_dynamics/qros_robot_dynamics_py.cpp src/robot_dynamics/qros_robot_dynamics_py.cpp
src/robot_dynamics/qros_robot_dynamics_client.cpp src/robot_dynamics/qros_robot_dynamics_client.cpp
src/robot_dynamics/qros_robot_dynamics_server.cpp src/robot_dynamics/qros_robot_dynamics_server.cpp
) )
target_include_directories(_qros_franka_robot_dynamic target_include_directories(_qros_franka_robot_dynamics_py
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/robot_dynamics> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/robot_dynamics>
$<INSTALL_INTERFACE:include/robot_dynamics>) $<INSTALL_INTERFACE:include/robot_dynamics>)
target_compile_definitions(_qros_franka_robot_dynamic PRIVATE IS_SAS_PYTHON_BUILD) target_compile_definitions(_qros_franka_robot_dynamics_py PRIVATE IS_SAS_PYTHON_BUILD)
# https://github.com/pybind/pybind11/issues/387 # https://github.com/pybind/pybind11/issues/387
target_link_libraries(_qros_franka_robot_dynamic PRIVATE ${PROJECT_NAME}_robot_dynamics -ldqrobotics) target_link_libraries(_qros_franka_robot_dynamics_py PRIVATE ${PROJECT_NAME}_robot_dynamics -ldqrobotics)
install(TARGETS _qros_franka_robot_dynamic install(TARGETS _qros_franka_robot_dynamics_py
DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}" DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}"
) )
##END## PYBIND11 LIBRARY ROBOT_DYNAMICS ##### ##END## PYBIND11 LIBRARY ROBOT_DYNAMICS #####

View File

@@ -1,11 +1,14 @@
""" """
""" """
from sas_robot_driver_franka._qros_franka_robot_dynamic import RobotDynamicsClient, RobotDynamicsServer from typing import Union
from sas_robot_driver_franka._qros_franka_robot_dynamics_py import RobotDynamicsClient, RobotDynamicsServer
import rclpy import rclpy
from rclpy.node import Node from rclpy.node import Node
# from sas_common import rclcpp_init, rclcpp_Node, rclcpp_spin_some, rclcpp_shutdown from rclpy.client import Client
from sas_robot_driver_franka_interfaces.srv import Move, Move_Request, Move_Response, Grasp, Grasp_Request, Grasp_Response from sas_common import rclcpp_init, rclcpp_Node, rclcpp_spin_some, rclcpp_shutdown
from sas_robot_driver_franka_interfaces.srv import Move, Grasp
from sas_robot_driver_franka_interfaces.msg import GripperState from sas_robot_driver_franka_interfaces.msg import GripperState
import os import os
import threading import threading
@@ -31,9 +34,9 @@ class FrankaGripperInterface:
self.grasp_service = node.create_client(Grasp, os.path.join(robot_prefix, GRASP_TOPIC_SUFFIX)) self.grasp_service = node.create_client(Grasp, os.path.join(robot_prefix, GRASP_TOPIC_SUFFIX))
self._grasping = False self._grasping = False
self.status_subscriber = node.create_subscription(GripperState, os.path.join(robot_prefix, STATUS_TOPIC_SUFFIX), self.status_subscriber = node.create_subscription(GripperState, os.path.join(robot_prefix, STATUS_TOPIC_SUFFIX),
self._status_callback, 5) self._status_callback, 10)
self.result_queue = Queue() self.service_future: Union[rclpy.Future, None] = None
# gripper state # gripper state
self.state_width = None self.state_width = None
@@ -45,14 +48,11 @@ class FrankaGripperInterface:
def _default_spin_handler(self): def _default_spin_handler(self):
rclpy.spin_once(self.node) rclpy.spin_once(self.node)
def set_spin_handler(self, spin_handler): def _is_service_ready(self, service: Client):
self.spin_handler = spin_handler
def _is_service_ready(self, service):
try: try:
self.node.get_logger().info("Waiting for service: " + service.service_name) # self.node.get_logger().info("Waiting for service: " + service.service_name)
service.wait_for_service(timeout_sec=0.1) ret = service.wait_for_service(timeout_sec=0.1)
return True return ret
except Exception as e: except Exception as e:
self.node.get_logger().info("Service error: " + service.service_name + ": " + str(e)) self.node.get_logger().info("Service error: " + service.service_name + ": " + str(e))
return False return False
@@ -81,7 +81,7 @@ class FrankaGripperInterface:
""" """
if self.is_busy(): if self.is_busy():
raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished") raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished")
threading.Thread(target=self._move, args=(width, speed)).start() self._move(width, speed)
def grasp(self, width, force=0, speed=0, epsilon_inner=0, epsilon_outer=0): def grasp(self, width, force=0, speed=0, epsilon_inner=0, epsilon_outer=0):
""" """
@@ -95,7 +95,7 @@ class FrankaGripperInterface:
""" """
if self.is_busy(): if self.is_busy():
raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished") raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished")
threading.Thread(target=self._grasp, args=(width, force, speed, epsilon_inner, epsilon_outer)).start() self._grasp(width, force, speed, epsilon_inner, epsilon_outer)
def get_max_width(self): def get_max_width(self):
""" Get the maximum width of the gripper """ """ Get the maximum width of the gripper """
@@ -131,7 +131,7 @@ class FrankaGripperInterface:
def is_busy(self): def is_busy(self):
""" Check if the gripper is currently moving or grasping """ """ Check if the gripper is currently moving or grasping """
return self._moving or self._grasping return self._moving or self._grasping or self.service_future is not None
def is_done(self): def is_done(self):
""" Check if the gripper is done moving or grasping """ """ Check if the gripper is done moving or grasping """
@@ -139,7 +139,9 @@ class FrankaGripperInterface:
self.node.get_logger().warn("Gripper is not moving or grasping") self.node.get_logger().warn("Gripper is not moving or grasping")
return False return False
else: else:
if self.result_queue.empty(): if self.service_future is not None:
if self.service_future.done():
return True
return False return False
else: else:
return True return True
@@ -149,11 +151,19 @@ class FrankaGripperInterface:
Get the result of the last action Get the result of the last action
:return: :return:
""" """
if not self.result_queue.empty(): if self.service_future is not None:
response = self.result_queue.get() if self.service_future.done():
self._moving = False response = self.service_future.result()
self._grasping = False if isinstance(response, Move.Response):
return response.success self._moving = False
elif isinstance(response, Grasp.Response):
self._grasping = False
else:
raise Exception("Invalid response type")
self.service_future = None
return response.success
else:
raise Exception("No result available")
else: else:
raise Exception("No result available") raise Exception("No result available")
@@ -164,40 +174,33 @@ class FrankaGripperInterface:
""" """
if not self.is_enabled(): if not self.is_enabled():
raise Exception("Gripper is not enabled") raise Exception("Gripper is not enabled")
if not self._moving and not self._grasping: if not self.is_busy():
raise Exception("Gripper is not moving or grasping") return
if not self._moving or self._grasping: while not self.is_done():
raise Exception("Gripper is not moving or grasping")
while self._moving or self._grasping:
self.spin_handler() self.spin_handler()
time.sleep(0.1) time.sleep(0.01)
if not self.result_queue.empty():
response = self.result_queue.get()
if isinstance(response, Move_Response):
self._moving = False
elif isinstance(response, Grasp_Response):
self._grasping = False
else:
raise Exception("Invalid response type")
break
return response.success
def _move(self, width, speed): def _move(self, width, speed):
self._moving = True self._moving = True
request = Move_Request() # self.node.get_logger().info("Moving gripper to width: " + str(width) + " speed: " + str(speed))
request.width = width request = Move.Request()
request.speed = speed request.width = float(width)
response = self.move_service.call(request) request.speed = float(speed)
self.result_queue.put(response) # self.node.get_logger().info("Calling move service")
self.service_future = self.move_service.call_async(request)
def _grasp(self, width, force, speed, epsilon_inner, epsilon_outer): def _grasp(self, width, force, speed, epsilon_inner, epsilon_outer):
self._grasping = True self._grasping = True
request = Grasp_Request() # self.node.get_logger().info("Grasping object at width: " + str(width) + " force: " + str(force) + " speed: " + str(speed))
request.width = width request = Grasp.Request()
request.force = force request.width = float(width)
request.speed = speed request.force = float(force)
request.epsilon_inner = epsilon_inner request.speed = float(speed)
request.epsilon_outer = epsilon_outer request.epsilon_inner = float(epsilon_inner)
response = self.grasp_service.call(request) request.epsilon_outer = float(epsilon_outer)
self.result_queue.put(response) # self.node.get_logger().info("Calling grasp service")
self.service_future = self.grasp_service.call_async(request)
def set_spin_handler(self, spin_handler):
self.spin_handler = spin_handler

View File

@@ -78,12 +78,11 @@ namespace qros
} }
void EffectorDriverFrankaHand::start_control_loop() void EffectorDriverFrankaHand::start_control_loop() {
{
sas::Clock clock = sas::Clock(configuration_.thread_sampeling_time_s); sas::Clock clock = sas::Clock(configuration_.thread_sampeling_time_s);
clock.init(); clock.init();
RCLCPP_INFO_STREAM(node_->get_logger(), RCLCPP_INFO_STREAM(node_->get_logger(),"[EffectorDriverFrankaHand]::start_control_loop::Starting control loop.");
"["+ std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::start_control_loop::Starting control loop."); RCLCPP_WARN_STREAM(node_->get_logger(),"[EffectorDriverFrankaHand]::Gripper READY.");
while (!(*break_loops_)) while (!(*break_loops_))
{ {
if (!_is_connected()) throw std::runtime_error("[" + std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::start_control_loop::Robot is not connected."); if (!_is_connected()) throw std::runtime_error("[" + std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::start_control_loop::Robot is not connected.");
@@ -141,7 +140,7 @@ namespace qros
{ {
throw std::runtime_error("[" + std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::gripper_homing::Failed to home the gripper."); throw std::runtime_error("[" + std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::gripper_homing::Failed to home the gripper.");
} }
RCLCPP_INFO_STREAM(node_->get_logger(),"["+ std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::gripper_homing::Gripper homed."); RCLCPP_INFO_STREAM(node_->get_logger(),"[EffectorDriverFrankaHand]::gripper_homing::Gripper homed.");
} }
void EffectorDriverFrankaHand::initialize() void EffectorDriverFrankaHand::initialize()
@@ -151,6 +150,14 @@ namespace qros
gripper_homing(); gripper_homing();
// start gripper status loop // start gripper status loop
status_loop_thread_ = std::thread(&EffectorDriverFrankaHand::_gripper_status_loop, this); status_loop_thread_ = std::thread(&EffectorDriverFrankaHand::_gripper_status_loop, this);
// check status loop with timeout
auto time_now = std::chrono::system_clock::now();
auto time_out = time_now + std::chrono::seconds(5);
while (!status_loop_running_)
{
if (std::chrono::system_clock::now() > time_out){throw std::runtime_error("[" + std::string(node_->get_name()) + "]::[EffectorDriverFrankaHand]::initialize::Could not start status loop.");}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
} }
void EffectorDriverFrankaHand::deinitialize() void EffectorDriverFrankaHand::deinitialize()
@@ -243,13 +250,12 @@ namespace qros
void EffectorDriverFrankaHand::_gripper_status_loop() void EffectorDriverFrankaHand::_gripper_status_loop()
{ {
status_loop_running_ = true;
sas::Clock clock = sas::Clock(configuration_.thread_sampeling_time_s); sas::Clock clock = sas::Clock(configuration_.thread_sampeling_time_s);
RCLCPP_INFO_STREAM(node_->get_logger(),"["+ std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Starting status loop.") RCLCPP_INFO_STREAM(node_->get_logger(),"["+ std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Starting status loop.");
;
clock.init(); clock.init();
try try
{ {
status_loop_running_ = true;
while (status_loop_running_) while (status_loop_running_)
{ {
#ifdef BLOCK_READ_IN_USED #ifdef BLOCK_READ_IN_USED

View File

@@ -40,7 +40,7 @@ using RDC = qros::RobotDynamicsClient;
using RDS = qros::RobotDynamicsServer; using RDS = qros::RobotDynamicsServer;
PYBIND11_MODULE(_qros_franka_robot_dynamic, m) PYBIND11_MODULE(_qros_franka_robot_dynamics_py, m)
{ {
py::class_<RDC>(m, "RobotDynamicsClient") py::class_<RDC>(m, "RobotDynamicsClient")
.def(py::init<const std::shared_ptr<rclcpp::Node>&,const std::string&>()) .def(py::init<const std::shared_ptr<rclcpp::Node>&,const std::string&>())

View File

@@ -118,35 +118,33 @@ int main(int argc, char **argv)
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"Force upper limits scaling factor is not set."); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"Force upper limits scaling factor is not set.");
} }
try{node->declare_parameter<std::vector<double>>("upper_torque_threshold");}catch (...){} try {
if(node->has_parameter("upper_torque_threshold")) {
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper torque threshold override and set.");
std::vector<double> upper_torque_threshold_std_vec; std::vector<double> upper_torque_threshold_std_vec;
sas::get_ros_parameter(node,"upper_torque_threshold",upper_torque_threshold_std_vec); sas::get_ros_parameter(node,"upper_torque_threshold",upper_torque_threshold_std_vec);
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper torque threshold override and set.");
franka_interface_configuration.upper_torque_threshold = std_vec_to_std_array<double,7>(upper_torque_threshold_std_vec); franka_interface_configuration.upper_torque_threshold = std_vec_to_std_array<double,7>(upper_torque_threshold_std_vec);
}else { }catch(...) {
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper torque threshold not set. Using default with value scalling."); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper torque threshold not set. Using default with value scalling.");
franka_interface_configuration.upper_torque_threshold = apply_scale_to_std_array(franka_interface_configuration.upper_torque_threshold, upper_scale_factor); franka_interface_configuration.upper_torque_threshold = apply_scale_to_std_array(franka_interface_configuration.upper_torque_threshold, upper_scale_factor);
} }
try{node->declare_parameter<std::vector<double>>("upper_force_threshold");}catch (...){} try {
if(node->has_parameter("upper_force_threshold")) { std::vector<double> upper_force_threshold_std_vec;
sas::get_ros_parameter(node,"upper_force_threshold",upper_force_threshold_std_vec);
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper force threshold override and set."); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper force threshold override and set.");
std::vector<double> upper_torque_threshold_std_vec; franka_interface_configuration.upper_force_threshold = std_vec_to_std_array<double,6>(upper_force_threshold_std_vec);
sas::get_ros_parameter(node,"upper_force_threshold",upper_torque_threshold_std_vec); }catch(...) {
franka_interface_configuration.upper_force_threshold = std_vec_to_std_array<double,6>(upper_torque_threshold_std_vec); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper torque threshold not set. Using default with value scalling.");
}else {
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper force threshold not set. Using default with value scalling.");
franka_interface_configuration.upper_force_threshold = apply_scale_to_std_array(franka_interface_configuration.upper_force_threshold, upper_scale_factor); franka_interface_configuration.upper_force_threshold = apply_scale_to_std_array(franka_interface_configuration.upper_force_threshold, upper_scale_factor);
} }
try{node->declare_parameter<std::string>("robot_parameter_file_path");}catch (...){} try {
if(node->has_parameter("robot_parameter_file_path"))
{
std::string robot_parameter_file_path; std::string robot_parameter_file_path;
sas::get_ros_parameter(node,"robot_parameter_file_path",robot_parameter_file_path); sas::get_ros_parameter(node,"robot_parameter_file_path",robot_parameter_file_path);
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Loading robot parameters from file: " + robot_parameter_file_path); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Loading robot parameters from file: " + robot_parameter_file_path);
const auto robot = DQ_JsonReader::get_from_json<DQ_SerialManipulatorDH>(robot_parameter_file_path); const auto robot = DQ_JsonReader::get_from_json<DQ_SerialManipulatorDH>(robot_parameter_file_path);
robot_driver_franka_configuration.robot_reference_frame = robot.get_reference_frame(); robot_driver_franka_configuration.robot_reference_frame = robot.get_reference_frame();
}else{RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Robot parameter file path not set. Robot Model Unknow.");} }catch(...) {
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Robot parameter file path not set. Robot Model Unknow.");
}
robot_driver_franka_configuration.interface_configuration = franka_interface_configuration; robot_driver_franka_configuration.interface_configuration = franka_interface_configuration;