towr_ros_interface.cc
Go to the documentation of this file.
00001 /******************************************************************************
00002 Copyright (c) 2018, 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 <towr_ros/towr_ros_interface.h>
00031 
00032 #include <std_msgs/Int32.h>
00033 
00034 #include <xpp_states/convert.h>
00035 #include <xpp_msgs/topic_names.h>
00036 #include <xpp_msgs/TerrainInfo.h>
00037 
00038 #include <towr/terrain/height_map.h>
00039 #include <towr/variables/euler_converter.h>
00040 #include <towr_ros/topic_names.h>
00041 #include <towr_ros/towr_xpp_ee_map.h>
00042 
00043 
00044 namespace towr {
00045 
00046 
00047 TowrRosInterface::TowrRosInterface ()
00048 {
00049   ::ros::NodeHandle n;
00050 
00051   user_command_sub_ = n.subscribe(towr_msgs::user_command, 1,
00052                                   &TowrRosInterface::UserCommandCallback, this);
00053 
00054   initial_state_pub_  = n.advertise<xpp_msgs::RobotStateCartesian>
00055                                           (xpp_msgs::robot_state_desired, 1);
00056 
00057   robot_parameters_pub_  = n.advertise<xpp_msgs::RobotParameters>
00058                                     (xpp_msgs::robot_parameters, 1);
00059 
00060   solver_ = std::make_shared<ifopt::IpoptSolver>();
00061 
00062   visualization_dt_ = 0.01;
00063 }
00064 
00065 BaseState
00066 TowrRosInterface::GetGoalState(const TowrCommandMsg& msg) const
00067 {
00068   BaseState goal;
00069   goal.lin.at(kPos) = xpp::Convert::ToXpp(msg.goal_lin.pos);
00070   goal.lin.at(kVel) = xpp::Convert::ToXpp(msg.goal_lin.vel);
00071   goal.ang.at(kPos) = xpp::Convert::ToXpp(msg.goal_ang.pos);
00072   goal.ang.at(kVel) = xpp::Convert::ToXpp(msg.goal_ang.vel);
00073 
00074   return goal;
00075 }
00076 
00077 void
00078 TowrRosInterface::UserCommandCallback(const TowrCommandMsg& msg)
00079 {
00080   // robot model
00081   formulation_.model_ = RobotModel(static_cast<RobotModel::Robot>(msg.robot));
00082   auto robot_params_msg = BuildRobotParametersMsg(formulation_.model_);
00083   robot_parameters_pub_.publish(robot_params_msg);
00084 
00085   // terrain
00086   auto terrain_id = static_cast<HeightMap::TerrainID>(msg.terrain);
00087   formulation_.terrain_ = HeightMap::MakeTerrain(terrain_id);
00088 
00089   int n_ee = formulation_.model_.kinematic_model_->GetNumberOfEndeffectors();
00090   formulation_.params_ = GetTowrParameters(n_ee, msg);
00091   formulation_.final_base_ = GetGoalState(msg);
00092 
00093   SetTowrInitialState();
00094 
00095   // solver parameters
00096   SetIpoptParameters(msg);
00097 
00098   // visualization
00099   PublishInitialState();
00100 
00101   // Defaults to /home/user/.ros/
00102   std::string bag_file = "towr_trajectory.bag";
00103   if (msg.optimize || msg.play_initialization) {
00104     nlp_ = ifopt::Problem();
00105     for (auto c : formulation_.GetVariableSets(solution))
00106       nlp_.AddVariableSet(c);
00107     for (auto c : formulation_.GetConstraints(solution))
00108       nlp_.AddConstraintSet(c);
00109     for (auto c : formulation_.GetCosts())
00110       nlp_.AddCostSet(c);
00111 
00112     solver_->Solve(nlp_);
00113     SaveOptimizationAsRosbag(bag_file, robot_params_msg, msg, false);
00114   }
00115 
00116   // playback using terminal commands
00117   if (msg.replay_trajectory || msg.play_initialization || msg.optimize) {
00118     int success = system(("rosbag play --topics "
00119         + xpp_msgs::robot_state_desired + " "
00120         + xpp_msgs::terrain_info
00121         + " -r " + std::to_string(msg.replay_speed)
00122         + " --quiet " + bag_file).c_str());
00123   }
00124 
00125   if (msg.plot_trajectory) {
00126     int success = system(("killall rqt_bag; rqt_bag " + bag_file + "&").c_str());
00127   }
00128 
00129   // to publish entire trajectory (e.g. to send to controller)
00130   // xpp_msgs::RobotStateCartesianTrajectory xpp_msg = xpp::Convert::ToRos(GetTrajectory());
00131 }
00132 
00133 void
00134 TowrRosInterface::PublishInitialState()
00135 {
00136   int n_ee = formulation_.initial_ee_W_.size();
00137   xpp::RobotStateCartesian xpp(n_ee);
00138   xpp.base_.lin.p_ = formulation_.initial_base_.lin.p();
00139   xpp.base_.ang.q  = EulerConverter::GetQuaternionBaseToWorld(formulation_.initial_base_.ang.p());
00140 
00141   for (int ee_towr=0; ee_towr<n_ee; ++ee_towr) {
00142     int ee_xpp = ToXppEndeffector(n_ee, ee_towr).first;
00143     xpp.ee_contact_.at(ee_xpp)   = true;
00144     xpp.ee_motion_.at(ee_xpp).p_ = formulation_.initial_ee_W_.at(ee_towr);
00145     xpp.ee_forces_.at(ee_xpp).setZero(); // zero for visualization
00146   }
00147 
00148   initial_state_pub_.publish(xpp::Convert::ToRos(xpp));
00149 }
00150 
00151 std::vector<TowrRosInterface::XppVec>
00152 TowrRosInterface::GetIntermediateSolutions ()
00153 {
00154   std::vector<XppVec> trajectories;
00155 
00156   for (int iter=0; iter<nlp_.GetIterationCount(); ++iter) {
00157     nlp_.SetOptVariables(iter);
00158     trajectories.push_back(GetTrajectory());
00159   }
00160 
00161   return trajectories;
00162 }
00163 
00164 TowrRosInterface::XppVec
00165 TowrRosInterface::GetTrajectory () const
00166 {
00167   XppVec trajectory;
00168   double t = 0.0;
00169   double T = solution.base_linear_->GetTotalTime();
00170 
00171   EulerConverter base_angular(solution.base_angular_);
00172 
00173   while (t<=T+1e-5) {
00174     int n_ee = solution.ee_motion_.size();
00175     xpp::RobotStateCartesian state(n_ee);
00176 
00177     state.base_.lin = ToXpp(solution.base_linear_->GetPoint(t));
00178 
00179     state.base_.ang.q  = base_angular.GetQuaternionBaseToWorld(t);
00180     state.base_.ang.w  = base_angular.GetAngularVelocityInWorld(t);
00181     state.base_.ang.wd = base_angular.GetAngularAccelerationInWorld(t);
00182 
00183     for (int ee_towr=0; ee_towr<n_ee; ++ee_towr) {
00184       int ee_xpp = ToXppEndeffector(n_ee, ee_towr).first;
00185 
00186       state.ee_contact_.at(ee_xpp) = solution.phase_durations_.at(ee_towr)->IsContactPhase(t);
00187       state.ee_motion_.at(ee_xpp)  = ToXpp(solution.ee_motion_.at(ee_towr)->GetPoint(t));
00188       state.ee_forces_ .at(ee_xpp) = solution.ee_force_.at(ee_towr)->GetPoint(t).p();
00189     }
00190 
00191     state.t_global_ = t;
00192     trajectory.push_back(state);
00193     t += visualization_dt_;
00194   }
00195 
00196   return trajectory;
00197 }
00198 
00199 xpp_msgs::RobotParameters
00200 TowrRosInterface::BuildRobotParametersMsg(const RobotModel& model) const
00201 {
00202   xpp_msgs::RobotParameters params_msg;
00203   auto max_dev_xyz = model.kinematic_model_->GetMaximumDeviationFromNominal();
00204   params_msg.ee_max_dev = xpp::Convert::ToRos<geometry_msgs::Vector3>(max_dev_xyz);
00205 
00206   auto nominal_B = model.kinematic_model_->GetNominalStanceInBase();
00207   int n_ee = nominal_B.size();
00208   for (int ee_towr=0; ee_towr<n_ee; ++ee_towr) {
00209     Vector3d pos = nominal_B.at(ee_towr);
00210     params_msg.nominal_ee_pos.push_back(xpp::Convert::ToRos<geometry_msgs::Point>(pos));
00211     params_msg.ee_names.push_back(ToXppEndeffector(n_ee, ee_towr).second);
00212   }
00213 
00214   params_msg.base_mass = model.dynamic_model_->m();
00215 
00216   return params_msg;
00217 }
00218 
00219 void
00220 TowrRosInterface::SaveOptimizationAsRosbag (const std::string& bag_name,
00221                                    const xpp_msgs::RobotParameters& robot_params,
00222                                    const TowrCommandMsg user_command_msg,
00223                                    bool include_iterations)
00224 {
00225   rosbag::Bag bag;
00226   bag.open(bag_name, rosbag::bagmode::Write);
00227   ::ros::Time t0(1e-6); // t=0.0 throws ROS exception
00228 
00229   // save the a-priori fixed optimization variables
00230   bag.write(xpp_msgs::robot_parameters, t0, robot_params);
00231   bag.write(towr_msgs::user_command+"_saved", t0, user_command_msg);
00232 
00233   // save the trajectory of each iteration
00234   if (include_iterations) {
00235     auto trajectories = GetIntermediateSolutions();
00236     int n_iterations = trajectories.size();
00237     for (int i=0; i<n_iterations; ++i)
00238       SaveTrajectoryInRosbag(bag, trajectories.at(i), towr_msgs::nlp_iterations_name + std::to_string(i));
00239 
00240     // save number of iterations the optimizer took
00241     std_msgs::Int32 m;
00242     m.data = n_iterations;
00243     bag.write(towr_msgs::nlp_iterations_count, t0, m);
00244   }
00245 
00246   // save the final trajectory
00247   auto final_trajectory = GetTrajectory();
00248   SaveTrajectoryInRosbag(bag, final_trajectory, xpp_msgs::robot_state_desired);
00249 
00250   bag.close();
00251 }
00252 
00253 void
00254 TowrRosInterface::SaveTrajectoryInRosbag (rosbag::Bag& bag,
00255                                  const XppVec& traj,
00256                                  const std::string& topic) const
00257 {
00258   for (const auto state : traj) {
00259     auto timestamp = ::ros::Time(state.t_global_ + 1e-6); // t=0.0 throws ROS exception
00260 
00261     xpp_msgs::RobotStateCartesian msg;
00262     msg = xpp::Convert::ToRos(state);
00263     bag.write(topic, timestamp, msg);
00264 
00265     xpp_msgs::TerrainInfo terrain_msg;
00266     for (auto ee : state.ee_motion_.ToImpl()) {
00267       Vector3d n = formulation_.terrain_->GetNormalizedBasis(HeightMap::Normal, ee.p_.x(), ee.p_.y());
00268       terrain_msg.surface_normals.push_back(xpp::Convert::ToRos<geometry_msgs::Vector3>(n));
00269       terrain_msg.friction_coeff = formulation_.terrain_->GetFrictionCoeff();
00270     }
00271 
00272     bag.write(xpp_msgs::terrain_info, timestamp, terrain_msg);
00273   }
00274 }
00275 
00276 } /* namespace towr */
00277 


towr_ros
Author(s): Alexander W. Winkler
autogenerated on Mon Apr 15 2019 02:42:39