From 5138ecab822ab2132dc04b71a3e081b10c9d26a7 Mon Sep 17 00:00:00 2001 From: Felix Mauch Date: Mon, 7 Oct 2019 10:42:54 +0200 Subject: [PATCH] Simplified calibration interface When showing this to collegues it turned out that this was quite complicated. I reduced the target definition to a simple filename, while documenting the package approach separately. --- README.md | 35 ++------- ur_calibration/README.md | 77 ++++++++++++------- .../launch/calibration_correction.launch | 10 +-- ur_calibration/src/calibration_correction.cpp | 47 ++++------- 4 files changed, 72 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 181f9a3..04d42a9 100644 --- a/README.md +++ b/README.md @@ -125,42 +125,19 @@ Each UR robot is calibrated inside the factory giving exact forward and inverse make use of this in ROS, you first have to extract the calibration information from the robot. Though this step is not necessary, to control the robot using this driver, it is highly recommended -to do so, as endeffector positions might be off in the magnitude of centimeters. +to do so, as otherwise endeffector positions might be off in the magnitude of centimeters. For this, there exists a helper script: $ roslaunch ur_calibration calibration_correction.launch \ - robot_ip:= \ - robot_name:= \ - output_package_name:=ur_calibration \ - subfolder_name:=etc + robot_ip:= target_filename:="${HOME}/my_robot_calibration.yaml" +For the parameter `robot_ip` insert the IP address on which the ROS pc can reach the robot. As +`target_filename` provide an absolute path where the result will be saved to. -As soon as you see the output: - - [ INFO] [1560953586.352160902]: Calibration correction done - -you can exit the roslaunch by bressing `CTRL+C`. - - -For the parameter **** insert the ip on which the ROS pc can reach the robot. The -**** is an arbitrary name you can give to the robot. It is recommended, to choose a unique -name that can be easily matched to the physical robot. - -The resulting yaml file is stored in the package specified in the **output_package_name** parameter -inside the folder **subfolder_name** with the name **robot_name***_calibration.yaml*. The parameter -**subfolder_name** is optional and defaults to *etc* if not given. - - -In the example above, we use the **ur_calibration** package from this repository. This won't work, -if you use a binary installation of this driver. In that case please create a new ROS package (before performing the calibration) by -going to your catkin_workspace's src folder and calling: - - catkin_create_pkg my_calibrations - -For further information on the calibration extraction, please see the [documentation of package -`ur_calibration`](ur_calibration/README.md). +We recommend keeping calibrations for all robots in your organization in a common package. See the +[package's documentation](ur_calibration/README.md) for details. #### Quick start Once the driver is built and the **externalcontrol** URCap is installed on the robot, you are good diff --git a/ur_calibration/README.md b/ur_calibration/README.md index e2e0544..f1fb47d 100644 --- a/ur_calibration/README.md +++ b/ur_calibration/README.md @@ -13,37 +13,60 @@ to do so, as end effector positions might be off in the magnitude of centimeters This node extracts calibration information directly from a robot, calculates the URDF correction and saves it into a .yaml file. -With the parameters explained below calibration will be saved inside -```bash -//_calibration.yaml -``` - - -#### Helper script In the launch folder of the ur_calibration package is a helper script: - $ roslaunch ur_calibration calibration_correction.launch \ - robot_ip:= \ - robot_name:= \ - output_package_name:=ur_calibration \ - subfolder_name:=etc +```bash +$ roslaunch ur_calibration calibration_correction.launch \ +robot_ip:= target_filename:="${HOME}/my_robot_calibration.yaml" +``` -For the parameter **** insert the ip on which the ROS pc can reach the robot. The -**** is an arbitrary name you can give to the robot. It is recommended, to choose a unique -name that can be easily matched to the physical robot. - -As soon as you see the output +For the parameter `robot_ip` insert the IP address on which the ROS pc can reach the robot. As +`target_filename` provide an absolute path where the result will be saved to. - [ INFO] [1560953586.352160902]: Calibration correction done +## Creating a calibration / launch package for all local robots +When dealing with multiple robots in one organization it might make sense to store calibration data +into a package dedicated to that purpose only. To do so, create a new package (if it doesn't already +exist) -you can exit the roslaunch by pressing `CTRL+C`. - - -#### Prerequisites for binary installation -In the example above, we use the **ur_calibration** package from this repository. This won't work, -if you use a binary installation of this driver. In that case please create a new ROS package -by going to your catkin_workspace's src folder and calling: +```bash +# Replace your actual catkin_ws folder +$ cd /src +$ catkin_create_pkg example_organization_ur_launch ur_rtde_driver \ +-D "Package containing calibrations and launch files for our UR robots." +# Create a skeleton package +$ mkdir -p example_organization_ur_launch/etc +$ mkdir -p example_organization_ur_launch/launch +``` - catkin_create_pkg my_calibrations +We can use the new package to store the calibration data in that package. We recommend naming each +robot individually, e.g. *ex-ur10-1*. -It is recommended to adapt the new package's *package.xml* with a meaningful description. +```bash +$ roslaunch ur_calibration calibration_correction.launch \ +robot_ip:= \ +target_filename:="$(rospack find example_organization_ur_launch)/etc/ex-ur10-1_calibration.yaml" +``` + +To make life easier, we create a launchfile for this particular robot. We base it upon the +respective launchfile in the driver: + +```bash +# Replace your actual catkin_ws folder +$ cd /src/example_organization_ur_launch/launch +$ roscp ur_rtde_driver ur10_bringup.launch ex-ur10-1.launch +``` + +Next, modify the parameter section of the new launchfile to match your actual calibration: + +```xml + + + +``` + +Then, anybody cloning this repository can startup the robot simply by launching + +```bash +$ roslaunch example_organization_ur_launch ex-ur10-1.launch +``` diff --git a/ur_calibration/launch/calibration_correction.launch b/ur_calibration/launch/calibration_correction.launch index ae2f982..54315d4 100644 --- a/ur_calibration/launch/calibration_correction.launch +++ b/ur_calibration/launch/calibration_correction.launch @@ -1,14 +1,10 @@ - - - - + + - - - + diff --git a/ur_calibration/src/calibration_correction.cpp b/ur_calibration/src/calibration_correction.cpp index a804e53..986ef1e 100644 --- a/ur_calibration/src/calibration_correction.cpp +++ b/ur_calibration/src/calibration_correction.cpp @@ -60,33 +60,20 @@ class CalibrationCorrection public: CalibrationCorrection(const ros::NodeHandle& nh) : nh_(nh) { - subfolder_ = nh_.param("subfolder_name", "etc"); std::string output_package_name; try { // The robot's IP address robot_ip_ = getRequiredParameter("robot_ip"); - // Name with which the robot will be referenced. Will be used for the filename the calibration - // data is stored in. This can be any arbitrary name. If left empty, the robot's serial number - // will be used. - robot_name_ = getRequiredParameter("robot_name"); - - // The resulting parameter file will be stored inside - // //_calibration.yaml - output_package_name = getRequiredParameter("output_package_name"); + // The target file where the calibration data is written to + output_filename_ = getRequiredParameter("output_filename"); } catch (const ParamaterMissingException& e) { ROS_FATAL_STREAM(e.what()); exit(1); } - package_path_ = ros::package::getPath(output_package_name); - if (package_path_ == "") - { - ROS_FATAL_STREAM("Could not find package " << output_package_name << ". Cannot save output file there."); - exit(1); - } } virtual ~CalibrationCorrection() = default; @@ -118,26 +105,20 @@ public: return false; } - ROS_INFO_STREAM("Writing calibration data"); - fs::path dst_path = fs::path(package_path_) / fs::path(subfolder_); + fs::path out_path = fs::complete(output_filename_); + + fs::path dst_path = out_path.parent_path(); if (!fs::exists(dst_path)) { - try - { - fs::create_directory(dst_path); - } - catch (const boost::filesystem::filesystem_error& e) - { - ROS_ERROR_STREAM("Could not create " << dst_path << ". Reason: " << e.what()); - return false; - } + ROS_ERROR_STREAM("Parent folder " << dst_path << " does not exist."); + return false; } - fs::path output_filename = dst_path / fs::path(robot_name_ + "_calibration.yaml"); - if (fs::exists(output_filename)) + ROS_INFO_STREAM("Writing calibration data to " << out_path); + if (fs::exists(output_filename_)) { - ROS_WARN_STREAM("Output file " << output_filename << " already exists. Overwriting."); + ROS_WARN_STREAM("Output file " << output_filename_ << " already exists. Overwriting."); } - std::ofstream file(output_filename.string()); + std::ofstream file(output_filename_); if (file.is_open()) { file << *calibration_data_; @@ -147,7 +128,7 @@ public: ROS_ERROR_STREAM("Failed writing the file. Do you have the correct rights?"); return false; } - ROS_INFO_STREAM("Wrote output to " << output_filename); + ROS_INFO_STREAM("Wrote output."); return true; } @@ -171,9 +152,7 @@ private: ros::NodeHandle nh_; std::string robot_ip_; - std::string robot_name_; - std::string package_path_; - std::string subfolder_; + std::string output_filename_; std::unique_ptr calibration_data_; };