00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <termios.h>
00033 #include <signal.h>
00034 #include <cstdio>
00035 #include <cstdlib>
00036 #include <unistd.h>
00037 #include <math.h>
00038
00039 #include <ros/ros.h>
00040
00041 #include <planning_environment/models/collision_models.h>
00042 #include <arm_navigation_msgs/PlanningScene.h>
00043 #include <arm_navigation_msgs/GetPlanningScene.h>
00044 #include <planning_environment/models/model_utils.h>
00045 #include <rosgraph_msgs/Clock.h>
00046 #include <tf/transform_broadcaster.h>
00047 #include <kinematics_msgs/GetConstraintAwarePositionIK.h>
00048 #include <kinematics_msgs/GetPositionIK.h>
00049 #include <actionlib/client/simple_action_client.h>
00050 #include <arm_navigation_msgs/GetMotionPlan.h>
00051 #include <arm_navigation_msgs/GetStateValidity.h>
00052 #include <trajectory_msgs/JointTrajectory.h>
00053 #include <arm_navigation_msgs/FilterJointTrajectoryWithConstraints.h>
00054 #include <arm_navigation_msgs/convert_messages.h>
00055 #include <interactive_markers/interactive_marker_server.h>
00056 #include <interactive_markers/menu_handler.h>
00057 #include <sensor_msgs/JointState.h>
00058 #include <move_arm_warehouse/move_arm_warehouse_logger_reader.h>
00059
00060 using namespace std;
00061 using namespace arm_navigation_msgs;
00062 using namespace interactive_markers;
00063 using namespace visualization_msgs;
00064 using namespace planning_environment;
00065 using namespace planning_models;
00066 using namespace geometry_msgs;
00067 using namespace move_arm_warehouse;
00068
00069 static const string VIS_TOPIC_NAME = "warehouse_components_visualizer";
00070
00071
00072 static const unsigned int CONTROL_SPEED = 10;
00073
00074 static const ros::Duration PLANNING_DURATION = ros::Duration(5.0);
00075
00076 static const double BASE_TRANS_SPEED = .3;
00077 static const double BASE_ROT_SPEED = .15;
00078
00079 static const double HAND_TRANS_SPEED = .05;
00080 static const double HAND_ROT_SPEED = .15;
00081
00082 static const string GET_PLANNING_SCENE_NAME = "/environment_server/get_planning_scene";
00083 static const string PLANNER_SERVICE_NAME = "/ompl_planning/plan_kinematic_path";
00084 static const string TRAJECTORY_FILTER_SERVICE_NAME = "/trajectory_filter_server/filter_trajectory_with_constraints";
00085 static string PLANNER_STAGE_NAME = "planner";
00086 static string FILTER_STAGE_NAME = "filter";
00087
00088 typedef map<MenuHandler::EntryHandle, string> MenuEntryMap;
00089 typedef map<string, MenuEntryMap> MenuMap;
00090 typedef map<string, MenuHandler> MenuHandlerMap;
00091
00092 class WarehouseComponentsVisualizer
00093 {
00094
00095 public:
00096
00098 enum IKControlType
00099 {
00100 StartPosition, EndPosition
00101 };
00102
00104 enum InteractiveMarkerType
00105 {
00106 EndEffectorControl, JointControl, CollisionObject
00107 };
00108
00110 struct SelectableMarker
00111 {
00113 InteractiveMarkerType type_;
00114
00116 string name_;
00117
00119 string controlName_;
00120
00122 string controlDescription_;
00123 };
00124
00125 struct StateTrajectoryDisplay
00126 {
00127
00128 StateTrajectoryDisplay()
00129 {
00130 state_ = NULL;
00131 reset();
00132 }
00133
00134 void reset()
00135 {
00136 if(state_ != NULL)
00137 {
00138 delete state_;
00139 state_ = NULL;
00140 }
00141 has_joint_trajectory_ = false;
00142 play_joint_trajectory_ = false;
00143 show_joint_trajectory_ = false;
00144 current_trajectory_point_ = 0;
00145 trajectory_bad_point_ = 0;
00146 trajectory_error_code_.val = 0;
00147 }
00148
00149 KinematicState* state_;
00150 trajectory_msgs::JointTrajectory joint_trajectory_;unsigned int current_trajectory_point_;
00151 std_msgs::ColorRGBA color_;
00152 bool has_joint_trajectory_;
00153 bool play_joint_trajectory_;
00154 bool show_joint_trajectory_;
00155 ArmNavigationErrorCodes trajectory_error_code_;unsigned int trajectory_bad_point_;
00156 };
00157
00158 struct GroupCollection
00159 {
00160 GroupCollection()
00161 {
00162 start_state_ = NULL;
00163 end_state_ = NULL;
00164 good_ik_solution_ = false;
00165
00166 state_trajectory_display_map_["planner"].color_.a = .6;
00167 state_trajectory_display_map_["planner"].color_.r = 1.0;
00168 state_trajectory_display_map_["planner"].color_.g = 1.0;
00169 state_trajectory_display_map_["planner"].color_.b = 0.5;
00170
00171 state_trajectory_display_map_["filter"].color_.a = .6;
00172 state_trajectory_display_map_["filter"].color_.r = 0.5;
00173 state_trajectory_display_map_["filter"].color_.g = 1.0;
00174 state_trajectory_display_map_["filter"].color_.b = 1.0;
00175 }
00176
00177 ~GroupCollection()
00178 {
00179 reset();
00180 }
00181
00182 void setState(IKControlType type, KinematicState* state)
00183 {
00184 switch (type)
00185 {
00186 case WarehouseComponentsVisualizer::StartPosition:
00187 if(start_state_ != NULL)
00188 {
00189 delete start_state_;
00190 start_state_ = NULL;
00191 }
00192 start_state_ = state;
00193 break;
00194 case WarehouseComponentsVisualizer::EndPosition:
00195 if(end_state_ != NULL)
00196 {
00197 delete end_state_;
00198 end_state_ = NULL;
00199 }
00200 end_state_ = state;
00201 break;
00202 }
00203 }
00204
00205 KinematicState* getState(IKControlType type)
00206 {
00207 switch (type)
00208 {
00209 case WarehouseComponentsVisualizer::StartPosition:
00210 return start_state_;
00211 case WarehouseComponentsVisualizer::EndPosition:
00212 return end_state_;
00213 }
00214
00215 return NULL;
00216 }
00217
00218 void reset()
00219 {
00220 for(map<string, StateTrajectoryDisplay>::iterator it = state_trajectory_display_map_.begin(); it
00221 != state_trajectory_display_map_.end(); it++)
00222 {
00223 it->second.reset();
00224 }
00225
00226 if(start_state_ != NULL)
00227 {
00228 delete start_state_;
00229 start_state_ = NULL;
00230 }
00231 if(end_state_ != NULL)
00232 {
00233 delete end_state_;
00234 end_state_ = NULL;
00235 }
00236
00237 }
00238
00239 string name_;
00240 string ik_link_name_;
00241 ros::ServiceClient coll_aware_ik_service_;
00242 ros::ServiceClient non_coll_aware_ik_service_;
00243 bool good_ik_solution_;
00244 KinematicState* start_state_;
00245 KinematicState* end_state_;
00246 map<string, StateTrajectoryDisplay> state_trajectory_display_map_;
00247 vector<string> joint_names_;
00248 tf::Transform last_good_state_;
00249
00250 };
00251
00252 WarehouseComponentsVisualizer()
00253 {
00254 ik_control_type_ = EndPosition;
00255 num_collision_poles_ = 0;
00256 collision_aware_ = true;
00257 cm_ = new CollisionModels("robot_description");
00258 vis_marker_publisher_ = nh_.advertise<Marker> (VIS_TOPIC_NAME, 128);
00259 vis_marker_array_publisher_ = nh_.advertise<MarkerArray> (VIS_TOPIC_NAME + "_array", 128);
00260 joint_state_publisher_ = nh_.advertise<sensor_msgs::JointState> ("joint_states", 10);
00261 constrain_rp_ = false;
00262 logger_ = new MoveArmWarehouseLoggerReader();
00263
00264 process_function_ptr_ = boost::bind(&WarehouseComponentsVisualizer::processInteractiveFeedback, this, _1);
00265
00266 while(!ros::service::waitForService(GET_PLANNING_SCENE_NAME, ros::Duration(1.0)))
00267 {
00268 ROS_INFO_STREAM("Waiting for planning scene service " << GET_PLANNING_SCENE_NAME);
00269 }
00270
00271 get_planning_scene_client_
00272 = nh_.serviceClient<arm_navigation_msgs::GetPlanningScene> (GET_PLANNING_SCENE_NAME);
00273
00274 while(!ros::service::waitForService(PLANNER_SERVICE_NAME, ros::Duration(1.0)))
00275 {
00276 ROS_INFO_STREAM("Waiting for planner service " << PLANNER_SERVICE_NAME);
00277 }
00278
00279 planner_service_client_ = nh_.serviceClient<GetMotionPlan> (PLANNER_SERVICE_NAME, true);
00280
00281 while(!ros::service::waitForService(TRAJECTORY_FILTER_SERVICE_NAME, ros::Duration(1.0)))
00282 {
00283 ROS_INFO_STREAM("Waiting for trajectory filter service " << TRAJECTORY_FILTER_SERVICE_NAME);
00284 }
00285
00286 trajectory_filter_service_client_
00287 = nh_.serviceClient<FilterJointTrajectoryWithConstraints> (TRAJECTORY_FILTER_SERVICE_NAME, true);
00288
00289 const map<string, KinematicModel::GroupConfig>& group_config_map =
00290 cm_->getKinematicModel()->getJointModelGroupConfigMap();
00291
00292 for(map<string, KinematicModel::GroupConfig>::const_iterator it = group_config_map.begin(); it
00293 != group_config_map.end(); it++)
00294 {
00295 if(!it->second.base_link_.empty())
00296 {
00297 group_map_[it->first].name_ = it->first;
00298 group_map_[it->first].ik_link_name_ = it->second.tip_link_;
00299 string ik_service_name = cm_->getKinematicModel()->getRobotName() + "_" + it->first + "_kinematics/";
00300 string coll_aware_name = ik_service_name + "get_constraint_aware_ik";
00301 string non_coll_aware_name = ik_service_name + "get_ik";
00302
00303 while(!ros::service::waitForService(coll_aware_name, ros::Duration(1.0)))
00304 {
00305 ROS_INFO_STREAM("Waiting for service " << coll_aware_name);
00306 }
00307
00308 while(!ros::service::waitForService(non_coll_aware_name, ros::Duration(1.0)))
00309 {
00310 ROS_INFO_STREAM("Waiting for service " << non_coll_aware_name);
00311 }
00312
00313 group_map_[it->first].coll_aware_ik_service_ = nh_.serviceClient<
00314 kinematics_msgs::GetConstraintAwarePositionIK> (coll_aware_name, true);
00315
00316 group_map_[it->first].non_coll_aware_ik_service_
00317 = nh_.serviceClient<kinematics_msgs::GetPositionIK> (non_coll_aware_name, true);
00318 }
00319 }
00320 robot_state_ = new KinematicState(cm_->getKinematicModel());
00321 robot_state_->setKinematicStateToDefault();
00322 sendPlanningScene();
00323
00324
00325 interactive_marker_server_.reset(new InteractiveMarkerServer("planning_visualizer_controls", "", false));
00326
00327
00328 menu_entry_maps_["End Effector"] = MenuEntryMap();
00329 menu_entry_maps_["End Effector Selection"] = MenuEntryMap();
00330 menu_entry_maps_["Top Level"] = MenuEntryMap();
00331 menu_entry_maps_["Collision Object"] = MenuEntryMap();
00332 menu_entry_maps_["Collision Object Selection"] = MenuEntryMap();
00333
00334
00335 menu_handler_map_["End Effector"];
00336 menu_handler_map_["End Effector Selection"];
00337 menu_handler_map_["Top Level"];
00338 menu_handler_map_["Collision Object"];
00339 menu_handler_map_["Collision Object Selection"];
00340
00341
00342 start_position_handle_ = registerMenuEntry(menu_handler_map_["End Effector"], menu_entry_maps_["End Effector"],
00343 "Set Start Position");
00344 end_position_handle_ = registerMenuEntry(menu_handler_map_["End Effector"], menu_entry_maps_["End Effector"],
00345 "Set End Position");
00346 constrain_rp_handle_ = registerMenuEntry(menu_handler_map_["End Effector"], menu_entry_maps_["End Effector"],
00347 "Constrain in Roll and Pitch");
00348
00349 menu_handler_map_["End Effector"].setCheckState(start_position_handle_, MenuHandler::UNCHECKED);
00350 menu_handler_map_["End Effector"].setCheckState(end_position_handle_, MenuHandler::CHECKED);
00351 menu_handler_map_["End Effector"].setCheckState(constrain_rp_handle_, MenuHandler::UNCHECKED);
00352
00353 registerMenuEntry(menu_handler_map_["End Effector"], menu_entry_maps_["End Effector"], "Plan");
00354 registerMenuEntry(menu_handler_map_["End Effector"], menu_entry_maps_["End Effector"], "Filter Trajectory");
00355 registerMenuEntry(menu_handler_map_["End Effector"], menu_entry_maps_["End Effector"], "Randomly Perturb");
00356 registerMenuEntry(menu_handler_map_["End Effector"], menu_entry_maps_["End Effector"], "Go To Last Good State");
00357 registerMenuEntry(menu_handler_map_["End Effector"], menu_entry_maps_["End Effector"], "Deselect");
00358 registerMenuEntry(menu_handler_map_["End Effector Selection"], menu_entry_maps_["End Effector Selection"],
00359 "Select");
00360
00361
00362 registerMenuEntry(menu_handler_map_["Collision Object Selection"],
00363 menu_entry_maps_["Collision Object Selection"], "Select");
00364 registerMenuEntry(menu_handler_map_["Collision Object Selection"],
00365 menu_entry_maps_["Collision Object Selection"], "Delete");
00366 registerMenuEntry(menu_handler_map_["Collision Object"], menu_entry_maps_["Collision Object"], "Deselect");
00367 registerMenuEntry(menu_handler_map_["Collision Object"], menu_entry_maps_["Collision Object"], "Delete");
00368
00369
00370 registerMenuEntry(menu_handler_map_["Top Level"], menu_entry_maps_["Top Level"], "Create Pole");
00371 ik_control_handle_ = registerMenuEntry(menu_handler_map_["Top Level"], menu_entry_maps_["Top Level"],
00372 "IK Control");
00373 joint_control_handle_ = registerMenuEntry(menu_handler_map_["Top Level"], menu_entry_maps_["Top Level"],
00374 "Joint Control");
00375 collision_aware_handle_ = registerMenuEntry(menu_handler_map_["Top Level"], menu_entry_maps_["Top Level"],
00376 "Collision Aware");
00377 menu_handler_map_["Top Level"].setCheckState(ik_control_handle_, MenuHandler::CHECKED);
00378 menu_handler_map_["Top Level"].setCheckState(joint_control_handle_, MenuHandler::UNCHECKED);
00379 menu_handler_map_["Top Level"].setCheckState(collision_aware_handle_, MenuHandler::CHECKED);
00380
00381 registerMenuEntry(menu_handler_map_["Top Level"], menu_entry_maps_["Top Level"], "Log Planning Scene ...");
00382
00383
00384 is_ik_control_active_ = true;
00385 is_joint_control_active_ = false;
00386
00387 MenuHandler::EntryHandle sub_menu_handle = menu_handler_map_["Top Level"].insert("Select Planning Chain");
00388
00389
00390 unsigned int cmd = 0;
00391 for(map<string, GroupCollection>::iterator it = group_map_.begin(); it != group_map_.end(); it++)
00392 {
00393 registerSubMenuEntry(menu_handler_map_["Top Level"], menu_entry_maps_["Top Level"], it->first, sub_menu_handle);
00394
00395
00396 makeSelectableMarker(WarehouseComponentsVisualizer::EndEffectorControl,
00397 tf::Transform(tf::Quaternion(0.0f, 0.0f, 0.0f, 1.0f), tf::Vector3(0.0f, 0.0f, 0.0f)), it->first,
00398 it->first, 0.5f);
00399 cmd++;
00400 }
00401
00402 makeTopLevelMenu();
00403
00404 interactive_marker_server_->applyChanges();
00405
00406 ROS_INFO_STREAM("Initialized");
00407
00408 }
00409
00410 ~WarehouseComponentsVisualizer()
00411 {
00412 deleteKinematicStates();
00413 delete robot_state_;
00414 delete cm_;
00415 }
00416
00420 inline void logOutcome(std::string& pipeline_stage, ArmNavigationErrorCodes& error_codes)
00421 {
00422 logger_->pushOutcomeToWarehouse(planning_scene_, pipeline_stage, error_codes);
00423 }
00424
00428 inline void logMotionPlanRequest(std::string& stage_name, arm_navigation_msgs::MotionPlanRequest& motion_plan_request)
00429 {
00430 logger_->pushMotionPlanRequestToWarehouse(planning_scene_, stage_name, motion_plan_request, "MPR 1");
00431 }
00432
00436 inline void logTrajectory(std::string& source, ros::Duration& production_time, trajectory_msgs::JointTrajectory& trajectory)
00437 {
00438 ArmNavigationErrorCodes errorCodes;
00439 logger_->pushJointTrajectoryToWarehouse(planning_scene_, source, production_time, trajectory, "Trajectory 1", "MPR 1", errorCodes);
00440 }
00441
00446 inline void logNewPlanningScene()
00447 {
00448 cm_->getPlanningSceneGivenState(*robot_state_, planning_scene_);
00449 logger_->pushPlanningSceneToWarehouse(planning_scene_);
00450 }
00451
00456 int nextCollisionPole()
00457 {
00458 return ++num_collision_poles_;
00459 }
00460
00465 void removeCollisionPole(int num)
00466 {
00467 stringstream id;
00468 id << "pole_" << num;
00469 removeCollisionPoleByName(id.str());
00470 }
00471
00476 void removeCollisionPoleByName(string id)
00477 {
00478 ROS_INFO("Removing collision pole %s", id.c_str());
00479 arm_navigation_msgs::CollisionObject& cylinder_object = collision_poles_[id];
00480 cylinder_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::REMOVE;
00481 }
00482
00488 void createCollisionPole(int num, Pose pose)
00489 {
00490 ROS_INFO("Creating collision pole %d", num);
00491
00492 arm_navigation_msgs::CollisionObject cylinder_object;
00493 cylinder_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00494 cylinder_object.header.stamp = ros::Time::now();
00495 cylinder_object.header.frame_id = "/" + cm_->getWorldFrameId();
00496 arm_navigation_msgs::Shape object;
00497 object.type = arm_navigation_msgs::Shape::CYLINDER;
00498 object.dimensions.resize(2);
00499 object.dimensions[0] = .1;
00500 object.dimensions[1] = 2.0;
00501
00502 cylinder_object.shapes.push_back(object);
00503 cylinder_object.poses.push_back(pose);
00504 stringstream id;
00505 id << "pole_" << num;
00506 cylinder_object.id = id.str();
00507 collision_poles_[id.str()] = cylinder_object;
00508
00509 tf::Transform cur = toBulletTransform(pose);
00510 makePoleContextMenu(cur, id.str(), "", 2.0f);
00511 }
00512
00513 void sendPlanningScene()
00514 {
00515 ROS_INFO("Sending Planning Scene....");
00516
00517 lock_.lock();
00518 arm_navigation_msgs::GetPlanningScene::Request planning_scene_req;
00519 arm_navigation_msgs::GetPlanningScene::Response planning_scene_res;
00520
00521 vector<string> removals;
00522
00523 for(map<string, arm_navigation_msgs::CollisionObject>::const_iterator it = collision_poles_.begin(); it
00524 != collision_poles_.end(); it++)
00525 {
00526 string name = it->first;
00527 arm_navigation_msgs::CollisionObject object = it->second;
00528
00529
00530 if(object.operation.operation != arm_navigation_msgs::CollisionObjectOperation::REMOVE)
00531 {
00532 ROS_INFO("Adding Collision Pole %s", object.id.c_str());
00533 planning_scene_req.planning_scene_diff.collision_objects.push_back(object);
00534 }
00535 else
00536 {
00537 removals.push_back(it->first);
00538 }
00539 }
00540
00541
00542 for(size_t i = 0; i < removals.size(); i++)
00543 {
00544 collision_poles_.erase(removals[i]);
00545 }
00546
00547 convertKinematicStateToRobotState(*robot_state_, ros::Time::now(), cm_->getWorldFrameId(),
00548 planning_scene_req.planning_scene_diff.robot_state);
00549
00550
00551 KinematicState* startState = NULL;
00552 KinematicState* endState = NULL;
00553 map<string, double> startStateValues;
00554 map<string, double> endStateValues;
00555
00556 if(current_group_name_ != "")
00557 {
00558 startState = group_map_[current_group_name_].getState(StartPosition);
00559 endState = group_map_[current_group_name_].getState(EndPosition);
00560
00561 if(startState != NULL)
00562 {
00563 startState->getKinematicStateValues(startStateValues);
00564 }
00565 if(endState != NULL)
00566 {
00567 endState->getKinematicStateValues(endStateValues);
00568 }
00569 }
00570
00571 deleteKinematicStates();
00572
00573
00574 if(robot_state_ != NULL)
00575 {
00576 ROS_INFO("Reverting planning scene to default.");
00577 cm_->revertPlanningScene(robot_state_);
00578 robot_state_ = NULL;
00579 }
00580
00581 if(!get_planning_scene_client_.call(planning_scene_req, planning_scene_res))
00582 {
00583 ROS_WARN("Can't get planning scene");
00584 lock_.unlock();
00585 return;
00586 }
00587
00588 robot_state_ = cm_->setPlanningScene(planning_scene_res.planning_scene);
00589
00590 if(robot_state_ == NULL)
00591 {
00592 ROS_ERROR("Something wrong with planning scene");
00593 lock_.unlock();
00594 return;
00595 }
00596
00597 if(current_group_name_ != "")
00598 {
00599 ROS_INFO("Resetting state...");
00600 group_map_[current_group_name_].setState(StartPosition, new KinematicState(robot_state_->getKinematicModel()));
00601 group_map_[current_group_name_].setState(EndPosition, new KinematicState(robot_state_->getKinematicModel()));
00602 startState = group_map_[current_group_name_].getState(StartPosition);
00603 endState = group_map_[current_group_name_].getState(EndPosition);
00604
00605 if(startState != NULL)
00606 {
00607 startState->setKinematicState(startStateValues);
00608 }
00609
00610 if(endState != NULL)
00611 {
00612 ROS_INFO("Resetting end state.");
00613 endState->setKinematicState(endStateValues);
00614 }
00615 }
00616 lock_.unlock();
00617 ROS_INFO("Planning scene sent.");
00618 }
00619
00620 void selectPlanningGroup(unsigned int entry)
00621 {
00622 ROS_INFO("Selecting planning group %u", entry);
00623 lock_.lock();
00624 vector<string> names;
00625 for(map<string, GroupCollection>::iterator it = group_map_.begin(); it != group_map_.end(); it++)
00626 {
00627 names.push_back(it->first);
00628 }
00629 string old_group_name = current_group_name_;
00630
00631 current_group_name_ = names[entry];
00632
00633 if(group_map_[current_group_name_].end_state_ != NULL)
00634 {
00635 group_map_[current_group_name_].setState(EndPosition,
00636 new KinematicState(*group_map_[current_group_name_].end_state_));
00637 }
00638 else
00639 {
00640 group_map_[current_group_name_].setState(EndPosition, new KinematicState(*robot_state_));
00641 }
00642
00643 if(group_map_[current_group_name_].start_state_ != NULL)
00644 {
00645 group_map_[current_group_name_].setState(StartPosition,
00646 new KinematicState(*group_map_[current_group_name_].start_state_));
00647 }
00648 else
00649 {
00650 group_map_[current_group_name_].setState(StartPosition, new KinematicState(*robot_state_));
00651 }
00652
00653 moveEndEffectorMarkers(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false);
00654
00655
00656 if(is_ik_control_active_ && old_group_name != "" && selectableMarkerExists(old_group_name + "_selectable"))
00657 {
00658 GroupCollection& gc = group_map_[old_group_name];
00659 tf::Transform cur = robot_state_->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform();
00660 deselectMarker(selectable_markers_[old_group_name + "_selectable"], cur);
00661
00662 if(is_joint_control_active_)
00663 {
00664 deleteJointMarkers(group_map_[old_group_name]);
00665 }
00666 }
00667 else if(is_joint_control_active_)
00668 {
00669 deleteJointMarkers(group_map_[old_group_name]);
00670 }
00671
00672
00673 if(is_ik_control_active_ && selectableMarkerExists(current_group_name_ + "_selectable"))
00674 {
00675 GroupCollection& gc = group_map_[current_group_name_];
00676 tf::Transform cur = gc.getState(ik_control_type_)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform();
00677 selectMarker(selectable_markers_[current_group_name_ + "_selectable"], cur);
00678 createSelectableJointMarkers(gc);
00679 }
00680 else if(is_joint_control_active_)
00681 {
00682 GroupCollection& gc = group_map_[current_group_name_];
00683 createSelectableJointMarkers(gc);
00684 }
00685
00686 interactive_marker_server_->applyChanges();
00687
00688 lock_.unlock();
00689 ROS_INFO("Planning group selected.");
00690 }
00691
00692 bool isValidJointName(GroupCollection& gc, string name)
00693 {
00694 for(size_t i = 0; i < gc.joint_names_.size(); i++)
00695 {
00696 if(name == gc.joint_names_[i])
00697 {
00698 return true;
00699 }
00700 }
00701 return false;
00702 }
00703
00704 void moveEndEffectorMarkers(double vx, double vy, double vz, double vr, double vp, double vw,
00705 bool coll_aware = true)
00706
00707 {
00708 lock_.lock();
00709 GroupCollection& gc = group_map_[current_group_name_];
00710 tf::Transform cur = gc.getState(ik_control_type_)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform();
00711 double mult = CONTROL_SPEED / 100.0;
00712
00713 tf::Vector3& curOrigin = cur.getOrigin();
00714 tf::Vector3 newOrigin(curOrigin.x() + (vx * mult), curOrigin.y() + (vy * mult), curOrigin.z() + (vz * mult));
00715 cur.setOrigin(newOrigin);
00716
00717 tfScalar roll, pitch, yaw;
00718
00719 cur.getBasis().getRPY(roll, pitch, yaw);
00720 roll += vr * mult;
00721 pitch += vp * mult;
00722 yaw += vw * mult;
00723
00724 if(roll > 2 * M_PI)
00725 {
00726 roll -= 2 * M_PI;
00727 }
00728 else if(roll < -2 * M_PI)
00729 {
00730 roll += 2 * M_PI;
00731 }
00732
00733 if(pitch > 2 * M_PI)
00734 {
00735 pitch -= 2 * M_PI;
00736 }
00737 else if(pitch < -2 * M_PI)
00738 {
00739 pitch += 2 * M_PI;
00740 }
00741
00742 cur.getBasis().setRPY(roll, pitch, yaw);
00743
00744 setNewEndEffectorPosition(gc, cur, coll_aware);
00745
00746 lock_.unlock();
00747 }
00748
00749 void deleteJointMarkers(GroupCollection& gc)
00750 {
00751 for(size_t i = 0; i < gc.joint_names_.size(); i++)
00752 {
00753 interactive_marker_server_->erase(gc.joint_names_[i] + "_joint_control");
00754 }
00755 }
00756
00761 void createSelectableJointMarkers(GroupCollection& gc)
00762 {
00763 if(!is_joint_control_active_)
00764 {
00765 return;
00766 }
00767
00768
00769 for(size_t i = 0; i < gc.joint_names_.size(); i++)
00770 {
00771 const string& jointName = gc.joint_names_[i];
00772 KinematicModel::JointModel* model =
00773 (KinematicModel::JointModel*)(gc.getState(ik_control_type_)->getKinematicModel()->getJointModel(jointName));
00774 KinematicModel::RevoluteJointModel* revoluteJoint = dynamic_cast<KinematicModel::RevoluteJointModel*> (model);
00775 KinematicModel::PrismaticJointModel* prismaticJoint =
00776 dynamic_cast<KinematicModel::PrismaticJointModel*> (model);
00777
00778 joint_clicked_map_[jointName + "_joint_control"] = false;
00779
00780 if(model->getParentLinkModel() != NULL)
00781 {
00782 string parentLinkName = model->getParentLinkModel()->getName();
00783 string childLinkName = model->getChildLinkModel()->getName();
00784 tf::Transform
00785 transform =
00786 gc.getState(ik_control_type_)->getLinkState(parentLinkName)->getGlobalLinkTransform()
00787 * (gc.getState(ik_control_type_)->getKinematicModel()->getLinkModel(childLinkName)->getJointOriginTransform()
00788 * (gc.getState(ik_control_type_)->getJointState(jointName)->getVariableTransform()));
00789
00790 joint_prev_transform_map_[jointName + "joint_control"] = transform;
00791
00792 const shapes::Shape* linkShape = model->getChildLinkModel()->getLinkShape();
00793 const shapes::Mesh* meshShape = dynamic_cast<const shapes::Mesh*> (linkShape);
00794
00795 double maxDimension = 0.0f;
00796 if(meshShape != NULL)
00797 {
00798 for(unsigned int i = 0; i < meshShape->vertexCount; i++)
00799 {
00800 double x = meshShape->vertices[3 * i];
00801 double y = meshShape->vertices[3 * i];
00802 double z = meshShape->vertices[3 * i];
00803
00804 if(abs(maxDimension) < abs(sqrt(x*x+y*y+z*z)))
00805 {
00806 maxDimension = abs(x);
00807 }
00808
00809 }
00810
00811 maxDimension *= 3.0;
00812
00813 maxDimension = max(0.15, maxDimension);
00814 maxDimension = min(0.5, maxDimension);
00815 }
00816 else
00817 {
00818 maxDimension = 0.15;
00819 }
00820
00821 if(revoluteJoint != NULL)
00822 {
00823 makeInteractive1DOFRotationMarker(transform,
00824 revoluteJoint->axis_,
00825 model->getName() + "_joint_control",
00826 "",
00827 (float)maxDimension,
00828 gc.getState(ik_control_type_)->getJointState(jointName)->getJointStateValues()[0]);
00829 }
00830 else if(prismaticJoint != NULL)
00831 {
00832 makeInteractive1DOFTranslationMarker(transform,
00833 prismaticJoint->axis_,
00834 model->getName() + "_joint_control",
00835 "",
00836 (float)maxDimension,
00837 gc.getState(ik_control_type_)-> getJointState(jointName)->getJointStateValues()[0]);
00838 }
00839
00840 }
00841 }
00842 interactive_marker_server_->applyChanges();
00843 }
00844
00850 void setJointState(GroupCollection& gc, std::string& jointName, tf::Transform value)
00851 {
00852
00853
00854 KinematicState* currentState = gc.getState(ik_control_type_);
00855 string parentLink =
00856 gc.getState(ik_control_type_)->getKinematicModel()->getJointModel(jointName)->getParentLinkModel()->getName();
00857 string childLink =
00858 gc.getState(ik_control_type_)->getKinematicModel()->getJointModel(jointName)->getChildLinkModel()->getName();
00859 KinematicState::JointState* jointState = currentState->getJointState(jointName);
00860 const KinematicModel::JointModel* jointModel = jointState->getJointModel();
00861
00862 bool isRotational = (dynamic_cast<const KinematicModel::RevoluteJointModel*>(jointModel) != NULL);
00863 bool isPrismatic = (dynamic_cast<const KinematicModel::PrismaticJointModel*>(jointModel) != NULL);
00864
00865 KinematicState::LinkState* linkState = currentState->getLinkState(parentLink);
00866 tf::Transform transformedValue;
00867
00868
00869 if(isPrismatic)
00870 {
00871 value.setRotation(jointState->getVariableTransform().getRotation());
00872 transformedValue =currentState->getLinkState(childLink)->getLinkModel()->getJointOriginTransform().inverse() * linkState->getGlobalLinkTransform().inverse() * value;
00873 }
00874 else if(isRotational)
00875 {
00876 transformedValue =currentState->getLinkState(childLink)->getLinkModel()->getJointOriginTransform().inverse() * linkState->getGlobalLinkTransform().inverse() * value;
00877
00878 }
00879
00880
00881
00882 tf::Transform oldState = jointState->getVariableTransform();
00883 jointState->setJointStateValues(transformedValue);
00884
00885
00886
00887 map<string, double> stateMap;
00888 if(currentState->isJointWithinBounds(jointName))
00889 {
00890 currentState->getKinematicStateValues(stateMap);
00891 currentState->setKinematicState(stateMap);
00892 robot_state_->setKinematicState(stateMap);
00893
00894 publishJointStates(gc);
00895
00896 createSelectableJointMarkers(gc);
00897
00898 if(is_ik_control_active_)
00899 {
00900 selectMarker(selectable_markers_[current_group_name_ + "_selectable"],
00901 currentState->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform());
00902 }
00903 }
00904 else
00905 {
00906 jointState->setJointStateValues(oldState);
00907 }
00908
00909 }
00910
00911 void resetToLastGoodState(GroupCollection& gc)
00912 {
00913 setNewEndEffectorPosition(gc, gc.last_good_state_, collision_aware_);
00914 if(is_ik_control_active_)
00915 {
00916 selectMarker(selectable_markers_[current_group_name_ + "_selectable"],
00917 gc.getState(ik_control_type_)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform());
00918 }
00919 }
00920
00921 void setNewEndEffectorPosition(GroupCollection& gc, tf::Transform& cur, bool coll_aware)
00922 {
00923 if(!gc.getState(ik_control_type_)->updateKinematicStateWithLinkAt(gc.ik_link_name_, cur))
00924 {
00925 ROS_INFO("Problem");
00926 }
00927
00928 if(solveIKForEndEffectorPose(gc, coll_aware, constrain_rp_))
00929 {
00930 gc.good_ik_solution_ = true;
00931 gc.last_good_state_ = cur;
00932 }
00933 else
00934 {
00935 gc.good_ik_solution_ = false;
00936 }
00937 }
00938
00939 void determinePitchRollConstraintsGivenState(const WarehouseComponentsVisualizer::GroupCollection& gc,
00940 const planning_models::KinematicState& state,
00941 arm_navigation_msgs::OrientationConstraint& goal_constraint,
00942 arm_navigation_msgs::OrientationConstraint& path_constraint) const
00943 {
00944 tf::Transform cur = state.getLinkState(gc.ik_link_name_)->getGlobalLinkTransform();
00945
00946
00947 goal_constraint.header.frame_id = cm_->getWorldFrameId();
00948 goal_constraint.header.stamp = ros::Time::now();
00949 goal_constraint.link_name = gc.ik_link_name_;
00950 tf::quaternionTFToMsg(cur.getRotation(), goal_constraint.orientation);
00951 goal_constraint.absolute_roll_tolerance = 0.04;
00952 goal_constraint.absolute_pitch_tolerance = 0.04;
00953 goal_constraint.absolute_yaw_tolerance = M_PI;
00954 path_constraint.header.frame_id = cm_->getWorldFrameId();
00955 path_constraint.header.stamp = ros::Time::now();
00956 path_constraint.link_name = gc.ik_link_name_;
00957 tf::quaternionTFToMsg(cur.getRotation(), path_constraint.orientation);
00958 path_constraint.type = path_constraint.HEADER_FRAME;
00959 path_constraint.absolute_roll_tolerance = 0.1;
00960 path_constraint.absolute_pitch_tolerance = 0.1;
00961 path_constraint.absolute_yaw_tolerance = M_PI;
00962 }
00963
00964
00965 bool solveIKForEndEffectorPose(WarehouseComponentsVisualizer::GroupCollection& gc, bool coll_aware = true,
00966 bool constrain_pitch_and_roll = false, double change_redundancy = 0.0)
00967 {
00968 kinematics_msgs::PositionIKRequest ik_request;
00969 ik_request.ik_link_name = gc.ik_link_name_;
00970 ik_request.pose_stamped.header.frame_id = cm_->getWorldFrameId();
00971 ik_request.pose_stamped.header.stamp = ros::Time::now();
00972 tf::poseTFToMsg(gc.getState(ik_control_type_)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform(),
00973 ik_request.pose_stamped.pose);
00974 convertKinematicStateToRobotState(*gc.getState(ik_control_type_), ros::Time::now(), cm_->getWorldFrameId(),
00975 ik_request.robot_state);
00976 ik_request.ik_seed_state = ik_request.robot_state;
00977
00978
00979
00980
00981
00982
00983
00984
00985 map<string, double> joint_values;
00986 vector<string> joint_names;
00987
00988 if(coll_aware)
00989 {
00990 kinematics_msgs::GetConstraintAwarePositionIK::Request ik_req;
00991 kinematics_msgs::GetConstraintAwarePositionIK::Response ik_res;
00992 if(constrain_pitch_and_roll) {
00993 IKControlType other_state;
00994 if(ik_control_type_ == EndPosition)
00995 {
00996 other_state = StartPosition;
00997 }
00998 else
00999 {
01000 other_state = EndPosition;
01001 }
01002 arm_navigation_msgs::Constraints goal_constraints;
01003 goal_constraints.orientation_constraints.resize(1);
01004 arm_navigation_msgs::Constraints path_constraints;
01005 path_constraints.orientation_constraints.resize(1);
01006 determinePitchRollConstraintsGivenState(gc,
01007 *gc.getState(other_state),
01008 goal_constraints.orientation_constraints[0],
01009 path_constraints.orientation_constraints[0]);
01010 arm_navigation_msgs::ArmNavigationErrorCodes err;
01011 if(!cm_->isKinematicStateValid(*gc.getState(ik_control_type_),
01012 std::vector<std::string>(),
01013 err,
01014 goal_constraints,
01015 path_constraints)) {
01016 ROS_INFO_STREAM("Violates rp constraints");
01017 return false;
01018 }
01019 ik_req.constraints = goal_constraints;
01020 }
01021 ik_req.ik_request = ik_request;
01022 ik_req.timeout = ros::Duration(0.2);
01023 if(!gc.coll_aware_ik_service_.call(ik_req, ik_res))
01024 {
01025 ROS_INFO("Problem with ik service call");
01026 return false;
01027 }
01028 if(ik_res.error_code.val != ik_res.error_code.SUCCESS)
01029 {
01030 ROS_DEBUG_STREAM("Call yields bad error code " << ik_res.error_code.val);
01031 return false;
01032 }
01033 joint_names = ik_res.solution.joint_state.name;
01034 gc.joint_names_.clear();
01035 gc.joint_names_ = joint_names;
01036 for(unsigned int i = 0; i < ik_res.solution.joint_state.name.size(); i++)
01037 {
01038 joint_values[ik_res.solution.joint_state.name[i]] = ik_res.solution.joint_state.position[i];
01039 }
01040
01041 }
01042 else
01043 {
01044 kinematics_msgs::GetPositionIK::Request ik_req;
01045 kinematics_msgs::GetPositionIK::Response ik_res;
01046 ik_req.ik_request = ik_request;
01047 ik_req.timeout = ros::Duration(0.2);
01048 if(!gc.non_coll_aware_ik_service_.call(ik_req, ik_res))
01049 {
01050 ROS_INFO("Problem with ik service call");
01051 return false;
01052 }
01053 if(ik_res.error_code.val != ik_res.error_code.SUCCESS)
01054 {
01055 ROS_DEBUG_STREAM("Call yields bad error code " << ik_res.error_code.val);
01056 return false;
01057 }
01058 for(unsigned int i = 0; i < ik_res.solution.joint_state.name.size(); i++)
01059 {
01060 joint_values[ik_res.solution.joint_state.name[i]] = ik_res.solution.joint_state.position[i];
01061 }
01062
01063 }
01064
01065 lock_.lock();
01066 gc.getState(ik_control_type_)->setKinematicState(joint_values);
01067 lock_.unlock();
01068
01069 createSelectableJointMarkers(gc);
01070 if(coll_aware)
01071 {
01072 Constraints emp_con;
01073 ArmNavigationErrorCodes error_code;
01074
01075 if(!cm_->isKinematicStateValid(*gc.getState(ik_control_type_), joint_names, error_code, emp_con, emp_con, true))
01076 {
01077 ROS_INFO_STREAM("Problem with response");
01078 }
01079 }
01080
01081 publishJointStates(gc);
01082
01083 return true;
01084 }
01085
01086
01091 void publishJointStates(GroupCollection& gc)
01092 {
01093 sensor_msgs::JointState msg;
01094 msg.header.frame_id = cm_->getWorldFrameId();
01095 msg.header.stamp = ros::Time::now();
01096
01097 vector<KinematicState::JointState*> jointStates = gc.getState(ik_control_type_)->getJointStateVector();
01098
01099 map<string, double> stateMap;
01100 gc.getState(ik_control_type_)->getKinematicStateValues(stateMap);
01101 robot_state_->setKinematicState(stateMap);
01102
01103 for(size_t i = 0; i < jointStates.size(); i++)
01104 {
01105 KinematicState::JointState* state = jointStates[i];
01106 msg.name.push_back(state->getName());
01107
01108
01109 if(state->getJointStateValues().size() > 0)
01110 {
01111 msg.position.push_back(state->getJointStateValues()[0]);
01112 }
01113 else
01114 {
01115 msg.position.push_back(0.0f);
01116 }
01117 }
01118 joint_state_publisher_.publish(msg);
01119 }
01120
01121 bool planToEndEffectorState(WarehouseComponentsVisualizer::GroupCollection& gc)
01122 {
01123 MotionPlanRequest motion_plan_request;
01124 motion_plan_request.group_name = gc.name_;
01125 motion_plan_request.num_planning_attempts = 1;
01126 motion_plan_request.allowed_planning_time = PLANNING_DURATION;
01127 const KinematicState::JointStateGroup* jsg = gc.getState(EndPosition)->getJointStateGroup(gc.name_);
01128 motion_plan_request.goal_constraints.joint_constraints.resize(jsg->getJointNames().size());
01129 vector<double> joint_values;
01130 jsg->getKinematicStateValues(joint_values);
01131 for(unsigned int i = 0; i < jsg->getJointNames().size(); i++)
01132 {
01133 motion_plan_request.goal_constraints.joint_constraints[i].joint_name = jsg->getJointNames()[i];
01134 motion_plan_request.goal_constraints.joint_constraints[i].position = joint_values[i];
01135 motion_plan_request.goal_constraints.joint_constraints[i].tolerance_above = 0.01;
01136 motion_plan_request.goal_constraints.joint_constraints[i].tolerance_below = 0.01;
01137 }
01138 if(constrain_rp_) {
01139 motion_plan_request.group_name += "_cartesian";
01140 motion_plan_request.goal_constraints.position_constraints.resize(1);
01141 motion_plan_request.goal_constraints.orientation_constraints.resize(1);
01142 geometry_msgs::PoseStamped end_effector_wrist_pose;
01143 tf::poseTFToMsg(gc.getState(StartPosition)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform(),
01144 end_effector_wrist_pose.pose);
01145 end_effector_wrist_pose.header.frame_id = cm_->getWorldFrameId();
01146 arm_navigation_msgs::poseStampedToPositionOrientationConstraints(end_effector_wrist_pose,
01147 gc.ik_link_name_,
01148 motion_plan_request.goal_constraints.position_constraints[0],
01149 motion_plan_request.goal_constraints.orientation_constraints[0]);
01150 motion_plan_request.path_constraints.orientation_constraints.resize(1);
01151 determinePitchRollConstraintsGivenState(gc,
01152 *gc.getState(StartPosition),
01153 motion_plan_request.goal_constraints.orientation_constraints[0],
01154 motion_plan_request.path_constraints.orientation_constraints[0]);
01155 }
01156 convertKinematicStateToRobotState(*gc.getState(StartPosition), ros::Time::now(), cm_->getWorldFrameId(),
01157 motion_plan_request.start_state);
01158 GetMotionPlan::Request plan_req;
01159 plan_req.motion_plan_request = motion_plan_request;
01160 GetMotionPlan::Response plan_res;
01161
01162 logMotionPlanRequest(PLANNER_STAGE_NAME, motion_plan_request);
01163
01164 if(!planner_service_client_.call(plan_req, plan_res))
01165 {
01166 ROS_INFO("Something wrong with planner client");
01167 logOutcome(PLANNER_STAGE_NAME, plan_res.error_code);
01168 return false;
01169 }
01170
01171 if(gc.state_trajectory_display_map_.find("planner") != gc.state_trajectory_display_map_.end())
01172 {
01173 StateTrajectoryDisplay& disp = gc.state_trajectory_display_map_["planner"];
01174 if(plan_res.error_code.val != plan_res.error_code.SUCCESS)
01175 {
01176 disp.trajectory_error_code_ = plan_res.error_code;
01177 ROS_INFO_STREAM("Bad planning error code " << plan_res.error_code.val);
01178 gc.state_trajectory_display_map_["planner"].reset();
01179 logOutcome(PLANNER_STAGE_NAME, plan_res.error_code);
01180 return false;
01181 }
01182 last_motion_plan_request_ = motion_plan_request;
01183 playTrajectory(gc, "planner", plan_res.trajectory.joint_trajectory);
01184 logOutcome(PLANNER_STAGE_NAME, plan_res.error_code);
01185 logTrajectory(PLANNER_STAGE_NAME, plan_res.planning_time, plan_res.trajectory.joint_trajectory);
01186 return true;
01187 }
01188 else
01189 {
01190 return false;
01191 }
01192 }
01193
01194 void randomlyPerturb(WarehouseComponentsVisualizer::GroupCollection& gc)
01195 {
01196 tf::Transform currentPose = gc.getState(ik_control_type_)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform();
01197
01198 int maxTries = 10;
01199 int numTries = 0;
01200 bool found = false;
01201 double posVariance = 0.5;
01202 double angleVariance = 0.5;
01203
01204 while(!found && numTries < maxTries)
01205 {
01206
01207 double xVar = posVariance*((double)random()/(double)RAND_MAX) - posVariance/2.0;
01208 double yVar = posVariance*((double)random()/(double)RAND_MAX) - posVariance/2.0;
01209 double zVar = posVariance*((double)random()/(double)RAND_MAX) - posVariance/2.0;
01210
01211 double xAngleVar = angleVariance*((double)random()/(double)RAND_MAX) - angleVariance/2.0;
01212 double yAngleVar = angleVariance*((double)random()/(double)RAND_MAX) - angleVariance/2.0;
01213 double zAngleVar = angleVariance*((double)random()/(double)RAND_MAX) - angleVariance/2.0;
01214
01215 double x = currentPose.getOrigin().x() + xVar;
01216 double y = currentPose.getOrigin().y() + yVar;
01217 double z = currentPose.getOrigin().z() + zVar;
01218
01219 double xA = currentPose.getRotation().x() + xAngleVar;
01220 double yA = currentPose.getRotation().y() + yAngleVar;
01221 double zA = currentPose.getRotation().z() + zAngleVar;
01222
01223 tf::Vector3 newPos(x,y,z);
01224 tf::Quaternion newOrient(xA,yA,zA,1.0);
01225 tf::Transform newTrans(newOrient,newPos);
01226
01227 setNewEndEffectorPosition(gc, newTrans, collision_aware_);
01228 if(gc.good_ik_solution_)
01229 {
01230 found = true;
01231 if(is_ik_control_active_)
01232 {
01233 selectMarker(selectable_markers_[current_group_name_ + "_selectable"],
01234 gc.getState(ik_control_type_)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform());
01235 }
01236 }
01237
01238 numTries ++;
01239 posVariance *= 1.1;
01240 }
01241 }
01242
01243 bool filterPlannerTrajectory(WarehouseComponentsVisualizer::GroupCollection& gc)
01244 {
01245 FilterJointTrajectoryWithConstraints::Request filter_req;
01246 FilterJointTrajectoryWithConstraints::Response filter_res;
01247
01248 convertKinematicStateToRobotState(*gc.getState(StartPosition), ros::Time::now(), cm_->getWorldFrameId(),
01249 filter_req.start_state);
01250 StateTrajectoryDisplay& planner_disp = gc.state_trajectory_display_map_["planner"];
01251 filter_req.trajectory = planner_disp.joint_trajectory_;
01252 filter_req.group_name = gc.name_;
01253
01254 filter_req.goal_constraints = last_motion_plan_request_.goal_constraints;
01255 filter_req.path_constraints = last_motion_plan_request_.path_constraints;
01256 filter_req.allowed_time = ros::Duration(2.0);
01257
01258 if(!trajectory_filter_service_client_.call(filter_req, filter_res))
01259 {
01260 ROS_INFO("Problem with trajectory filter");
01261 gc.state_trajectory_display_map_["filter"].reset();
01262 logOutcome(FILTER_STAGE_NAME, filter_res.error_code);
01263 return false;
01264 }
01265 StateTrajectoryDisplay& filter_disp = gc.state_trajectory_display_map_["filter"];
01266 if(filter_res.error_code.val != filter_res.error_code.SUCCESS)
01267 {
01268 filter_disp.trajectory_error_code_ = filter_res.error_code;
01269 ROS_INFO_STREAM("Bad trajectory_filter error code " << filter_res.error_code.val);
01270 gc.state_trajectory_display_map_["filter"].reset();
01271 logOutcome(FILTER_STAGE_NAME, filter_res.error_code);
01272 return false;
01273 }
01274 playTrajectory(gc, "filter", filter_res.trajectory);
01275 logTrajectory(FILTER_STAGE_NAME, filter_req.allowed_time, filter_res.trajectory);
01276 return true;
01277 }
01278
01279 bool playTrajectory(WarehouseComponentsVisualizer::GroupCollection& gc, const string& source_name,
01280 const trajectory_msgs::JointTrajectory& traj)
01281 {
01282 lock_.lock();
01283 if(gc.state_trajectory_display_map_.find(source_name) == gc.state_trajectory_display_map_.end())
01284 {
01285 ROS_INFO_STREAM("No state display for group " << gc.name_ << " source name " << source_name);
01286 lock_.unlock();
01287 return false;
01288 }
01289 StateTrajectoryDisplay& disp = gc.state_trajectory_display_map_[source_name];
01290 disp.reset();
01291 disp.joint_trajectory_ = traj;
01292 disp.has_joint_trajectory_ = true;
01293 disp.show_joint_trajectory_ = true;
01294 disp.play_joint_trajectory_ = true;
01295 disp.state_ = new KinematicState(*robot_state_);
01296 vector<ArmNavigationErrorCodes> trajectory_error_codes;
01297
01298 cm_->isJointTrajectoryValid(*disp.state_, disp.joint_trajectory_, last_motion_plan_request_.goal_constraints,
01299 last_motion_plan_request_.path_constraints, disp.trajectory_error_code_,
01300 trajectory_error_codes, false);
01301
01302 if(disp.trajectory_error_code_.val != disp.trajectory_error_code_.SUCCESS)
01303 {
01304 disp.trajectory_bad_point_ = trajectory_error_codes.size() - 1;
01305 }
01306 else
01307 {
01308 disp.trajectory_bad_point_ = -1;
01309 }
01310
01311 moveThroughTrajectory(gc, source_name, 0);
01312 lock_.unlock();
01313 return true;
01314 }
01315
01316 void moveThroughTrajectory(WarehouseComponentsVisualizer::GroupCollection& gc, const string& source_name, int step)
01317 {
01318 lock_.lock();
01319 StateTrajectoryDisplay& disp = gc.state_trajectory_display_map_[source_name];
01320 unsigned int tsize = disp.joint_trajectory_.points.size();
01321 if(tsize == 0 || disp.state_ == NULL)
01322 {
01323 lock_.unlock();
01324 return;
01325 }
01326 if((int)disp.current_trajectory_point_ + step < 0)
01327 {
01328 disp.current_trajectory_point_ = 0;
01329 }
01330 else
01331 {
01332 disp.current_trajectory_point_ = ((int)disp.current_trajectory_point_) + step;
01333 }
01334 if(disp.current_trajectory_point_ >= tsize - 1)
01335 {
01336 disp.current_trajectory_point_ = tsize - 1;
01337 disp.play_joint_trajectory_ = false;
01338 disp.show_joint_trajectory_ = false;
01339 }
01340 map<string, double> joint_values;
01341 for(unsigned int i = 0; i < disp.joint_trajectory_.joint_names.size(); i++)
01342 {
01343 joint_values[disp.joint_trajectory_.joint_names[i]]
01344 = disp.joint_trajectory_.points[disp.current_trajectory_point_].positions[i];
01345 }
01346 disp.state_->setKinematicState(joint_values);
01347 lock_.unlock();
01348 }
01349
01358 MenuHandler::EntryHandle registerSubMenuEntry(MenuHandler& handler, MenuEntryMap& map, string name,
01359 MenuHandler::EntryHandle subMenuHandle)
01360 {
01361 MenuHandler::EntryHandle toReturn = handler.insert(subMenuHandle, name, process_function_ptr_);
01362 map[toReturn] = name;
01363 return toReturn;
01364 }
01365
01373 MenuHandler::EntryHandle registerMenuEntry(MenuHandler& handler, MenuEntryMap& map, string name)
01374 {
01375 MenuHandler::EntryHandle toReturn = handler.insert(name, process_function_ptr_);
01376 map[toReturn] = name;
01377 return toReturn;
01378 }
01379
01380 void sendMarkers()
01381 {
01382 lock_.lock();
01383 MarkerArray arr;
01384
01385 std_msgs::ColorRGBA stat_color_;
01386 stat_color_.a = 1.0;
01387 stat_color_.r = 0.1;
01388 stat_color_.g = 0.8;
01389 stat_color_.b = 0.3;
01390
01391 std_msgs::ColorRGBA attached_color_;
01392 attached_color_.a = 1.0;
01393 attached_color_.r = 0.6;
01394 attached_color_.g = 0.4;
01395 attached_color_.b = 0.3;
01396
01397 cm_->getAllCollisionSpaceObjectMarkers(*robot_state_, arr, "", stat_color_, attached_color_, ros::Duration(0.1));
01398
01399
01400
01401 if(!current_group_name_.empty())
01402 {
01403 std_msgs::ColorRGBA group_color;
01404 group_color.a = 0.3;
01405 group_color.r = 0.5;
01406 group_color.g = 0.9;
01407 group_color.b = 0.5;
01408
01409 std_msgs::ColorRGBA updated_color;
01410 updated_color.a = 0.3;
01411 updated_color.r = 1.0;
01412 updated_color.g = 0.5;
01413 updated_color.b = 1.0;
01414
01415 std_msgs::ColorRGBA bad_color;
01416 bad_color.a = 0.6;
01417 bad_color.r = 1.0;
01418 bad_color.g = 0.0;
01419 bad_color.b = 0.0;
01420
01421 GroupCollection& gc = group_map_[current_group_name_];
01422 const KinematicModel* kinematic_model = cm_->getKinematicModel();
01423
01424 IKControlType otherState;
01425 if(ik_control_type_ == EndPosition)
01426 {
01427 otherState = StartPosition;
01428 }
01429 else
01430 {
01431 otherState = EndPosition;
01432 }
01433
01434 if(is_ik_control_active_)
01435 {
01436 if(gc.getState(otherState) != NULL)
01437 {
01438 cm_->getGroupAndUpdatedJointMarkersGivenState(*gc.getState(otherState), arr, current_group_name_, group_color,
01439 updated_color, ros::Duration(0.1));
01440 }
01441 else
01442 {
01443 ROS_ERROR("Other state invalid!");
01444 }
01445 }
01446
01447 if(!gc.good_ik_solution_ && gc.getState(ik_control_type_) != NULL)
01448 {
01449 vector<string> lnames =
01450 kinematic_model->getChildLinkModelNames(kinematic_model->getLinkModel(gc.ik_link_name_));
01451
01452 cm_->getRobotMarkersGivenState(*gc.getState(ik_control_type_), arr, bad_color,
01453 current_group_name_, ros::Duration(0.1), &lnames);
01454 cm_->getAttachedCollisionObjectMarkers(*gc.getState(ik_control_type_), arr, current_group_name_, bad_color,
01455 ros::Duration(.2));
01456
01457 }
01458 for(map<string, StateTrajectoryDisplay>::iterator it = gc.state_trajectory_display_map_.begin(); it
01459 != gc.state_trajectory_display_map_.end(); it++)
01460 {
01461
01462 if(it->second.play_joint_trajectory_)
01463 {
01464 moveThroughTrajectory(gc, it->first, 5);
01465 }
01466
01467 if(it->second.show_joint_trajectory_)
01468 {
01469 const vector<const KinematicModel::LinkModel*>& updated_links =
01470 kinematic_model->getModelGroup(gc.name_)->getUpdatedLinkModels();
01471 vector<string> lnames;
01472 lnames.resize(updated_links.size());
01473 for(unsigned int i = 0; i < updated_links.size(); i++)
01474 {
01475 lnames[i] = updated_links[i]->getName();
01476 }
01477 cm_->getRobotMarkersGivenState(*(it->second.state_), arr, it->second.color_,
01478 it->first + "_trajectory", ros::Duration(0.1), &lnames);
01479
01480 cm_->getAttachedCollisionObjectMarkers(*(it->second.state_), arr, it->first + "_trajectory",
01481 it->second.color_, ros::Duration(0.1));
01482 }
01483 }
01484 }
01485 vis_marker_array_publisher_.publish(arr);
01486 lock_.unlock();
01487 }
01488
01489 void sendTransforms()
01490 {
01491 lock_.lock();
01492
01493 interactive_marker_server_->applyChanges();
01494 lock_.unlock();
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508 }
01509
01516 Marker makeMarkerBox(InteractiveMarker &msg, float alpha = 1.0f)
01517 {
01518 Marker marker;
01519 marker.type = Marker::CUBE;
01520
01521 marker.scale.x = msg.scale * 0.25;
01522 marker.scale.y = msg.scale * 0.25;
01523 marker.scale.z = msg.scale * 0.25;
01524 marker.color.r = 1.0;
01525 marker.color.g = 1.0;
01526 marker.color.b = 1.0;
01527 marker.color.a = alpha;
01528
01529 return marker;
01530 }
01531
01538 Marker makeMarkerCylinder(InteractiveMarker &msg, float alpha = 1.0f)
01539 {
01540 Marker marker;
01541 marker.type = Marker::CYLINDER;
01542
01543 marker.scale.x = msg.scale * 0.11;
01544 marker.scale.y = msg.scale * 0.11;
01545 marker.scale.z = msg.scale * 1.1;
01546 marker.color.r = 0.2;
01547 marker.color.g = 0.9;
01548 marker.color.b = 0.2;
01549 marker.color.a = alpha;
01550
01551 return marker;
01552 }
01553
01559 Marker makeMarkerSphere(InteractiveMarker &msg)
01560 {
01561 Marker marker;
01562
01563 marker.type = Marker::SPHERE;
01564
01565 marker.scale.x = msg.scale * 0.75;
01566 marker.scale.y = msg.scale * 0.75;
01567 marker.scale.z = msg.scale * 0.75;
01568 marker.color.r = 0.8;
01569 marker.color.g = 0.8;
01570 marker.color.b = 1.0;
01571 marker.color.a = 0.1;
01572
01573 return marker;
01574 }
01575
01582 InteractiveMarkerControl& makeInteractiveBoxControl(InteractiveMarker &msg, float alpha = 1.0f)
01583 {
01584 InteractiveMarkerControl control;
01585 control.always_visible = true;
01586 control.markers.push_back(makeMarkerBox(msg, alpha));
01587 msg.controls.push_back(control);
01588 return msg.controls.back();
01589 }
01590
01597 InteractiveMarkerControl& makeInteractiveCylinderControl(InteractiveMarker &msg, float alpha = 1.0f)
01598 {
01599 InteractiveMarkerControl control;
01600 control.always_visible = true;
01601 control.markers.push_back(makeMarkerCylinder(msg, alpha));
01602 msg.controls.push_back(control);
01603 return msg.controls.back();
01604 }
01605
01609 void refreshEnvironment()
01610 {
01611 GroupCollection& gc = group_map_[current_group_name_];
01612 sendPlanningScene();
01613 moveEndEffectorMarkers(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false);
01614
01615 tf::Transform cur = toBulletTransform(last_ee_poses_[current_group_name_]);
01616 setNewEndEffectorPosition(gc, cur, collision_aware_);
01617 }
01618
01624 void processInteractiveFeedback(const InteractiveMarkerFeedbackConstPtr &feedback)
01625 {
01626 GroupCollection& gc = group_map_[current_group_name_];
01627 switch (feedback->event_type)
01628 {
01629 case InteractiveMarkerFeedback::BUTTON_CLICK:
01630 if(feedback->marker_name.rfind("_selectable") != string::npos)
01631 {
01632 tf::Transform cur = toBulletTransform(feedback->pose);
01633 if(isGroupName(feedback->marker_name.substr(0, feedback->marker_name.rfind("_selectable"))))
01634 {
01635 unsigned int cmd = 0;
01636 for(map<string, GroupCollection>::iterator it = group_map_.begin(); it != group_map_.end(); it++)
01637 {
01638
01639 if(feedback->marker_name.substr(0, feedback->marker_name.rfind("_selectable")) == it->first)
01640 {
01641 deleteKinematicStates();
01642 selectPlanningGroup(cmd);
01643 break;
01644 }
01645 cmd++;
01646 }
01647
01648 }
01649 else if(feedback->marker_name.rfind("pole_") != string::npos)
01650 {
01651 selectMarker(selectable_markers_[feedback->marker_name], cur);
01652 }
01653 }
01654 break;
01655
01656 case InteractiveMarkerFeedback::MENU_SELECT:
01657 MenuHandler::EntryHandle handle;
01658 if(feedback->marker_name.rfind("_selectable") != string::npos)
01659 {
01660 tf::Transform cur = toBulletTransform(feedback->pose);
01661 if(is_ik_control_active_
01662 && isGroupName(feedback->marker_name.substr(0, feedback->marker_name.rfind("_selectable"))))
01663 {
01664 handle = feedback->menu_entry_id;
01665 unsigned int cmd = 0;
01666 for(map<string, GroupCollection>::iterator it = group_map_.begin(); it != group_map_.end(); it++)
01667 {
01668
01669 if(feedback->marker_name.substr(0, feedback->marker_name.rfind("_selectable")) == it->first)
01670 {
01671 deleteKinematicStates();
01672 selectPlanningGroup(cmd);
01673 break;
01674 }
01675 cmd++;
01676 }
01677
01678 }
01679 else if(feedback->marker_name.rfind("pole_") != string::npos)
01680 {
01681 handle = feedback->menu_entry_id;
01682 if(menu_entry_maps_["Collision Object Selection"][handle] == "Select")
01683 {
01684 selectMarker(selectable_markers_[feedback->marker_name], cur);
01685 }
01686 else if(menu_entry_maps_["Collision Object Selection"][handle] == "Delete")
01687 {
01688 this->removeCollisionPoleByName(
01689 feedback->marker_name.substr(0,
01690 feedback->marker_name.rfind("_selectable")));
01691 interactive_marker_server_->erase(feedback->marker_name);
01692 refreshEnvironment();
01693 }
01694 }
01695 }
01696 else if(feedback->marker_name == "top_level")
01697 {
01698 handle = feedback->menu_entry_id;
01699
01700 if(handle == ik_control_handle_)
01701 {
01702 MenuHandler::CheckState currentState;
01703 menu_handler_map_["Top Level"].getCheckState(ik_control_handle_, currentState);
01704
01705 if(currentState == MenuHandler::UNCHECKED)
01706 {
01707 is_ik_control_active_ = true;
01708 menu_handler_map_["Top Level"].setCheckState(ik_control_handle_, MenuHandler::CHECKED);
01709 menu_handler_map_["Top Level"].reApply(*interactive_marker_server_);
01710 selectMarker(selectable_markers_[current_group_name_ + "_selectable"],
01711 gc.getState(ik_control_type_)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform());
01712 }
01713 else
01714 {
01715 is_ik_control_active_ = false;
01716 menu_handler_map_["Top Level"].setCheckState(ik_control_handle_, MenuHandler::UNCHECKED);
01717 menu_handler_map_["Top Level"].reApply(*interactive_marker_server_);
01718 geometry_msgs::Pose nonsensePose;
01719 deselectMarker(selectable_markers_[current_group_name_ + "_selectable"],
01720 gc.getState(ik_control_type_)->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform());
01721 interactive_marker_server_->applyChanges();
01722 }
01723 }
01724 else if(handle == joint_control_handle_)
01725 {
01726 MenuHandler::CheckState currentState;
01727 menu_handler_map_["Top Level"].getCheckState(joint_control_handle_, currentState);
01728 if(currentState == MenuHandler::UNCHECKED)
01729 {
01730 is_joint_control_active_ = true;
01731 menu_handler_map_["Top Level"].setCheckState(joint_control_handle_, MenuHandler::CHECKED);
01732 createSelectableJointMarkers(gc);
01733 menu_handler_map_["Top Level"].reApply(*interactive_marker_server_);
01734 }
01735 else
01736 {
01737 is_joint_control_active_ = false;
01738 menu_handler_map_["Top Level"].setCheckState(joint_control_handle_, MenuHandler::UNCHECKED);
01739 deleteJointMarkers(gc);
01740 menu_handler_map_["Top Level"].reApply(*interactive_marker_server_);
01741 }
01742 }
01743 else if(handle == collision_aware_handle_)
01744 {
01745 MenuHandler::CheckState currentState;
01746 menu_handler_map_["Top Level"].getCheckState(collision_aware_handle_, currentState);
01747 if(currentState == MenuHandler::UNCHECKED)
01748 {
01749 collision_aware_ = true;
01750 menu_handler_map_["Top Level"].setCheckState(collision_aware_handle_, MenuHandler::CHECKED);
01751 createSelectableJointMarkers(gc);
01752 menu_handler_map_["Top Level"].reApply(*interactive_marker_server_);
01753 }
01754 else if(currentState == MenuHandler::CHECKED)
01755 {
01756 collision_aware_ = false;
01757 menu_handler_map_["Top Level"].setCheckState(collision_aware_handle_, MenuHandler::UNCHECKED);
01758 createSelectableJointMarkers(gc);
01759 menu_handler_map_["Top Level"].reApply(*interactive_marker_server_);
01760 }
01761 }
01762 else if(menu_entry_maps_["Top Level"][handle] == "Create Pole")
01763 {
01764 Pose polePose;
01765 polePose.position.x = 2.0f;
01766 polePose.position.z = 1.0f;
01767 polePose.position.y = 0.0f;
01768 polePose.orientation.x = 0.0f;
01769 polePose.orientation.y = 0.0f;
01770 polePose.orientation.z = 0.0f;
01771 polePose.orientation.w = 1.0f;
01772
01773 createCollisionPole(nextCollisionPole(), polePose);
01774 refreshEnvironment();
01775 }
01776 else if(menu_entry_maps_["Top Level"][handle] == "Log Planning Scene ...")
01777 {
01778 logNewPlanningScene();
01779 }
01780
01781 unsigned int cmd = 0;
01782 for(map<string, GroupCollection>::iterator it = group_map_.begin(); it != group_map_.end(); it++)
01783 {
01784
01785 if(menu_entry_maps_["Top Level"][handle] == it->first)
01786 {
01787 selectPlanningGroup(cmd);
01788 break;
01789 }
01790 cmd++;
01791 }
01792
01793 }
01794 else if(is_ik_control_active_ && isGroupName(feedback->marker_name))
01795 {
01796 handle = feedback->menu_entry_id;
01797 MenuHandler::CheckState checkState;
01798
01799 if(handle == start_position_handle_ || handle == end_position_handle_)
01800 {
01801 menu_handler_map_["End Effector"].getCheckState(handle, checkState);
01802
01803 if(checkState != MenuHandler::CHECKED)
01804 {
01805 menu_handler_map_["End Effector"].setCheckState(handle, MenuHandler::CHECKED);
01806 menu_handler_map_["End Effector"].reApply(*interactive_marker_server_);
01807 }
01808
01809 if(handle == start_position_handle_)
01810 {
01811 menu_handler_map_["End Effector"].setCheckState(end_position_handle_, MenuHandler::UNCHECKED);
01812 ik_control_type_ = StartPosition;
01813 selectMarker(selectable_markers_[feedback->marker_name + "_selectable"],
01814 gc.start_state_->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform());
01815 createSelectableJointMarkers(gc);
01816 menu_handler_map_["End Effector"].reApply(*interactive_marker_server_);
01817 }
01818 else if(handle == end_position_handle_)
01819 {
01820 menu_handler_map_["End Effector"].setCheckState(start_position_handle_, MenuHandler::UNCHECKED);
01821 ik_control_type_ = EndPosition;
01822 selectMarker(selectable_markers_[feedback->marker_name + "_selectable"],
01823 gc.end_state_->getLinkState(gc.ik_link_name_)->getGlobalLinkTransform());
01824 createSelectableJointMarkers(gc);
01825 menu_handler_map_["End Effector"].reApply(*interactive_marker_server_);
01826 }
01827
01828 publishJointStates(gc);
01829
01830 }
01831 else if(handle == constrain_rp_handle_) {
01832 menu_handler_map_["End Effector"].getCheckState(handle, checkState);
01833 if(checkState != MenuHandler::CHECKED)
01834 {
01835 menu_handler_map_["End Effector"].setCheckState(handle, MenuHandler::CHECKED);
01836 constrain_rp_ = true;
01837 } else {
01838 menu_handler_map_["End Effector"].setCheckState(handle, MenuHandler::UNCHECKED);
01839 constrain_rp_ = false;
01840 }
01841 moveEndEffectorMarkers(0.0,0.0,0.0,0.0,0.0,0.0,true);
01842 menu_handler_map_["End Effector"].reApply(*interactive_marker_server_);
01843 }
01844 else if(menu_entry_maps_["End Effector"][handle] == "Plan")
01845 {
01846 planToEndEffectorState(gc);
01847 }
01848 else if(menu_entry_maps_["End Effector"][handle] == "Filter Trajectory")
01849 {
01850 filterPlannerTrajectory(gc);
01851 }
01852 else if(menu_entry_maps_["End Effector"][handle] == "Randomly Perturb")
01853 {
01854 randomlyPerturb(gc);
01855 }
01856 else if(menu_entry_maps_["End Effector"][handle] == "Go To Last Good State")
01857 {
01858 resetToLastGoodState(gc);
01859 }
01860 else if(menu_entry_maps_["End Effector"][handle] == "Deselect")
01861 {
01862 tf::Transform cur = toBulletTransform(feedback->pose);
01863 deselectMarker(selectable_markers_[feedback->marker_name + "_selectable"], cur);
01864 }
01865 }
01866 else if(feedback->marker_name.rfind("pole_") != string::npos)
01867 {
01868 handle = feedback->menu_entry_id;
01869
01870 stringstream controlName;
01871 controlName << feedback->marker_name;
01872
01873 if(menu_entry_maps_["Collision Object"][handle] == "Delete")
01874 {
01875 this->removeCollisionPoleByName(feedback->marker_name);
01876 interactive_marker_server_->erase(feedback->marker_name);
01877 refreshEnvironment();
01878 }
01879 else if(menu_entry_maps_["Collision Object"][handle] == "Deselect")
01880 {
01881 tf::Transform cur = toBulletTransform(feedback->pose);
01882 deselectMarker(selectable_markers_[feedback->marker_name + "_selectable"], cur);
01883 }
01884 }
01885
01886 break;
01887
01888 case InteractiveMarkerFeedback::MOUSE_UP:
01889 if(feedback->marker_name.rfind("pole_") != string::npos && feedback->marker_name.rfind("_selectable")
01890 == string::npos)
01891 {
01892 collision_poles_[feedback->marker_name].poses[0] = feedback->pose;
01893 refreshEnvironment();
01894 }
01895 else if(feedback->marker_name.rfind("_joint_control") != string::npos)
01896 {
01897 joint_clicked_map_[feedback->marker_name] = false;
01898 }
01899 break;
01900
01901 case InteractiveMarkerFeedback::MOUSE_DOWN:
01902 if(feedback->marker_name.rfind("_joint_control") != string::npos)
01903 {
01904 if(!joint_clicked_map_[feedback->marker_name])
01905 {
01906 joint_clicked_map_[feedback->marker_name] = true;
01907 joint_prev_transform_map_[feedback->marker_name] = toBulletTransform(feedback->pose);
01908 }
01909 }
01910 break;
01911 case InteractiveMarkerFeedback::POSE_UPDATE:
01912 if(is_ik_control_active_ && isGroupName(feedback->marker_name))
01913 {
01914 tf::Transform cur = toBulletTransform(feedback->pose);
01915 setNewEndEffectorPosition(gc, cur, collision_aware_);
01916 last_ee_poses_[current_group_name_] = feedback->pose;
01917 }
01918 else if(is_joint_control_active_ && feedback->marker_name.rfind("_joint_control") != string::npos)
01919 {
01920 tf::Transform cur = toBulletTransform(feedback->pose);
01921
01922 string jointName = feedback->marker_name.substr(0, feedback->marker_name.rfind("_joint_control"));
01923 setJointState(gc, jointName, cur);
01924 }
01925 break;
01926 }
01927 interactive_marker_server_->applyChanges();
01928 }
01929
01935 bool isGroupName(const string& name)
01936 {
01937 return group_map_.find(name) != group_map_.end();
01938 }
01939
01940 void makeTopLevelMenu()
01941 {
01942 InteractiveMarker int_marker;
01943 int_marker.pose.position.z = 2.25;
01944 int_marker.name = "top_level";
01945 int_marker.description = "Planning Visualizer";
01946 int_marker.header.frame_id = "/" + cm_->getWorldFrameId();
01947
01948
01949 InteractiveMarkerControl control;
01950 control.interaction_mode = InteractiveMarkerControl::MENU;
01951 control.always_visible = true;
01952
01953 Marker labelMarker;
01954 labelMarker.type = Marker::TEXT_VIEW_FACING;
01955 labelMarker.text = "Command...";
01956 labelMarker.color.r = 1.0;
01957 labelMarker.color.g = 1.0;
01958 labelMarker.color.b = 1.0;
01959 labelMarker.color.a = 1.0;
01960 labelMarker.scale.x = 0.5;
01961 labelMarker.scale.y = 0.2;
01962 labelMarker.scale.z = 0.1;
01963 control.markers.push_back(labelMarker);
01964
01965 int_marker.controls.push_back(control);
01966
01967 interactive_marker_server_->insert(int_marker);
01968 interactive_marker_server_->setCallback(int_marker.name, process_function_ptr_);
01969 menu_handler_map_["Top Level"].apply(*interactive_marker_server_, int_marker.name);
01970 }
01971
01975 void makePoleContextMenu(tf::Transform transform, string name, string description, float scale = 1.0f)
01976 {
01977
01978 makeSelectableMarker(WarehouseComponentsVisualizer::CollisionObject, transform, name, description, scale);
01979 }
01980
01990 void makeSelectableMarker(InteractiveMarkerType type, tf::Transform transform, string name, string description,
01991 float scale = 1.0f, bool publish = true)
01992 {
01993 SelectableMarker selectable_marker;
01994 selectable_marker.type_ = type;
01995 selectable_marker.name_ = name + "_selectable";
01996 selectable_marker.controlName_ = name;
01997 selectable_marker.controlDescription_ = description;
01998
01999 InteractiveMarker marker;
02000 marker.header.frame_id = "/" + cm_->getWorldFrameId();
02001 ;
02002 marker.header.stamp = ros::Time::now();
02003 marker.pose.position.x = transform.getOrigin().x();
02004 marker.pose.position.y = transform.getOrigin().y();
02005 marker.pose.position.z = transform.getOrigin().z();
02006 marker.pose.orientation.w = transform.getRotation().w();
02007 marker.pose.orientation.x = transform.getRotation().x();
02008 marker.pose.orientation.y = transform.getRotation().y();
02009 marker.pose.orientation.z = transform.getRotation().z();
02010 marker.scale = scale;
02011 marker.name = name + "_selectable";
02012 marker.description = description;
02013 InteractiveMarkerControl control;
02014 control.interaction_mode = InteractiveMarkerControl::BUTTON;
02015 control.always_visible = true;
02016
02017 switch (type)
02018 {
02019 case WarehouseComponentsVisualizer::EndEffectorControl:
02020 control.markers.push_back(makeMarkerBox(marker, 0.5f));
02021 marker.controls.push_back(control);
02022 interactive_marker_server_->insert(marker);
02023 interactive_marker_server_->setCallback(marker.name, process_function_ptr_);
02024 menu_handler_map_["End Effector Selection"].apply(*interactive_marker_server_, marker.name);
02025 break;
02026 case WarehouseComponentsVisualizer::CollisionObject:
02027 control.markers.push_back(makeMarkerCylinder(marker, 1.0f));
02028 marker.controls.push_back(control);
02029 interactive_marker_server_->insert(marker);
02030 interactive_marker_server_->setCallback(marker.name, process_function_ptr_);
02031 menu_handler_map_["Collision Object Selection"].apply(*interactive_marker_server_, marker.name);
02032 break;
02033 case WarehouseComponentsVisualizer::JointControl:
02034 control.markers.push_back(makeMarkerBox(marker, 0.5f));
02035 marker.controls.push_back(control);
02036 interactive_marker_server_->insert(marker);
02037 interactive_marker_server_->setCallback(marker.name, process_function_ptr_);
02038 menu_handler_map_["Joint Selection"].apply(*interactive_marker_server_, marker.name);
02039 break;
02040 }
02041
02042 selectable_markers_[marker.name] = selectable_marker;
02043
02044 if(publish)
02045 {
02046 interactive_marker_server_->applyChanges();
02047 }
02048 }
02049
02055 bool selectableMarkerExists(string name)
02056 {
02057 return selectable_markers_.find(name) != selectable_markers_.end();
02058 }
02059
02065 void selectMarker(SelectableMarker& marker, tf::Transform transform)
02066 {
02067 InteractiveMarker dummy;
02068 if(interactive_marker_server_->get(marker.controlName_, dummy))
02069 {
02070 dummy.header.stamp = ros::Time::now();
02071 interactive_marker_server_->setPose(marker.controlName_, toGeometryPose(transform), dummy.header);
02072 }
02073 else
02074 {
02075 if(!interactive_marker_server_->erase(marker.name_))
02076 {
02077 return;
02078 }
02079
02080 switch (marker.type_)
02081 {
02082 case WarehouseComponentsVisualizer::EndEffectorControl:
02083 makeInteractive6DOFMarker(false, transform, marker.controlName_, marker.controlDescription_, 0.225f, false);
02084 break;
02085 case WarehouseComponentsVisualizer::CollisionObject:
02086 makeInteractive6DOFMarker(false, transform, marker.controlName_, marker.controlDescription_, 2.0f, true);
02087 break;
02088 case WarehouseComponentsVisualizer::JointControl:
02089 makeInteractive6DOFMarker(false, transform, marker.controlName_, marker.controlDescription_, 0.225f, false);
02090 break;
02091 }
02092 }
02093 }
02094
02100 void deselectMarker(SelectableMarker& marker, tf::Transform transform)
02101 {
02102 if(!interactive_marker_server_->erase(marker.controlName_))
02103 {
02104 return;
02105 }
02106
02107 float scale = 1.0f;
02108
02109 switch (marker.type_)
02110 {
02111 case WarehouseComponentsVisualizer::EndEffectorControl:
02112 scale = 0.5f;
02113 break;
02114 case WarehouseComponentsVisualizer::CollisionObject:
02115 scale = 2.0f;
02116 break;
02117 case WarehouseComponentsVisualizer::JointControl:
02118 scale = 0.225f;
02119 break;
02120 }
02121
02122 makeSelectableMarker(marker.type_, transform, marker.controlName_, marker.controlDescription_, scale);
02123 }
02124
02125 void makeInteractive1DOFTranslationMarker(tf::Transform transform, tf::Vector3 axis, string name, string description,
02126 float scale = 1.0f, float value = 0.0f)
02127 {
02128 InteractiveMarker marker;
02129 marker.header.frame_id = cm_->getWorldFrameId();
02130 marker.pose.position.x = transform.getOrigin().x();
02131 marker.pose.position.y = transform.getOrigin().y();
02132 marker.pose.position.z = transform.getOrigin().z();
02133 marker.pose.orientation.w = transform.getRotation().w();
02134 marker.pose.orientation.x = transform.getRotation().x();
02135 marker.pose.orientation.y = transform.getRotation().y();
02136 marker.pose.orientation.z = transform.getRotation().z();
02137 marker.scale = scale;
02138 marker.name = name;
02139 marker.description = description;
02140 InteractiveMarker dummy;
02141 InteractiveMarkerControl control;
02142 if(interactive_marker_server_->get(marker.name, dummy))
02143 {
02144 interactive_marker_server_->setPose(marker.name, marker.pose, marker.header);
02145 }
02146 else
02147 {
02148 control.orientation.x = axis.x();
02149 control.orientation.y = axis.z();
02150 control.orientation.z = axis.y();
02151 control.orientation.w = 1;
02152 control.independent_marker_orientation = false;
02153 control.always_visible = false;
02154 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
02155 marker.controls.push_back(control);
02156 interactive_marker_server_->insert(marker);
02157 interactive_marker_server_->setCallback(marker.name, process_function_ptr_);
02158 }
02159
02160 }
02161
02162 void makeInteractive1DOFRotationMarker(tf::Transform transform, tf::Vector3 axis, string name, string description,
02163 float scale = 1.0f, float angle = 0.0f)
02164 {
02165 InteractiveMarker marker;
02166 marker.header.frame_id = cm_->getWorldFrameId();
02167 marker.pose.position.x = transform.getOrigin().x();
02168 marker.pose.position.y = transform.getOrigin().y();
02169 marker.pose.position.z = transform.getOrigin().z();
02170 marker.pose.orientation.w = transform.getRotation().w();
02171 marker.pose.orientation.x = transform.getRotation().x();
02172 marker.pose.orientation.y = transform.getRotation().y();
02173 marker.pose.orientation.z = transform.getRotation().z();
02174 marker.scale = scale;
02175 marker.name = name;
02176 marker.description = description;
02177
02178 InteractiveMarker dummy;
02179 if(interactive_marker_server_->get(marker.name, dummy))
02180 {
02181 interactive_marker_server_->setPose(marker.name, marker.pose, marker.header);
02182 }
02183 else
02184 {
02185 InteractiveMarkerControl control;
02186 control.orientation.x = axis.x();
02187 control.orientation.y = axis.z();
02188 control.orientation.z = axis.y();
02189 control.orientation.w = 1;
02190 control.independent_marker_orientation = false;
02191 control.always_visible = false;
02192 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
02193 marker.controls.push_back(control);
02194 interactive_marker_server_->insert(marker);
02195 interactive_marker_server_->setCallback(marker.name, process_function_ptr_);
02196 }
02197 }
02198
02208 void makeInteractive6DOFMarker(bool fixed, tf::Transform transform, string name, string description,
02209 float scale = 1.0f, bool pole = false)
02210 {
02211 InteractiveMarker marker;
02212 marker.header.frame_id = "/" + cm_->getWorldFrameId();
02213 marker.pose.position.x = transform.getOrigin().x();
02214 marker.pose.position.y = transform.getOrigin().y();
02215 marker.pose.position.z = transform.getOrigin().z();
02216 marker.pose.orientation.w = transform.getRotation().w();
02217 marker.pose.orientation.x = transform.getRotation().x();
02218 marker.pose.orientation.y = transform.getRotation().y();
02219 marker.pose.orientation.z = transform.getRotation().z();
02220 marker.scale = scale;
02221 marker.name = name;
02222 marker.description = description;
02223
02224 if(!pole)
02225 {
02226 makeInteractiveBoxControl(marker, 0.5f);
02227 }
02228 else
02229 {
02230 makeInteractiveCylinderControl(marker, 1.0f);
02231 }
02232
02233 InteractiveMarkerControl control;
02234
02235 if(fixed)
02236 {
02237 control.orientation_mode = InteractiveMarkerControl::FIXED;
02238 }
02239
02240 control.orientation.w = 1;
02241 control.orientation.x = 1;
02242 control.orientation.y = 0;
02243 control.orientation.z = 0;
02244 control.always_visible = false;
02245 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
02246 marker.controls.push_back(control);
02247 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
02248 marker.controls.push_back(control);
02249
02250 control.orientation.w = 1;
02251 control.orientation.x = 0;
02252 control.orientation.y = 1;
02253 control.orientation.z = 0;
02254 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
02255 marker.controls.push_back(control);
02256 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
02257 marker.controls.push_back(control);
02258
02259 control.orientation.w = 1;
02260 control.orientation.x = 0;
02261 control.orientation.y = 0;
02262 control.orientation.z = 1;
02263 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
02264 marker.controls.push_back(control);
02265 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
02266 marker.controls.push_back(control);
02267
02268 interactive_marker_server_->insert(marker);
02269 interactive_marker_server_->setCallback(marker.name, process_function_ptr_);
02270
02271 control.interaction_mode = InteractiveMarkerControl::MENU;
02272
02273 marker.controls.push_back(control);
02274
02275 if(!pole)
02276 {
02277 menu_handler_map_["End Effector"].apply(*interactive_marker_server_, marker.name);
02278 }
02279 else
02280 {
02281 menu_handler_map_["Collision Object"].apply(*interactive_marker_server_, marker.name);
02282 }
02283
02284 }
02285
02286 bool doesGroupHaveGoodIKSolution(const string& group) const
02287 {
02288 if(group_map_.find(group) == group_map_.end())
02289 {
02290 return false;
02291 }
02292 return group_map_.find(group)->second.good_ik_solution_;
02293 }
02294
02295 bool doesGroupHaveGoodTrajectory(const string& group, const string& source) const
02296 {
02297 if(group_map_.find(group) == group_map_.end())
02298 {
02299 return false;
02300 }
02301 const GroupCollection& gc = group_map_.find(group)->second;
02302 if(gc.state_trajectory_display_map_.find(source) == gc.state_trajectory_display_map_.end())
02303 {
02304 return false;
02305 }
02306 return gc.state_trajectory_display_map_.find(source)->second.has_joint_trajectory_;
02307 }
02308
02313 size_t getNumPlanningGroups()
02314 {
02315 return group_map_.size();
02316 }
02317
02318 GroupCollection* getPlanningGroup(unsigned int i)
02319 {
02320 unsigned int cmd = 0;
02321 for(map<string, GroupCollection>::iterator it = group_map_.begin(); it != group_map_.end(); it++)
02322 {
02323 if(cmd == i)
02324 {
02325 return &(it->second);
02326 }
02327 cmd++;
02328 }
02329
02330 return NULL;
02331 }
02332 protected:
02333
02334 Pose toGeometryPose(tf::Transform transform)
02335 {
02336 Pose toReturn;
02337 toReturn.position.x = transform.getOrigin().x();
02338 toReturn.position.y = transform.getOrigin().y();
02339 toReturn.position.z = transform.getOrigin().z();
02340 toReturn.orientation.x = transform.getRotation().x();
02341 toReturn.orientation.y = transform.getRotation().y();
02342 toReturn.orientation.z = transform.getRotation().z();
02343 toReturn.orientation.w = transform.getRotation().w();
02344 return toReturn;
02345 }
02346
02347 tf::Transform toBulletTransform(geometry_msgs::Pose pose)
02348 {
02349 tf::Quaternion quat = tf::Quaternion(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w);
02350 tf::Vector3 vec = tf::Vector3(pose.position.x, pose.position.y, pose.position.z);
02351 return tf::Transform(quat, vec);
02352 }
02353
02354 void deleteKinematicStates()
02355 {
02356 for(map<string, GroupCollection>::iterator it = group_map_.begin(); it != group_map_.end(); it++)
02357 {
02358 it->second.reset();
02359 }
02360 }
02361
02362 IKControlType ik_control_type_;
02363
02364 boost::recursive_mutex lock_;
02365 boost::shared_ptr<InteractiveMarkerServer> interactive_marker_server_;
02366
02367 CollisionModels* cm_;
02368
02370 int num_collision_poles_;
02371
02372 KinematicState* robot_state_;
02373
02374 map<string, GroupCollection> group_map_;
02375
02377 map<string, arm_navigation_msgs::CollisionObject> collision_poles_;
02378
02380 map<string, Pose> last_ee_poses_;
02381
02383 map<string, SelectableMarker> selectable_markers_;
02384
02386 MenuHandler::FeedbackCallback process_function_ptr_;
02387
02388 MenuHandler::EntryHandle start_position_handle_;
02389 MenuHandler::EntryHandle end_position_handle_;
02390 MenuHandler::EntryHandle ik_control_handle_;
02391 MenuHandler::EntryHandle joint_control_handle_;
02392 MenuHandler::EntryHandle collision_aware_handle_;
02393 MenuHandler::EntryHandle constrain_rp_handle_;
02394 bool constrain_rp_;
02395 bool collision_aware_;
02397 MenuHandlerMap menu_handler_map_;
02398
02400 MenuMap menu_entry_maps_;
02401
02402 MotionPlanRequest last_motion_plan_request_;
02403
02404 ros::NodeHandle nh_;
02405 ros::Publisher joint_state_publisher_;
02406 ros::Publisher vis_marker_array_publisher_;
02407 ros::Publisher vis_marker_publisher_;
02408 ros::ServiceClient get_planning_scene_client_;
02409 ros::ServiceClient planner_service_client_;
02410 ros::ServiceClient trajectory_filter_service_client_;
02411
02412 string current_group_name_;
02413
02414 tf::TransformBroadcaster transform_broadcaster_;
02415
02416 bool is_ik_control_active_;
02417 bool is_joint_control_active_;
02418
02419 map<string, bool> joint_clicked_map_;
02420 map<string, tf::Transform> joint_prev_transform_map_;
02421
02422 move_arm_warehouse::MoveArmWarehouseLoggerReader* logger_;
02423 arm_navigation_msgs::PlanningScene planning_scene_;
02424
02425 };
02426
02427 WarehouseComponentsVisualizer* wcv;
02428
02429 bool inited = false;
02430
02431 void spin_function()
02432 {
02433 ros::WallRate r(100.0);
02434 while(ros::ok())
02435 {
02436 r.sleep();
02437 ros::spinOnce();
02438 }
02439 }
02440
02441 void update_function()
02442 {
02443 unsigned int counter = 0;
02444 while(ros::ok())
02445 {
02446 if(inited)
02447 {
02448
02449 if(counter % 5 == 0)
02450 {
02451 counter = 1;
02452 wcv->sendMarkers();
02453 }
02454 else
02455 {
02456 counter++;
02457 }
02458 }
02459
02460 usleep(3000);
02461 }
02462 }
02463
02464 void quit(int sig)
02465 {
02466 if(wcv != NULL)
02467 {
02468 delete wcv;
02469 }
02470 exit(0);
02471 }
02472
02473 int main(int argc, char** argv)
02474 {
02475 ros::init(argc, argv, "warehouse_components_visualizer", ros::init_options::NoSigintHandler);
02476
02477 boost::thread spin_thread(boost::bind(&spin_function));
02478 boost::thread update_thread(boost::bind(&update_function));
02479 wcv = new WarehouseComponentsVisualizer();
02480
02481 inited = true;
02482
02483 for(size_t i = 0; i < wcv->getNumPlanningGroups(); i++)
02484 {
02485 wcv->selectPlanningGroup(i);
02486 wcv->solveIKForEndEffectorPose((*wcv->getPlanningGroup(i)));
02487 wcv->publishJointStates((*wcv->getPlanningGroup(i)));
02488 }
02489
02490 ros::waitForShutdown();
02491
02492 return 0;
02493 }