Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
raultapia committed Dec 19, 2023
0 parents commit efd7cac
Show file tree
Hide file tree
Showing 11 changed files with 1,264 additions and 0 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/documentation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Documentation

on:
push:
branches: [ main ]

jobs:
build-documentation:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Doxygen
uses: mattnotmitt/[email protected]
with:
doxyfile-path: Doxyfile
working-directory: docs

- name: Github Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/html/
publish_branch: gh-pages
32 changes: 32 additions & 0 deletions .github/workflows/submodule.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Submodule

on:
push:
branches: [ main ]

jobs:
update-submodule-branch:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Configure git
run: |
git config --global user.name "Raul Tapia"
git config --global user.email "[email protected]"
- name: Delete submodule branch
run: |
git push origin --delete submodule
continue-on-error: true

- name: Publish into submodule branch
run: |
mv include/rush/*.hpp .
rm -rf .github docs include .gitignore README.md LICENSE
git checkout -b submodule
git add .
git commit --amend -m "Auto-update RUSH"
git push origin submodule
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.clang-format
build/
cmake
CMakeLists.txt
Dockerfile
docs/*.svg
tests/
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!--
\cond INTERNAL
-->
<div align="center" style="margin-bottom: 10px;">
<a href="https://github.com/raultapia/rush">
<img src="https://github.com/raultapia/rush/blob/main/docs/rush.png?raw=true" alt="rush">
</a>
</div>
<p align="center">
Reusable Utilities in Single Headers is a collection of header-only utilities for C++
</p>
<!--
\endcond
-->

## ⚙️ Using RUSH in Your Project
```bash
git submodule add -b submodule https://github.com/raultapia/rush include/rush
```

## 🖥️ List of Utilities
|Name|Include|Namespace|
|:-|:-|:-:|
|Chrono|`#include <rush/chrono.hpp>`|`rush::chrono`|
|OpenCV HighGUI|`#include <rush/cv-highgui.hpp>`|`rush::cv`|
|ROS-OpenCV Bridge|`#include <rush/ros-cv-bridge.hpp>`|`rush::roscv`|
|ROS Parameter Manager|`#include <rush/ros-parameter-manager.hpp>`|`rush::ros`|

## 📚 Documentation
RUSH documentation can be found [here](https://raultapia.github.io/rush).

## 📝 License

Distributed under the GPLv3 License. See [`LICENSE`](https://github.com/raultapia/rush/tree/main/LICENSE) for more information.

## 📬 Contact

[Raul Tapia](https://raultapia.com) - [email protected]
9 changes: 9 additions & 0 deletions docs/Doxyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
PROJECT_NAME = RUSH
PROJECT_BRIEF = "Reusable Utilities in Single Headers is a collection of header-only utilities for C++"
PROJECT_LOGO = rush.png
USE_MDFILE_AS_MAINPAGE = ../README.md
GENERATE_HTML = YES
USE_MATHJAX = YES
RECURSIVE = YES
INPUT = ..
OUTPUT_DIRECTORY = .
Binary file added docs/rush.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
116 changes: 116 additions & 0 deletions include/rush/chrono.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* @file chrono.hpp
* @brief This library provides chrono utilities.
* @author Raul Tapia (raultapia.com)
*/
#ifndef RUSH_CHRONO_HPP
#define RUSH_CHRONO_HPP

#include <chrono>
#include <iostream>
#include <ratio>
#include <string>
#include <utility>

