VrepVFController.hpp
Go to the documentation of this file.
1 /// @author Andrew Hundt <athundt@gmail.com>
2 #ifndef _VREP_VF_CONTROLLER_
3 #define _VREP_VF_CONTROLLER_
4 
5 /// @todo remove IGNORE_ROTATION or make it a runtime configurable parameter
6 // #define IGNORE_ROTATION
7 
8 
9 
10 #include <string>
11 #include <tuple>
12 #include <boost/format.hpp>
13 #include <Eigen/Core>
14 #include <Eigen/Geometry>
15 
16 #include <sawConstraintController/mtsVFController.h>
17 
19 #include "grl/vrep/Vrep.hpp"
22 #include "grl/vrep/Eigen.hpp"
23 
24 #include <boost/lexical_cast.hpp>
25 #include <boost/range/algorithm/copy.hpp>
26 
27 namespace grl {
28 
29 /// @todo verify Robotiiwa is the correct base, and RobotMillTipTarget is the right target, because if the transform doesn't match the one in the jacobian the algorithm will break
30 //template<typename DesiredKinematics = DesiredKinematicsObject>
32 {
33 public:
35 
36  //using parent_type::currentKinematicsStateP_;
37  //using parent_type::parent_type::InitializeKinematicsState;
38 
42  };
43 
44  typedef std::tuple<
45  std::string // DesiredKinematicsObjectName
46  ,std::string // IKGroupName
47  > Params;
48 
50  {
51  return std::make_tuple("RobotMillTipTarget","IK_Group1_iiwa");
52  }
53 
54  /// @todo need to call parent constructor:
55  /*! Constructor
56  */
57  VrepInverseKinematicsController(size_t num_joints = 7, mtsVFBase::CONTROLLERMODE cm = mtsVFBase::CONTROLLERMODE::JPOS):
58  InverseKinematicsController(num_joints,cm)
59  {
60  }
61 
62  void construct(Params params = defaultParams()){
63  // get kinematics group name
64  // get number of joints
65  VrepRobotArmDriverP_ = std::make_shared<vrep::VrepRobotArmDriver>();
66  VrepRobotArmDriverP_->construct();
67 
68  ikGroupHandle_ = simGetIkGroupHandle(std::get<IKGroupName>(params).c_str());
69  simSetExplicitHandling(ikGroupHandle_,1); // enable explicit handling for the ik
70 
71  this->currentKinematicsStateP_->Name = std::get<IKGroupName>(params);
72 
73  this->desiredKinematicsStateP_->Name = std::get<DesiredKinematicsObjectName>(params);
74 
75  /// @todo set desiredKinematicsStateP name, INITIALIZE ALL MEMBER OBJECTS, & SET NAMES
76  //
77  positionLimitsName = std::get<IKGroupName>(params)+"_PositionLimits";
79 
80  velocityLimitsName = std::get<IKGroupName>(params)+"_VelocityLimits";
82 
83 // /// This will hold the Jacobian
84 // std::unique_ptr<prmKinematicsState> currentKinematicsStateP_;
85 //
86 // /// This will hold the xyz position and the rotation of where I want to go
87 // std::unique_ptr<prmKinematicsState> desiredKinematicsStateP_;
88 //
89 // // want to follow a goal position
90 // /// @todo will want to use an addVFFollow member function once it is added in
91 // std::unique_ptr<mtsVFDataBase> followVFP_;
92 //
93 // /// need velocity limits for the joints
94 // std::unique_ptr<mtsVFDataJointLimits> jointVelocityLimitsVFP_;
95 // /// joints cannot go to certain position
96 // std::unique_ptr<mtsVFDataJointLimits> jointPositionLimitsVFP_;
97 
98  /// @todo verify object lifetimes
99  //parent_type::parent_type::InitializeKinematicsState(this->currentKinematicsStateP_)
100 
101  // for each virtual fixture need names and number of rows
102 
103 
104  /// @todo read objective rows from vrep
105 
106  // Initialize Variables for update
107  //jointHandles_ = VrepRobotArmDriverP_->getJointHandles();
108  //int numJoints =jointHandles_.size();
109 
110 #ifndef IGNORE_ROTATION
111  /// @todo objectiveRows seems to currently be a 3 vector, may eventually want a rotation and translation, perhaps with quaternion rotation
112  followVFP_->ObjectiveRows = 6;
113 #else
114  followVFP_->ObjectiveRows = 3;
115 #endif
116  // set the names once for each object, only once
117  followVFP_->KinNames.push_back(currentKinematicsStateP_->Name);
118  followVFP_->KinNames.push_back(desiredKinematicsStateP_->Name);
119 
120  AddVFFollowPath(*followVFP_);
121 
122  /// @todo set vrep explicit handling of IK here, plus unset in destructor of this object
123  }
124 
125 
126 
127 
128 
129 
130 
131 
132 
133 
134 
135 
136 
137 
138 
139  /// check out sawConstraintController
141 
142  jointHandles_ = VrepRobotArmDriverP_->getJointHandles();
143  auto eigentestJacobian=::grl::vrep::getJacobian(*VrepRobotArmDriverP_);
144 
145  /// The row/column major order is swapped between cisst and VREP!
146  this->currentKinematicsStateP_->Jacobian.SetSize(eigentestJacobian.cols(),eigentestJacobian.rows());
147  Eigen::Map<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> > mckp2(this->currentKinematicsStateP_->Jacobian.Pointer(),this->currentKinematicsStateP_->Jacobian.cols(),this->currentKinematicsStateP_->Jacobian.rows());
148  mckp2 = eigentestJacobian.cast<double>();
149 
150 
151  //Eigen::Map<Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> > mf(eigentestJacobian,eigentestJacobian.cols(),eigentestJacobian.rows());
152  //Eigen::MatrixXf eigenJacobian = mf;
153  Eigen::MatrixXf eigenJacobian = eigentestJacobian;
154 
155 
156  ///////////////////////////////////////////////////////////
157  // Copy Joint Interval, the range of motion for each joint
158 
159 
160  // lower limits
161  auto & llim = std::get<vrep::VrepRobotArmDriver::JointLowerPositionLimit>(currentArmState_);
162  std::vector<double> llimits(llim.begin(),llim.end());
163  jointPositionLimitsVFP_->LowerLimits = vctDoubleVec(llimits.size(),&llimits[0]);
164 
165  // upper limits
166  auto & ulim = std::get<vrep::VrepRobotArmDriver::JointUpperPositionLimit>(currentArmState_);
167  std::vector<double> ulimits(ulim.begin(),ulim.end());
168  jointPositionLimitsVFP_->UpperLimits = vctDoubleVec(ulimits.size(),&ulimits[0]);
169 
170  // current position
171  auto & currentJointPos = std::get<vrep::VrepRobotArmDriver::JointPosition>(currentArmState_);
172  std::vector<double> currentJointPosVec(currentJointPos.begin(),currentJointPos.end());
173  vctDoubleVec vctDoubleVecCurrentJoints(currentJointPosVec.size(),&currentJointPosVec[0]);
174 
175  // update limits
176  /// @todo does this leak memory when called every time around?
177  UpdateJointPosLimitsVF(positionLimitsName,jointPositionLimitsVFP_->UpperLimits,jointPositionLimitsVFP_->LowerLimits,vctDoubleVecCurrentJoints);
178 
179 
180  const auto& handleParams = VrepRobotArmDriverP_->getVrepHandleParams();
181  Eigen::Affine3d currentEndEffectorPose =
183  std::get<vrep::VrepRobotArmDriver::RobotTipName>(handleParams)
184  ,std::get<vrep::VrepRobotArmDriver::RobotTargetBaseName>(handleParams)
185  );
186  auto currentEigenT = currentEndEffectorPose.translation();
187  auto& currentCisstT = currentKinematicsStateP_->Frame.Translation();
188  currentCisstT[0] = currentEigenT(0);
189  currentCisstT[1] = currentEigenT(1);
190  currentCisstT[2] = currentEigenT(2);
191 #ifndef IGNORE_ROTATION
192  Eigen::Map<Eigen::Matrix<double,3,3,Eigen::ColMajor>> ccr(currentKinematicsStateP_->Frame.Rotation().Pointer());
193  ccr = currentEndEffectorPose.rotation();
194 #endif // IGNORE_ROTATION
195  /// @todo set rotation component of current position
196 
197 
198  Eigen::Affine3d desiredEndEffectorPose =
200  std::get<vrep::VrepRobotArmDriver::RobotTargetName>(handleParams)
201  ,std::get<vrep::VrepRobotArmDriver::RobotTargetBaseName>(handleParams)
202  );
203  auto desiredEigenT = desiredEndEffectorPose.translation();
204  auto& desiredCisstT = desiredKinematicsStateP_->Frame.Translation();
205  desiredCisstT[0] = desiredEigenT(0);
206  desiredCisstT[1] = desiredEigenT(1);
207  desiredCisstT[2] = desiredEigenT(2);
208 #ifndef IGNORE_ROTATION
209  Eigen::Map<Eigen::Matrix<double,3,3,Eigen::ColMajor>> dcr(desiredKinematicsStateP_->Frame.Rotation().Pointer());
210  dcr = desiredEndEffectorPose.rotation();
211 #endif // IGNORE_ROTATION
212  /// @todo set rotation component of desired position
213 
214  // for debugging, the translation between the current and desired position in cartesian coordinates
215  auto inputDesired_dx = desiredCisstT - currentCisstT;
216 
217  vct3 dx_translation, dx_rotation;
218 
219  // Rotation part
220  vctAxAnRot3 dxRot;
221  vct3 dxRotVec;
222  dxRot.FromNormalized((currentKinematicsStateP_->Frame.Inverse() * desiredKinematicsStateP_->Frame).Rotation());
223  dxRotVec = dxRot.Axis() * dxRot.Angle();
224  dx_rotation[0] = dxRotVec[0];
225  dx_rotation[1] = dxRotVec[1];
226  dx_rotation[2] = dxRotVec[2];
227  //dx_rotation.SetAll(0.0);
228  dx_rotation = currentKinematicsStateP_->Frame.Rotation() * dx_rotation;
229 
230  Eigen::AngleAxis<float> tipToTarget_cisstToEigen;
231 
232  Eigen::Matrix3f rotmat;
233  double theta = std::sqrt(dx_rotation[0]*dx_rotation[0]+dx_rotation[1]*dx_rotation[1]+dx_rotation[2]*dx_rotation[2]);
234  rotmat= Eigen::AngleAxisf(theta,Eigen::Vector3f(dx_rotation[0]/theta,dx_rotation[1]/theta,dx_rotation[2]/theta));
235 
236 // std::cout << "\ntiptotarget \n" << tipToTarget.matrix() << "\n";
237 // std::cout << "\ntiptotargetcisst\n" << rotmat.matrix() << "\n";
238 
239 
240  //BOOST_LOG_TRIVIAL(trace) << "\n test desired dx: " << inputDesired_dx << " " << dx_rotation << "\noptimizer Calculated dx: " << optimizerCalculated_dx;
241  SetKinematics(*currentKinematicsStateP_); // replaced by name of object
242  // fill these out in the desiredKinematicsStateP_
243  //RotationType RotationMember; // vcRot3
244  //TranslationType TranslationMember; // vct3
245 
246  SetKinematics(*desiredKinematicsStateP_); // replaced by name of object
247  // call setKinematics with the new kinematics
248  // sawconstraintcontroller has kinematicsState
249  // set the jacobian here
250 
251  //////////////////////
252  /// @todo move code below here back under run_one updateKinematics() call
253 
254  /// @todo need to provide tick time in double seconds and get from vrep API call
255  float simulationTimeStep = simGetSimulationTimeStep();
256  UpdateOptimizer(simulationTimeStep);
257 
258  vctDoubleVec jointAngles_dt;
259  auto returncode = Solve(jointAngles_dt);
260 
261 
262  /// @todo check the return code, if it doesn't have a result, use the VREP version as a fallback and report an error.
263  if(returncode != nmrConstraintOptimizer::NMR_OK) BOOST_THROW_EXCEPTION(std::runtime_error("VrepInverseKinematicsController: constrained optimization error, please investigate"));
264 
265 
266  /// @todo: rethink where/when/how to send command for the joint angles. Return to LUA? Set Directly? Distribute via vrep send message command?
267  std::string str;
268  // str = "";
269  for (std::size_t i=0 ; i < jointHandles_.size() ; i++)
270  {
271  float currentAngle;
272  auto ret = simGetJointPosition(jointHandles_[i],&currentAngle);
273  BOOST_VERIFY(ret!=-1);
274  float futureAngle = currentAngle + jointAngles_dt[i];
275  //simSetJointTargetVelocity(jointHandles_[i],jointAngles_dt[i]/simulationTimeStep);
276  //simSetJointTargetPosition(jointHandles_[i],jointAngles_dt[i]);
277  //simSetJointTargetPosition(jointHandles_[i],futureAngle);
278  simSetJointPosition(jointHandles_[i],futureAngle);
279  str+=boost::lexical_cast<std::string>(jointAngles_dt[i]);
280  if (i<jointHandles_.size()-1)
281  str+=", ";
282  }
283  BOOST_LOG_TRIVIAL(trace) << "jointAngles_dt: "<< str;
284 
285  auto optimizerCalculated_dx = this->currentKinematicsStateP_->Jacobian * jointAngles_dt;
286 
287  BOOST_LOG_TRIVIAL(trace) << "\n desired dx: " << inputDesired_dx << " " << dx_rotation << "\noptimizer Calculated dx: " << optimizerCalculated_dx;
288  }
289 
290  /// may not need this it is in the base class
291  /// blocking call, call in separate thread, just allocates memory
292  void run_one(){
294 
295  }
296 
297 
298  /// may not need this it is in the base class
299  /// this will have output
300  /// blocking call, call in separate thread, just allocates memory
301  /// this runs the actual optimization algorithm
302  void solve(){
303 
304  }
305 
306  std::vector<int> jointHandles_; ///< @todo move this item back into VrepRobotArmDriver
308  std::shared_ptr<vrep::VrepRobotArmDriver> VrepRobotArmDriverP_;
310  std::string positionLimitsName;
311  std::string velocityLimitsName;
312 };
313 
314 } // namespace grl
315 
316 #endif
std::unique_ptr< mtsVFDataJointLimits > jointPositionLimitsVFP_
joints cannot go to certain position
ptrSimGetJointPosition simGetJointPosition
Definition: v_repLib.cpp:79
std::tuple< std::string,std::string > Params
Eigen::Affine3d getObjectTransform(int objectHandle, int relativeToObjectHandle=-1)
Definition: Eigen.hpp:135
VrepInverseKinematicsController(size_t num_joints=7, mtsVFBase::CONTROLLERMODE cm=mtsVFBase::CONTROLLERMODE::JPOS)
ptrSimGetIkGroupHandle simGetIkGroupHandle
Definition: v_repLib.cpp:157
vrep::VrepRobotArmDriver::State currentArmState_
grl::InverseKinematicsController parent_type
Eigen::MatrixXf getJacobian(vrep::VrepRobotArmDriver &driver, bool jacobianOnly=false)
get the Jacobian as calculated by vrep in an Eigen::MatrixXf in column major format ...
std::tuple< std::string,std::string,std::string,std::size_t,std::string,std::size_t,std::string,std::size_t > Params
ptrSimSetJointPosition simSetJointPosition
Definition: v_repLib.cpp:80
void updateKinematics()
check out sawConstraintController
std::unique_ptr< prmKinematicsState > desiredKinematicsStateP_
This will hold the xyz position and the rotation of where I want to go.
void construct(Params params=defaultParams())
std::unique_ptr< mtsVFDataJointLimits > jointVelocityLimitsVFP_
need velocity limits for the joints
std::unique_ptr< mtsVFDataBase > followVFP_
std::unique_ptr< prmKinematicsState > currentKinematicsStateP_
This will hold the Jacobian.
std::tuple< JointScalar, JointScalar, JointScalar, JointScalar, JointScalar, TransformationMatrices, JointStateTag, JointScalar > State
std::shared_ptr< vrep::VrepRobotArmDriver > VrepRobotArmDriverP_
ptrSimSetExplicitHandling simSetExplicitHandling
Definition: v_repLib.cpp:267
ptrSimGetSimulationTimeStep simGetSimulationTimeStep
Definition: v_repLib.cpp:181