Skip to content

Commit bd8ce49

Browse files
authored
Merge pull request #3795 from JdeRobot/cpp-laser-mapping-update
Cpp laser mapping update
2 parents 5d1fc6a + 8187e06 commit bd8ce49

20 files changed

Lines changed: 802 additions & 1 deletion

File tree

database/exercises/db.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ COPY public.exercises (id, exercise_id, name, description, tags, status, url) FR
124124
11 montecarlo_laser_loc Montecarlo Laser Loc Calculate the position of the robot based on the ["ROS2"] ACTIVE https://jderobot.github.io/RoboticsAcademy/exercises/MobileRobots/montecarlo_laser_loc
125125
12 montecarlo_visual_loc Montecarlo Visual Loc Calculate the position of the robot based on the ["ROS2"] ACTIVE https://jderobot.github.io/RoboticsAcademy/exercises/ComputerVision/montecarlo_visual_loc
126126
13 marker_visual_loc Marker Visual Loc Calculate the position of the robot based on the ["ROS2"] ACTIVE https://jderobot.github.io/RoboticsAcademy/exercises/ComputerVision/marker_visual_loc
127-
14 laser_mapping Laser Mapping Build a map based on sensor readings ["ROS2"] ACTIVE https://jderobot.github.io/RoboticsAcademy/exercises/MobileRobots/laser_mapping
127+
14 laser_mapping Laser Mapping Build a map based on sensor readings ["ROS2", "MULTILANGUAGE"] ACTIVE https://jderobot.github.io/RoboticsAcademy/exercises/MobileRobots/laser_mapping
128128
15 basic_computer_vision Basic Computer Vision Basic Computer Vision exercise using React and RAM ["ROS2"] ACTIVE https://jderobot.github.io/RoboticsAcademy/exercises/ComputerVision/basic_computer_vision
129129
16 follow_road Drone Follow Road Drone Follow Road exercise ["ROS2"] ACTIVE https://jderobot.github.io/RoboticsAcademy/exercises/Drones/follow_road
130130
17 pick_place Pick and Place Pick and Place exercise ["ROS2"] PROTOTYPE https://jderobot.github.io/RoboticsAcademy/exercises/IndustrialRobots/pick_place
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
project(ObstacleAvoidanceLibs CXX)
3+
4+
set(CMAKE_CXX_STANDARD 17)
5+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
7+
8+
find_package(ament_cmake REQUIRED)
9+
10+
set(ROS2_PACKAGES
11+
rclcpp
12+
nav_msgs
13+
geometry_msgs
14+
sensor_msgs
15+
std_msgs
16+
cv_bridge
17+
)
18+
19+
foreach(pkg IN LISTS ROS2_PACKAGES)
20+
find_package(${pkg} REQUIRED)
21+
endforeach()
22+
23+
find_package(Boost REQUIRED COMPONENTS system)
24+
find_package(nlohmann_json REQUIRED)
25+
find_package(OpenCV REQUIRED)
26+
27+
set(COMMON_INTERFACES_INCLUDE "/home/ws/install/common_interfaces_cpp/include")
28+
set(COMMON_INTERFACES_LIB "/home/ws/install/common_interfaces_cpp/lib/libcommon_interfaces_cpp.so")
29+
30+
set(WEBGUI_ROS_DEPS rclcpp geometry_msgs std_msgs nav_msgs sensor_msgs cv_bridge)
31+
set(WEBGUI_SYS_DEPS Frequency Boost::system nlohmann_json::nlohmann_json ${OpenCV_LIBS})
32+
set(HAL_ROS_DEPS rclcpp geometry_msgs sensor_msgs nav_msgs cv_bridge)
33+
set(HAL_SYS_DEPS ${OpenCV_LIBS})
34+
35+
# --- libFrequency.so ---
36+
add_library(Frequency SHARED src/Frequency.cpp)
37+
target_include_directories(Frequency PUBLIC include)
38+
39+
# --- libWebGUI.so ---
40+
add_library(WebGUI SHARED
41+
src/WebGUI.cpp
42+
src/Map.cpp
43+
)
44+
target_include_directories(WebGUI PUBLIC include ${COMMON_INTERFACES_INCLUDE} ${OpenCV_INCLUDE_DIRS})
45+
ament_target_dependencies(WebGUI ${WEBGUI_ROS_DEPS})
46+
target_link_libraries(WebGUI ${WEBGUI_SYS_DEPS} ${COMMON_INTERFACES_LIB})
47+
48+
# --- libHAL.so ---
49+
add_library(HAL SHARED src/HAL.cpp)
50+
target_include_directories(HAL PUBLIC include ${COMMON_INTERFACES_INCLUDE} ${OpenCV_INCLUDE_DIRS})
51+
ament_target_dependencies(HAL ${HAL_ROS_DEPS})
52+
target_link_libraries(HAL ${HAL_SYS_DEPS} ${COMMON_INTERFACES_LIB})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef INCLUDE_FREQUENCY_HPP_
2+
#define INCLUDE_FREQUENCY_HPP_
3+
4+
#include <chrono>
5+
#include <cmath>
6+
#include <thread>
7+
8+
class Frequency
9+
{
10+
private:
11+
std::chrono::high_resolution_clock::time_point last_time;
12+
int is_first_iteration;
13+
14+
public:
15+
Frequency();
16+
~Frequency();
17+
18+
static int rate;
19+
void tick(int ideal_cycle = 50);
20+
};
21+
22+
#endif
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef INCLUDE_HAL_HPP_
2+
#define INCLUDE_HAL_HPP_
3+
4+
#include <memory>
5+
#include <thread>
6+
#include <vector>
7+
#include <array>
8+
9+
class MotorsNode;
10+
class OdometryNode;
11+
class LaserNode;
12+
namespace rclcpp::executors { class MultiThreadedExecutor; }
13+
14+
class HAL
15+
{
16+
public:
17+
HAL() = delete;
18+
19+
static void set_v(const float velocity);
20+
static void set_w(const float velocity);
21+
static std::array<double, 3> get_pose3d();
22+
static std::array<double, 3> get_odom();
23+
static std::vector<float> get_laser_data();
24+
25+
private:
26+
static void init();
27+
friend class SystemBootstrapper;
28+
29+
static std::shared_ptr<MotorsNode> motors_node_;
30+
static std::shared_ptr<OdometryNode> odometry_node_;
31+
static std::shared_ptr<OdometryNode> noisy_odometry_node_;
32+
static std::shared_ptr<LaserNode> laser_node_;
33+
static std::shared_ptr<rclcpp::executors::MultiThreadedExecutor> executor_;
34+
static std::thread spin_thread_;
35+
};
36+
37+
#endif
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef INCLUDE_MAP_HPP_
2+
#define INCLUDE_MAP_HPP_
3+
4+
#include <functional>
5+
#include <tuple>
6+
#include <opencv2/opencv.hpp>
7+
#include "common_interfaces_cpp/hal/odometry.hpp"
8+
9+
class Map
10+
{
11+
public:
12+
Map(std::function<Pose3d()> pose_getter, std::function<Pose3d()> noisy_pose_getter);
13+
14+
cv::Mat rtx(double angle, double tx, double ty, double tz);
15+
cv::Mat rty(double angle, double tx, double ty, double tz);
16+
cv::Mat rtz(double angle, double tx, double ty, double tz);
17+
cv::Mat rt_vacuum();
18+
19+
std::tuple<double, double, double> get_robot_coordinates();
20+
std::tuple<double, double, double> get_robot_coordinates_with_noise();
21+
22+
void reset();
23+
24+
private:
25+
std::function<Pose3d()> pose_getter_;
26+
std::function<Pose3d()> noisy_pose_getter_;
27+
};
28+
29+
#endif
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef INCLUDE_WEBGUI_HPP_
2+
#define INCLUDE_WEBGUI_HPP_
3+
4+
#include <opencv2/opencv.hpp>
5+
#include <vector>
6+
#include <memory>
7+
#include <thread>
8+
9+
class WebGUINode;
10+
namespace rclcpp::executors { class MultiThreadedExecutor; }
11+
12+
class WebGUI
13+
{
14+
public:
15+
WebGUI() = delete;
16+
17+
static void set_user_map(const cv::Mat& image);
18+
static std::vector<double> pose_to_map(double x_prime, double y_prime, double yaw_prime);
19+
20+
private:
21+
static void init();
22+
friend class SystemBootstrapper;
23+
24+
static std::shared_ptr<WebGUINode> gui_node_;
25+
static std::shared_ptr<rclcpp::executors::MultiThreadedExecutor> executor_;
26+
static std::thread spin_thread_;
27+
};
28+
29+
#endif
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include "Frequency.hpp"
2+
3+
int Frequency::rate = 0;
4+
5+
Frequency::Frequency() : is_first_iteration(1) {}
6+
7+
Frequency::~Frequency() {}
8+
9+
void Frequency::tick(int ideal_cycle)
10+
{
11+
const auto ideal_ms = std::chrono::milliseconds(1000 / ideal_cycle);
12+
const auto now = std::chrono::high_resolution_clock::now();
13+
14+
if (is_first_iteration == 1)
15+
{
16+
last_time = now;
17+
is_first_iteration = 0;
18+
return;
19+
}
20+
21+
const auto iter_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_time);
22+
23+
if (iter_ms < ideal_ms)
24+
{
25+
rate = std::round(1000.0 / ideal_ms.count());
26+
std::this_thread::sleep_for(ideal_ms - iter_ms);
27+
}
28+
else
29+
{
30+
rate = std::round(1000.0 / iter_ms.count());
31+
}
32+
33+
last_time = now;
34+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include "HAL.hpp"
2+
#include "common_interfaces_cpp/hal/motors.hpp"
3+
#include "common_interfaces_cpp/hal/odometry.hpp"
4+
#include "common_interfaces_cpp/hal/laser.hpp"
5+
#include "rclcpp/rclcpp.hpp"
6+
#include <chrono>
7+
8+
using namespace std::chrono_literals;
9+
10+
std::shared_ptr<MotorsNode> HAL::motors_node_ = nullptr;
11+
std::shared_ptr<OdometryNode> HAL::odometry_node_ = nullptr;
12+
std::shared_ptr<OdometryNode> HAL::noisy_odometry_node_ = nullptr;
13+
std::shared_ptr<LaserNode> HAL::laser_node_ = nullptr;
14+
std::shared_ptr<rclcpp::executors::MultiThreadedExecutor> HAL::executor_ = nullptr;
15+
std::thread HAL::spin_thread_;
16+
17+
void HAL::init()
18+
{
19+
if (!motors_node_) {
20+
odometry_node_ = std::make_shared<OdometryNode>("/turtlebot3/odom", "hal_odometry");
21+
noisy_odometry_node_ = std::make_shared<OdometryNode>("/turtlebot3/odom_noisy", "hal_noisy_odometry_node");
22+
motors_node_ = std::make_shared<MotorsNode>("/turtlebot3/cmd_vel", 4.0, 0.3, "hal_motors");
23+
laser_node_ = std::make_shared<LaserNode>("/turtlebot3/laser/scan", "hal_laser");
24+
25+
executor_ = std::make_shared<rclcpp::executors::MultiThreadedExecutor>();
26+
executor_->add_node(odometry_node_);
27+
executor_->add_node(noisy_odometry_node_);
28+
executor_->add_node(motors_node_);
29+
executor_->add_node(laser_node_);
30+
31+
spin_thread_ = std::thread([]() {
32+
executor_->spin();
33+
});
34+
spin_thread_.detach();
35+
}
36+
}
37+
38+
void HAL::set_v(const float velocity)
39+
{
40+
if (motors_node_) motors_node_->sendV(static_cast<double>(velocity));
41+
}
42+
43+
void HAL::set_w(const float velocity)
44+
{
45+
if (motors_node_) motors_node_->sendW(static_cast<double>(velocity));
46+
}
47+
48+
std::array<double, 3> HAL::get_pose3d()
49+
{
50+
if (!odometry_node_) return {0.0, 0.0, 0.0};
51+
52+
auto raw_pose = odometry_node_->getPose3d();
53+
return {raw_pose.x, raw_pose.y, raw_pose.yaw};
54+
}
55+
56+
std::array<double, 3> HAL::get_odom()
57+
{
58+
if (!noisy_odometry_node_) return {0.0, 0.0, 0.0};
59+
60+
auto raw_pose = noisy_odometry_node_->getPose3d();
61+
return {raw_pose.x, raw_pose.y, raw_pose.yaw};
62+
}
63+
64+
std::vector<float> HAL::get_laser_data()
65+
{
66+
if (!laser_node_) return {};
67+
68+
auto raw_laser = laser_node_->getLaserData();
69+
while (raw_laser.values.empty() && rclcpp::ok()) {
70+
std::this_thread::sleep_for(5ms);
71+
raw_laser = laser_node_->getLaserData();
72+
}
73+
74+
return raw_laser.values;
75+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#include "Map.hpp"
2+
#include <cmath>
3+
4+
Map::Map(std::function<Pose3d()> pose_getter, std::function<Pose3d()> noisy_pose_getter)
5+
: pose_getter_(pose_getter), noisy_pose_getter_(noisy_pose_getter)
6+
{
7+
}
8+
9+
cv::Mat Map::rtx(double angle, double tx, double ty, double tz)
10+
{
11+
return (cv::Mat_<double>(4, 4) <<
12+
1, 0, 0, tx,
13+
0, std::cos(angle), -std::sin(angle), ty,
14+
0, std::sin(angle), std::cos(angle), tz,
15+
0, 0, 0, 1);
16+
}
17+
18+
cv::Mat Map::rty(double angle, double tx, double ty, double tz)
19+
{
20+
return (cv::Mat_<double>(4, 4) <<
21+
std::cos(angle), 0, std::sin(angle), tx,
22+
0, 1, 0, ty,
23+
-std::sin(angle), 0, std::cos(angle), tz,
24+
0, 0, 0, 1);
25+
}
26+
27+
cv::Mat Map::rtz(double angle, double tx, double ty, double tz)
28+
{
29+
return (cv::Mat_<double>(4, 4) <<
30+
std::cos(angle), -std::sin(angle), 0, tx,
31+
std::sin(angle), std::cos(angle), 0, ty,
32+
0, 0, 1, tz,
33+
0, 0, 0, 1);
34+
}
35+
36+
cv::Mat Map::rt_vacuum()
37+
{
38+
return rtz(CV_PI / 2.0, 50, 70, 0);
39+
}
40+
41+
std::tuple<double, double, double> Map::get_robot_coordinates()
42+
{
43+
Pose3d pose = pose_getter_();
44+
45+
double y = -23.53 * (-31.95 - pose.y);
46+
double x = -23.58 * (-20.36 - pose.x);
47+
48+
return {x, y, pose.yaw};
49+
}
50+
51+
std::tuple<double, double, double> Map::get_robot_coordinates_with_noise()
52+
{
53+
Pose3d pose = noisy_pose_getter_();
54+
55+
double y = -23.53 * (-31.95 - pose.y);
56+
double x = -23.58 * (-20.36 - pose.x);
57+
58+
return {x, y, pose.yaw};
59+
}
60+
61+
void Map::reset()
62+
{
63+
}

0 commit comments

Comments
 (0)