Autonomous Racing  1
f1tenth Project Group of Technical University Dortmund, Germany
dms_controller.cpp
Go to the documentation of this file.
1 #include "dms_controller.h"
2 
4 {
5  this->m_heartbeat_manual_subscriber =
6  this->m_node_handle.subscribe<std_msgs::Time>(TOPIC_HEARTBEAT_MANUAL, 1,
7  &DMSController::heartbeatManualCallback, this);
8  this->m_heartbeat_autonomous_subscriber =
9  this->m_node_handle.subscribe<std_msgs::Time>(TOPIC_HEARTBEAT_AUTONOMOUS, 1,
10  &DMSController::heartbeatAutonomousCallback, this);
11  this->m_emergencystop_subscriber =
12  this->m_node_handle.subscribe<std_msgs::Time>(TOPIC_EMERGENCYSTOP, 1, &DMSController::emergencystopCallback,
13  this);
14  this->m_drive_mode_publisher = this->m_node_handle.advertise<std_msgs::Int32>(TOPIC_DRIVE_MODE, 1);
15  this->m_command_emergencystop_publisher =
16  this->m_node_handle.advertise<std_msgs::Bool>(TOPIC_COMMAND_EMERGENCYSTOP, 1);
17  this->configureParameters();
18  this->m_last_heartbeat_manual = ros::Time();
19  this->m_last_heartbeat_autonomous = ros::Time();
20  this->m_last_emergencystop = ros::Time();
21 }
22 
24 {
25  ros::Rate loop(this->m_update_frequency);
26  while (ros::ok())
27  {
28  this->publishDriveMode();
29  this->publishCommandEmergencyStop();
30  ros::spinOnce();
31  loop.sleep();
32  }
33 }
34 
35 DriveMode DMSController::getDriveMode()
36 {
37  if (this->m_mode_override != NO_OVERRIDE)
38  {
39  return this->m_mode_override;
40  }
41 
42  auto current_time = ros::Time::now();
43  if (this->m_last_heartbeat_manual + this->m_expiration_time > current_time &&
44  this->m_last_heartbeat_manual < current_time)
45  {
46  return DriveMode::MANUAL;
47  }
48  if (this->m_last_heartbeat_autonomous + this->m_expiration_time > current_time &&
49  this->m_last_heartbeat_autonomous < current_time)
50  {
51  return DriveMode::AUTONOMOUS;
52  }
53  return DriveMode::LOCKED;
54 }
55 
56 void DMSController::publishDriveMode()
57 {
58  std_msgs::Int32 drive_mode_message;
59  drive_mode_message.data = (int)this->getDriveMode();
60  this->m_drive_mode_publisher.publish(drive_mode_message);
61 }
62 
63 bool DMSController::getEmergencyStop()
64 {
65  auto current_time = ros::Time::now();
66  return (!this->m_last_emergencystop.is_zero() &&
67  this->m_last_emergencystop + this->m_emergencystop_expiration_time > current_time &&
68  this->m_last_emergencystop < current_time);
69 }
70 
71 void DMSController::publishCommandEmergencyStop()
72 {
73  std_msgs::Bool emergency_stop_message;
74  emergency_stop_message.data = this->getEmergencyStop();
75  this->m_command_emergencystop_publisher.publish(emergency_stop_message);
76 }
77 
78 void DMSController::heartbeatManualCallback(const std_msgs::Time::ConstPtr& message)
79 {
80  this->m_last_heartbeat_manual = message->data;
81 }
82 
83 void DMSController::heartbeatAutonomousCallback(const std_msgs::Time::ConstPtr& message)
84 {
85  this->m_last_heartbeat_autonomous = message->data;
86 }
87 
88 void DMSController::emergencystopCallback(const std_msgs::Time::ConstPtr& message)
89 {
90  this->m_last_emergencystop = message->data;
91 }
92 
93 void DMSController::configureParameters()
94 {
95  ros::NodeHandle private_node_handle("~");
96 
97  // configure check rate
98  private_node_handle.getParam(PARAMETER_DMS_CHECK_RATE, this->m_update_frequency);
99  if (this->m_update_frequency <= 0 || this->m_update_frequency > 1000)
100  {
101  ROS_WARN_STREAM("dms_check_rate should be between 0 and 1000. Your value: " << this->m_update_frequency
102  << ", using default: 20.");
103  this->m_update_frequency = 20;
104  }
105 
106  // configure dms exploration time
107  int expiration_ms;
108  private_node_handle.getParam(PARAMETER_DMS_EXPIRATION, expiration_ms);
109  if (expiration_ms <= 0 || expiration_ms > 1000)
110  {
111  ROS_WARN_STREAM("dms_expiration should be between 0 and 1000. Your value: " << expiration_ms
112  << ", using default: 100.");
113  expiration_ms = 100;
114  }
115  this->m_expiration_time = ros::Duration(expiration_ms / 1000.0);
116 
117  // configure emergency stop exploration time
118  int emergencystop_expiration_time;
119  private_node_handle.getParam(PARAMETER_EMERGENCYSTOP_EXPIRATION, emergencystop_expiration_time);
120  if (emergencystop_expiration_time <= 0 || emergencystop_expiration_time > 10000)
121  {
122  ROS_WARN_STREAM("emergencystop_expiration should be between 0 and 10000. Your value: "
123  << emergencystop_expiration_time << ", using default: 3000.");
124  emergencystop_expiration_time = 3000;
125  }
126  this->m_emergencystop_expiration_time = ros::Duration(emergencystop_expiration_time / 1000.0);
127 
128  // configure mode override parameter
129  int mode_override_parameter;
130  private_node_handle.getParam(PARAMETER_MODE_OVERRIDE, mode_override_parameter);
131 
132  this->m_mode_override = (DriveMode)mode_override_parameter;
133  if (this->m_mode_override != DriveMode::LOCKED && this->m_mode_override != DriveMode::MANUAL &&
134  this->m_mode_override != DriveMode::AUTONOMOUS)
135  {
136  ROS_WARN_STREAM("Invalid value for mode override.");
137  this->m_mode_override = NO_OVERRIDE;
138  }
139 
140  if (this->m_mode_override != NO_OVERRIDE)
141  {
142  ROS_WARN_STREAM("Drive Mode Override is enabled. The car will drive even if no key is pressed.");
143  }
144 }
145 
146 int main(int argc, char** argv)
147 {
148  ros::init(argc, argv, "dms_controller");
149  DMSController dmsController;
150  dmsController.spin();
151 
152  return EXIT_SUCCESS;
153 }
constexpr const char * TOPIC_DRIVE_MODE
int main(int argc, char **argv)
constexpr const char * TOPIC_HEARTBEAT_MANUAL
constexpr const char * PARAMETER_MODE_OVERRIDE
constexpr const char * TOPIC_HEARTBEAT_AUTONOMOUS
constexpr const char * TOPIC_EMERGENCYSTOP
constexpr const char * PARAMETER_EMERGENCYSTOP_EXPIRATION
constexpr const char * PARAMETER_DMS_CHECK_RATE
DriveMode
Definition: drive_mode.h:3
constexpr const char * PARAMETER_DMS_EXPIRATION
constexpr DriveMode NO_OVERRIDE
constexpr const char * TOPIC_COMMAND_EMERGENCYSTOP