00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <vamos/body/Rigid_Body.h>
00022 #include <vamos/body/Aerodynamic_Device.h>
00023 #include <vamos/body/Contact_Point.h>
00024
00025 #include <cassert>
00026
00027 using Vamos_Geometry::Three_Vector;
00028 using Vamos_Geometry::Three_Matrix;
00029
00030
00031
00032
00033
00034 Vamos_Body::
00035 Contact_Parameters::Contact_Parameters ()
00036 : m_distance (0.0)
00037 {
00038 }
00039
00040
00041
00042
00043
00044
00045 Vamos_Body::
00046 Rigid_Body::Rigid_Body (const Three_Vector& pos, const Three_Matrix& orient)
00047 : Frame (pos, orient),
00048 m_initial_position (pos),
00049 m_delta_time (0.0),
00050 m_mass (0.0)
00051 {
00052 valid = false;
00053 }
00054
00055
00056 Vamos_Body::
00057 Rigid_Body::Rigid_Body (const Three_Vector& pos)
00058 : Frame (pos),
00059 m_initial_position (pos),
00060 m_delta_time (0.0),
00061 m_mass (0.0)
00062 {
00063 valid = false;
00064 }
00065
00066
00067 Vamos_Body::
00068 Rigid_Body::Rigid_Body ()
00069 : Frame (),
00070 m_delta_time (0.0),
00071 m_mass (0.0)
00072 {
00073 valid = false;
00074 }
00075
00076
00077
00078 Vamos_Body::Rigid_Body::
00079 ~Rigid_Body ()
00080 {
00081
00082
00083 for (std::vector <Particle*>::iterator it = m_particles.begin ();
00084 it != m_particles.end ();
00085 it++)
00086 {
00087
00088 }
00089 }
00090
00091
00092
00093 Three_Vector Vamos_Body::
00094 Rigid_Body::cm_position ()
00095 {
00096 return transform_out (m_body_cm, m_body_cm);
00097 }
00098
00099
00100
00101 Three_Vector Vamos_Body::
00102 Rigid_Body::contact_position (Particle* contact_point)
00103 {
00104 return transform_out (contact_point->contact_position (), m_body_cm);
00105 }
00106
00107 Three_Vector Vamos_Body::
00108 Rigid_Body::last_contact_position (Particle* contact_point)
00109 {
00110 Three_Vector temp_position;
00111 Three_Matrix temp_orientation;
00112
00113 temp_position = m_position;
00114 temp_orientation = m_orientation;
00115
00116 m_position = m_last_position;
00117 m_orientation = m_last_orientation;
00118
00119 Three_Vector out;
00120
00121 out = transform_out (contact_point->contact_position (), m_last_body_cm);
00122
00123 m_position = temp_position;
00124 m_orientation = temp_orientation;
00125
00126 return out;
00127 }
00128
00129
00130 void Vamos_Body::
00131 Rigid_Body::roll_back()
00132 {
00133 m_position = m_last_position;
00134 m_orientation = m_last_orientation;
00135 m_body_cm = m_last_body_cm;
00136 m_cm_velocity = m_last_cm_velocity;
00137 m_ang_velocity = m_last_ang_velocity;
00138 }
00139
00140 void Vamos_Body::
00141 Rigid_Body::kill_vel()
00142 {
00143 m_velocity = m_velocity * 0;
00144 m_ang_velocity = m_ang_velocity * 0;
00145
00146 std::vector <Particle*>::const_iterator it = m_particles.begin ();
00147
00148 for (it++; it != m_particles.end (); it++)
00149 {
00150 (*it)->set_ang_velocity(m_ang_velocity);
00151 (*it)->set_velocity(m_velocity);
00152 }
00153 }
00154
00155
00156 double Vamos_Body::
00157 Rigid_Body::lowest_contact_position () const
00158 {
00159 std::vector <Particle*>::const_iterator it = m_particles.begin ();
00160 double pos = transform_out ((*it)->contact_position ()) [2];
00161 double lowest = pos;
00162
00163 for (it++; it != m_particles.end (); it++)
00164 {
00165 pos = transform_out ((*it)->contact_position ()) [2];
00166 if (pos < lowest)
00167 {
00168 lowest = pos;
00169 }
00170 }
00171
00172 return lowest;
00173 }
00174
00175
00176 void Vamos_Body::
00177 Rigid_Body::update_center_of_mass ()
00178 {
00179 if (m_contact_parameters.m_distance > 0.0)
00180 {
00181 }
00182 else
00183 m_last_body_cm = m_body_cm;
00184
00185
00186 m_body_cm = Three_Vector (0.0, 0.0, 0.0);
00187 m_mass = 0.0;
00188 for (std::vector <Particle*>::const_iterator it = m_particles.begin ();
00189 it != m_particles.end ();
00190 it++)
00191 {
00192 m_mass += (*it)->mass ();
00193
00194 m_body_cm += (*it)->mass_position () * (*it)->mass ();
00195 }
00196 m_body_cm /= m_mass;
00197
00198
00199 m_inertia.zero ();
00200
00201 for (std::vector <Particle*>::const_iterator it = m_particles.begin ();
00202 it != m_particles.end ();
00203 it++)
00204 {
00205 m_inertia.add ((*it)->mass (),
00206 (*it)->mass_position () - m_body_cm);
00207 }
00208 m_inertia.update ();
00209 }
00210
00211 void Vamos_Body::
00212 Rigid_Body::find_forces ()
00213 {
00214 for (std::vector <Particle*>::const_iterator it = m_particles.begin ();
00215 it != m_particles.end ();
00216 it++)
00217 {
00218 (*it)->find_forces ();
00219 }
00220 }
00221
00222 void Vamos_Body::
00223 Rigid_Body::propagate_contact()
00224 {
00225
00226 if (m_contact_parameters.m_distance > 0.0)
00227 {
00228 Particle* point = m_contact_parameters.mp_contact_point;
00229 Three_Vector position = rotate_out (point->contact_position ()
00230 - m_body_cm);
00231 Three_Vector velocity = m_cm_velocity + rotate_out (m_ang_velocity).
00232 cross (rotate_out (point->position () - m_body_cm));
00233 Three_Vector ang_vel =
00234 m_ang_velocity.project (m_contact_parameters.m_normal);
00235 point->contact (position,
00236 m_inertia,
00237 rotate_in (velocity),
00238 m_contact_parameters.m_distance,
00239 rotate_in (m_contact_parameters.m_normal),
00240 rotate_in (ang_vel),
00241 m_contact_parameters.m_material);
00242
00243 translate ((m_contact_parameters.m_distance + 0.00)
00244 * m_contact_parameters.m_normal);
00245
00246 m_contact_parameters.m_distance = 0.0;
00247 }
00248 }
00249
00250 void Vamos_Body::
00251 Rigid_Body::single_point_contact(Vamos_Geometry::Three_Vector worldposition,
00252 double distance,
00253 Vamos_Geometry::Three_Vector normal,
00254 Vamos_Geometry::Material_Handle material, double time)
00255 {
00256 if (distance > 0.0)
00257 {
00258 Three_Vector contactposition = transform_in(worldposition);
00259 Three_Vector position = rotate_out (contactposition - m_body_cm);
00260 Three_Vector velocity = m_cm_velocity + rotate_out (m_ang_velocity).
00261 cross (position);
00262 Three_Vector ang_vel =
00263 m_ang_velocity.project (normal);
00264
00265 Vamos_Geometry::Three_Vector v_perp = rotate_in (velocity.project (normal));
00266
00267
00268
00269
00270 double meff = m_inertia.inertia (position, normal);
00271 Three_Vector impulse = -(1.0 + (material->restitution_factor ())) * meff * v_perp;
00272
00273 Vamos_Geometry::Three_Vector v_par = rotate_in (velocity) - v_perp;
00274 impulse -= v_par.unit () * material->friction_factor () * impulse.abs ();
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 translate ((distance + 0.00)
00301 * normal);
00302
00303
00304
00305
00306
00307 Three_Vector total_force;
00308 Three_Vector total_torque;
00309
00310 Three_Vector body_force = impulse / time;
00311 total_force += body_force;
00312
00313
00314
00315
00316
00317
00318
00319 Three_Vector force_dist = m_body_cm - contactposition;
00320 Three_Vector zero(0,0,0);
00321 total_torque += zero - force_dist.cross (body_force);
00322
00323
00324
00325 total_force = rotate_out (total_force) + m_gravity * m_mass;
00326
00327 Three_Vector delta_omega = time * total_torque * m_inertia.inverse ();
00328 Three_Vector delta_theta = (m_ang_velocity + delta_omega) * time;
00329
00330 m_ang_velocity += delta_omega;
00331
00332 Three_Vector delta_v = time * total_force / m_mass;
00333 Three_Vector delta_r = (m_cm_velocity + delta_v) * time;
00334
00335 m_cm_velocity += delta_v;
00336
00337
00338
00339
00340
00341
00342 translate (m_body_cm);
00343
00344
00345
00346 rotate (delta_theta);
00347 translate (delta_r - m_body_cm);
00348
00349
00350
00351 m_velocity = (m_position - m_last_position) / time;
00352 }
00353 }
00354
00355
00356 void Vamos_Body::
00357 Rigid_Body::propagate (double time)
00358 {
00359 valid = true;
00360
00361 bool contact = false;
00362
00363
00364 update_center_of_mass ();
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 for (std::vector <Particle*>::iterator it = m_particles.begin ();
00375 it != m_particles.end ();
00376 it++)
00377 {
00378 (*it)->propagate (time);
00379 }
00380
00381
00382
00383
00384 m_delta_time = time;
00385 Three_Vector total_force;
00386 Three_Vector total_torque;
00387
00388 for (std::vector <Particle*>::const_iterator it = m_particles.begin ();
00389 it != m_particles.end ();
00390 it++)
00391 {
00392
00393
00394 Three_Vector body_force = (*it)->force () + (*it)->impulse () / time;
00395
00396 total_force += body_force;
00397
00398
00399
00400 Three_Vector torque_dist = m_body_cm - (*it)->torque_position ();
00401 Three_Vector torque = (*it)->torque ();
00402 double I = (m_inertia * torque.unit ()).abs ();
00403 torque *= I / (I + m_mass * torque_dist.dot (torque_dist));
00404 Three_Vector force_dist = m_body_cm - (*it)->force_position ();
00405 total_torque += torque - force_dist.cross (body_force);
00406 }
00407
00408
00409
00410 total_force = rotate_out (total_force) + m_gravity * m_mass;
00411
00412 Three_Vector delta_omega = time * total_torque * m_inertia.inverse ();
00413 Three_Vector delta_theta = (m_ang_velocity + delta_omega) * time;
00414 if (!contact)
00415 m_last_ang_velocity = m_ang_velocity;
00416 m_ang_velocity += delta_omega;
00417
00418 Three_Vector delta_v = time * total_force / m_mass;
00419 Three_Vector delta_r = (m_cm_velocity + delta_v) * time;
00420 if (!contact)
00421 m_last_cm_velocity = m_cm_velocity;
00422 m_cm_velocity += delta_v;
00423
00424
00425
00426
00427
00428 if (!contact)
00429 m_last_position = m_position;
00430 translate (m_body_cm);
00431
00432
00433 if (!contact)
00434 m_last_orientation = m_orientation;
00435 rotate (delta_theta);
00436 translate (delta_r - m_body_cm);
00437
00438
00439 if (!contact)
00440 m_last_velocity = m_velocity;
00441 m_velocity = (m_position - m_last_position) / time;
00442 }
00443
00444
00445 void Vamos_Body::
00446 Rigid_Body::rewind ()
00447 {
00448 m_position = m_last_position;
00449 m_velocity = m_last_velocity;
00450 m_cm_velocity = m_last_cm_velocity;
00451
00452 m_orientation = m_last_orientation;
00453 m_ang_velocity = m_last_ang_velocity;
00454 }
00455
00456
00457 void Vamos_Body::
00458 Rigid_Body::end_timestep ()
00459 {
00460 for (std::vector <Particle*>::iterator it = m_particles.begin ();
00461 it != m_particles.end ();
00462 it++)
00463 {
00464 (*it)->end_timestep ();
00465 }
00466 }
00467
00468
00469 Three_Vector Vamos_Body::
00470 Rigid_Body::velocity (Particle* particle)
00471 {
00472 Three_Vector r_vec = particle->position ();
00473 return m_cm_velocity + rotate_out (m_ang_velocity).
00474 cross (rotate_out (r_vec - m_body_cm));
00475 }
00476
00477
00478 void Vamos_Body::
00479 Rigid_Body::contact (Particle* contact_point,
00480 double distance,
00481 const Three_Vector& normal,
00482 const Vamos_Geometry::Material_Handle material)
00483 {
00484 if (contact_point->single_contact ())
00485 {
00486 if (distance > m_contact_parameters.m_distance)
00487 {
00488 m_contact_parameters.mp_contact_point = contact_point;
00489 m_contact_parameters.m_distance = distance;
00490 m_contact_parameters.m_normal = normal;
00491 m_contact_parameters.m_material = material;
00492 }
00493 }
00494 else
00495 {
00496 Three_Vector position =
00497 rotate_out (contact_point->contact_position () - m_body_cm);
00498 Three_Vector ang_vel = m_ang_velocity.project (normal);
00499 Three_Vector velocity = m_cm_velocity + rotate_out (m_ang_velocity).
00500 cross (rotate_out (contact_point->position () - m_body_cm));
00501 contact_point->contact (position,
00502 m_inertia,
00503 rotate_in (velocity),
00504 distance,
00505 rotate_in (normal),
00506 rotate_in (ang_vel),
00507 material);
00508 }
00509 }
00510
00511
00512
00513 void Vamos_Body::
00514 Rigid_Body::wind (Particle* aero_device,
00515 const Three_Vector& wind_vector,
00516 double density)
00517 {
00518 aero_device->wind (rotate_in (wind_vector), density);
00519 }
00520
00521
00522 void Vamos_Body::
00523 Rigid_Body::reset ()
00524 {
00525 m_position = m_initial_position;
00526 m_orientation.identity ();
00527
00528 private_reset ();
00529 }
00530
00531
00532
00533 void Vamos_Body::
00534 Rigid_Body::reset (const Three_Vector& position,
00535 const Three_Matrix& orientation)
00536 {
00537 m_position = position;
00538 m_orientation = orientation;
00539
00540 private_reset ();
00541 }
00542
00543
00544 void Vamos_Body::
00545 Rigid_Body::private_reset ()
00546 {
00547 m_velocity.zero ();
00548 m_cm_velocity.zero ();
00549 m_ang_velocity.zero ();
00550
00551 for (std::vector <Particle*>::iterator it = m_particles.begin ();
00552 it != m_particles.end ();
00553 it++)
00554 {
00555 (*it)->reset ();
00556 }
00557 }