23 ROS_INFO(
"Particle concentration sensor is starting");
30 ROS_ERROR(
"Not loading sensor plugin since ROS has not been properly initialized");
35 unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
36 this->
rndGen = std::default_random_engine(seed);
56 this->
nodeHandle->getParam(
"~saturation", this->saturation);
60 if (this->
nodeHandle->hasParam(
"~noise_amplitude"))
61 this->
nodeHandle->getParam(
"~noise_amplitude", this->noiseAmp);
65 if (this->
nodeHandle->hasParam(
"~noise_sigma"))
66 this->
nodeHandle->getParam(
"~noise_sigma", this->noiseSigma);
74 if (this->
nodeHandle->hasParam(
"~use_geo_coordinates"))
76 "~use_geo_coordinates", this->useGeoCoordinates);
79 if (this->useGeoCoordinates)
81 GeographicLib::Geocentric earth(
82 GeographicLib::Constants::WGS84_a(),
83 GeographicLib::Constants::WGS84_f());
86 double longitude = -1;
90 this->
nodeHandle->getParam(
"~latitude", latitude);
91 this->
nodeHandle->getParam(
"~longitude", longitude);
93 this->
projection = GeographicLib::LocalCartesian(
94 latitude, longitude, 0, earth);
99 if (this->
nodeHandle->hasParam(
"~salinity_unit"))
100 this->
nodeHandle->getParam(
"~salinity_unit", this->salinityUnit);
108 if (this->
nodeHandle->hasParam(
"~reference_salinity_value"))
109 this->
nodeHandle->getParam(
"~reference_salinity_value",
110 this->referenceSalinityValue);
130 uuv_plume_msgs::ParticleConcentration>(
137 this->
nodeHandle->getParam(
"~use_odom", this->useOdom);
140 this->
nodeHandle->getParam(
"~use_gps", this->useGPS);
147 ROS_INFO(
"Using the odometry <nav_msgs::Odometry> as input for sensor position");
149 else if (this->
useGPS && this->useGeoCoordinates)
154 ROS_INFO(
"Using the GPS <sensor_msgs::NatSatFix> as input for sensor position");
160 ROS_INFO(
"Using the a frame ID as input for sensor position");
172 if (this->
nodeHandle->hasParam(
"~publish_salinity"))
173 this->
nodeHandle->getParam(
"~publish_salinity", this->publishSalinity);
177 uuv_plume_msgs::Salinity>(
"salinity", 1);
183 ROS_INFO(
"Particle concentration sensor running");
194 const sensor_msgs::PointCloud::ConstPtr &_msg)
204 geometry_msgs::TransformStamped childTransform;
205 std::string targetFrame = _msg->header.frame_id;
215 targetFrame.c_str(), sourceFrame.c_str());
219 this->
cartPos.x = childTransform.transform.translation.x;
220 this->
cartPos.y = childTransform.transform.translation.y;
221 this->
cartPos.z = childTransform.transform.translation.z;
237 double latitude, longitude, altitude;
239 this->
cartPos.x, this->cartPos.y, this->cartPos.z,
240 latitude, longitude, altitude);
253 double totalParticleConc = 0.0;
254 double smoothingParam;
256 double distToParticle;
262 for (
int i = 0; i < _msg->points.size(); i++)
265 distToParticle = std::sqrt(
266 std::pow(_msg->points[i].x - this->cartPos.x, 2) +
267 std::pow(_msg->points[i].y - this->cartPos.y, 2) +
268 std::pow(_msg->points[i].z - this->cartPos.z, 2));
270 smoothingParam = std::pow(initSmoothingLength +
271 this->
gamma * (currentTime - _msg->channels[0].values[i]), 1.5);
275 if (distToParticle >= 0 && distToParticle < smoothingParam)
277 6.0 * std::pow(distToParticle / smoothingParam, 2) +
278 3.0 * std::pow(distToParticle / smoothingParam, 3);
279 else if (distToParticle >= smoothingParam && distToParticle < 2 * smoothingParam)
280 particleConc = std::pow(2 - distToParticle / smoothingParam, 3);
284 particleConc *= 1 / (4 * M_PI * std::pow(smoothingParam, 3));
285 totalParticleConc += particleConc;
293 this->
salinityMsg.header.frame_id = _msg->header.frame_id;
304 this->salinityMsg.salinity += this->noiseAmp \
305 * this->noiseModel(this->rndGen);
317 const nav_msgs::Odometry::ConstPtr &_msg)
323 this->
cartPos.x = _msg->pose.pose.position.x;
324 this->
cartPos.y = _msg->pose.pose.position.y;
325 this->
cartPos.z = _msg->pose.pose.position.z;
331 const sensor_msgs::NavSatFix::ConstPtr &_msg)
338 this->
geoPos.latitude = _msg->latitude;
339 this->
geoPos.longitude = _msg->longitude;
340 this->
geoPos.altitude = _msg->altitude;
342 _msg->latitude, _msg->longitude, _msg->altitude,
343 this->cartPos.x, this->cartPos.y, this->cartPos.z);
ros::Subscriber odometrySub
Subscriber for odometry topic.
ros::Subscriber particlesSub
Subscriber for the plume particle point cloud.
#define ROS_INFO_NAMED(name,...)
double updateRate
Output topic's update rate.
void publish(const boost::shared_ptr< M > &message) const
uuv_plume_msgs::ParticleConcentration concentrationMsg
Plume concentration message.
bool useTFUpdate
Flag set if the TF update wrt the sensor frame ID.
bool publishSalinity
Flag to activate publishing the simulated salinity.
~CPCSensor()
Class destructor.
ROSCPP_DECL bool isInitialized()
bool areParticlesInit
Flag set to true after the first set of plume particles is received.
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
std::normal_distribution< double > noiseModel
Normal distribution describing the noise model.
geographic_msgs::GeoPoint geoPos
Measured geodetic position.
ros::Subscriber gpsSub
Subscriber to the GPS update topic.
double gamma
Gamma velocity parameter for the smoothing function.
bool useGPS
Flag set if the sensor position update must be read from the vehicle's GPS topic. ...
void OnSensorUpdate(const ros::TimerEvent &)
Update the output concentration and salinity topics.
ros::Timer updateTimer
Sensor update timer.
double smoothingLength
Radius of the kernel to identify particles that will be taken into account in the concentration compu...
#define CONCENTRATION_UNIT_PPT
double noiseSigma
Noise standard deviation.
ros::Publisher concentrationPub
Output topic for particle concentration.
double referenceSalinityValue
Default salinity value for the fluid e.g. sea water.
double saturation
Sensor saturation.
ros::Publisher salinityPub
Output topic for salinity.
std::default_random_engine rndGen
Pseudo random number generator.
GeographicLib::LocalCartesian projection
Local Cartesian projection.
uuv_plume_msgs::Salinity salinityMsg
Salinity message.
bool useGeoCoordinates
Flag that will allow storing the geodetic coordinates with the measurement message.
std::shared_ptr< ros::NodeHandle > nodeHandle
ROS node handle.
std::string sensorFrameID
Name of the sensor frame.
void OnGPSUpdate(const sensor_msgs::NavSatFix::ConstPtr &_msg)
Update the GPS update callback.
bool updateMeasurement
Set to true to avoid particle update.
tf2_ros::Buffer tfBuffer
TF buffer instance.
uint32_t getNumSubscribers() const
std::string salinityUnit
Salinity unit to be used. Options are.
void OnPlumeParticlesUpdate(const sensor_msgs::PointCloud::ConstPtr &_msg)
Update callback from the plume particles.
std::shared_ptr< tf2_ros::TransformListener > tfListener
TF listener pointer.
void OnOdometryUpdate(const nav_msgs::Odometry::ConstPtr &_msg)
Update the odometry callback.
#define ROS_ERROR_NAMED(name,...)
bool updatingCloud
Flag to ensure the cloud and measurement update don't coincide.
geometry_msgs::Vector3 cartPos
Measured Cartesian position.
bool useOdom
Flag set if the sensor position update must be read from the vehicle's odometry input topic...
#define CONCENTRATION_UNIT_PSU
#define CONCENTRATION_UNIT_PPM
CPCSensor()
Class constructor.
double noiseAmp
Noise amplitude.