Skip to content

Commit e3582fc

Browse files
authored
Merge pull request #15 from IOES-Lab/sonar_ws_progress
Multibeam Sonar Migration Template
2 parents 197359e + 098e7f5 commit e3582fc

File tree

45 files changed

+5016
-26
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+5016
-26
lines changed

.docker/jazzy.amd64.dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ ADD https://raw.githubusercontent.com/IOES-Lab/dave/$BRANCH/\
6666
extras/repos/dave.$ROS_DISTRO.repos $DAVE_WS/dave.repos
6767
RUN vcs import --shallow --input $DAVE_WS/dave.repos
6868

69+
# FIX ROS GPG KEY error (may be temporary)
70+
RUN rm /etc/apt/sources.list.d/ros2.list && apt update && apt install -y jq && rm -rf /var/lib/apt/lists/
71+
RUN UBUNTU_CODENAME=noble && \
72+
ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | jq -r '.tag_name') && \
73+
curl -L -o /tmp/ros2-apt-source.deb \
74+
"https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.${UBUNTU_CODENAME}_all.deb" && \
75+
apt-get install -y /tmp/ros2-apt-source.deb && \
76+
rm -f /tmp/ros2-apt-source.deb
77+
6978
# Install dave dependencies
7079
RUN apt-get update && rosdep update && \
7180
rosdep install -iy --from-paths . && \

.pre-commit-config.yaml

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
repos:
2929
# Standard hooks
3030
- repo: https://github.com/pre-commit/pre-commit-hooks
31-
rev: v4.6.0
31+
rev: v5.0.0
3232
hooks:
3333
- id: check-added-large-files
3434
args: ["--maxkb=2000"]
@@ -48,7 +48,7 @@ repos:
4848

4949
# Python hooks
5050
- repo: https://github.com/asottile/pyupgrade
51-
rev: v3.16.0
51+
rev: v3.19.1
5252
hooks:
5353
- id: pyupgrade
5454
args: [--py36-plus]
@@ -62,20 +62,23 @@ repos:
6262
["--ignore=D100,D101,D102,D103,D104,D105,D106,D107,D203,D212,D404"]
6363

6464
- repo: https://github.com/psf/black
65-
rev: 24.4.2
65+
rev: 24.10.0
6666
hooks:
6767
- id: black
6868
args: ["--line-length=99", "--exclude=tools/code_check"]
6969

7070
- repo: https://github.com/pycqa/flake8
71-
rev: 7.1.0
71+
rev: 7.1.1
7272
hooks:
7373
- id: flake8
74-
args: ["--extend-ignore=E501", "--exclude=tools/code_check"]
74+
args:
75+
- "--ignore=E203,W503,E501"
76+
- "--exclude=tools/code_check"
77+
7578

7679
# CPP hooks
7780
- repo: https://github.com/pre-commit/mirrors-clang-format
78-
rev: v18.1.7
81+
rev: v19.1.6
7982
hooks:
8083
- id: clang-format
8184
args: ["-fallback-style=none", "-i"]
@@ -126,7 +129,7 @@ repos:
126129

127130
# Docs - RestructuredText hooks
128131
- repo: https://github.com/PyCQA/doc8
129-
rev: v1.1.1
132+
rev: v1.1.2
130133
hooks:
131134
- id: doc8
132135
args: ["--max-line-length=100", "--ignore=D001"]
@@ -151,7 +154,7 @@ repos:
151154

152155
# Json lint
153156
- repo: https://github.com/python-jsonschema/check-jsonschema
154-
rev: 0.28.6
157+
rev: 0.31.0
155158
hooks:
156159
- id: check-github-workflows
157160
args: ["--verbose"]
@@ -162,7 +165,7 @@ repos:
162165

163166
# XML lint for xacro, urdf, and sdf files
164167
- repo: https://github.com/pamoller/xmlformatter
165-
rev: v0.2.6
168+
rev: v0.2.8
166169
hooks:
167170
- id: xml-formatter
168171
name: Format XML

dave_interfaces/package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?><package format="3">
33
<name>dave_interfaces</name>
44
<version>0.0.0</version>
5-
<description>TODO: Package description</description>
5+
<description>Topic and Service Message Formats</description>
66
<maintainer email="helenamoyen@usp.br">lena</maintainer>
77
<maintainer email="gaurav.og.9920@gmail.com">Gaurav Kumar</maintainer>
88
<license>Apache 2.0</license>

