main.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020-2023 RaccoonLab.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, version 3.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authors: Dmitry Ponomarev <ponomarevda96@gmail.com>
17  * Roman Fedorenko <frontwise@gmail.com>
18  */
19 
20 #include "main.hpp"
21 #include <rosgraph_msgs/Clock.h>
22 #include <geometry_msgs/TransformStamped.h>
23 #include <std_msgs/Time.h>
24 
26 #include "vtolDynamicsSim.hpp"
27 #include "cs_converter.hpp"
28 
29 
30 int main(int argc, char **argv){
31  ros::init(argc, argv, "uav_dynamics_node");
34  }
35 
36  ros::NodeHandle node_handler("inno_dynamics_sim");
37  Uav_Dynamics uav_dynamics_node(node_handler);
38  if(uav_dynamics_node.init() == -1){
39  ROS_ERROR("Shutdown.");
40  ros::shutdown();
41  return -1;
42  }
43 
44  ros::spin();
45  return 0;
46 }
47 
48 
50  _node(nh),
51  _sensors(&nh),
52  _rviz_visualizator(_node),
53  _scenarioManager(_node, _actuators, _sensors),
54  _logger(_actuators, _sensors, info){
55 }
56 
57 
62  if(getParamsFromRos() == -1){
63  return -1;
64  }else if(initDynamicsSimulator() == -1){
65  return -1;
66  }else if(initSensors() == -1){
67  return -1;
68  }else if(initCalibration() == -1){
69  return -1;
70  }else if(_rviz_visualizator.init(uavDynamicsSim_) == -1){
71  return -1;
72  }else if(startClockAndThreads() == -1){
73  return -1;
74  }
75 
76  return 0;
77 }
78 
80  const std::string SIM_PARAMS_PATH = "/uav/sim_params/";
81  if(!ros::param::get(SIM_PARAMS_PATH + "use_sim_time", useSimTime_ ) ||
82  !_node.getParam("vehicle", info.vehicleName) ||
83  !_node.getParam("dynamics", info.dynamicsName) ||
84  !ros::param::get(SIM_PARAMS_PATH + "init_pose", initPose_)){
85  ROS_ERROR("Dynamics: There is no at least one of required simulator parameters.");
86  return -1;
87  }
88  return 0;
89 }
90 
92  const char DYNAMICS_NAME_FLIGHTGOGGLES[] = "flightgoggles_multicopter";
93  const char DYNAMICS_NAME_INNO_VTOL[] = "inno_vtol";
94  const char VEHICLE_NAME_INNOPOLIS_VTOL[] = "innopolis_vtol";
95  const char VEHICLE_NAME_IRIS[] = "iris";
96  if(info.dynamicsName == DYNAMICS_NAME_FLIGHTGOGGLES){
98  uavDynamicsSim_ = std::make_shared<FlightgogglesDynamics>();
100  }else if(info.dynamicsName == DYNAMICS_NAME_INNO_VTOL){
101  uavDynamicsSim_ = std::make_shared<InnoVtolDynamicsSim>();
104  }else{
105  ROS_ERROR("Dynamics type with name \"%s\" is not exist.", info.dynamicsName.c_str());
106  return -1;
107  }
108 
109  if(info.vehicleName == VEHICLE_NAME_INNOPOLIS_VTOL){
111  }else if(info.vehicleName == VEHICLE_NAME_IRIS){
113  }else{
114  ROS_ERROR("Wrong vehicle. It should be 'innopolis_vtol' or 'iris'");
115  return -1;
116  }
117 
118  if(uavDynamicsSim_ == nullptr || uavDynamicsSim_->init() == -1){
119  ROS_ERROR("Can't init uav dynamics sim. Shutdown.");
120  return -1;
121  }
122 
123  Eigen::Vector3d initPosition(initPose_.at(0), initPose_.at(1), initPose_.at(2));
124  Eigen::Quaterniond initAttitude(initPose_.at(6), initPose_.at(3), initPose_.at(4), initPose_.at(5));
125  initAttitude.normalize();
126  uavDynamicsSim_->setInitialPosition(initPosition, initAttitude);
127 
128  return 0;
129 }
130 
135  return _sensors.init(uavDynamicsSim_);
136 }
137 
139  calibrationSub_ = _node.subscribe("/uav/calibration", 1, &Uav_Dynamics::calibrationCallback, this);
140  return 0;
141 }
142 
144  ros::Duration(0.1).sleep();
145  if(useSimTime_){
146  clockPub_ = _node.advertise<rosgraph_msgs::Clock>("/clock", 1);
147  rosgraph_msgs::Clock clock_time;
148  clock_time.clock = currentTime_;
149  clockPub_.publish(clock_time);
150  }else{
151  // Get the current time if we are using wall time. Otherwise, use 0 as initial clock.
153  }
154 
155 
158  this);
160 
162  proceedDynamicsTask.detach();
163 
165  publishToRosTask.detach();
166 
167  diagnosticTask = std::thread(&Uav_Dynamics::performLogging, this, 1.0);
168  diagnosticTask.detach();
169 
170  return 0;
171 }
172 
178  if (useSimTime_){
180  rosgraph_msgs::Clock clock_time;
181  clock_time.clock = currentTime_;
182  clockPub_.publish(clock_time);
183  } else {
184  ros::Time loopStartTime = ros::Time::now();
185  dt_secs_ = (loopStartTime - currentTime_).toSec();
186  currentTime_ = loopStartTime;
187  }
188 }
189 
190 void Uav_Dynamics::performLogging(double periodSec){
191  while(ros::ok()){
192  auto crnt_time = std::chrono::system_clock::now();
193  auto sleed_period = std::chrono::seconds(int(periodSec * clockScale_));
194 
195  std::stringstream logStream;
196  auto pose = uavDynamicsSim_->getVehiclePosition();
197  _logger.createStringStream(logStream, pose, dynamicsCounter_, rosPubCounter_, periodSec);
198  dynamicsCounter_ = 0;
199  rosPubCounter_ = 0;
200 
201 
202  ROS_INFO_STREAM(logStream.str());
203  fflush(stdout);
204  std::this_thread::sleep_until(crnt_time + sleed_period);
205  }
206 }
207 
208 // The sequence of steps for lockstep are:
209 // The simulation sends a sensor message HIL_SENSOR including a timestamp time_usec to update
210 // the sensor state and time of PX4.
211 // PX4 receives this and does one iteration of state estimation, controls, etc. and eventually
212 // sends an actuator message HIL_ACTUATOR_CONTROLS.
213 // The simulation waits until it receives the actuator/motor message, then simulates the physics
214 // and calculates the next sensor message to send to PX4 again.
215 // The system starts with a "freewheeling" period where the simulation sends sensor messages
216 // including time and therefore runs PX4 until it has initialized and responds with an actautor
217 // message.
218 // But instead of waiting actuators cmd, we will wait for an arming
219 void Uav_Dynamics::proceedDynamics(double periodSec){
220  while(ros::ok()){
221  auto crnt_time = std::chrono::system_clock::now();
222  auto sleed_period = std::chrono::milliseconds(int(1000 * periodSec * clockScale_));
223  auto time_point = crnt_time + sleed_period;
225 
227  uavDynamicsSim_->calibrate(calibrationType_);
228  }else if(_actuators.armed_){
229  static auto crnt_time = std::chrono::system_clock::now();
230  auto prev_time = crnt_time;
231  crnt_time = std::chrono::system_clock::now();
232  auto time_dif_sec = static_cast<double>((crnt_time - prev_time).count()) * 1e-9;
233 
235  const double MAX_TIME_DIFF_SEC = 10 * periodSec;
236  if (time_dif_sec > MAX_TIME_DIFF_SEC) {
237  ROS_ERROR_STREAM_THROTTLE(1, "Time jumping: " << time_dif_sec << " seconds.");
238  time_dif_sec = MAX_TIME_DIFF_SEC;
239  }
240 
241  uavDynamicsSim_->process(time_dif_sec, _actuators._actuators, true);
242  }else{
243  uavDynamicsSim_->land();
244  }
245 
247 
248  std::this_thread::sleep_until(time_point);
249  }
250 }
251 
252 void Uav_Dynamics::publishToRos(double period){
253  while(ros::ok()){
254  auto crnt_time = std::chrono::system_clock::now();
255  auto sleed_period = std::chrono::microseconds(int(1000000 * period * clockScale_));
256  auto time_point = crnt_time + sleed_period;
257  rosPubCounter_++;
258 
260 
261  static auto next_time = std::chrono::system_clock::now();
262  if(crnt_time > next_time){
265  }
266  next_time += std::chrono::milliseconds(int(50));
267  }
268 
269  std::this_thread::sleep_until(time_point);
270  }
271 }
272 
273 void Uav_Dynamics::calibrationCallback(std_msgs::UInt8 msg){
274  if(calibrationType_ != static_cast<UavDynamicsSimBase::SimMode_t>(msg.data)){
275  ROS_INFO_STREAM_THROTTLE(1, "calibration type: " << msg.data + 0);
276  }
277  calibrationType_ = static_cast<UavDynamicsSimBase::SimMode_t>(msg.data);
278 }
void simulationLoopTimerCallback(const ros::WallTimerEvent &event)
Main Simulator loop.
Definition: main.cpp:177
std::string dynamicsName
Definition: dynamics.hpp:38
void calibrationCallback(std_msgs::UInt8 msg)
Definition: main.cpp:273
void proceedDynamics(double period)
Definition: main.cpp:219
ros::NodeHandle _node
Definition: main.hpp:57
#define ROS_ERROR_STREAM_THROTTLE(period, args)
ros::WallTimer simulationLoopTimer_
Definition: main.hpp:86
int8_t initDynamicsSimulator()
Definition: main.cpp:91
ROSCONSOLE_DECL void notifyLoggerLevelsChanged()
double dt_secs_
Definition: main.hpp:62
#define ROS_INFO_STREAM_THROTTLE(period, args)
const float ROS_PUB_PERIOD_SEC
Definition: main.hpp:96
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int main(int argc, char **argv)
Definition: main.cpp:30
void init(ros::NodeHandle &node)
Definition: actuators.hpp:28
int8_t init(const std::shared_ptr< UavDynamicsSimBase > &uavDynamicsSim)
Definition: sensors.cpp:39
Actuators _actuators
Definition: main.hpp:70
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
ros::Time currentTime_
Definition: main.hpp:61
void performLogging(double period)
Definition: main.cpp:190
double clockScale_
Definition: main.hpp:63
uint64_t dynamicsCounter_
Definition: main.hpp:82
uint64_t rosPubCounter_
Definition: main.hpp:83
int8_t init()
Definition: main.cpp:61
UavDynamicsSimBase::SimMode_t calibrationType_
Definition: main.hpp:78
int8_t getParamsFromRos()
Definition: main.cpp:79
void publishStateToCommunicator(uint8_t dynamicsNotation)
Definition: sensors.cpp:92
std::thread publishToRosTask
Definition: main.hpp:88
int8_t initSensors()
Definition: main.cpp:131
WallTimer createWallTimer(WallDuration period, void(T::*callback)(const WallTimerEvent &), T *obj, bool oneshot=false, bool autostart=true) const
std::string vehicleName
Definition: dynamics.hpp:42
void publish(uint8_t dynamicsNotation)
void publishToRos(double period)
Definition: main.cpp:252
void publish(const boost::shared_ptr< M > &message) const
ros::Subscriber calibrationSub_
Definition: main.hpp:77
DynamicsNotation_t notation
Definition: dynamics.hpp:44
std::thread diagnosticTask
Definition: main.hpp:89
ROSCPP_DECL bool get(const std::string &key, std::string &s)
bool getParam(const std::string &key, std::string &s) const
std::vector< double > initPose_
Definition: main.hpp:66
UAV Dynamics class used for dynamics, IMU, and angular rate control simulation node.
Definition: main.hpp:44
ROSCPP_DECL bool ok()
bool armed_
Definition: actuators.hpp:44
std::thread proceedDynamicsTask
Definition: main.hpp:87
RvizVisualizator _rviz_visualizator
Definition: main.hpp:72
Uav_Dynamics(ros::NodeHandle nh)
Definition: main.cpp:49
std::vector< double > _actuators
Definition: actuators.hpp:34
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ROSCPP_DECL void spin()
std::shared_ptr< UavDynamicsSimBase > uavDynamicsSim_
Definition: main.hpp:58
void init(double clockScale, double dt_secs)
Definition: logger.cpp:33
void createStringStream(std::stringstream &logStream, const Eigen::Vector3d &pose, double dynamicsCounter, double rosPubCounter, double periodSec)
Definition: logger.cpp:38
ScenarioManager _scenarioManager
Definition: main.hpp:73
#define ROS_INFO_STREAM(args)
bool useSimTime_
Definition: main.hpp:64
static Time now()
StateLogger _logger
Definition: main.hpp:74
void publishTf(uint8_t dynamicsNotation)
Perform TF transform between GLOBAL_FRAME -> UAV_FRAME in ROS (enu/flu) format.
ROSCPP_DECL void shutdown()
DynamicsType dynamicsType
Definition: dynamics.hpp:39
int8_t init(const std::shared_ptr< UavDynamicsSimBase > &uavDynamicsSim_)
ROSCONSOLE_DECL bool set_logger_level(const std::string &name, levels::Level level)
bool sleep() const
int8_t startClockAndThreads()
Definition: main.cpp:143
Sensors _sensors
Definition: main.hpp:71
DynamicsInfo info
Definition: main.hpp:68
#define ROS_ERROR(...)
#define ROSCONSOLE_DEFAULT_NAME
int8_t initCalibration()
Definition: main.cpp:138
ros::Publisher clockPub_
Definition: main.hpp:59
VehicleType vehicleType
Definition: dynamics.hpp:41


inno_vtol_dynamics
Author(s): Roman Fedorenko, Dmitry Ponomarev, Ezra Tal, Winter Guerra
autogenerated on Sat Jul 1 2023 02:13:44