update pt1
This commit is contained in:
24
CMakeLists.txt
Normal file
24
CMakeLists.txt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
project(lidarProject)
|
||||||
|
|
||||||
|
# Find ROS 2 dependencies
|
||||||
|
find_package(ament_cmake REQUIRED)
|
||||||
|
find_package(rclcpp REQUIRED)
|
||||||
|
find_package(std_msgs REQUIRED)
|
||||||
|
find_package(visualization_msgs REQUIRED)
|
||||||
|
|
||||||
|
# Add executable files
|
||||||
|
add_executable(publisher_node src/publisher_node.cpp)
|
||||||
|
add_executable(subscriber_node src/subscriber_node.cpp)
|
||||||
|
|
||||||
|
# Link executables with ROS 2 libraries
|
||||||
|
ament_target_dependencies(publisher_node rclcpp std_msgs)
|
||||||
|
ament_target_dependencies(subscriber_node rclcpp std_msgs visualization_msgs)
|
||||||
|
|
||||||
|
# Install executables
|
||||||
|
install(TARGETS
|
||||||
|
publisher_node
|
||||||
|
subscriber_node
|
||||||
|
DESTINATION lib/${PROJECT_NAME})
|
||||||
|
|
||||||
|
ament_package()
|
||||||
71
README.md
71
README.md
@ -1,3 +1,74 @@
|
|||||||
# Lidar-Scanner
|
# Lidar-Scanner
|
||||||
|
|
||||||
|
# Obrada Lidar podataka
|
||||||
|
|
||||||
|
Obradu koordinata sam radio po ovom principu. Za kooridnate od lidara sam koristio simulator, taj deo možeš i da preskočiš.
|
||||||
|
|
||||||
|
1. Učitavanje lidar podataka
|
||||||
|
2. Klasterovanje podataka
|
||||||
|
3. Proveravanje dimenzija klastera
|
||||||
|
4. Računanje brzine i ubrzanja
|
||||||
|
|
||||||
|
|
||||||
|
# Učitavanje lidar podataka
|
||||||
|
Simulator predstavlja jenostavnu puthon skriptu koja ima centralnu tačku i prati njene projekcije na svaku oblast u njenoj okolini.
|
||||||
|
Fomrat učitavanja podataka je (x, y) što bi trebalo da se izmeni da odgovara pravim lidar podacima.
|
||||||
|
Pretpostavke za lidar tačke
|
||||||
|
- Tačke se ciklično prosledjuju
|
||||||
|
- Dve tačke ne mogu imati isti ugao od centra do sebe tj. ne može jedna tačka biti iza druge
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# Klasterovanje podataka
|
||||||
|
|
||||||
|
Pristup klasterovanja već korišćen od strane ostalih
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
```c++
|
||||||
|
bool arePointsInSameCluster(const Point& p1, const Point& p2, double thresholdAngle, double radiusMultiplier)
|
||||||
|
{
|
||||||
|
double angleDifference = std::fabs(p1.angle - p2.angle);
|
||||||
|
if (angleDifference > M_PI)
|
||||||
|
angleDifference = 2 * M_PI - angleDifference;
|
||||||
|
|
||||||
|
double adaptiveThreshold = std::min(p1.r, p2.r) * std::sin(angleDifference) / std::sin(thresholdAngle - angleDifference);
|
||||||
|
double distance = std::sqrt(std::pow(p2.x - p1.x, 2) + std::pow(p2.y - p1.y, 2));
|
||||||
|
|
||||||
|
return distance <= adaptiveThreshold* radiusMultiplier;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Moj pristup samo ne koristimo ugao već razdaljinu
|
||||||
|
|
||||||
|
```c++
|
||||||
|
bool arePointsInSameCluster2(const Point& p1, const Point& p2, double thresholdAngle)
|
||||||
|
{
|
||||||
|
|
||||||
|
double distance = std::sqrt(std::pow(p2.x - p1.x, 2) + std::pow(p2.y - p1.y, 2));
|
||||||
|
|
||||||
|
return distance <= thresholdAngle;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Proveravanje dimenzija klastera
|
||||||
|
|
||||||
|
Posle toga odredjujemo da li selektovana erija pripada odredjenom području.
|
||||||
|
U suštini proveravano najdalj tačke u sva četiri smera da li se nalaze u odredjenom pravugaoniku kako bi bili sigurni da se radi o protivniku.
|
||||||
|
|
||||||
|
# Računanje brzine i ubrzanja
|
||||||
|
|
||||||
|
Za računanje ubrzanja i brzine prvo pronalazimo centar kruga i čuvamo ga sa trenutnim vremenom.
|
||||||
|
Treba proveriti na pravom primeru kako radi.
|
||||||
|
Čuvamo trenutnu i 2 prošle tačke koje su nam dovoljne da izračunamo ubrzanje i vektor kretanja.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Pokretanje
|
||||||
|
|
||||||
|
colcon build
|
||||||
|
source install/setup.bash
|
||||||
|
ros2 run lidarProject subscriber_node
|
||||||
18
package.xml
Normal file
18
package.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||||
|
<package format="3">
|
||||||
|
<name>lidarProject</name>
|
||||||
|
<version>0.0.0</version>
|
||||||
|
<description>TODO: Package description</description>
|
||||||
|
<maintainer email="bogda@todo.todo">bogda</maintainer>
|
||||||
|
<license>TODO: License declaration</license>
|
||||||
|
|
||||||
|
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||||
|
|
||||||
|
<test_depend>ament_lint_auto</test_depend>
|
||||||
|
<test_depend>ament_lint_common</test_depend>
|
||||||
|
|
||||||
|
<export>
|
||||||
|
<build_type>ament_cmake</build_type>
|
||||||
|
</export>
|
||||||
|
</package>
|
||||||
BIN
source/a.jpg
Normal file
BIN
source/a.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 482 KiB |
BIN
source/b.png
Normal file
BIN
source/b.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
360
src/lidar_points.txt
Normal file
360
src/lidar_points.txt
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
(800, 300)
|
||||||
|
(800, 306)
|
||||||
|
(800, 313)
|
||||||
|
(800, 320)
|
||||||
|
(800, 327)
|
||||||
|
(800, 335)
|
||||||
|
(800, 342)
|
||||||
|
(800, 349)
|
||||||
|
(800, 356)
|
||||||
|
(800, 363)
|
||||||
|
(800, 370)
|
||||||
|
(800, 377)
|
||||||
|
(800, 385)
|
||||||
|
(800, 392)
|
||||||
|
(800, 399)
|
||||||
|
(800, 407)
|
||||||
|
(800, 414)
|
||||||
|
(800, 422)
|
||||||
|
(800, 430)
|
||||||
|
(800, 438)
|
||||||
|
(800, 445)
|
||||||
|
(800, 453)
|
||||||
|
(800, 461)
|
||||||
|
(800, 469)
|
||||||
|
(800, 478)
|
||||||
|
(800, 486)
|
||||||
|
(800, 495)
|
||||||
|
(800, 503)
|
||||||
|
(800, 513)
|
||||||
|
(800, 522)
|
||||||
|
(800, 531)
|
||||||
|
(800, 540)
|
||||||
|
(800, 550)
|
||||||
|
(800, 559)
|
||||||
|
(800, 570)
|
||||||
|
(800, 580)
|
||||||
|
(800, 590)
|
||||||
|
(798, 600)
|
||||||
|
(784, 600)
|
||||||
|
(770, 600)
|
||||||
|
(757, 600)
|
||||||
|
(745, 600)
|
||||||
|
(733, 600)
|
||||||
|
(721, 600)
|
||||||
|
(710, 600)
|
||||||
|
(700, 600)
|
||||||
|
(690, 600)
|
||||||
|
(680, 600)
|
||||||
|
(670, 600)
|
||||||
|
(661, 600)
|
||||||
|
(651, 600)
|
||||||
|
(643, 600)
|
||||||
|
(634, 600)
|
||||||
|
(626, 600)
|
||||||
|
(618, 600)
|
||||||
|
(610, 600)
|
||||||
|
(602, 600)
|
||||||
|
(594, 600)
|
||||||
|
(587, 600)
|
||||||
|
(580, 600)
|
||||||
|
(573, 600)
|
||||||
|
(566, 600)
|
||||||
|
(559, 600)
|
||||||
|
(552, 600)
|
||||||
|
(546, 600)
|
||||||
|
(540, 600)
|
||||||
|
(533, 600)
|
||||||
|
(527, 600)
|
||||||
|
(521, 600)
|
||||||
|
(515, 600)
|
||||||
|
(509, 600)
|
||||||
|
(503, 600)
|
||||||
|
(497, 600)
|
||||||
|
(491, 600)
|
||||||
|
(486, 600)
|
||||||
|
(480, 600)
|
||||||
|
(474, 600)
|
||||||
|
(469, 600)
|
||||||
|
(463, 600)
|
||||||
|
(458, 600)
|
||||||
|
(452, 600)
|
||||||
|
(447, 600)
|
||||||
|
(442, 600)
|
||||||
|
(436, 600)
|
||||||
|
(431, 600)
|
||||||
|
(426, 600)
|
||||||
|
(420, 600)
|
||||||
|
(415, 600)
|
||||||
|
(410, 600)
|
||||||
|
(405, 600)
|
||||||
|
(400, 600)
|
||||||
|
(394, 600)
|
||||||
|
(389, 600)
|
||||||
|
(384, 600)
|
||||||
|
(379, 600)
|
||||||
|
(373, 600)
|
||||||
|
(368, 600)
|
||||||
|
(363, 600)
|
||||||
|
(357, 600)
|
||||||
|
(352, 600)
|
||||||
|
(347, 600)
|
||||||
|
(341, 600)
|
||||||
|
(336, 600)
|
||||||
|
(330, 600)
|
||||||
|
(325, 600)
|
||||||
|
(319, 600)
|
||||||
|
(313, 600)
|
||||||
|
(308, 600)
|
||||||
|
(302, 600)
|
||||||
|
(296, 600)
|
||||||
|
(290, 600)
|
||||||
|
(284, 600)
|
||||||
|
(278, 600)
|
||||||
|
(272, 600)
|
||||||
|
(266, 600)
|
||||||
|
(259, 600)
|
||||||
|
(253, 600)
|
||||||
|
(247, 600)
|
||||||
|
(240, 600)
|
||||||
|
(233, 600)
|
||||||
|
(226, 600)
|
||||||
|
(219, 600)
|
||||||
|
(212, 600)
|
||||||
|
(205, 600)
|
||||||
|
(197, 600)
|
||||||
|
(189, 600)
|
||||||
|
(181, 600)
|
||||||
|
(173, 600)
|
||||||
|
(165, 600)
|
||||||
|
(156, 600)
|
||||||
|
(148, 600)
|
||||||
|
(138, 600)
|
||||||
|
(129, 600)
|
||||||
|
(119, 600)
|
||||||
|
(109, 600)
|
||||||
|
(99, 600)
|
||||||
|
(89, 600)
|
||||||
|
(78, 600)
|
||||||
|
(66, 600)
|
||||||
|
(54, 600)
|
||||||
|
(42, 600)
|
||||||
|
(29, 600)
|
||||||
|
(15, 600)
|
||||||
|
(1, 600)
|
||||||
|
(0, 590)
|
||||||
|
(0, 580)
|
||||||
|
(0, 570)
|
||||||
|
(0, 559)
|
||||||
|
(0, 550)
|
||||||
|
(0, 540)
|
||||||
|
(0, 531)
|
||||||
|
(0, 522)
|
||||||
|
(0, 513)
|
||||||
|
(0, 503)
|
||||||
|
(0, 495)
|
||||||
|
(322, 335)
|
||||||
|
(328, 331)
|
||||||
|
(330, 329)
|
||||||
|
(333, 326)
|
||||||
|
(334, 325)
|
||||||
|
(335, 323)
|
||||||
|
(336, 321)
|
||||||
|
(337, 320)
|
||||||
|
(337, 319)
|
||||||
|
(338, 317)
|
||||||
|
(339, 316)
|
||||||
|
(338, 315)
|
||||||
|
(339, 313)
|
||||||
|
(340, 312)
|
||||||
|
(340, 311)
|
||||||
|
(340, 310)
|
||||||
|
(340, 309)
|
||||||
|
(340, 308)
|
||||||
|
(341, 307)
|
||||||
|
(341, 306)
|
||||||
|
(341, 305)
|
||||||
|
(341, 304)
|
||||||
|
(341, 303)
|
||||||
|
(341, 302)
|
||||||
|
(341, 301)
|
||||||
|
(341, 300)
|
||||||
|
(341, 298)
|
||||||
|
(341, 297)
|
||||||
|
(341, 296)
|
||||||
|
(341, 295)
|
||||||
|
(341, 294)
|
||||||
|
(340, 293)
|
||||||
|
(340, 292)
|
||||||
|
(340, 291)
|
||||||
|
(339, 290)
|
||||||
|
(339, 289)
|
||||||
|
(339, 288)
|
||||||
|
(338, 286)
|
||||||
|
(337, 285)
|
||||||
|
(337, 284)
|
||||||
|
(337, 283)
|
||||||
|
(335, 281)
|
||||||
|
(334, 280)
|
||||||
|
(334, 278)
|
||||||
|
(332, 276)
|
||||||
|
(331, 275)
|
||||||
|
(329, 272)
|
||||||
|
(325, 270)
|
||||||
|
(0, 130)
|
||||||
|
(0, 121)
|
||||||
|
(0, 113)
|
||||||
|
(0, 104)
|
||||||
|
(0, 96)
|
||||||
|
(0, 86)
|
||||||
|
(0, 77)
|
||||||
|
(0, 68)
|
||||||
|
(0, 59)
|
||||||
|
(0, 49)
|
||||||
|
(0, 40)
|
||||||
|
(0, 29)
|
||||||
|
(0, 19)
|
||||||
|
(0, 9)
|
||||||
|
(1, 0)
|
||||||
|
(15, 0)
|
||||||
|
(29, 0)
|
||||||
|
(42, 0)
|
||||||
|
(54, 0)
|
||||||
|
(66, 0)
|
||||||
|
(78, 0)
|
||||||
|
(89, 0)
|
||||||
|
(99, 0)
|
||||||
|
(109, 0)
|
||||||
|
(119, 0)
|
||||||
|
(129, 0)
|
||||||
|
(138, 0)
|
||||||
|
(148, 0)
|
||||||
|
(156, 0)
|
||||||
|
(165, 0)
|
||||||
|
(173, 0)
|
||||||
|
(181, 0)
|
||||||
|
(189, 0)
|
||||||
|
(197, 0)
|
||||||
|
(205, 0)
|
||||||
|
(212, 0)
|
||||||
|
(219, 0)
|
||||||
|
(226, 0)
|
||||||
|
(233, 0)
|
||||||
|
(240, 0)
|
||||||
|
(247, 0)
|
||||||
|
(253, 0)
|
||||||
|
(259, 0)
|
||||||
|
(266, 0)
|
||||||
|
(272, 0)
|
||||||
|
(278, 0)
|
||||||
|
(284, 0)
|
||||||
|
(290, 0)
|
||||||
|
(296, 0)
|
||||||
|
(302, 0)
|
||||||
|
(308, 0)
|
||||||
|
(313, 0)
|
||||||
|
(319, 0)
|
||||||
|
(325, 0)
|
||||||
|
(330, 0)
|
||||||
|
(336, 0)
|
||||||
|
(341, 0)
|
||||||
|
(347, 0)
|
||||||
|
(352, 0)
|
||||||
|
(357, 0)
|
||||||
|
(363, 0)
|
||||||
|
(368, 0)
|
||||||
|
(373, 0)
|
||||||
|
(379, 0)
|
||||||
|
(384, 0)
|
||||||
|
(389, 0)
|
||||||
|
(394, 0)
|
||||||
|
(399, 0)
|
||||||
|
(405, 0)
|
||||||
|
(410, 0)
|
||||||
|
(415, 0)
|
||||||
|
(420, 0)
|
||||||
|
(426, 0)
|
||||||
|
(431, 0)
|
||||||
|
(436, 0)
|
||||||
|
(442, 0)
|
||||||
|
(447, 0)
|
||||||
|
(452, 0)
|
||||||
|
(458, 0)
|
||||||
|
(463, 0)
|
||||||
|
(469, 0)
|
||||||
|
(474, 0)
|
||||||
|
(480, 0)
|
||||||
|
(486, 0)
|
||||||
|
(491, 0)
|
||||||
|
(497, 0)
|
||||||
|
(503, 0)
|
||||||
|
(509, 0)
|
||||||
|
(515, 0)
|
||||||
|
(521, 0)
|
||||||
|
(527, 0)
|
||||||
|
(533, 0)
|
||||||
|
(540, 0)
|
||||||
|
(546, 0)
|
||||||
|
(552, 0)
|
||||||
|
(559, 0)
|
||||||
|
(566, 0)
|
||||||
|
(573, 0)
|
||||||
|
(580, 0)
|
||||||
|
(587, 0)
|
||||||
|
(469, 192)
|
||||||
|
(468, 198)
|
||||||
|
(468, 202)
|
||||||
|
(468, 205)
|
||||||
|
(469, 208)
|
||||||
|
(469, 210)
|
||||||
|
(470, 212)
|
||||||
|
(471, 214)
|
||||||
|
(472, 216)
|
||||||
|
(473, 218)
|
||||||
|
(474, 220)
|
||||||
|
(475, 221)
|
||||||
|
(477, 222)
|
||||||
|
(478, 224)
|
||||||
|
(479, 225)
|
||||||
|
(481, 226)
|
||||||
|
(483, 227)
|
||||||
|
(485, 228)
|
||||||
|
(487, 229)
|
||||||
|
(489, 230)
|
||||||
|
(491, 230)
|
||||||
|
(494, 231)
|
||||||
|
(497, 231)
|
||||||
|
(501, 231)
|
||||||
|
(507, 230)
|
||||||
|
(800, 49)
|
||||||
|
(800, 59)
|
||||||
|
(800, 68)
|
||||||
|
(800, 77)
|
||||||
|
(800, 86)
|
||||||
|
(800, 96)
|
||||||
|
(800, 104)
|
||||||
|
(800, 113)
|
||||||
|
(800, 121)
|
||||||
|
(800, 130)
|
||||||
|
(800, 138)
|
||||||
|
(800, 146)
|
||||||
|
(800, 154)
|
||||||
|
(800, 161)
|
||||||
|
(800, 169)
|
||||||
|
(800, 177)
|
||||||
|
(800, 185)
|
||||||
|
(800, 192)
|
||||||
|
(800, 200)
|
||||||
|
(800, 207)
|
||||||
|
(800, 214)
|
||||||
|
(800, 222)
|
||||||
|
(800, 229)
|
||||||
|
(800, 236)
|
||||||
|
(800, 243)
|
||||||
|
(800, 250)
|
||||||
|
(800, 257)
|
||||||
|
(800, 264)
|
||||||
|
(800, 272)
|
||||||
|
(800, 279)
|
||||||
|
(800, 286)
|
||||||
|
(800, 293)
|
||||||
18
src/my_node.cpp
Normal file
18
src/my_node.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "rclcpp/rclcpp.hpp"
|
||||||
|
|
||||||
|
class MyNode : public rclcpp::Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyNode() : Node("my_node")
|
||||||
|
{
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Hello, ROS 2!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
rclcpp::init(argc, argv);
|
||||||
|
rclcpp::spin(std::make_shared<MyNode>());
|
||||||
|
rclcpp::shutdown();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
90
src/publisher_node.cpp
Normal file
90
src/publisher_node.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "rclcpp/rclcpp.hpp"
|
||||||
|
#include "std_msgs/msg/string.hpp"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class PublisherNode : public rclcpp::Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PublisherNode() : Node("publisher_node"), current_section_index_(0)
|
||||||
|
{
|
||||||
|
publisher_ = this->create_publisher<std_msgs::msg::String>("coordinates", 10);
|
||||||
|
|
||||||
|
// Učitavanje sekcija iz fajla
|
||||||
|
load_sections_from_file("/mnt/c/Users/bogda/OneDrive/Desktop/lidarProject/src/lidar_points.txt");
|
||||||
|
|
||||||
|
// Postavljanje tajmera za slanje jedne sekcije po sekundi
|
||||||
|
timer_ = this->create_wall_timer(
|
||||||
|
std::chrono::seconds(1),
|
||||||
|
std::bind(&PublisherNode::publish_next_section, this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void load_sections_from_file(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
|
||||||
|
if (!infile.is_open()) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Ne može se otvoriti fajl %s", filename.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::ostringstream current_section;
|
||||||
|
|
||||||
|
while (std::getline(infile, line)) {
|
||||||
|
if (line == "NEW SECTION") {
|
||||||
|
// Sačuvaj trenutnu sekciju i započni novu
|
||||||
|
if (!current_section.str().empty()) {
|
||||||
|
sections_.push_back(current_section.str());
|
||||||
|
current_section.str(""); // Resetuj sekciju
|
||||||
|
}
|
||||||
|
} else if (!line.empty()) {
|
||||||
|
// Dodaj liniju (koordinate) u trenutnu sekciju
|
||||||
|
current_section << line << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dodaj poslednju sekciju ako postoji
|
||||||
|
if (!current_section.str().empty()) {
|
||||||
|
sections_.push_back(current_section.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void publish_next_section()
|
||||||
|
{
|
||||||
|
if (sections_.empty()) {
|
||||||
|
RCLCPP_WARN(this->get_logger(), "Nema sekcija za slanje.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proveri indeks i objavi trenutnu sekciju
|
||||||
|
std_msgs::msg::String message;
|
||||||
|
message.data = sections_[current_section_index_];
|
||||||
|
publisher_->publish(message);
|
||||||
|
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Objavljena sekcija %zu:\n%s", current_section_index_ + 1, message.data.c_str());
|
||||||
|
|
||||||
|
|
||||||
|
// Pređi na sledeću sekciju (kružni indeks)
|
||||||
|
current_section_index_ = (current_section_index_ + 1) % sections_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
|
||||||
|
rclcpp::TimerBase::SharedPtr timer_;
|
||||||
|
std::vector<std::string> sections_;
|
||||||
|
size_t current_section_index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
rclcpp::init(argc, argv);
|
||||||
|
rclcpp::spin(std::make_shared<PublisherNode>());
|
||||||
|
rclcpp::shutdown();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
339
src/subscriber_node.cpp
Normal file
339
src/subscriber_node.cpp
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
#include "rclcpp/rclcpp.hpp"
|
||||||
|
#include "std_msgs/msg/string.hpp"
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double r;
|
||||||
|
double angle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PointT
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double t;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cluster {
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
Point southernmost_y = {0, std::numeric_limits<double>::max()};
|
||||||
|
Point northernmost_y = {0, std::numeric_limits<double>::lowest()};
|
||||||
|
Point westernmost_x = {std::numeric_limits<double>::max(), 0};
|
||||||
|
Point easternmost_x = {std::numeric_limits<double>::lowest(), 0};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Point> parseCoordinates(const std::string& data)
|
||||||
|
{
|
||||||
|
std::vector<Point> points;
|
||||||
|
std::istringstream stream(data);
|
||||||
|
double x, y;
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(stream, line))
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if(line =="NEW SECTION")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xPos = line.find("(");
|
||||||
|
size_t yPos = line.find(",");
|
||||||
|
size_t yEnd = line.find(")");
|
||||||
|
std::cout << line+"\n";
|
||||||
|
|
||||||
|
if (xPos != std::string::npos && yPos != std::string::npos)
|
||||||
|
{
|
||||||
|
|
||||||
|
x = std::stod(line.substr(xPos + 1, yPos - (xPos + 1)));
|
||||||
|
y = std::stod(line.substr(yPos + 2, yEnd - (yPos + 2)));
|
||||||
|
|
||||||
|
// Adjust for the new center at (400, 300)
|
||||||
|
double newX = x + 400; // Shift X by 400 to center at (400, 300)
|
||||||
|
double newY = y + 300; // Shift Y by 300 to center at (400, 300)
|
||||||
|
|
||||||
|
// Output the adjusted coordinates
|
||||||
|
//std::cout << "Adjusted coordinates: " << std::to_string(newX) + " " + std::to_string(newY) + "\n";
|
||||||
|
|
||||||
|
// Calculate the distance from the new center (400, 300)
|
||||||
|
double r = std::sqrt(newX * newX + newY * newY);
|
||||||
|
//std::cout << "Distance (r): " << r << "\n";
|
||||||
|
|
||||||
|
// Calculate the angle from the new center (400, 300)
|
||||||
|
double angle = std::atan2(newY, newX);
|
||||||
|
//std::cout << "Angle: " << angle << "\n";
|
||||||
|
|
||||||
|
// Store the results: the adjusted coordinates, distance, and angle
|
||||||
|
points.push_back({newX, newY, r, angle});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << line+"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool arePointsInSameCluster(const Point& p1, const Point& p2, double thresholdAngle, double radiusMultiplier)
|
||||||
|
{
|
||||||
|
double angleDifference = std::fabs(p1.angle - p2.angle);
|
||||||
|
if (angleDifference > M_PI)
|
||||||
|
angleDifference = 2 * M_PI - angleDifference;
|
||||||
|
|
||||||
|
double adaptiveThreshold = std::min(p1.r, p2.r) * std::sin(angleDifference) / std::sin(thresholdAngle - angleDifference);
|
||||||
|
double distance = std::sqrt(std::pow(p2.x - p1.x, 2) + std::pow(p2.y - p1.y, 2));
|
||||||
|
|
||||||
|
return distance <= adaptiveThreshold* radiusMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool arePointsInSameCluster2(const Point& p1, const Point& p2, double thresholdAngle)
|
||||||
|
{
|
||||||
|
|
||||||
|
double distance = std::sqrt(std::pow(p2.x - p1.x, 2) + std::pow(p2.y - p1.y, 2));
|
||||||
|
|
||||||
|
return distance <= thresholdAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point findCentroid(std::vector<Point>& points) {
|
||||||
|
double sumX = 0.0;
|
||||||
|
double sumY = 0.0;
|
||||||
|
|
||||||
|
// Jedan prolaz kroz sve tačke da bismo sabrali koordinate
|
||||||
|
|
||||||
|
for (const auto& point : points) {
|
||||||
|
sumX += point.x;
|
||||||
|
sumY += point.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prosečne koordinate (centroid)
|
||||||
|
size_t n = points.size();
|
||||||
|
return {sumX / n, sumY / n,0,0};
|
||||||
|
}
|
||||||
|
|
||||||
|
void findLineEquation(Point p1, Point p2, double& m, double& b) {
|
||||||
|
if (p1.x == p2.x) {
|
||||||
|
m = 0;
|
||||||
|
b = p1.x;
|
||||||
|
} else {
|
||||||
|
m = (p2.y - p1.y) / (p2.x - p1.x);
|
||||||
|
b = p1.y - m * p1.x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Point findIntersection(Point p1, Point p2, Point p3, Point p4) {
|
||||||
|
double m1, b1, m2, b2;
|
||||||
|
|
||||||
|
findLineEquation(p1, p2, m1, b1);
|
||||||
|
findLineEquation(p3, p4, m2, b2);
|
||||||
|
|
||||||
|
Point intersection;
|
||||||
|
|
||||||
|
if (m1 == m2) {
|
||||||
|
std::cerr << "Prave su paralelne i nemaju presek." << std::endl;
|
||||||
|
return {0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
// m1 * x + b1 = m2 * x + b2
|
||||||
|
// (m1 - m2) * x = b2 - b1
|
||||||
|
intersection.x = (b2 - b1) / (m1 - m2);
|
||||||
|
intersection.y = m1 * intersection.x + b1;
|
||||||
|
|
||||||
|
return intersection;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point findCentroid2(Point p1, Point p2, Point p3, Point p4) {
|
||||||
|
double sumX = 0.0;
|
||||||
|
double sumY = 0.0;
|
||||||
|
|
||||||
|
//Nadji najblizu tacku centru u ovom slucaju
|
||||||
|
double dist1 = std::sqrt(p1.x * p1.x + p1.y * p1.y); // Rastojanje od (0, 0)
|
||||||
|
double dist2 = std::sqrt(p2.x * p2.x + p2.y * p2.y); // Rastojanje od (0, 0)
|
||||||
|
double dist3 = std::sqrt(p3.x * p3.x + p3.y * p3.y); // Rastojanje od (0, 0)
|
||||||
|
double dist4 = std::sqrt(p4.x * p4.x + p4.y * p4.y); // Rastojanje od (0, 0)
|
||||||
|
|
||||||
|
Point p = {0,0,0,0};
|
||||||
|
|
||||||
|
if (dist1 <= dist2 && dist1 <= dist3 && dist1 <= dist4) {
|
||||||
|
|
||||||
|
// pronadji kvadrat p1, p3, p4
|
||||||
|
return findIntersection(p1, p, p3, p4);
|
||||||
|
|
||||||
|
} else if (dist2 <= dist3 && dist2 <= dist4) {
|
||||||
|
|
||||||
|
// pronadji kvadrat p2, p3, p4
|
||||||
|
return findIntersection(p2, p, p3, p4);
|
||||||
|
|
||||||
|
} else if (dist3 <= dist4) {
|
||||||
|
|
||||||
|
// pronadji kvadrat p3, p1, p2
|
||||||
|
return findIntersection(p3, p, p1, p2);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// pronadji kvadrat p4, p1, p2
|
||||||
|
return findIntersection(p4, p, p1, p2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PointT calculateVelocity(const PointT& p1, const PointT& p2) {
|
||||||
|
return {p2.x - p1.x, p2.y - p1.y, p2.t - p1.t};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funkcija za izračunavanje ubrzanja između dva vektora kretanja
|
||||||
|
PointT calculateAcceleration(const PointT& p1, const PointT& p2, const PointT& p3) {
|
||||||
|
PointT velocity1 = calculateVelocity(p1, p2);
|
||||||
|
PointT velocity2 = calculateVelocity(p2, p3);
|
||||||
|
|
||||||
|
return {velocity2.x - velocity1.x, velocity2.y - velocity1.y, velocity2.t - velocity1.t};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Predikcija sledeće tačke na osnovu trenutne tačke, prethodne dve tačke i ubrzanja
|
||||||
|
PointT predictNextPoint(const PointT& p1, const PointT& p2, const PointT& p3) {
|
||||||
|
// Izračunavamo ubrzanje
|
||||||
|
PointT acceleration = calculateAcceleration(p1, p2, p3);
|
||||||
|
|
||||||
|
// Predikcija nove tačke (x, y) uzimajući u obzir ubrzanje
|
||||||
|
double predictedX = p3.x + (p3.x - p2.x) + acceleration.x;
|
||||||
|
double predictedY = p3.y + (p3.y - p2.y) + acceleration.y;
|
||||||
|
double predictedT = p3.t + (p3.t - p2.t) + acceleration.t;
|
||||||
|
|
||||||
|
return {predictedX, predictedY, predictedT};
|
||||||
|
}
|
||||||
|
|
||||||
|
PointT prev1 = {0.0, 0.0, 0.0}; // Prethodna tačka 1
|
||||||
|
|
||||||
|
PointT prev2 = {0.0, 0.0, 0.0}; // Prethodna tačka 2
|
||||||
|
|
||||||
|
|
||||||
|
class SubscriberNode : public rclcpp::Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SubscriberNode() : Node("subscriber_node")
|
||||||
|
{
|
||||||
|
|
||||||
|
subscription_ = this->create_subscription<std_msgs::msg::String>(
|
||||||
|
"coordinates", 10, std::bind(&SubscriberNode::message_callback, this, std::placeholders::_1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void message_callback(const std_msgs::msg::String::SharedPtr msg)
|
||||||
|
{
|
||||||
|
std::vector<Point> points = parseCoordinates(msg->data);
|
||||||
|
|
||||||
|
std::vector<Cluster> clusters;
|
||||||
|
Cluster current_cluster;
|
||||||
|
|
||||||
|
double thresholdAngle = M_PI / 6; // Prag od 30 stepeni
|
||||||
|
double radiusMultiplier = 50; // Povećajte radius faktor
|
||||||
|
|
||||||
|
double boxdimensions = 100;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < points.size(); ++i)
|
||||||
|
{
|
||||||
|
if (current_cluster.points.empty() || arePointsInSameCluster2(current_cluster.points.back(), points[i], radiusMultiplier))
|
||||||
|
{
|
||||||
|
current_cluster.points.push_back(points[i]);
|
||||||
|
|
||||||
|
// Ažuriraj ekstremne tačke
|
||||||
|
if (points[i].y < current_cluster.southernmost_y.y) {
|
||||||
|
current_cluster.southernmost_y = points[i];
|
||||||
|
}
|
||||||
|
if (points[i].y > current_cluster.northernmost_y.y) {
|
||||||
|
current_cluster.northernmost_y = points[i];
|
||||||
|
}
|
||||||
|
if (points[i].x < current_cluster.westernmost_x.x) {
|
||||||
|
current_cluster.westernmost_x = points[i];
|
||||||
|
}
|
||||||
|
if (points[i].x > current_cluster.easternmost_x.x) {
|
||||||
|
current_cluster.easternmost_x = points[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clusters.push_back(current_cluster);
|
||||||
|
current_cluster = Cluster{};
|
||||||
|
current_cluster.points.push_back(points[i]);
|
||||||
|
|
||||||
|
if (points[i].y < current_cluster.southernmost_y.y) {
|
||||||
|
current_cluster.southernmost_y = points[i];
|
||||||
|
}
|
||||||
|
if (points[i].y > current_cluster.northernmost_y.y) {
|
||||||
|
current_cluster.northernmost_y = points[i];
|
||||||
|
}
|
||||||
|
if (points[i].x < current_cluster.westernmost_x.x) {
|
||||||
|
current_cluster.westernmost_x = points[i];
|
||||||
|
}
|
||||||
|
if (points[i].x > current_cluster.easternmost_x.x) {
|
||||||
|
current_cluster.easternmost_x = points[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current_cluster.points.empty())
|
||||||
|
{
|
||||||
|
clusters.push_back(current_cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ispis za svaki klaster
|
||||||
|
for (size_t i = 0; i < clusters.size(); ++i)
|
||||||
|
{
|
||||||
|
double vertical_distance = std::fabs(clusters[i].northernmost_y.y - clusters[i].southernmost_y.y);
|
||||||
|
double horizontal_distance = std::fabs(clusters[i].easternmost_x.x - clusters[i].westernmost_x.x);
|
||||||
|
|
||||||
|
if(boxdimensions > vertical_distance && boxdimensions > horizontal_distance)
|
||||||
|
{
|
||||||
|
std::cout << "Klaster moze da bude protivnik " << i + 1 << ":\n";
|
||||||
|
for (const auto& point : clusters[i].points)
|
||||||
|
{
|
||||||
|
std::cout << " Tacka (x=" << point.x << ", y=" << point.y << ")\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& finalpoint = findCentroid2(clusters[i].easternmost_x,clusters[i].westernmost_x,clusters[i].northernmost_y,clusters[i].southernmost_y);
|
||||||
|
std::cout << " FINALNA (x=" << finalpoint.x << ", y=" << finalpoint.y << ")\n";
|
||||||
|
|
||||||
|
//Pretpostavka da ce biti samo jedan ovakav objekat
|
||||||
|
|
||||||
|
PointT current;
|
||||||
|
current.x = finalpoint.x;
|
||||||
|
current.y = finalpoint.y;
|
||||||
|
current.t = 0.0;
|
||||||
|
|
||||||
|
PointT predicted = predictNextPoint(prev1, prev2, current);
|
||||||
|
|
||||||
|
std::cout << "Predvidjena sledeca tacka: ("
|
||||||
|
<< predicted.x << ", " << predicted.y << ", " << predicted.t << ")" << std::endl;
|
||||||
|
|
||||||
|
prev1 = prev2;
|
||||||
|
prev2 = current;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
rclcpp::init(argc, argv);
|
||||||
|
rclcpp::spin(std::make_shared<SubscriberNode>());
|
||||||
|
rclcpp::shutdown();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user