cnoid_ros_utils
PosePublisherItem.cpp
Go to the documentation of this file.
1 /* Author: Masaki Murooka */
2 
3 #include <cnoid/BodyItem>
4 #include <cnoid/DyBody>
5 #include <cnoid/ItemManager>
6 #include <cnoid/MessageView>
7 #include <cnoid/PutPropertyFunction>
8 #include <cnoid/RootItem>
9 
10 #include <geometry_msgs/msg/pose_stamped.hpp>
11 #include <geometry_msgs/msg/transform_stamped.hpp>
12 #include <geometry_msgs/msg/twist_stamped.hpp>
13 
14 #include "PosePublisherItem.h"
15 
16 using namespace CnoidRosUtils;
17 
18 void PosePublisherItem::initialize(cnoid::ExtensionManager * ext)
19 {
20  int argc = 0;
21  char ** argv;
22  if(!rclcpp::ok())
23  {
24  rclcpp::init(argc, argv);
25  }
26 
27  if(!initialized_)
28  {
29  ext->itemManager().registerClass<PosePublisherItem>("CnoidRosUtils::PosePublisherItem");
30  ext->itemManager().addCreationPanel<PosePublisherItem>();
31  initialized_ = true;
32  }
33 }
34 
36 {
37  cnoid::RootItem::instance()->sigSubTreeChanged().connect(std::bind(&PosePublisherItem::setup, this));
38 }
39 
41 {
42  cnoid::RootItem::instance()->sigSubTreeChanged().connect(std::bind(&PosePublisherItem::setup, this));
43  hooked_sims_.clear();
45  sim_cnt_ = 0;
46 }
47 
49 {
50  stop();
51 }
52 
53 cnoid::Item * PosePublisherItem::doDuplicate() const
54 {
55  return new PosePublisherItem(*this);
56 }
57 
58 void PosePublisherItem::doPutProperties(cnoid::PutPropertyFunction & putProperty)
59 {
60  cnoid::Item::doPutProperties(putProperty);
61  putProperty("Link name", link_name_, cnoid::changeProperty(link_name_));
62  putProperty("Frame id", frame_id_, cnoid::changeProperty(frame_id_));
63  putProperty("Pose topic name (only for topic output)", pose_topic_name_, cnoid::changeProperty(pose_topic_name_));
64  putProperty("Velocity topic name (only for topic output)", vel_topic_name_, cnoid::changeProperty(vel_topic_name_));
65  putProperty("TF frame id (only for TF output)", tf_child_frame_id_, cnoid::changeProperty(tf_child_frame_id_));
66  putProperty("Publish rate", pub_rate_,
67  [&](const double & pub_rate)
68  {
69  pub_rate_ = std::min(std::max(pub_rate, 1e-1), 1e3);
70  if(sim_)
71  {
73  }
74  return true;
75  });
76  putProperty("Output TF", output_tf_, cnoid::changeProperty(output_tf_));
77 }
78 
79 bool PosePublisherItem::store(cnoid::Archive & archive)
80 {
81  archive.write("Link name", link_name_);
82  archive.write("Frame id", frame_id_);
83  archive.write("Pose topic name (only for topic output)", pose_topic_name_);
84  archive.write("Velocity topic name (only for topic output)", vel_topic_name_);
85  archive.write("TF frame id (only for TF output)", tf_child_frame_id_);
86  archive.write("Publish rate", pub_rate_);
87  archive.write("Output TF", output_tf_);
88 
89  return true;
90 }
91 
92 bool PosePublisherItem::restore(const cnoid::Archive & archive)
93 {
94  archive.read("Link name", link_name_);
95  archive.read("Frame id", frame_id_);
96  archive.read("Pose topic name (only for topic output)", pose_topic_name_);
97  archive.read("Velocity topic name (only for topic output)", vel_topic_name_);
98  archive.read("TF frame id (only for TF output)", tf_child_frame_id_);
99  archive.read("Publish rate", pub_rate_);
100  archive.read("Output TF", output_tf_);
101 
102  return true;
103 }
104 
106 {
107  // Get WorldItem
108  world_ = this->findOwnerItem<cnoid::WorldItem>();
109  if(!world_)
110  {
111  // cnoid::MessageView::instance()->putln("[PosePublisherItem] WorldItem not found", cnoid::MessageView::ERROR);
112  return;
113  }
114 
115  // Set hook functions for simulation start and stop
116  for(cnoid::Item * child = world_->childItem(); child; child = child->nextItem())
117  {
118  cnoid::SimulatorItemPtr sim = dynamic_cast<cnoid::SimulatorItem *>(child);
119  if(sim && !sim->isRunning() && !hooked_sims_.count(sim->name()))
120  {
121  sim->sigSimulationStarted().connect(std::bind(&PosePublisherItem::start, this));
122  sim->sigSimulationFinished().connect(std::bind(&PosePublisherItem::stop, this));
123  hooked_sims_.insert(sim->name());
124  }
125  }
126 }
127 
129 {
130  // Get SimulatorItem
131  sim_ = cnoid::SimulatorItem::findActiveSimulatorItemFor(this);
132  if(!sim_)
133  {
134  cnoid::MessageView::instance()->putln("[PosePublisherItem] SimulatorItem not found", cnoid::MessageView::ERROR);
135  return false;
136  }
137 
138  // Get BodyItem
139  body_item_ = this->findOwnerItem<cnoid::BodyItem>();
140  if(!body_item_)
141  {
142  cnoid::MessageView::instance()->putln("[PosePublisherItem] Owner BodyItem not found", cnoid::MessageView::ERROR);
143  return false;
144  }
145 
146  // Setup ROS
147  nh_ = rclcpp::Node::make_shared("CnoidROSPlugin::PosePublisher");
148 
149  if(pose_topic_name_.empty())
150  {
151  pose_topic_name_ = "cnoid/" + body_item_->name() + "/pose";
152  }
153  if(vel_topic_name_.empty())
154  {
155  vel_topic_name_ = "cnoid/" + body_item_->name() + "/vel";
156  }
157  if(frame_id_.empty())
158  {
159  frame_id_ = "robot_map";
160  }
161  if(tf_child_frame_id_.empty())
162  {
164  }
165  pose_pub_ = nh_->create_publisher<geometry_msgs::msg::PoseStamped>(pose_topic_name_, 1);
166  vel_pub_ = nh_->create_publisher<geometry_msgs::msg::TwistStamped>(vel_topic_name_, 1);
167  pub_skip_ = getPubSkip();
168 
169  // Add postDynamicsFunction
170  post_dynamics_func_id_ = sim_->addPostDynamicsFunction(std::bind(&PosePublisherItem::onPostDynamics, this));
171 
172  return true;
173 }
174 
176 {
177  // Remove postDynamicsFunction
178  if(post_dynamics_func_id_ != -1)
179  {
180  sim_->removePostDynamicsFunction(post_dynamics_func_id_);
182  }
183 }
184 
186 {
187  sim_cnt_++;
188  if(sim_cnt_ % pub_skip_ != 0)
189  {
190  return;
191  }
192 
193  // Get SimulationBody
194  cnoid::SimulationBody * sim_body = sim_->findSimulationBody(body_item_);
195  if(!sim_body)
196  {
197  cnoid::MessageView::instance()->putln("[PosePublisherItem] SimulationBody not found", cnoid::MessageView::ERROR);
198  return;
199  }
200 
201  // Get Link
202  cnoid::DyLink * link = nullptr;
203  if(link_name_.empty())
204  {
205  link = static_cast<cnoid::DyBody *>(sim_body->body())->rootLink();
206  }
207  else
208  {
209  link = static_cast<cnoid::DyBody *>(sim_body->body())->link(link_name_);
210  }
211  if(!link)
212  {
213  cnoid::MessageView::instance()->putln("[PosePublisherItem] Link " + link_name_ + " not found",
214  cnoid::MessageView::ERROR);
215  return;
216  }
217 
218  // Publish message
219  rclcpp::Time stamp_now = nh_->now();
220 
221  // You need to use Ta() instead of T() to get correct rotation
222  // ref: https://github.com/s-nakaoka/choreonoid/commit/cefcfce0caddf94d9eef9c75277fc78e9fbd53b6
223  cnoid::Isometry3 pose = link->T();
224 
225  if(output_tf_)
226  {
227  if(!tf_br_)
228  {
229  tf_br_ = std::make_shared<tf2_ros::TransformBroadcaster>(nh_);
230  }
231 
232  geometry_msgs::msg::TransformStamped msg;
233  msg.header.stamp = stamp_now;
234  msg.header.frame_id = frame_id_;
235  msg.child_frame_id = tf_child_frame_id_;
236  tf2::toMsg(pose.translation(), msg.transform.translation);
237  msg.transform.rotation = tf2::toMsg(Eigen::Quaterniond(pose.rotation()));
238 
239  tf_br_->sendTransform(msg);
240  }
241  else
242  {
243  geometry_msgs::msg::PoseStamped pose_msg;
244  pose_msg.header.stamp = stamp_now;
245  pose_msg.header.frame_id = frame_id_;
246  pose_msg.pose = tf2::toMsg(pose);
247  pose_pub_->publish(pose_msg);
248 
249  geometry_msgs::msg::TwistStamped vel_msg;
250  vel_msg.header.stamp = stamp_now;
251  vel_msg.header.frame_id = frame_id_;
252  tf2::toMsg(link->v(), vel_msg.twist.linear);
253  tf2::toMsg(link->w(), vel_msg.twist.angular);
254 
255  vel_pub_->publish(vel_msg);
256  }
257 }
258 
260 {
261  return std::max(static_cast<int>(1.0 / (pub_rate_ * sim_->worldTimeStep())), 1);
262 }
Plugin item to publish topics and broadcast TF of pose and velocity of the model.
rclcpp::Publisher< geometry_msgs::msg::PoseStamped >::SharedPtr pose_pub_
std::set< std::string > hooked_sims_
virtual bool store(cnoid::Archive &archive) override
virtual void doPutProperties(cnoid::PutPropertyFunction &putProperty) override
virtual bool restore(const cnoid::Archive &archive) override
virtual cnoid::Item * doDuplicate() const override
rclcpp::Publisher< geometry_msgs::msg::TwistStamped >::SharedPtr vel_pub_
static void initialize(cnoid::ExtensionManager *ext)
cnoid::SimulatorItemPtr sim_
std::shared_ptr< tf2_ros::TransformBroadcaster > tf_br_