00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "smoothMover.h"
00020 #include "notify.h"
00021 #include "compose_matrix.h"
00022
00023 SmoothMover::SmoothMode SmoothMover::_smooth_mode = SmoothMover::SM_off;
00024 SmoothMover::PredictionMode SmoothMover::_prediction_mode = SmoothMover::PM_off;
00025 double SmoothMover::_delay = 0.2;
00026 bool SmoothMover::_accept_clock_skew = true;
00027 double SmoothMover::_max_position_age = 0.25;
00028 double SmoothMover::_reset_velocity_age = 0.3;
00029
00030
00031
00032
00033
00034
00035 SmoothMover::
00036 SmoothMover() {
00037 _scale.set(1.0, 1.0, 1.0);
00038 _sample._pos.set(0.0, 0.0, 0.0);
00039 _sample._hpr.set(0.0, 0.0, 0.0);
00040 _sample._timestamp = 0.0;
00041
00042 _smooth_pos.set(0.0, 0.0, 0.0);
00043 _smooth_hpr.set(0.0, 0.0, 0.0);
00044 _smooth_mat = LMatrix4f::ident_mat();
00045 _smooth_timestamp = 0.0;
00046 _smooth_position_known = false;
00047 _smooth_position_changed = true;
00048 _computed_smooth_mat = true;
00049
00050 _smooth_forward_velocity = 0.0;
00051 _smooth_rotational_velocity = 0.0;
00052
00053 _last_point_before = -1;
00054 _last_point_after = -1;
00055
00056 _net_timestamp_delay = 0;
00057
00058
00059 _timestamp_delays.push_back(0);
00060
00061 _last_heard_from = 0.0;
00062 }
00063
00064
00065
00066
00067
00068
00069 SmoothMover::
00070 ~SmoothMover() {
00071 }
00072
00073
00074
00075
00076
00077
00078
00079 bool SmoothMover::
00080 set_mat(const LMatrix4f &mat) {
00081 bool result = false;
00082
00083 LVecBase3f scale, hpr, pos;
00084 if (decompose_matrix(mat, scale, hpr, pos)) {
00085 result = set_scale(scale) | set_hpr(hpr) | set_pos(pos);
00086 }
00087 return result;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 void SmoothMover::
00103 mark_position() {
00104 if (_smooth_mode == SM_off) {
00105
00106
00107
00108
00109
00110
00111 double timestamp = ClockObject::get_global_clock()->get_frame_time();
00112
00113
00114 if (_smooth_position_known) {
00115 LVector3f pos_delta = _sample._pos - _smooth_pos;
00116 LVecBase3f hpr_delta = _sample._hpr - _smooth_hpr;
00117 double age = timestamp - _smooth_timestamp;
00118 age = min(age, _max_position_age);
00119
00120 set_smooth_pos(_sample._pos, _sample._hpr, timestamp);
00121 if (age != 0.0) {
00122 compute_velocity(pos_delta, hpr_delta, age);
00123 }
00124
00125 } else {
00126
00127 set_smooth_pos(_sample._pos, _sample._hpr, timestamp);
00128 }
00129
00130 } else {
00131
00132
00133
00134 if (_points.full()) {
00135
00136
00137 _points.pop_front();
00138
00139
00140 _last_point_before = -1;
00141 _last_point_after = -1;
00142 }
00143
00144 _points.push_back(_sample);
00145 }
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 void SmoothMover::
00158 clear_positions(bool reset_velocity) {
00159 while (!_points.empty()) {
00160 _points.pop_front();
00161 }
00162 _last_point_before = -1;
00163 _last_point_after = -1;
00164 _smooth_position_known = false;
00165
00166 if (reset_velocity) {
00167 _smooth_forward_velocity = 0.0;
00168 _smooth_rotational_velocity = 0.0;
00169 }
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 bool SmoothMover::
00187 compute_smooth_position(double timestamp) {
00188 if (_points.empty()) {
00189
00190
00191
00192
00193 if (_smooth_position_known) {
00194 double age = timestamp - _smooth_timestamp;
00195 if (age > _reset_velocity_age) {
00196 _smooth_forward_velocity = 0.0;
00197 _smooth_rotational_velocity = 0.0;
00198 }
00199 }
00200 bool result = _smooth_position_changed;
00201 _smooth_position_changed = false;
00202 return result;
00203 }
00204 if (_smooth_mode == SM_off) {
00205
00206
00207
00208 clear_positions(false);
00209 bool result = _smooth_position_changed;
00210 _smooth_position_changed = false;
00211 return result;
00212 }
00213
00214
00215 double orig_timestamp = timestamp;
00216 timestamp -= _delay;
00217 if (_accept_clock_skew) {
00218 timestamp -= get_avg_timestamp_delay();
00219 }
00220
00221
00222 int point_way_before = -1;
00223 int point_before = -1;
00224 double timestamp_before = 0.0;
00225 int point_after = -1;
00226 double timestamp_after = 0.0;
00227
00228
00229
00230
00231
00232
00233 int num_points = _points.size();
00234 for (int i = 0; i < num_points; i++) {
00235 const SamplePoint &point = _points[i];
00236 if (point._timestamp < timestamp) {
00237
00238
00239 if (point_before == -1 || point._timestamp > timestamp_before) {
00240 point_way_before = point_before;
00241 point_before = i;
00242 timestamp_before = point._timestamp;
00243 }
00244 }
00245 if (point._timestamp >= timestamp) {
00246
00247
00248 if (point_after == -1 || point._timestamp < timestamp_after) {
00249 point_after = i;
00250 timestamp_after = point._timestamp;
00251 }
00252 }
00253 }
00254
00255 if (point_before == -1) {
00256 nassertr(point_after != -1, false);
00257
00258 bool result = !(_last_point_before == point_before &&
00259 _last_point_after == point_after);
00260 const SamplePoint &point = _points[point_after];
00261 set_smooth_pos(point._pos, point._hpr, timestamp);
00262 _smooth_forward_velocity = 0.0;
00263 _smooth_rotational_velocity = 0.0;
00264 _last_point_before = point_before;
00265 _last_point_after = point_after;
00266 return result;
00267 }
00268
00269 bool result = true;
00270
00271 if (point_after == -1 && _prediction_mode != PM_off) {
00272
00273
00274
00275
00276 if (point_way_before != -1) {
00277
00278
00279
00280 SamplePoint &point = _points[point_way_before];
00281 point_after = point_before;
00282 timestamp_after = timestamp_before;
00283 point_before = point_way_before;
00284 timestamp_before = point._timestamp;
00285
00286 if (timestamp > timestamp_after + _max_position_age) {
00287
00288
00289 timestamp = timestamp_after + _max_position_age;
00290 }
00291 }
00292 }
00293
00294 if (point_after == -1) {
00295
00296
00297 if (point_way_before != -1) {
00298
00299
00300 linear_interpolate(point_way_before, point_before, timestamp_before);
00301
00302 } else {
00303
00304 const SamplePoint &point = _points[point_before];
00305 set_smooth_pos(point._pos, point._hpr, timestamp);
00306 }
00307
00308 if (orig_timestamp - _last_heard_from > _reset_velocity_age) {
00309
00310
00311
00312
00313 _smooth_forward_velocity = 0.0;
00314 _smooth_rotational_velocity = 0.0;
00315 }
00316
00317 result = !(_last_point_before == point_before &&
00318 _last_point_after == point_after);
00319 _last_point_before = point_before;
00320 _last_point_after = point_after;
00321
00322 } else {
00323
00324 linear_interpolate(point_before, point_after, timestamp);
00325 }
00326
00327
00328
00329
00330 double timestamp_way_before = _points[point_way_before]._timestamp;
00331 while (!_points.empty() && _points.front()._timestamp < timestamp_way_before) {
00332 _points.pop_front();
00333
00334
00335 _last_point_before = -1;
00336 _last_point_after = -1;
00337 }
00338
00339 return result;
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 bool SmoothMover::
00354 get_latest_position() {
00355 if (_points.empty()) {
00356
00357 return _smooth_position_known;
00358 }
00359
00360 const SamplePoint &point = _points.back();
00361 set_smooth_pos(point._pos, point._hpr, point._timestamp);
00362 _smooth_forward_velocity = 0.0;
00363 _smooth_rotational_velocity = 0.0;
00364 return true;
00365 }
00366
00367
00368
00369
00370
00371
00372 void SmoothMover::
00373 output(ostream &out) const {
00374 out << "SmoothMover, " << _points.size() << " sample points.";
00375 }
00376
00377
00378
00379
00380
00381
00382 void SmoothMover::
00383 write(ostream &out) const {
00384 out << "SmoothMover, " << _points.size() << " sample points:\n";
00385 int num_points = _points.size();
00386 for (int i = 0; i < num_points; i++) {
00387 const SamplePoint &point = _points[i];
00388 out << " " << i << ". time = " << point._timestamp << " pos = "
00389 << point._pos << " hpr = " << point._hpr << "\n";
00390 }
00391 }
00392
00393
00394
00395
00396
00397
00398
00399 void SmoothMover::
00400 set_smooth_pos(const LPoint3f &pos, const LVecBase3f &hpr,
00401 double timestamp) {
00402 _smooth_pos = pos;
00403 _smooth_hpr = hpr;
00404 _smooth_timestamp = timestamp;
00405 _smooth_position_known = true;
00406 _smooth_position_changed = true;
00407 _computed_smooth_mat = false;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416 void SmoothMover::
00417 compose_smooth_mat() {
00418 compose_matrix(_smooth_mat, _scale, _smooth_hpr, _smooth_pos);
00419 _computed_smooth_mat = true;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428 void SmoothMover::
00429 linear_interpolate(int point_before, int point_after, double timestamp) {
00430 SamplePoint &point_b = _points[point_before];
00431 const SamplePoint &point_a = _points[point_after];
00432
00433 double age = (point_a._timestamp - point_b._timestamp);
00434
00435 if (point_before == _last_point_before &&
00436 point_after == _last_point_after) {
00437
00438
00439 double t = (timestamp - point_b._timestamp) / age;
00440 set_smooth_pos(point_b._pos + t * (point_a._pos - point_b._pos),
00441 point_b._hpr + t * (point_a._hpr - point_b._hpr),
00442 timestamp);
00443
00444
00445
00446 } else {
00447 _last_point_before = point_before;
00448 _last_point_after = point_after;
00449
00450 if (age > _max_position_age) {
00451
00452
00453
00454 point_b._timestamp = min(timestamp, point_a._timestamp - _max_position_age);
00455 age = (point_a._timestamp - point_b._timestamp);
00456 }
00457
00458
00459
00460 for (int j = 0; j < 3; j++) {
00461 if ((point_b._hpr[j] - point_a._hpr[j]) > 180.0) {
00462 point_b._hpr[j] -= 360.0;
00463 } else if ((point_b._hpr[j] - point_a._hpr[j]) < -180.0) {
00464 point_b._hpr[j] += 360.0;
00465 }
00466 }
00467
00468 double t = (timestamp - point_b._timestamp) / age;
00469 LVector3f pos_delta = point_a._pos - point_b._pos;
00470 LVecBase3f hpr_delta = point_a._hpr - point_b._hpr;
00471
00472 set_smooth_pos(point_b._pos + t * pos_delta,
00473 point_b._hpr + t * hpr_delta,
00474 timestamp);
00475 compute_velocity(pos_delta, hpr_delta, age);
00476 }
00477 }
00478
00479
00480
00481
00482
00483
00484
00485 void SmoothMover::
00486 compute_velocity(const LVector3f &pos_delta, const LVecBase3f &hpr_delta,
00487 double age) {
00488
00489
00490
00491 LMatrix3f rot_mat;
00492 compose_matrix(rot_mat, LVecBase3f(1.0, 1.0, 1.0), _smooth_hpr);
00493 LVector3f y_axis = LVector3f(0.0, 1.0, 0.0) * rot_mat;
00494 float forward_distance = pos_delta.dot(y_axis);
00495
00496 _smooth_forward_velocity = forward_distance / age;
00497 _smooth_rotational_velocity = hpr_delta[0] / age;
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 void SmoothMover::
00509 record_timestamp_delay(double timestamp) {
00510 double now = ClockObject::get_global_clock()->get_frame_time();
00511
00512
00513
00514
00515 int delay = (int)((now - timestamp) * 1000.0);
00516 if (_timestamp_delays.full()) {
00517 _net_timestamp_delay -= _timestamp_delays.front();
00518 _timestamp_delays.pop_front();
00519 }
00520 _net_timestamp_delay += delay;
00521 _timestamp_delays.push_back(delay);
00522
00523 _last_heard_from = now;
00524 }