examples/dave_demos/launch/dave_sensor.launch.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def launch_setup(context, *args, **kwargs):
1212
use_sim_time = LaunchConfiguration("use_sim_time")
1313
debug = LaunchConfiguration("debug")
1414
headless = LaunchConfiguration("headless")
15-
verbose = LaunchConfiguration("verbose")
15+
verbosity_level = LaunchConfiguration("verbosity_level")
1616
namespace = LaunchConfiguration("namespace")
1717
world_name = LaunchConfiguration("world_name")
1818
x = LaunchConfiguration("x")
@@ -38,8 +38,7 @@ def launch_setup(context, *args, **kwargs):
3838
if paused.perform(context) == "false":
3939
gz_args.append(" -r")
4040
if debug.perform(context) == "true":
41-
gz_args.append(" -v ")
42-
gz_args.append(verbose.perform(context))
41+
gz_args.append(f"-v {verbosity_level.perform(context)}")
4342

4443
gz_sim_launch = IncludeLaunchDescription(
4544
PythonLaunchDescriptionSource(
@@ -117,9 +116,9 @@ def generate_launch_description():
117116
description="Flag to enable the gazebo headless mode",
118117
),
119118
DeclareLaunchArgument(
120-
"verbose",
121-
default_value="0",
122-
description="Adjust level of console verbosity",
119+
"verbosity_level",
120+
default_value="1",
121+
description="Verbosity level for Gazebo if debug is enabled (0-4)",
123122
),
124123
DeclareLaunchArgument(
125124
"world_name",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# DAVE Multibeam Sonar Plugin
2+
3+
The DAVE multibeam sonar plugin, adapted for ROS 2 Jazzy and Gazebo Harmonic, uses a ray-based multibeam model that simulates phase, reverberation, and speckle noise through a point scattering approach. It generates realistic intensity-range (A-plot) data while accounting for time and angular ambiguities as well as speckle noise.
4+
5+
> **System Requirement**:
6+
> An **NVIDIA graphics card with CUDA compatibility** is required to use the sonar plugin. This enables GPU-accelerated simulation for real-time performance.
7+
8+
**Documentation**
9+
10+
The documentation for the plugin and tutorial can be found here: [Wiki](https://dave-ros2.notion.site/Multibeam-Sonar-Plugin-223661362ab2803b873bda4878fc55a8)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#ifndef GZ_SENSORS_ACOUSTICBEAM_HH_
2+
#define GZ_SENSORS_ACOUSTICBEAM_HH_
3+
4+
#include <cmath>
5+
#include <gz/math/Angle.hh>
6+
#include <gz/math/Pose3.hh>
7+
#include <gz/math/Quaternion.hh>
8+
#include <gz/math/Vector2.hh>
9+
#include <gz/math/Vector3.hh>
10+
#include <string>
11+
#include "AxisAlignedPatch2.hh"
12+
13+
namespace gz::sensors
14+
{
15+
16+
class AcousticBeam
17+
{
18+
public:
19+
AcousticBeam(
20+
int _id, const gz::math::Angle & _apertureAngle, const gz::math::Angle & _rotationAngle,
21+
const gz::math::Angle & _tiltAngle)
22+
: id(_id),
23+
apertureAngle(_apertureAngle),
24+
normalizedRadius(std::atan(_apertureAngle.Radian() / 2.))
25+
{
26+
using Quaterniond = gz::math::Quaterniond;
27+
28+
// Rotação extrínseca XY (rot_x * rot_y)
29+
this->transform.Rot() = Quaterniond::EulerToQuaternion(_rotationAngle.Radian(), 0., 0.) *
30+
Quaterniond::EulerToQuaternion(0., _tiltAngle.Radian(), 0.);
31+
32+
this->axis = this->transform.Rot() * gz::math::Vector3d::UnitX;
33+
34+
const gz::math::Angle azimuthAngle = std::atan2(this->axis.Y(), this->axis.X());
35+
const gz::math::Angle inclinationAngle = std::atan2(
36+
this->axis.Z(), std::sqrt(this->axis.X() * this->axis.X() + this->axis.Y() * this->axis.Y()));
37+
38+
const gz::math::Vector2d topLeft{
39+
(azimuthAngle + _apertureAngle / 2.).Radian(),
40+
(inclinationAngle + _apertureAngle / 2.).Radian()};
41+
42+
const gz::math::Vector2d bottomRight{
43+
(azimuthAngle - _apertureAngle / 2.).Radian(),
44+
(inclinationAngle - _apertureAngle / 2.).Radian()};
45+
46+
this->sphericalFootprint = AxisAlignedPatch2d{topLeft, bottomRight};
47+
}
48+
49+
int Id() const { return this->id; }
50+
const gz::math::Pose3d & Transform() const { return this->transform; }
51+
const gz::math::Vector3d & Axis() const { return this->axis; }
52+
double NormalizedRadius() const { return this->normalizedRadius; }
53+
const gz::math::Angle & ApertureAngle() const { return this->apertureAngle; }
54+
const AxisAlignedPatch2d & SphericalFootprint() const { return this->sphericalFootprint; }
55+
56+
private:
57+
int id;
58+
gz::math::Angle apertureAngle;
59+
double normalizedRadius;
60+
gz::math::Pose3d transform;
61+
gz::math::Vector3d axis;
62+
AxisAlignedPatch2d sphericalFootprint;
63+
};
64+
65+
/// \brief Acoustic beam reflecting target.
66+
/// Pose is defined w.r.t. the beams frame.
67+
struct ObjectTarget
68+
{
69+
gz::math::Pose3d pose;
70+
uint64_t entity;
71+
std::string name;
72+
};
73+
74+
} // namespace gz::sensors
75+
76+
#endif // GZ_SENSORS_ACOUSTIC_BEAM_HH_
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#ifndef GZ_SENSORS_AXISALIGNEDPATCH2_HH_
2+
#define GZ_SENSORS_AXISALIGNEDPATCH2_HH_
3+
4+
#include <algorithm>
5+
#include <gz/math/Vector2.hh>
6+
7+
namespace gz::sensors
8+
{
9+
10+
/// \brief Axis-aligned patch on a plane, using image frame conventions.
11+
template <typename T>
12+
class AxisAlignedPatch2
13+
{
14+
public:
15+
AxisAlignedPatch2() = default;
16+
17+
AxisAlignedPatch2(
18+
const gz::math::Vector2<T> & _topLeft, const gz::math::Vector2<T> & _bottomRight)
19+
: topLeft(_topLeft), bottomRight(_bottomRight)
20+
{
21+
}
22+
23+
/// Scalar converting copy constructor
24+
template <typename U>
25+
AxisAlignedPatch2(const AxisAlignedPatch2<U> & _other)
26+
{
27+
this->topLeft.X(static_cast<T>(_other.XMax()));
28+
this->topLeft.Y(static_cast<T>(_other.YMax()));
29+
this->bottomRight.X(static_cast<T>(_other.XMin()));
30+
this->bottomRight.Y(static_cast<T>(_other.YMin()));
31+
}
32+
33+
T XMax() const { return this->topLeft.X(); }
34+
T XMin() const { return this->bottomRight.X(); }
35+
T XSize() const { return this->XMax() - this->XMin(); }
36+
37+
T YMax() const { return this->topLeft.Y(); }
38+
T YMin() const { return this->bottomRight.Y(); }
39+
T YSize() const { return this->YMax() - this->YMin(); }
40+
41+
/// Merge patch with `_other`. Returns *this
42+
AxisAlignedPatch2<T> & Merge(const AxisAlignedPatch2<T> & _other)
43+
{
44+
this->topLeft.Set(
45+
std::max(this->topLeft.X(), _other.topLeft.X()),
46+
std::max(this->topLeft.Y(), _other.topLeft.Y()));
47+
this->bottomRight.Set(
48+
std::min(this->bottomRight.X(), _other.bottomRight.X()),
49+
std::min(this->bottomRight.Y(), _other.bottomRight.Y()));
50+
return *this;
51+
}
52+
53+
AxisAlignedPatch2<T> Flip() const { return {-this->bottomRight, -this->topLeft}; }
54+
55+
const AxisAlignedPatch2<T> operator*(gz::math::Vector2<T> _vector) const
56+
{
57+
return {this->topLeft * _vector, this->bottomRight * _vector};
58+
}
59+
60+
const AxisAlignedPatch2<T> operator/(gz::math::Vector2<T> _vector) const
61+
{
62+
return {this->topLeft / _vector, this->bottomRight / _vector};
63+
}
64+
65+
const AxisAlignedPatch2<T> operator+(gz::math::Vector2<T> _vector) const
66+
{
67+
return {this->topLeft + _vector, this->bottomRight + _vector};
68+
}
69+
70+
const AxisAlignedPatch2<T> operator-(gz::math::Vector2<T> _vector) const
71+
{
72+
return {this->topLeft - _vector, this->bottomRight - _vector};
73+
}
74+
75+
private:
76+
gz::math::Vector2<T> topLeft;
77+
gz::math::Vector2<T> bottomRight;
78+
};
79+
80+
// Handy typedefs
81+
using AxisAlignedPatch2d = AxisAlignedPatch2<double>;
82+
using AxisAlignedPatch2i = AxisAlignedPatch2<int>;
83+
84+
} // namespace gz::sensors
85+
86+
#endif // GZ_SENSORS_AXISALIGNEDPATCH2_HH_

0 commit comments

Comments
 (0)