Skip to content

Commit 6dda2df

Browse files
author
Tyler Lum
committed
Implement use of sonar msg
1 parent c3abc19 commit 6dda2df

File tree

1 file changed

+100
-4
lines changed

1 file changed

+100
-4
lines changed

src/stageros.cpp

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <boost/thread/mutex.hpp>
4444
#include <boost/thread/thread.hpp>
4545
#include <sensor_msgs/LaserScan.h>
46+
#include <sensor_msgs/Range.h>
4647
#include <sensor_msgs/Image.h>
4748
#include <sensor_msgs/image_encodings.h>
4849
#include <sensor_msgs/CameraInfo.h>
@@ -60,6 +61,7 @@
6061
#define CAMERA_INFO "camera_info"
6162
#define ODOM "odom"
6263
#define BASE_SCAN "base_scan"
64+
#define SONAR "sonar/range" // should later change to just "sonar" and add "/range" in later naming
6365
#define BASE_POSE_GROUND_TRUTH "base_pose_ground_truth"
6466
#define CMD_VEL "cmd_vel"
6567

@@ -76,16 +78,20 @@ class StageNode
7678

7779
// The models that we're interested in
7880
std::vector<Stg::ModelCamera *> cameramodels;
79-
std::vector<Stg::ModelRanger *> lasermodels;
81+
std::vector<Stg::ModelRanger *> rangermodels;
8082
std::vector<Stg::ModelPosition *> positionmodels;
83+
std::vector<Stg::ModelRanger *> lasermodels;
84+
std::vector<Stg::ModelRanger *> sonarmodels;
8185

8286
//a structure representing a robot inthe simulator
8387
struct StageRobot
8488
{
8589
//stage related models
8690
Stg::ModelPosition* positionmodel; //one position
8791
std::vector<Stg::ModelCamera *> cameramodels; //multiple cameras per position
88-
std::vector<Stg::ModelRanger *> lasermodels; //multiple rangers per position
92+
std::vector<Stg::ModelRanger *> rangermodels; //multiple rangers per position, contains lasers and sonars
93+
std::vector<Stg::ModelRanger *> lasermodels; // multiple lasers per position
94+
std::vector<Stg::ModelRanger *> sonarmodels; // multiple sonars per position
8995

9096
//ros publishers
9197
ros::Publisher odom_pub; //one odom
@@ -95,6 +101,7 @@ class StageNode
95101
std::vector<ros::Publisher> depth_pubs; //multiple depths
96102
std::vector<ros::Publisher> camera_pubs; //multiple cameras
97103
std::vector<ros::Publisher> laser_pubs; //multiple lasers
104+
std::vector<ros::Publisher> sonar_pubs; // multiple sonars
98105

99106
ros::Subscriber cmdvel_sub; //one cmd_vel subscriber
100107
};
@@ -364,6 +371,44 @@ StageNode::SubscribeModels()
364371
new_robot->ground_truth_pub = n_.advertise<nav_msgs::Odometry>(mapName(BASE_POSE_GROUND_TRUTH, r, static_cast<Stg::Model*>(new_robot->positionmodel)), 10);
365372
new_robot->cmdvel_sub = n_.subscribe<geometry_msgs::Twist>(mapName(CMD_VEL, r, static_cast<Stg::Model*>(new_robot->positionmodel)), 10, boost::bind(&StageNode::cmdvelReceived, this, r, _1));
366373

