1
+ #include " dave_gz_sensor_plugins/sea_pressure_sensor.hh"
2
+ #include < gz/msgs/fluid_pressure.pb.h>
3
+ #include < chrono>
4
+ #include < geometry_msgs/msg/point_stamped.hpp>
5
+ #include < gz/math/Pose3.hh>
6
+ #include < gz/math/Vector3.hh>
7
+ #include < gz/msgs/Utility.hh>
8
+ #include < gz/plugin/Register.hh>
9
+ #include < gz/sim/System.hh>
10
+ #include < gz/sim/World.hh>
11
+ #include < gz/sim/components/CustomSensor.hh>
12
+ #include < gz/sim/components/Link.hh>
13
+ #include < gz/sim/components/Name.hh>
14
+ #include < gz/sim/components/ParentEntity.hh>
15
+ #include < gz/sim/components/Pose.hh>
16
+ #include < gz/sim/components/Sensor.hh>
17
+ #include < gz/sim/components/World.hh>
18
+ #include < gz/transport/Node.hh>
19
+ #include < memory>
20
+ #include < rclcpp/rclcpp.hpp>
21
+ #include < sensor_msgs/msg/fluid_pressure.hpp>
22
+
23
+ GZ_ADD_PLUGIN (
24
+ dave_gz_sensor_plugins::SubseaPressureSensorPlugin, gz::sim::System,
25
+ dave_gz_sensor_plugins::SubseaPressureSensorPlugin::ISystemConfigure,
26
+ dave_gz_sensor_plugins::SubseaPressureSensorPlugin::ISystemPreUpdate,
27
+ dave_gz_sensor_plugins::SubseaPressureSensorPlugin::ISystemPostUpdate)
28
+
29
+ namespace dave_gz_sensor_plugins
30
+ {
31
+ struct SubseaPressureSensorPlugin ::PrivateData
32
+ {
33
+ public:
34
+ double saturation;
35
+ gz::sim::EntityComponentManager * ecm = nullptr ;
36
+ std::chrono::steady_clock::duration lastMeasurementTime{0 };
37
+ bool estimateDepth;
38
+ double standardPressure = 101.325 ;
39
+ double kPaPerM = 9.80638 ;
40
+ std::shared_ptr<gz::transport::Node> gazeboNode;
41
+ gz::transport::Node::Publisher gz_pressure_sensor_pub;
42
+ rclcpp::Publisher<sensor_msgs::msg::FluidPressure>::SharedPtr ros_pressure_sensor_pub;
43
+ rclcpp::Publisher<geometry_msgs::msg::PointStamped>::SharedPtr ros_depth_estimate_pub;
44
+ std::shared_ptr<rclcpp::Node> rosNode;
45
+ std::string robotNamespace;
46
+ double noiseAmp = 0.0 ;
47
+ double noiseSigma = 3.0 ;
48
+ double inferredDepth = 0.0 ;
49
+ double pressure = 0.0 ;
50
+ std::string modelName;
51
+ gz::sim::Entity modelEntity;
52
+ };
53
+
54
+ SubseaPressureSensorPlugin::SubseaPressureSensorPlugin () : dataPtr (std::make_unique<PrivateData>())
55
+ {
56
+ }
57
+
58
+ SubseaPressureSensorPlugin::~SubseaPressureSensorPlugin () {}
59
+
60
+ void SubseaPressureSensorPlugin::Configure (
61
+ const gz::sim::Entity & _entity, const std::shared_ptr<const sdf::Element> & _sdf,
62
+ gz::sim::EntityComponentManager & _ecm, gz::sim::EventManager & _eventManager)
63
+ {
64
+ if (!rclcpp::ok ())
65
+ {
66
+ rclcpp::init (0 , nullptr );
67
+ }
68
+
69
+ gzdbg << " dave_gz_sensor_plugins::SubseaPressureSensorPlugin::Configure on entity: " << _entity
70
+ << std::endl;
71
+
72
+ // Initialize the ROS 2 node
73
+ this ->rosNode = std::make_shared<rclcpp::Node>(" subsea_pressure_sensor" );
74
+
75
+ // Initialize the Gazebo node
76
+ this ->dataPtr ->gazeboNode = std::make_shared<gz::transport::Node>();
77
+
78
+ if (!_sdf->HasElement (" namespace" ))
79
+ {
80
+ gzerr << " Missing required parameter <namespace>, "
81
+ << " plugin will not be initialized." << std::endl;
82
+ return ;
83
+ }
84
+ this ->dataPtr ->robotNamespace = _sdf->Get <std::string>(" namespace" );
85
+
86
+ if (_sdf->HasElement (" saturation" ))
87
+ {
88
+ this ->dataPtr ->saturation = _sdf->Get <double >(" saturation" );
89
+ }
90
+ else
91
+ {
92
+ this ->dataPtr ->saturation = 3000 ;
93
+ }
94
+
95
+ if (_sdf->HasElement (" estimate_depth_on" ))
96
+ {
97
+ this ->dataPtr ->estimateDepth = _sdf->Get <bool >(" estimate_depth_on" );
98
+ }
99
+ else
100
+ {
101
+ this ->dataPtr ->estimateDepth = true ;
102
+ }
103
+
104
+ if (_sdf->HasElement (" standard_pressure" ))
105
+ {
106
+ this ->dataPtr ->standardPressure = _sdf->Get <double >(" standard_pressure" );
107
+ }
108
+ else
109
+ {
110
+ this ->dataPtr ->standardPressure = 101.325 ;
111
+ }
112
+
113
+ if (_sdf->HasElement (" kPa_per_meter" ))
114
+ {
115
+ this ->dataPtr ->kPaPerM = _sdf->Get <double >(" kPa_per_meter" );
116
+ }
117
+ else
118
+ {
119
+ this ->dataPtr ->kPaPerM = 9.80638 ;
120
+ }
121
+
122
+ // this->dataPtr->gazeboNode->Init();
123
+ this ->dataPtr ->modelEntity = GetModelEntity (this ->dataPtr ->robotNamespace , _ecm);
124
+
125
+ this ->dataPtr ->ros_pressure_sensor_pub =
126
+ this ->rosNode ->create_publisher <sensor_msgs::msg::FluidPressure>(
127
+ this ->dataPtr ->robotNamespace + " /" + " Pressure" , rclcpp::QoS (10 ).reliable ());
128
+
129
+ if (this ->dataPtr ->estimateDepth )
130
+ {
131
+ this ->dataPtr ->ros_depth_estimate_pub =
132
+ this ->rosNode ->create_publisher <geometry_msgs::msg::PointStamped>(
133
+ this ->dataPtr ->robotNamespace + " /" + " Pressure_depth" , rclcpp::QoS (10 ).reliable ());
134
+ }
135
+
136
+ this ->dataPtr ->gz_pressure_sensor_pub =
137
+ this ->dataPtr ->gazeboNode ->Advertise <gz::msgs::FluidPressure>(
138
+ this ->dataPtr ->robotNamespace + " /" + " Pressure" );
139
+ }
140
+ // ////////////////////////////////////////
141
+
142
+ gz::sim::Entity SubseaPressureSensorPlugin::GetModelEntity (
143
+ const std::string & modelName, gz::sim::EntityComponentManager & ecm)
144
+ {
145
+ gz::sim::Entity modelEntity = gz::sim::kNullEntity ;
146
+
147
+ ecm.Each <gz::sim::components::Name>(
148
+ [&](const gz::sim::Entity & entity, const gz::sim::components::Name * nameComp) -> bool
149
+ {
150
+ if (nameComp->Data () == modelName)
151
+ {
152
+ modelEntity = entity;
153
+ return false ; // Stop iteration
154
+ }
155
+ return true ; // Continue iteration
156
+ });
157
+
158
+ return modelEntity;
159
+ }
160
+
161
+ gz::math::Pose3d SubseaPressureSensorPlugin::GetModelPose (
162
+ const gz::sim::Entity & modelEntity, gz::sim::EntityComponentManager & ecm)
163
+ {
164
+ const auto * poseComp = ecm.Component <gz::sim::components::Pose>(modelEntity);
165
+ if (poseComp)
166
+ {
167
+ return poseComp->Data ();
168
+ }
169
+ else
170
+ {
171
+ gzerr << " Pose component not found for entity: " << modelEntity << std::endl;
172
+ return gz::math::Pose3d::Zero;
173
+ }
174
+ }
175
+
176
+ void SubseaPressureSensorPlugin::PreUpdate (
177
+ const gz::sim::UpdateInfo & _info, gz::sim::EntityComponentManager & _ecm)
178
+ {
179
+ // Get model pose
180
+ gz::math::Pose3d sea_pressure_sensor_pos = GetModelPose (this ->dataPtr ->modelEntity , _ecm);
181
+ double depth = std::abs (sea_pressure_sensor_pos.Z ());
182
+ this ->dataPtr ->pressure = this ->dataPtr ->standardPressure ;
183
+ if (depth >= 0 )
184
+ {
185
+ this ->dataPtr ->pressure += depth * this ->dataPtr ->kPaPerM ;
186
+ }
187
+
188
+ // not adding gaussian noise for now, Future Work (TODO)
189
+ // pressure += this->dataPtr->GetGaussianNoise(this->dataPtr->noiseAmp);
190
+ this ->dataPtr ->pressure += this ->dataPtr ->noiseAmp ; // noiseAmp is 0.0
191
+
192
+ // double inferredDepth = 0.0;
193
+ if (this ->dataPtr ->estimateDepth )
194
+ {
195
+ this ->dataPtr ->inferredDepth =
196
+ (this ->dataPtr ->pressure - this ->dataPtr ->standardPressure ) / this ->dataPtr ->kPaPerM ;
197
+ }
198
+ }
199
+
200
+ void SubseaPressureSensorPlugin::PostUpdate (
201
+ const gz::sim::UpdateInfo & _info, const gz::sim::EntityComponentManager & _ecm)
202
+ {
203
+ this ->dataPtr ->lastMeasurementTime = _info.simTime ;
204
+
205
+ // Publishing Sea_Pressure and depth estimate on gazebo topic
206
+ gz::msgs::FluidPressure gzPressureMsg;
207
+ gzPressureMsg.set_pressure (this ->dataPtr ->pressure );
208
+ gzPressureMsg.set_variance (this ->dataPtr ->noiseSigma * this ->dataPtr ->noiseSigma );
209
+
210
+ // Publishing the pressure message
211
+ this ->dataPtr ->gz_pressure_sensor_pub .Publish (gzPressureMsg);
212
+
213
+ // Publishing Sea_Pressure on Ros Topic
214
+ sensor_msgs::msg::FluidPressure rosPressureMsg;
215
+ rosPressureMsg.header .stamp .sec =
216
+ std::chrono::duration_cast<std::chrono::seconds>(_info.simTime ).count (); // Time in seconds
217
+ rosPressureMsg.header .stamp .nanosec =
218
+ std::chrono::duration_cast<std::chrono::nanoseconds>(_info.simTime ).count () %
219
+ 1000000000 ; // Time in nanoseconds
220
+ rosPressureMsg.fluid_pressure = this ->dataPtr ->pressure ;
221
+ rosPressureMsg.variance = this ->dataPtr ->noiseSigma * this ->dataPtr ->noiseSigma ;
222
+ this ->dataPtr ->ros_pressure_sensor_pub ->publish (rosPressureMsg);
223
+
224
+ // publishing depth message
225
+ if (this ->dataPtr ->estimateDepth )
226
+ {
227
+ geometry_msgs::msg::PointStamped rosDepthMsg;
228
+ rosDepthMsg.point .z = this ->dataPtr ->inferredDepth ;
229
+ rosDepthMsg.header .stamp .sec =
230
+ std::chrono::duration_cast<std::chrono::seconds>(this ->dataPtr ->lastMeasurementTime ).count ();
231
+ this ->dataPtr ->ros_depth_estimate_pub ->publish (rosDepthMsg);
232
+ }
233
+
234
+ if (!_info.paused )
235
+ {
236
+ rclcpp::spin_some (this ->rosNode );
237
+
238
+ if (_info.iterations % 1000 == 0 )
239
+ {
240
+ gzmsg << " dave_ros_gz_plugins::SubseaPressureSensorPlugin::PostUpdate" << std::endl;
241
+ }
242
+ }
243
+ }
244
+
245
+ } // namespace dave_gz_sensor_plugins
0 commit comments