selfdriving
MVSIM_VehicleInterface.h
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  * SelfDriving C++ library based on PTGs and mrpt-nav
3  * Copyright (C) 2019-2022 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
6 
7 #pragma once
8 
11 #include <mrpt/core/lock_helper.h>
12 #include <mrpt/kinematics/CVehicleSimul_DiffDriven.h>
13 #include <mrpt/kinematics/CVehicleSimul_Holo.h>
14 #include <mrpt/obs/CObservation2DRangeScan.h>
15 #include <mvsim/Comms/Client.h>
16 #include <mvsim/mvsim-msgs/GenericObservation.pb.h>
17 #include <mvsim/mvsim-msgs/SrvGetPose.pb.h>
18 #include <mvsim/mvsim-msgs/SrvGetPoseAnswer.pb.h>
19 #include <mvsim/mvsim-msgs/SrvSetControllerTwist.pb.h>
20 #include <mvsim/mvsim-msgs/SrvSetControllerTwistAnswer.pb.h>
21 
22 namespace mpp
23 {
24 /** Vehicle adaptor class for the MVSIM simulator.
25  *
26  * Motion commands implemented here in motion_execute():
27  * - mrpt::nav::CVehicleSimul_DiffDriven: For ackermann-like steering.
28  * - mrpt::nav::CVehicleSimul_Holo: For holonomic-like steering.
29  *
30  * \note This file must be implemented in the .h to avoid a direct dependency
31  * of this library on mvsim headers. Only if the user project uses this,
32  * it must then depend on mvsim.
33  */
35 {
36  DEFINE_MRPT_OBJECT(MVSIM_VehicleInterface, mpp)
37 
38  public:
40 
41  /** Connect to the MVSIM server.
42  */
43  void connect()
44  {
45  connection_.enable_profiler(true);
46  MRPT_LOG_INFO("Connecting to mvsim server...");
47  connection_.connect();
48 
49  connection_.subscribeTopic<mvsim_msgs::GenericObservation>(
50  mrpt::format("/%s/%s", robotName_.c_str(), lidarName_.c_str()),
51  [this](const mvsim_msgs::GenericObservation& o) { onLidar(o); });
52 
53  MRPT_LOG_INFO("Connected OK.");
54  }
55 
56  // See base class docs
58  {
59  mvsim_msgs::SrvGetPose req;
60  req.set_objectid(robotName_);
61 
62  mvsim_msgs::SrvGetPoseAnswer ans;
63  connection_.callService("get_pose", req, ans);
64 
66  vls.frame_id = "map";
67  vls.timestamp = mrpt::Clock::now();
68  vls.valid = true;
69 
70  vls.pose.x = ans.pose().x();
71  vls.pose.y = ans.pose().y();
72  vls.pose.phi = ans.pose().yaw();
73 
74  return vls;
75  }
76 
77  // See base class docs
79  {
80  mvsim_msgs::SrvGetPose req;
81  req.set_objectid(robotName_);
82 
83  mvsim_msgs::SrvGetPoseAnswer ans;
84  connection_.callService("get_pose", req, ans);
85 
87  vos.odometry.x = ans.pose().x();
88  vos.odometry.y = ans.pose().y();
89  vos.odometry.phi = ans.pose().yaw();
90 
91  vos.odometryVelocityLocal.vx = ans.twist().vx();
92  vos.odometryVelocityLocal.vy = ans.twist().vy();
93  vos.odometryVelocityLocal.omega = ans.twist().wz();
94 
95  vos.pendedActionExists = false; // TODO!
96  vos.timestamp = mrpt::Clock::now();
97  vos.valid = true;
98 
99  return vos;
100  }
101 
102  // See base class docs
104  const std::optional<CVehicleVelCmd::Ptr>& immediate,
105  const std::optional<EnqueuedMotionCmd>& next) override
106  {
107  if (next.has_value())
108  {
109  THROW_EXCEPTION(
110  "Enqueued actions not implemented yet in this wrapper.");
111  }
112  if (!immediate.has_value())
113  {
114  // a NOP:
115  // TODO
116  return true; // ok
117  }
118 
119  // A regular immediate cmd:
120  // We map this request into a service call "set_controller_twist()".
121  mvsim_msgs::SrvSetControllerTwist req;
122  req.set_objectid(robotName_);
123  auto* tw = req.mutable_twistsetpoint();
124  tw->set_vz(0);
125  tw->set_wx(0);
126  tw->set_wy(0);
127 
128  if (auto cmdDiff = std::dynamic_pointer_cast<
129  mrpt::kinematics::CVehicleVelCmd_DiffDriven>(immediate.value());
130  cmdDiff)
131  {
132  tw->set_vx(cmdDiff->lin_vel);
133  tw->set_vy(0);
134  tw->set_wz(cmdDiff->ang_vel);
135  }
136  else if (auto cmdHolo = std::dynamic_pointer_cast<
137  mrpt::kinematics::CVehicleVelCmd_Holo>(immediate.value());
138  cmdHolo)
139  {
140  tw->set_vx(cmdHolo->vel * std::cos(cmdHolo->dir_local));
141  tw->set_vy(cmdHolo->vel * std::sin(cmdHolo->dir_local));
142  tw->set_wz(cmdHolo->rot_speed);
143  }
144  else
145  {
146  MRPT_LOG_ERROR("Unhandled class received in motion_execute().");
147  return false;
148  }
149 
150  mvsim_msgs::SrvSetControllerTwistAnswer ans;
151  connection_.callService("set_controller_twist", req, ans);
152 
153  return ans.success();
154  }
155 
156  // See base class docs
157  void stop([[maybe_unused]] const STOP_TYPE stopType) override
158  {
159  //
160  }
161 
162  /// Returns a copy of the last lidar observation
163  mrpt::obs::CObservation2DRangeScan::Ptr last_lidar_obs() const override
164  {
165  auto lck = mrpt::lockHelper(lastLidarObsMtx_);
166  return lastLidarObs_;
167  }
168 
169  private:
170  mvsim::Client connection_{"MVSIM_VehicleInterface"};
171  std::string robotName_ = "r1";
172  std::string lidarName_ = "laser1";
173 
174  std::mutex lastLidarObsMtx_;
175  mrpt::obs::CObservation2DRangeScan::Ptr lastLidarObs_;
176 
177  void onLidar(const mvsim_msgs::GenericObservation& o)
178  {
179  try
180  {
181  const std::vector<uint8_t> data(
182  o.mrptserializedobservation().begin(),
183  o.mrptserializedobservation().end());
184 
185  mrpt::serialization::CSerializable::Ptr obj;
186  mrpt::serialization::OctetVectorToObject(data, obj);
187 
188  auto lck = mrpt::lockHelper(lastLidarObsMtx_);
189  lastLidarObs_ =
190  std::dynamic_pointer_cast<mrpt::obs::CObservation2DRangeScan>(
191  obj);
192  ASSERT_(lastLidarObs_);
193 
194  // MRPT_LOG_DEBUG_STREAM("sensor callback: " <<
195  // lastLidarObs_->getDescriptionAsTextValue());
196  }
197  catch (const std::exception& e)
198  {
199  MRPT_LOG_ERROR_STREAM(e.what());
200  }
201  }
202 };
203 
204 } // namespace mpp
205 
206 IMPLEMENTS_MRPT_OBJECT(MVSIM_VehicleInterface, VehicleMotionInterface, mpp)
void stop([[maybe_unused]] const STOP_TYPE stopType) override
Definition: MVSIM_VehicleInterface.h:157
VehicleOdometryState get_odometry() override
Definition: MVSIM_VehicleInterface.h:78
Definition: VehicleOdometryState.h:18
std::mutex lastLidarObsMtx_
Definition: MVSIM_VehicleInterface.h:174
Definition: VehicleMotionInterface.h:52
Definition: bestTrajectory.h:15
mrpt::system::TTimeStamp timestamp
Definition: VehicleLocalizationState.h:33
bool valid
Definition: VehicleOdometryState.h:23
std::string robotName_
Definition: MVSIM_VehicleInterface.h:171
std::string lidarName_
Definition: MVSIM_VehicleInterface.h:172
mrpt::math::TTwist2D odometryVelocityLocal
Definition: VehicleOdometryState.h:33
MVSIM_VehicleInterface()
Definition: MVSIM_VehicleInterface.h:39
std::string frame_id
Definition: VehicleLocalizationState.h:46
mrpt::obs::CObservation2DRangeScan::Ptr lastLidarObs_
Definition: MVSIM_VehicleInterface.h:175
bool pendedActionExists
Definition: VehicleOdometryState.h:43
mvsim::Client connection_
Definition: MVSIM_VehicleInterface.h:170
Definition: LidarSource.h:13
mrpt::obs::CObservation2DRangeScan::Ptr last_lidar_obs() const override
Returns a copy of the last lidar observation.
Definition: MVSIM_VehicleInterface.h:163
bool valid
Definition: VehicleLocalizationState.h:25
STOP_TYPE
Definition: VehicleMotionInterface.h:20
mrpt::math::TPose2D pose
Definition: VehicleLocalizationState.h:29
bool motion_execute(const std::optional< CVehicleVelCmd::Ptr > &immediate, const std::optional< EnqueuedMotionCmd > &next) override
Definition: MVSIM_VehicleInterface.h:103
mrpt::system::TTimeStamp timestamp
Definition: VehicleOdometryState.h:37
void connect()
Definition: MVSIM_VehicleInterface.h:43
mrpt::math::TPose2D odometry
Definition: VehicleOdometryState.h:28
Definition: VehicleLocalizationState.h:20
void onLidar(const mvsim_msgs::GenericObservation &o)
Definition: MVSIM_VehicleInterface.h:177
Definition: MVSIM_VehicleInterface.h:34
VehicleLocalizationState get_localization() override
Definition: MVSIM_VehicleInterface.h:57