Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
pacsim_main.cpp
Go to the documentation of this file.
1#include "rclcpp/rclcpp.hpp"
2#include <sstream>
3
4#include <chrono>
5#include <condition_variable>
6#include <limits>
7#include <mutex>
8#include <thread>
9#include <vector>
10
11#include "geometry_msgs/msg/transform_stamped.hpp"
12#include "rosgraph_msgs/msg/clock.h"
13#include <geometry_msgs/msg/twist_with_covariance_stamped.hpp>
14#include "custom_interfaces/msg/vehicle_state_vector.hpp"
15#include <sensor_msgs/msg/imu.hpp>
16#include <tf2/LinearMath/Quaternion.h>
17#include <tf2_ros/static_transform_broadcaster.h>
18#include <tf2_ros/transform_broadcaster.h>
19
21#include "configParser.hpp"
22#include "sensor_msgs/msg/joint_state.hpp"
23#include "visualization_msgs/msg/marker_array.hpp"
24
25#include "track/trackLoader.hpp"
26
27#include "logger.hpp"
32
34
35#include <rosgraph_msgs/msg/clock.hpp>
36
37#include "ros2Helpers.hpp"
38
39#include "pacsim/msg/perception_detections.hpp"
40#include "pacsim/msg/stamped_scalar.hpp"
41#include "pacsim/msg/wheels.hpp"
42#include "pacsim/srv/clock_trigger_absolute.hpp"
43#include "pacsim/srv/clock_trigger_relative.hpp"
44#include "types.hpp"
45
46#include "competitionLogic.hpp"
47
48#include "std_srvs/srv/empty.hpp"
49
50#include "reportWriter.hpp"
51
53
54#include "track/gripMap.hpp"
55
57void updateStateEstimation(const pacsim::msg::PerceptionDetections msg);
58
59// DynamicDoubleTrackModel7Dof model;
60std::shared_ptr<rclcpp::executors::SingleThreadedExecutor> executor;
61std::shared_ptr<IVehicleModel> model;
62std::string mapFilePrefix;
63double simTime = 0.0;
64rclcpp::Publisher<rosgraph_msgs::msg::Clock>::SharedPtr clockPub;
65rclcpp::Publisher<geometry_msgs::msg::TwistWithCovarianceStamped>::SharedPtr velocity_pub;
66rclcpp::Publisher<sensor_msgs::msg::Imu>::SharedPtr imu_pub;
67rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr mapVizPub;
68rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr simulatedSeVizPub;
69rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr stateEstimationPub;
70rclcpp::Publisher<pacsim::msg::StampedScalar>::SharedPtr steeringFrontPub;
71rclcpp::Publisher<pacsim::msg::StampedScalar>::SharedPtr steeringRearPub;
72rclcpp::Publisher<pacsim::msg::Wheels>::SharedPtr wheelspeedPub;
73rclcpp::Publisher<pacsim::msg::Wheels>::SharedPtr torquesPub;
74rclcpp::Publisher<pacsim::msg::StampedScalar>::SharedPtr voltageSensorTSPub;
75rclcpp::Publisher<pacsim::msg::StampedScalar>::SharedPtr currentSensorTSPub;
76rclcpp::Publisher<geometry_msgs::msg::TwistWithCovarianceStamped>::SharedPtr pose_pub;
77rclcpp::Publisher<custom_interfaces::msg::VehicleStateVector>::SharedPtr state_vector_pub;
78std::map<std::pair<double, double>, geometry_msgs::msg::Point> detected_cones_map;
79
80
81
82rclcpp::Publisher<sensor_msgs::msg::JointState>::SharedPtr jointStatePublisher;
83
84std::shared_ptr<tf2_ros::StaticTransformBroadcaster> tf_static_broadcaster_;
85
86rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr perceptionVizPub;
87std::vector<rclcpp::Publisher<pacsim::msg::PerceptionDetections>::SharedPtr> lms_pubs;
88std::map<std::shared_ptr<PerceptionSensor>, rclcpp::Publisher<pacsim::msg::PerceptionDetections>::SharedPtr>
90std::map<std::shared_ptr<PerceptionSensor>, std::shared_ptr<LandmarksMarkerWrapper>> perceptionSensorMarkersWrappersMap;
91std::map<std::shared_ptr<PerceptionSensor>, rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr>
93std::map<std::shared_ptr<ImuSensor>, rclcpp::Publisher<sensor_msgs::msg::Imu>::SharedPtr> imuPublisherMap;
94std::map<std::shared_ptr<GnssSensor>, rclcpp::Publisher<pacsim::msg::GNSS>::SharedPtr> gnssPublisherMap;
95
104
105std::mutex mutexSimTime;
106
107std::string trackName;
108std::string grip_map_path;
109std::string trackFrame;
110std::string report_file_dir;
115std::string discipline;
116std::vector<std::string> jointNames
117 = { "FL_steer", "FL_rotate", "FR_steer", "FR_rotate", "RR_rotate", "RL_rotate", "steering" };
118double realtimeRatio = 1.0;
120std::vector<std::shared_ptr<PerceptionSensor>> perceptionSensors;
121std::vector<std::shared_ptr<ImuSensor>> imus;
122std::vector<std::shared_ptr<GnssSensor>> gnssSensors;
123std::shared_ptr<CompetitionLogic> cl;
124
125std::shared_ptr<ImuSensor> imuSensor;
126std::shared_ptr<ScalarValueSensor> steeringSensorFront;
127std::shared_ptr<ScalarValueSensor> steeringSensorRear;
128std::shared_ptr<WheelsSensor> wheelspeedSensor;
129std::shared_ptr<WheelsSensor> torquesSensor;
130std::shared_ptr<ScalarValueSensor> currentSensorTS;
131std::shared_ptr<ScalarValueSensor> voltageSensorTS;
132
133std::shared_ptr<Logger> logger;
134
135std::condition_variable cvClockTrigger;
136double clockStopTime = std::numeric_limits<double>::max();
137
138int threadMainLoopFunc(std::shared_ptr<rclcpp::Node> node)
139{
140
141 std::unique_ptr<tf2_ros::TransformBroadcaster> br = std::make_unique<tf2_ros::TransformBroadcaster>(node);
142
143 const double targetLoopPeriod = 1.0 / 1000.0;
144 double egoMotionSensorRate = 200.0;
145 double lastEgoMotionSensorSampleTime = 0.0;
146 std::string framePerception = "perception";
147 std::string frameStateEstimation = "cog_static";
148
149 Eigen::Vector3d start_position;
150 Eigen::Vector3d start_orientation;
151 Track lms = loadMap(trackName, start_position, start_orientation);
152
153 model->setPosition(start_position);
154 model->setOrientation(start_orientation);
155
156 gripMap gm(logger);
158
160 {
161 lms = transformTrack(lms, start_position, start_orientation);
162 model->setPosition(Eigen::Vector3d::Zero());
163 model->setOrientation(Eigen::Vector3d::Zero());
164 gm.transformPoints(start_position, start_orientation);
165 start_position = Eigen::Vector3d::Zero();
166 start_orientation = Eigen::Vector3d::Zero();
167 }
168
169 LandmarkList trackAsLMList = trackToLMList(lms);
170
171 LandmarksMarkerWrapper mapMarkersWrapper(0.8, "pacsim");
172
173 visualization_msgs::msg::MarkerArray mapMarkerMsg = mapMarkersWrapper.markerFromLMs(lms, trackFrame, 0.0);
174 mapVizPub->publish(mapMarkerMsg);
175
184
185 double current_wheel_speed_angle = 0.0;
186
187 auto nextLoopTime = std::chrono::steady_clock::now();
188 auto lastLoopTime = nextLoopTime;
189
190 cl = std::make_shared<CompetitionLogic>(logger, lms, mainConfig);
191 bool finish = false;
192 std::mutex mtxClockTrigger;
193 std::unique_lock<std::mutex> lockClockTrigger(mtxClockTrigger);
194
195 while (rclcpp::ok() && !(finish))
196 {
197 auto loopStartTime = std::chrono::steady_clock::now();
198 double realDt = std::chrono::duration<double>(loopStartTime - lastLoopTime).count();
199 lastLoopTime = loopStartTime;
200 double dt = realDt * realtimeRatio;
201
202 rosgraph_msgs::msg::Clock clockMsg;
203 clockMsg.clock = rclcpp::Time(static_cast<uint64_t>(simTime * 1e9));
204 clockPub->publish(clockMsg);
205 auto wheelPositions = model->getWheelPositions();
206 Wheels gripValues = gm.getGripValues(wheelPositions);
207 model->forwardIntegrate(dt/* , gripValues */);
208 auto t = model->getPosition();
209 auto rEulerAngles = model->getOrientation();
210 auto alpha = model->getAngularAcceleration();
211 finish = cl->performAllChecks(lms, simTime, t, rEulerAngles);
212 // geometry_msgs::msg::TransformStamped static_transform = createStaticTransform("map", "center", simTime);
213 geometry_msgs::msg::TransformStamped transformStamped
214 = createRosTransformMsg(t, rEulerAngles, trackFrame, "car", simTime);
215 br->sendTransform(transformStamped);
216 geometry_msgs::msg::TwistWithCovarianceStamped poseStamped;
217 poseStamped.twist.twist.linear.x = t.x();
218 poseStamped.twist.twist.linear.y = t.y();
219 poseStamped.twist.twist.angular.z = rEulerAngles.z();
220 pose_pub->publish(poseStamped);
221
222 if (deadTimeSteeringFront.availableDeadTime(simTime))
223 {
224 double val = deadTimeSteeringFront.getOldest();
225 model->setSteeringSetpointFront(val);
226 }
227 if (deadTimeSteeringRear.availableDeadTime(simTime))
228 {
229 double val = deadTimeSteeringRear.getOldest();
230 model->setSteeringSetpointRear(val);
231 }
232 if (deadTimeTorques.availableDeadTime(simTime))
233 {
234 Wheels val = deadTimeTorques.getOldest();
235 model->setTorques(val);
236 }
237 if (deadTimeWspdSetpoints.availableDeadTime(simTime))
238 {
239 Wheels val = deadTimeWspdSetpoints.getOldest();
240 model->setRpmSetpoints(val);
241 }
242 if (deadTimeMaxTorques.availableDeadTime(simTime))
243 {
244 Wheels val = deadTimeMaxTorques.getOldest();
245 model->setMaxTorques(val);
246 }
247 if (deadTimeMinTorques.availableDeadTime(simTime))
248 {
249 Wheels val = deadTimeMinTorques.getOldest();
250 model->setMinTorques(val);
251 }
252 if (deadTimeThrottle.availableDeadTime(simTime))
253 {
254 Wheels val = deadTimeThrottle.getOldest();
255 model->setThrottle(val);
256 }
257 if (deadTimePowerGroundSetpoint.availableDeadTime(simTime))
258 {
259 double val = deadTimePowerGroundSetpoint.getOldest();
260 model->setPowerGroundSetpoint(val);
261 }
262
263 if (simTime >= (lastEgoMotionSensorSampleTime + 1 / egoMotionSensorRate))
264 {
265 lastEgoMotionSensorSampleTime += 1 / egoMotionSensorRate;
266
267 // Publish velocity
268 Eigen::Vector3d vel = model->getVelocity();
269 Eigen::Vector3d rot = model->getAngularVelocity();
270 geometry_msgs::msg::TwistWithCovarianceStamped velMsg = createRosTwistMsg(vel, rot, "car", simTime);
271 velocity_pub->publish(velMsg);
272
273 // Publish state vector
274 custom_interfaces::msg::VehicleStateVector msg;
275 msg.velocity_x = model->getVelocity().x();
276 msg.velocity_y = model->getVelocity().y();
277 msg.yaw_rate = model->getAngularVelocity().z();
278 msg.acceleration_x = model->getAcceleration().x();
279 msg.acceleration_y = model->getAcceleration().y();
280 // direção média dianteira
281 msg.steering_angle = 0.5 * (model->getSteeringAngles().FL + model->getSteeringAngles().FR);
282
283 msg.fl_rpm = model->getWheelspeeds().FL;
284 msg.fr_rpm = model->getWheelspeeds().FR;
285 msg.rl_rpm = model->getWheelspeeds().RL;
286 msg.rr_rpm = model->getWheelspeeds().RR;
287
288 msg.header.stamp = rclcpp::Time(static_cast<uint64_t>(simTime * 1e9));
289
290 state_vector_pub->publish(msg);
291
292 }
293
294 ImuData imuDataCog { model->getAcceleration(), model->getAngularVelocity(), Eigen::Matrix3d::Zero(),
295 Eigen::Matrix3d::Zero(), simTime, "" };
296 for (auto& imuSensor : imus)
297 {
298 if (imuSensor->RunTick(imuDataCog, alpha, simTime))
299 {
300 ImuData imuData = imuSensor->getOldest();
301 sensor_msgs::msg::Imu imuMsg = createRosImuMsg(imuData);
302 imuPublisherMap[imuSensor]->publish(imuMsg);
303 }
304 }
305 Wheels steeringCurr = model->getSteeringAngles();
306 double steeringWheelCurr = model->getSteeringWheelAngle();
307
308 StampedScalar steeringDataFront { (steeringCurr.FL + steeringCurr.FR) / 2, simTime };
309 // tire_positions for model
310
311 //
312 if (steeringSensorFront->RunTick(steeringDataFront, simTime))
313 {
314 StampedScalar steeringData = steeringSensorFront->getOldest();
315 pacsim::msg::StampedScalar msg;
316 msg.value = steeringData.data;
317 msg.stamp = rclcpp::Time(static_cast<uint64_t>(steeringData.timestamp * 1e9));
318 steeringFrontPub->publish(msg);
319 }
320 StampedScalar steeringDataRear { (steeringCurr.RL + steeringCurr.RR) * 0.5, simTime };
321 if (steeringSensorRear->RunTick(steeringDataRear, simTime))
322 {
323 StampedScalar steeringData = steeringSensorRear->getOldest();
324 pacsim::msg::StampedScalar msg;
325 msg.value = steeringData.data;
326 msg.stamp = rclcpp::Time(static_cast<uint64_t>(steeringData.timestamp * 1e9));
327 steeringRearPub->publish(msg);
328 }
329
330 double voltageTsCurr = model->getVoltageTS();
331 StampedScalar voltageTSData { voltageTsCurr, simTime };
332 if (voltageSensorTS->RunTick(voltageTSData, simTime))
333 {
334 StampedScalar voltageData = voltageSensorTS->getOldest();
335 pacsim::msg::StampedScalar msg;
336 msg.value = voltageData.data;
337 msg.stamp = rclcpp::Time(static_cast<uint64_t>(voltageData.timestamp * 1e9));
338 voltageSensorTSPub->publish(msg);
339 }
340
341 double currentTsCurr = model->getCurrentTS();
342 StampedScalar currentTSData { currentTsCurr, simTime };
343 if (currentSensorTS->RunTick(currentTSData, simTime))
344 {
345 StampedScalar currentData = currentSensorTS->getOldest();
346 pacsim::msg::StampedScalar msg;
347 msg.value = currentData.data;
348 msg.stamp = rclcpp::Time(static_cast<uint64_t>(currentData.timestamp * 1e9));
349 currentSensorTSPub->publish(msg);
350 }
351
352 for (auto& gnss : gnssSensors)
353 {
354
355 if (gnss->RunTick(lms.gnssOrigin, lms.enuToTrackRotation, t, rEulerAngles, simTime, model->getVelocity(),
356 model->getAngularVelocity(), start_position, start_orientation, mainConfig.pre_transform_track))
357 {
358 auto gnssData = gnss->getOldest();
359 auto gnssMsg = createRosGnssMessage(gnssData);
360 gnssPublisherMap[gnss]->publish(gnssMsg);
361 }
362 }
363
364 for (auto& perceptionSensor : perceptionSensors)
365 {
366 if (perceptionSensor->RunTick(trackAsLMList, t, rEulerAngles, simTime))
367 {
368 LandmarkList sensorLms = perceptionSensor->getOldest();
369 // TODO fix conversion hack
370 Track trackMsg = lmListToTrack(sensorLms);
371 visualization_msgs::msg::MarkerArray lmsMarkerMsg
372 = perceptionSensorMarkersWrappersMap[perceptionSensor]->markerFromLMs(
373 trackMsg, sensorLms.frame_id, sensorLms.timestamp);
374 perceptionSensorVizPublisherMap[perceptionSensor]->publish(lmsMarkerMsg);
375
376 mapVizPub->publish(mapMarkerMsg);
378
379 pacsim::msg::PerceptionDetections lmsMsg
380 = LandmarkListToRosMessage(sensorLms, sensorLms.frame_id, sensorLms.timestamp);
381 perceptionSensorPublisherMap[perceptionSensor]->publish(lmsMsg);
382 updateStateEstimation(lmsMsg);
383 }
384 }
385
386 Wheels wspd = model->getWheelspeeds();
387 Wheels torques = model->getTorques();
388 wspd.timestamp = simTime;
389 torques.timestamp = simTime;
390 Wheels orientation = model->getWheelOrientations();
391 if (wheelspeedSensor->RunTick(wspd, t, rEulerAngles, simTime))
392 {
393 wspd = wheelspeedSensor->getOldest();
394 pacsim::msg::Wheels wspdMsg;
395 wspdMsg.fl = wspd.FL;
396 wspdMsg.fr = wspd.FR;
397 wspdMsg.rl = wspd.RL;
398 wspdMsg.rr = wspd.RR;
399 wspdMsg.stamp = rclcpp::Time(static_cast<uint64_t>(wspd.timestamp * 1e9));
400 wheelspeedPub->publish(wspdMsg);
401 }
402 if (torquesSensor->RunTick(torques, t, rEulerAngles, simTime))
403 {
404 torques = torquesSensor->getOldest();
405 pacsim::msg::Wheels torquesMsg;
406 torquesMsg.fl = torques.FL;
407 torquesMsg.fr = torques.FR;
408 torquesMsg.rl = torques.RL;
409 torquesMsg.rr = torques.RR;
410 torquesMsg.stamp = rclcpp::Time(static_cast<uint64_t>(torques.timestamp * 1e9));
411 torquesPub->publish(torquesMsg);
412 }
413
414 std::vector<double> jointMsg = { steeringCurr.FL, orientation.FL, steeringCurr.FR, orientation.FR,
415 orientation.RR, orientation.RL, -steeringWheelCurr };
416 sensor_msgs::msg::JointState jointStamped = createRosJointMsg(jointNames, jointMsg, simTime);
417 jointStatePublisher->publish(jointStamped);
418 mutexSimTime.lock();
419 simTime += dt;
420 mutexSimTime.unlock();
421 if (simTime >= clockStopTime)
422 {
423 cvClockTrigger.wait(lockClockTrigger);
424 nextLoopTime = std::chrono::steady_clock::now();
425 lastLoopTime = nextLoopTime;
426 }
427 nextLoopTime += std::chrono::microseconds((int)((targetLoopPeriod / realtimeRatio) * 1000000.0));
428 std::this_thread::sleep_until(nextLoopTime);
429 }
430 logger->logWarning("Ros status, 1 is OK, 0 is not OK: " + to_string(rclcpp::ok()));
431 logger->logWarning("Simulation finished, generating report");
432 Report report;
433 cl->fillReport(report, simTime);
434 report.track_name = trackName;
436 logger->logWarning("Canceling executor!");
437 executor->cancel();
438 return 0;
439}
440
441void cbFuncLat(const pacsim::msg::StampedScalar& msg)
442{
443 std::lock_guard<std::mutex> l(mutexSimTime);
444 deadTimeSteeringFront.addVal(msg.value, simTime);
445 deadTimeSteeringRear.addVal(0.0, simTime);
446}
447
448void cbFuncLong(const pacsim::msg::Wheels& msg)
449{
450 std::lock_guard<std::mutex> l(mutexSimTime);
451 Wheels w;
452 w.FL = msg.fl;
453 w.FR = msg.fr;
454 w.RL = msg.rl;
455 w.RR = msg.rr;
456 w.timestamp = simTime;
457 deadTimeThrottle.addVal(w, simTime);
458}
459
460void cbFuncTorquesInverterMin(const pacsim::msg::Wheels& msg)
461{
462 std::lock_guard<std::mutex> l(mutexSimTime);
463 Wheels min;
464 min.FL = msg.fl;
465 min.FR = msg.fr;
466 min.RL = msg.rl;
467 min.RR = msg.rr;
468 deadTimeMinTorques.addVal(min, simTime);
469}
470
471void cbFuncTorquesInverterMax(const pacsim::msg::Wheels& msg)
472{
473 std::lock_guard<std::mutex> l(mutexSimTime);
474 Wheels max;
475 max.FL = msg.fl;
476 max.FR = msg.fr;
477 max.RL = msg.rl;
478 max.RR = msg.rr;
479 deadTimeMaxTorques.addVal(max, simTime);
480}
481
482void cbWheelspeeds(const pacsim::msg::Wheels& msg)
483{
484 std::lock_guard<std::mutex> l(mutexSimTime);
485 Wheels w { msg.fl, msg.fr, msg.rl, msg.rr };
487}
488
489void cbPowerGround(const pacsim::msg::StampedScalar& msg)
490{
491 std::lock_guard<std::mutex> l(mutexSimTime);
492 deadTimePowerGroundSetpoint.addVal(msg.value, simTime);
493}
494
495void cbFinishSignal(const std::shared_ptr<std_srvs::srv::Empty::Request> request,
496 std::shared_ptr<std_srvs::srv::Empty::Response> response)
497{
498 cl->setFinish(true);
499}
500
501void cbClockTriggerAbsolute(const std::shared_ptr<pacsim::srv::ClockTriggerAbsolute::Request> request,
502 std::shared_ptr<pacsim::srv::ClockTriggerAbsolute::Response> response)
503{
504 std::lock_guard<std::mutex> l(mutexSimTime);
505 clockStopTime = rclcpp::Time(request->stop_time).seconds();
506 response->already_past = (clockStopTime < simTime);
507 cvClockTrigger.notify_all();
508}
509
510void cbClockTriggerRelative(const std::shared_ptr<pacsim::srv::ClockTriggerRelative::Request> request,
511 std::shared_ptr<pacsim::srv::ClockTriggerRelative::Response> response)
512{
513 std::lock_guard<std::mutex> l(mutexSimTime);
514 clockStopTime = simTime + rclcpp::Duration(request->runtime).seconds();
515 response->stop_time = rclcpp::Time(static_cast<uint64_t>(clockStopTime * 1e9));
516 cvClockTrigger.notify_all();
517}
518void getRos2Params(rclcpp::Node::SharedPtr& node)
519{
520 std::vector<std::pair<std::string, std::string*>> params;
521 params.push_back({ "track_name", &trackName });
522 params.push_back({ "grip_map_path", &grip_map_path });
523 params.push_back({ "track_frame", &trackFrame });
524 params.push_back({ "report_file_dir", &report_file_dir });
525 params.push_back({ "main_config_path", &main_config_path });
526 params.push_back({ "perception_config_path", &perception_config_path });
527 params.push_back({ "sensors_config_path", &sensors_config_path });
528 params.push_back({ "vehicle_model_config_path", &vehicle_model_config_path });
529 params.push_back({ "discipline", &discipline });
530
531 for (auto p : params)
532 {
533 node->declare_parameter(std::string(p.first), rclcpp::PARAMETER_STRING);
534 (*p.second) = node->get_parameter(std::string(p.first)).as_string();
535 }
536
537 node->declare_parameter("realtime_ratio", rclcpp::PARAMETER_DOUBLE);
538 node->get_parameter("realtime_ratio", realtimeRatio);
539}
540
542{
544 auto perceptionSensorsConfig = cfg.getElement("perception_sensors");
545 std::vector<ConfigElement> sensors;
546 perceptionSensorsConfig.getElements(&sensors);
547 for (auto& sensor : sensors)
548 {
549 std::shared_ptr<PerceptionSensor> perceptionSensor = std::make_shared<PerceptionSensor>();
550 perceptionSensor->readConfig(sensor);
551 perceptionSensors.push_back(perceptionSensor);
552 }
553 return;
554}
555
556void updateStateEstimation(const pacsim::msg::PerceptionDetections msg)
557{
558 std::lock_guard<std::mutex> lock(mutexSimTime); // Ensure thread safety
559
560 // Get vehicle position and orientation from the model
561 Eigen::Vector3d vehicle_position = model->getPosition();
562 Eigen::Vector3d vehicle_orientation = model->getOrientation();
563
564 double yaw = vehicle_orientation.z(); // Extract yaw (rotation around Z-axis)
565
566 // Create 2D rotation matrix for transforming perception detections
567 Eigen::Matrix2d rotation_matrix;
568 rotation_matrix << cos(yaw), -sin(yaw),
569 sin(yaw), cos(yaw);
570
571 // Set duplicate removal threshold (meters)
572 const double epsilon = 2.5; // Ignore detections closer than 30cm to existing cones
573
574 for (const auto& detection : msg.detections)
575 {
576 // Get detected point in vehicle frame
577 Eigen::Vector2d local_point(detection.pose.pose.position.x, detection.pose.pose.position.y);
578
579 // Transform to map frame
580 Eigen::Vector2d global_point = rotation_matrix * local_point;
581 global_point += vehicle_position.head<2>(); // Apply translation
582
583 // Check if a cone already exists nearby
584 bool is_duplicate = false;
585 for (const auto& existing_cone : detected_cones_map)
586 {
587 double dist = std::hypot(global_point.x() - existing_cone.first.first,
588 global_point.y() - existing_cone.first.second);
589 if (dist < epsilon)
590 {
591 is_duplicate = true;
592 break;
593 }
594 }
595
596 if (!is_duplicate)
597 {
598 // Round positions to avoid tiny variations (grid-based key system)
599 double rounded_x = std::round(global_point.x() * 100.0) / 100.0; // Round to 2 decimal places
600 double rounded_y = std::round(global_point.y() * 100.0) / 100.0;
601
602 std::pair<double, double> key = {rounded_x, rounded_y};
603 geometry_msgs::msg::Point point;
604 point.x = global_point.x();
605 point.y = global_point.y();
606 point.z = detection.pose.pose.position.z; // Keep Z as detected
607
608 detected_cones_map[key] = point;
609 }
610 }
611}
612
613
615{
616 visualization_msgs::msg::MarkerArray marker_array;
617 int id = 0; // Unique ID for each marker
618
619 for (const auto& entry : detected_cones_map)
620 {
621 visualization_msgs::msg::Marker marker;
622 marker.header.frame_id = "map"; // Map reference frame
623 marker.header.stamp = rclcpp::Time(simTime * 1e9);
624 marker.ns = "seen_cones";
625 marker.id = id++; // Assign unique ID
626 marker.type = visualization_msgs::msg::Marker::SPHERE;
627 marker.action = visualization_msgs::msg::Marker::ADD;
628 marker.pose.position = entry.second;
629 marker.pose.orientation.w = 1.0;
630
631 // Marker Size
632 marker.scale.x = 0.2; // Adjust based on cone size
633 marker.scale.y = 0.2;
634 marker.scale.z = 0.2;
635
636 // Marker Color (e.g., Orange for cones)
637 marker.color.a = 1.0;
638 marker.color.r = 1.0;
639 marker.color.g = 0.5;
640 marker.color.b = 0.0;
641 marker_array.markers.push_back(marker);
642 }
643
644 stateEstimationPub->publish(marker_array); // Publish all seen cones
645}
646
647
649{
651 auto sensorsConfig = cfg.getElement("sensors");
652
653 auto gnssConfigs = sensorsConfig.getElement("gnssSensors");
654 std::vector<ConfigElement> gnssSensorConfigs;
655 gnssConfigs.getElements(&gnssSensorConfigs);
656 for (auto& sensor : gnssSensorConfigs)
657 {
658 std::shared_ptr<GnssSensor> gnssSensor = std::make_shared<GnssSensor>();
659 gnssSensor->readConfig(sensor);
660 gnssSensors.push_back(gnssSensor);
661 }
662
663 auto imuConfigs = sensorsConfig.getElement("imus");
664 std::vector<ConfigElement> sensors;
665 imuConfigs.getElements(&sensors);
666 for (auto& sensor : sensors)
667 {
668 std::shared_ptr<ImuSensor> imuSensor = std::make_shared<ImuSensor>(200.0, 0.002);
669 imuSensor->readConfig(sensor);
670 imus.push_back(imuSensor);
671 }
672 steeringSensorFront = std::make_shared<ScalarValueSensor>(200.0, 0.005);
673 auto frontSteeringConfig = sensorsConfig.getElement("steering_front");
674 steeringSensorFront->readConfig(frontSteeringConfig);
675 steeringSensorRear = std::make_shared<ScalarValueSensor>(200.0, 0.005);
676 auto rearSteeringConfig = sensorsConfig.getElement("steering_front");
677 steeringSensorRear->readConfig(rearSteeringConfig);
678 auto wheelSpeedConfig = sensorsConfig.getElement("wheelspeeds");
679 wheelspeedSensor = std::make_shared<WheelsSensor>(200.0, 0.005);
680 wheelspeedSensor->readConfig(wheelSpeedConfig);
681
682 voltageSensorTS = std::make_shared<ScalarValueSensor>(200.0, 0.005);
683 auto voltageTSConfig = sensorsConfig.getElement("voltage_ts");
684 voltageSensorTS->readConfig(voltageTSConfig);
685 currentSensorTS = std::make_shared<ScalarValueSensor>(200.0, 0.005);
686 auto currentTSConfig = sensorsConfig.getElement("current_ts");
687 currentSensorTS->readConfig(currentTSConfig);
688
689 auto torquesConfig = sensorsConfig.getElement("wheelspeeds");
690 torquesSensor = std::make_shared<WheelsSensor>(200.0, 0.005);
691 torquesSensor->readConfig(torquesConfig);
692}
693
694MainConfig fillMainConfig(std::string path)
695{
696 MainConfig ret;
697 Config cfg(path);
698 ConfigElement config = cfg.getElement("pacsim");
699 config["timeouts"].getElement<double>(&ret.timeout_start, "start");
700 config["timeouts"].getElement<double>(&ret.timeout_acceleration, "acceleration");
701 config["timeouts"].getElement<double>(&ret.timeout_autocross, "autocross");
702 config["timeouts"].getElement<double>(&ret.timeout_skidpad, "skidpad");
703 config["timeouts"].getElement<double>(&ret.timeout_trackdrive_first, "trackdrive_first");
704 config["timeouts"].getElement<double>(&ret.timeout_trackdrive_total, "trackdrive_total");
705
706 config.getElement<std::string>(&ret.cog_frame_id_pipeline, "cog_frame_id_pipeline");
707 config.getElement<bool>(&ret.broadcast_sensors_tf2, "broadcast_sensors_tf2");
708
709 config.getElement<bool>(&ret.oc_detect, "oc_detect");
710 config.getElement<bool>(&ret.doo_detect, "doo_detect");
711 config.getElement<bool>(&ret.uss_detect, "uss_detect");
712 config.getElement<bool>(&ret.finish_validate, "finish_validate");
713
714 config.getElement<bool>(&ret.pre_transform_track, "pre_transform_track");
715
717 return ret;
718}
719
721{
723 {
724
725 for (auto sensor : perceptionSensors)
726 {
727 geometry_msgs::msg::TransformStamped t;
728
729 t.header.stamp = rclcpp::Time(0, 0);
730 t.header.frame_id = mainConfig.cog_frame_id_pipeline;
731 t.child_frame_id = sensor->getFrameId();
732
733 auto translation = sensor->getPosition();
734 auto orientation = sensor->getOrientation();
735 t.transform.translation.x = translation.x();
736 t.transform.translation.y = translation.y();
737 t.transform.translation.z = translation.z();
738 tf2::Quaternion q;
739 q.setRPY(orientation.x(), orientation.y(), orientation.z());
740 t.transform.rotation.x = q.x();
741 t.transform.rotation.y = q.y();
742 t.transform.rotation.z = q.z();
743 t.transform.rotation.w = q.w();
744
745 tf_static_broadcaster_->sendTransform(t);
746 }
747 }
748}
749
750int main(int argc, char** argv)
751{
752 rclcpp::init(argc, argv);
753 auto node = std::make_shared<rclcpp::Node>("pacsim_node");
754 tf_static_broadcaster_ = std::make_shared<tf2_ros::StaticTransformBroadcaster>(node);
755 logger = std::make_shared<Logger>();
756
757 auto latsub = node->create_subscription<pacsim::msg::StampedScalar>("/pacsim/steering_setpoint", 1, cbFuncLat);
758 auto torquessubmin
759 = node->create_subscription<pacsim::msg::Wheels>("/pacsim/torques_min", 1, cbFuncTorquesInverterMin);
760 auto torquessubmax
761 = node->create_subscription<pacsim::msg::Wheels>("/pacsim/torques_max", 1, cbFuncTorquesInverterMax);
762
763 auto throttleSub = node->create_subscription<pacsim::msg::Wheels>("/pacsim/throttle_setpoint", 1, cbFuncLong);
764 RCLCPP_INFO_STREAM(rclcpp::get_logger("pacsim_logger"), "Created subscription for throttle (Wheels)");
765
766
767 auto wspdSetpointSub
768 = node->create_subscription<pacsim::msg::Wheels>("/pacsim/wheelspeed_setpoints", 1, cbWheelspeeds);
769
770 auto powerGroundSetpointSub
771 = node->create_subscription<pacsim::msg::StampedScalar>("/pacsim/powerground_setpoint", 1, cbPowerGround);
772
773 velocity_pub = node->create_publisher<geometry_msgs::msg::TwistWithCovarianceStamped>("/pacsim/velocity", 3);
774
776 = node->create_publisher<custom_interfaces::msg::VehicleStateVector>("/pacsim/state_vector", 3);
777
778 pose_pub = node->create_publisher<geometry_msgs::msg::TwistWithCovarianceStamped>("/pacsim/pose", 3);
779
780 clockPub = node->create_publisher<rosgraph_msgs::msg::Clock>("/clock", 1);
781
782 mapVizPub = node->create_publisher<visualization_msgs::msg::MarkerArray>("/pacsim/map", 1);
783
784 simulatedSeVizPub = node->create_publisher<visualization_msgs::msg::MarkerArray>("/pacsim/state_estimation", 1);
785
786 auto finishSignalServer = node->create_service<std_srvs::srv::Empty>("/pacsim/finish_signal", cbFinishSignal);
787 auto clockTriggerAbsoluteServer = node->create_service<pacsim::srv::ClockTriggerAbsolute>(
788 "/pacsim/clock_trigger/absolute", cbClockTriggerAbsolute);
789 auto clockTriggerRelativeServer = node->create_service<pacsim::srv::ClockTriggerRelative>(
790 "/pacsim/clock_trigger/relative", cbClockTriggerRelative);
791
792 stateEstimationPub = node->create_publisher<visualization_msgs::msg::MarkerArray>("/pacsim/state_estimation", 1);
793
794
795 getRos2Params(node);
798 initSensors();
800 for (auto& i : perceptionSensors)
801 {
802 auto detectionsMarkersWrapper = std::make_shared<LandmarksMarkerWrapper>(0.8, "pacsim/" + i->getName());
803 auto pub = node->create_publisher<pacsim::msg::PerceptionDetections>(
804 "/pacsim/perception/" + i->getName() + "/landmarks", 1);
805 auto pubViz = node->create_publisher<visualization_msgs::msg::MarkerArray>(
806 "/pacsim/perception/" + i->getName() + "/visualization", 1);
807 lms_pubs.push_back(pub);
809 perceptionSensorMarkersWrappersMap[i] = detectionsMarkersWrapper;
811 pubViz->publish(detectionsMarkersWrapper->deleteAllMsg(i->getFrameId()));
812 }
813 for (auto& i : imus)
814 {
815 auto pub = node->create_publisher<sensor_msgs::msg::Imu>("/pacsim/imu/" + i->getName(), 3);
816 imuPublisherMap[i] = pub;
817 }
818 for (auto& i : gnssSensors)
819 {
820 auto pub = node->create_publisher<pacsim::msg::GNSS>("/pacsim/gnss/" + i->getName(), 3);
821 gnssPublisherMap[i] = pub;
822 }
823
824 steeringFrontPub = node->create_publisher<pacsim::msg::StampedScalar>("/pacsim/steeringFront", 1);
825 steeringRearPub = node->create_publisher<pacsim::msg::StampedScalar>("/pacsim/steeringRear", 1);
826 voltageSensorTSPub = node->create_publisher<pacsim::msg::StampedScalar>("/pacsim/ts/voltage", 1);
827 currentSensorTSPub = node->create_publisher<pacsim::msg::StampedScalar>("/pacsim/ts/current", 1);
828
829 wheelspeedPub = node->create_publisher<pacsim::msg::Wheels>("/pacsim/wheelspeeds", 1);
830 torquesPub = node->create_publisher<pacsim::msg::Wheels>("/pacsim/torques", 1);
831
832 jointStatePublisher = node->create_publisher<sensor_msgs::msg::JointState>("/joint_states", 3);
833
834 model = std::make_shared<VehicleModelBicycle>();
836 auto configVehicleModel = modelConfig.getElement("vehicle_model");
837 model->readConfig(configVehicleModel);
838
839 std::thread mainLoopThread(threadMainLoopFunc, std::ref(node));
840 logger->logInfo("Started pacsim");
841 executor = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
842 executor->add_node(node);
843 executor->spin();
844
845 mainLoopThread.join();
846 logger->logWarning("Finished pacsim");
847 rclcpp::shutdown();
848
849 return 0;
850}
ConfigElement getElement(string elementName)
vector< ConfigElement > getElements()
visualization_msgs::msg::MarkerArray markerFromLMs(Track &in, std::string frame, double time)
Wheels getGripValues(std::array< Eigen::Vector3d, 4 > in)
Definition gripMap.cpp:32
void transformPoints(Eigen::Vector3d trans, Eigen::Vector3d rot)
Definition gripMap.cpp:53
void loadConfig(std::string path)
Definition gripMap.cpp:5
Definition main.py:1
std::map< std::shared_ptr< PerceptionSensor >, std::shared_ptr< LandmarksMarkerWrapper > > perceptionSensorMarkersWrappersMap
void cbFuncLong(const pacsim::msg::Wheels &msg)
rclcpp::Publisher< pacsim::msg::Wheels >::SharedPtr wheelspeedPub
void cbFuncLat(const pacsim::msg::StampedScalar &msg)
void cbWheelspeeds(const pacsim::msg::Wheels &msg)
std::string perception_config_path
std::string report_file_dir
std::map< std::shared_ptr< GnssSensor >, rclcpp::Publisher< pacsim::msg::GNSS >::SharedPtr > gnssPublisherMap
std::string discipline
void cbFuncTorquesInverterMin(const pacsim::msg::Wheels &msg)
void initSensors()
std::shared_ptr< tf2_ros::StaticTransformBroadcaster > tf_static_broadcaster_
std::map< std::pair< double, double >, geometry_msgs::msg::Point > detected_cones_map
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr simulatedSeVizPub
std::shared_ptr< ScalarValueSensor > voltageSensorTS
DeadTime< double > deadTimeSteeringFront(0.0)
void handleTf2StaticTransforms()
std::shared_ptr< ScalarValueSensor > currentSensorTS
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr perceptionVizPub
DeadTime< Wheels > deadTimeMinTorques(0.0)
std::map< std::shared_ptr< PerceptionSensor >, rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr > perceptionSensorVizPublisherMap
DeadTime< double > deadTimeSteeringRear(0.0)
std::shared_ptr< WheelsSensor > wheelspeedSensor
std::mutex mutexSimTime
std::vector< std::shared_ptr< GnssSensor > > gnssSensors
std::vector< std::string > jointNames
DeadTime< Wheels > deadTimeThrottle(0.0)
DeadTime< double > deadTimePowerGroundSetpoint(0.0)
rclcpp::Publisher< geometry_msgs::msg::TwistWithCovarianceStamped >::SharedPtr velocity_pub
rclcpp::Publisher< sensor_msgs::msg::Imu >::SharedPtr imu_pub
double realtimeRatio
std::string grip_map_path
std::vector< rclcpp::Publisher< pacsim::msg::PerceptionDetections >::SharedPtr > lms_pubs
void publishStateEstimation()
std::shared_ptr< ImuSensor > imuSensor
void cbClockTriggerRelative(const std::shared_ptr< pacsim::srv::ClockTriggerRelative::Request > request, std::shared_ptr< pacsim::srv::ClockTriggerRelative::Response > response)
std::map< std::shared_ptr< ImuSensor >, rclcpp::Publisher< sensor_msgs::msg::Imu >::SharedPtr > imuPublisherMap
std::string trackName
rclcpp::Publisher< geometry_msgs::msg::TwistWithCovarianceStamped >::SharedPtr pose_pub
std::condition_variable cvClockTrigger
std::string main_config_path
std::shared_ptr< ScalarValueSensor > steeringSensorRear
void cbFuncTorquesInverterMax(const pacsim::msg::Wheels &msg)
double simTime
rclcpp::Publisher< pacsim::msg::StampedScalar >::SharedPtr currentSensorTSPub
std::vector< std::shared_ptr< ImuSensor > > imus
MainConfig mainConfig
rclcpp::Publisher< custom_interfaces::msg::VehicleStateVector >::SharedPtr state_vector_pub
double clockStopTime
std::shared_ptr< Logger > logger
std::map< std::shared_ptr< PerceptionSensor >, rclcpp::Publisher< pacsim::msg::PerceptionDetections >::SharedPtr > perceptionSensorPublisherMap
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr stateEstimationPub
std::string trackFrame
std::vector< std::shared_ptr< PerceptionSensor > > perceptionSensors
rclcpp::Publisher< pacsim::msg::Wheels >::SharedPtr torquesPub
void updateStateEstimation(const pacsim::msg::PerceptionDetections msg)
std::shared_ptr< CompetitionLogic > cl
rclcpp::Publisher< pacsim::msg::StampedScalar >::SharedPtr steeringRearPub
MainConfig fillMainConfig(std::string path)
std::shared_ptr< WheelsSensor > torquesSensor
DeadTime< Wheels > deadTimeMaxTorques(0.0)
std::shared_ptr< rclcpp::executors::SingleThreadedExecutor > executor
void cbFinishSignal(const std::shared_ptr< std_srvs::srv::Empty::Request > request, std::shared_ptr< std_srvs::srv::Empty::Response > response)
void getRos2Params(rclcpp::Node::SharedPtr &node)
void initPerceptionSensors()
rclcpp::Publisher< pacsim::msg::StampedScalar >::SharedPtr steeringFrontPub
int threadMainLoopFunc(std::shared_ptr< rclcpp::Node > node)
DeadTime< Wheels > deadTimeTorques(0.0)
rclcpp::Publisher< sensor_msgs::msg::JointState >::SharedPtr jointStatePublisher
rclcpp::Publisher< pacsim::msg::StampedScalar >::SharedPtr voltageSensorTSPub
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr mapVizPub
void cbClockTriggerAbsolute(const std::shared_ptr< pacsim::srv::ClockTriggerAbsolute::Request > request, std::shared_ptr< pacsim::srv::ClockTriggerAbsolute::Response > response)
std::string mapFilePrefix
void cbPowerGround(const pacsim::msg::StampedScalar &msg)
std::string sensors_config_path
DeadTime< Wheels > deadTimeWspdSetpoints(0.0)
std::shared_ptr< IVehicleModel > model
rclcpp::Publisher< rosgraph_msgs::msg::Clock >::SharedPtr clockPub
std::string vehicle_model_config_path
std::shared_ptr< ScalarValueSensor > steeringSensorFront
bool reportToFile(Report report, std::string dir)
geometry_msgs::msg::TwistWithCovarianceStamped createRosTwistMsg(const Eigen::Vector3d &vel, const Eigen::Vector3d &rot, const std::string &frame, double time)
pacsim::msg::PerceptionDetections LandmarkListToRosMessage(const LandmarkList &sensorLms, std::string frameId, double time)
sensor_msgs::msg::Imu createRosImuMsg(const ImuData &data)
sensor_msgs::msg::JointState createRosJointMsg(const std::vector< std::string > &joint_names, const std::vector< double > &joint_vals, double time)
geometry_msgs::msg::TransformStamped createRosTransformMsg(const Eigen::Vector3d &trans, const Eigen::Vector3d &rot, const std::string &frame, const std::string &child_frame, double time)
pacsim::msg::GNSS createRosGnssMessage(const GnssData &data)
double timestamp
Definition types.hpp:56
std::string frame_id
Definition types.hpp:55
double timeout_skidpad
Definition types.hpp:184
double timeout_acceleration
Definition types.hpp:182
double timeout_autocross
Definition types.hpp:183
double timeout_start
Definition types.hpp:181
Discipline discipline
Definition types.hpp:191
bool oc_detect
Definition types.hpp:187
bool broadcast_sensors_tf2
Definition types.hpp:193
bool finish_validate
Definition types.hpp:190
double timeout_trackdrive_first
Definition types.hpp:185
bool doo_detect
Definition types.hpp:188
bool pre_transform_track
Definition types.hpp:194
double timeout_trackdrive_total
Definition types.hpp:186
bool uss_detect
Definition types.hpp:189
std::string cog_frame_id_pipeline
Definition types.hpp:192
std::string track_name
Definition types.hpp:132
double timestamp
Definition types.hpp:126
double data
Definition types.hpp:124
Eigen::Vector3d enuToTrackRotation
Definition types.hpp:47
Eigen::Vector3d gnssOrigin
Definition types.hpp:46
double RL
Definition types.hpp:77
double FL
Definition types.hpp:75
double FR
Definition types.hpp:76
double RR
Definition types.hpp:78
double timestamp
Definition types.hpp:80
Track loadMap(std::string mapPath, Eigen::Vector3d &start_position, Eigen::Vector3d &start_orientation)
Track transformTrack(Track &in, Eigen::Vector3d trans, Eigen::Vector3d rot)
Definition transform.cpp:52
Discipline stringToDiscipline(const std::string &disciplineStr)
Definition types.cpp:63
Track lmListToTrack(LandmarkList &in)
Definition types.cpp:53
LandmarkList trackToLMList(Track &in)
Definition types.cpp:33