58 static const char*
const NODE_NAME =
"jog_arm_server";
62 int main(
int argc,
char** argv)
86 pthread_t joggingThread;
95 pthread_t collisionThread;
162 outgoing_cmd_pub.publish(new_traj);
166 std_msgs::Float64MultiArray joints;
168 joints.data = new_traj.points[0].positions;
170 joints.data = new_traj.points[0].velocities;
171 outgoing_cmd_pub.publish(joints);
177 "Try a larger 'incoming_command_timeout' parameter?");
184 (void)pthread_join(joggingThread,
nullptr);
185 (void)pthread_join(collisionThread,
nullptr);
205 const std::unique_ptr<robot_model_loader::RobotModelLoader>& model_loader_ptr)
212 while (
ros::ok() && !model_loader_ptr)
217 const robot_model::RobotModelPtr& kinematic_model = model_loader_ptr->getModel();
228 ros::topic::waitForMessage<sensor_msgs::JointState>(parameters.
joint_topic);
231 ROS_INFO_NAMED(
NODE_NAME,
"Waiting for first command msg.");
233 ROS_INFO_NAMED(
NODE_NAME,
"Received first command msg.");
238 velocity_scale_filter.
reset(1);
246 sensor_msgs::JointState jts = shared_variables.
joints;
248 for (std::size_t i = 0; i < jts.position.size(); ++i)
249 current_state.setJointPositions(jts.name[i], &jts.position[i]);
252 std::map<std::string, moveit_msgs::CollisionObject> c_objects_map = planning_scene_interface.
getObjects();
253 for (
auto& kv : c_objects_map)
258 collision_result.
clear();
259 planning_scene.
checkCollision(collision_request, collision_result);
266 double velocity_scale = 1;
281 velocity_scale = velocity_scale_filter.
filter(velocity_scale);
283 if (velocity_scale > 1)
285 else if (velocity_scale < 0.05)
286 velocity_scale = 0.05;
290 velocity_scale = 0.02;
296 collision_rate.
sleep();
303 const std::unique_ptr<robot_model_loader::RobotModelLoader>& model_loader_ptr)
304 : move_group_(parameters.move_group_name)
313 while (
ros::ok() && !model_loader_ptr)
318 const robot_model::RobotModelPtr& kinematic_model = model_loader_ptr->getModel();
319 kinematic_state_ = std::make_shared<robot_state::RobotState>(kinematic_model);
324 std::vector<double> dummy_joint_values;
332 ROS_INFO_NAMED(
NODE_NAME,
"Waiting for first command msg.");
334 ROS_INFO_NAMED(
NODE_NAME,
"Received first command msg.");
344 for (
size_t i = 0; i <
jt_state_.name.size(); ++i)
356 for (std::size_t i = 0; i <
jt_state_.name.size(); ++i)
362 geometry_msgs::TwistStamped cartesian_deltas;
363 jog_msgs::JogJoint joint_deltas;
375 int zero_velocity_count = 0;
376 int num_zero_cycles_to_publish = 4;
386 if (zero_cartesian_traj_flag && zero_joint_traj_flag)
402 if ((zero_velocity_count <= num_zero_cycles_to_publish) && zero_joint_traj_flag)
411 else if ((zero_velocity_count <= num_zero_cycles_to_publish) && !zero_joint_traj_flag)
422 if (shared_variables.
command_is_stale || (zero_cartesian_traj_flag && zero_joint_traj_flag))
425 zero_cartesian_traj_flag =
true;
426 zero_joint_traj_flag =
true;
431 bool valid_nonzero_trajectory =
432 !((zero_velocity_count > num_zero_cycles_to_publish) && zero_cartesian_traj_flag && zero_joint_traj_flag);
438 if (valid_nonzero_trajectory)
449 else if (zero_velocity_count > num_zero_cycles_to_publish)
458 if (zero_cartesian_traj_flag && zero_joint_traj_flag)
459 zero_velocity_count += 1;
461 zero_velocity_count = 0;
473 if (std::isnan(cmd.twist.linear.x) || std::isnan(cmd.twist.linear.y) || std::isnan(cmd.twist.linear.z) ||
474 std::isnan(cmd.twist.angular.x) || std::isnan(cmd.twist.angular.y) || std::isnan(cmd.twist.angular.z))
483 if ((fabs(cmd.twist.linear.x) > 1) || (fabs(cmd.twist.linear.y) > 1) || (fabs(cmd.twist.linear.z) > 1) ||
484 (fabs(cmd.twist.angular.x) > 1) || (fabs(cmd.twist.angular.y) > 1) || (fabs(cmd.twist.angular.z) > 1))
504 geometry_msgs::Vector3Stamped lin_vector;
505 lin_vector.vector = cmd.twist.linear;
506 lin_vector.header.frame_id = cmd.header.frame_id;
517 geometry_msgs::Vector3Stamped rot_vector;
518 rot_vector.vector = cmd.twist.angular;
519 rot_vector.header.frame_id = cmd.header.frame_id;
531 geometry_msgs::TwistStamped twist_cmd;
532 twist_cmd.header.stamp = cmd.header.stamp;
534 twist_cmd.twist.linear = lin_vector.vector;
535 twist_cmd.twist.angular = rot_vector.vector;
544 Eigen::JacobiSVD<Eigen::MatrixXd> svd(jacobian, Eigen::ComputeThinU | Eigen::ComputeThinV);
545 Eigen::VectorXd delta_theta =
pseudoInverse(svd.matrixU(), svd.matrixV(), svd.singularValues().asDiagonal()) * delta_x;
583 for (std::size_t i = 0; i < cmd.deltas.size(); ++i)
585 if (std::isnan(cmd.deltas[i]) || (fabs(cmd.deltas[i]) > 1))
641 auto point = trajectory.points[0];
644 for (
int i = 2; i < count + 1; ++i)
647 trajectory.points.push_back(point);
653 for (
size_t i = 0; i <
jt_state_.name.size(); ++i)
668 for (
size_t i = 0; i <
jt_state_.name.size(); ++i)
673 if (std::isnan(
jt_state_.velocity[static_cast<long>(i)]))
685 trajectory_msgs::JointTrajectory new_jt_traj;
687 new_jt_traj.header.stamp = stamp;
688 new_jt_traj.joint_names = joint_state.name;
690 trajectory_msgs::JointTrajectoryPoint point;
693 point.positions = joint_state.position;
695 point.velocities = joint_state.velocity;
701 std::vector<double> acceleration(joint_state.velocity.size());
702 point.accelerations = acceleration;
704 new_jt_traj.points.push_back(point);
714 const Eigen::VectorXd& delta_theta,
double singularity_scale)
718 for (
size_t i = 0; i <
jt_state_.velocity.size(); ++i)
724 new_jt_traj.points[0].positions[i] =
725 new_jt_traj.points[0].positions[i] -
726 (1. - singularity_scale * collision_scale) * delta_theta[static_cast<long>(i)];
729 new_jt_traj.points[0].velocities[i] *= singularity_scale * collision_scale;
738 double maximum_joint_vel = calculated_joint_vel.cwiseAbs().maxCoeff();
750 double velocity_scale = 1;
755 Eigen::JacobiSVD<Eigen::MatrixXd> svd(jacobian, Eigen::ComputeThinU | Eigen::ComputeThinV);
756 Eigen::VectorXd vector_toward_singularity = svd.matrixU().col(5);
758 double ini_condition = svd.singularValues()(0) / svd.singularValues()(svd.singularValues().size() - 1);
766 Eigen::VectorXd delta_x(6);
768 delta_x[0] = vector_toward_singularity[0] / scale;
769 delta_x[1] = vector_toward_singularity[1] / scale;
770 delta_x[2] = vector_toward_singularity[2] / scale;
771 delta_x[3] = vector_toward_singularity[3] / scale;
772 delta_x[4] = vector_toward_singularity[4] / scale;
773 delta_x[5] = vector_toward_singularity[5] / scale;
776 Eigen::VectorXd delta_theta =
pseudoInverse(jacobian) * delta_x;
780 for (std::size_t i = 0, size = static_cast<std::size_t>(delta_theta.size()); i < size; ++i)
781 theta[i] = prev_joints[i] + delta_theta(i);
785 svd = Eigen::JacobiSVD<Eigen::MatrixXd>(jacobian);
786 double new_condition = svd.singularValues()(0) / svd.singularValues()(svd.singularValues().size() - 1);
790 if (ini_condition >= new_condition)
792 vector_toward_singularity[0] *= -1;
793 vector_toward_singularity[1] *= -1;
794 vector_toward_singularity[2] *= -1;
795 vector_toward_singularity[3] *= -1;
796 vector_toward_singularity[4] *= -1;
797 vector_toward_singularity[5] *= -1;
802 double dot = vector_toward_singularity.dot(commanded_velocity);
811 velocity_scale = 1. -
824 return velocity_scale;
829 bool halting =
false;
836 " velocity limit. Enforcing limit.");
838 for (std::size_t c = 0; c < new_jt_traj.joint_names.size(); ++c)
840 if (new_jt_traj.joint_names[c] == joint->getName())
842 new_jt_traj.points[0].velocities[c] =
kinematic_state_->getJointVelocities(joint)[0];
850 double joint_angle = 0;
851 for (std::size_t c = 0; c < new_jt_traj.joint_names.size(); ++c)
863 const std::vector<moveit_msgs::JointLimits> limits = joint->getVariableBoundsMsg();
866 if (limits.size() > 0)
869 (joint_angle < (limits[0].min_position + jog_arm::JogROSInterface::ros_parameters_.
joint_limit_margin))) ||
871 (joint_angle > (limits[0].max_position - jog_arm::JogROSInterface::ros_parameters_.
joint_limit_margin))))
875 " position limit. Halting.");
887 std_msgs::Bool status;
888 status.data =
static_cast<std_msgs::Bool::_data_type
>(active);
896 for (std::size_t i = 0; i <
jt_state_.velocity.size(); ++i)
905 jt_traj.points[0].velocities[i] = 0;
913 for (std::size_t i = 0; i <
jt_state_.name.size(); ++i)
921 bool all_zeros =
true;
930 for (std::size_t c = 0; c <
jt_state_.name.size(); ++c)
950 Eigen::VectorXd result(6);
980 Eigen::VectorXd result(
jt_state_.name.size());
982 for (std::size_t i = 0; i <
jt_state_.name.size(); ++i)
988 for (std::size_t m = 0; m < command.joint_names.size(); ++m)
990 for (std::size_t c = 0; c <
jt_state_.name.size(); ++c)
992 if (command.joint_names[m] ==
jt_state_.name[c])
1014 return J.transpose() * (J * J.transpose()).inverse();
1017 Eigen::MatrixXd
JogCalcs::pseudoInverse(
const Eigen::MatrixXd& u_matrix,
const Eigen::MatrixXd& v_matrix,
const Eigen::MatrixXd& s_diagonals)
const 1019 return v_matrix * s_diagonals.inverse() * u_matrix.transpose();
1025 for (std::size_t i = 0, size = static_cast<std::size_t>(increments.size()); i < size; ++i)
1029 output.position[i] += increments[
static_cast<long>(i)];
1031 catch (
const std::out_of_range& e)
1034 "increments do not match.");
1046 pthread_mutex_lock(&shared_variables_.command_deltas_mutex);
1050 shared_variables_.command_deltas.twist = msg->twist;
1051 shared_variables_.command_deltas.header.stamp = msg->header.stamp;
1054 pthread_mutex_lock(&shared_variables_.zero_cartesian_cmd_flag_mutex);
1055 shared_variables_.zero_cartesian_cmd_flag = shared_variables_.command_deltas.twist.linear.x == 0.0 &&
1056 shared_variables_.command_deltas.twist.linear.y == 0.0 &&
1057 shared_variables_.command_deltas.twist.linear.z == 0.0 &&
1058 shared_variables_.command_deltas.twist.angular.x == 0.0 &&
1059 shared_variables_.command_deltas.twist.angular.y == 0.0 &&
1060 shared_variables_.command_deltas.twist.angular.z == 0.0;
1061 pthread_mutex_unlock(&shared_variables_.zero_cartesian_cmd_flag_mutex);
1063 pthread_mutex_unlock(&shared_variables_.command_deltas_mutex);
1065 pthread_mutex_lock(&shared_variables_.incoming_cmd_stamp_mutex);
1066 shared_variables_.incoming_cmd_stamp = msg->header.stamp;
1067 pthread_mutex_unlock(&shared_variables_.incoming_cmd_stamp_mutex);
1074 pthread_mutex_lock(&shared_variables_.joint_command_deltas_mutex);
1075 shared_variables_.joint_command_deltas = *msg;
1079 bool all_zeros =
true;
1080 for (
double delta : shared_variables_.joint_command_deltas.deltas)
1082 all_zeros &= (delta == 0.0);
1084 pthread_mutex_unlock(&shared_variables_.joint_command_deltas_mutex);
1086 pthread_mutex_lock(&shared_variables_.zero_joint_cmd_flag_mutex);
1087 shared_variables_.zero_joint_cmd_flag = all_zeros;
1088 pthread_mutex_unlock(&shared_variables_.zero_joint_cmd_flag_mutex);
1090 pthread_mutex_lock(&shared_variables_.incoming_cmd_stamp_mutex);
1091 shared_variables_.incoming_cmd_stamp = msg->header.stamp;
1092 pthread_mutex_unlock(&shared_variables_.incoming_cmd_stamp_mutex);
1099 pthread_mutex_lock(&shared_variables_.joints_mutex);
1100 shared_variables_.joints = *msg;
1101 pthread_mutex_unlock(&shared_variables_.joints_mutex);
1107 std::size_t error = 0;
1111 std::string parameter_ns;
1113 if (parameter_ns ==
"")
1118 "value=\"left_jog_arm_server\" />");
1124 error += !
rosparam_shortcuts::get(
"", n, parameter_ns +
"/collision_check_rate", ros_parameters_.collision_check_rate);
1126 error += !
rosparam_shortcuts::get(
"", n, parameter_ns +
"/scale/rotational", ros_parameters_.rotational_scale);
1129 !
rosparam_shortcuts::get(
"", n, parameter_ns +
"/low_pass_filter_coeff", ros_parameters_.low_pass_filter_coeff);
1133 ros_parameters_.cartesian_command_in_topic);
1135 !
rosparam_shortcuts::get(
"", n, parameter_ns +
"/joint_command_in_topic", ros_parameters_.joint_command_in_topic);
1138 ros_parameters_.incoming_command_timeout);
1140 ros_parameters_.lower_singularity_threshold);
1142 ros_parameters_.hard_stop_singularity_threshold);
1144 ros_parameters_.lower_collision_proximity_threshold);
1146 ros_parameters_.hard_stop_collision_proximity_threshold);
1152 error += !
rosparam_shortcuts::get(
"", n, parameter_ns +
"/joint_limit_margin", ros_parameters_.joint_limit_margin);
1153 error += !
rosparam_shortcuts::get(
"", n, parameter_ns +
"/command_out_topic", ros_parameters_.command_out_topic);
1154 error += !
rosparam_shortcuts::get(
"", n, parameter_ns +
"/command_out_type", ros_parameters_.command_out_type);
1156 ros_parameters_.publish_joint_positions);
1158 ros_parameters_.publish_joint_velocities);
1160 ros_parameters_.publish_joint_accelerations);
1165 pthread_mutex_lock(&shared_variables_.command_deltas_mutex);
1166 shared_variables_.command_deltas.header.frame_id = ros_parameters_.command_frame;
1167 pthread_mutex_unlock(&shared_variables_.command_deltas_mutex);
1170 if (ros_parameters_.hard_stop_singularity_threshold < ros_parameters_.lower_singularity_threshold)
1173 "should be greater than 'lower_singularity_threshold.' " 1174 "Check yaml file.");
1177 if ((ros_parameters_.hard_stop_singularity_threshold < 0.) || (ros_parameters_.lower_singularity_threshold < 0.))
1180 "and 'lower_singularity_threshold' should be " 1181 "greater than zero. Check yaml file.");
1184 if (ros_parameters_.hard_stop_collision_proximity_threshold >= ros_parameters_.lower_collision_proximity_threshold)
1187 "should be less than 'lower_collision_proximity_threshold.' " 1188 "Check yaml file.");
1191 if ((ros_parameters_.hard_stop_collision_proximity_threshold < 0.) ||
1192 (ros_parameters_.lower_collision_proximity_threshold < 0.))
1195 "and 'lower_collision_proximity_threshold' should be " 1196 "greater than zero. Check yaml file.");
1199 if (ros_parameters_.low_pass_filter_coeff < 0.)
1202 "greater than zero. Check yaml file.");
1205 if (ros_parameters_.joint_limit_margin < 0.)
1208 "greater than zero. Check yaml file.");
1211 if (ros_parameters_.command_in_type !=
"unitless" && ros_parameters_.command_in_type !=
"speed_units")
1214 "'speed_units'. Check yaml file.");
1217 if (ros_parameters_.command_out_type !=
"trajectory_msgs/JointTrajectory" &&
1218 ros_parameters_.command_out_type !=
"std_msgs/Float64MultiArray")
1221 "'trajectory_msgs/JointTrajectory' or " 1222 "'std_msgs/Float64MultiArray'. Check yaml file.");
1225 if (!ros_parameters_.publish_joint_positions && !ros_parameters_.publish_joint_velocities &&
1226 !ros_parameters_.publish_joint_accelerations)
1229 "publish_joint_velocities / " 1230 "publish_joint_accelerations must be true. Check " 1234 if ((ros_parameters_.command_out_type ==
"std_msgs/Float64MultiArray") && ros_parameters_.publish_joint_positions &&
1235 ros_parameters_.publish_joint_velocities)
1238 "you must select positions OR velocities.");
1241 if (ros_parameters_.collision_check_rate < 0)
1244 "greater than zero. Check yaml file.");
bool publish_joint_accelerations
double lower_singularity_threshold
std::string joint_command_in_topic
double collision_velocity_scale
tf::TransformListener listener_
bool checkIfJointsWithinBounds(trajectory_msgs::JointTrajectory_< std::allocator< void >> &new_jt_traj)
robot_state::RobotState & getCurrentStateNonConst()
double filter(double new_msrmt)
std::string warning_topic
#define ROS_INFO_NAMED(name,...)
#define ROS_WARN_THROTTLE_NAMED(rate, name,...)
pthread_mutex_t collision_velocity_scale_mutex
void lowPassFilterVelocities(const Eigen::VectorXd &joint_vel)
sensor_msgs::JointState incoming_jts_
void publish(const boost::shared_ptr< M > &message) const
bool cartesianJogCalcs(const geometry_msgs::TwistStamped &cmd, jog_arm_shared &shared_variables)
bool zero_cartesian_cmd_flag
#define ROS_ERROR_STREAM_NAMED(name, args)
void enforceJointVelocityLimits(Eigen::VectorXd &calculated_joint_vel)
std::vector< jog_arm::LowPassFilter > position_filters_
#define ROS_WARN_NAMED(name,...)
pthread_mutex_t incoming_cmd_stamp_mutex
bool publish_joint_positions
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
double collision_check_rate
bool publish_joint_velocities
ros::Time incoming_cmd_stamp
trajectory_msgs::JointTrajectory new_traj_
std::string move_group_name
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
double hard_stop_collision_proximity_threshold
void deltaCartesianCmdCB(const geometry_msgs::TwistStampedConstPtr &msg)
sensor_msgs::JointState jt_state_
trajectory_msgs::JointTrajectory composeOutgoingMessage(sensor_msgs::JointState &joint_state, const ros::Time &stamp) const
ROSCPP_DECL const std::string & getName()
JogCalcs(const jog_arm_parameters ¶meters, jog_arm_shared &shared_variables, const std::unique_ptr< robot_model_loader::RobotModelLoader > &model_loader_ptr)
void halt(trajectory_msgs::JointTrajectory &jt_traj)
std::string command_in_type
std::map< std::string, moveit_msgs::CollisionObject > getObjects(const std::vector< std::string > &object_ids=std::vector< std::string >())
void resetVelocityFilters()
double joint_limit_margin
double hard_stop_singularity_threshold
pthread_mutex_t new_traj_mutex
std::string cartesian_command_in_topic
std::string planning_frame
bool processCollisionObjectMsg(const moveit_msgs::CollisionObject &object)
Eigen::VectorXd scaleCartesianCommand(const geometry_msgs::TwistStamped &command) const
bool readParameters(ros::NodeHandle &n)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW void clear()
geometry_msgs::TwistStamped command_deltas
jog_msgs::JogJoint joint_command_deltas
ros::Publisher warning_pub_
jog_arm_parameters parameters_
std::string command_out_topic
sensor_msgs::JointState joints
double low_pass_filter_coeff
Eigen::MatrixXd pseudoInverse(const Eigen::MatrixXd &J) const
void insertRedundantPointsIntoTrajectory(trajectory_msgs::JointTrajectory &trajectory, int count) const
ROSCPP_DECL bool get(const std::string &key, std::string &s)
#define ROS_FATAL_STREAM_NAMED(name, args)
void jointsCB(const sensor_msgs::JointStateConstPtr &msg)
#define ROS_WARN_STREAM_THROTTLE_NAMED(rate, name, args)
void publishWarning(bool active) const
bool addJointIncrements(sensor_msgs::JointState &output, const Eigen::VectorXd &increments) const
static struct jog_arm_shared shared_variables_
void checkCollision(const collision_detection::CollisionRequest &req, collision_detection::CollisionResult &res)
static std::unique_ptr< robot_model_loader::RobotModelLoader > model_loader_ptr_
moveit::planning_interface::MoveGroupInterface move_group_
static const char *const NODE_NAME
double lower_collision_proximity_threshold
CollisionCheckThread(const jog_arm_parameters ¶meters, jog_arm_shared &shared_variables, const std::unique_ptr< robot_model_loader::RobotModelLoader > &model_loader_ptr)
pthread_mutex_t command_is_stale_mutex
double decelerateForSingularity(Eigen::MatrixXd jacobian, const Eigen::VectorXd commanded_velocity)
void lowPassFilterPositions()
bool applyVelocityScaling(jog_arm_shared &shared_variables, trajectory_msgs::JointTrajectory &new_jt_traj, const Eigen::VectorXd &delta_theta, double singularity_scale)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::vector< jog_arm::LowPassFilter > velocity_filters_
Eigen::VectorXd scaleJointCommand(const jog_msgs::JogJoint &command) const
int main(int argc, char **argv)
static void * CollisionCheckThread(void *thread_id)
static const int GAZEBO_REDUNTANT_MESSAGE_COUNT
void shutdownIfError(const std::string &parent_name, std::size_t error_count)
trajectory_msgs::JointTrajectory new_traj
const robot_state::JointModelGroup * joint_model_group_
double incoming_command_timeout
const std::vector< std::string > & getJointNames()
bool jointJogCalcs(const jog_msgs::JogJoint &cmd, jog_arm_shared &shared_variables)
std::string command_out_type
sensor_msgs::JointState original_jts_
pthread_mutex_t ok_to_publish_mutex
robot_state::RobotStatePtr kinematic_state_
static struct jog_arm_parameters ros_parameters_
ROSCPP_DECL void spinOnce()
bool get(const std::string &parent_name, const ros::NodeHandle &nh, const std::string ¶m_name, bool &value)
void deltaJointCmdCB(const jog_msgs::JogJointConstPtr &msg)
static void * jogCalcThread(void *thread_id)
#define ROS_WARN_STREAM_NAMED(name, args)