diff --git a/source/armarx/control/pointing/core/Pointing.cpp b/source/armarx/control/pointing/core/Pointing.cpp index 1f6426fe5f3f14f5e73678689b1ca270d648b002..7352a446d0e65af31d8f26ffcb1a34e39609ef24 100644 --- a/source/armarx/control/pointing/core/Pointing.cpp +++ b/source/armarx/control/pointing/core/Pointing.cpp @@ -84,20 +84,28 @@ namespace armarx::control::pointing::core Pointing::computTrajectory(VirtualRobot::RobotPtr robot, Side side, Eigen::Vector3f target) { ARMARX_VERBOSE << "Computing trajectory..."; - auto ik = PointingIK(robot, side); - armarx::TrajectoryPtr traj = ik.computeTrajectory(target); - if (not traj) - { - ARMARX_WARNING << "IK didn't find a solution"; - throw PointingFailedException(); - } - ARMARX_VERBOSE << "Done computing trajectory"; + auto ik = PointingIK(robot, side, target); - if (traj->size() == 1) // forearm already aligned with target + if (ik.isTargetReached()) // forearm already aligned with target { return armarx::TrajectoryPtr(new Trajectory); } - return traj; + + do + { + if (ik.optimize() < 1e-6) + { + ARMARX_WARNING << "PointingIK didn't find a solution"; + throw PointingFailedException(); + } + if (aborted) + { + ARMARX_INFO << "Pointing aborted."; + throw PointingAbortedException(); + } + } while (not ik.isTargetReached()); + + return ik.getTrajectory(); } void diff --git a/source/armarx/control/pointing/core/PointingIK.cpp b/source/armarx/control/pointing/core/PointingIK.cpp index c7b903cbfcadb43d3302a90380567edd29643cf4..d29958582af69c86c5ae0314a42086dafce2d729 100644 --- a/source/armarx/control/pointing/core/PointingIK.cpp +++ b/source/armarx/control/pointing/core/PointingIK.cpp @@ -6,7 +6,7 @@ namespace armarx::control::pointing::core { - PointingIK::PointingIK(VirtualRobot::RobotPtr robot, Side side) + PointingIK::PointingIK(VirtualRobot::RobotPtr robot, Side side, Eigen::Vector3f& target) { auto humanMapping = robot->getHumanMapping(); ARMARX_CHECK(humanMapping) << "Robot '" << robot->getName() << "' has no human mapping"; @@ -31,39 +31,41 @@ namespace armarx::control::pointing::core *reducedRobot_->getNode(elbow), side == LEFT ? reducedRobot_->humanMapping()->leftArm : reducedRobot_->humanMapping()->rightArm); - } - TrajectoryPtr - PointingIK::computeTrajectory(Eigen::Vector3f& target) - { ik_->setPointingTarget(target.cast<double>() / 1000); // simox uses meters - // actuated joints x timesteps - std::vector<std::vector<double>> configs(ik_->getNodeNames().size()); - auto appendConfig = [&configs](Eigen::VectorXd config) - { - for (size_t i = 0; i < configs.size(); i++) - { - configs[i].push_back(config[i]); - } - }; + trajData.assign(ik_->getNodeNames().size(), std::vector<double>()); + appendTrajData(ik_->getJointValues()); + } - appendConfig(ik_->getJointValues()); + bool + PointingIK::isTargetReached() + { + return ik_->isTargetReached(); + } + double + PointingIK::optimize() + { Eigen::VectorXd prevJointValues = ik_->getJointValues(); - while (not ik_->isTargetReached()) - { - ik_->optimize(); - if ((ik_->getJointValues() - prevJointValues).norm() < 1e-6) - { - return nullptr; - } + ik_->optimize(); + appendTrajData(ik_->getJointValues()); + return (ik_->getJointValues() - prevJointValues).norm(); + } - appendConfig(ik_->getJointValues()); - prevJointValues = ik_->getJointValues(); - } + TrajectoryPtr + PointingIK::getTrajectory() + { + return new Trajectory(trajData, Ice::DoubleSeq(), ik_->getNodeNames()); + } - return new Trajectory(configs, Ice::DoubleSeq(), ik_->getNodeNames()); + void + PointingIK::appendTrajData(const Eigen::VectorXd& jointValues) + { + for (size_t i = 0; i < trajData.size(); i++) + { + trajData[i].push_back(jointValues[i]); + } } } // namespace armarx::control::pointing::core diff --git a/source/armarx/control/pointing/core/PointingIK.h b/source/armarx/control/pointing/core/PointingIK.h index 8660d52ab28d4f5ce26be320a44e13c42146d7e0..eb9942f3735343a8ec1b258543b0832aff448b62 100644 --- a/source/armarx/control/pointing/core/PointingIK.h +++ b/source/armarx/control/pointing/core/PointingIK.h @@ -10,11 +10,29 @@ namespace armarx::control::pointing::core { /** - * @brief IK to compute joint configurations for a pointing gesture. + * @brief IK to compute trajectory for a pointing gesture. * - * Wrapper for simox-control's method::example::PointingIK. Computes pointing gesture joint - * configurations that line up the forearm with the target. Uses the robot's human mapping to - * obtain relevant joints: All arm-joints until (exluding) the wrist are beeing used. + * Wrapper for simox-control's method::example::PointingIK. Computes a trajectory for a + * pointing gesture that lines up the forearm with a target. Uses the robot's human mapping to + * obtain relevant joints: All arm-joints until (excluding) the wrist are being used. + * + * This class keeps an internal robot model. Each call to @ref optimize() optimizes the joint + * configuration regarding pointing towards the target. @ref isTargetReached() returns whether + * the robot in the latest configuration already points at the target. @ref getTrajectory() + * returns the sequence of generated configurations as Trajectory. + * + * Example usage: + * + * @code + * ik = PointingIK(...); + * + * while (not ik.isTargetReached()) { + * if (ik.optimize) < 1e-6 { + * return nullptr; + * } + * } + * return ik.getTrajectory(); + * @endcode * * @ingroup Library-pointing */ @@ -26,35 +44,45 @@ namespace armarx::control::pointing::core * @param robot Robot model with current robot configuration to be used by the IK. Must * provide a human mapping. * @param side Side of the arm to point with. + * @param target Target position to point at in the global coordinate system (mm). */ - PointingIK(VirtualRobot::RobotPtr robot, Side side); + PointingIK(VirtualRobot::RobotPtr robot, Side side, Eigen::Vector3f& target); + /** + * @return Whether the robot in the latest joint configuration (from @ref optimize()) + * already points at the target. + */ + bool isTargetReached(); /** - * @brief Compute a joint trajectory ending in a configuration in which the robot points in - * the direction of the passed target position. - * - * The initial timestep of the trajectory contains the current joint configuration of the - * robot passed to the constructor. The following timesteps contain the step-by-step - * optimized configurations until the end configuration is reached. The trajectory is - * constructed without timestamps, i.e., has a duration of 1s with equidistant timesteps. + * @brief Optimizes the joint configuration of the internal robot model regarding pointing + * towards the target. + * @return Difference between the previous and new joint configurations. May be used to + * determine if the IK is unable to find a solution. + */ + double optimize(); + + /** + * @brief Constructs a trajectory containing the sequence of joint configurations from the + * calls to @ref optimize(). * - * Neither the generated trajectory nor the end configuration are guaranteed to be self- - * collision-free. Furthermore, generated trajectories aren't efficient in reaching the end + * Neither the trajectory nor the end configuration are guaranteed to be self- + * collision free. Furthermore, the trajectories aren't efficient in reaching the end * configuration. * - * This method may only be called once to ensure a well-defined initial robot configuration. + * `getTrajectory()->size()` will equal the number of calls to @ref optimize() plus one for + * the initial joint configuration * - * @param target Target position to point at in the global coordinate system (mm). - * @return The computed trajectory. Null if no solution was found. If the robot has already - * pointed at the target, the trajectory only contains the initial timestep (i.e. - * size()==1). + * @return The constructed trajectory. */ - TrajectoryPtr computeTrajectory(Eigen::Vector3f& target); + armarx::TrajectoryPtr getTrajectory(); private: std::unique_ptr<simox::control::simox::robot::Robot> reducedRobot_; std::unique_ptr<simox::control::method::example::PointingIK> ik_; + + std::vector<std::vector<double>> trajData; // actuated joints x timesteps + void appendTrajData(const Eigen::VectorXd& jointValues); }; } // namespace armarx::control::pointing::core