Skip to content

Commit 1689f53

Browse files
authored
Merge pull request #701 from JdeRobot/cpp_common_interfaces
Cpp common interfaces
2 parents 40fb5b2 + 37ffc79 commit 1689f53

19 files changed

Lines changed: 1000 additions & 2 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
project(common_interfaces_cpp)
3+
4+
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
5+
add_compile_options(-Wall -Wextra -Wpedantic)
6+
endif()
7+
8+
# Define a list of ROS 2 dependencies for easy modularity
9+
set(ros2_dependencies
10+
rclcpp
11+
nav_msgs
12+
sensor_msgs
13+
geometry_msgs
14+
gazebo_msgs
15+
rosgraph_msgs
16+
cv_bridge
17+
ros_gz_interfaces
18+
)
19+
20+
# Find ament_cmake (required for the build system itself)
21+
find_package(ament_cmake REQUIRED)
22+
23+
# Loop through the list to find all specified ROS 2 packages automatically
24+
foreach(dependency IN LISTS ros2_dependencies)
25+
find_package(${dependency} REQUIRED)
26+
endforeach()
27+
28+
# Find OpenCV explicitly (Required by Camera and Classnet for cv::Mat and cv::dnn)
29+
find_package(OpenCV REQUIRED)
30+
31+
# Create the shared library from the source files matching the new structure
32+
add_library(${PROJECT_NAME} SHARED
33+
src/hal/bumper.cpp
34+
src/hal/camera.cpp
35+
src/hal/classnet.cpp
36+
src/hal/laser.cpp
37+
src/hal/lidar.cpp
38+
src/hal/motors.cpp
39+
src/hal/odometry.cpp
40+
src/hal/sim_time.cpp
41+
)
42+
43+
# Specify the include directories so the compiler finds the .hpp files
44+
target_include_directories(${PROJECT_NAME} PUBLIC
45+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
46+
$<INSTALL_INTERFACE:include>
47+
${OpenCV_INCLUDE_DIRS}
48+
)
49+
50+
# Link all listed ROS 2 dependencies and OpenCV to the library
51+
ament_target_dependencies(${PROJECT_NAME} ${ros2_dependencies})
52+
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBRARIES})
53+
54+
# Install the include directory so other packages can do #include
55+
install(DIRECTORY include/
56+
DESTINATION include
57+
)
58+
59+
# Install the library and export the target for downstream usage
60+
install(TARGETS ${PROJECT_NAME}
61+
EXPORT ${PROJECT_NAME}
62+
ARCHIVE DESTINATION lib
63+
LIBRARY DESTINATION lib
64+
RUNTIME DESTINATION bin
65+
)
66+
67+
# Export include directories, targets, and dependencies
68+
ament_export_include_directories(include)
69+
ament_export_targets(${PROJECT_NAME} HAS_LIBRARY_TARGET)
70+
ament_export_dependencies(${ros2_dependencies})
71+
72+
ament_package()
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#ifndef COMMON_INTERFACES_CPP__BUMPER_HPP_
2+
#define COMMON_INTERFACES_CPP__BUMPER_HPP_
3+
4+
#include <vector>
5+
#include <string>
6+
#include "rclcpp/rclcpp.hpp"
7+
#include "ros_gz_interfaces/msg/contacts.hpp"
8+
9+
/* ### AUXILIARY FUNCTIONS ### */
10+
11+
const int RIGHT_BUMPER = 0;
12+
const int CENTER_BUMPER = 1;
13+
const int LEFT_BUMPER = 2;
14+
15+
class BumperData {
16+
public:
17+
BumperData();
18+
int state;
19+
int bumper;
20+
21+
std::string to_string() const;
22+
};
23+
24+
BumperData contactsToBumperData(const std::vector<ros_gz_interfaces::msg::Contacts>& contacts);
25+
26+
/* ### HAL INTERFACE ### */
27+
class BumperNode : public rclcpp::Node {
28+
public:
29+
BumperNode(const std::vector<std::string>& topics);
30+
BumperData getBumperData() const;
31+
32+
private:
33+
void right_callback(const ros_gz_interfaces::msg::Contacts::SharedPtr contact);
34+
void center_callback(const ros_gz_interfaces::msg::Contacts::SharedPtr contact);
35+
void left_callback(const ros_gz_interfaces::msg::Contacts::SharedPtr contact);
36+
37+
std::vector<std::string> topics;
38+
std::vector<rclcpp::Subscription<ros_gz_interfaces::msg::Contacts>::SharedPtr> subs_;
39+
std::vector<ros_gz_interfaces::msg::Contacts> contact_states_;
40+
};
41+
42+
#endif
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#ifndef COMMON_INTERFACES_CPP__CAMERA_HPP_
2+
#define COMMON_INTERFACES_CPP__CAMERA_HPP_
3+
4+
#include <string>
5+
#include <memory>
6+
#include "rclcpp/rclcpp.hpp"
7+
#include "sensor_msgs/msg/image.hpp"
8+
#include <opencv2/opencv.hpp>
9+
#include <cv_bridge/cv_bridge.h>
10+
11+
/* ### AUXILIARY FUNCTIONS ### */
12+
13+
const int MAXRANGE = 8; // max length received from imageD
14+
const int MINRANGE = 0;
15+
16+
/* Represents a camera image with metadata and pixel data. */
17+
class Image {
18+
public:
19+
Image();
20+
int height; // Image height [pixels]
21+
int width; // Image width [pixels]
22+
double timeStamp; // Time stamp [s] */
23+
std::string format; // Image format string (RGB8, BGR,...)
24+
cv::Mat data; // The image data itself
25+
26+
std::string to_string() const;
27+
};
28+
29+
// Declaración de función auxiliar implícita en tu código Python
30+
cv::Mat depthToRGB8(const cv::Mat& gray_img_buff, const std::string& encoding);
31+
32+
/*
33+
* Convert a ROS Image message to a JdeRobot Image object.
34+
*
35+
* Args:
36+
* img: ROS sensor_msgs/Image message.
37+
*
38+
* Returns:
39+
* Image object with BGR data, or None if the message is empty.
40+
*/
41+
std::shared_ptr<Image> imageMsg2Image(const sensor_msgs::msg::Image& img);
42+
43+
/* ### HAL INTERFACE ### */
44+
45+
/* ROS2 node that subscribes to a camera topic and stores the latest image. */
46+
class CameraNode : public rclcpp::Node {
47+
public:
48+
CameraNode(const std::string& topic);
49+
50+
/*
51+
* Return the latest camera image.
52+
*
53+
* Returns:
54+
* Image object with BGR data, or None if no image has been received.
55+
*/
56+
std::shared_ptr<Image> getImage() const;
57+
58+
private:
59+
/* Store the latest image message received from the topic. */
60+
void listener_callback(const sensor_msgs::msg::Image::SharedPtr msg);
61+
62+
rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr sub_;
63+
sensor_msgs::msg::Image last_img_;
64+
};
65+
66+
#endif
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#ifndef COMMON_INTERFACES_CPP__CLASSNET_HPP_
2+
#define COMMON_INTERFACES_CPP__CLASSNET_HPP_
3+
4+
#include <string>
5+
#include <vector>
6+
#include <map>
7+
#include <opencv2/opencv.hpp>
8+
#include <opencv2/dnn.hpp>
9+
10+
extern const std::string FROZEN_GRAPH;
11+
extern const std::string PB_TXT;
12+
extern const int SIZE;
13+
14+
extern std::map<int, std::string> LABEL_MAP;
15+
16+
class BoundingBox {
17+
public:
18+
BoundingBox(int identifier, const std::string& class_id_str, float score, float xmin, float ymin, float xmax, float ymax);
19+
20+
int id;
21+
std::string class_id;
22+
float score;
23+
float xmin;
24+
float ymin;
25+
float xmax;
26+
float ymax;
27+
28+
std::string to_string() const;
29+
};
30+
31+
class NeuralNetwork {
32+
public:
33+
NeuralNetwork();
34+
cv::Mat detect(const cv::Mat& img);
35+
36+
// Get bounding boxes function
37+
std::vector<BoundingBox> getBoundingBoxes(const cv::Mat& img);
38+
39+
private:
40+
cv::dnn::Net net;
41+
};
42+
43+
#endif
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#ifndef COMMON_INTERFACES_CPP__LASER_HPP_
2+
#define COMMON_INTERFACES_CPP__LASER_HPP_
3+
4+
#include <vector>
5+
#include <string>
6+
#include "rclcpp/rclcpp.hpp"
7+
#include "sensor_msgs/msg/laser_scan.hpp"
8+
9+
/* ### AUXILIARY FUNCTIONS */
10+
11+
class LaserData {
12+
public:
13+
LaserData();
14+
std::vector<float> values; // meters
15+
double minAngle; // Angle of first value (rads)
16+
double maxAngle; // Angle of last value (rads)
17+
double minRange; // Min Range possible (meters)
18+
double maxRange; // Max Range possible (meters)
19+
double timeStamp; // seconds
20+
21+
std::string to_string() const;
22+
};
23+
24+
/*
25+
* Translates from ROS LaserScan to JderobotTypes LaserData.
26+
* @param scan: ROS LaserScan to translate
27+
* @type scan: LaserScan
28+
* @return a LaserData translated from scan
29+
*/
30+
LaserData laserScan2LaserData(const sensor_msgs::msg::LaserScan& scan);
31+
32+
33+
/* ### HAL INTERFACE ### */
34+
class LaserNode : public rclcpp::Node {
35+
public:
36+
LaserNode(const std::string& topic);
37+
LaserData getLaserData() const;
38+
39+
private:
40+
void listener_callback(const sensor_msgs::msg::LaserScan::SharedPtr scan);
41+
42+
rclcpp::Subscription<sensor_msgs::msg::LaserScan>::SharedPtr sub_;
43+
sensor_msgs::msg::LaserScan last_scan_;
44+
};
45+
46+
#endif
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#ifndef COMMON_INTERFACES_CPP__LIDAR_HPP_
2+
#define COMMON_INTERFACES_CPP__LIDAR_HPP_
3+
4+
#include <vector>
5+
#include <string>
6+
#include <memory>
7+
#include <mutex>
8+
#include <array>
9+
#include "rclcpp/rclcpp.hpp"
10+
#include "sensor_msgs/msg/point_cloud2.hpp"
11+
12+
class LidarData {
13+
public:
14+
LidarData();
15+
std::vector<std::array<float, 3>> points;
16+
std::vector<float> intensities;
17+
double timeStamp;
18+
double min_range;
19+
double max_range;
20+
std::pair<double, double> field_of_view;
21+
bool is_dense;
22+
23+
std::string to_string() const;
24+
};
25+
26+
LidarData pointCloud2LidarData(const sensor_msgs::msg::PointCloud2::SharedPtr cloud);
27+
28+
class LidarNode : public rclcpp::Node {
29+
public:
30+
LidarNode(const std::string& topic);
31+
LidarData getLidarData();
32+
sensor_msgs::msg::PointCloud2::SharedPtr get_point_cloud();
33+
34+
private:
35+
void pointcloud_callback(const sensor_msgs::msg::PointCloud2::SharedPtr cloud);
36+
37+
std::mutex lock_;
38+
sensor_msgs::msg::PointCloud2::SharedPtr last_cloud_;
39+
rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr sub_;
40+
};
41+
42+
#endif
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef COMMON_INTERFACES_CPP__MOTORS_HPP_
2+
#define COMMON_INTERFACES_CPP__MOTORS_HPP_
3+
4+
#include <string>
5+
#include "rclcpp/rclcpp.hpp"
6+
#include "geometry_msgs/msg/twist.hpp"
7+
8+
/* ### HAL INTERFACE ### */
9+
10+
/* ROS2 node that publishes linear and angular velocity commands to a robot. */
11+
class MotorsNode : public rclcpp::Node {
12+
public:
13+
MotorsNode(const std::string& topic, double maxV, double maxW);
14+
15+
/* Publish a linear velocity command.
16+
*
17+
* Args:
18+
* v (float): Linear velocity in m/s.
19+
*/
20+
void sendV(double v);
21+
22+
/* Publish an angular velocity command.
23+
*
24+
* Args:
25+
* w (float): Angular velocity in rad/s.
26+
*/
27+
void sendW(double w);
28+
29+
private:
30+
rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr pub;
31+
geometry_msgs::msg::Twist last_twist;
32+
};
33+
34+
#endif
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef COMMON_INTERFACES_CPP__ODOMETRY_HPP_
2+
#define COMMON_INTERFACES_CPP__ODOMETRY_HPP_
3+
4+
#include <vector>
5+
#include <string>
6+
#include "rclcpp/rclcpp.hpp"
7+
#include "nav_msgs/msg/odometry.hpp"
8+
9+
struct Pose3d {
10+
double x, y, z, h, yaw, pitch, roll, timeStamp;
11+
std::vector<double> q;
12+
std::string to_string() const;
13+
};
14+
15+
double quat2Yaw(double qw, double qx, double qy, double qz);
16+
double quat2Pitch(double qw, double qx, double qy, double qz);
17+
double quat2Roll(double qw, double qx, double qy, double qz);
18+
Pose3d odometry2Pose3D(const nav_msgs::msg::Odometry& odom);
19+
20+
class OdometryNode : public rclcpp::Node {
21+
public:
22+
OdometryNode(const std::string& topic, const std::string& node_name = "odometry_node");
23+
Pose3d getPose3d() const;
24+
25+
private:
26+
void listener_callback(const nav_msgs::msg::Odometry::SharedPtr msg);
27+
rclcpp::Subscription<nav_msgs::msg::Odometry>::SharedPtr sub_;
28+
nav_msgs::msg::Odometry last_pose_;
29+
};
30+
31+
#endif

0 commit comments

Comments
 (0)