@@ -61,119 +61,257 @@ GZBridge::~GZBridge()
61
61
62
62
int GZBridge::init ()
63
63
{
64
- // clock
64
+ // REQUIRED:
65
+ if (!subscribeClock (true )) {
66
+ return PX4_ERROR;
67
+ }
68
+
69
+ // We must wait for clock before subscribing to other topics. This is because
70
+ // if we publish a 0 timestamp it screws up the EKF.
71
+ while (1 ) {
72
+ px4_usleep (25000 );
73
+
74
+ if (_realtime_clock_set) {
75
+ px4_usleep (25000 );
76
+ break ;
77
+ }
78
+ }
79
+
80
+ if (!subscribePoseInfo (true )) {
81
+ return PX4_ERROR;
82
+ }
83
+
84
+ if (!subscribeImu (true )) {
85
+ return PX4_ERROR;
86
+ }
87
+
88
+ if (!subscribeMag (true )) {
89
+ return PX4_ERROR;
90
+ }
91
+
92
+ // OPTIONAL:
93
+ if (!subscribeNavsat (false )) {
94
+ return PX4_ERROR;
95
+ }
96
+
97
+ if (!subscribeAirPressure (false )) {
98
+ return PX4_ERROR;
99
+ }
100
+
101
+ if (!subscribeDistanceSensor (false )) {
102
+ return PX4_ERROR;
103
+ }
104
+
105
+ if (!subscribeAirspeed (false )) {
106
+ return PX4_ERROR;
107
+ }
108
+
109
+ if (!subscribeOpticalFlow (false )) {
110
+ return PX4_ERROR;
111
+ }
112
+
113
+ if (!subscribeOdometry (false )) {
114
+ return PX4_ERROR;
115
+ }
116
+
117
+ if (!subscribeLaserScan (false )) {
118
+ return PX4_ERROR;
119
+ }
120
+
121
+ // ESC mixing interface
122
+ if (!_mixing_interface_esc.init (_model_name)) {
123
+ PX4_ERR (" failed to init ESC output" );
124
+ return PX4_ERROR;
125
+ }
126
+
127
+ // Servo mixing interface
128
+ if (!_mixing_interface_servo.init (_model_name)) {
129
+ PX4_ERR (" failed to init servo output" );
130
+ return PX4_ERROR;
131
+ }
132
+
133
+ // Wheel mixing interface
134
+ if (!_mixing_interface_wheel.init (_model_name)) {
135
+ PX4_ERR (" failed to init motor output" );
136
+ return PX4_ERROR;
137
+ }
138
+
139
+ // Gimbal mixing interface
140
+ if (!_gimbal.init (_world_name, _model_name)) {
141
+ PX4_ERR (" failed to init gimbal" );
142
+ return PX4_ERROR;
143
+ }
144
+
145
+ ScheduleNow ();
146
+ return OK;
147
+ }
148
+
149
+ void GZBridge::Run ()
150
+ {
151
+ if (should_exit ()) {
152
+ ScheduleClear ();
153
+
154
+ _mixing_interface_esc.stop ();
155
+ _mixing_interface_servo.stop ();
156
+ _mixing_interface_wheel.stop ();
157
+ _gimbal.stop ();
158
+
159
+ exit_and_cleanup ();
160
+ return ;
161
+ }
162
+
163
+ if (_parameter_update_sub.updated ()) {
164
+ parameter_update_s pupdate;
165
+ _parameter_update_sub.copy (&pupdate);
166
+
167
+ updateParams ();
168
+
169
+ _mixing_interface_esc.updateParams ();
170
+ _mixing_interface_servo.updateParams ();
171
+ _mixing_interface_wheel.updateParams ();
172
+ _gimbal.updateParams ();
173
+ }
174
+
175
+ ScheduleDelayed (10_ms);
176
+ }
177
+
178
+ bool GZBridge::subscribeClock (bool required)
179
+ {
65
180
std::string clock_topic = " /world/" + _world_name + " /clock" ;
66
181
67
182
if (!_node.Subscribe (clock_topic, &GZBridge::clockCallback, this )) {
68
183
PX4_ERR (" failed to subscribe to %s" , clock_topic.c_str ());
69
- return PX4_ERROR ;
184
+ return required ? false : true ;
70
185
}
71
186
72
- // pose: /world/$WORLD/pose/info
187
+ return true ;
188
+ }
189
+
190
+ bool GZBridge::subscribePoseInfo (bool required)
191
+ {
73
192
std::string world_pose_topic = " /world/" + _world_name + " /pose/info" ;
74
193
75
194
if (!_node.Subscribe (world_pose_topic, &GZBridge::poseInfoCallback, this )) {
76
195
PX4_ERR (" failed to subscribe to %s" , world_pose_topic.c_str ());
77
- return PX4_ERROR ;
196
+ return required ? false : true ;
78
197
}
79
198
80
- // IMU: /world/$WORLD/model/$MODEL/link/base_link/sensor/imu_sensor/imu
199
+ return true ;
200
+ }
201
+
202
+ bool GZBridge::subscribeImu (bool required)
203
+ {
81
204
std::string imu_topic = " /world/" + _world_name + " /model/" + _model_name + " /link/base_link/sensor/imu_sensor/imu" ;
82
205
83
206
if (!_node.Subscribe (imu_topic, &GZBridge::imuCallback, this )) {
84
207
PX4_ERR (" failed to subscribe to %s" , imu_topic.c_str ());
85
- return PX4_ERROR ;
208
+ return required ? false : true ;
86
209
}
87
210
88
- // mag: /world/$WORLD/model/$MODEL/link/base_link/sensor/magnetometer_sensor/magnetometer
211
+ return true ;
212
+ }
213
+
214
+ bool GZBridge::subscribeMag (bool required)
215
+ {
89
216
std::string mag_topic = " /world/" + _world_name + " /model/" + _model_name +
90
217
" /link/base_link/sensor/magnetometer_sensor/magnetometer" ;
91
218
92
219
if (!_node.Subscribe (mag_topic, &GZBridge::magnetometerCallback, this )) {
93
220
PX4_ERR (" failed to subscribe to %s" , mag_topic.c_str ());
94
- return PX4_ERROR ;
221
+ return required ? false : true ;
95
222
}
96
223
224
+ return true ;
225
+ }
226
+
227
+ bool GZBridge::subscribeOdometry (bool required)
228
+ {
97
229
// odom: /world/$WORLD/model/$MODEL/link/base_link/odometry_with_covariance
98
230
std::string odometry_topic = " /model/" + _model_name + " /odometry_with_covariance" ;
99
231
100
232
if (!_node.Subscribe (odometry_topic, &GZBridge::odometryCallback, this )) {
101
233
PX4_ERR (" failed to subscribe to %s" , odometry_topic.c_str ());
102
- return PX4_ERROR ;
234
+ return required ? false : true ;
103
235
}
104
236
105
- // Laser Scan: optional
237
+ return true ;
238
+ }
239
+
240
+ bool GZBridge::subscribeLaserScan (bool required)
241
+ {
106
242
std::string laser_scan_topic = " /world/" + _world_name + " /model/" + _model_name + " /link/link/sensor/lidar_2d_v2/scan" ;
107
243
108
244
if (!_node.Subscribe (laser_scan_topic, &GZBridge::laserScanCallback, this )) {
109
245
PX4_WARN (" failed to subscribe to %s" , laser_scan_topic.c_str ());
246
+ return required ? false : true ;
110
247
}
111
248
112
- // Distance Sensor(AFBRS50): optional
249
+ return true ;
250
+ }
251
+
252
+ bool GZBridge::subscribeDistanceSensor (bool required)
253
+ {
113
254
std::string lidar_sensor = " /world/" + _world_name + " /model/" + _model_name +
114
255
" /link/lidar_sensor_link/sensor/lidar/scan" ;
115
256
116
257
if (!_node.Subscribe (lidar_sensor, &GZBridge::laserScantoLidarSensorCallback, this )) {
117
258
PX4_WARN (" failed to subscribe to %s" , lidar_sensor.c_str ());
259
+ return required ? false : true ;
118
260
}
119
261
120
- // Airspeed: /world/$WORLD/model/$MODEL/link/airspeed_link/sensor/air_speed/air_speed
262
+ return true ;
263
+ }
264
+
265
+ bool GZBridge::subscribeAirspeed (bool required)
266
+ {
121
267
std::string airspeed_topic = " /world/" + _world_name + " /model/" + _model_name +
122
268
" /link/airspeed_link/sensor/air_speed/air_speed" ;
123
269
124
270
if (!_node.Subscribe (airspeed_topic, &GZBridge::airspeedCallback, this )) {
125
271
PX4_ERR (" failed to subscribe to %s" , airspeed_topic.c_str ());
126
- return PX4_ERROR ;
272
+ return required ? false : true ;
127
273
}
128
274
129
- // Air pressure: /world/$WORLD/model/$MODEL/link/base_link/sensor/air_pressure_sensor/air_pressure
275
+ return true ;
276
+ }
277
+
278
+ bool GZBridge::subscribeAirPressure (bool required)
279
+ {
130
280
std::string air_pressure_topic = " /world/" + _world_name + " /model/" + _model_name +
131
281
" /link/base_link/sensor/air_pressure_sensor/air_pressure" ;
132
282
133
- if (!_node.Subscribe (air_pressure_topic, &GZBridge::barometerCallback , this )) {
283
+ if (!_node.Subscribe (air_pressure_topic, &GZBridge::airPressureCallback , this )) {
134
284
PX4_ERR (" failed to subscribe to %s" , air_pressure_topic.c_str ());
135
- return PX4_ERROR ;
285
+ return required ? false : true ;
136
286
}
137
287
138
- // GPS: /world/$WORLD/model/$MODEL/link/base_link/sensor/navsat_sensor/navsat
288
+ return true ;
289
+ }
290
+
291
+ bool GZBridge::subscribeNavsat (bool required)
292
+ {
139
293
std::string nav_sat_topic = " /world/" + _world_name + " /model/" + _model_name +
140
294
" /link/base_link/sensor/navsat_sensor/navsat" ;
141
295
142
296
if (!_node.Subscribe (nav_sat_topic, &GZBridge::navSatCallback, this )) {
143
297
PX4_ERR (" failed to subscribe to %s" , nav_sat_topic.c_str ());
144
- return PX4_ERROR ;
298
+ return required ? false : true ;
145
299
}
146
300
301
+ return true ;
302
+ }
303
+
304
+ bool GZBridge::subscribeOpticalFlow (bool required)
305
+ {
147
306
std::string flow_topic = " /world/" + _world_name + " /model/" + _model_name +
148
307
" /link/flow_link/sensor/optical_flow/optical_flow" ;
149
308
150
309
if (!_node.Subscribe (flow_topic, &GZBridge::opticalFlowCallback, this )) {
151
310
PX4_ERR (" failed to subscribe to %s" , flow_topic.c_str ());
152
- return PX4_ERROR ;
311
+ return required ? false : true ;
153
312
}
154
313
155
- if (!_mixing_interface_esc.init (_model_name)) {
156
- PX4_ERR (" failed to init ESC output" );
157
- return PX4_ERROR;
158
- }
159
-
160
- if (!_mixing_interface_servo.init (_model_name)) {
161
- PX4_ERR (" failed to init servo output" );
162
- return PX4_ERROR;
163
- }
164
-
165
- if (!_mixing_interface_wheel.init (_model_name)) {
166
- PX4_ERR (" failed to init motor output" );
167
- return PX4_ERROR;
168
- }
169
-
170
- if (!_gimbal.init (_world_name, _model_name)) {
171
- PX4_ERR (" failed to init gimbal" );
172
- return PX4_ERROR;
173
- }
174
-
175
- ScheduleNow ();
176
- return OK;
314
+ return true ;
177
315
}
178
316
179
317
void GZBridge::clockCallback (const gz::msgs::Clock &msg)
@@ -254,7 +392,7 @@ void GZBridge::magnetometerCallback(const gz::msgs::Magnetometer &msg)
254
392
_sensor_mag_pub.publish (report);
255
393
}
256
394
257
- void GZBridge::barometerCallback (const gz::msgs::FluidPressure &msg)
395
+ void GZBridge::airPressureCallback (const gz::msgs::FluidPressure &msg)
258
396
{
259
397
const uint64_t timestamp = hrt_absolute_time ();
260
398
@@ -273,7 +411,6 @@ void GZBridge::barometerCallback(const gz::msgs::FluidPressure &msg)
273
411
_sensor_baro_pub.publish (report);
274
412
}
275
413
276
-
277
414
void GZBridge::airspeedCallback (const gz::msgs::AirSpeed &msg)
278
415
{
279
416
const uint64_t timestamp = hrt_absolute_time ();
@@ -495,7 +632,7 @@ void GZBridge::odometryCallback(const gz::msgs::OdometryWithCovariance &msg)
495
632
_visual_odometry_pub.publish (report);
496
633
}
497
634
498
- static float generate_wgn ()
635
+ float GZBridge:: generate_wgn ()
499
636
{
500
637
// generate white Gaussian noise sample with std=1
501
638
@@ -798,35 +935,6 @@ void GZBridge::rotateQuaternion(gz::math::Quaterniond &q_FRD_to_NED, const gz::m
798
935
q_FRD_to_NED = q_ENU_to_NED * q_FLU_to_ENU * q_FLU_to_FRD.Inverse ();
799
936
}
800
937
801
- void GZBridge::Run ()
802
- {
803
- if (should_exit ()) {
804
- ScheduleClear ();
805
-
806
- _mixing_interface_esc.stop ();
807
- _mixing_interface_servo.stop ();
808
- _mixing_interface_wheel.stop ();
809
- _gimbal.stop ();
810
-
811
- exit_and_cleanup ();
812
- return ;
813
- }
814
-
815
- if (_parameter_update_sub.updated ()) {
816
- parameter_update_s pupdate;
817
- _parameter_update_sub.copy (&pupdate);
818
-
819
- updateParams ();
820
-
821
- _mixing_interface_esc.updateParams ();
822
- _mixing_interface_servo.updateParams ();
823
- _mixing_interface_wheel.updateParams ();
824
- _gimbal.updateParams ();
825
- }
826
-
827
- ScheduleDelayed (10_ms);
828
- }
829
-
830
938
int GZBridge::task_spawn (int argc, char *argv[])
831
939
{
832
940
std::string world_name;
0 commit comments