namespace rush::chrono {

/*! \cond INTERNAL */
#define DEFINE_UNIT_MACRO(name, unit) \
template <> \
struct Unit<name> { \
static constexpr const char *str() { \
return unit; \
} \
};

template <typename T>
struct Unit;

DEFINE_UNIT_MACRO(std::nano, "ns")
DEFINE_UNIT_MACRO(std::micro, "us")
DEFINE_UNIT_MACRO(std::milli, "ms")
DEFINE_UNIT_MACRO(std::ratio<1>, "s")
DEFINE_UNIT_MACRO(std::ratio<60>, "min")
DEFINE_UNIT_MACRO(std::ratio<3600>, "h")
DEFINE_UNIT_MACRO(std::ratio<86400>, "day")
/*! \endcond */

using ns = std::nano; ///< Convenience alias for nanoseconds
using us = std::micro; ///< Convenience alias for microseconds
using ms = std::milli; ///< Convenience alias for milliseconds
using s = std::ratio<1>; ///< Convenience alias for seconds
using min = std::ratio<60>; ///< Convenience alias for minutes
using hour = std::ratio<3600>; ///< Convenience alias for hours
using day = std::ratio<86400>; ///< Convenience alias for days

/**
* @brief A simple chrono class to measure elapsed time.
*
* @tparam T Unit of time (default to seconds).
*/
template <typename T = s>
class Chrono {
public:
Chrono() : t0_(std::chrono::high_resolution_clock::now()) {}
~Chrono() = default;
Chrono(const Chrono &) = delete;
Chrono(Chrono &&) noexcept = delete;
Chrono &operator=(const Chrono &) = delete;
Chrono &operator=(Chrono &&other) noexcept = delete;

/**
* @brief Reset the chrono timer.
*
*/
inline void tic() {
t0_ = std::chrono::high_resolution_clock::now();
}

/**
* @brief Get elapsed time since last tic.
*
* @return Elapsed time in the specified unit.
*/
[[nodiscard]] inline double toc() const {
return std::chrono::duration_cast<std::chrono::duration<double, T>>(std::chrono::high_resolution_clock::now() - t0_).count();
}

private:
std::chrono::time_point<std::chrono::high_resolution_clock> t0_;
};

/**
* @brief A chrono class that automatically prints elapsed time.
*
* @tparam T Unit of time (default to seconds).
*/
template <typename T = s>
class Chronometer : public Chrono<T> {
public:
/**
* @brief Constructor.
*
* @param name Optional name to be printed along with elapsed time.
*/
explicit Chronometer(std::string name = "") : name_{std::move(name)} {}

~Chronometer() {
double t = Chrono<T>::toc();
if(!name_.empty()) {
std::cout << "[" << name_ << "] ";
}
std::cout << "Elapsed time: " << t << " " << Unit<T>().str() << std::endl;
}

Chronometer(const Chronometer &) = delete;
Chronometer(Chronometer &&) noexcept = delete;
Chronometer &operator=(const Chronometer &) = delete;
Chronometer &operator=(Chronometer &&other) noexcept = delete;

private:
std::string name_;
};

} // namespace rush::chrono

#endif // RUSH_CHRONO_HPP
80 changes: 80 additions & 0 deletions include/rush/cv-highgui.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* @file cv-highgui.hpp
* @brief This library extends OpenCV's HighGUI functionalities.
* @author Raul Tapia (raultapia.com)
*/
#ifndef RUSH_CV_HIGHGUI_HPP
#define RUSH_CV_HIGHGUI_HPP

#include <algorithm>
#include <cstddef>
#include <opencv2/core.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/core/mat.inl.hpp>
#include <opencv2/core/types.hpp>
#include <opencv2/imgproc.hpp>
#include <vector>

namespace rush::cv {

/**
* @brief Create a montage from a matrix of images.
*
* This function takes a vector of vectors of images and creates a montage by resizing and concatenating them.
*
* @param images Vector of vectors of images.
* @return A single montage image.
*/
inline ::cv::Mat montage(std::vector<std::vector<::cv::Mat>> &images) {
::cv::Mat montage;
::cv::Size ref{images[0][0].size()};
std::size_t max_col = 0;

for(const std::vector<::cv::Mat> &v : images) {
for(const ::cv::Mat &i : v) {
if(i.size().area() < ref.area()) {
ref = i.size();
}
max_col = std::max(max_col, v.size());
}
}

std::vector<::cv::Mat> rows;
for(std::vector<::cv::Mat> &v : images) {
for(::cv::Mat &i : v) {
::cv::resize(i, i, ref);
}
while(v.size() < max_col) {
v.emplace_back(ref, images[0][0].type(), ::cv::Scalar(0));
}
rows.emplace_back(v.size() * ref.width, ref.height, images[0][0].type());
::cv::hconcat(v.data(), v.size(), rows.back());
}
::cv::vconcat(rows.data(), rows.size(), montage);
return montage;
}

/**
* @brief Create a montage from a vector of images with a specified step.
*
* This function takes a vector of images and creates a montage with a specified step by calling the main montage function.
*
* @param images Vector of images.
* @param step Step size for selecting images.
* @return A single montage image.
* @see montage(std::vector<std::vector<::cv::Mat>> &images)
*/
inline ::cv::Mat montage(std::vector<::cv::Mat> &images, std::size_t step = 0) {
std::vector<std::vector<::cv::Mat>> img_vector;
if(!static_cast<bool>(step)) {
step = images.size();
}
for(std::size_t i = 0; i < images.size(); i += step) {
img_vector.emplace_back(images.begin() + static_cast<long>(i), std::min(images.begin() + static_cast<long>(i + step), images.end()));
}
return montage(img_vector);
}

} // namespace rush::cv

#endif // RUSH_CV_HIGHGUI_HPP
Loading

0 comments on commit efd7cac

Please sign in to comment.