rviz_robot_builder.cc
Go to the documentation of this file.
00001 /******************************************************************************
00002 Copyright (c) 2017, Alexander W. Winkler. All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 
00010 * Redistributions in binary form must reproduce the above copyright notice,
00011   this list of conditions and the following disclaimer in the documentation
00012   and/or other materials provided with the distribution.
00013 
00014 * Neither the name of the copyright holder nor the names of its
00015   contributors may be used to endorse or promote products derived from
00016   this software without specific prior written permission.
00017 
00018 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00022 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00024 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00025 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00027 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028 ******************************************************************************/
00029 
00030 #include <xpp_vis/rviz_robot_builder.h>
00031 
00032 #include <xpp_states/convert.h>
00033 #include <xpp_vis/rviz_colors.h>
00034 
00035 namespace xpp {
00036 
00037 RvizRobotBuilder::RvizRobotBuilder()
00038 {
00039   terrain_msg_.friction_coeff = 0.0;
00040 }
00041 
00042 void
00043 RvizRobotBuilder::SetRobotParameters (const xpp_msgs::RobotParameters& msg)
00044 {
00045   params_msg_ = msg;
00046 }
00047 
00048 void
00049 RvizRobotBuilder::SetTerrainParameters (const xpp_msgs::TerrainInfo& msg)
00050 {
00051   terrain_msg_ = msg;
00052 }
00053 
00054 void
00055 RvizRobotBuilder::FillWithInvisible(int max_size, MarkerVec& vec) const
00056 {
00057   Marker invisible = vec.empty()? Marker() : vec.back();
00058   invisible.color.a = 0.0;
00059   vec.resize(max_size, invisible);
00060 }
00061 
00062 RvizRobotBuilder::MarkerArray
00063 RvizRobotBuilder::BuildRobotState (const xpp_msgs::RobotStateCartesian& state_msg) const
00064 {
00065   MarkerArray msg;
00066 
00067   auto state = Convert::ToXpp(state_msg);
00068   auto ee_pos = state.ee_motion_.Get(kPos);
00069 
00070   Marker base = CreateBasePose(state.base_.lin.p_,
00071                                state.base_.ang.q,
00072                                state.ee_contact_);
00073   msg.markers.push_back(base);
00074 
00075   MarkerVec m_ee_pos = CreateEEPositions(ee_pos, state.ee_contact_);
00076   FillWithInvisible(max_ee_, m_ee_pos);
00077   msg.markers.insert(msg.markers.begin(), m_ee_pos.begin(), m_ee_pos.end());
00078 
00079   MarkerVec ee_forces = CreateEEForces(state.ee_forces_, ee_pos, state.ee_contact_);
00080   FillWithInvisible(max_ee_, ee_forces);
00081   msg.markers.insert(msg.markers.begin(), ee_forces.begin(), ee_forces.end());
00082 
00083   MarkerVec rom = CreateRangeOfMotion(state.base_);
00084   FillWithInvisible(max_ee_, rom);
00085   msg.markers.insert(msg.markers.begin(), rom.begin(), rom.end());
00086 
00087   MarkerVec support = CreateSupportArea(state.ee_contact_, ee_pos);
00088   FillWithInvisible(max_ee_, support);
00089   msg.markers.insert(msg.markers.begin(), support.begin(), support.end());
00090 
00091   MarkerVec friction = CreateFrictionCones(ee_pos, state.ee_contact_);
00092   FillWithInvisible(max_ee_, friction);
00093   msg.markers.insert(msg.markers.begin(), friction.begin(), friction.end());
00094 
00095   Marker cop = CreateCopPos(state.ee_forces_, ee_pos);
00096   msg.markers.push_back(cop);
00097 
00098   Marker ip = CreatePendulum(state.base_.lin.p_, state.ee_forces_, ee_pos);
00099   msg.markers.push_back(ip);
00100 
00101   msg.markers.push_back(CreateGravityForce(state.base_.lin.p_));
00102 
00103   int id = 0;
00104   for (Marker& m : msg.markers) {
00105     m.header.frame_id = frame_id_;
00106     m.id = id++;
00107   }
00108 
00109   return msg;
00110 }
00111 
00112 RvizRobotBuilder::MarkerVec
00113 RvizRobotBuilder::CreateEEPositions (const EEPos& ee_pos,
00114                                      const ContactState& in_contact) const
00115 {
00116   MarkerVec vec;
00117 
00118   for (auto ee : ee_pos.GetEEsOrdered()) {
00119     Marker m = CreateSphere(ee_pos.at(ee), 0.04);
00120     m.ns     = "endeffector_pos";
00121     m.color  = color.blue;
00122 
00123     vec.push_back(m);
00124   }
00125 
00126   return vec;
00127 }
00128 
00129 RvizRobotBuilder::Marker
00130 RvizRobotBuilder::CreateGravityForce (const Vector3d& base_pos) const
00131 {
00132   double g = 9.81;
00133   double mass = params_msg_.base_mass;
00134   Marker m = CreateForceArrow(Eigen::Vector3d(0.0, 0.0, -mass*g), base_pos);
00135   m.color  = color.red;
00136   m.ns     = "gravity_force";
00137 
00138   return m;
00139 }
00140 
00141 RvizRobotBuilder::MarkerVec
00142 RvizRobotBuilder::CreateEEForces (const EEForces& ee_forces,
00143                                   const EEPos& ee_pos,
00144                                   const ContactState& contact_state) const
00145 {
00146   MarkerVec vec;
00147 
00148   for (auto ee : ee_forces.GetEEsOrdered()) {
00149     Vector3d p = ee_pos.at(ee);
00150     Vector3d f = ee_forces.at(ee);
00151 
00152     Marker m  = CreateForceArrow(f, p);
00153     m.color   = color.red;
00154     m.color.a = f.norm() > 0.1 ? 1.0 : 0.0;
00155     m.ns      = "ee_force";
00156     vec.push_back(m);
00157   }
00158 
00159   return vec;
00160 }
00161 
00162 RvizRobotBuilder::MarkerVec
00163 RvizRobotBuilder::CreateFrictionCones (const EEPos& ee_pos,
00164                                        const ContactState& contact_state) const
00165 {
00166   MarkerVec vec;
00167 
00168   // add at least one invisible to have namespace template to fill
00169   Marker invisible  = CreateFrictionCone(Vector3d::Zero(), Vector3d::Zero(), 0.0);
00170   invisible.color.a = 0.0;
00171   vec.push_back(invisible);
00172 
00173   // only draw cones if terrain_msg and robot state correspond
00174   double mu = terrain_msg_.friction_coeff;
00175   if (ee_pos.GetEECount() == terrain_msg_.surface_normals.size() && mu > 1e-3) {
00176 
00177     auto normals = Convert::ToXpp(terrain_msg_.surface_normals);
00178     for (auto ee : normals.GetEEsOrdered()) {
00179       Marker m;
00180       Vector3d n = normals.at(ee);
00181       m         = CreateFrictionCone(ee_pos.at(ee), -n, mu);
00182       m.color   = color.red;
00183       m.color.a = contact_state.at(ee)? 0.25 : 0.0;
00184       vec.push_back(m);
00185     }
00186   }
00187 
00188   return vec;
00189 }
00190 
00191 RvizRobotBuilder::Marker
00192 RvizRobotBuilder::CreateFrictionCone (const Vector3d& pos,
00193                                       const Vector3d& normal,
00194                                       double mu) const
00195 {
00196   Marker m;
00197   m.type = Marker::ARROW;
00198   m.ns   = "friction_cone";
00199 
00200   double cone_height = 0.1; // [m]
00201 
00202   m.scale.x = 0.00; // [shaft diameter] hide arrow shaft to generate cone
00203   m.scale.y = 2.0 * cone_height * mu; // arrow-head diameter
00204   m.scale.z = cone_height;            // arrow head length
00205 
00206   auto start = Convert::ToRos<geometry_msgs::Point>(pos + normal);
00207   m.points.push_back(start);
00208 
00209   auto end = Convert::ToRos<geometry_msgs::Point>(pos);
00210   m.points.push_back(end);
00211 
00212   return m;
00213 }
00214 
00215 RvizRobotBuilder::Marker
00216 RvizRobotBuilder::CreateBasePose (const Vector3d& pos,
00217                                   Eigen::Quaterniond ori,
00218                                   const ContactState& contact_state) const
00219 {
00220   Vector3d edge_length(0.1, 0.05, 0.02);
00221   Marker m = CreateBox(pos, ori, 3*edge_length);
00222 
00223   m.color = color.black;
00224   m.color.a = 0.8;
00225   for (auto ee : contact_state.GetEEsOrdered())
00226     if (contact_state.at(ee))
00227       m.color = color.black;
00228 
00229   m.ns = "base_pose";
00230 
00231   return m;
00232 }
00233 
00234 RvizRobotBuilder::Marker
00235 RvizRobotBuilder::CreateCopPos (const EEForces& ee_forces,
00236                                 const EEPos& ee_pos) const
00237 {
00238   double z_sum = 0.0;
00239   for (Vector3d ee : ee_forces.ToImpl())
00240     z_sum += ee.z();
00241 
00242   Marker m;
00243   // only then can the Center of Pressure be calculated
00244   Vector3d cop = Vector3d::Zero();
00245   if (z_sum > 0.0) {
00246     for (auto ee : ee_forces.GetEEsOrdered()) {
00247       double p = ee_forces.at(ee).z()/z_sum;
00248       cop += p*ee_pos.at(ee);
00249     }
00250     m = CreateSphere(cop);
00251   } else {
00252     m = CreateSphere(cop, 0.001); // no CoP exists b/c flight phase
00253   }
00254 
00255   m.color = color.red;
00256   m.ns = "cop";
00257 
00258   return m;
00259 }
00260 
00261 RvizRobotBuilder::Marker
00262 RvizRobotBuilder::CreatePendulum (const Vector3d& pos,
00263                                   const EEForces& ee_forces,
00264                                   const EEPos& ee_pos) const
00265 {
00266   Marker m;
00267   m.type = Marker::LINE_STRIP;
00268   m.scale.x = 0.007; // thickness of pendulum pole
00269 
00270   geometry_msgs::Point cop = CreateCopPos(ee_forces, ee_pos).pose.position;
00271   geometry_msgs::Point com = CreateSphere(pos).pose.position;
00272 
00273   m.points.push_back(cop);
00274   m.points.push_back(com);
00275 
00276   m.ns = "inverted_pendulum";
00277   m.color = color.black;
00278 
00279   double fz_sum = 0.0;
00280   for (Vector3d ee : ee_forces.ToImpl())
00281     fz_sum += ee.z();
00282 
00283   if (fz_sum < 1.0) // [N] flight phase
00284     m.color.a = 0.0; // hide marker
00285 
00286   return m;
00287 }
00288 
00289 RvizRobotBuilder::MarkerVec
00290 RvizRobotBuilder::CreateRangeOfMotion (const State3d& base) const
00291 {
00292   MarkerVec vec;
00293 
00294   auto w_R_b = base.ang.q.toRotationMatrix();
00295 
00296   for (const auto& pos_B : params_msg_.nominal_ee_pos) {
00297     Vector3d pos_W = base.lin.p_ + w_R_b*Convert::ToXpp(pos_B);
00298 
00299     Vector3d edge_length = 2*Convert::ToXpp(params_msg_.ee_max_dev);
00300     Marker m  = CreateBox(pos_W, base.ang.q, edge_length);
00301     m.color   = color.blue;
00302     m.color.a = 0.2;
00303     m.ns      = "range_of_motion";
00304     vec.push_back(m);
00305   }
00306 
00307   return vec;
00308 }
00309 
00310 RvizRobotBuilder::Marker
00311 RvizRobotBuilder::CreateBox (const Vector3d& pos, Eigen::Quaterniond ori,
00312                              const Vector3d& edge_length) const
00313 {
00314   Marker m;
00315 
00316   m.type = Marker::CUBE;
00317   m.pose.position    = Convert::ToRos<geometry_msgs::Point>(pos);
00318   m.pose.orientation = Convert::ToRos(ori);
00319   m.scale            = Convert::ToRos<geometry_msgs::Vector3>(edge_length);
00320 
00321   return m;
00322 }
00323 
00324 RvizRobotBuilder::Marker
00325 RvizRobotBuilder::CreateSphere (const Vector3d& pos, double diameter) const
00326 {
00327   Marker m;
00328 
00329   m.type = Marker::SPHERE;
00330   m.pose.position = Convert::ToRos<geometry_msgs::Point>(pos);
00331   m.scale.x = diameter;
00332   m.scale.y = diameter;
00333   m.scale.z = diameter;
00334 
00335   return m;
00336 }
00337 
00338 RvizRobotBuilder::Marker
00339 RvizRobotBuilder::CreateForceArrow (const Vector3d& force,
00340                                     const Vector3d& ee_pos) const
00341 {
00342   Marker m;
00343   m.type = Marker::ARROW;
00344 
00345   m.scale.x = 0.01; // shaft diameter
00346   m.scale.y = 0.02; // arrow-head diameter
00347   m.scale.z = 0.06; // arrow-head length
00348 
00349   double force_scale = 800;
00350   Vector3d p_start = ee_pos - force/force_scale;
00351   auto start = Convert::ToRos<geometry_msgs::Point>(p_start);
00352   m.points.push_back(start);
00353 
00354   auto end = Convert::ToRos<geometry_msgs::Point>(ee_pos);
00355   m.points.push_back(end);
00356 
00357   return m;
00358 }
00359 
00360 RvizRobotBuilder::MarkerVec
00361 RvizRobotBuilder::CreateSupportArea (const ContactState& contact_state,
00362                                      const EEPos& ee_pos) const
00363 {
00364   MarkerVec vec;
00365 
00366   Marker m;
00367   m.ns = "support_polygons";
00368   m.scale.x = m.scale.y = m.scale.z = 1.0;
00369 
00370   for (auto ee : contact_state.GetEEsOrdered()) {
00371     if (contact_state.at(ee)) { // endeffector in contact
00372       auto p = Convert::ToRos<geometry_msgs::Point>(ee_pos.at(ee));
00373       m.points.push_back(p);
00374       m.color = color.black;
00375       m.color.a = 0.2;
00376     }
00377   }
00378 
00379   switch (m.points.size()) {
00380     case 4: {
00381       m.type = Marker::TRIANGLE_LIST;
00382       auto temp = m.points;
00383 
00384       // add two triangles to represent a square
00385       m.points.pop_back();
00386       vec.push_back(m);
00387 
00388       m.points = temp;
00389       m.points.erase(m.points.begin());
00390       vec.push_back(m);
00391       break;
00392     }
00393     case 3: {
00394       m.type = Marker::TRIANGLE_LIST;
00395       vec.push_back(m);
00396       vec.push_back(m);
00397       break;
00398     }
00399     case 2: {
00400       m.type = Marker::LINE_STRIP;
00401       m.scale.x = 0.01;
00402       vec.push_back(m);
00403       vec.push_back(m);
00404       break;
00405     }
00406     case 1: {
00407       /* just make so small that random marker can't be seen */
00408       m.type = Marker::CUBE; // just so same shape is specified
00409       m.color.a = 0.0; // hide marker
00410       vec.push_back(m);
00411       vec.push_back(m);
00412       break;
00413     }
00414     default:
00415       m.type = Marker::CUBE; // just so same shapes is specified
00416       m.color.a = 0.0; // hide marker
00417       vec.push_back(m);
00418       vec.push_back(m);
00419       break;
00420   }
00421 
00422   return vec;
00423 }
00424 
00425 } /* namespace xpp */


xpp_vis
Author(s): Alexander W. Winkler
autogenerated on Fri Apr 5 2019 02:55:52