Skip to content

Commit ee45b4a

Browse files
committed
Merge branch 'docs/move-docu-under-packages' into develop
2 parents c11f000 + d3a05cf commit ee45b4a

File tree

18 files changed

+1716
-1
lines changed

18 files changed

+1716
-1
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# CHANGELOG
22

3-
## 0.10.2 - UNRELEASED
3+
## 0.10.3 - 2025-10-20
4+
5+
Requires `libfranka` >= 0.8.0
6+
7+
* docs: Move documentation under each package.
8+
9+
## 0.10.2 - 2023-12-20
410

511
Requires `libfranka` >= 0.8.0
612

docs/index.rst

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
franka_ros
2+
==========
3+
4+
.. toctree::
5+
:maxdepth: 1
6+
7+
../franka_ros/doc/index
8+
../franka_control/doc/index
9+
../franka_description/doc/index
10+
../franka_example_controllers/doc/index
11+
../franka_gazebo/doc/index
12+
../franka_gripper/doc/index
13+
../franka_hw/doc/index
14+
../franka_msgs/doc/index
15+
../franka_visualization/doc/index
16+
17+
.. _write_own_controller:
18+
19+
Writing your own controller
20+
----------------------------
21+
All example controllers from the :ref:`example controllers package<example_controllers>` are
22+
derived from the ``controller_interface::MultiInterfaceController`` class, which allows to claim
23+
up to four interfaces in one controller instance. The declaration of your class then looks like:
24+
25+
.. code-block:: c++
26+
27+
class NameOfYourControllerClass : controller_interface::MultiInterfaceController <
28+
my_mandatory_first_interface,
29+
my_possible_second_interface,
30+
my_possible_third_interface,
31+
my_possible_fourth_interface> {
32+
bool init (hardware_interface::RobotHW* hw, ros::NodeHandle& nh); // mandatory
33+
void update (const ros::Time& time, const ros::Duration& period); // mandatory
34+
void starting (const ros::Time& time) // optional
35+
void stopping (const ros::Time& time); // optional
36+
...
37+
}
38+
39+
40+
The available interfaces are described in Section :ref:`franka_hw <franka_hw>`.
41+
42+
.. important::
43+
44+
Note that the claimable combinations of commanding interfaces are restricted as it does not
45+
make sense to e.g. command joint positions and Cartesian poses simultaneously. Read-only
46+
interfaces like the *JointStateInterface*, the *FrankaStateInterface* or the
47+
*FrankaModelInterface* can always be claimed and are not subject to restrictions.
48+
49+
50+
Possible claims to command interfaces are:
51+
52+
+-------------------------------------------------+----------------------------------------------+
53+
| ``franka_hw::FrankaHW`` | ``franka_combinable_hw::FrankaCombinableHW`` |
54+
+=================================================+==============================================+
55+
| - all possible single interface claims | - ``EffortJointInterface`` |
56+
| - ``EffortJointInterface`` + | - ``EffortJointInterface`` + |
57+
| ``PositionJointInterface`` | ``FrankaCartesianPoseInterface`` |
58+
| - ``EffortJointInterface`` + | - ``EffortJointInterface`` + |
59+
| ``VelocityJointInterface`` | ``FrankaCartesianVelocityInterface`` |
60+
| - ``EffortJointInterface`` + | |
61+
| ``FrankaCartesianPoseInterface`` | |
62+
| - ``EffortJointInterface`` + | |
63+
| ``FrankaCartesianVelocityInterface`` | |
64+
+-------------------------------------------------+----------------------------------------------+
65+
66+
The idea behind offering the *EffortJointInterface* in combination with a motion generator
67+
interface is to expose the internal motion generators to the user. The calculated desired joint
68+
pose corresponding to a motion generator command is available in the robot state one time step
69+
later. One use case for this combination would be following a Cartesian trajectory using your own
70+
joint-level torque controller. In this case you would claim the combination *EffortJointInterface*
71+
+ *FrankaCartesianPoseInterface*, stream your trajectory into the *FrankaCartesianPoseInterface*,
72+
and compute your joint-level torque commands based on the resulting desired joint pose (q_d) from
73+
the robot state. This allows to use the robot's built-in inverse kinematics instead of having to
74+
solve it on your own.
75+
76+
To implement a fully functional controller you have to implement at least the inherited virtual
77+
functions ``init`` and ``update``. Initializing - e.g. start poses - should be done in the
78+
``starting`` function as ``starting`` is called when restarting the controller, while ``init`` is
79+
called only once when loading the controller. The ``stopping`` method should contain shutdown
80+
related functionality (if needed).
81+
82+
.. important::
83+
84+
Always command a gentle slowdown before shutting down the controller. When using velocity
85+
interfaces, do not simply command zero velocity in ``stopping``. Since it might be called
86+
while the robot is still moving, it would be equivalent to commanding a jump in velocity
87+
leading to very high resulting joint-level torques. In this case it would be better to keep the
88+
same velocity and stop the controller than sending zeros and let the robot handle
89+
the slowdown.
90+
91+
Your controller class must be exported correctly with ``pluginlib`` which requires adding:
92+
93+
.. code-block:: c++
94+
95+
#include <pluginlib/class_list_macros.h>
96+
// Implementation ..
97+
PLUGINLIB_EXPORT_CLASS(name_of_your_controller_package::NameOfYourControllerClass,
98+
controller_interface::ControllerBase)
99+
100+
101+
at the end of the ``.cpp`` file. In addition you need to define a ``plugin.xml`` file with the
102+
following content:
103+
104+
.. code-block:: xml
105+
106+
<library path="lib/lib<name_of_your_controller_library>">
107+
<class name="name_of_your_controller_package/NameOfYourControllerClass"
108+
type="name_of_your_controller_package::NameOfYourControllerClass"
109+
base_class_type="controller_interface::ControllerBase">
110+
<description>
111+
Some text to describe what your controller is doing
112+
</description>
113+
</class>
114+
</library>
115+
116+
117+
which is exported by adding:
118+
119+
.. code-block:: xml
120+
121+
<export>
122+
<controller_interface plugin="${prefix}/plugin.xml"/>
123+
</export>
124+
125+
126+
to your package.xml. Further, you need to load at least a controller name in combination with a
127+
controller type to the ROS parameter server. Additionally, you can include other parameters you
128+
need. An exemplary configuration.yaml file can look like:
129+
130+
.. code-block:: yaml
131+
132+
your_custom_controller_name:
133+
type: name_of_your_controller_package/NameOfYourControllerClass
134+
additional_example_parameter: 0.0
135+
# ..
136+
137+
Now you can start your controller using the ``controller_spawner`` node from ROS control or via the
138+
service calls offered by the ``hardware_manager``. Just make sure that both the
139+
``controller_spawner`` and the ``franka_control_node`` run in the same namespace. For more details
140+
have a look at the controllers from the
141+
:ref:`franka_example_controllers package<example_controllers>` or the
142+
`ROS control tutorials <http://wiki.ros.org/ros_control/Tutorials>`_.

0 commit comments

Comments
 (0)