0% found this document useful (0 votes)
30 views4 pages

Give A Quick Summary On What Each Part of This Code Does and Its Expected Outcomes

The code processes laser scan data to detect objects. It includes headers for threading and callbacks. Key functions count the number of readings and detected objects, identify segments representing cones or obstacles, and compute the closest cone and road center point. Mutexes and callbacks synchronize access to shared data during parallel processing of scans.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views4 pages

Give A Quick Summary On What Each Part of This Code Does and Its Expected Outcomes

The code processes laser scan data to detect objects. It includes headers for threading and callbacks. Key functions count the number of readings and detected objects, identify segments representing cones or obstacles, and compute the closest cone and road center point. Mutexes and callbacks synchronize access to shared data during parallel processing of scans.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 4

Give a quick summary on what each part of this code does and its expected outcomes.

include
information about the mutexs and callbacks and what these link too. #include "laserprocessing.h"
#include <algorithm> #include <numeric> #include <thread> #include <mutex> #include
<condition_variable> using namespace std;
LaserProcessing::LaserProcessing(sensor_msgs::LaserScan laserScan): laserScan_(laserScan) { }
unsigned int LaserProcessing::countObjectReadings(){ //This function computes the amount of
objects unsigned int count=0; for (unsigned int i = 0; i < laserScan_.ranges.size(); ++i) { if
((laserScan_.ranges.at(i) > laserScan_.range_min) && (laserScan_.ranges.at(i) <
laserScan_.range_max) && !isnan(laserScan_.ranges.at(i)) && isfinite(laserScan_.ranges.at(i)))
{ count++; } } return count; } int LaserProcessing::countSegments() //This function detects the
cones and stores them into a vector of pairs. If the object detected is larger than a cone, a flag is
sent and the stopMission() function is called. { unsigned int count=0; if (cones_.size() > 0) { return
cones_.size(); } unsigned int i = 1; while (i < laserScan_.ranges.size()) { bool countFlag = true; bool
init = false; unsigned int st = i, en = i; double distance = 0; if (isinf(laserScan_.ranges.at(i - 1))) { i+
+; continue; } if (laserScan_.ranges.at(i -1) != laserScan_.ranges.at(i - 1)) { i++; continue; } while
(countFlag && i < laserScan_.ranges.size()) { if (isinf(laserScan_.ranges.at(i))) { countFlag = false; }
else { geometry_msgs::Point prev; float prevAngle = laserScan_.angle_min +
laserScan_.angle_increment * (i -1); prev.x = laserScan_.ranges.at(i - 1) * cos(prevAngle); prev.y =
laserScan_.ranges.at(i - 1) * sin(prevAngle); prev.z = 0; geometry_msgs::Point curr; float currAngle
= laserScan_.angle_min + laserScan_.angle_increment * i; curr.x = laserScan_.ranges.at(i) *
cos(currAngle); curr.y = laserScan_.ranges.at(i) * sin(currAngle); curr.z = 0; distance =
sqrt(pow(curr.x - prev.x, 2) + pow(curr.y - prev.y, 2)); if (distance < 0.3) { if (!init) { st = i; init = true;
} } else if(distance > 0.3 && distance < 2){ //the comparison of the distance between two flags
being 0.3 < distance < 2 means the flag is only activated if two points are taller than the cone
height ROS_INFO("Foreign Object Detected. Stopping mission."); return -1; // -1 count returns the
flag to the run function so that the stopMisson function can be called } else { countFlag = false; } }
if (!countFlag) { en = i; } i++; } if (st != en) { count++; double xC = 0, yC = 0; for (unsigned j = st; j
< en; j++) { float angle = laserScan_.angle_min + laserScan_.angle_increment * (j -1); xC +=
laserScan_.ranges.at(j - 1) * cos(angle); yC += laserScan_.ranges.at(j - 1) * sin(angle); // distance to
the point is converted to coordinates with trigonometry } xC = xC / (en - st); yC = yC / (en - st);
cones_.push_back(std::make_pair(xC, yC)); } } return count; } geometry_msgs::Point
LaserProcessing::detectClosestCone(){ //This function searches the cones_ vector, populated from
countSegments(), for the closest cone. geometry_msgs::Point point; unsigned int count =
countSegments(); if (count == 0) { return {}; } double dclosest = laserScan_.range_max; unsigned
int idx = 0, i = 0; for (auto cone : cones_) { double d = pow(pow(cone.first, 2) + pow(cone.second,
2), 0.5); if (d < dclosest) { idx = i; dclosest = d; } //the cones_ vector is iterated through and
repeatedly compared to the previous closest cone until the minimum value is found. i++; }
point.x = cones_.at(idx).first; point.y = cones_.at(idx).second; return point; } geometry_msgs::Point
LaserProcessing::detectRoadCentre(){ //This function determines the roadCentre between two
cones by splitting the distance between pairs. geometry_msgs::Point point; unsigned int count =
countSegments(); if (count == 0) { return {}; } double dclosest = laserScan_.range_max; unsigned
int idx = 0, jdx = 0; for (unsigned i = 0; i < cones_.size(); i++) { for(unsigned j = 0; j < cones_.size();
j++) { if (i == j) { continue; } double d = pow(pow(cones_.at(i).first - cones_.at(j).first, 2) +
pow(cones_.at(i).second - cones_.at(j).second, 2), 0.5); if (d < dclosest) { idx = i; jdx = j; dclosest =
d; } } } point.x = (cones_.at(idx).first + cones_.at(jdx).first) / 2; point.y = (cones_.at(idx).second +
cones_.at(jdx).second) / 2; return point; } void LaserProcessing::newScan(sensor_msgs::LaserScan
laserScan){ //The newScan function solely makes a local copy of the laserScan data.
laserScan_=laserScan; } geometry_msgs::PoseArray LaserProcessing::getCones(){ //The getCones
function individually extracts the cones from the vector and pushes them into a poseArray to be
published in Ackerman::publishCones() geometry_msgs::PoseArray conesArray;
conesArray.header.seq = 0; conesArray.header.frame_id = "world"; conesArray.header.stamp =
ros::Time::now(); for (const auto cone : cones_){ geometry_msgs::Pose pose; pose.position.x =
cone.first; pose.position.y = cone.second; //vector to posearray conversion pose.position.z = 0;
pose.orientation.w = 1.0; conesArray.poses.push_back(pose); } return conesArray; }
visualization_msgs::Marker LaserProcessing::createRoadCentreMarker(){ //The marker for the
roadCentre point is created here to be later published to the visualiser in
Ackerman::publishConess geometry_msgs::Point roadCentre = detectRoadCentre();
visualization_msgs::Marker marker; unsigned int ct=0; marker.header.frame_id = "world"; // Frame
ID "World" marker.header.stamp = ros::Time::now(); //We set lifetime (it will dissapear in this
many seconds) marker.lifetime = ros::Duration(1000.0); //zero is forever // Set the namespace and
id for this marker. This serves to create a unique ID // Any marker sent with the same namespace
and id will overwrite the old one marker.ns = "road"; //This is namespace, markers can be in
diofferent namespace marker.id = ct++; // We need to keep incrementing markers to send
others ... so THINK, where do you store a vaiable if you need to keep incrementing it marker.type
= visualization_msgs::Marker::CUBE; marker.action = visualization_msgs::Marker::ADD;
marker.pose.position.x = roadCentre.x; marker.pose.position.y = roadCentre.y;
marker.pose.position.z = 0; //Orientation, we are not going to orientate it, for a quaternion it
needs 0,0,0,1 marker.pose.orientation.x = 0.0; marker.pose.orientation.y = 0.0;
marker.pose.orientation.z = 0.0; marker.pose.orientation.w = 1.0; marker.scale.x = 0.5; //
Dimensions of the cubes representing the road centre marker.scale.y = 0.5; marker.scale.z =
0.5; //Let's send a marker with color (red for now) std_msgs::ColorRGBA color; color.a=1;//a is
alpha - transparency 1 is 100%; color.r=1.0; color.g=0; color.b=0; marker.color = color; return
marker; } visualization_msgs::MarkerArray LaserProcessing::createConeMarkers(){ //The markers
for the cones are created here to be later published to the visualiser in Ackerman::publishCones
visualization_msgs::MarkerArray markersArray; unsigned int ct=0; if (cones_.empty())
{ ROS_INFO("No cone data found"); } for (const auto cone : cones_){ visualization_msgs::Marker
marker; marker.header.frame_id = "world"; // Frame ID "World" marker.header.stamp =
ros::Time::now(); //We set lifetime (it will dissapear in this many seconds) marker.lifetime =
ros::Duration(1000.0); //zero is forever // Set the namespace and id for this marker. This serves to
create a unique ID // Any marker sent with the same namespace and id will overwrite the old one
marker.ns = "cones"; //This is namespace, markers can be in different namespace marker.id = ct+
+; // We need to keep incrementing markers to send others marker.type =
visualization_msgs::Marker::CYLINDER; marker.action = visualization_msgs::Marker::ADD;
marker.pose.position.x = cone.first; marker.pose.position.y = cone.second; marker.pose.position.z
= 0; //Orientation, we are not going to orientate it, for a quaternion it needs 0,0,0,1
marker.pose.orientation.x = 0.0; marker.pose.orientation.y = 0.0; marker.pose.orientation.z = 0.0;
marker.pose.orientation.w = 1.0; marker.scale.x = 0.4; // Diameter of the cylinder representing
cones marker.scale.y = 0.4; marker.scale.z = 0.5; //Let's send a marker with color (blue for now)
std_msgs::ColorRGBA color; color.a=1;//a is alpha - transparency 1 is 100%; color.r=0; color.g=0;
color.b=1.0; marker.color = color; //ROS_INFO_STREAM("Marker:" << marker.pose.position.x <<
", " << marker.pose.position.y); markersArray.markers.push_back(marker); } return markersArray; }
geometry_msgs::Point LaserProcessing::polarToCart(unsigned int index) //this function converts
the polar values of distance and angle to cartesian points { float angle = laserScan_.angle_min +
laserScan_.angle_increment*index; float range = laserScan_.ranges.at(index);
geometry_msgs::Point cart; cart.x = static_cast<double>(range*cos(angle)); cart.y =
static_cast<double>(range*sin(angle)); return cart; } double
LaserProcessing::angleConnectingPoints(geometry_msgs::Point p1, geometry_msgs::Point p2)
//this function computes the angle between two points using the atan function. { return
atan2(p2.y - p1.y, p2.x - p1.x); }
ChatGPT
The given code is a part of a larger program that processes laser scan data. Here is a summary of
each part and its expected outcome:

1. Includes and Namespace:


 The code includes necessary header files for the program.
 It uses the std namespace.
2. LaserProcessing Class Constructor:
 Initializes the laserScan_ member variable with the provided sensor_msgs::LaserScan
object.
3. countObjectReadings Function:
 Computes the number of valid readings in the laser scan data.
 It iterates over the ranges vector of laserScan_ .
 If a reading falls within the valid range and is not NaN or infinite, the count is
incremented.
 Returns the count of valid readings.
4. countSegments Function:
 Detects segments (possibly cones) in the laser scan data and stores them in a
vector of pairs ( cones_ ).
 It iterates over the ranges vector of laserScan_ .
 It checks the adjacent readings to determine if a segment starts and ends.
 If a segment is found, its center coordinates are computed and added to the
cones_ vector.
 If a segment is larger than a cone (based on distance), a flag is returned (-1) to
indicate stopping the mission.
 Returns the count of segments (cones) detected.
5. detectClosestCone Function:
 Searches the cones_ vector populated by countSegments to find the closest cone.
 Iterates over the cones_ vector and calculates the distance from each cone to the
origin.
 Updates the closest cone index if a closer cone is found.
 Returns the closest cone's coordinates as a geometry_msgs::Point object.
6. detectRoadCentre Function:
 Determines the center point between two cones by splitting the distance between
each pair.
 Iterates over the cones_ vector using nested loops to compare each cone's
distance to other cones.
 Updates the indices of the cones that result in the smallest distance.
 Returns the center point between the closest cone pair as a geometry_msgs::Point
object.
7. newScan Function:
 Updates the laserScan_ member variable with a new sensor_msgs::LaserScan object.
8. getCones Function:
 Extracts the cones from the cones_ vector and creates a geometry_msgs::PoseArray
containing their positions.
 Each cone's position is added to the poses vector of the conesArray .
 Returns the conesArray .
9. createRoadCentreMarker Function:
 Creates a visualization marker for the road center point ( roadCentre) using the
detectRoadCentre function.
 Sets the marker's position, orientation, scale, and color.
 Returns the marker as a visualization_msgs::Marker object.
10. createConeMarkers Function:
 Creates visualization markers for the cones using the cones_ vector.
 Iterates over the cones_ vector and creates a marker for each cone.
 Sets the marker's position, orientation, scale, and color.
 Returns the markers as a visualization_msgs::MarkerArray object.
11. polarToCart Function:
 Converts polar coordinates (index, range, and angle) to Cartesian coordinates.
 Takes an index as input and retrieves the corresponding range and angle from
the laserScan_ object.

You might also like