tutorial-franka-real-joint-impedance-control.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2021 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  *****************************************************************************/
32 
34 
35 #include <iostream>
36 
37 #include <visp3/gui/vpPlot.h>
38 #include <visp3/robot/vpRobotFranka.h>
39 
40 #if defined( VISP_HAVE_FRANKA ) && defined( VISP_HAVE_DISPLAY )
41 
42 int
43 main( int argc, char **argv )
44 {
45  std::string opt_robot_ip = "192.168.1.1";
46  bool opt_verbose = false;
47  bool opt_save_data = false;
48 
49  for ( int i = 1; i < argc; i++ )
50  {
51  if ( std::string( argv[i] ) == "--ip" && i + 1 < argc )
52  {
53  opt_robot_ip = std::string( argv[i + 1] );
54  }
55  else if ( std::string( argv[i] ) == "--verbose" || std::string( argv[i] ) == "-v" )
56  {
57  opt_verbose = true;
58  }
59  else if ( std::string( argv[i] ) == "--save" )
60  {
61  opt_save_data = true;
62  }
63  else if ( std::string( argv[i] ) == "--help" || std::string( argv[i] ) == "-h" )
64  {
65  std::cout << argv[0] << " [--ip <default " << opt_robot_ip << ">]"
66  << " [--save]"
67  << " [--verbose] [-v]"
68  << " [--help] [-h] " << std::endl;
69  return EXIT_SUCCESS;
70  }
71  }
72 
73  vpRobotFranka robot;
74  try
75  {
76  std::cout << "ip: " << opt_robot_ip << std::endl;
77  robot.connect( opt_robot_ip );
78 
79  vpColVector q_init( { 0, vpMath::rad( -45 ), 0, vpMath::rad( -135 ), 0, vpMath::rad( 90 ), vpMath::rad( 45 ) } );
80 
81  robot.setRobotState( vpRobot::STATE_POSITION_CONTROL );
82  robot.setPosition( vpRobot::JOINT_STATE, q_init );
83  vpTime::wait( 500 );
84 
85  vpPlot *plotter = nullptr;
86 
87  plotter = new vpPlot( 4, 800, 800, 10, 10, "Real time curves plotter" );
88  plotter->setTitle( 0, "Joint position [rad]" );
89  plotter->initGraph( 0, 7 );
90  plotter->setLegend( 0, 0, "q1" );
91  plotter->setLegend( 0, 1, "q2" );
92  plotter->setLegend( 0, 2, "q3" );
93  plotter->setLegend( 0, 3, "q4" );
94  plotter->setLegend( 0, 4, "q5" );
95  plotter->setLegend( 0, 5, "q6" );
96  plotter->setLegend( 0, 6, "q7" );
97 
98  plotter->setTitle( 1, "Joint position error [rad]" );
99  plotter->initGraph( 1, 7 );
100  plotter->setLegend( 1, 0, "e_q1" );
101  plotter->setLegend( 1, 1, "e_q2" );
102  plotter->setLegend( 1, 2, "e_q3" );
103  plotter->setLegend( 1, 3, "e_q4" );
104  plotter->setLegend( 1, 4, "e_q5" );
105  plotter->setLegend( 1, 5, "e_q6" );
106  plotter->setLegend( 1, 6, "e_q7" );
107 
108  plotter->setTitle( 2, "Joint torque measure [Nm]" );
109  plotter->initGraph( 2, 7 );
110  plotter->setLegend( 2, 0, "Tau1" );
111  plotter->setLegend( 2, 1, "Tau2" );
112  plotter->setLegend( 2, 2, "Tau3" );
113  plotter->setLegend( 2, 3, "Tau4" );
114  plotter->setLegend( 2, 4, "Tau5" );
115  plotter->setLegend( 2, 5, "Tau6" );
116  plotter->setLegend( 2, 6, "Tau7" );
117 
118  plotter->setTitle( 3, "Joint error norm [deg]" );
119  plotter->initGraph( 3, 1 );
120  plotter->setLegend( 3, 0, "||qd - d||" );
121 
122  // Create joint array
123  vpColVector q( 7, 0 ), qd( 7, 0 ), dq( 7, 0 ), dqd( 7, 0 ), ddqd( 7, 0 ), tau_d( 7, 0 ), C( 7, 0 ), q0( 7, 0 ),
124  F( 7, 0 ), tau_d0( 7, 0 ), tau_cmd( 7, 0 ), tau( 7, 0 );
125  vpMatrix B( 7, 7 );
126 
127  std::cout << "Reading current joint position" << std::endl;
128  robot.getPosition( vpRobot::JOINT_STATE, q0 );
129  std::cout << "Initial joint position: " << q0.t() << std::endl;
130 
131  robot.setRobotState( vpRobot::STATE_FORCE_TORQUE_CONTROL );
132  qd = q0;
133 
134  bool final_quit = false;
135  bool first_time = true;
136  bool start_trajectory = false;
137 
138  vpMatrix K( 7, 7 ), D( 7, 7 ), I( 7, 7 );
139  K.diag( { 400.0, 400.0, 400.0, 400.0, 400.0, 400.0, 900.0 } );
140  D.diag( { 20.0, 45.0, 45.0, 45.0, 45.0, 45.0, 60.0 } );
141  I.diag( { 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 60.0 } );
142 
143  vpColVector integral( 7, 0 ), G( 7, 0 ), tau_J( 7, 0 ), sig( 7, 0 );
144 
145  double mu = 4;
146  double dt = 0;
147 
148  double time_ref = vpTime::measureTimeSecond();
149  double time_start_trajectory, time_prev, time_cur;
150  double delay_before_trajectory = 0.5; // Start sinusoidal trajectory after this delay in [s]
151 
152  while ( !final_quit )
153  {
154  time_cur = vpTime::measureTimeSecond();
155 
156  robot.getPosition( vpRobot::JOINT_STATE, q );
157  robot.getVelocity( vpRobot::JOINT_STATE, dq );
158  robot.getForceTorque( vpRobot::JOINT_STATE, tau );
159  robot.getMass( B );
160  robot.getCoriolis( C );
161  // robot.getFriction( F );
162 
163  if ( time_cur - time_ref < delay_before_trajectory )
164  {
165  time_start_trajectory = time_cur; // To ensure exp() = 1
166  first_time = true;
167  }
168  else if ( !start_trajectory ) // After the delay we start joint trajectory
169  {
170  time_start_trajectory = time_cur;
171  start_trajectory = true;
172  }
173 
174  // Compute joint trajectories
175  // clang-format off
176  qd[0] = q0[0] + ( start_trajectory ? std::sin( 2 * M_PI * 0.1 * ( time_cur - time_start_trajectory ) ) : 0 );
177  dqd[0] = ( start_trajectory ? 2 * M_PI * 0.1 * std::cos( 2 * M_PI * 0.1 * ( time_cur - time_start_trajectory ) ) : 0 );
178  ddqd[0] = ( start_trajectory ? - std::pow( 2 * 0.1 * M_PI, 2 ) * std::sin( 2 * M_PI * 0.1 * ( time_cur - time_start_trajectory ) ) : 0 );
179 
180  qd[2] = q0[2] + ( start_trajectory ? ( M_PI / 16 ) * std::sin( 2 * M_PI * 0.2 * ( time_cur - time_start_trajectory ) ) : 0 );
181  dqd[2] = ( start_trajectory ? M_PI * ( M_PI / 8 ) * 0.2 * std::cos( 2 * M_PI * 0.2 * ( time_cur - time_start_trajectory ) ) : 0 );
182  ddqd[2] = ( start_trajectory ? -M_PI * M_PI * 0.2 * ( M_PI / 4 ) * std::sin( 2 * M_PI * 0.2 * ( time_cur - time_start_trajectory ) ) : 0 );
183 
184  qd[3] = q0[3] + ( start_trajectory ? 0.25 * std::sin( 2 * M_PI * 0.05 * ( time_cur - time_start_trajectory ) ) : 0 );
185  dqd[3] = ( start_trajectory ? 2 * M_PI * 0.05 * 0.25 * std::cos( 2 * M_PI * 0.05 * ( time_cur - time_start_trajectory ) ) : 0 );
186  ddqd[3] = ( start_trajectory ? -0.25 * std::pow( 2 * 0.05 * M_PI, 2 ) * std::sin( 2 * M_PI * 0.05 * ( time_cur - time_start_trajectory ) ) : 0 );
187 
188  //qd[6] = q0[6] + ( start_trajectory ? std::sin( 2 * M_PI * 0.1 * ( time_cur - time_start_trajectory ) ) : 0 );
189  //dqd[6] = ( start_trajectory ? 2 * M_PI * 0.1 * std::cos( 2 * M_PI * 0.1 * ( time_cur - time_start_trajectory ) ) : 0 );
190  //ddqd[6] = ( start_trajectory ? -std::pow( 2 * 0.1 * M_PI, 2 ) * std::sin( 2 * M_PI * 0.1 * ( time_cur - time_start_trajectory ) ) : 0 );
191  // clang-format on
192 
193  dt = time_cur - time_prev;
194  if ( start_trajectory )
195  {
196  integral += ( qd - q ) * dt;
197  }
198 
199  // Compute the control law
200  tau_d = B * ( K * ( qd - q ) + D * ( dqd - dq ) + I * ( integral ) + ddqd ) + C + F;
201 
202  if ( first_time )
203  {
204  tau_d0 = tau_d;
205  }
206 
207  tau_cmd = tau_d - tau_d0 * std::exp( -mu * ( time_cur - time_start_trajectory ) );
208 
209  // Send command to the torque robot
210  robot.setForceTorque( vpRobot::JOINT_STATE, tau_cmd );
211 
212  vpColVector norm( 1, vpMath::deg( std::sqrt( ( qd - q ).sumSquare() ) ) );
213  plotter->plot( 0, time_cur - time_ref, q );
214  plotter->plot( 1, time_cur - time_ref, qd - q );
215  plotter->plot( 2, time_cur - time_ref, tau );
216  plotter->plot( 3, time_cur - time_ref, norm );
217 
218  vpMouseButton::vpMouseButtonType button;
219  if ( vpDisplay::getClick( plotter->I, button, false ) )
220  {
221  if ( button == vpMouseButton::button3 )
222  {
223  final_quit = true;
224  tau_cmd = 0;
225  std::cout << "Stop the robot " << std::endl;
226  robot.setRobotState( vpRobot::STATE_STOP );
227  }
228  }
229 
230  if ( opt_verbose )
231  {
232  std::cout << "dt: " << dt << std::endl;
233  }
234 
235  time_prev = time_cur;
236  vpTime::wait( time_cur * 1000., 1. ); // Sync loop at 1000 Hz (1 ms)
237  }
238 
239  if ( opt_save_data )
240  {
241  plotter->saveData( 0, "real-joint-position.txt", "# " );
242  plotter->saveData( 1, "real-joint-position-error.txt", "# " );
243  plotter->saveData( 2, "real-joint-torque-measure.txt", "# " );
244  plotter->saveData( 3, "real-joint-error-norm.txt", "# " );
245  }
246  if ( plotter != nullptr )
247  {
248  delete plotter;
249  plotter = nullptr;
250  }
251  }
252  catch ( const vpException &e )
253  {
254  std::cout << "ViSP exception: " << e.what() << std::endl;
255  std::cout << "Stop the robot " << std::endl;
256  robot.setRobotState( vpRobot::STATE_STOP );
257  return EXIT_FAILURE;
258  }
259  catch ( const franka::NetworkException &e )
260  {
261  std::cout << "Franka network exception: " << e.what() << std::endl;
262  std::cout << "Check if you are connected to the Franka robot"
263  << " or if you specified the right IP using --ip command line option set by default to 192.168.1.1. "
264  << std::endl;
265  return EXIT_FAILURE;
266  }
267  catch ( const std::exception &e )
268  {
269  std::cout << "Franka exception: " << e.what() << std::endl;
270  return EXIT_FAILURE;
271  }
272 
273  return 0;
274 }
275 #else
276 int
278 {
279 #if !defined( VISP_HAVE_DISPLAY )
280  std::cout << "Install display capabilities: X11, OpenCV" << std::endl;
281 #endif
282 #if !defined( VISP_HAVE_FRANKA )
283  std::cout << "Install libfranka." << std::endl;
284 #endif
285  return 0;
286 }
287 #endif


visp_ros
Author(s): Francois Pasteau, Fabien Spindler, Gatien Gaumerais, Alexander Oliva
autogenerated on Tue Mar 1 2022 00:03:22