40 #include <Eigen/Dense> 44 #include <yaml-cpp/yaml.h> 54 if ( filter_type_str ==
"ekf" )
58 else if ( filter_type_str ==
"ukf" )
69 nh_p_(
"robot_localization"),
70 odom_sub_(nh_,
"odometry/filtered", 1),
71 accel_sub_(nh_,
"accel/filtered", 1),
72 sync_(odom_sub_, accel_sub_, 10),
73 tf_listener_(tf_buffer_),
85 std::string filter_type_str;
86 nh_param.
param(
"filter_type", filter_type_str, std::string(
"ekf"));
90 ROS_ERROR(
"RosRobotLocalizationListener: Parameter filter_type invalid");
98 process_noise_covariance.setZero();
101 if (!nh_param.
hasParam(
"process_noise_covariance"))
103 ROS_FATAL_STREAM(
"Process noise covariance not found in the robot localization listener config (namespace " <<
104 nh_param.
getNamespace() <<
")! Use the ~parameter_namespace to specify the parameter namespace.");
110 nh_param.
getParam(
"process_noise_covariance", process_noise_covar_config);
114 int mat_size = process_noise_covariance.rows();
116 for (
int i = 0; i < mat_size; i++)
118 for (
int j = 0; j < mat_size; j++)
125 std::ostringstream ostr;
126 process_noise_covar_config[mat_size * i + j].
write(ostr);
127 std::istringstream istr(ostr.str());
128 istr >> process_noise_covariance(i, j);
141 ROS_DEBUG_STREAM(
"Process noise covariance is:\n" << process_noise_covariance <<
"\n");
147 " for process_noise_covariance (type: " <<
148 process_noise_covar_config.
getType() <<
")");
152 std::vector<double> filter_args;
153 nh_param.
param(
"filter_args", filter_args, std::vector<double>());
159 ROS_INFO_STREAM(
"Ros Robot Localization Listener: Listening to topics " <<
178 const geometry_msgs::AccelWithCovarianceStamped& accel)
201 tf2::fromMsg(odom.pose.pose.orientation, orientation_quat);
202 double roll, pitch, yaw;
210 for (
unsigned int i = 0; i <
POSE_SIZE; i++ )
212 for (
unsigned int j = 0; j <
POSE_SIZE; j++ )
229 for (
unsigned int i = 0; i <
TWIST_SIZE; i++ )
231 for (
unsigned int j = 0; j <
TWIST_SIZE; j++ )
261 if ( source_frame == target_frame )
266 std::string parent_frame = tree[source_frame][
"parent"].Scalar();
268 if ( parent_frame.empty() )
282 const std::vector<std::string>& ancestors = ancestor_map[source_frame];
283 if (std::find(ancestors.begin(), ancestors.end(), target_frame) != ancestors.end())
287 const std::vector<std::string>& descendants = descendant_map[source_frame];
288 if (std::find(descendants.begin(), descendants.end(), target_frame) != descendants.end())
294 YAML::Node frames_yaml = YAML::Load(frames_stream);
300 if (target_frame_is_ancestor)
302 ancestor_map[source_frame].push_back(target_frame);
304 if (target_frame_is_descendant)
306 descendant_map[source_frame].push_back(target_frame);
309 return target_frame_is_ancestor;
314 const std::string& frame_id,
315 Eigen::VectorXd& state,
316 Eigen::MatrixXd& covariance,
317 std::string world_frame_id)
const 323 covariance.setZero();
329 ROS_WARN(
"Ros Robot Localization Listener: The base or world frame id is not set. " 330 "No odom/accel messages have come in.");
334 ROS_ERROR(
"Ros Robot Localization Listener: The base or world frame id is not set. " 335 "Are the child_frame_id and the header.frame_id in the odom messages set?");
343 ROS_WARN(
"Ros Robot Localization Listener: A state is requested at a time stamp older than the oldest in the " 344 "estimator buffer. The result is an extrapolation into the past. Maybe you should increase the buffer " 349 if (world_frame_id.empty())
358 state = estimator_state.
state;
366 Eigen::Affine3d world_pose_requested_frame;
371 world_pose_requested_frame.setIdentity();
375 geometry_msgs::TransformStamped world_requested_to_world_transform;
385 ROS_ERROR_STREAM(
"You are trying to get the state with respect to world frame " << world_frame_id <<
386 ", but this frame is a child of robot base frame " <<
base_frame_id_ <<
387 ", so this doesn't make sense.");
393 ROS_WARN_STREAM(
"Ros Robot Localization Listener: Could not look up transform: " << e.what());
406 geometry_msgs::TransformStamped base_to_target_transform;
418 ROS_ERROR_STREAM(
"You are trying to get the state of " << frame_id <<
", but this frame is not a child of the " 425 ROS_WARN_STREAM(
"Ros Robot Localization Listener: Could not look up transform: " << e.what());
430 Eigen::Affine3d target_pose_base;
440 Eigen::AngleAxisd yaw_angle(estimator_state.
state(
StateMemberYaw), Eigen::Vector3d::UnitZ());
442 Eigen::Quaterniond base_orientation(yaw_angle * pitch_angle * roll_angle);
444 Eigen::Affine3d base_pose(Eigen::Translation3d(base_position) * base_orientation);
447 Eigen::Affine3d target_pose_odom = world_pose_requested_frame * base_pose * target_pose_base;
450 state(
StateMemberX) = target_pose_odom.translation().x();
451 state(
StateMemberY) = target_pose_odom.translation().y();
452 state(
StateMemberZ) = target_pose_odom.translation().z();
454 Eigen::Vector3d ypr = target_pose_odom.rotation().eulerAngles(2, 1, 0);
463 Twist target_velocity_base;
477 target_velocity_base.
linear = base_velocity.
linear + base_velocity.
angular.cross(target_pose_base.translation());
481 Twist target_velocity;
482 target_velocity.
linear = target_pose_base.rotation().transpose() * target_velocity_base.
linear;
483 target_velocity.
angular = target_pose_base.rotation().transpose() * target_velocity_base.
angular;
495 rot_6d.setIdentity();
499 target_pose_base.rotation();
503 rot_6d * estimator_state.
covariance.eval() * rot_6d.transpose();
509 Eigen::VectorXd& state, Eigen::MatrixXd& covariance,
510 const std::string& world_frame_id)
const 515 ROS_INFO(
"Ros Robot Localization Listener: State requested at time = zero, returning state at current time");
520 time = ros_time.
toSec();
523 return getState(time, frame_id, state, covariance, world_frame_id);
std::string getTopic() const
const std::string & getMessage() const
bool findAncestor(const tf2_ros::Buffer &buffer, const std::string &source_frame, const std::string &target_frame)
const int STATE_SIZE
Global constants that define our state vector size and offsets to groups of values within that state...
const int POSITION_A_OFFSET
bool findAncestorRecursiveYAML(YAML::Node &tree, const std::string &source_frame, const std::string &target_frame)
std::string world_frame_id_
Frame id received from the odometry message.
bool getState(const double time, const std::string &frame_id, Eigen::VectorXd &state, Eigen::MatrixXd &covariance, std::string world_frame_id="") const
Get a state from the localization estimator.
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
ros::NodeHandle nh_p_
A private handle to the ROS node.
message_filters::Subscriber< geometry_msgs::AccelWithCovarianceStamped > accel_sub_
Subscriber to the acceleration state topic (output of a filter node)
Type const & getType() const
Robot Localization Listener class.
const int POSITION_V_OFFSET
~RosRobotLocalizationListener()
Destructor.
const std::string & getBaseFrameId() const
getBaseFrameId Returns the base frame id of the localization listener
void odomAndAccelCallback(const nav_msgs::Odometry &odom, const geometry_msgs::AccelWithCovarianceStamped &accel)
Callback for odom and accel.
FilterType filterTypeFromString(const std::string &filter_type_str)
const int ORIENTATION_SIZE
static std::map< std::string, std::vector< std::string > > ancestor_map
static std::map< std::string, std::vector< std::string > > descendant_map
message_filters::TimeSynchronizer< nav_msgs::Odometry, geometry_msgs::AccelWithCovarianceStamped > sync_
Waits for both an Odometry and an Accel message before calling a single callback function.
Connection registerCallback(C &callback)
double time_stamp
Time at which this state is/was achieved.
#define ROS_FATAL_STREAM(args)
void setState(const EstimatorState &state)
Sets the current internal state of the listener.
const int POSITION_OFFSET
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
EstimatorResult getState(const double time, EstimatorState &state) const
Returns the state at a given time.
void fromMsg(const A &, B &b)
const std::string & getNamespace() const
const int ACCELERATION_SIZE
#define ROS_WARN_STREAM(args)
Eigen::VectorXd state
System state at time = time_stamp.
RobotLocalizationEstimator * estimator_
The core state estimator that facilitates inter- and extrapolation between buffered states...
#define ROS_DEBUG_STREAM(args)
std::string allFramesAsYAML(double current_time) const
const std::string & getWorldFrameId() const
getWorldFrameId Returns the world frame id of the localization listener
std::ostream & write(std::ostream &os) const
Eigen::MatrixXd covariance
System state covariance at time = time_stamp.
void transformMsgToEigen(const geometry_msgs::Transform &m, Eigen::Affine3d &e)
#define ROS_INFO_STREAM(args)
const int POSE_SIZE
Pose and twist messages each contain six variables.
const int ORIENTATION_OFFSET
bool getParam(const std::string &key, std::string &s) const
unsigned int getSize() const
Returns the current buffer size.
Robot Localization Estimator State.
tf2_ros::Buffer tf_buffer_
Tf buffer for looking up transforms.
bool hasParam(const std::string &key) const
RosRobotLocalizationListener()
Constructor.
#define ROS_ERROR_STREAM(args)
#define ROS_INFO_STREAM_THROTTLE(rate, args)
std::string base_frame_id_
Child frame id received from the Odometry message.
ROSCPP_DECL void spinOnce()
void quatToRPY(const tf2::Quaternion &quat, double &roll, double &pitch, double &yaw)
Utility method for converting quaternion to RPY.
message_filters::Subscriber< nav_msgs::Odometry > odom_sub_
Subscriber to the odometry state topic (output of a filter node)