<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE article PUBLIC "-//NLM//DTD Journal Publishing DTD v2.3 20070202//EN" "journalpublishing.dtd"><article xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:mml="http://www.w3.org/1998/Math/MathML" article-type="research-article"><front><journal-meta><journal-id journal-id-type="publisher-id">Front. Robot. AI</journal-id><journal-title>Frontiers in Robotics and AI</journal-title><abbrev-journal-title abbrev-type="pubmed">Front. Robot. AI</abbrev-journal-title><issn pub-type="epub">2296-9144</issn><publisher><publisher-name>Frontiers Media S.A.</publisher-name></publisher></journal-meta><article-meta><article-id pub-id-type="publisher-id">304630</article-id><article-id pub-id-type="doi">10.3389/frobt.2018.00046</article-id><article-categories><subj-group subj-group-type="heading"><subject>Robotics and AI</subject><subj-group><subject>Code</subject></subj-group></subj-group></article-categories><title-group><article-title>Markerless Eye-Hand Kinematic Calibration on the iCub Humanoid Robot</article-title></title-group><contrib-group><contrib corresp="yes" contrib-type="author"><name><surname>Vicente</surname><given-names>Pedro</given-names></name><uri xlink:href="http://loop.frontiersin.org/people/245917"/><xref ref-type="aff" rid="aff1"><sup>1</sup></xref><xref ref-type="corresp" rid="cor1"><sup>&#x002A;</sup></xref></contrib><contrib contrib-type="author"><name><surname>Jamone</surname><given-names>Lorenzo</given-names></name><uri xlink:href="https://loop.frontiersin.org/people/31029"/><xref ref-type="aff" rid="aff1"><sup>1</sup></xref><xref ref-type="aff" rid="aff2"><sup>2</sup></xref></contrib><contrib contrib-type="author"><name><surname>Bernardino</surname><given-names>Alexandre</given-names></name><uri xlink:href="http://loop.frontiersin.org/people/158486"/><xref ref-type="aff" rid="aff1"><sup>1</sup></xref></contrib><aff id="aff1"><sup>1</sup><institution>Institute for Systems and Robotics, Instituto Superior T&#x00E9;cnico, Universidade de Lisboa</institution>, <addr-line>Lisbon</addr-line>, <country>Portugal</country></aff><aff id="aff2"><sup>2</sup><institution>ARQ (Advanced Robotics at Queen Mary),&#x00A0;School of Electronic Engineering and Computer Science, Queen Mary University of London</institution>, <addr-line>London</addr-line>, <country>United Kingdom</country></aff></contrib-group><author-notes><fn fn-type="edited-by"><p>Edited by: Giorgio Metta, Fondazione Istituto Italiano di Technologia, Italy</p></fn><fn fn-type="edited-by"><p>Reviewed by: Claudio Fantacci, Fondazione Istituto Italiano di Technologia, Italy; Hyung Jin Chang, Imperial College London, United Kingdom</p></fn><corresp id="cor1">&#x002A;Pedro Vicente, <email>pvicente@isr.tecnico.ulisboa.pt</email></corresp><fn fn-type="other" id="fn001"><p>Specialty section: This article was submitted to Humanoid Robotics, a section of the journal Frontiers in Robotics and AI</p></fn></author-notes><pub-date pub-type="epub"><day>12</day><month>06</month><year>2018</year></pub-date><pub-date pub-type="collection"><year>2018</year></pub-date><volume>5</volume><elocation-id>46</elocation-id><history><date date-type="received"><day>21</day><month>08</month><year>2017</year></date><date date-type="accepted"><day>06</day><month>04</month><year>2018</year></date></history><permissions><copyright-statement>Copyright &#x00A9; 2018 Vicente, Jamone and Bernardino</copyright-statement><copyright-year>2018</copyright-year><copyright-holder>Vicente, Jamone and Bernardino</copyright-holder><license xlink:href="http://creativecommons.org/licenses/by/4.0/"><p>This is an open-access article distributed under the terms of the <uri xlink:href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution License (CC BY)</uri>. The use, distribution or reproduction in other forums is permitted, provided the original author(s) and the copyright owner are credited and that the original publication in this journal is cited, in accordance with accepted academic practice. No use, distribution or reproduction is permitted which does not comply with these terms.</p></license></permissions><abstract><p>Humanoid robots are resourceful platforms and can be used in diverse application scenarios. However, their high number of degrees of freedom (<italic>i.e.</italic>, moving arms, head and eyes) deteriorates the precision of eye-hand coordination. A good kinematic calibration is often difficult to achieve, due to several factors, <italic>e.g.</italic>, unmodeled deformations of the structure or backlash in the actuators. This is particularly challenging for very complex robots such as the iCub humanoid robot, which has 12 degrees of freedom and cable-driven actuation in the serial chain from the eyes to the hand. The exploitation of real-time robot sensing is of paramount importance to increase the accuracy of the coordination, for example, to realize precise grasping and manipulation tasks. In this code paper, we propose an online and markerless solution to the eye-hand kinematic calibration of the iCub humanoid robot. We have implemented a sequential Monte Carlo algorithm estimating kinematic calibration parameters (joint offsets) which improve the eye-hand coordination based on the proprioception and vision sensing of the robot. We have shown the usefulness of the developed code and its accuracy on simulation and real-world scenarios. The code is written in C++ and CUDA, where we exploit the GPU to increase the speed of the method. The code is made available online along with a Dataset for testing purposes.</p></abstract><kwd-group><kwd>code:C++</kwd><kwd>humanoid robot</kwd><kwd>markerless</kwd><kwd>hand pose estimation</kwd><kwd>sequential monte carlo parameter estimation</kwd><kwd>kinematic calibration</kwd></kwd-group><counts><fig-count count="3"/><table-count count="0"/><equation-count count="3"/><ref-count count="13"/><page-count count="10"/><word-count count="6132"/></counts></article-meta></front><body><sec id="s1" sec-type="intro"><title>1. Introduction and Related Work</title><p>An intelligent and autonomous robot must be robust to errors on its perceptual and motor systems to reach and grasp an object with great accuracy. The classical solution adopted by industrial robots rely on a precise calibration of the mechanics and sensing systems in controlled environments, where sub-millimeter accuracy can be achieved. However, a new emerging market is targeting consumer robots for collaboration with humans in more general scenarios. These robots cannot achieve high degrees of mechanical accuracy, due to (1) the use of lighter and flexible materials, compliant controllers for safe human-robot interaction, and (2) lower sensing precision due to varying environmental conditions. Indeed, humanoid robots, with complex kinematic chains, are among the most difficult platforms to calibrate and model properly with the precision required to reach and/or grasp objects. A small error in the beginning of the kinematic chain can generate a huge mismatch between the target location (usually coming from vision sensing) and the actual 6D end-effector pose.</p><p>Eye-hand calibration is a common problem in robotic systems that several authors tried to solve exploiting vision sensing [e.g., <xref ref-type="bibr" rid="B6">Gratal et al. (2011)</xref>; <xref ref-type="bibr" rid="B4">Fanello et al. (2014)</xref>; <xref ref-type="bibr" rid="B3">Garcia Cifuentes et al. (2017)</xref>; <xref ref-type="bibr" rid="B5">Fantacci et al. (2017)</xref>]<xref ref-type="fn" rid="FN1"><sup>1</sup></xref>.</p></sec><sec id="s2"><title>2. Proposed Solution</title><p>In this code paper, we propose a markerless hand pose estimation software for the iCub humanoid robot [<xref ref-type="bibr" rid="B10">Metta et al. (2010)</xref>] along with an eye-hand kinematic calibration. We exploit the 3D CAD model of the robot embedded in a game engine, which works as the robot&#x2019;s internal model. This tool is used to generate multiple hypotheses of the hand pose and compare them with the real visual perception. By using the information extracted from the robot motor encoders, we generate hypotheses of the hand pose and its appearance in the cameras, that are combined with the actual appearance of the hand in the real images, using particle filtering, a sequential Monte Carlo method. The best hypothesis of the 6D hand pose is used to estimate the corrective terms (joint offsets) to update the robot kinematic model. The visual based estimation of the hand pose is used as an input, together with the proprioception, to continuously calibrate (<italic>i.e.</italic>, update) the robot internal model. At the same time, the internal model is used to provide better hypotheses for the hand position in the camera images, therefore enhancing the robot perception. The two processes help each other, and the final outcome is that we can keep the internal model calibrated and obtain a good estimation of the hand pose, without using specialized visual markers on the hand.</p><p>The original research work [<xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref> and <xref ref-type="bibr" rid="B13">Vicente et al. (2016b)</xref>] contains: (1) a complete motivation from the developmental psychology point of view and theoretical details of the estimation process, and (2) technical details on the interoperability between the several libraries and the GPGPU approach for an increased boost on the method speed, respectively.</p><p>The present manuscript is a companion and complementary code paper of the method presented in <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref>. We will not describe with full details the theoretical perspective of our work, instead we will focus on the resulting software system connecting the code with the solution proposed in <xref ref-type="bibr" rid="B13">Vicente et al., 2016b</xref>. Moreover, the objective of this publication is to give a hands-on perspective on the implemented software which could be used and extended by the research community.</p><p>The source code is available at <italic>the <bold>official GitHub code repository</bold></italic>:</p><preformat><uri xlink:href="https://github.com/vicentepedro/Online-Body-Schema-Adaptation">https://github.com/vicentepedro/Online-Body-Schema-Adaptation</uri>&#x00A0;</preformat><p>and the documentation on the <italic><bold>Online Documentation page</bold></italic>:</p><preformat><uri xlink:href="http://vicentepedro.github.com/Online-Body-Schema-Adaptation">http://vicentepedro.github.com/Online-Body-Schema-Adaptation</uri></preformat><p>We use a Sequential Monte Carlo parameter estimation method to estimate the calibration error <italic>&#x03B2;</italic> in the 7D robot&#x2019;s joint space corresponding to the kinematic chain going from each eye to the end-effector. Let us consider:</p><p><disp-formula id="E1"><label> (1) </label><mml:math id="M11"><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mrow><mml:mi>&#x03B8;</mml:mi><mml:mo>=</mml:mo><mml:msup><mml:mi>&#x03B8;</mml:mi><mml:mrow><mml:mi>r</mml:mi></mml:mrow></mml:msup><mml:mo>+</mml:mo><mml:mi>&#x03B2;</mml:mi></mml:mrow></mml:mstyle></mml:math></disp-formula></p><p>where <italic>&#x03B8;<sup>r</sup></italic> are the real angles; <italic>&#x03B8;</italic> are the measured angles; <italic>&#x03B2;</italic> are joint offsets representing calibration errors. Given an estimate of the joint offsets (<inline-formula><mml:math id="M21"><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mrow><mml:mrow><mml:mover><mml:mi mathvariant="bold-italic">&#x03B2;</mml:mi><mml:mo mathvariant="bold" stretchy="false">&#x005E;</mml:mo></mml:mover></mml:mrow></mml:mrow></mml:mstyle></mml:math></inline-formula>), a better end-effector&#x2019;s pose can be retrieved using the forward kinematics.</p><p>One of the proposed solutions for using Sequential Monte Carlo methods for parameter estimation<xref ref-type="fn" rid="FN2"><sup>2</sup></xref> (<italic>i.e</italic>., the parameters <italic>&#x03B2;</italic> in our problem), is to introduce an artificial dynamics, changing from a static transition model <inline-formula><mml:math id="M22" display="block"><mml:semantics><mml:mrow><mml:mo>(</mml:mo><mml:msub><mml:mi>&#x3B2;</mml:mi><mml:mi>t</mml:mi></mml:msub><mml:mo>=</mml:mo><mml:msub><mml:mi>&#x3B2;</mml:mi><mml:mrow><mml:mi>t</mml:mi><mml:mo>&#x2212;</mml:mo><mml:mn>1</mml:mn></mml:mrow></mml:msub><mml:mo>)</mml:mo></mml:mrow></mml:semantics></mml:math></inline-formula> to a slowly time-varying one:</p><p><disp-formula id="E2"><label> (2) </label><mml:math id="M12"><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mrow><mml:msub><mml:mi>&#x03B2;</mml:mi><mml:mrow><mml:mi>t</mml:mi></mml:mrow></mml:msub><mml:mo>=</mml:mo><mml:msub><mml:mi>&#x03B2;</mml:mi><mml:mrow><mml:mi>t</mml:mi><mml:mo>&#x2212;</mml:mo><mml:mn>1</mml:mn></mml:mrow></mml:msub><mml:mo>+</mml:mo><mml:msub><mml:mtext>w</mml:mtext><mml:mrow><mml:mi>t</mml:mi></mml:mrow></mml:msub></mml:mrow></mml:mstyle></mml:math></disp-formula></p><p>where w<italic><sub>t</sub></italic> is an artificial dynamic noise that decreases when <italic>t</italic> increases.</p></sec><sec id="s3"><title>3. Software Design and Architecture Principles</title><p>The software design and architecture for implementing the eye-hand kinematic calibration solution has the following requirements: (1) the software should be able to run in real-time since the objective is to calibrate the robot during a normal operating behaviour, and (2) it should be possible to run the algorithm in a distributed way, <italic>i.e.</italic>, run parts of the algorithm in several computers in order to increase computation power.</p><p>The authors decided to implement the code in <monospace>C</monospace><monospace>++&#x00A0;</monospace>in order to cope with the real-time constraint, and to exploit the YARP middleware [<xref ref-type="bibr" rid="B9">Metta et al. (2006)</xref>] to distribute the components of the algorithm in more than one machine.</p><p>The source code for these modules are available at <italic>the <bold>official GitHub code repository</bold></italic> (check section 2).</p><p>The code is divided into three logical components: (1) the hand pose estimation (section 4.1), (2) the Robot&#x2019;s Internal Model generator (section 4.2), and (3) the likelihood assessment (section 4.3), which are implemented, respectively, at the following repository locations:</p><list list-type="bullet"><list-item><p><preformat><monospace>modules/handPoseEstimation</monospace></preformat></p><list list-type="bullet"><list-item><p><preformat><monospace>include/handPoseEstimationModule.h</monospace></preformat></p></list-item><list-item><p><preformat><monospace>src/handPoseEstimationMain.cpp</monospace></preformat></p></list-item><list-item><p><preformat><monospace>src/handPoseEstimationModule.cpp</monospace></preformat></p></list-item></list></list-item><list-item><p><preformat><monospace>modules/internalmodel</monospace></preformat></p><list list-type="bullet"><list-item><p><preformat><monospace>icub-internalmodel-rightA-cam-Lisbon.exe</monospace></preformat></p></list-item><list-item><p><preformat><monospace>icub-internalmodel-leftA-cam-Lisbon.exe</monospace></preformat></p></list-item></list></list-item><list-item><p><preformat><monospace>modules/likelihodAssessment</monospace></preformat></p><list list-type="bullet"><list-item><p><preformat><monospace>src/Cuda_Gl.cu</monospace></preformat></p></list-item><list-item><p><preformat><monospace>src/likelihood.cpp</monospace></preformat></p></list-item></list></list-item></list><p>The software architecture implementing the proposed eye-hand calibration solution can be seen in <xref ref-type="fig" rid="F1">Figure 1</xref>. The first component - Hand Pose Estimation - is responsible for proposing multiple hypotheses according to the posterior distribution. We use a Sequential Monte Carlo parameter estimation method in our work [check <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref> Section 3.3 for further theoretical details]. The definitions of the functions presented in the architecture (<xref ref-type="fig" rid="F1">Figure 1</xref>) can be found in the <monospace>.cpp</monospace> and <monospace>.h</monospace> files and will be explained in detail in Section 4.1. The Hand Pose Estimation is OS independent and can run in any computer with the YARP library installed.</p><fig id="F1" position="float"><label>Figure 1</label><caption><p> Architecture of the software. The hand pose estimation component (<italic>handPoseEstimation</italic>) initiates the Sequential Monte Carlo parameter estimation method (<italic>initSMC</italic>) and waits for a start command from the user. The perception and proprioception (cameras and encoders) of the robot are received and the parameter estimation starts. The real image and the particles are sent (<italic>sendData</italic>) to the Robot&#x2019;s internal Model (<italic>icub-internalmodel-rightA-cam-Lisbon.exe</italic> or<italic> icub-internalmodel-leftA-cam-Lisbon.exe</italic>) in order to generate the hypotheses. The likelihood assessment of each hypothesis is calculated using a Dynamic Link Library (DLL) file inside the Robot&#x2019;s internal model. The likelihood of each particle is saved and a Kernel Density estimation is performed to calculate the best calibration parameters. The Resampling step is performed and a new set of particles are saved for the next iteration of the Sequential Monte Carlo parameters estimation.</p></caption><graphic xlink:href="frobt-05-00046-g001.tif"/></fig><p>The second component - Robot&#x2019;s Internal Model - generates hypotheses of the hand pose based on the 3D CAD model of the robot and was build using the game engine Unity<sup>&#x00AE;</sup>. There are two versions of the internal model on the repository. One for the right-hand (<monospace>rightA</monospace>) and another one for the left-hand (<monospace>leftA</monospace>). Our approach was to divide the two internal models since we have separated calibration parameters for the head-left-arm and for the head-right-hand kinematic chains. The Unity platform was chosen to develop the internal model of the robot since it is able to generate a high number of <italic>frames per second</italic> on the GPU even for complex graphics models. The scripting component of the Unity game engine was programmed in <monospace>C#</monospace>.&#x00A0;The bindings of YARP for <monospace>C#</monospace> were used in order to facilitate the internal model generator to communicate with the other components of the system. This component is OS-dependent and only runs on Windows and the build version available on the repository does not require a paid license of Unity Pro.</p><p>Finally, the likelihood assessment is called inside the Robot&#x2019;s Internal Model as a Dynamic Link Library and exploits GPGPU programming to compare the real perception with the multiple generated hypotheses. The GPGPU programming, using the CUDA library [<xref ref-type="bibr" rid="B11">Nickolls et al. (2008)</xref>], allows the algorithm to run in quasi-real-time. The <monospace>.cpp</monospace> file contains the likelihood computation method, and the <monospace>.cu</monospace> the GPGPU program.</p><p>Our eye-hand calibration solution exploits vision sensing to reduce the error between the perception and the simulated hypotheses, the OpenCV library [<xref ref-type="bibr" rid="B2">Bradski (2000)</xref>] with CUDA enabled capabilities [<xref ref-type="bibr" rid="B11">Nickolls et al. (2008)</xref>] was chosen to exploit computer vision algorithms and run them in real-time.</p><p>The interoperability between the OpenCV, CUDA and OpenGL libraries was studied in <xref ref-type="bibr" rid="B13">Vicente et al. (2016b)</xref>. In the particular case of the iCub humanoid robot [<xref ref-type="bibr" rid="B10">Metta et al. (2010)</xref>], and to suit within the YARP and iCub architectures, we encapsulated part of the code in an RFModule<xref ref-type="fn" rid="FN3"><sup>3</sup></xref> class structure and use YARP buffered ports<xref ref-type="fn" rid="FN4"><sup>4</sup></xref> and RPC services<xref ref-type="fn" rid="FN5"><sup>5</sup></xref> for communications and user interface (Check section 5.2.3). The hand pose estimation module allows the user to send requests to the algorithm which follows an event-driven architecture: where for each new incoming information from the robot (cameras and encoders) a new iteration of the Sequential Monte Carlo parameter estimation is performed.</p></sec><sec id="s4"><title>4. Code Description</title><sec id="s4-1"><title>4.1. Hand Pose Estimation Module</title><sec id="s4-1-1"><title>4.1.1. Initializing the Sequential Monte Carlo parameter estimation - initSMC Function</title><p>In the function <italic>initSMC</italic> we initialize the variables of the Sequential Monte Carlo parameter estimation, <italic>i.e.</italic>, the initial distribution <italic>p</italic>(<italic>&#x03B2;</italic><sub>0</sub>) [Eq. (10) in <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref>], and the initial artificial dynamic noise. The <xref ref-type="other" rid="C1">Listings 1</xref> contains the <italic>initSMC</italic> function where some of the variables (in red) are parametrized at initialization time (check sub-section 5.2.1 for more details on the initialization parameters). We use a random seed generated according with the current time and initialize each angular offset with a Gaussian distribution: <italic>N</italic>(initialMean; initialStdDev).</p><boxed-text id="C1" position="float"><label>Listing 1&#x00A0;</label><title>HandPoseEstimationModule::initSMC Function. Defined in handPoseEstimationModule.cpp</title><p><preformat>1.&#x00A0;bool handPoseEstimationModule :: initSMC ( )</preformat></p><p><preformat><named-content content-type="line-number">2.&#x2003;</named-content>&#x007B;</preformat></p><p><preformat><named-content content-type="line-number">4.&#x2003;&#x2003;</named-content>// Generate random particles</preformat></p><p><preformat><named-content content-type="line-number">5.&#x2003;&#x2003;</named-content>srand((unsigned int)time(0)); // make sure random numbers are really random.</preformat></p><p><preformat><named-content content-type="line-number">6.&#x2003;&#x2003;</named-content>rngState = cvRNG(rand());</preformat></p><p><preformat><named-content content-type="line-number">7.&#x2003;&#x2003;</named-content>// initialize Beta1</preformat></p><p><preformat><named-content content-type="line-number">8.&#x2003;&#x2003;</named-content>cvRandArr(&#x0026;rngState, particles 1, CV_RAND_NORMAL, cvScalar(<bold>initialMean</bold>), cvScalar(<bold>initialStdDev</bold>));</preformat></p><p><preformat><named-content content-type="line-number">9.&#x2003;&#x2003;</named-content>&#x2026; &#x2026; // similar for particles2 to particles6</preformat></p><p><preformat><named-content content-type="line-number">10.&#x2003;&#x2003;</named-content>cvRandArr (&#x0026;rngState, particles7, CV_RAND_NORMAL, cvScalar(<bold>initialMean</bold>) , cvScalar(<bold>initialStdDev</bold>));</preformat></p><p><preformat><named-content content-type="line-number">11.&#x2003;&#x2003;</named-content>// Artificial Noise Initialization </preformat></p><p><preformat><named-content content-type="line-number">12.&#x2003;&#x2003;</named-content>artifNoiseStdDev = <bold>initialArtificialNoiseStdDev</bold>;</preformat></p><p><preformat><named-content content-type="line-number">13.&#x2003;</named-content>&#x007D;</preformat></p></boxed-text></sec><sec id="s4-1-2"><title>4.1.2 Read Image, Read Encoders, ProcessImages and SendData</title><p>The left and right images along with the head and arm encoders are read at the same time to ensure consistency between the several sensors.</p><p>The reading and processing procedure of the images are defined inside the function:</p><preformat>handPoseEstimationModule::updateModule()&#x00A0;</preformat><p>that can be found on the file:&#x00A0;</p><preformat>src/handPoseEstimationModule.cpp.</preformat><p>The function process&#x00A0;Images (see <xref ref-type="other" rid="C2">Listings 2</xref>) applies a Canny edge detector and a distance transform to both images separately. Moreover, the left and the right processed images are merged, <italic>i.e.</italic>, concatenated horizontally, in order to be compared to the generated hypotheses inside the Robot&#x2019;s internal model.</p><boxed-text id="C2" position="float"><label>Listing 2&#x00A0;</label><title>HandPoseEstimationModule::processImages. Defined in handPoseEstimationModule.cpp</title><preformat><named-content content-type="line-number">1.&#x00A0;</named-content>Mat handPoseEstimationModule :: processImages (Mat inputImage)</preformat><preformat><named-content content-type="line-number">2.&#x2003;</named-content>&#x007B;</preformat><preformat><named-content content-type="line-number">3.&#x2003;&#x2003;</named-content>Mat edges , dt Image; </preformat><preformat><named-content content-type="line-number">4.&#x2003;&#x2003;</named-content>cvtColor(inputImage, edges, CV_RGB2GRAY);</preformat><preformat><named-content content-type="line-number">5.&#x2003;&#x2003;</named-content>// Blur Image </preformat><preformat><named-content content-type="line-number">6.&#x2003;&#x2003;</named-content>blur(edges, edges, Size (3, 3));</preformat><preformat><named-content content-type="line-number">7.&#x2003;&#x2003;</named-content>Canny(edges, edges, 65, 3&#x002A;65,3); </preformat><preformat><named-content content-type="line-number">8.&#x2003;&#x2003;</named-content>threshold(edges, edges, 100,255,THRESH_BINARY_INV); // binary Image </preformat><preformat><named-content content-type="line-number">9.&#x2003;&#x2003;</named-content>distanceTransform(edges, dt Image, CV_DIST_L2, CV_DIST_MASK_5); </preformat><preformat><named-content content-type="line-number">10.&#x2003;&#x2003;</named-content>return dtImage;</preformat><preformat><named-content content-type="line-number">11.&#x2003;</named-content>&#x007D;</preformat></boxed-text><p>The Hand pose estimation module sends: (1) the pre-processed images, (2) the head encoders and (3) the arm encoders (<italic>&#x03B8;</italic>) along with the offsets (<italic>&#x03B2;</italic>) to the Robot&#x2019;s internal model<xref ref-type="fn" rid="FN6"><sup>6</sup></xref>. This procedure is defined inside the function:&#x00A0;</p><preformat>handPoseEstimationModule::runSMCIteration()</preformat></sec><sec id="s4-1-3"><title>4.1.3. Update Likelihood</title><p>The Hand Pose Estimation module receives the likelihood vector from the Robot&#x2019;s internal model and updates the likelihood value for each particle on the for-loop at line:</p><preformat>handPoseEstimationModule.cpp#L225</preformat></sec><sec id="s4-1-4"><title>4.1.4. Kernel Density Estimation</title><p>Although the state is represented at each time step as a distribution approximated by the weighted particles, our best guess for the angular offsets can be computed using a Kernel Density Estimation (KDE) to smooth the weight of the particles according to the information of neighbor particles, and choose the particle with the highest smoothed weight (<italic>&#x03C9;</italic>ʹ<sup>[<italic>i</italic>]</sup>) as our state estimate [Section 3.5 of <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref>].</p><p>The implementation of the KDE with a Gaussian kernel can be seen in <xref ref-type="other" rid="C3">Listings 3</xref>. The double for-loop implements the KDE accessing each particle (<italic>iParticle</italic>) and computing the influence of each neighbor (<italic>mParticle</italic>) according to the relative distance in the 7D-space between the two particles and the likelihood of the neighbor <italic>[cvmGet (particles, 7,mParticle)</italic>]. The parameters that can be fine-tuned are highlighted in red.</p><boxed-text id="C3" position="float"><label>Listing 3&#x00A0;</label><title>Kernel Density Estimation with Multivariate Normal Distribution Kernel: modules/handPoseEstimation/src/handPoseEstimationModule.cpp</title><preformat><named-content content-type="line-number">1.&#x00A0;</named-content>void handPoseEstimationModule :: kernelDensityEstimation ( )</preformat><preformat><named-content content-type="line-number">2.</named-content>&#x007B;</preformat><preformat><named-content content-type="line-number">3.&#x2003;</named-content>// Particle i&#x00A0;</preformat><preformat><named-content content-type="line-number">4.&#x2003;</named-content>double maxWeight = 0.0; </preformat><preformat><named-content content-type="line-number">5.&#x2003;</named-content>for (int iParticle = 0; iParticle &#x003C;n Particles; iParticle ++)&#x00A0;</preformat><preformat><named-content content-type="line-number">6.&#x2003;</named-content>&#x007B;</preformat><preformat><named-content content-type="line-number">7.&#x2003;&#x2003;</named-content>double sum1 = 0.0;</preformat><preformat><named-content content-type="line-number">8.&#x2003;&#x2003;</named-content>// Particle m </preformat><preformat><named-content content-type="line-number">9.&#x2003;&#x2003;</named-content>&#x00A0;for (int mParticle = 0; mParticle &#x003C;nParticles; mParticle++)</preformat><preformat><named-content content-type="line-number">10.&#x2003;&#x2003;</named-content>&#x007B;</preformat><preformat><named-content content-type="line-number">11.&#x2003;&#x2003;&#x2003;</named-content>double sum2 = 0.0; </preformat><preformat><named-content content-type="line-number">12.&#x2003;&#x2003;&#x2003;</named-content>if&#x00A0;( (float) cvmGet (particles, 7, mParticle) &#x003E; 0 )</preformat><preformat><named-content content-type="line-number">13.&#x2003;&#x2003;&#x2003;</named-content>&#x007B;</preformat><preformat><named-content content-type="line-number">14.&#x2003;&#x2003;&#x2003;&#x2003;</named-content>// Beta 0.. to..6</preformat><preformat><named-content content-type="line-number">15.&#x2003;&#x2003;&#x2003;&#x2003;</named-content>for&#x00A0;(int joint = 0; joint &#x003C;7; joint ++)</preformat><preformat><named-content content-type="line-number">16.&#x2003;&#x2003;&#x2003;&#x2003;</named-content>&#x007B;</preformat><preformat><named-content content-type="line-number">17.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;</named-content>// &#x007C;&#x007C; pi&#x2013;pj &#x007C;&#x007C;<sup>&#x005E;</sup>2&#x00A0;/&#x00A0;KDEStdDev <sup>&#x005E;</sup>2</preformat><preformat><named-content content-type="line-number">18.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;</named-content>sum2 += pow( ((float) cvmGet (particles, joint, mParticle)&#x2013;(float) &#x00A0;cvmGet (particles, joint, iParticle )) , 2) / pow(<bold>KDEStdDev</bold>, 2); // &#x00A0;Multivariate normal distribution</preformat><preformat><named-content content-type="line-number">19.&#x2003;&#x2003;&#x2003;&#x2003;</named-content>&#x007D;</preformat><preformat><named-content content-type="line-number">20.&#x2003;&#x2003;&#x2003;&#x2003;</named-content>sum1 += s t d :: exp(&#x2013;sum2/( 2) ) &#x002A;cvmGet (particles, 7 , &#x00A0;mParticle);</preformat><preformat><named-content content-type="line-number">21.&#x2003;&#x2003;&#x2003;</named-content>&#x007D;</preformat><preformat><named-content content-type="line-number">22.&#x2003;&#x2003;</named-content>&#x007D;</preformat><preformat><named-content content-type="line-number">23.&#x2003;&#x2003;</named-content>sum1 = sum1 / ( nParticles&#x002A;sqrt (pow(2&#x002A;M_PI, 1) &#x002A;pow(<bold>KDEStdDev</bold>, &#x00A0;7) ) );&#x00A0;</preformat><preformat><named-content content-type="line-number">24.&#x2003;&#x2003;</named-content>double weight = <bold>alphaKDE</bold>&#x002A;sum1 + cvmGet (particles, 7 , &#x00A0;iParticle);&#x00A0;</preformat><preformat><named-content content-type="line-number">25.&#x2003;&#x2003;</named-content>if&#x00A0;(weight&#x003E;maxWeight)</preformat><preformat><named-content content-type="line-number">26.&#x2003;&#x2003;</named-content>&#x007B; </preformat><preformat><named-content content-type="line-number">27.&#x2003;&#x2003;&#x2003;</named-content>maxWeightIndex= iParticle; // save the best particle index</preformat><preformat><named-content content-type="line-number">28.&#x2003;&#x2003;</named-content>&#x007D;</preformat><preformat><named-content content-type="line-number">29.&#x2003;</named-content>&#x007D;</preformat><preformat><named-content content-type="line-number">30.</named-content>&#x007D;</preformat></boxed-text></sec><sec id="s4-1-5"><title>4.1.5. Best Hypothesis</title><p>The best hypothesis, computed using the KDE, is sent through a YARP buffered port from the module after <italic>N</italic> iterations. The port has the following name:</p><preformat>/hpe/bestOffsets:o</preformat><p>The parameter <italic>N</italic> (the number of elapsed iterations before sending the estimated angular offsets) can be changed by the user at initialization using the <monospace>minIteration</monospace> parameter (check Section 5.2.1 for more details) and the objective is to ensure the filter convergence before using the estimate (<italic>e.g.</italic>, to control the robot). This is an important parameter since in the initial stages the estimation can jump a lot from an iteration to the next one (before converging to a more stable solution).</p></sec><sec id="s4-1-6"><title>4.1.6. Update Artificial Noise, Resampling and New Particles</title><p>The artificial noise is updated according to the maximum likelihood criteria. See the pseudo-code on <xref ref-type="other" rid="C4">Listings 4</xref>, which corresponds to line 230 to 254 in the file:</p><preformat>src/handPoseEstimationModule.cpp</preformat><boxed-text id="C4" position="float"><label>Listing 4&#x00A0;</label><title>Pseudo Code updating artificial noise corresponding to part of the function runSMCIteration() within file: <italic>src/handPoseEstimationModule.cpp</italic></title><preformat><named-content content-type="line-number">1.&#x00A0;</named-content>IN handPoseEstimationModule :: runSMCIteration ( )</preformat><preformat><named-content content-type="line-number">2.</named-content>&#x007B;</preformat><preformat><named-content content-type="line-number">3.&#x2003;</named-content>&#x2026;</preformat><preformat><named-content content-type="line-number">4.&#x2003;</named-content>// Resampling or not Resampling. That&#x2019;s the Question </preformat><preformat><named-content content-type="line-number">5.&#x2003;</named-content>if (maxLikelihood &#x003E;<bold>minimumLikelihood</bold>) &#x007B; </preformat><preformat><named-content content-type="line-number">6.&#x2003;&#x2003;</named-content>systematic_resampling ( ); // Check Section Resampling and New Particles</preformat><preformat><named-content content-type="line-number">7.&#x2003;&#x2003;</named-content>reduceArtificialNoise ( );</preformat><preformat><named-content content-type="line-number">8.&#x2003;</named-content>&#x007D; </preformat><preformat><named-content content-type="line-number">9.&#x2003;</named-content>else &#x007B; // do not apply resampling stage </preformat><preformat><named-content content-type="line-number">10.&#x2003;&#x2003;</named-content>increaseArtificialNoise ( );</preformat><preformat><named-content content-type="line-number">11.&#x2003;</named-content>&#x007D; </preformat><preformat><named-content content-type="line-number">12.&#x2003;</named-content>if (artifNoiseStdDev &#x003E; <bold>upperBoundNoise</bold>) &#x007B; // upperbound of artificial noise</preformat><preformat><named-content content-type="line-number">13.&#x2003;&#x2003;</named-content>artifNoiseStdDev = <bold>upperBoundNoise</bold>;</preformat><preformat><named-content content-type="line-number">14.&#x2003;</named-content>&#x007D;</preformat><preformat><named-content content-type="line-number">15.&#x2003;</named-content>if (artifNoiseStdDev &#x003C; <bold>lowerBoundNoise</bold>) &#x007B; // lowerbound of artificial noise </preformat><preformat><named-content content-type="line-number">16.&#x2003;&#x2003;</named-content>artifNoiseStdDev = <bold>lowerBoundNoise</bold>;</preformat><preformat><named-content content-type="line-number">17.&#x2003;</named-content>&#x007D; </preformat><preformat><named-content content-type="line-number">18.&#x2003;</named-content>addNoiseToEachSample ()</preformat><preformat><named-content content-type="line-number">19.</named-content>&#x007D;</preformat></boxed-text><p>We update the artificial noise according to the maximum likelihood, <italic>i.e.</italic>, if the maximum likelihood is below a certain threshold (<italic>minimumLikelihood</italic>), we do not perform the resampling step and we increase the artificial noise. On the other hand, if the maximum likelihood is greater than the threshold we apply the resampling and decrease the artificial noise. The objective is to prevent the particles to become trapped in a &#x201C;local maximum&#x201D; since the current best solution is not worthy of resampling the particles. Indeed, this approach will force them to explore the state space.</p><p>The trade-off between exploration and exploitation is measured according to the maximum likelihood in each time step of the algorithm. The idea is to exploit the low number of particles in a clever way. Moreover, the upper and lower bound ensure, respectively, that: (1) the noise will not increase asymptotically and the samples will be spread over the 7D state-space and (2) the particles will not end-up all at the same value, which can happen when the random noise is Zero.</p><p>On the resampling stage, we use the systematic resampling strategy [check <xref ref-type="bibr" rid="B7">Hol et al. (2006)</xref>], which ensures that a particle with a weight greater than 1/<italic>M</italic> is always resampled, where <italic>M</italic> is the number of particles.</p></sec></sec><sec id="s4-2"><title>4.2. Robot&#x2019;s Internal Model Generator</title><p>The <xref ref-type="other" rid="C5">Listings 5</xref> shows the general architecture of the Robot&#x2019;s Internal Model Generator using pseudo-code.</p><boxed-text id="C5" position="float"><label>Listing 5&#x00A0;</label><title>Pseudo-Code Robot&#x0027;s internal model.</title><preformat><named-content content-type="line-number">1.&#x00A0;</named-content>InitRenderTextures ( ) // Initialization of the strutures to receive </preformat><preformat><named-content content-type="line-number">2.</named-content></preformat><preformat><named-content content-type="line-number">3.</named-content>for (each iteration) // for each iteration of the SMC</preformat><preformat><named-content content-type="line-number">4.</named-content>&#x007B; </preformat><preformat><named-content content-type="line-number">5.&#x2003;</named-content>waitForInput ( ); // wait for input vector with particles to be generated </preformat><preformat><named-content content-type="line-number">6.</named-content></preformat><preformat><named-content content-type="line-number">7.&#x2003;</named-content>for (each particle) &#x007B; </preformat><preformat><named-content content-type="line-number">8.&#x2003;&#x2003;</named-content>moveTheInternalModel ( ) // Change the robot&#x2019;s configuration</preformat><preformat><named-content content-type="line-number">9.&#x2003;&#x2003;</named-content>RenderAllucinatedImages ( ); // render left and right image on a render texture </preformat><preformat><named-content content-type="line-number">10.&#x2003;&#x2003;</named-content>nextFrame ( );</preformat><preformat><named-content content-type="line-number">11.&#x2003;</named-content>&#x007D;</preformat><preformat><named-content content-type="line-number">12.&#x2003;</named-content>// After 200 frames call DLL function</preformat><preformat><named-content content-type="line-number">13.&#x2003;</named-content>ComputeLikelihood (AllucinatedImages (200), RealImage) // Call the DLL function (CudaEdgeLikelihood) to compare the hypotheses with the real image.</preformat><preformat><named-content content-type="line-number">14.</named-content>&#x007D;</preformat></boxed-text><sec id="s4-2-1"><title>4.2.1. Initialization of the Render Textures</title><p>The render textures, which will be used to render the two camera images, are initialized for each particle for both left and right views of the scene.</p></sec><sec id="s4-2-2"><title>4.2.2. Generate Hypotheses</title><p>The hypotheses are generated on a frame-based approach, <italic>i.e.</italic>, we generate one hypothesis for each frame of the &#x201C;game&#x201D;. After we receive the vector with the 200 hypotheses to generate, we virtually move the robot to each of the configurations to be tested and record both images (left and right) in a renderTexture.</p><p>After the 200 generations, we call the likelihood assessment DLL function to perform the comparison between the real images and the generated hypotheses.</p><p>The available version of the Robot&#x2019;s internal model generator is an executable compiled and self-contained which works on Windows-based computers with the installed dependencies<xref ref-type="fn" rid="FN7"><sup>7</sup></xref>. Moreover, this does not require neither the Unity<sup>&#x00AE;</sup> Editor to be installed in the computer nor the Unity Pro license.</p><p>More details on the creation of the Unity<sup>&#x00AE;</sup> iCub Simulator for this project can be found in <xref ref-type="bibr" rid="B13">Vicente et al. (2016b)</xref> Sec. 5.2 - &#x201C;The Unity<sup>&#x00AE;</sup> iCub Simulator&#x201D;.</p></sec></sec><sec id="s4-3"><title>4.3. Likelihood Assessment Module</title><p>The likelihood assessment is based on the observation model defined in <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref> Section 3.4.2.</p><p>We exploit an edge-based extraction approach along with a distance transform algorithm computing the likelihood using the Chamfer matching distance [<xref ref-type="bibr" rid="B1">Borgefors and Bradski (1986)</xref>].</p><p>In our code, these quantities are computed in the GPU using the OpenCV and CUDA libraries, and the interoperability between these libraries and the OpenGL library. The solution adopted was to add the likelihood assessment as a <monospace>cpp</monospace> plugin called inside the internal model generator module. The likelihood.cpp file, particularly the function <italic>CudaEdgeLikelihood</italic>, is where the likelihood of each sample is computed. Part of the code of the likelihood function is shown and analysed in <xref ref-type="other" rid="C6">Listings 6</xref>. Up to the line 21 of the Listings 6, we exploit the interoperability between the libraries used (OpenGL, CUDA, OpenCV) and after line 21 we apply our likelihood metric using the functionality of the OpenCV library, where <italic>GgpuMat</italic> is the generated Image of the <italic>ith</italic> sample and GgpuMat_R is the real Distance Transform image. In line 35, the lambdaEdge is a parameter to tune the distance metric sensitivity, which is initialized at the value 25 in line 1 (corresponding to line 148 of the <monospace>C</monospace><monospace>++ </monospace>file)<xref ref-type="fn" rid="FN8"><sup>8</sup></xref>. When the generated image does not have edges (<italic>i.e.</italic>, the hand is not visible by the cameras), we force the likelihood of this particle to be almost zero (line 37 and 39, respectively). The maximum likelihood (<italic></italic><italic>i.e.</italic>, the value 1.0) is achieved when each entry of the result image is zero. This happen when every edge on the generated image match a zero distance on the distance transform image. The multiplication by 1,000 and the <italic>int</italic> cast in line 42 is used to send the likelihood as a int value (the inverse process is made in the internal model when it receives the likelihood vector) and it is one of the limitations of the current approach due to software limitations the authors could not send directly a double value between 0 and 1.</p><boxed-text id="C6" position="float"><label>Listing 6&#x00A0;</label><title>Likelihood Assessment: modules/likelihoodAssessment/src/likelihood.cpp</title><preformat><named-content content-type="line-number"> 1.&#x00A0;</named-content>int lambdaEdge = 25;</preformat><preformat><named-content content-type="line-number"> 2.&#x00A0;</named-content>// For each particle i &#x2013; line 149 modules / likelihoodAssessment / src / likelihood.cpp</preformat><preformat><named-content content-type="line-number"> 3.&#x00A0;</named-content>// Interopelability between the several libraries (OpenGL , CUDA, OpenCV) </preformat><preformat><named-content content-type="line-number"> 4.&#x2003;</named-content>gltex =(GLuint) (size_t) (ID[i]); // ID is a vector with pointers to the render textures </preformat><preformat><named-content content-type="line-number"> 5.&#x2003;</named-content>glBindTexture(GL_TEXTURE_2D, gltex);</preformat><preformat><named-content content-type="line-number"> 6.&#x2003;</named-content>GLint width, height, internalFormat; </preformat><preformat><named-content content-type="line-number"> 7.&#x2003;</named-content>glGetTexLevelParameteriv(GLTEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &#x0026;internalFormat); // get internal format type of GL texture </preformat><preformat><named-content content-type="line-number"> 8.&#x2003;</named-content>glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &#x0026;width); // get width of GL texture </preformat><preformat><named-content content-type="line-number"> 9.&#x2003;</named-content>glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &#x0026;height); // get height of GL texture </preformat><preformat><named-content content-type="line-number"> 10.</named-content></preformat><preformat><named-content content-type="line-number"> 11.&#x2003;</named-content>checkCudaErrors( cudaGraphicsGLRegisterImage ( &#x0026;cuda_tex_screen_resource , gltex , GL_TEXTURE_2D, cudaGraphicsMapFlagsReadOnly ) );</preformat><preformat><named-content content-type="line-number"> 12.&#x2003;</named-content>// Copy color buffer </preformat><preformat><named-content content-type="line-number"> 13.&#x2003;</named-content>checkCudaErrors( cudaGraphicsMapResources ( 1, &#x0026;cuda_tex_screen_resource , 0 ) ); </preformat><preformat><named-content content-type="line-number"> 14.&#x2003;</named-content>checkCudaErrors( cudaGraphicsSubResourceGe tMappedArray ( &#x0026;cuArr , cuda_tex_screen_resource, 0, 0 ) );</preformat><preformat><named-content content-type="line-number"> 15.&#x2003;</named-content>BindToTexture( cuArr); // BindToTexture Functions defined in Cuda_Gl.cu</preformat><preformat><named-content content-type="line-number"> 16.</named-content></preformat><preformat><named-content content-type="line-number"> 17.&#x2003;</named-content>DeviceArrayCopyFromTexture( ( float3&#x002A;) gpuMat.data, gpuMat.step, gpuMat.cols, gpuMat.rows );//DeviceArrayCopyFromTexture function defined on Cuda_Gl.cu </preformat><preformat><named-content content-type="line-number"> 18.</named-content></preformat><preformat><named-content content-type="line-number"> 19.&#x2003;</named-content>checkCudaErrors( cudaGraphicsUnmapResources ( 1, &#x0026;cuda_tex_screen_resource, 0 ) ); </preformat><preformat><named-content content-type="line-number"> 20.&#x2003;</named-content>checkCudaErrors( cudaGraphicsUnregisterResource (cuda_tex_screen_resource) ); </preformat><preformat><named-content content-type="line-number"> 21.&#x2003;</named-content>cv::gpu::cvtColor(gpuMat, GgpuMat,CV_RGB2GRAY);</preformat><preformat><named-content content-type="line-number"> 22.</named-content></preformat><preformat><named-content content-type="line-number"> 23.&#x2003;</named-content>// Apply the likelihood Assessment</preformat><preformat><named-content content-type="line-number"> 24.&#x2003;</named-content>// GgpuMat &#x2013; generated Image</preformat><preformat><named-content content-type="line-number"> 25.&#x2003;</named-content>// GgpuMat_R &#x2013; Real Distance Transform image </preformat><preformat><named-content content-type="line-number"> 26.&#x2003;</named-content>cv :: gpu :: multiply (GgpuMat, GgpuMat_R, GpuMatMul); </preformat><preformat><named-content content-type="line-number"> 27.&#x2003;</named-content>cv :: Scalar sumS = cv :: gpu :: sum(GpuMatMul);</preformat><preformat><named-content content-type="line-number"> 28.</named-content></preformat><preformat><named-content content-type="line-number"> 29.&#x2003;</named-content>/&#x002A;&#x00A0;</preformat><preformat><named-content content-type="line-number"> 30.&#x2003;</named-content>Check the article:</preformat><preformat><named-content content-type="line-number"> 31.&#x2003;</named-content>Online Body Schema Adaptation Based on Internal Mental Simulation and Multisensory Feedback, Vicente&#x00A0;et al.</preformat><preformat><named-content content-type="line-number"> 32.&#x2003;</named-content>In particular, Equation (21)</preformat><preformat><named-content content-type="line-number"> 34.&#x2003;</named-content>&#x002A;/ </preformat><preformat><named-content content-type="line-number"> 35.</named-content>&#x2003;sum = sumS [0]&#x002A;lambdaEdge; // lambdaEdge is a tuning parameter for distance sensitivity </preformat><preformat><named-content content-type="line-number"> 36.&#x2003;</named-content>nonZero = (float) cv::gpu::countNonZero (GgpuMat); // generated image </preformat><preformat><named-content content-type="line-number"> 37.</named-content>&#x2003;if (nonZero ==0) &#x007B; </preformat><preformat><named-content content-type="line-number"> 38.</named-content>&#x2003;&#x2003;likelihood [i] = 0.000000001; // Almost Zero</preformat><preformat><named-content content-type="line-number"> 39.</named-content>&#x2003;&#x007D;</preformat><preformat><named-content content-type="line-number"> 40.</named-content>&#x2003;else &#x007B;</preformat><preformat><named-content content-type="line-number"> 41.&#x2003;&#x2003;</named-content>result = sum/nonZero; </preformat><preformat><named-content content-type="line-number"> 42.&#x2003;&#x2003;</named-content>likelihood[i] = (int) ((cv::exp(&#x2013; result)) &#x002A;1000);</preformat><preformat><named-content content-type="line-number">43.</named-content>&#x2003;&#x007D;</preformat><preformat><named-content content-type="line-number">44.</named-content>&#x007D;</preformat></boxed-text></sec></sec><sec id="s5"><title>5. Application and Utility</title><p>The Markerless kinematic calibration can run during normal operations of the iCub robot. It will update the joint offsets according to the new incoming observations. Moreover, one can also stop the calibration and use the estimated offsets so far, however, to achieve a better accuracy in different poses of the end-effector the method should be kept running in an online fashion to perform a better adaptation of the parameters.</p><p>The details of the dependencies, installation and how to run the modules can be found at <italic><bold>Online Documentation page</bold></italic> (check Section 2).</p><sec id="s5-1"><title>5.1. Installation and Dependencies</title><p>The dependencies of the proposed solution can be divided in two sets of libraries: (1) the libraries needed to run the handPoseEstimation module, and (2) the libraries needed to run the Robot&#x2019;s internal model and the likelihood Assessment.</p><sec id="s5-1-1"><title>5.1.1. Hand Pose Estimation Module</title><p>The handPoseEstimation depends on YARP library, which can be installed following the installation procedure of the official repository<xref ref-type="fn" rid="FN9"><sup>9</sup></xref>. Moreover, it depends on the OpenCV library<xref ref-type="fn" rid="FN10"><sup>10</sup></xref>.</p><p>We tested this module with the last release of YARP (<italic>i.e.</italic>, June 15, 2017), version 2.3.70, with the OpenCV library V2.4.10 and V3.3 and the code works with both versions. The authors recommend the reader to follow the official installation guides for these libraries.</p><p>To install theses modules, one can just run <italic>CMake</italic> using the <italic>CMakeLists.txt</italic> on the folder:</p><preformat>/modules/handPoseEstimation/</preformat></sec><sec id="s5-1-2"><title>5.1.2 Robot&#x2019;s Internal Model Generator and Likelihood Assessment</title><p>The Robot&#x2019;s internal model and the likelihood assessment depend on YARP library for communication and on the OpenCV library with CUDA enabled computation (<italic>i.e.</italic>, installing the CUDA toolkit) for image processing and GPGPU accelerated algorithms. A Windows machine should be used to install this module.</p><p>The tested version of the OpenCV library was V.2.4.10 with the CUDA toolkit 6.5. The C# bindings for the YARP middleware on a windows machine should be compiled. The details regarding the installations procedures can be found at the following URL: <uri xlink:href="http://www.yarp.it/yarp_swig.html#yarp_swig_windows.">http://www.yarp.it/yarp_swig.html#yarp_swig_windows.</uri></p><p>The C# bindings will allow the internal model generator to communicate with the other modules.</p><p>The C# bindings will generate a DLL file that, along with the DLL generated from the likelihood assessment module, should be copied to the <monospace>Plugins</monospace> folder of the internal model generator. In the official compiled version of the repository this folder has the following path: <monospace>internalmodel/icub-internalmodel-rightA-cam-Lisbon_Data/Plugins/</monospace></p><p>The complete and step-by-step installation procedure can be seen in the <italic><bold>Online Documentation page</bold></italic> on the Installation section.</p></sec></sec><sec id="s5-2"><title>5.2. Running the Modules</title><p>The proposed method can run on a cluster of computers connected with the YARP middleware. The internal model generator should run on a computer with Windows Operating System and with CUDA capabilities. The step-by-step running procedure guide can be found on the<italic><bold>Online</bold><bold> Documentation page</bold></italic>. The rest of the section is organized with a high level perspective of running the algorithm. The YARP connections required between the several components can be connected through the XML file under the <monospace>app/scripts</monospace> folder.</p><sec id="s5-2-1"><title>5.2.1. Running the Hand Pose Estimation and its parameters</title><p>The Hand Pose Estimation can be initialized using the yarpmanager or in a terminal running the command: </p><preformat>handPoseEstimation [--&#x003C;parameter_name&#x003E; &#x003C;value &#x003E; &#x2026;] </preformat><p>where, &#x003C;<monospace>value</monospace>&#x003E; is the value for one of the parameters (&#x003C;<monospace>parameter</monospace>_<monospace>name</monospace>&#x003E;) defined in the itemize list below:</p><list list-type="bullet"><list-item><p><monospace>name</monospace>: name of the module (default&#x00A0;=&#x201C;hpe&#x201D;)</p></list-item><list-item><p><monospace>arm</monospace>: arm which the module should connect to. (default&#x00A0;=&#x00A0;right&#x2019;)</p></list-item><list-item><p><monospace>initialMean</monospace>: mean for the initial distribution of the particles [in degrees]. (default = 0.0&#x00B0;)</p></list-item><list-item><p><monospace>initialStdDev</monospace>: StdDev of the initial distribution of the particles degrees</p></list-item><list-item><p><monospace>artificialNoiseStdDev</monospace>: initial  Artificial Noise&#x00A0;(StdDev) to spread the particles after each iteration (default = 3.0&#x00B0;)</p></list-item><list-item><p><monospace>lowerBound</monospace>: artificial noise lower bound (StdDev). Should be greater than Zero to prevent the particles to collapse in one single value (default = 0.04&#x00B0;)</p></list-item><list-item><p><monospace>upperBound</monospace>: artificial noise upper bound (StdDev). The artificial noise should have a upper bound to prevent the particles to diverge after each resampling stage (default = 3.5&#x00B0;)</p></list-item><list-item><p><monospace>minimumLikelihood</monospace>: minimumLikelihood [0,1] in order to resample the particles (default = 0.55)</p></list-item><list-item><p>increaseMultiplier: increase the artificial noise of a certain value (currentValue&#x002A;increaseMultiplier) if the maximum likelihood is lower than the minimumLikelihood (default = 1.15)</p></list-item><list-item><p><monospace>decreaseMultiplier</monospace>: decrease the artificial noise of a certain value (currentValue&#x002A;decreaseMultiplier) if the maximum likelihood is greater than the minimumLikelihood (default = 0.85)</p></list-item><list-item><p><monospace>KDEStdDev</monospace>: StdDev of each kernel in the Kernel Density Estimation algorithm (default = 1.0&#x00B0;)</p></list-item><list-item><p><monospace>minIteration</monospace>: minimum number of iterations before sending the estimated offsets. The objective is to give time to the algorithm to converge, without this feature one can receive completely different offsets from iteration <italic>t</italic> to <italic>t</italic> + 1 during the filter convergence (default = 35)</p></list-item></list></sec><sec id="s5-2-2"><title>5.2.2. Running the Robot&#x2019;s Internal Model</title><p>The internal model generator should run on a terminal using the following command:</p><preformat>icub-internalmodel-rightA-cam-Lisbon.exe -force-opengl</preformat><p>The <monospace>-force-opengl</monospace> argument will force the robot&#x2019;s internal model to use the OpenGL library for rendering purposes, which is fundamental for the libraries interoperability.</p></sec><sec id="s5-2-3"><title>5.2.3. User interface</title><p>The user can send commands to the Hand Pose estimation algorithm through the RPC port <italic>hpe/rpc:i</italic>. The RPC port acts like a service to the user where the algorithm can be started, stoped or paused/resumed. It is also possible to request the last joint offsets estimated by the algorithm. The thrift file (<italic>modules/handPoseEstimation/handPoseEstimation.thrift</italic>) contains the input and output of each RPC service function (<italic>i.e.</italic>,<italic> start, stop, pause, resume, lastOffsets and quit</italic>). More details about these commands can be seen in the use procedure on the documentation. Moreover, after connecting to the RPC port (<italic>yarp rpc hpe/rpc:i</italic>), the user can type <monospace>help</monospace> to get the available commands. The module also replies the input and output parameters of a given command if the user type <italic>help FunctionName</italic> (<italic>e.g., <monospace>help start</monospace></italic>).</p></sec></sec></sec><sec id="s6"><title>6. Experiments and Examples of Use</title><p>The experiments performed with the proposed method on the iCub simulator, with ground truth data, have shown a good accuracy on the hand pose estimation, where artificial offsets were introduced in the seven joints of the arm. The results on the real robot have shown a significant reduction of the calibration error [Check <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref> Section 5 for more results in simulation (Section 5.1) and with the real iCub (Section 5.2)].</p><p>For the reader to be able to test the algorithm, the authors collected a simulated dataset (encoders of the head and arms, and the left and right images) which can be used to test the algorithm. The simulation results of the present article were obtained running the above-stated code with the default parameters on the collected dataset.</p><p>The dataset<xref ref-type="fn" rid="FN11"><sup>11</sup></xref> was collected using a visual simulator based on the CAD model of the iCub humanoid robot adding artificial offsets in the arm joints. The artificial angular offsets <italic>&#x03B2;</italic> were the following:</p><p><disp-formula><italic>&#x03B2;</italic> = &#x007B; &#x2013; 10.0, &#x2013; 10.0, 6.0, &#x2013; 7.0, &#x2013; 1.0, &#x2013; 20.0, 7.0&#x007D;&#x00B0;.</disp-formula></p><p>The robot performed a babbling movement which consists in a random walk in each joint. The minimum and maximum values of the uniform distribution used to generate the babbling movement starts at [&#x2013;5,&#x00A0;5]&#x00B0;, and is reduced during the movement to [&#x2013; 0.5, 0.5]&#x00B0;, respectively. Despite a great amount of errors in the robot&#x2019;s kinematic chain, the algorithm was able to converge to the solution in <xref ref-type="fig" rid="F2">Figure 2</xref>. Moreover, the cluttered environment on the background did not influence the filter convergence. The reader can see the projection of the fingertips on the left camera image: (1) according to the canonical representation on <xref ref-type="fig" rid="F2">Figure 2A</xref> (where it is assumed an error-free kinematic structure, <italic>i.e.</italic>, with <inline-formula><mml:math id="M23"><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mrow><mml:mrow><mml:mover><mml:mi>&#x03B2;</mml:mi><mml:mo stretchy="false">&#x005E;</mml:mo></mml:mover></mml:mrow><mml:mo>=</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:mstyle></mml:math></inline-formula> and (2) the corrected kinematic structure using the algorithm implemented and documented in this code paper on <xref ref-type="fig" rid="F2">Figure 2B</xref>.</p><fig id="F2" position="float"><label>Figure 2</label><caption><p> Projection of the fingertips on the left camera on simulated robot experiments. The blue dot represents the end-effector projection (<italic>i.e.</italic>, base of the middle finger), the red represents the index fingertip, the green the thumb fingertip, the dark yellow the middle fingertip and the soft yellow the ring and little fingertips. On the left image <bold>(</bold><bold>A</bold><bold>)</bold> is the canonical projection (<italic>i.e.</italic>, with <inline-formula><mml:math id="M24"><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mrow><mml:mrow><mml:mover><mml:mi mathvariant="bold-italic">&#x03B2;</mml:mi><mml:mo mathvariant="bold" stretchy="false">&#x005E;</mml:mo></mml:mover></mml:mrow><mml:mo>=</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:mstyle></mml:math></inline-formula>) and on the right image <bold>(</bold><bold>B</bold><bold>)</bold> the estimated offsets (<inline-formula><mml:math id="M25"><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mrow><mml:mrow><mml:mover><mml:mi mathvariant="bold-italic">&#x03B2;</mml:mi><mml:mo mathvariant="bold" stretchy="false">&#x005E;</mml:mo></mml:mover></mml:mrow></mml:mrow></mml:mstyle></mml:math></inline-formula>).</p></caption><graphic xlink:href="frobt-05-00046-g002.tif"/></fig><p>The convergence of the algorithm along with a side-by-side comparison with the canonical solution can be seen in the following video: <monospace><uri>https://youtu.be/0tzLFqZLbxc</uri></monospace></p><p>On the real robot, we already performed several experiments in previous works, with different initial and final poses using the 320 &#x00D7; 240 cameras. In <xref ref-type="fig" rid="F3">Figure 3</xref> one can see one example of the hand estimation. While the image on the left (<xref ref-type="fig" rid="F3">Figure 3A</xref>) shows the canonical estimation of the hand projected on the left camera image according to the non-calibrated kinematic chain, the image on the right (<xref ref-type="fig" rid="F3">Figure 3B</xref>) shows the corrected kinematic chain which originates a better estimation of the hand pose. The rendering of the estimated hand pose was done taking into account the joint offsets on the kinematic chain before computing the hand pose in the image reference frame.</p><fig id="F3" position="float"><label>Figure 3</label><caption><p> Projection of the fingertips on left camera in real robot experiments. On the left image <bold>(</bold><bold>A</bold><bold>)</bold> the canonical projection (<italic>i.e.</italic>, with <inline-formula><mml:math id="M26"><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mrow><mml:mrow><mml:mover><mml:mi mathvariant="bold-italic">&#x03B2;</mml:mi><mml:mo mathvariant="bold" stretchy="false">&#x005E;</mml:mo></mml:mover></mml:mrow><mml:mo>=</mml:mo><mml:mn>0</mml:mn></mml:mrow></mml:mstyle></mml:math></inline-formula>) is shown, and on the right <bold>(</bold><bold>B</bold><bold>)</bold> the projection according with the corrected kinematic chain using the estimated offsets (<inline-formula><mml:math id="M27"><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mrow><mml:mrow><mml:mover><mml:mi mathvariant="bold-italic">&#x03B2;</mml:mi><mml:mo mathvariant="bold" stretchy="false">&#x005E;</mml:mo></mml:mover></mml:mrow></mml:mrow></mml:mstyle></mml:math></inline-formula>).</p></caption><graphic xlink:href="frobt-05-00046-g003.tif"/></fig></sec><sec id="s7"><title>7. Known Issues</title><p>There are some known issues or limitations in this algorithm and its software. The Windows dependency of the internal model generator module can be a problem for non-windows users. Moreover, the number of particles in the Sequential Monte Carlo is fixed (200 particles), which we found to be a good trade-off between accuracy and speed [check <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref> for more details on this matter].</p><p>The camera size is also fixed to the 320 &#x00D7; 240 resolution, which is sufficient to most of the experiments performed on the iCub. Indeed, to the authors&#x2019; knowledge, this is the most popular resolution in the iCub community. The camera resolution can be modified by changing the input resolution on the hand pose estimation module and on the internal structures of the internal model and the likelihood assessment. However, this demands for a recompilation of the internal model generator which could not be done without a Pro license of Unity<sup>&#x00AE;</sup>.</p><p>The limitation on the integration of the likelihood assessment and the <italic>int</italic> cast discussed in Section 4.3 should be investigated since we are truncating the likelihood and in the end we have, at most, three significant figures of the likelihood value.</p><p>Hand occlusions can also be problematic at this stage of the work since we are not dealing explicitly with them. If the hand is occluded for a long period, the filter can start to diverge since it does not find a good match of the hand model in its perception.</p></sec><sec id="s8"><title>8. Conclusion and Future Work</title><p>In this paper, we have shown how to calibrate the eye-hand kinematic chain of a humanoid robot &#x2013; the iCub robot. We have provided a tutorial on how to execute the module and how it works, its inputs and outputs. Our proposed work could be beneficial for research works with the iCub humanoid robot, from manipulation related fields to human-robot interaction, for instance. The results have shown a good accuracy in simulation and in a real-world environment. For future work, we are planning to extend the architecture. A useful feature is to be able to predict if the hand is present or not in the image or if it is occluded in order to perform a better match between the perception and the generated hypotheses. We will investigate the possibility of running the internal model simulator on different platforms (<italic>i.e.</italic>, Linux, macOS), which seems to be a new feature of the Unity game engine editor environment.</p></sec><sec id="S9"><title>Author Contributions</title><p>In this work, all the authors contributed to the conception of the markerless eye-hand kinematic calibration solution and to the analysis and interpretation of the data acquired.</p></sec><sec id="S10"><title>Conflict of Interest Statement</title><p>The authors declare that the research was conducted in the absence of any commercial or financial relationships that could be construed as a potential conflict of interest.</p><p>The reviewer, CF, and handling Editor declared their shared affiliation.</p></sec></body><back><fn-group><fn fn-type="financial-disclosure"><p><bold>Funding.</bold> This work was partially supported by Funda&#x00E7;&#x00E3;o para a Ci&#x00EA;ncia e a Tecnologia [UID/EEA/50009/2013] and PhD grant [PD/BD/135115/2017] and by EPSRC UK (project NCNR, National Centre for Nuclear Robotics, EP/R02572X/1). We acknowledge the support of NVIDIA Corporation with the donation of the GPU used for this research.</p></fn></fn-group><ref-list><title>References</title><ref id="B1"><citation citation-type="journal"><person-group person-group-type="author"><name><surname>Borgefors</surname><given-names>G</given-names></name> <name><surname>Bradski</surname><given-names>G</given-names></name></person-group>. (<year>1986</year>). <article-title>Distance transformations in digital images</article-title>. <source>Computer Vision Graphics and Image Processing</source> <volume>34</volume> (<issue>3</issue>), <fpage>344</fpage>&#x2013;<lpage>371</lpage>. <pub-id pub-id-type="doi">10.1016/S0734-189X(86)80047-0</pub-id></citation></ref><ref id="B2"><citation citation-type="other"><person-group person-group-type="author"><name><surname>Bradski</surname><given-names>G</given-names></name></person-group>. (<year>2000</year>). <article-title>The OpenCV Library</article-title>. <publisher-name>Dr. Dobb&#x2019;s Journal of Software Tools</publisher-name>.</citation></ref><ref id="B4"><citation citation-type="confproc"><person-group person-group-type="author"><name><surname>Fanello</surname><given-names>S</given-names></name> <name><surname>Pattacini</surname><given-names>U</given-names></name> <name><surname>Gori</surname><given-names>I</given-names></name> <name><surname>Tikhanoff</surname><given-names>V</given-names></name> <name><surname>Randazzo</surname><given-names>M</given-names></name> <name><surname>Roncone</surname><given-names>A</given-names></name></person-group>. (<year>2014</year>). &#x201C;<article-title>3D stereo estimation and fully automated learning of eye-hand coordination in humanoid robot</article-title>&#x201D; <conf-name>IEEE-RAS International Conference on Humanoid Robots</conf-name> <fpage>1028</fpage>&#x2013;<lpage>1035</lpage>.</citation></ref><ref id="B5"><citation citation-type="journal"><person-group person-group-type="author"><name><surname>Fantacci</surname><given-names>C</given-names></name> <name><surname>Pattacini</surname><given-names>U</given-names></name> <name><surname>Tikhanoff</surname><given-names>V</given-names></name> <name><surname>Natale</surname><given-names>L</given-names></name></person-group>. (<year>2017</year>). <article-title>Visual end-effector tracking using a 3D model-aided particle filter for humanoid robot platforms</article-title>. <source>arXiv preprint arXiv</source> <volume>1703</volume>, <fpage>04771</fpage>.</citation></ref><ref id="B3"><citation citation-type="journal"><person-group person-group-type="author"><name><surname>Garcia Cifuentes</surname><given-names>C</given-names></name> <name><surname>Issac</surname><given-names>J</given-names></name> <name><surname>Wuthrich</surname><given-names>M</given-names></name> <name><surname>Schaal</surname><given-names>S</given-names></name> <name><surname>Bohg</surname><given-names>J</given-names></name></person-group>. (<year>2017</year>). <article-title>Probabilistic articulated real-time tracking for robot manipulation</article-title>. <source>IEEE Robot. Autom. Lett.</source> <volume>2</volume> (<issue>2</issue>), <fpage>577</fpage>&#x2013;<lpage>584</lpage>. <pub-id pub-id-type="doi">10.1109/LRA.2016.2645124</pub-id></citation></ref><ref id="B6"><citation citation-type="confproc"><person-group person-group-type="author"><name><surname>Gratal</surname><given-names>X</given-names></name> <name><surname>Romero</surname><given-names>J</given-names></name> <name><surname>Kragic</surname><given-names>D</given-names></name></person-group>. (<year>2011</year>). &#x201C;<article-title>Virtual Visual Servoing for Real-Time Robot Pose Estimation</article-title>&#x201D; <conf-name>Proc. of the 18th IFAC World Congress</conf-name> <fpage>9017</fpage>&#x2013;<lpage>9022</lpage>.</citation></ref><ref id="B7"><citation citation-type="confproc"><person-group person-group-type="author"><name><surname>Hol</surname><given-names>JD</given-names></name> <name><surname>Schon</surname><given-names>TB</given-names></name> <name><surname>Gustafsson</surname><given-names>F</given-names></name></person-group>. (<year>2006</year>). &#x201C;<article-title>On resampling algorithms for particle filters</article-title>&#x201D; <conf-name>IEEE Nonlinear Statistical Signal Processing Workshop</conf-name> <fpage>79</fpage>&#x2013;<lpage>82</lpage>.</citation></ref><ref id="B8"><citation citation-type="book"><person-group person-group-type="author"><name><surname>Kantas</surname><given-names>N</given-names></name> <name><surname>Doucet</surname><given-names>A</given-names></name> <name><surname>Singh</surname><given-names>S. S</given-names></name> <name><surname>Maciejowski</surname><given-names>J. M</given-names></name></person-group>. (<year>2009</year>). &#x201C;<article-title>An overview of Sequential Monte Carlo methods for parameter estimation on general state space models</article-title>,&#x201D; <comment>in</comment> <source>IFAC Symposium on System Identification (SYSID)</source>, <volume>Vol. 42</volume>, <fpage>774</fpage>&#x2013;<lpage>785</lpage>. <pub-id pub-id-type="doi">10.3182/20090706-3-FR-2004.00129</pub-id></citation></ref><ref id="B9"><citation citation-type="journal"><person-group person-group-type="author"><name><surname>Metta</surname><given-names>G</given-names></name> <name><surname>Fitzpatrick</surname><given-names>P</given-names></name> <name><surname>Natale</surname><given-names>L</given-names></name></person-group>. (<year>2006</year>). <article-title>YARP: yet another robot platform</article-title>. <source>International Journal of Advanced Robotic Systems</source> <volume>3</volume> (<issue>1</issue>), <fpage>8</fpage>. <pub-id pub-id-type="doi">10.5772/5761</pub-id></citation></ref><ref id="B10"><citation citation-type="journal"><person-group person-group-type="author"><name><surname>Metta</surname><given-names>G</given-names></name> <name><surname>Natale</surname><given-names>L</given-names></name> <name><surname>Nori</surname><given-names>F</given-names></name> <name><surname>Sandini</surname><given-names>G</given-names></name> <name><surname>Vernon</surname><given-names>D</given-names></name> <name><surname>Fadiga</surname><given-names>L</given-names></name> <etal/></person-group>. (<year>2010</year>). <article-title>The iCub humanoid robot: an open-systems platform for research in cognitive development</article-title>. <source>Neural Netw.</source> <volume>23</volume> (<issue>8-9</issue>), <fpage>1125</fpage>&#x2013;<lpage>1134</lpage>. <pub-id pub-id-type="doi">10.1016/j.neunet.2010.08.010</pub-id></citation></ref><ref id="B11"><citation citation-type="journal"><person-group person-group-type="author"><name><surname>Nickolls</surname><given-names>J</given-names></name> <name><surname>Buck</surname><given-names>I</given-names></name> <name><surname>Garland</surname><given-names>M</given-names></name> <name><surname>Skadron</surname><given-names>K</given-names></name></person-group>. (<year>2008</year>). <article-title>Scalable parallel programming with CUDA</article-title>. <source>Queue</source> <volume>6</volume> (<issue>2</issue>), <fpage>40</fpage>&#x2013;<lpage>53</lpage>. <pub-id pub-id-type="doi">10.1145/1365490.1365500</pub-id></citation></ref><ref id="B12"><citation citation-type="journal"><person-group person-group-type="author"><name><surname>Vicente</surname><given-names>P</given-names></name> <name><surname>Jamone</surname><given-names>L</given-names></name> <name><surname>Bernardino</surname><given-names>A</given-names></name></person-group>. (<year>2016a</year>). <article-title>Online body schema adaptation based on internal mental simulation and multisensory feedback</article-title>. <source>Front. Robot. AI</source> <volume>3</volume>:<elocation-id>7</elocation-id>. <pub-id pub-id-type="doi">10.3389/frobt.2016.00007</pub-id></citation></ref><ref id="B13"><citation citation-type="journal"><person-group person-group-type="author"><name><surname>Vicente</surname><given-names>P</given-names></name> <name><surname>Jamone</surname><given-names>L</given-names></name> <name><surname>Bernardino</surname><given-names>A</given-names></name></person-group>. (<year>2016b</year>). <article-title>Robotic hand pose estimation based on stereo vision and GPU-enabled internal graphical simulation</article-title>. <source>J. Intell. Robot. Syst.</source> <volume>83</volume> (<issue>3-4</issue>), <fpage>339</fpage>&#x2013;<lpage>358</lpage>. <pub-id pub-id-type="doi">10.1007/s10846-016-0376-6</pub-id></citation></ref></ref-list><fn-group><fn id="FN1"><label>1</label><p>For a more detailed review of the state of the art, please check the article <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref></p></fn><fn id="FN2"><label>2</label><p>See <xref ref-type="bibr" rid="B8">Kantas et al. (2009)</xref> for other solutions</p></fn><fn id="FN3"><label>3</label><p><uri xlink:href="http://www.yarp.it/classyarp_1_1os_1_1RFModule.html">http://www.yarp.it/classyarp_1_1os_1_1RFModule.html</uri></p></fn><fn id="FN4"><label>4</label><p><uri xlink:href="http://www.yarp.it/classyarp_1_1os_1_1BufferedPort.html">http://www.yarp.it/classyarp_1_1os_1_1BufferedPort.html</uri></p></fn><fn id="FN5"><label>5</label><p><uri xlink:href="http://www.yarp.it/classyarp_1_1os_1_1RpcServer.html">http://www.yarp.it/classyarp_1_1os_1_1RpcServer.html</uri></p></fn><fn id="FN6"><label>6</label><p>See <xref ref-type="disp-formula" rid="E1">Eq. 1</xref> and handPoseEstimationModule.cpp#L214</p></fn><fn id="FN7"><label>7</label><p>The list of dependencies can be seen on Section 5.1.2</p></fn><fn id="FN8"><label>8</label><p>Check <xref ref-type="bibr" rid="B12">Vicente et al. (2016a)</xref> Eq (21) for more details on the lambdaEdge parameter</p></fn><fn id="FN9"><label>9</label><p><uri xlink:href="https://github.com/robotology/yarp">https://github.com/robotology/yarp</uri></p></fn><fn id="FN10"><label>10</label><p>It is not mandatory the CUDA-enabled capabilities</p></fn><fn id="FN11"><label>11</label><p><uri xlink:href="https://github.com/vicentepedro/eyeHandCalibrationDataset-Sim">https://github.com/vicentepedro/eyeHandCalibrationDataset-Sim</uri></p></fn></fn-group></back></article>
