Apollo 11.0
自动驾驶开放平台
localization_gnss_process.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include "yaml-cpp/yaml.h"
20
21#include "cyber/common/log.h"
22#include "cyber/time/clock.h"
24
26
27namespace apollo {
28namespace localization {
29namespace msf {
30
32
34 : gnss_solver_(new GnssSolver()),
35 enable_ins_aid_rtk_(true),
36 gnss_lever_arm_{0.0, 0.0, 0.0},
37 sins_align_finish_(false),
38 double_antenna_solver_(new GnssSolver()),
39 current_obs_time_(0.0),
41 SetDefaultOption();
42}
43
45 map_gnss_eph_.clear();
46
47 delete gnss_solver_;
48 gnss_solver_ = nullptr;
49 delete double_antenna_solver_;
50 double_antenna_solver_ = nullptr;
51}
52
54 // set launch parameter
55 enable_ins_aid_rtk_ = param.enable_ins_aid_rtk;
56 gnss_solver_->set_enable_external_prediction(enable_ins_aid_rtk_);
57
58 gnss_lever_arm_.arm_x = param.imu_to_ant_offset.offset_x;
59 gnss_lever_arm_.arm_y = param.imu_to_ant_offset.offset_y;
60 gnss_lever_arm_.arm_z = param.imu_to_ant_offset.offset_z;
61
62 map_gnss_eph_.clear();
63 sins_align_finish_ = false;
64
65 return Status::OK();
66}
67
68void LocalizationGnssProcess::SetDefaultOption() {
69 // set default process modes
70 gnss_solver_->set_position_option(3);
71 gnss_solver_->set_tropsphere_option(0);
72 gnss_solver_->enable_cycle_slip_fix();
73 enable_ins_aid_rtk_ = false;
74
75 gnss_lever_arm_.arm_x = -0.030;
76 gnss_lever_arm_.arm_y = 0.338;
77 gnss_lever_arm_.arm_z = 1.291;
78}
79
81 const drivers::gnss::EpochObservation &raw_obs) {
82 if (!raw_obs.has_receiver_id()) {
83 AERROR << "Obs data being invalid if without receiver id!";
84 return;
85 }
86 const double unix_to_gps = 315964800;
87 const double sec_per_week = 604800;
88 double leap_second_s = gnss_solver_->get_leap_second(raw_obs.gnss_week(),
89 raw_obs.gnss_second_s());
90
91 double sys_secs_to_gnss =
92 Clock::NowInSeconds() - unix_to_gps + leap_second_s;
93 double obs_secs =
94 raw_obs.gnss_second_s() + raw_obs.gnss_week() * sec_per_week;
95 double obs_delay = sys_secs_to_gnss - obs_secs;
96
97 double obs_xyz[3] = {0.0};
98 if (raw_obs.has_position_x() && raw_obs.has_position_y() &&
99 raw_obs.has_position_z()) {
100 obs_xyz[0] = raw_obs.position_x();
101 obs_xyz[1] = raw_obs.position_y();
102 obs_xyz[2] = raw_obs.position_z();
103 }
104 const unsigned int max_msg_size = 256;
105 char message[max_msg_size] = {'\0'};
106 snprintf(
107 message, max_msg_size,
108 "user %u time:%12.3f sat_num:%d obs_delay:%12.3f%16.3f%16.3f%16.3f\n",
109 raw_obs.receiver_id(), raw_obs.gnss_second_s(), raw_obs.sat_obs_num(),
110 obs_delay, obs_xyz[0], obs_xyz[1], obs_xyz[2]);
111 AINFO << message;
112
113 EpochObservationMsg raw_obs_msg;
114 GnssMagTransfer::Transfer(raw_obs, &raw_obs_msg);
115 if (raw_obs.receiver_id() != 0) {
116 // Notice: the baser coordinate should be binded with obs together anytime.
117 gnss_solver_->save_baser_observation(raw_obs_msg);
118 // id - 0x80000000 = station_id from gnss_driver
119 return;
120 }
121
122 const unsigned int second_per_week = 604800;
123 double new_obs_time =
124 raw_obs.gnss_second_s() + raw_obs.gnss_week() * second_per_week;
125 if (new_obs_time <= current_obs_time_) {
126 return;
127 }
128 current_obs_time_ = new_obs_time;
129 GnssPosition(&raw_obs_msg);
130}
131
133 const drivers::gnss::GnssEphemeris &msg) {
134 if (!msg.has_gnss_type()) {
135 return;
136 }
137 auto gnss_orbit = msg;
138 if (gnss_orbit.gnss_type() == drivers::gnss::GnssType::GLO_SYS) {
139 /* caros driver (derived from rtklib src) set glonass eph toe as the GPST,
140 * and here convert it back to UTC(+0), so leap seconds should be in
141 * accordance with the GNSS-Driver
142 */
143 double leap_sec =
144 gnss_solver_->get_leap_second(gnss_orbit.glonass_orbit().week_num(),
145 gnss_orbit.glonass_orbit().toe());
146 double toe = gnss_orbit.glonass_orbit().toe() - leap_sec;
147 gnss_orbit.mutable_glonass_orbit()->set_toe(toe);
148 gnss_orbit.mutable_glonass_orbit()->set_week_second_s(toe);
149 }
150 static int eph_counter = 0;
151 ++eph_counter;
152 // printf("received a gnss ephemeris: %d!\n", eph_counter);
153 if (DuplicateEph(gnss_orbit)) {
154 AINFO << "received an existed gnss ephemeris!";
155 return;
156 }
157
158 GnssEphemerisMsg gnss_orbit_msg;
159 GnssMagTransfer::Transfer(gnss_orbit, &gnss_orbit_msg);
160 gnss_solver_->save_gnss_ephemris(gnss_orbit_msg);
161}
162
163void LocalizationGnssProcess::IntegSinsPvaProcess(const InsPva &sins_pva_msg,
164 const double variance[9][9]) {
165 if (!sins_pva_msg.init_and_alignment) {
166 return;
167 }
168
169 sins_align_finish_ = true;
170
171 // feed into GNSS-RTK Engine
172 double sec_s = sins_pva_msg.time;
173 double llh[3] = {sins_pva_msg.pos.longitude, sins_pva_msg.pos.latitude,
174 sins_pva_msg.pos.height};
175 double velocity[3] = {sins_pva_msg.vel.ve, sins_pva_msg.vel.vn,
176 sins_pva_msg.vel.vu};
177 double lever_arm[3] = {gnss_lever_arm_.arm_x, gnss_lever_arm_.arm_y,
178 gnss_lever_arm_.arm_z};
179 double euler[3] = {sins_pva_msg.att.pitch, sins_pva_msg.att.roll,
180 sins_pva_msg.att.yaw};
181
182 double std_pos[3][3] = {0.0};
183 double std_vel[3][3] = {0.0};
184 // const unsigned int dim = 9;
185 for (unsigned int i = 0; i < 3; ++i) {
186 for (unsigned int j = 0; j < 3; ++j) {
187 std_pos[i][j] = variance[i][j];
188 std_vel[i][j] = variance[i + 3][j + 3];
189 }
190 }
191
192 gnss_solver_->motion_update(sec_s, llh, std_pos, velocity, std_vel, euler,
193 lever_arm);
194}
195
197 MeasureData *gnss_msg) {
198 CHECK_NOTNULL(gnss_msg);
199
200 // convert GnssPntResult to IntegMeasure
201 // double sec_s = Clock::NowInSeconds(); //
202 // ros::Time::now().toSec();
203 const unsigned int second_per_week = 604800;
204 double sec_s = gnss_pnt_result_.gnss_week() * second_per_week +
205 gnss_pnt_result_.gnss_second_s();
206 gnss_msg->time = sec_s;
207 gnss_msg->frame_type = FrameType::ECEF;
208
209 // velocity must be in ENU frame and position in frame WGS84
210 const int dim = 9;
211 for (int i = 0; i < dim; ++i) {
212 for (int j = 0; j < dim; ++j) {
213 gnss_msg->variance[i][j] = 0.0;
214 }
215 }
216
217 bool b_pos = false;
218 if (gnss_pnt_result_.has_pos_x_m() && gnss_pnt_result_.has_pos_y_m() &&
219 gnss_pnt_result_.has_pos_z_m()) {
220 b_pos = true;
221 gnss_msg->gnss_pos.longitude = gnss_pnt_result_.pos_x_m();
222 gnss_msg->gnss_pos.latitude = gnss_pnt_result_.pos_y_m();
223 gnss_msg->gnss_pos.height = gnss_pnt_result_.pos_z_m();
224 gnss_msg->measure_type = MeasureType::GNSS_POS_ONLY;
225
226 gnss_msg->is_have_variance = true;
227 // std
228 gnss_msg->variance[0][0] =
229 gnss_pnt_result_.std_pos_x_m() * gnss_pnt_result_.std_pos_x_m();
230 gnss_msg->variance[1][1] =
231 gnss_pnt_result_.std_pos_y_m() * gnss_pnt_result_.std_pos_y_m();
232 gnss_msg->variance[2][2] =
233 gnss_pnt_result_.std_pos_z_m() * gnss_pnt_result_.std_pos_z_m();
234 }
235 bool b_vel = false;
236 if (gnss_pnt_result_.has_vel_x_m() && gnss_pnt_result_.has_vel_y_m() &&
237 gnss_pnt_result_.has_vel_z_m()) {
238 // output velocity whenever possible.
239 b_vel = true;
240 gnss_msg->gnss_vel.ve = gnss_pnt_result_.vel_x_m();
241 gnss_msg->gnss_vel.vn = gnss_pnt_result_.vel_y_m();
242 gnss_msg->gnss_vel.vu = gnss_pnt_result_.vel_z_m();
243 gnss_msg->measure_type = MeasureType::ENU_VEL_ONLY;
244 gnss_msg->is_have_variance = true;
245 // std
246 gnss_msg->variance[3][3] =
247 gnss_pnt_result_.std_vel_x_m() * gnss_pnt_result_.std_vel_x_m();
248 gnss_msg->variance[4][4] =
249 gnss_pnt_result_.std_vel_y_m() * gnss_pnt_result_.std_vel_y_m();
250 gnss_msg->variance[5][5] =
251 gnss_pnt_result_.std_vel_z_m() * gnss_pnt_result_.std_vel_z_m();
252 }
253 if (b_pos && b_vel) {
254 gnss_msg->measure_type = MeasureType::GNSS_POS_VEL;
255 }
256
257 return gnss_state_;
258}
259
260bool LocalizationGnssProcess::DuplicateEph(
261 const drivers::gnss::GnssEphemeris &raw_eph) {
262 drivers::gnss::GnssType t_type = raw_eph.gnss_type();
263 if (t_type != drivers::gnss::GnssType::GPS_SYS &&
266 return true;
267 }
268 unsigned int sat_prn = 0;
269 unsigned int week_num = 0;
270 double toe = -0.1;
271 if (t_type == drivers::gnss::GnssType::GLO_SYS) {
272 sat_prn = raw_eph.glonass_orbit().slot_prn();
273 week_num = raw_eph.glonass_orbit().week_num();
274 toe = raw_eph.glonass_orbit().toe();
275 } else {
276 sat_prn = raw_eph.keppler_orbit().sat_prn();
277 week_num = raw_eph.keppler_orbit().week_num();
278 toe = raw_eph.keppler_orbit().toe();
279 }
280 const EphKey temp(drivers::gnss::GnssType(t_type), sat_prn, week_num, toe);
281 if (map_gnss_eph_.find(temp) != map_gnss_eph_.end()) {
282 return true;
283 }
284 map_gnss_eph_.insert(
285 std::map<EphKey, drivers::gnss::GnssEphemeris>::value_type(temp,
286 raw_eph));
287 return false;
288}
289
290inline void LocalizationGnssProcess::LogPnt(const GnssPntResultMsg &rover_pnt,
291 double ratio) {
292 char print_infor[256] = {'\0'};
293 snprintf(print_infor, sizeof(print_infor),
294 "%6d%12.3f%4d%16.3f%16.3f%16.3f%4d%4.1f%6.1f%8.3f%8.3f%8.3f%8.3f%8."
295 "3f%8.3f\n",
296 rover_pnt.gnss_week(), rover_pnt.gnss_second_s(),
297 static_cast<int>(rover_pnt.pnt_type()), rover_pnt.pos_x_m(),
298 rover_pnt.pos_y_m(), rover_pnt.pos_z_m(), rover_pnt.sovled_sat_num(),
299 rover_pnt.pdop(), ratio, rover_pnt.vel_x_m(), rover_pnt.vel_y_m(),
300 rover_pnt.vel_z_m(), rover_pnt.std_pos_x_m(),
301 rover_pnt.std_pos_y_m(), rover_pnt.std_pos_z_m());
302 AINFO << print_infor;
303}
304
305bool LocalizationGnssProcess::GnssPosition(EpochObservationMsg *raw_rover_obs) {
306 CHECK_NOTNULL(raw_rover_obs);
307
309 if (raw_rover_obs->receiver_id() != 0) {
310 AERROR << "Wrong Rover Obs Data!";
311 return false;
312 }
313 int b_solved = gnss_solver_->solve(raw_rover_obs, &gnss_pnt_result_);
314 if (b_solved < 0) {
315 return false;
316 }
317 LogPnt(gnss_pnt_result_, gnss_solver_->get_ratio());
318 if (!sins_align_finish_) {
319 AWARN << "Sins-ekf has not converged or finished its alignment!";
320 }
321 if (gnss_pnt_result_.has_std_pos_x_m() &&
322 gnss_pnt_result_.has_std_pos_y_m() &&
323 gnss_pnt_result_.has_std_pos_z_m()) {
324 double sigma =
325 gnss_pnt_result_.std_pos_x_m() * gnss_pnt_result_.std_pos_x_m() +
326 gnss_pnt_result_.std_pos_y_m() * gnss_pnt_result_.std_pos_y_m() +
327 gnss_pnt_result_.std_pos_z_m() * gnss_pnt_result_.std_pos_z_m();
328 sigma = std::sqrt(fabs(sigma));
329 const double sigma_threshold = 10.0;
330 if (fabs(sigma) > sigma_threshold) {
331 AWARN << "Position std exceeds the threshold " << sigma_threshold << "!";
332 return false;
333 }
334 }
335
336 gnss_state_ = LocalizationMeasureState::OK;
337
338 return true;
339}
340
341} // namespace msf
342} // namespace localization
343} // namespace apollo
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
a singleton clock that can be used to get the current timestamp.
Definition clock.h:39
static double NowInSeconds()
gets the current time in second.
Definition clock.cc:56
static void Transfer(const apollo::drivers::gnss::BandObservation &in, BandObservationMsg *out)
void RawObservationProcess(const drivers::gnss::EpochObservation &raw_obs)
void RawEphemerisProcess(const drivers::gnss::GnssEphemeris &gnss_orbit)
apollo::common::Status Init(const LocalizationIntegParam &param)
LocalizationMeasureState GetResult(MeasureData *gnss_measure)
void IntegSinsPvaProcess(const InsPva &sins_pva, const double variance[9][9])
The class of GnssMsgTransfer
The class of LocalizationGnssProcess
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
class register implement
Definition arena_queue.h:37