VrepRobotArmDriver.hpp
Go to the documentation of this file.
1 #ifndef _GRL_VREP_ROBOT_ARM_DRIVER_HPP_
2 #define _GRL_VREP_ROBOT_ARM_DRIVER_HPP_
3 
4 #include <iostream>
5 #include <memory>
6 #include <array>
7 
8 #include <boost/range.hpp>
9 #include <boost/log/trivial.hpp>
10 #include <boost/exception/all.hpp>
11 #include <boost/algorithm/string.hpp>
12 #include <boost/lexical_cast.hpp>
13 
14 #include "grl/vrep/Vrep.hpp"
15 
16 #include "v_repLib.h"
17 
18 
19 namespace grl { namespace vrep {
20 
21 
22  /// @todo TODO(ahundt) joint to link and joint to respondable only works for v-rep provided scene heirarchy names, modify full class so these workarounds aren't needed
23  /// in other words this assumes everything is named like the following:
24  /// joint1: LBR_iiwa_14_R820_joint1
25  /// link1: LBR_iiwa_14_R820_link1
26  /// link1_respondable: LBR_iiwa_14_R820_link1_resp
27  ///
28  /// That assumption is definitely not true and names can be arbitrary so they must be provided
29  /// through the v-rep lua API.
30  std::vector<std::string> jointToLink(const std::vector<std::string>& jointNames)
31  {
32  std::vector<std::string> linkNames;
33  for(std::string jointName : jointNames)
34  {
35  boost::algorithm::replace_last(jointName,"joint","link");
36  linkNames.push_back(jointName);
37  }
38  /// @todo TODO(ahundt) FIX HACK! Manually adding last link
39  linkNames.push_back("LBR_iiwa_14_R820_link8");
40  return linkNames;
41  }
42 
43  /// @todo TODO(ahundt) HACK joint to link and joint to respondable only works for v-rep provided scene heirarchy names, modify full class so these workarounds aren't needed.
44  /// @see jointToLink
45  std::vector<std::string> jointToLinkRespondable(std::vector<std::string> jointNames)
46  {
47  auto linkNames = jointToLink(jointNames);
48 
49  std::vector<std::string> linkNames_resp;
50 
51  int i = 1;
52  for(std::string linkName : linkNames)
53  {
54  /// @todo TODO(ahundt) link 1 isn't respondable because it is anchored to the ground, but should there be an empty string so the indexes are consistent or skip it entirely? (currently skipping)
55  if(i!=1)
56  {
57  boost::algorithm::replace_last(linkName,"link" + boost::lexical_cast<std::string>(i),"link" + boost::lexical_cast<std::string>(i) + "_resp");
58  linkNames_resp.push_back(linkName);
59  }
60  ++i;
61  }
62 
63  return linkNames_resp;
64  }
65 
66 /// @brief C++ interface for any open chain V-REP robot arm
67 ///
68 /// VrepRobotArmDriver makes it easy to specify and interact with the
69 /// joints in a V-REP defined robot arm in a consistent manner.
70 ///
71 /// @todo add support for links, particularly the respondable aspects, see LBR_iiwa_14_R820_joint1_resp in RoboneSimulation.ttt
72 /// @todo write generic getters and setters for this object like in KukaFRIalgorithm.hpp and the member functions of KukaFRIdriver, KukaJAVAdriver
73 class VrepRobotArmDriver : public std::enable_shared_from_this<VrepRobotArmDriver> {
74 public:
75 
76  enum ParamIndex {
78  RobotFlangeTipName, // the tip of the base robot model without tools, where tools get attached
79  RobotTipName, // the tip of the robot tool or end effector, where stuff interacts
83  };
84 
85  typedef std::tuple<
86  std::vector<std::string>,
87  std::string,
88  std::string,
89  std::string,
90  std::string,
91  std::string
92  > Params;
93 
94  typedef std::tuple<
95  std::vector<int>,
96  int,
97  int,
98  int,
99  int,
100  int
102 
103  static const Params defaultParams()
104  {
105  std::vector<std::string> jointNames{
106  "LBR_iiwa_14_R820_joint1" , // Joint1Handle,
107  "LBR_iiwa_14_R820_joint2" , // Joint2Handle,
108  "LBR_iiwa_14_R820_joint3" , // Joint3Handle,
109  "LBR_iiwa_14_R820_joint4" , // Joint4Handle,
110  "LBR_iiwa_14_R820_joint5" , // Joint5Handle,
111  "LBR_iiwa_14_R820_joint6" , // Joint6Handle,
112  "LBR_iiwa_14_R820_joint7" // Joint7Handle,
113  };
114 
115  return std::make_tuple(
116  jointNames , // JointNames
117  "RobotFlangeTip" , // RobotFlangeTipName,
118  "RobotMillTip" , // RobotTipName,
119  "RobotMillTipTarget" , // RobotTargetName,
120  "Robotiiwa" , // RobotTargetBaseName,
121  "IK_Group1_iiwa" // RobotIkGroup
122  );
123  }
124 
125  static const Params measuredArmParams()
126  {
127  std::vector<std::string> jointNames{
128  "LBR_iiwa_14_R820_joint1#0" , // Joint1Handle,
129  "LBR_iiwa_14_R820_joint2#0" , // Joint2Handle,
130  "LBR_iiwa_14_R820_joint3#0" , // Joint3Handle,
131  "LBR_iiwa_14_R820_joint4#0" , // Joint4Handle,
132  "LBR_iiwa_14_R820_joint5#0" , // Joint5Handle,
133  "LBR_iiwa_14_R820_joint6#0" , // Joint6Handle,
134  "LBR_iiwa_14_R820_joint7#0" // Joint7Handle,
135  };
136 
137  return std::make_tuple(
138  jointNames , // JointNames
139  "RobotFlangeTip#0" , // RobotFlangeTipName,
140  "RobotMillTip#0" , // RobotTipName,
141  "RobotMillTipTarget#0" , // RobotTargetName,
142  "Robotiiwa#0" , // RobotTargetBaseName,
143  "IK_Group1_iiwa#0" // RobotIkGroup
144  );
145  }
146 
147 
148  /// unique tag type so State never
149  /// conflicts with a similar tuple
150  struct JointStateTag{};
151 
161  };
162 
163 
164  typedef std::vector<float> JointScalar;
165 
166  /// @see http://www.coppeliarobotics.com/helpFiles/en/apiFunctions.htm#simGetJointMatrix for data layout information
167  typedef std::array<float,12> TransformationMatrix;
168  typedef std::vector<TransformationMatrix> TransformationMatrices;
169 
170  typedef std::tuple<
171  JointScalar, // jointPosition
172  // JointScalar // JointVelocity // no velocity yet
173  JointScalar, // jointForce
174  JointScalar, // jointTargetPosition
175  JointScalar, // JointLowerPositionLimit
176  JointScalar, // JointUpperPositionLimit
177  TransformationMatrices, // jointTransformation
178  JointStateTag, // JointStateTag unique identifying type so tuple doesn't conflict
179  JointScalar // externalTorque
180  > State;
181 
182 
184  : params_(params)
185  {
186  }
187 
188 /// @todo create a function that calls simGetObjectHandle and throws an exception when it fails
189 /// @warning getting the ik group is optional, so it does not throw an exception
190 void construct() {
191  std::vector<int> jointHandle;
192  getHandleFromParam<JointNames>(params_,std::back_inserter(jointHandle));
193  handleParams_ =
194  std::make_tuple(
195  std::move(jointHandle) //Obtain Joint Handles
196  ,getHandleFromParam<RobotTipName> (params_) //Obtain RobotTip handle
197  ,getHandleFromParam<RobotFlangeTipName> (params_) //Obtain RobotTip handle
198  ,getHandleFromParam<RobotTargetName> (params_)
199  ,getHandleFromParam<RobotTargetBaseName> (params_)
200  ,simGetIkGroupHandle(std::get<RobotIkGroup> (params_).c_str())
201  );
202 
203  /// @todo TODO(ahundt) move these functions/member variables into params_ object, take as parameters from lua!
204  linkNames = jointToLink(std::get<JointNames>(params_));
205  getHandles(linkNames, std::back_inserter(linkHandles));
206  linkRespondableNames = jointToLinkRespondable(std::get<JointNames>(params_));
207  // First link is fixed to the ground so can't be respondable
208  linkHandles.push_back(-1);
209  getHandles(boost::make_iterator_range(linkRespondableNames.begin()+1,linkRespondableNames.end()), std::back_inserter(linkHandles));
210 
211  allHandlesSet = true;
212 }
213 
214 
215 /// @return 0 if ok 1 if problem
216 /// @todo handle cyclic joints (see isCyclic below & simGetJointInterval)
217 bool getState(State& state){
218  if(!allHandlesSet) return false;
219  const std::vector<int>& jointHandle = std::get<JointNames>(handleParams_);
220 
221  std::get<JointPosition> (state).resize(jointHandle.size());
222  std::get<JointForce> (state).resize(jointHandle.size());
223  std::get<JointTargetPosition> (state).resize(jointHandle.size());
224  std::get<JointMatrix> (state).resize(jointHandle.size());
225  std::get<JointLowerPositionLimit> (state).resize(jointHandle.size());
226  std::get<JointUpperPositionLimit> (state).resize(jointHandle.size());
227 
228  enum limit {
229  lower
230  ,upper
231  ,numLimits
232  };
233 
234  simBool isCyclic;
235  float jointAngleInterval[2]; // min,max
236  double inf = std::numeric_limits<double>::infinity();
237 
238  for (std::size_t i=0 ; i < jointHandle.size() ; i++)
239  {
240  int currentJointHandle = jointHandle[i];
241  simGetJointPosition(currentJointHandle,&std::get<JointPosition>(state)[i]); //retrieves the intrinsic position of a joint (Angle for revolute joint)
242  simGetJointForce(currentJointHandle,&std::get<JointForce>(state)[i]); //retrieves the force or torque applied to a joint along/about its active axis. This function retrieves meaningful information only if the joint is prismatic or revolute, and is dynamically enabled.
243  simGetJointTargetPosition(currentJointHandle,&std::get<JointTargetPosition>(state)[i]); //retrieves the target position of a joint
244  simGetJointMatrix(currentJointHandle,&std::get<JointMatrix>(state)[i][0]); //retrieves the intrinsic transformation matrix of a joint (the transformation caused by the joint movement)
245  simGetJointInterval(currentJointHandle,&isCyclic,jointAngleInterval);
246 
247  /// @todo TODO(ahundt) is always setting infinity if it is cyclic the right thing to do?
248  if(isCyclic)
249  {
250  std::get<JointLowerPositionLimit>(state)[i] = -inf;
251  std::get<JointUpperPositionLimit>(state)[i] = inf;
252  }
253  else
254  {
255  std::get<JointLowerPositionLimit>(state)[i] = jointAngleInterval[lower];
256  std::get<JointUpperPositionLimit>(state)[i] = jointAngleInterval[upper];
257  }
258 
259  }
260 
261 // BOOST_LOG_TRIVIAL(info) << "simJointPostition = " << simJointPosition << std::endl;
262 // BOOST_LOG_TRIVIAL(info) << "simJointForce = " << simJointForce << std::endl;
263 // BOOST_LOG_TRIVIAL(info) << "simJointTargetPostition = " << simJointTargetPosition << std::endl;
264 // BOOST_LOG_TRIVIAL(info) << "simJointTransformationMatrix = " << simJointTransformationMatrix << std::endl;
265 //
266 // float simTipPosition[3];
267 // float simTipOrientation[3];
268 //
269 // simGetObjectPosition(target, targetBase, simTipPosition);
270 // simGetObjectOrientation(target, targetBase, simTipOrientation);
271 //
272 // for (int i = 0 ; i < 3 ; i++)
273 // {
274 // BOOST_LOG_TRIVIAL(info) << "simTipPosition[" << i << "] = " << simTipPosition[i] << std::endl;
275 // BOOST_LOG_TRIVIAL(info) << "simTipOrientation[" << i << "] = " << simTipOrientation[i] << std::endl;
276 //
277 // }
278  // Send updated position to the real arm based on simulation
279  return false;
280 }
281 
282 
283 
284 
285 bool setState(State& state) {
286  // Step 1
287  ////////////////////////////////////////////////////
288  // call the functions here and just print joint angles out
289  // or display something on the screens
290 
291  ///////////////////
292  // call our object to get the latest real kuka state
293  // then use the functions below to set the simulation state
294  // to match
295 
296  /////////////////// assuming given real joint position (angles), forces, target position and target velocity
297  if(!allHandlesSet) return false;
298  const std::vector<int>& jointHandle = std::get<JointNames>(handleParams_);
299  std::vector<float> realJointPosition = std::get<JointPosition>(state);
300  std::vector<float> realJointForce = std::get<JointForce>(state);
301  std::vector<float> externalJointForce = std::get<ExternalTorque>(state);
302 
303  // setting the simulation variables to data from real robot (here they have been assumed given)
304 
305  for (int i=0 ; i < 7 ; i++)
306  {
307  simSetJointPosition(jointHandle[i],realJointPosition[i]); //Sets the intrinsic position of a joint. May have no effect depending on the joint mode
308 
309 
310  //simSetJointTargetPosition(jointHandle[i],realJointTargetPosition[i]); //Sets the target position of a joint if the joint is in torque/force mode (also make sure that the joint's motor and position control are enabled
311 
312  //simSetJointForce(jointHandle[i],realJointForce[i]); //Sets the maximum force or torque that a joint can exert. This function has no effect when the joint is not dynamically enabled
313 
314 
315  //simSetJointTargetVelocity(jointHandle[i],realJointTargetVelocity[i]); //Sets the intrinsic target velocity of a non-spherical joint. This command makes only sense when the joint mode is: (a) motion mode: the joint's motion handling feature must be enabled (simHandleJoint must be called (is called by default in the main script), and the joint motion properties must be set in the joint settings dialog), (b) torque/force mode: the dynamics functionality and the joint motor have to be enabled (position control should however be disabled)
316  }
317 
318  if (externalHandlesSet) {
319 
320  }
321 
322  else {
323 
324  for (int i=0 ; i < 7 ; i++) {
325  std::string torqueString = boost::lexical_cast<std::string>(externalJointForce[i]);
326  char * externalTorqueBytes = new char[torqueString.length()+1];
327  std::strcpy(externalTorqueBytes, torqueString.c_str());
328 
329  simAddObjectCustomData(jointHandle[i], externalTorqueHandle, externalTorqueBytes, torqueString.length()+1);
330  }
331  }
332 
333  return true;
334 }
335 
336 
337 
338 /// @todo deal with !allHandlesSet()
339 const std::vector<int>& getJointHandles()
340 {
341  return std::get<JointNames>(handleParams_);
342 }
343 
344 const std::vector<std::string>& getJointNames()
345 {
346  return std::get<JointNames>(params_);
347 }
348 
349 
350 /// @todo deal with !allHandlesSet()
351 const std::vector<int>& getLinkHandles()
352 {
353  return linkHandles;
354 }
355 
356 const std::vector<std::string>& getLinkNames()
357 {
358  return linkNames;
359 }
360 
361 
362 /// @todo deal with !allHandlesSet()
363 const std::vector<int>& getLinkRespondableHandles()
364 {
365  return linkRespondableHandles;
366 }
367 
368 const std::vector<std::string>& getLinkRespondableNames()
369 {
370  return linkRespondableNames;
371 }
372 
373 
374 
375 const Params & getParams(){
376  return params_;
377 }
378 
380  return handleParams_;
381 }
382 
383 private:
384 
385 Params params_;
386 VrepHandleParams handleParams_;
387 
388 /// @todo TODO(ahundt) put these into params or handleparams as appropriate
389 std::vector<std::string> linkNames;
390 /// @todo TODO(ahundt) put these into params or handleparams as appropriate
391 std::vector<std::string> linkRespondableNames;
392 
393 /// @todo TODO(ahundt) put these into params or handleparams as appropriate
394 std::vector<int> linkHandles;
395 /// @todo TODO(ahundt) put these into params or handleparams as appropriate
396 std::vector<int> linkRespondableHandles;
397 
398 /// This is a unique identifying handle for external torque values
399 /// since they are set as V-REP custom data.
400 /// @see simAddObjectCustomData
401 int externalTorqueHandle = 310832412;
402 
403 volatile bool allHandlesSet = false;
404 volatile bool externalHandlesSet = false;
405 
406 
407 
408 };
409 
410 
411 
412 
413 }} // grl::vrep
414 
415 #endif // _GRL_VREP_ROBOT_ARM_DRIVER_HPP_
std::array< float, 12 > TransformationMatrix
ptrSimGetJointPosition simGetJointPosition
Definition: v_repLib.cpp:79
ptrSimGetJointMatrix simGetJointMatrix
Definition: v_repLib.cpp:87
C++ interface for any open chain V-REP robot arm.
std::vector< std::string > jointToLinkRespondable(std::vector< std::string > jointNames)
ptrSimGetIkGroupHandle simGetIkGroupHandle
Definition: v_repLib.cpp:157
const std::vector< std::string > & getJointNames()
ptrSimGetJointInterval simGetJointInterval
Definition: v_repLib.cpp:89
static const Params defaultParams()
ptrSimSetJointPosition simSetJointPosition
Definition: v_repLib.cpp:80
VrepRobotArmDriver(Params params=defaultParams())
const VrepHandleParams & getVrepHandleParams()
const std::vector< int > & getLinkHandles()
OutputIterator getHandles(const SinglePassRange inputRange, OutputIterator out)
Definition: Vrep.hpp:20
std::tuple< std::vector< std::string >, std::string, std::string, std::string, std::string, std::string > Params
std::tuple< std::vector< int >, int, int, int, int, int > VrepHandleParams
const std::vector< std::string > & getLinkNames()
std::vector< std::string > jointToLink(const std::vector< std::string > &jointNames)
std::vector< TransformationMatrix > TransformationMatrices
const std::vector< int > & getLinkRespondableHandles()
ptrSimGetJointTargetPosition simGetJointTargetPosition
Definition: v_repLib.cpp:82
unsigned char simBool
Definition: v_repTypes.h:36
ptrSimAddObjectCustomData simAddObjectCustomData
Definition: v_repLib.cpp:168
const std::vector< std::string > & getLinkRespondableNames()
ptrSimGetJointForce simGetJointForce
Definition: v_repLib.cpp:323
const std::vector< int > & getJointHandles()
std::tuple< JointScalar, JointScalar, JointScalar, JointScalar, JointScalar, TransformationMatrices, JointStateTag, JointScalar > State
static const Params measuredArmParams()