From 900f6aa2e111151e29954476ca8be0a03a875db0 Mon Sep 17 00:00:00 2001 From: qlin960618 Date: Fri, 16 Aug 2024 11:30:58 +0900 Subject: [PATCH] minor renaming of file and working coppelia node --- CMakeLists.txt | 18 + .../coppelia/sas_robot_driver_coppelia.hpp | 139 ++++++ ...h => qros_effector_driver_franka_hand.hpp} | 0 ...ce_franka.h => robot_interface_franka.hpp} | 0 ...erface_hand.h => robot_interface_hand.hpp} | 0 ...r_franka.h => sas_robot_driver_franka.hpp} | 2 +- launch/sas_robot_driver_franka_example.py | 25 +- ..._robot_driver_franka_simulation_example.py | 27 ++ qt/configuration_window/mainwindow.h | 2 +- src/coppelia/sas_robot_driver_coppelia.cpp | 430 +++++++++--------- src/coppelia/sas_robot_driver_coppelia.h | 134 ------ src/hand/qros_effector_driver_franka_hand.cpp | 2 +- src/hand/robot_interface_hand.cpp | 31 +- src/joint/robot_interface_franka.cpp | 2 +- src/joint/sas_robot_driver_franka.cpp | 9 +- src/sas_robot_driver_coppelia_node.cpp | 71 +-- src/sas_robot_driver_franka_hand_node.cpp | 2 +- src/sas_robot_driver_franka_node.cpp | 14 +- 18 files changed, 504 insertions(+), 404 deletions(-) create mode 100644 include/sas_robot_driver_franka/coppelia/sas_robot_driver_coppelia.hpp rename include/sas_robot_driver_franka/interfaces/{qros_effector_driver_franka_hand.h => qros_effector_driver_franka_hand.hpp} (100%) rename include/sas_robot_driver_franka/interfaces/{robot_interface_franka.h => robot_interface_franka.hpp} (100%) rename include/sas_robot_driver_franka/{robot_interface_hand.h => robot_interface_hand.hpp} (100%) rename include/sas_robot_driver_franka/{sas_robot_driver_franka.h => sas_robot_driver_franka.hpp} (99%) create mode 100644 launch/sas_robot_driver_franka_simulation_example.py delete mode 100644 src/coppelia/sas_robot_driver_coppelia.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c082786..40d521b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,24 @@ install(TARGETS sas_robot_driver_franka_hand_node DESTINATION lib/${PROJECT_NAME}) +##### Coppelia Mirror Node ##### + +add_executable(sas_robot_driver_franka_coppelia_node + src/sas_robot_driver_coppelia_node.cpp + src/coppelia/sas_robot_driver_coppelia.cpp +) +ament_target_dependencies(sas_robot_driver_franka_coppelia_node + rclcpp sas_common sas_core sas_conversions sas_robot_driver +) + +target_link_libraries(sas_robot_driver_franka_coppelia_node + dqrobotics + dqrobotics-interface-json11 + dqrobotics-interface-vrep +) +install(TARGETS + sas_robot_driver_franka_coppelia_node + DESTINATION lib/${PROJECT_NAME}) ##### JuanEmika diff --git a/include/sas_robot_driver_franka/coppelia/sas_robot_driver_coppelia.hpp b/include/sas_robot_driver_franka/coppelia/sas_robot_driver_coppelia.hpp new file mode 100644 index 0000000..337f2a0 --- /dev/null +++ b/include/sas_robot_driver_franka/coppelia/sas_robot_driver_coppelia.hpp @@ -0,0 +1,139 @@ +/* +# Copyright (c) 2023 Juan Jose Quiroz Omana +# +# This file is part of sas_robot_driver_franka. +# +# sas_robot_driver_franka is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# sas_robot_driver_franka is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with sas_robot_driver. If not, see . +# +# ################################################################ +# +# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com +# +# ################################################################ +# +# Contributors: +# 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com) +# - Adapted from sas_robot_driver_denso.cpp +# (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso.cpp) +# +# ################################################################ +*/ + + +#pragma once +#include +#include +#include +#include +#include +#include +#include +// #include +#include +#include +// #include +#include +#include +#include +#include + +#define VIRTUAL_ROBOT_SIMULATION_SAMPLING_TIME_SEC 0.002 // 2ms, 500Hz +#define REAL_ROBOT_INTERFACE_INIT_TIMEOUT_COUNT 500 +using namespace DQ_robotics; +using namespace Eigen; + +namespace qros +{ + + + +struct RobotDriverCoppeliaConfiguration +{ + + double thread_sampling_time_sec; // frontend vrep update rate + int vrep_port; + std::string vrep_ip; + std::vector vrep_joint_names; + bool vrep_dynamically_enabled = false; + std::string robot_mode; + bool using_real_robot; + std::string robot_topic_prefix; + std::string robot_parameter_file_path; + // VectorXd q_min; + // VectorXd q_max; +}; + +class RobotDriverCoppelia +{ +private: + enum ControlMode{ + Position=0, + Velocity + }; + + RobotDriverCoppeliaConfiguration configuration_; + std::shared_ptr node_sptr_; + + sas::Clock clock_; + std::atomic_bool* break_loops_; + bool _should_shutdown() const {return (*break_loops_);} + ControlMode robot_mode_; + + std::shared_ptr vi_; + std::shared_ptr real_robot_interface_ = nullptr; + std::shared_ptr robot_provider_ = nullptr; + + // backend thread for simulaton + /** + * Current simulation mechanism is not accounting for any robot dynamics, just the joint limits + */ + std::thread velocity_control_simulation_thread_; + VectorXd simulated_joint_positions_; + VectorXd simulated_joint_velocities_; + void start_simulation_thread(); // thread entry point + void _velocity_control_simulation_thread_main(); + std::atomic_bool simulation_thread_started_{false}; + + bool initialized_ = false; + inline void _assert_initialized() const{ + if (!initialized_){throw std::runtime_error("[RobotDriverCoppelia] Robot driver not initialized");} + } + inline void _assert_is_alive() const{ + if(!configuration_.using_real_robot && !simulation_thread_started_){throw std::runtime_error("[RobotDriverCoppelia] Robot Simulation is not alive");} + } + + void _start_control_loop(); +protected: + inline void _update_vrep_position(const VectorXd &joint_positions, const bool& force_update=false) const; + inline void _update_vrep_velocity(const VectorXd & joint_velocity) const; + +public: + RobotDriverCoppelia(const RobotDriverCoppelia&)=delete; + RobotDriverCoppelia()=delete; + ~RobotDriverCoppelia(); + + RobotDriverCoppelia(const std::shared_ptr &node_sptr, const RobotDriverCoppeliaConfiguration& configuration, std::atomic_bool* break_loops); + + int start_control_loop(); // public entry point + + void connect(); + void disconnect(); + + void initialize(); + void deinitialize(); + + std::tuple joint_limits_; + +}; +} diff --git a/include/sas_robot_driver_franka/interfaces/qros_effector_driver_franka_hand.h b/include/sas_robot_driver_franka/interfaces/qros_effector_driver_franka_hand.hpp similarity index 100% rename from include/sas_robot_driver_franka/interfaces/qros_effector_driver_franka_hand.h rename to include/sas_robot_driver_franka/interfaces/qros_effector_driver_franka_hand.hpp diff --git a/include/sas_robot_driver_franka/interfaces/robot_interface_franka.h b/include/sas_robot_driver_franka/interfaces/robot_interface_franka.hpp similarity index 100% rename from include/sas_robot_driver_franka/interfaces/robot_interface_franka.h rename to include/sas_robot_driver_franka/interfaces/robot_interface_franka.hpp diff --git a/include/sas_robot_driver_franka/robot_interface_hand.h b/include/sas_robot_driver_franka/robot_interface_hand.hpp similarity index 100% rename from include/sas_robot_driver_franka/robot_interface_hand.h rename to include/sas_robot_driver_franka/robot_interface_hand.hpp diff --git a/include/sas_robot_driver_franka/sas_robot_driver_franka.h b/include/sas_robot_driver_franka/sas_robot_driver_franka.hpp similarity index 99% rename from include/sas_robot_driver_franka/sas_robot_driver_franka.h rename to include/sas_robot_driver_franka/sas_robot_driver_franka.hpp index 0f6aeaf..b6fda2c 100644 --- a/include/sas_robot_driver_franka/sas_robot_driver_franka.h +++ b/include/sas_robot_driver_franka/sas_robot_driver_franka.hpp @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include diff --git a/launch/sas_robot_driver_franka_example.py b/launch/sas_robot_driver_franka_example.py index 8820acd..003a843 100644 --- a/launch/sas_robot_driver_franka_example.py +++ b/launch/sas_robot_driver_franka_example.py @@ -13,16 +13,33 @@ def generate_launch_description(): "robot_ip_address": "172.16.0.4", "thread_sampling_time_sec": 0.004, # "thread_sampling_time_nsec": 4000000, - "q_min": [-2.3093,-1.5133,-2.4937, -2.7478,-2.4800, 0.8521, -2.6895], - "q_max": [ 2.3093, 1.5133, 2.4937, -0.4461, 2.4800, 4.2094, 2.6895], + "q_min": [-2.3093, -1.5133, -2.4937, -2.7478, -2.4800, 0.8521, -2.6895], + "q_max": [2.3093, 1.5133, 2.4937, -0.4461, 2.4800, 4.2094, 2.6895], "force_upper_limits_scaling_factor": 4.0, "upper_torque_threshold": [40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0], "upper_force_threshold": [40.0, 40.0, 40.0, 40.0, 40.0, 40.0], "robot_mode": "VelocityControl", "robot_parameter_file_path": os.environ["ROBOT_3_JSON_PATH"] }], - output="screen" + output="screen" + ), + Node( + package='sas_robot_driver_franka', + executable='sas_robot_driver_franka_coppelia_node', + name='arm3_coppelia', + parameters=[{ + "thread_sampling_time_sec": 0.008, + "vrep_ip": os.environ["VREP_IP"], + "vrep_port": 20012, + "vrep_dynamically_enabled": True, + "using_real_robot": True, + "vrep_joint_names": ["Franka_joint1#1", "Franka_joint2#1", "Franka_joint3#1", "Franka_joint4#1", + "Franka_joint5#1", "Franka_joint6#1", "Franka_joint7#1"], + "robot_topic_prefix": "/arm3", + "robot_mode": "VelocityControl", + "robot_parameter_file_path": os.environ["ROBOT_3_JSON_PATH"] + }], + output="screen" ), ]) - diff --git a/launch/sas_robot_driver_franka_simulation_example.py b/launch/sas_robot_driver_franka_simulation_example.py new file mode 100644 index 0000000..a68756b --- /dev/null +++ b/launch/sas_robot_driver_franka_simulation_example.py @@ -0,0 +1,27 @@ +from launch import LaunchDescription +from launch_ros.actions import Node +import os + + +def generate_launch_description(): + return LaunchDescription([ + Node( + package='sas_robot_driver_franka', + executable='sas_robot_driver_franka_coppelia_node', + name='arm3_coppelia', + parameters=[{ + "thread_sampling_time_sec": 0.008, + "vrep_ip": os.environ["VREP_IP"], + "vrep_port": 20012, + "vrep_dynamically_enabled": True, + "using_real_robot": False, + "vrep_joint_names": ["Franka_joint1#1", "Franka_joint2#1", "Franka_joint3#1", "Franka_joint4#1", + "Franka_joint5#1", "Franka_joint6#1", "Franka_joint7#1"], + "robot_topic_prefix": "/arm3", + "robot_mode": "VelocityControl", + "robot_parameter_file_path": os.environ["ROBOT_3_JSON_PATH"] + }], + output="screen" + ), + + ]) diff --git a/qt/configuration_window/mainwindow.h b/qt/configuration_window/mainwindow.h index 7b801be..5293af5 100644 --- a/qt/configuration_window/mainwindow.h +++ b/qt/configuration_window/mainwindow.h @@ -7,7 +7,7 @@ #include #include "qspinbox.h" -#include +#include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } diff --git a/src/coppelia/sas_robot_driver_coppelia.cpp b/src/coppelia/sas_robot_driver_coppelia.cpp index 552442c..5789291 100644 --- a/src/coppelia/sas_robot_driver_coppelia.cpp +++ b/src/coppelia/sas_robot_driver_coppelia.cpp @@ -1,252 +1,246 @@ -#include "sas_robot_driver_coppelia.h" +#include -namespace sas +namespace qros { - -RobotDriverCoppelia::RobotDriverCoppelia(const RobotDriverCoppeliaConfiguration &configuration, std::atomic_bool *break_loops): -RobotDriver(break_loops), - configuration_(configuration), - robot_mode_(configuration.robot_mode), - jointnames_(configuration.jointnames), - mirror_mode_(configuration.mirror_mode), - dim_configuration_space_(configuration.jointnames.size()), - real_robot_topic_prefix_(configuration.real_robot_topic_prefix) -{ - vi_ = std::make_shared(); - desired_joint_velocities_ = VectorXd::Zero(dim_configuration_space_); - auto nodehandle = ros::NodeHandle(); - std::cout<<"RobotDriverCoppelia::Rostopic: "<<"/"+real_robot_topic_prefix_<(nodehandle, "/"+real_robot_topic_prefix_); +RobotDriverCoppelia::~RobotDriverCoppelia() { + deinitialize(); + disconnect(); } -VectorXd RobotDriverCoppelia::get_joint_positions() +RobotDriverCoppelia::RobotDriverCoppelia(const std::shared_ptr &node_sptr, const RobotDriverCoppeliaConfiguration &configuration, std::atomic_bool *break_loops): + configuration_(configuration), + node_sptr_(node_sptr), + clock_(configuration.thread_sampling_time_sec), + break_loops_(break_loops), + robot_mode_(ControlMode::Position), + vi_(std::make_shared()) { - return current_joint_positions_; -} - -void RobotDriverCoppelia::set_target_joint_positions(const VectorXd &desired_joint_positions_rad) -{ - desired_joint_positions_ = desired_joint_positions_rad; -} - -VectorXd RobotDriverCoppelia::get_joint_velocities() -{ - return current_joint_velocities_; -} - -void RobotDriverCoppelia::set_target_joint_velocities(const VectorXd &desired_joint_velocities) -{ - desired_joint_velocities_ = desired_joint_velocities; -} - -VectorXd RobotDriverCoppelia::get_joint_forces() -{ - return current_joint_forces_; -} - -RobotDriverCoppelia::~RobotDriverCoppelia()=default; - -void RobotDriverCoppelia::connect() -{ - - vi_->connect(configuration_.ip, configuration_.port, 500, 10); - vi_->set_joint_target_velocities(jointnames_, VectorXd::Zero(dim_configuration_space_)); - std::cout<<"RobotDriverCoppelia::Connecting..."<disconnect(); - if (joint_velocity_control_mode_thread_.joinable()) + // should initialize robot driver interface to real robot + DQ_SerialManipulatorDH smdh = DQ_JsonReader::get_from_json(configuration_.robot_parameter_file_path); + joint_limits_ = {smdh.get_lower_q_limit(),smdh.get_upper_q_limit()}; + if(configuration_.using_real_robot) { - joint_velocity_control_mode_thread_.join(); - } - if (joint_velocity_control_mirror_mode_thread_.joinable()) - { - joint_velocity_control_mirror_mode_thread_.join(); - } - std::cout<<"RobotDriverCoppelia::Disconnected."<start_simulation(); - if (mirror_mode_ == false) - { - _start_joint_velocity_control_thread(); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Using real robot, Instantiating robot interface to real driver at ["+configuration_.robot_topic_prefix+"]."); + real_robot_interface_ = std::make_shared(node_sptr_, configuration_.robot_topic_prefix); }else{ - _start_joint_velocity_control_mirror_thread(); - } - std::cout<<"RobotDriverCoppelia::Velocity loop running..."<set_joint_target_velocities(jointnames_, VectorXd::Zero(dim_configuration_space_)); - vi_->stop_simulation(); - finish_motion(); - std::cout<<"RobotDriverCoppelia::Deinitialized."<get_joint_positions(jointnames_); - VectorXd q_dot = vi_->get_joint_velocities(jointnames_); - VectorXd forces = vi_->get_joint_torques(jointnames_); - _update_robot_state(q, q_dot, forces); - - desired_joint_positions_ = q; - while(true) - { - - VectorXd q = vi_->get_joint_positions(jointnames_); - VectorXd q_dot = vi_->get_joint_velocities(jointnames_); - VectorXd forces = vi_->get_joint_torques(jointnames_); - _update_robot_state(q, q_dot, forces); - - - if (robot_mode_ == std::string("VelocityControl")) - { - vi_->set_joint_target_velocities(jointnames_, desired_joint_velocities_); - } - else if (robot_mode_ == std::string("PositionControl")) - { - vi_->set_joint_target_positions(jointnames_, desired_joint_positions_); - } - if (finish_motion_) { - finish_motion_ = false; - return; - } + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Using simulation robot, simulation mode is set to "+ configuration_.robot_mode); + robot_provider_ = std::make_shared(node_sptr_, configuration_.robot_topic_prefix); + std::string _mode_upper = configuration_.robot_mode; + std::transform(_mode_upper.begin(), _mode_upper.end(), _mode_upper.begin(), ::toupper); + if(_mode_upper == "POSITIONCONTROL"){ + robot_mode_ = ControlMode::Position; + }else if(_mode_upper == "VELOCITYCONTROL"){ + robot_mode_ = ControlMode::Velocity; + }else{ + throw std::invalid_argument("[" + std::string(node_sptr_->get_name()) + "]::Robot mode must be either 'position' or 'velocity'"); } } + +} + +void RobotDriverCoppelia::_update_vrep_position(const VectorXd &joint_positions, const bool& force_update) const{ + if(configuration_.vrep_dynamically_enabled){ + if(force_update){ + vi_->set_joint_positions(configuration_.vrep_joint_names, joint_positions); + } + vi_->set_joint_target_positions(configuration_.vrep_joint_names, joint_positions); + }else{ + vi_->set_joint_positions(configuration_.vrep_joint_names, joint_positions); + } +} + +void RobotDriverCoppelia::_update_vrep_velocity(const VectorXd & joint_velocity) const{ + if(!configuration_.vrep_dynamically_enabled){ + throw std::runtime_error("[RobotDriverCoppelia]::[_update_vrep_velocity]::Vrep is not dynamically enabled"); + } + vi_->set_joint_target_velocities(configuration_.vrep_joint_names, joint_velocity); +} + +void RobotDriverCoppelia::_start_control_loop(){ + clock_.init(); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Starting control loop..."); + while(!_should_shutdown()){ + clock_.update_and_sleep(); + rclcpp::spin_some(node_sptr_); + if(!rclcpp::ok()){break_loops_->store(true);} + if(configuration_.using_real_robot){ + // real_robot_interface_ + auto joint_position = real_robot_interface_->get_joint_positions(); + _update_vrep_position(joint_position); + }else{ + // robot_provider_ + VectorXd target_joint_positions; + auto current_joint_positions = vi_->get_joint_positions(configuration_.vrep_joint_names); + VectorXd current_joint_velocity; + if(robot_provider_->is_enabled()) { + if(robot_mode_ == ControlMode::Velocity) + { + if(robot_provider_->is_enabled(sas::RobotDriver::Functionality::VelocityControl)) { + simulated_joint_velocities_ = robot_provider_->get_target_joint_velocities(); + current_joint_velocity = simulated_joint_velocities_; + // try{_update_vrep_velocity(simulated_joint_velocities_);}catch (...){} + } + else{ + RCLCPP_DEBUG_STREAM(node_sptr_->get_logger(), "::Velocity control is not enabled."); + } + target_joint_positions = simulated_joint_positions_; + }else{ + target_joint_positions = robot_provider_->get_target_joint_positions(); + } + }else { + target_joint_positions = current_joint_positions; + } + _update_vrep_position(target_joint_positions); + robot_provider_->send_joint_states(current_joint_positions, current_joint_velocity, VectorXd()); + robot_provider_->send_joint_limits(joint_limits_); + + } + } + + +} + +int RobotDriverCoppelia::start_control_loop(){ + try{ + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Waiting to connect with coppelia..."); + connect(); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Connected to coppelia."); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Initializing..."); + initialize(); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::initialized."); + + _start_control_loop(); + } catch(const std::exception& e) { - std::cout<<"RobotDriverCoppelia::sas_robot_coppelia_driver::_start_joint_velocity_control_mode(). Error or exception caught " << e.what()<get_logger(), "::Error or exception caught::" << e.what()); } catch(...) { - std::cout<<"RobotDriverCoppelia::sas_robot_coppelia_driver::_start_joint_velocity_control_mode(). Error or exception caught " <get_logger(), "::Unexpected error or exception caught"); } + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Deinitializing..."); + deinitialize(); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::deinitialized."); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Disconnecting from coppelia..."); + disconnect(); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Disconnected from coppelia."); - + return 0; } -void RobotDriverCoppelia::_start_joint_velocity_control_thread() -{ - finish_motion_ = false; - if (joint_velocity_control_mode_thread_.joinable()) - { - joint_velocity_control_mode_thread_.join(); + +void RobotDriverCoppelia::connect(){ + auto ret = vi_->connect(configuration_.vrep_ip, configuration_.vrep_port, 100, 10); + if(!ret){ + throw std::runtime_error("[RobotDriverCoppelia]::connect::Could not connect to Vrep"); } - if (joint_velocity_control_mirror_mode_thread_.joinable()) - { - joint_velocity_control_mirror_mode_thread_.join(); - } - joint_velocity_control_mode_thread_ = std::thread(&RobotDriverCoppelia::_start_joint_velocity_control_mode, this); + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::connect::Connected to Vrep"); +} +void RobotDriverCoppelia::disconnect(){ + vi_->disconnect_all(); } -void RobotDriverCoppelia::_start_joint_velocity_control_mirror_thread() -{ - finish_motion_ = false; - if (joint_velocity_control_mode_thread_.joinable()) +void RobotDriverCoppelia::initialize(){ + if(configuration_.using_real_robot) { - joint_velocity_control_mode_thread_.join(); - } - if (joint_velocity_control_mirror_mode_thread_.joinable()) - { - joint_velocity_control_mirror_mode_thread_.join(); - } - joint_velocity_control_mirror_mode_thread_ = std::thread(&RobotDriverCoppelia::_start_joint_velocity_control_mirror_mode, this); -} - -void RobotDriverCoppelia::_start_joint_velocity_control_mirror_mode() -{ - - try{ - finish_motion_ = false; - std::cout<<"RobotDriverCoppelia::Waiting for real robot topics..."<is_enabled()) - { - q = franka1_ros_->get_joint_positions(); - break; + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::Waiting for real robot interface to initialize..."); + rclcpp::spin_some(node_sptr_); + int count = 0; + while (!real_robot_interface_->is_enabled(sas::RobotDriver::Functionality::PositionControl)) { + rclcpp::spin_some(node_sptr_); + // std::cout<<"Waiting for real robot interface to initialize..."< REAL_ROBOT_INTERFACE_INIT_TIMEOUT_COUNT){ + RCLCPP_ERROR_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::Real robot interface not initialized. Exiting on TIMEOUT..."); + throw std::runtime_error("[" + std::string(node_sptr_->get_name()) +"]::[RobotDriverCoppelia]::initialize::Real robot interface not initialized."); + } + if(!rclcpp::ok()) { + RCLCPP_WARN_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::ROS shutdown received. Exiting..."); + throw std::runtime_error("[" + std::string(node_sptr_->get_name()) +"]::[RobotDriverCoppelia]::initialize::ROS shutdown received, not OK."); } - ros::spinOnce(); } - std::cout<<"RobotDriverCoppelia::Done!"<get_joint_positions(jointnames_); - VectorXd q_dot_vrep = vi_->get_joint_velocities(jointnames_); - VectorXd forces_vrep = vi_->get_joint_torques(jointnames_); - _update_robot_state(q_vrep, q_dot_vrep, forces_vrep); - - desired_joint_positions_ = q_vrep; - - - while(ros::ok()) + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::Real robot interface initialized."); + joint_limits_ = real_robot_interface_->get_joint_limits(); + _update_vrep_position(real_robot_interface_->get_joint_positions(), true); + }else{ + RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::Simulation mode."); + // initialization information for robot driver provider + /** + * TODO: check for making sure real robot is not actually connected + */ + auto current_joint_positions = vi_->get_joint_positions(configuration_.vrep_joint_names); + VectorXd current_joint_velocity; + if(robot_mode_ == ControlMode::Velocity) + {current_joint_velocity = VectorXd::Zero(current_joint_positions.size());} + robot_provider_->send_joint_states(current_joint_positions, current_joint_velocity, VectorXd()); + robot_provider_->send_joint_limits(joint_limits_); + // start velocity control simulation thread if needed + if(robot_mode_ == ControlMode::Velocity) { - q = franka1_ros_->get_joint_positions(); - if (q.size() == dim_configuration_space_) - { - VectorXd q_vrep = vi_->get_joint_positions(jointnames_); - VectorXd q_dot_vrep = vi_->get_joint_velocities(jointnames_); - VectorXd forces_vrep = vi_->get_joint_torques(jointnames_); - _update_robot_state(q_vrep, q_dot_vrep, forces_vrep); - - - if (robot_mode_ == std::string("VelocityControl")) - { - vi_->set_joint_target_velocities(jointnames_, gain_*(q-q_vrep)); - } - else if (robot_mode_ == std::string("PositionControl")) - { - vi_->set_joint_target_positions(jointnames_, q); - } - if (finish_motion_) { - finish_motion_ = false; - return; - } - } + simulated_joint_positions_ = current_joint_positions; + simulated_joint_velocities_ = current_joint_velocity; + start_simulation_thread(); } } - catch(const std::exception& e) - { - std::cout<<"RobotDriverCoppelia::sas_robot_coppelia_driver::_start_joint_velocity_control_mirror_mode(). Error or exception caught " << e.what()<get_logger(), "::RobotDriverCoppelia]::[_velocity_control_simulation_thread_main]::Simulation thread started."); + sas::Clock clock = sas::Clock(VIRTUAL_ROBOT_SIMULATION_SAMPLING_TIME_SEC); + double tau = VIRTUAL_ROBOT_SIMULATION_SAMPLING_TIME_SEC; + auto current_joint_positions = simulated_joint_positions_; + clock.init(); + while (!(*break_loops_) && rclcpp::ok()) { + + current_joint_positions += tau * simulated_joint_velocities_; // no dynamic model + // cap joint limit + auto q_min = std::get<0>(joint_limits_); + auto q_max = std::get<1>(joint_limits_); + for (int i = 0; i < current_joint_positions.size(); i++) { + if (current_joint_positions(i) < q_min(i)) { + current_joint_positions(i) = q_min(i); + } + if (current_joint_positions(i) > q_max(i)) { + current_joint_positions(i) = q_max(i); + } + } + simulated_joint_positions_ = current_joint_positions; + clock.update_and_sleep(); + } + }catch(std::exception &e){ + RCLCPP_ERROR_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::[_velocity_control_simulation_thread_main]::Exception::" << e.what()); + simulation_thread_started_ = false; + }catch(...){ + RCLCPP_ERROR_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::[_velocity_control_simulation_thread_main]::Exception::Unknown"); + simulation_thread_started_ = false; + } + break_loops_->store(true); + +} diff --git a/src/coppelia/sas_robot_driver_coppelia.h b/src/coppelia/sas_robot_driver_coppelia.h deleted file mode 100644 index cabdd9f..0000000 --- a/src/coppelia/sas_robot_driver_coppelia.h +++ /dev/null @@ -1,134 +0,0 @@ -/* -# Copyright (c) 2023 Juan Jose Quiroz Omana -# -# This file is part of sas_robot_driver_franka. -# -# sas_robot_driver_franka is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# sas_robot_driver_franka is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with sas_robot_driver. If not, see . -# -# ################################################################ -# -# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com -# -# ################################################################ -# -# Contributors: -# 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com) -# - Adapted from sas_robot_driver_denso.cpp -# (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso.cpp) -# -# ################################################################ -*/ - - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace DQ_robotics; -using namespace Eigen; - -namespace sas -{ - - - -struct RobotDriverCoppeliaConfiguration -{ - - int thread_sampling_time_nsec; - int port; - std::string ip; - std::vector jointnames; - std::string robot_mode; - bool mirror_mode; - std::string real_robot_topic_prefix; -}; - -class RobotDriverCoppelia: public RobotDriver -{ -private: - RobotDriverCoppeliaConfiguration configuration_; - - std::string robot_mode_ = std::string("VelocityControl"); // PositionControl - bool mirror_mode_ = false; - double gain_ = 3.0; - std::string real_robot_topic_prefix_; - - VectorXd current_joint_positions_; - VectorXd current_joint_velocities_; - VectorXd current_joint_forces_; - - - VectorXd desired_joint_velocities_; - VectorXd desired_joint_positions_; - - std::atomic finish_motion_; - - int dim_configuration_space_; - - void _update_robot_state(const VectorXd& q, const VectorXd& q_dot, const VectorXd& forces); - - void finish_motion(); - - void _start_joint_velocity_control_mode(); - std::thread joint_velocity_control_mode_thread_; - void _start_joint_velocity_control_thread(); - - - void _start_joint_velocity_control_mirror_mode(); - std::thread joint_velocity_control_mirror_mode_thread_; - void _start_joint_velocity_control_mirror_thread(); - - std::shared_ptr franka1_ros_; - - -protected: - std::shared_ptr vi_; - std::vector jointnames_; - - - -public: - RobotDriverCoppelia(const RobotDriverCoppelia&)=delete; - RobotDriverCoppelia()=delete; - ~RobotDriverCoppelia(); - - RobotDriverCoppelia(const RobotDriverCoppeliaConfiguration& configuration, std::atomic_bool* break_loops); - - - VectorXd get_joint_positions() override; - void set_target_joint_positions(const VectorXd& desired_joint_positions_rad) override; - - VectorXd get_joint_velocities() override; - void set_target_joint_velocities(const VectorXd& desired_joint_velocities) override; - - VectorXd get_joint_forces() override; - - void connect() override; - void disconnect() override; - - void initialize() override; - void deinitialize() override; - - -}; -} diff --git a/src/hand/qros_effector_driver_franka_hand.cpp b/src/hand/qros_effector_driver_franka_hand.cpp index 0a49057..b04e624 100644 --- a/src/hand/qros_effector_driver_franka_hand.cpp +++ b/src/hand/qros_effector_driver_franka_hand.cpp @@ -27,7 +27,7 @@ # # ################################################################ */ -#include +#include #include diff --git a/src/hand/robot_interface_hand.cpp b/src/hand/robot_interface_hand.cpp index fd5bc1a..c1a8d3f 100644 --- a/src/hand/robot_interface_hand.cpp +++ b/src/hand/robot_interface_hand.cpp @@ -1,4 +1,33 @@ -#include "sas_robot_driver_franka/robot_interface_hand.h" +/* +# Copyright (c) 2023 Juan Jose Quiroz Omana +# +# This file is part of sas_robot_driver_franka. +# +# sas_robot_driver_franka is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# sas_robot_driver_franka is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with sas_robot_driver. If not, see . +# +# ################################################################ +# +# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com +# +# ################################################################ +# +# Contributors: +# 1. Quenitin Lin +# +# ################################################################ +*/ +#include "sas_robot_driver_franka/robot_interface_hand.hpp" diff --git a/src/joint/robot_interface_franka.cpp b/src/joint/robot_interface_franka.cpp index 89e0a99..9b7071f 100644 --- a/src/joint/robot_interface_franka.cpp +++ b/src/joint/robot_interface_franka.cpp @@ -30,7 +30,7 @@ */ -#include +#include /** diff --git a/src/joint/sas_robot_driver_franka.cpp b/src/joint/sas_robot_driver_franka.cpp index d96cbad..426433d 100644 --- a/src/joint/sas_robot_driver_franka.cpp +++ b/src/joint/sas_robot_driver_franka.cpp @@ -31,7 +31,7 @@ */ -#include +#include #include #include @@ -42,8 +42,8 @@ namespace sas const std::shared_ptr &node, const std::shared_ptr &robot_dynamic_provider, const RobotDriverFrankaConfiguration &configuration, std::atomic_bool *break_loops ): - node_(node), RobotDriver(break_loops), + node_(node), configuration_(configuration), robot_dynamic_provider_sptr_(robot_dynamic_provider), break_loops_(break_loops) @@ -55,11 +55,10 @@ namespace sas //joint_positions_buffer_.resize(8,0); //end_effector_pose_euler_buffer_.resize(7,0); //end_effector_pose_homogenous_transformation_buffer_.resize(10,0); - std::cout<get_logger(), "Mode: " << configuration_.mode); if (configuration_.mode == std::string("None")) { diff --git a/src/sas_robot_driver_coppelia_node.cpp b/src/sas_robot_driver_coppelia_node.cpp index 04c4654..22b42d0 100644 --- a/src/sas_robot_driver_coppelia_node.cpp +++ b/src/sas_robot_driver_coppelia_node.cpp @@ -26,6 +26,9 @@ # 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com) # - Adapted from sas_robot_driver_denso_node.cpp # (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso_node.cpp) +# 2. Quentin Lin (qlin1806@g.ecc.u-tokyo.ac.jp) +# - Adapted for simplify operation +# - porting to ROS2 # # ################################################################ */ @@ -36,10 +39,9 @@ #include #include //#include -#include -#include -#include -#include "coppelia/sas_robot_driver_coppelia.h" +#include +#include +#include /********************************************* * SIGNAL HANDLER @@ -52,52 +54,51 @@ void sig_int_handler(int) } + int main(int argc, char **argv) { if(signal(SIGINT, sig_int_handler) == SIG_ERR) { - throw std::runtime_error(ros::this_node::getName() + "::Error setting the signal int handler."); + throw std::runtime_error("Error setting the signal int handler."); } - ros::init(argc, argv, "sas_robot_driver_coppelia_node", ros::init_options::NoSigintHandler); - ROS_WARN("====================================================================="); - ROS_WARN("----------------------Juan Jose Quiroz Omana------------------------"); - ROS_WARN("====================================================================="); - ROS_INFO_STREAM(ros::this_node::getName()+"::Loading parameters from parameter server."); + rclcpp::init(argc,argv,rclcpp::InitOptions(),rclcpp::SignalHandlerOptions::None); + auto context = rclcpp::contexts::get_global_default_context(); + + auto node = std::make_shared("sas_robot_driver_franka_coppelia_node"); + + const auto node_name = std::string(node->get_name()); + RCLCPP_WARN(node->get_logger(),"====================================================================="); + RCLCPP_WARN(node->get_logger(),"-----------------Adapted by Quentin Lin ------------------------"); + RCLCPP_WARN(node->get_logger(),"====================================================================="); + RCLCPP_INFO_STREAM_ONCE(node->get_logger(),":Loading parameters from parameter server."); - ros::NodeHandle nh; - sas::RobotDriverCoppeliaConfiguration robot_driver_coppelia_configuration; - - sas::get_ros_param(nh,"/robot_ip_address",robot_driver_coppelia_configuration.ip); - sas::get_ros_param(nh,"/robot_mode", robot_driver_coppelia_configuration.robot_mode); - sas::get_ros_param(nh,"/vrep_port", robot_driver_coppelia_configuration.port); - sas::get_ros_param(nh,"/vrep_robot_joint_names", robot_driver_coppelia_configuration.jointnames); - sas::get_ros_param(nh,"/mirror_mode", robot_driver_coppelia_configuration.mirror_mode); - sas::get_ros_param(nh, "/real_robot_topic_prefix", robot_driver_coppelia_configuration.real_robot_topic_prefix); - sas::RobotDriverROSConfiguration robot_driver_ros_configuration; - - sas::get_ros_param(nh,"/thread_sampling_time_nsec",robot_driver_ros_configuration.thread_sampling_time_nsec); - sas::get_ros_param(nh,"/q_min",robot_driver_ros_configuration.q_min); - sas::get_ros_param(nh,"/q_max",robot_driver_ros_configuration.q_max); - - robot_driver_ros_configuration.robot_driver_provider_prefix = ros::this_node::getName(); + qros::RobotDriverCoppeliaConfiguration robot_driver_coppelia_configuration; + sas::get_ros_parameter(node,"thread_sampling_time_sec",robot_driver_coppelia_configuration.thread_sampling_time_sec); + sas::get_ros_parameter(node,"vrep_ip",robot_driver_coppelia_configuration.vrep_ip); + sas::get_ros_parameter(node,"vrep_port",robot_driver_coppelia_configuration.vrep_port); + sas::get_ros_parameter(node,"vrep_joint_names", robot_driver_coppelia_configuration.vrep_joint_names); + sas::get_ros_parameter(node,"vrep_dynamically_enabled", robot_driver_coppelia_configuration.vrep_dynamically_enabled); + sas::get_ros_parameter(node,"robot_mode", robot_driver_coppelia_configuration.robot_mode); + sas::get_ros_parameter(node,"using_real_robot", robot_driver_coppelia_configuration.using_real_robot); + sas::get_ros_parameter(node,"robot_topic_prefix", robot_driver_coppelia_configuration.robot_topic_prefix); + sas::get_ros_parameter(node,"robot_parameter_file_path", robot_driver_coppelia_configuration.robot_parameter_file_path); try { - ROS_INFO_STREAM(ros::this_node::getName()+"::Instantiating Coppelia robot."); - sas::RobotDriverCoppelia robot_driver_coppelia(robot_driver_coppelia_configuration, + RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"::Instantiating Coppelia robot mirror."); + qros::RobotDriverCoppelia robot_driver_coppelia(node, robot_driver_coppelia_configuration, &kill_this_process); - ROS_INFO_STREAM(ros::this_node::getName()+"::Instantiating RobotDriverROS."); - sas::RobotDriverROS robot_driver_ros(nh, - &robot_driver_coppelia, - robot_driver_ros_configuration, - &kill_this_process); - robot_driver_ros.control_loop(); + + return robot_driver_coppelia.start_control_loop(); } catch (const std::exception& e) { - ROS_ERROR_STREAM(ros::this_node::getName() + "::Exception::" + e.what()); + kill_this_process = true; + RCLCPP_ERROR_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Exception::" + e.what()); + shutdown(context, "Exception in main function: " + std::string(e.what())); + return -1; } diff --git a/src/sas_robot_driver_franka_hand_node.cpp b/src/sas_robot_driver_franka_hand_node.cpp index b924621..12ede61 100644 --- a/src/sas_robot_driver_franka_hand_node.cpp +++ b/src/sas_robot_driver_franka_hand_node.cpp @@ -35,7 +35,7 @@ #include #include // #include -#include +#include /********************************************* diff --git a/src/sas_robot_driver_franka_node.cpp b/src/sas_robot_driver_franka_node.cpp index ff5fe45..eb13751 100644 --- a/src/sas_robot_driver_franka_node.cpp +++ b/src/sas_robot_driver_franka_node.cpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include @@ -76,6 +76,15 @@ std::array std_vec_to_std_array(const std::vector& vector) } return array; } +VectorXd std_vec_to_eigen_vector(const std::vector& vector) +{ + VectorXd eigen_vector(vector.size()); + for(std::size_t i = 0; i < vector.size(); i++) + { + eigen_vector(i) = vector[i]; + } + return eigen_vector; +} int main(int argc, char **argv) @@ -164,7 +173,8 @@ int main(int argc, char **argv) robot_driver_franka_configuration, &kill_this_process ); - //robot_driver_franka.set_joint_limits({qmin, qmax}); + std::tuple joint_limits = {std_vec_to_eigen_vector(robot_driver_ros_configuration.q_min), std_vec_to_eigen_vector(robot_driver_ros_configuration.q_max)}; + robot_driver_franka -> set_joint_limits(joint_limits); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Instantiating RobotDriverROS."); sas::RobotDriverROS robot_driver_ros(node, robot_driver_franka,