LinearController.cpp
Go to the documentation of this file.
2 
3 using std::max;
4 
6  pnh("~"),
7  tf_listener(tf_buffer),
8  linear_move_server(pnh, "linear_move", boost::bind(&LinearController::executeLinearMove, this, _1), false),
9  arm_control_client("arm_controller/follow_joint_trajectory")
10 {
11  pnh.param("max_linear_vel", max_vel, 0.3);
12  pnh.param("goal_tolerance", goal_tolerance, 0.002);
13  pnh.param("abort_threshold", abort_threshold, 0.08);
14  pnh.param("kp", kp, 3.0);
15  pnh.param("ki", ki, 0.0);
16  pnh.param<std::string>("eef_link", eef_link, "gripper_link");
17  abort_threshold = pow(abort_threshold, 2);
18 
19  hold_goal.trajectory.joint_names.push_back("shoulder_pan_joint");
20  hold_goal.trajectory.joint_names.push_back("shoulder_lift_joint");
21  hold_goal.trajectory.joint_names.push_back("upperarm_roll_joint");
22  hold_goal.trajectory.joint_names.push_back("elbow_flex_joint");
23  hold_goal.trajectory.joint_names.push_back("forearm_roll_joint");
24  hold_goal.trajectory.joint_names.push_back("wrist_flex_joint");
25  hold_goal.trajectory.joint_names.push_back("wrist_roll_joint");
26  hold_goal.trajectory.points.resize(1);
27 
28  arm_cartesian_cmd_publisher = n.advertise<geometry_msgs::TwistStamped>("/arm_controller/cartesian_twist/command", 1);
29 
31 }
32 
33 void LinearController::executeLinearMove(const fetch_simple_linear_controller::LinearMoveGoalConstPtr &goal)
34 {
35  fetch_simple_linear_controller::LinearMoveResult result;
36 
37  geometry_msgs::Point goal_point;
38  if (goal->point.header.frame_id != "base_link")
39  {
40  geometry_msgs::TransformStamped goal_to_base_transform = tf_buffer.lookupTransform("base_link",
41  goal->point.header.frame_id,
42  ros::Time(0),
43  ros::Duration(1.0));
44  tf2::doTransform(goal->point.point, goal_point, goal_to_base_transform);
45  }
46  else
47  {
48  goal_point = goal->point.point;
49  }
50 
51  // get initial pose to calculate expected duration
52  geometry_msgs::TransformStamped gripper_tf = tf_buffer.lookupTransform("base_link", eef_link, ros::Time(0),
53  ros::Duration(1.0));
54  double x_err = goal_point.x - gripper_tf.transform.translation.x;
55  double y_err = goal_point.y - gripper_tf.transform.translation.y;
56  double z_err = goal_point.z - gripper_tf.transform.translation.z;
57 
58  geometry_msgs::TwistStamped cmd;
59  cmd.header.frame_id = "base_link";
60 
61  ros::Rate controller_rate(100);
62  double move_duration = max(max(fabs(x_err), fabs(y_err)), fabs(z_err)) / max_vel;
63  move_duration *= 3.0; // give the controller extra time in case things don't go perfectly smoothly
64  ros::Time end_time = ros::Time::now() + ros::Duration(move_duration);
65 
66  double x_err_accum = 0;
67  double y_err_accum = 0;
68  double z_err_accum = 0;
69 
70  while (ros::Time::now() < end_time && (fabs(x_err) > goal_tolerance || fabs(y_err) > goal_tolerance
71  || fabs(z_err) > goal_tolerance))
72  {
73  gripper_tf = tf_buffer.lookupTransform("base_link", eef_link, ros::Time(0),
74  ros::Duration(0.05));
75  x_err = goal_point.x - gripper_tf.transform.translation.x;
76  y_err = goal_point.y - gripper_tf.transform.translation.y;
77  z_err = goal_point.z - gripper_tf.transform.translation.z;
78 
79  x_err_accum += x_err;
80  y_err_accum += y_err;
81  z_err_accum += z_err;
82 
83  double dx = kp*x_err + ki*x_err_accum;
84  double dy = kp*y_err + ki*y_err_accum;
85  double dz = kp*z_err + ki*z_err_accum;
86 
87  double max_cmd = max(max(fabs(dx), fabs(dy)), fabs(dz));
88  if (max_cmd > max_vel)
89  {
90  double scale = max_vel/max_cmd;
91  dx *= scale;
92  dy *= scale;
93  dz *= scale;
94  }
95 
96  cmd.twist.linear.x = dx;
97  cmd.twist.linear.y = dy;
98  cmd.twist.linear.z = dz;
99 
101 
102  controller_rate.sleep();
103  }
104 
105  cmd.twist.linear.x = 0;
106  cmd.twist.linear.y = 0;
107  cmd.twist.linear.z = 0;
109 
110  if (goal->hold_final_pose)
111  {
112  sensor_msgs::JointStateConstPtr js_msg;
113  sensor_msgs::JointState joint_state;
114  while (joint_state.position.size() <= 3)
115  {
116  js_msg = ros::topic::waitForMessage<sensor_msgs::JointState>("joint_states", n);
117  if (js_msg != NULL)
118  {
119  joint_state = *js_msg;
120  }
121  }
122 
123  // publish a non-trajectory to FollowJointTrajectory to disable gravity comp
124  hold_goal.trajectory.points[0].positions.clear();
125  for (size_t i = 6; i < 6 + hold_goal.trajectory.joint_names.size(); i ++)
126  {
127  hold_goal.trajectory.points[0].positions.push_back(joint_state.position[i]);
128  }
129 
132  }
133 
134  ros::Duration(0.3).sleep(); // let the arm settle
135  gripper_tf = tf_buffer.lookupTransform("base_link", eef_link, ros::Time(0),
136  ros::Duration(0.05));
137  x_err = goal_point.x - gripper_tf.transform.translation.x;
138  y_err = goal_point.y - gripper_tf.transform.translation.y;
139  z_err = goal_point.z - gripper_tf.transform.translation.z;
140 
141  result.error.x = x_err;
142  result.error.y = y_err;
143  result.error.z = z_err;
144 
145  ROS_INFO("Final linear translation error: (%f, %f, %f)", x_err, y_err, z_err);
146  if (pow(x_err, 2) + pow(y_err, 2) + pow(z_err, 2) > abort_threshold)
147  {
148  ROS_INFO("Did not pass execution threshold, aborting linear move action server.");
150  return;
151  }
152 
154 }
155 
156 
157 int main(int argc, char **argv)
158 {
159  ros::init(argc, argv, "linear_controller");
160 
161  LinearController lc;
162 
163  ros::spin();
164 
165  return EXIT_SUCCESS;
166 }
tf2_ros::Buffer tf_buffer
actionlib::SimpleActionServer< fetch_simple_linear_controller::LinearMoveAction > linear_move_server
ros::NodeHandle n
string cmd
bool waitForResult(const ros::Duration &timeout=ros::Duration(0, 0))
int main(int argc, char **argv)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
std::string eef_link
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
bool param(const std::string &param_name, T &param_val, const T &default_val) const
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
void publish(const boost::shared_ptr< M > &message) const
#define ROS_INFO(...)
void executeLinearMove(const fetch_simple_linear_controller::LinearMoveGoalConstPtr &goal)
ros::Publisher arm_cartesian_cmd_publisher
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ROSCPP_DECL void spin()
bool sleep()
control_msgs::FollowJointTrajectoryGoal hold_goal
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
void sendGoal(const Goal &goal, SimpleDoneCallback done_cb=SimpleDoneCallback(), SimpleActiveCallback active_cb=SimpleActiveCallback(), SimpleFeedbackCallback feedback_cb=SimpleFeedbackCallback())
tf2_ros::Buffer * tf_buffer
static Time now()
ros::NodeHandle pnh
bool sleep() const
double max(double a, double b)
actionlib::SimpleActionClient< control_msgs::FollowJointTrajectoryAction > arm_control_client


fetch_simple_linear_controller
Author(s): David Kent
autogenerated on Mon Feb 28 2022 22:21:03