Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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
00096 SetIpoptParameters(msg);
00097
00098
00099 PublishInitialState();
00100
00101
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
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
00130
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();
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);
00228
00229
00230 bag.write(xpp_msgs::robot_parameters, t0, robot_params);
00231 bag.write(towr_msgs::user_command+"_saved", t0, user_command_msg);
00232
00233
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
00241 std_msgs::Int32 m;
00242 m.data = n_iterations;
00243 bag.write(towr_msgs::nlp_iterations_count, t0, m);
00244 }
00245
00246
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);
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 }
00277