374+
// break rangermodes -> lasermdoels + sonarmodels
375+
int num_lasers = 0;
376+
int num_sonars = 0;
377+
for (size_t s = 0; s < new_robot->rangermodels.size(); s++)
378+
{
379+
// assumed only one sensor per ranger, as Stage currently only supports this
380+
// sonar is sample_count == 1
381+
if (rangermodels[s]->GetSensors()[0].sample_count == 1)
382+
{
383+
new_robot->sonarmodels.push_back(rangermodels[s]);
384+
num_sonars++;
385+
}
386+
else
387+
{
388+
new_robot->lasermodels.push_back(rangermodels[s]);
389+
num_lasers++;
390+
}
391+
}
392+
393+
// create publishers for lasers and sonars with correct labelling
394+
// add number label on each topic with more than one device
395+
if (num_lasers == 1)
396+
new_robot->laser_pubs.push_back(n_.advertise<sensor_msgs::LaserScan>(mapName(BASE_SCAN, r, static_cast<Stg::Model*>(new_robot->positionmodel)), 10));
397+
else
398+
{
399+
for (size_t s = 0; s < num_lasers; ++s)
400+
new_robot->laser_pubs.push_back(n_.advertise<sensor_msgs::LaserScan>(mapName(BASE_SCAN, r, s, static_cast<Stg::Model*>(new_robot->positionmodel)), 10));
401+
}
402+
403+
// add "/range" at end of name, need to change mapName to return string
404+
if (num_sonars == 1)
405+
new_robot->sonar_pubs.push_back(n_.advertise<sensor_msgs::Range>(mapName(SONAR, r, static_cast<Stg::Model*>(new_robot->positionmodel)), 10));
406+
else
407+
{
408+
for (size_t s = 0; s < num_sonars; ++s)
409+
new_robot->sonar_pubs.push_back(n_.advertise<sensor_msgs::Range>(mapName(SONAR, r, s, static_cast<Stg::Model*>(new_robot->positionmodel)), 10));
410+
}
411+
367412
for (size_t s = 0; s < new_robot->lasermodels.size(); ++s)
368413
{
369414
if (new_robot->lasermodels.size() == 1)
@@ -444,14 +489,14 @@ StageNode::WorldCallback()
444489
{
445490
StageRobot const * robotmodel = this->robotmodels_[r];
446491

447-
//loop on the laser devices for the current robot
492+
// loop on the laser devices for the current robot
448493
for (size_t s = 0; s < robotmodel->lasermodels.size(); ++s)
449494
{
450495
Stg::ModelRanger const* lasermodel = robotmodel->lasermodels[s];
451496
const std::vector<Stg::ModelRanger::Sensor>& sensors = lasermodel->GetSensors();
452497

453498
if( sensors.size() > 1 )
454-
ROS_WARN( "ROS Stage currently supports rangers with 1 sensor only." );
499+
ROS_WARN_ONCE( "ROS Stage currently supports rangers with 1 sensor only." );
455500

456501
// for now we access only the zeroth sensor of the ranger - good
457502
// enough for most laser models that have a single beam origin
@@ -501,6 +546,57 @@ StageNode::WorldCallback()
501546
mapName("base_laser_link", r, static_cast<Stg::Model*>(robotmodel->positionmodel))));
502547
}
503548

549+
// loop on the sonar devices for the current robot
550+
for (size_t s = 0; s < robotmodel->sonarmodels.size(); ++s)
551+
{
552+
Stg::ModelRanger const* sonarmodel = robotmodel->sonarmodels[s];
553+
const std::vector<Stg::ModelRanger::Sensor>& sensors = sonarmodel->GetSensors();
554+
555+
if (sensors.size() > 1)
556+
ROS_WARN("ROS Stage currently supports sonars with 1 sensor only.");
557+
558+
// for now we access only the zeroth sensor of the sonar - good
559+
// enough for most sonar models that have a single beam origin
560+
const Stg::ModelRanger::Sensor& sensor = sensors[0];
561+
562+
if (sensor.ranges.size())
563+
{
564+
// Translate into ROS message format and publish
565+
sensor_msgs::Range msg;
566+
msg.field_of_view = sensor.fov;
567+
msg.min_range = sensor.range.min;
568+
msg.max_range = sensor.range.max;
569+
msg.range = sensor.ranges[0];
570+
571+
// assume all are sonar, not infrared. This choice not currently in Stage
572+
msg.radiation_type = sensor_msgs::Range::ULTRASOUND;
573+
574+
if (robotmodel->sonarmodels.size() > 1)
575+
msg.header.frame_id = mapName("base_sonar_link", r, s, static_cast<Stg::Model*>(robotmodel->positionmodel));
576+
else
577+
msg.header.frame_id = mapName("base_sonar_link", r, static_cast<Stg::Model*>(robotmodel->positionmodel));
578+
579+
msg.header.stamp = sim_time;
580+
robotmodel->sonar_pubs[s].publish(msg);
581+
}
582+
583+
// Also publish the base->sonar_link Tx. This could eventually move
584+
// into being retrieved from the param server as a static Tx.
585+
Stg::Pose lp = sonarmodel->GetPose();
586+
tf::Quaternion sonarQ;
587+
sonarQ.setRPY(0.0, 0.0, lp.a);
588+
tf::Transform txSonar = tf::Transform(sonarQ, tf::Point(lp.x, lp.y, robotmodel->positionmodel->GetGeom().size.z + lp.z));
589+
590+
if (robotmodel->sonarmodels.size() > 1)
591+
tf.sendTransform(tf::StampedTransform(txSonar, sim_time,
592+
mapName("base_link", r, static_cast<Stg::Model*>(robotmodel->positionmodel)),
593+
mapName("base_sonar_link", r, s, static_cast<Stg::Model*>(robotmodel->positionmodel))));
594+
else
595+
tf.sendTransform(tf::StampedTransform(txSonar, sim_time,
596+
mapName("base_link", r, static_cast<Stg::Model*>(robotmodel->positionmodel)),
597+
mapName("base_sonar_link", r, static_cast<Stg::Model*>(robotmodel->positionmodel))));
598+
}
599+
504600
//the position of the robot
505601
tf.sendTransform(tf::StampedTransform(tf::Transform::getIdentity(),
506602
sim_time,

0 commit comments

Comments
 (0)