@@ -22,6 +22,16 @@ class SensorTest : public ServerFixture
22
22
{
23
23
};
24
24
25
+ std::mutex g_mutex;
26
+ unsigned int g_messageCount = 0 ;
27
+
28
+ // //////////////////////////////////////////////////////////////////////
29
+ void SensorCallback (const ConstIMUSensorPtr &/* _msg*/ )
30
+ {
31
+ std::lock_guard<std::mutex> lock (g_mutex);
32
+ g_messageCount++;
33
+ }
34
+
25
35
// ///////////////////////////////////////////////
26
36
// This tests getting links from a model.
27
37
TEST_F (SensorTest, GetScopedName)
@@ -48,6 +58,101 @@ TEST_F(SensorTest, FastSensor)
48
58
// SensorManager::SensorContainer::RunLoop() is set improperly
49
59
}
50
60
61
+ // ///////////////////////////////////////////////
62
+ // Make sure sensors update rates are respected
63
+ // Spawn two sensors, one after another, with different update rates and
64
+ // verify the rates are correctly throttled
65
+ TEST_F (SensorTest, MaxUpdateRate)
66
+ {
67
+ Load (" worlds/empty.world" );
68
+
69
+ physics::WorldPtr world = physics::get_world (" default" );
70
+ ASSERT_NE (nullptr , world);
71
+
72
+ auto spawnSensorWithUpdateRate = [&](const std::string &_name,
73
+ const ignition::math::Pose3d &_pose, double _rate)
74
+ {
75
+ std::ostringstream newModelStr;
76
+ newModelStr << " <sdf version='" << SDF_VERSION << " '>"
77
+ << " <model name ='" << _name << " '>\n "
78
+ << " <static>true</static>\n "
79
+ << " <pose>" << _pose << " </pose>\n "
80
+ << " <link name ='body'>\n "
81
+ << " <inertial>\n "
82
+ << " <mass>0.1</mass>\n "
83
+ << " </inertial>\n "
84
+ << " <collision name='parent_collision'>\n "
85
+ << " <pose>0 0 0.0205 0 0 0</pose>\n "
86
+ << " <geometry>\n "
87
+ << " <cylinder>\n "
88
+ << " <radius>0.021</radius>\n "
89
+ << " <length>0.029</length>\n "
90
+ << " </cylinder>\n "
91
+ << " </geometry>\n "
92
+ << " </collision>\n "
93
+ << " <sensor name ='" << _name << " ' type ='imu'>\n "
94
+ << " <update_rate>" << _rate << " </update_rate>\n "
95
+ << " <topic>" << _name << " </topic>\n "
96
+ << " <imu>\n "
97
+ << " </imu>\n "
98
+ << " </sensor>\n "
99
+ << " </link>\n "
100
+ << " </model>\n "
101
+ << " </sdf>\n " ;
102
+
103
+ SpawnSDF (newModelStr.str ());
104
+ };
105
+
106
+ transport::NodePtr node = transport::NodePtr (new transport::Node ());
107
+ node->Init ();
108
+
109
+ g_messageCount = 0 ;
110
+
111
+ // spawn first sensor with low update rate
112
+ spawnSensorWithUpdateRate (" sensor1" , ignition::math::Pose3d::Zero, 5 );
113
+
114
+ transport::SubscriberPtr sub = node->Subscribe (" ~/sensor1/body/sensor1/imu" ,
115
+ SensorCallback);
116
+
117
+ // wait for messages
118
+ int sleep = 0 ;
119
+ int maxSleep = 1000 ;
120
+ double t0 = 0.0 ;
121
+ while (g_messageCount < 30 && sleep ++ < maxSleep)
122
+ {
123
+ if (g_messageCount == 0 )
124
+ t0 = world->SimTime ().Double ();
125
+ common::Time::MSleep (10 );
126
+ }
127
+
128
+ // verify update rate by checking the time it takes to receive n msgs
129
+ double elapsed = world->SimTime ().Double () - t0;
130
+ EXPECT_NEAR (6.0 , elapsed, 0.5 );
131
+
132
+ // disconnect first sensor
133
+ sub.reset ();
134
+
135
+ g_messageCount = 0 ;
136
+
137
+ // spawn another sensor with higher update rate
138
+ spawnSensorWithUpdateRate (" sensor2" , ignition::math::Pose3d::Zero, 10 );
139
+ sub = node->Subscribe (" ~/sensor2/body/sensor2/imu" , SensorCallback);
140
+
141
+ // wait for more msgs
142
+ sleep = 0 ;
143
+ t0 = 0.0 ;
144
+ while (g_messageCount < 30 && sleep ++ < maxSleep)
145
+ {
146
+ if (g_messageCount == 0 )
147
+ t0 = world->SimTime ().Double ();
148
+ common::Time::MSleep (10 );
149
+ }
150
+
151
+ // verify update rate by checking the time it takes to receive n msgs
152
+ elapsed = world->SimTime ().Double () - t0;
153
+ EXPECT_NEAR (3.0 , elapsed, 0.5 );
154
+ }
155
+
51
156
int main (int argc, char **argv)
52
157
{
53
158
::testing::InitGoogleTest (&argc, argv);
0 commit comments