Advertisement
ZdenekM

RivetingController

Jun 15th, 2017
554
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.62 KB | None | 0 0
  1. /******************************************************************************
  2.  * \file
  3.  *
  4.  * Copyright (C) Brno University of Technology (BUT)
  5.  *
  6.  * This file is part of software developed by Robo@FIT group.
  7.  *
  8.  * Author: Zdenek Materna (imaterna@fit.vutbr.cz)
  9.  * Supervised by:
  10.  * Date: 2014/07/24
  11.  */
  12.  
  13. #include "riveting_controller/riveting_controller.h"
  14. #include <boost/lexical_cast.hpp>
  15.  
  16. using namespace riveting_controller;
  17.  
  18. RivetingController::RivetingController(std::string group_name) :
  19.     //listener_(tf_buffer_),
  20.     group_name_(group_name), initialized_(false), home_frame_("rivet_home"), inverted_target_(false), /*robot_movement_client_(
  21.      "/simulation_interface_ur5/cartesian_position", true),*/velocity_scale_(1.0), camera_frame_("stereo_camera_link"), rand_rotation_(
  22.         1.0)
  23. {
  24.  
  25.   srand(ros::Time::now().toNSec());
  26.  
  27.   listener_.reset(new tf::TransformListener(ros::Duration(5), true));
  28.  
  29. }
  30.  
  31. bool RivetingController::initialize()
  32. {
  33.  
  34.   moveit::planning_interface::MoveGroup::Options ops(group_name_, "/simulation_ur5/robot_description_limited");
  35.  
  36.   ROS_INFO("creating move_group_interface");
  37.  
  38.   group_.reset(new move_group_interface::MoveGroup(ops));
  39.  
  40.   ROS_INFO("move_group_interface ready");
  41.  
  42.   planning_scene_monitor_.reset(
  43.       new planning_scene_monitor::PlanningSceneMonitor("/simulation_ur5/robot_description_limited", listener_,
  44.                                                        group_name_));
  45.  
  46.   ros::NodeHandle nh;
  47.   planning_scene_pub_ = nh.advertise<moveit_msgs::PlanningScene>("/simulation_ur5/planning_scene", 1, false);
  48.  
  49.   goal_pub_ = nh.advertise<visualization_msgs::Marker>("goal_marker", 1, true);
  50.  
  51.   group_->startStateMonitor();
  52.  
  53.   ROS_INFO("Caching camera-end. ef. TF");
  54.  
  55.   if (listener_->waitForTransform(camera_frame_, group_->getEndEffectorLink(), ros::Time(0), ros::Duration(5.0)))
  56.   {
  57.  
  58.     listener_->lookupTransform(camera_frame_, group_->getEndEffectorLink(), ros::Time(0), camera_to_endef_tf_);
  59.  
  60.     tf::StampedTransform tmp = camera_to_endef_tf_;
  61.  
  62.     camera_to_endef_tf_.setOrigin(tf::Vector3(tmp.getOrigin().getZ(), tmp.getOrigin().getY(), tmp.getOrigin().getX()));
  63.  
  64.   }
  65.   else
  66.   {
  67.  
  68.     camera_to_endef_tf_.setIdentity();
  69.     ROS_ERROR("Error on getting transform to camera frame!!");
  70.  
  71.   }
  72.  
  73.   initialized_ = true;
  74.  
  75.   return true;
  76.  
  77. }
  78.  
  79. RivetingController::PlanningResult RivetingController::moveHome()
  80. {
  81.  
  82.   PlanningResult res = moveToFrameOrigin(home_frame_);
  83.  
  84.   //rand_rotation_ = 1.0;
  85.   if (res != PLANNED)
  86.     return res;
  87.  
  88.   return executePlan();
  89.  
  90. }
  91.  
  92. bool RivetingController::frameToPose(std::string frame, geometry_msgs::PoseStamped& pose)
  93. {
  94.  
  95.   pose.header.frame_id = frame;
  96.   pose.header.stamp = ros::Time(0); // scene is static so this is legal
  97.  
  98.   pose.pose.position.x = 0.0;
  99.   pose.pose.position.y = 0.0;
  100.   pose.pose.position.z = 0.0;
  101.  
  102.   pose.pose.orientation.x = 0.0;
  103.   pose.pose.orientation.y = 0.0;
  104.   pose.pose.orientation.z = 0.0;
  105.   pose.pose.orientation.w = 1.0;
  106.  
  107.   return true;
  108.  
  109. }
  110.  
  111. void RivetingController::setInvertedTarget(bool value)
  112. {
  113.  
  114.   inverted_target_ = value;
  115.  
  116. }
  117.  
  118. RivetingController::PlanningResult RivetingController::approachToFrameOrigin(const geometry_msgs::PoseStamped& pose,
  119.                                                                              const geometry_msgs::Vector3& offset,
  120.                                                                              const bool& cam)
  121. {
  122.  
  123.   if (!initialized_)
  124.   {
  125.  
  126.     ROS_ERROR("Not initialized!");
  127.     return OTHER_FAILURE;
  128.  
  129.   }
  130.  
  131.   ROS_INFO("Approaching to pose with frame_id: %s", pose.header.frame_id.c_str());
  132.  
  133.   //group_->setStartStateToCurrentState();
  134.  
  135.   geometry_msgs::PoseStamped ps = pose;
  136.  
  137.   ps.pose.position.x += offset.x;
  138.   ps.pose.position.y += offset.y;
  139.   ps.pose.position.z += offset.z;
  140.  
  141.   return moveToPoseStamped(ps, "RRTConnectkConfigDefault", cam);
  142.  
  143. }
  144.  
  145. RivetingController::PlanningResult RivetingController::approachToFrameOrigin(const std::string& frame,
  146.                                                                              const geometry_msgs::Vector3& offset,
  147.                                                                              const bool& cam)
  148. {
  149.  
  150.   if (!initialized_)
  151.   {
  152.  
  153.     ROS_ERROR("Not initialized!");
  154.     return OTHER_FAILURE;
  155.  
  156.   }
  157.  
  158.   ROS_INFO("Approaching to pose: %s", frame.c_str());
  159.  
  160.   geometry_msgs::PoseStamped ps;
  161.  
  162.   if (!frameToPose(frame, ps))
  163.     return OTHER_FAILURE;
  164.  
  165.   return approachToFrameOrigin(ps, offset, cam);
  166.  
  167. }
  168.  
  169. RivetingController::PlanningResult RivetingController::moveToFrameOrigin(const std::string& frame)
  170. {
  171.  
  172.   if (!initialized_)
  173.   {
  174.  
  175.     ROS_ERROR("Not initialized!");
  176.     return OTHER_FAILURE;
  177.  
  178.   }
  179.  
  180.   geometry_msgs::PoseStamped ps;
  181.  
  182.   if (!frameToPose(frame, ps))
  183.     return OTHER_FAILURE;
  184.  
  185.   ROS_INFO("Moving to: %s", frame.c_str());
  186.  
  187.   //group_->setStartStateToCurrentState();
  188.  
  189.   return moveToPoseStamped(ps, "RRTConnectkConfigDefault");
  190.  
  191. }
  192.  
  193. RivetingController::PlanningResult RivetingController::translateToFrameOrigin(const geometry_msgs::PoseStamped& pose,
  194.                                                                               const geometry_msgs::Vector3& offset)
  195. {
  196.  
  197.   if (!initialized_)
  198.   {
  199.  
  200.     ROS_ERROR("Not initialized!");
  201.     return OTHER_FAILURE;
  202.  
  203.   }
  204.  
  205.   ROS_INFO("Translating to pose with frame_id: %s", pose.header.frame_id.c_str());
  206.  
  207.   geometry_msgs::PoseStamped ps = pose;
  208.   ps.header.stamp = ros::Time(0);
  209.  
  210.   // here we suppose that pose is in hole coordinate frame - maybe check it somehow?
  211.   ps.pose.position.x += offset.x;
  212.   ps.pose.position.y += offset.y;
  213.   ps.pose.position.z += offset.z;
  214.  
  215.   if (!transformPose(group_->getPlanningFrame(), ps, ps))
  216.     return OTHER_FAILURE;
  217.  
  218.   group_->setStartStateToCurrentState();
  219.   ps.pose.orientation = group_->getCurrentPose().pose.orientation;
  220.  
  221.   // TODO (some) random rotation if planning inside hole fails??????????????????????????????
  222.  
  223.   moveit_msgs::OrientationConstraint ocm;
  224.   ocm.link_name = group_->getEndEffectorLink();
  225.   ocm.header.frame_id = ps.header.frame_id;
  226.   ocm.orientation = ps.pose.orientation;
  227.   ocm.absolute_x_axis_tolerance = 0.0001; // TODO experiment with these values
  228.   ocm.absolute_y_axis_tolerance = 0.0001;
  229.   ocm.absolute_z_axis_tolerance = M_PI;
  230.   ocm.weight = 1.0;
  231.  
  232.   moveit_msgs::Constraints constraints;
  233.   constraints.name = "tcp orientation";
  234.   constraints.orientation_constraints.push_back(ocm);
  235.   group_->setPathConstraints(constraints);
  236.  
  237.   velocity_scale_ = 0.1;
  238.  
  239.   // we are going to use alternative planner for translation as RRTConnect doesn't behave well (but otherwise is ok and fastest)
  240.   PlanningResult res = moveToPoseStamped(ps, "PRMstarkConfigDefault" /*"RRTConnectkConfigDefault"*/, false, true, true,
  241.                                          true);
  242.  
  243.   group_->clearPathConstraints();
  244.  
  245.   return res;
  246.  
  247. }
  248.  
  249. RivetingController::PlanningResult RivetingController::translateToFrameOrigin(const std::string& frame,
  250.                                                                               const geometry_msgs::Vector3& offset)
  251. {
  252.  
  253.   if (!initialized_)
  254.   {
  255.  
  256.     ROS_ERROR("Not initialized!");
  257.     return OTHER_FAILURE;
  258.  
  259.   }
  260.  
  261.   geometry_msgs::PoseStamped ps;
  262.  
  263.   if (!frameToPose(frame, ps)) // offset will be applied later
  264.     return OTHER_FAILURE;
  265.  
  266.   return translateToFrameOrigin(ps, offset);
  267.  
  268. }
  269.  
  270. void RivetingController::clearObjects()
  271. {
  272.  
  273.   ROS_INFO("Removing stored objects.");
  274.   planning_scene_interface_.removeCollisionObjects(object_ids_);
  275.   object_ids_.clear();
  276.  
  277. }
  278.  
  279. bool RivetingController::addCyllinder(const geometry_msgs::PoseStamped& pose, float height, float radius,
  280.                                       bool allow_collisions)
  281. {
  282.  
  283.   geometry_msgs::PoseStamped ps = pose;
  284.  
  285.   ps.header.stamp = ros::Time(0); // scene is static so this is legal
  286.  
  287.   if (!transformPose(group_->getPlanningFrame(), ps, ps))
  288.     return false;
  289.  
  290.   moveit_msgs::CollisionObject obj;
  291.  
  292.   obj.id = "collision_object_" + boost::lexical_cast<std::string>(object_ids_.size());
  293.  
  294.   shape_msgs::SolidPrimitive primitive;
  295.   primitive.type = primitive.CYLINDER;
  296.   primitive.dimensions.resize(2);
  297.   primitive.dimensions[0] = height;
  298.   primitive.dimensions[1] = radius;
  299.  
  300.   object_ids_.push_back(obj.id);
  301.  
  302.   /* A pose for the box (specified relative to frame_id) */
  303.  
  304.   obj.header.frame_id = ps.header.frame_id;
  305.   obj.primitives.push_back(primitive);
  306.   obj.primitive_poses.push_back(ps.pose);
  307.   obj.operation = obj.ADD;
  308.  
  309.   std::vector<moveit_msgs::CollisionObject> collision_objects;
  310.   collision_objects.push_back(obj);
  311.  
  312.   // Now, let's add the collision object into the world
  313.   ROS_INFO("Add an object into the world");
  314.   planning_scene_interface_.addCollisionObjects(collision_objects);
  315.  
  316.   if (allow_collisions)
  317.   {
  318.  
  319.     if (!planning_scene_monitor_->requestPlanningSceneState("/simulation_ur5/get_planning_scene"))
  320.       ROS_WARN("Error on getting current planning scene.");
  321.  
  322.     planning_scene_monitor::LockedPlanningSceneRW planning_scene = planning_scene_monitor::LockedPlanningSceneRW(
  323.         planning_scene_monitor_);
  324.  
  325.     //planning_scene->getAllowedCollisionMatrixNonConst().setEntry(true); // TODO just test - disable collision checking completely
  326.  
  327.     planning_scene->getAllowedCollisionMatrixNonConst().setEntry(obj.id, true); // allow collisions with this object
  328.     planning_scene->getAllowedCollisionMatrixNonConst().print(std::cout);
  329.  
  330.     moveit_msgs::PlanningScene ps;
  331.  
  332.     planning_scene->getPlanningSceneDiffMsg(ps);
  333.  
  334.     if (planning_scene_pub_.getNumSubscribers() == 0)
  335.       ROS_ERROR("No one is listening to our planning scene! Double check topic name.");
  336.     planning_scene_pub_.publish(ps);
  337.  
  338.   }
  339.  
  340.   return true;
  341.  
  342. }
  343.  
  344. bool RivetingController::addCyllinder(std::string frame, float height, float radius, bool allow_collisions)
  345. {
  346.  
  347.   geometry_msgs::PoseStamped ps;
  348.  
  349.   if (!frameToPose(frame, ps))
  350.     return false;
  351.  
  352.   return addCyllinder(ps, height, radius, allow_collisions);
  353.  
  354. }
  355.  
  356. void RivetingController::clearCollisionMap()
  357. {
  358.  
  359.   if (!planning_scene_monitor_->requestPlanningSceneState("/simulation_ur5/get_planning_scene"))
  360.   {
  361.  
  362.     ROS_WARN("Error on getting current planning scene.");
  363.     return;
  364.  
  365.   }
  366.  
  367.   planning_scene_monitor::LockedPlanningSceneRW planning_scene = planning_scene_monitor::LockedPlanningSceneRW(
  368.       planning_scene_monitor_);
  369.  
  370.   moveit_msgs::PlanningScene ps;
  371.  
  372.   planning_scene->getPlanningSceneMsg(ps);
  373.  
  374.   //ps.world.collision_objects.clear();
  375.   ps.world.octomap.octomap.data.clear(); // TODO is this ok / sufficient?
  376.  
  377.   planning_scene_pub_.publish(ps);
  378.  
  379. }
  380.  
  381. bool RivetingController::transformPose(const std::string& target, const geometry_msgs::PoseStamped& in,
  382.                                        geometry_msgs::PoseStamped& out)
  383. {
  384.  
  385.   if (listener_->resolve(target) == listener_->resolve(in.header.frame_id))
  386.   {
  387.  
  388.     out = in;
  389.     return true;
  390.  
  391.   }
  392.  
  393.   if (!listener_->waitForTransform(target, in.header.frame_id, in.header.stamp, ros::Duration(3.0)))
  394.   {
  395.  
  396.     ROS_ERROR("Can't transform %s frame to %s", in.header.frame_id.c_str(), target.c_str());
  397.     return false;
  398.  
  399.   }
  400.  
  401.   try
  402.   {
  403.  
  404.     listener_->transformPose(target, in, out);
  405.  
  406.   }
  407.   catch (tf::TransformException& ex)
  408.   {
  409.  
  410.     ROS_ERROR("TF exception: %s", ex.what());
  411.     return false;
  412.  
  413.   }
  414.  
  415.   return true;
  416.  
  417. }
  418.  
  419. bool RivetingController::isStateValid(moveit::core::RobotState *robot_state,
  420.                                       const moveit::core::JointModelGroup *joint_group,
  421.                                       const double *joint_group_variable_values)
  422. {
  423.  
  424.   planning_scene_monitor::LockedPlanningSceneRW planning_scene = planning_scene_monitor::LockedPlanningSceneRW(
  425.       planning_scene_monitor_);
  426.  
  427.   robot_state->setJointGroupPositions(group_->getName(), joint_group_variable_values);
  428.  
  429.   collision_detection::CollisionRequest req;
  430.   req.verbose = false;
  431.   req.group_name = group_->getName();
  432.  
  433.   collision_detection::CollisionResult res;
  434.   planning_scene->checkCollision(req, res, *robot_state); // planning_scene->isStateColliding ??
  435.   if (res.collision)
  436.     return false;
  437.  
  438.   return planning_scene->isStateFeasible(*robot_state);
  439. }
  440.  
  441. RivetingController::PlanningResult RivetingController::moveToPoseStamped(const geometry_msgs::PoseStamped& pose,
  442.                                                                          const std::string& planner, const bool& cam,
  443.                                                                          const bool& no_transform,
  444.                                                                          const bool& replanning,
  445.                                                                          const bool& disable_pretest)
  446. {
  447.  
  448.   ROS_ASSERT(pose.header.frame_id != "");
  449.  
  450.   if (!initialized_)
  451.     return OTHER_FAILURE;
  452.  
  453.   geometry_msgs::PoseStamped ps = pose;
  454.  
  455.   if (no_transform == false)
  456.   {
  457.  
  458.     tf::Pose tfpose;
  459.     tf::poseMsgToTF(ps.pose, tfpose);
  460.     if (pose.header.frame_id != home_frame_)
  461.       tfpose.setRotation(tfpose.getRotation() * tf::Quaternion(tf::Vector3(0, 0, 1), rand_rotation_ * M_PI));
  462.     tf::poseTFToMsg(tfpose, ps.pose);
  463.  
  464.   }
  465.  
  466.   if (!transformPose(group_->getPlanningFrame(), ps, ps))
  467.     return OTHER_FAILURE;
  468.  
  469.   if (cam)
  470.   {
  471.  
  472.     ROS_INFO("Use camera as end effector.");
  473.  
  474.     tf::Pose pstf;
  475.  
  476.     tf::poseMsgToTF(ps.pose, pstf);
  477.  
  478.     pstf = pstf * camera_to_endef_tf_;
  479.  
  480.     pstf.setRotation(pstf.getRotation() * tf::Quaternion(tf::Vector3(0, 1, 0), -M_PI / 2));
  481.     pstf.setRotation(pstf.getRotation() * tf::Quaternion(tf::Vector3(1, 0, 0), M_PI));
  482.  
  483.     tf::poseTFToMsg(pstf, ps.pose);
  484.  
  485.   }
  486.  
  487.   if (inverted_target_ && (no_transform == false))
  488.   {
  489.  
  490.     tf::Pose tfpose;
  491.  
  492.     tf::poseMsgToTF(ps.pose, tfpose);
  493.     // TODO if planning fail - rotate it around x axis? add some rotation around z axis?
  494.     tfpose.setRotation(tfpose.getRotation() * tf::Quaternion(tf::Vector3(0, 1, 0), M_PI));
  495.     tfpose.setRotation(tfpose.getRotation() * tf::Quaternion(tf::Vector3(0, 0, 1), M_PI)); // TODO tmp workaround for camera-table collision
  496.     tf::poseTFToMsg(tfpose, ps.pose);
  497.  
  498.   }
  499.  
  500.   visualization_msgs::Marker marker;
  501.  
  502.   marker.header = ps.header;
  503.   marker.ns = "riveting_controller";
  504.   marker.id = 0;
  505.   marker.type = visualization_msgs::Marker::ARROW;
  506.   marker.action = visualization_msgs::Marker::ADD;
  507.   marker.pose = ps.pose;
  508.   marker.scale.x = 0.1;
  509.   marker.scale.y = 0.02;
  510.   marker.scale.z = 0.02;
  511.   marker.color.r = 0.0f;
  512.   marker.color.g = 1.0f;
  513.   marker.color.b = 0.0f;
  514.   marker.color.a = 1.0;
  515.   marker.lifetime = ros::Duration();
  516.  
  517.   goal_pub_.publish(marker);
  518.  
  519.   if (!disable_pretest)
  520.   {
  521.  
  522.     if (!planning_scene_monitor_->requestPlanningSceneState("/simulation_ur5/get_planning_scene"))
  523.       ROS_WARN("Error on getting current planning scene.");
  524.  
  525.     robot_state::RobotStatePtr state = group_->getCurrentState();
  526.     if (!state->setFromIK(state->getJointModelGroup(group_name_), ps.pose, group_->getEndEffectorLink(), 5, 0.0,
  527.                           boost::bind(&RivetingController::isStateValid, this, _1, _2, _3)))
  528.     {
  529.  
  530.       ROS_WARN("No valid IK for target pose.");
  531.       return PLANNING_FAILED;
  532.  
  533.     }
  534.  
  535.   }
  536.  
  537.   group_->setPlannerId(planner);
  538.   group_->setGoalPositionTolerance(0.00001);
  539.   group_->setGoalOrientationTolerance(0.00001);
  540.   group_->setPlanningTime(3.0);
  541.   group_->allowReplanning(replanning);
  542.   group_->setNumPlanningAttempts(6); // attempts are done in parallel (I hope)
  543.   group_->setWorkspace(-1.0, -2.0, 0.5, 2.0, 2.0, 1.5);
  544.   //group_->setEndEffectorLink("tcp");
  545.   //group_->setEndEffector("end_eff");
  546.  
  547.   if (!group_->setPoseTarget(ps, "tcp"))
  548.   {
  549.  
  550.     ROS_ERROR("Failed to set target pose.");
  551.     return OTHER_FAILURE;
  552.  
  553.   }
  554.  
  555.   plan_.reset(new move_group_interface::MoveGroup::Plan);
  556.  
  557.   if (!group_->plan(*plan_))
  558.   {
  559.  
  560.     plan_.reset();
  561.     velocity_scale_ = 1.0;
  562.     ROS_ERROR("Error on planning!");
  563.     return PLANNING_FAILED; // TODO indicate this state to allow for instance slight change in pose and another try
  564.  
  565.   }
  566.  
  567.   scaleTrajectory(plan_, velocity_scale_);
  568.   velocity_scale_ = 1.0;
  569.   target_pose_ = ps;
  570.  
  571.   return PLANNED;
  572.  
  573. }
  574.  
  575. RivetingController::PlanningResult RivetingController::executePlan()
  576. {
  577.  
  578.   if (!plan_)
  579.     return OTHER_FAILURE;
  580.  
  581.   plan_.reset();
  582.  
  583.   ros::Time start(ros::Time::now());
  584.  
  585.   /*if (!group_->execute(*plan_))
  586.   {
  587.  
  588.     plan_.reset();
  589.     ROS_ERROR("Movement not finished (%f)!", (ros::Time::now()-start).toSec());
  590.     return EXECUTION_FAILED;
  591.  
  592.   }*/
  593.  
  594.   if (!group_->move()) {
  595.  
  596.     ROS_ERROR("Movement not finished (%f)!", (ros::Time::now()-start).toSec());
  597.     return EXECUTION_FAILED;
  598.  
  599.   }
  600.  
  601.   target_pose_.header.stamp = ros::Time(0);
  602.  
  603.   float err = poseFrameDist(target_pose_, "tcp");
  604.  
  605.   ROS_INFO("Movement finished (duration: %f, position error: %f)!", (ros::Time::now()-start).toSec(), err);
  606.  
  607.   //plan_.reset();
  608.   return EXECUTED;
  609.  
  610. }
  611.  
  612. RivetingController::~RivetingController()
  613. {
  614.  
  615. }
  616.  
  617. void RivetingController::scaleTrajectory(PlanPtr plan, float scale)
  618. {
  619.  
  620.   if (scale == 1.0)
  621.     return;
  622.  
  623.   if (!plan) {
  624.  
  625.     ROS_ERROR("Trajectory scaling: not a valid plan.");
  626.     return;
  627.  
  628.   }
  629.  
  630.   ROS_INFO("Scaling trajectory (%f).",scale);
  631.  
  632.   for (unsigned int i = 0; i < plan->trajectory_.joint_trajectory.points.size(); i++)
  633.   {
  634.  
  635.     plan->trajectory_.joint_trajectory.points[i].time_from_start = ros::Duration(
  636.         plan->trajectory_.joint_trajectory.points[i].time_from_start.toSec() / scale);
  637.  
  638.     for (unsigned int j = 0; j < plan->trajectory_.joint_trajectory.joint_names.size(); j++)
  639.     {
  640.  
  641.       plan->trajectory_.joint_trajectory.points[i].velocities[j] *= scale;
  642.       plan->trajectory_.joint_trajectory.points[i].accelerations[j] *= (scale * scale);
  643.  
  644.     }
  645.  
  646.   }
  647.  
  648. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement