base_footprint.cpp
Go to the documentation of this file.
1 
2 /*
3  * Publish the Nao humanoid's base_footprint frame according to REP-120
4  * Based on nao_common/remap_odometry.cpp
5  *
6  * Copyright 2013 Armin Hornung, Stefan Osswald, University of Freiburg
7  * http://www.ros.org/wiki/nao
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * * Neither the name of the University of Freiburg nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <ros/ros.h>
37 #include <tf/transform_datatypes.h>
38 #include <tf/transform_listener.h>
39 #include <tf/message_filter.h>
40 #include <sensor_msgs/JointState.h>
41 
43 {
44 public:
45  BaseFootprint();
47 
48 
49 private:
50  void jsCallback(const sensor_msgs::JointState::ConstPtr & msg);
51 
54 
55  // for base_footprint_frame: broadcasts frame between right and left foot, coinciding with the ground
60 
61  std::string m_odomFrameId;
62  std::string m_baseFrameId;
63  std::string m_lfootFrameId;
64  std::string m_rfootFrameId;
65  std::string m_baseFootPrintID;
66 
67 };
68 
70  : m_privateNh("~"), m_odomFrameId("odom"), m_baseFrameId("base_link"),
71  m_lfootFrameId("l_sole"), m_rfootFrameId("r_sole"),
72  m_baseFootPrintID("base_footprint")
73 {
74  // Read parameters
75  m_privateNh.param("odom_frame_id", m_odomFrameId, m_odomFrameId);
76  m_privateNh.param("base_frame_id", m_baseFrameId, m_baseFrameId);
77  m_privateNh.param("base_footprint_frame_id", m_baseFootPrintID, m_baseFootPrintID);
78 
79 
80  // Resolve TF frames using ~tf_prefix parameter
81 
87 
88  // subscribe to joint_states to provide a clock signal for synchronization
89  // since the frames are computed based on the joint state, all should be available
90  // with the same time stamps
93  std::vector<std::string> frames;
94  frames.push_back(m_rfootFrameId);
95  frames.push_back(m_odomFrameId);
96  m_jsFilter->setTargetFrames(frames);
97  m_jsFilter->registerCallback(boost::bind(&BaseFootprint::jsCallback, this, _1));
98 }
99 
101  delete m_jsFilter;
102  delete m_jsSub;
103 }
104 
105 void BaseFootprint::jsCallback(const sensor_msgs::JointState::ConstPtr & ptr)
106 {
107  ros::Time time = ptr->header.stamp;
108  tf::StampedTransform tf_odom_to_base, tf_odom_to_left_foot, tf_odom_to_right_foot;
109 
110  ROS_DEBUG("JointState callback function, computing frame %s", m_baseFootPrintID.c_str());
111  try {
112  m_listener.lookupTransform(m_odomFrameId, m_lfootFrameId, time, tf_odom_to_left_foot);
113  m_listener.lookupTransform(m_odomFrameId, m_rfootFrameId, time, tf_odom_to_right_foot);
114  m_listener.lookupTransform(m_odomFrameId, m_baseFrameId, time, tf_odom_to_base);
115  } catch (const tf::TransformException& ex){
116  ROS_ERROR("%s",ex.what());
117  return ;
118  }
119 
120  tf::Vector3 new_origin = (tf_odom_to_right_foot.getOrigin() + tf_odom_to_left_foot.getOrigin())/2.0; // middle of both feet
121  double height = std::min(tf_odom_to_left_foot.getOrigin().getZ(), tf_odom_to_right_foot.getOrigin().getZ()); // fix to lowest foot
122  new_origin.setZ(height);
123 
124  // adjust yaw according to torso orientation, all other angles 0 (= in z-plane)
125  double roll, pitch, yaw;
126  tf_odom_to_base.getBasis().getRPY(roll, pitch, yaw);
127 
128  tf::Transform tf_odom_to_footprint(tf::createQuaternionFromYaw(yaw), new_origin);
129  tf::Transform tf_base_to_footprint = tf_odom_to_base.inverse() * tf_odom_to_footprint;
130 
131  // publish transform with parent m_baseFrameId and new child m_baseFootPrintID
132  // i.e. transform from m_baseFrameId to m_baseFootPrintID
134  ROS_DEBUG("Published Transform %s --> %s", m_baseFrameId.c_str(), m_baseFootPrintID.c_str());
135 
136  return;
137 
138 }
139 
140 int main(int argc, char** argv){
141  ros::init(argc, argv, "base_footprint");
142  BaseFootprint baseFootprint;
143  ros::spin();
144 
145  return 0;
146 }
147 
148 
tf::MessageFilter< sensor_msgs::JointState > * m_jsFilter
std::string m_rfootFrameId
TFSIMD_FORCE_INLINE Matrix3x3 & getBasis()
tf::TransformListener m_listener
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
TFSIMD_FORCE_INLINE void setZ(tfScalar z)
ros::NodeHandle m_nh
tf::TransformBroadcaster m_brBaseFootPrint
std::string resolve(const std::string &frame_name)
TFSIMD_FORCE_INLINE const tfScalar & getZ() const
std::string m_odomFrameId
std::string m_baseFrameId
ROSCPP_DECL void spin(Spinner &spinner)
std::string m_lfootFrameId
void jsCallback(const sensor_msgs::JointState::ConstPtr &msg)
static Quaternion createQuaternionFromYaw(double yaw)
ros::NodeHandle m_privateNh
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
std::string m_baseFootPrintID
void sendTransform(const StampedTransform &transform)
Transform inverse() const
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
int main(int argc, char **argv)
#define ROS_ERROR(...)
message_filters::Subscriber< sensor_msgs::JointState > * m_jsSub
Connection registerCallback(const C &callback)
#define ROS_DEBUG(...)


nao_description
Author(s): Armin Hornung, Stefan Osswald
autogenerated on Mon Jun 10 2019 14:05:03