## 2 Materials and Methods
### ROS-Based Implementation
#### 2.2.3 Implementation Details  
The overall architecture is described through a context diagram and a hybrid decomposition/class diagram in Figures 5 and 6, respectively. Here, the _interaction_controller:: InteractionController_ class name is a placeholder for the real controller class name, i.e., _admittance_controller::AdmittanceController_ or _direct_force_controller::DirectForceController_. As discussed in previous sections, the real robots are position-controlled robots; thus, the interaction controllers have been implemented by inheriting the class _controller_interface:: Controller \(\langle\)hardware_interface::Position\(|\)jointInterface\(\rangle\)[38], which allows sending joint position commands and reading joint states through the provided _JointHandle_[39] interface. Every controller requires the implementation of the methods _init_, _starting_, _stopping_, and _update_. While the first three functions are called when the controller is loaded, started, and stopped, respectively, _update_ embeds the control law, i.e., the FSM described in Section 2.2.1, and is called at the control cycle frequency. The communication between the controller and the force/torque sensor is handled through the class _ForceTorqueSensor_, designed as a plugin, such that specific implementations can be provided for specific sensors, both real and simulated. In particular, an object of the _ForceTorqueSensor_ class is instantiated in the _init_ function and is used at each _update_ call to obtain the force measures from a driver. It is worth noting that ROS already provides a _force_torque_sensor_controller_[40] based on topic communication but, since the API is faster, it is preferable for real-time systems. Thus, new force/torque sensors can be added by implementing the _ForceTorqueSensor_ interface. Figure 5: Context diagram. One of the main issues in designing a robot-agnostic architecture is to make the software independent from the specific kinematic structure of the robot. In fact, the reference frames used for inverse kinematics and force measurements can change from robot to robot. Moreover, the _Unified Robot Description Format_ (URDF) file used to obtain the kinematic description of the manipulator may contain additional frames that are not present in the real robot kinematic structure, as configured by the manufacturer for on-board computations, but might be implicitly used by the ROS functions. For instance, the URDF _world_ frame is typically used for kinematic inversion, but it may not correspond to the frame in which the workspace trajectory is expressed. The reference frames used by the interaction controllers are reported in Figure 7. \(\mathcal{F}_{b}\) is the _base_ reference frame, usually used to specify the workspace trajectory. \(\mathcal{F}_{w}\) is the _world_ reference frame, and, when different from \(\mathcal{F}_{b}\), might be used to interpret the pose subject to inverse kinematics. \(\mathcal{F}_{b}\) is transformed into \(\mathcal{F}_{w}\) through the constant transformation matrix \(\mathbf{T}_{b}^{w}\). \(\mathcal{F}_{m}\) is the flange frame (usually the last frame in a kinematic chain without end-effector), and is where the force/torque sensor is mounted. \(\mathcal{F}_{s}\) is the sensor frame, with respect to which force/torque measures are given. The constant transformation matrix \(\mathbf{T}_{m}^{s}\) depends on the mechanical interface between the flange and the sensor. \(\mathcal{F}_{f}\) is the end-effector frame when the robot is at the trajectory's starting point, while \(\mathcal{F}_{e}\) is the end-effector-fixed moving frame. As a consequence, controllers have been parametrized to indicate the reference frames for the task, for inverse kinematics, and for force/torque measurements, while transformations between them are automatically handled by the controller. All these frames and transformation matrices are provided by the user in configuration files and loaded on the _parameter server_[41].