25 #include <mrpt/poses/CPose2D.h> 26 #include <mrpt/opengl/CPolyhedron.h> 32 using namespace mvsim;
43 static bool done =
false;
55 constexpr
char VehicleBase::DL_TIMESTAMP[];
56 constexpr
char VehicleBase::LOGGER_POSE[];
57 constexpr
char VehicleBase::LOGGER_WHEEL[];
59 constexpr
char VehicleBase::PL_Q_X[];
60 constexpr
char VehicleBase::PL_Q_Y[];
61 constexpr
char VehicleBase::PL_Q_Z[];
62 constexpr
char VehicleBase::PL_Q_YAW[];
63 constexpr
char VehicleBase::PL_Q_PITCH[];
64 constexpr
char VehicleBase::PL_Q_ROLL[];
65 constexpr
char VehicleBase::PL_DQ_X[];
66 constexpr
char VehicleBase::PL_DQ_Y[];
67 constexpr
char VehicleBase::PL_DQ_Z[];
69 constexpr
char VehicleBase::WL_TORQUE[];
70 constexpr
char VehicleBase::WL_WEIGHT[];
71 constexpr
char VehicleBase::WL_VEL_X[];
72 constexpr
char VehicleBase::WL_VEL_Y[];
73 constexpr
char VehicleBase::WL_FRIC_X[];
74 constexpr
char VehicleBase::WL_FRIC_Y[];
80 m_b2d_vehicle_body(NULL),
81 m_q(0, 0, 0, 0, 0, 0),
84 m_chassis_z_min(0.05),
86 m_chassis_color(0xff, 0x00, 0x00),
87 m_chassis_com(.0, .0),
88 m_wheels_info(nWheels),
89 m_fixture_wheels(nWheels, NULL)
93 m_chassis_poly.push_back(TPoint2D(-0.4, -0.5));
94 m_chassis_poly.push_back(TPoint2D(-0.4, 0.5));
95 m_chassis_poly.push_back(TPoint2D(0.4, 0.5));
96 m_chassis_poly.push_back(TPoint2D(0.6, 0.3));
97 m_chassis_poly.push_back(TPoint2D(0.6, -0.3));
98 m_chassis_poly.push_back(TPoint2D(0.4, -0.5));
99 updateMaxRadiusFromPoly();
104 if (m_b2d_vehicle_body)
107 const b2Vec2& pos = m_b2d_vehicle_body->GetPosition();
116 const b2Vec2& vel = m_b2d_vehicle_body->GetLinearVelocity();
117 const float32 w = m_b2d_vehicle_body->GetAngularVelocity();
118 m_dq.vals[0] = vel(0);
119 m_dq.vals[1] = vel(1);
132 "[VehicleBase::register_vehicle_class] XML node is NULL");
133 if (0 != strcmp(xml_node->
name(),
"vehicle:class"))
136 "[VehicleBase::register_vehicle_class] XML element is '%s' " 137 "('vehicle:class' expected)",
142 std::stringstream ss;
158 if (!root)
throw runtime_error(
"[VehicleBase::factory] XML node is NULL");
159 if (0 != strcmp(root->
name(),
"vehicle"))
162 "[VehicleBase::factory] XML root element is '%s' ('vehicle' " 178 const string sClassName = veh_class->
value();
184 "[VehicleBase::factory] Vehicle class '%s' undefined",
185 sClassName.c_str()));
187 veh_root_node.
add(class_root);
194 const xml_node<>* dyn_node = veh_root_node.
first_node(
"dynamics");
197 "[VehicleBase::factory] Missing XML node <dynamics>");
200 if (!dyn_class || !dyn_class->
value())
202 "[VehicleBase::factory] Missing mandatory attribute 'class' in " 210 "[VehicleBase::factory] Unknown vehicle dynamics class '%s'",
211 dyn_class->
value()));
218 if (attrib_name && attrib_name->
value())
226 veh->
m_name = mrpt::format(
"veh%i", ++cnt);
232 const xml_node<>* node = veh_root_node.
first_node(
"init_pose");
235 "[VehicleBase::factory] Missing XML node <init_pose>");
238 node->value(),
"%lf %lf %lf", &veh->m_q.x, &veh->m_q.y,
241 "[VehicleBase::factory] Error parsing " 242 "<init_pose>...</init_pose>");
243 veh->m_q.yaw *= M_PI / 180.0;
248 const xml_node<>* node = veh_root_node.
first_node(
"init_vel");
252 node->value(),
"%lf %lf %lf", &veh->m_dq.vals[0],
253 &veh->m_dq.vals[1], &veh->m_dq.vals[2]))
255 "[VehicleBase::factory] Error parsing " 256 "<init_vel>...</init_vel>");
257 veh->m_dq.vals[2] *= M_PI / 180.0;
260 const mrpt::poses::CPose2D pose(
263 veh->m_dq.vals[0], veh->m_dq.vals[1], veh->m_dq.vals[0],
275 const xml_node<>* log_path_node = veh_root_node.
first_node(
"log_path");
290 if (veh->m_b2d_vehicle_body)
293 veh->m_b2d_vehicle_body->SetTransform(
294 b2Vec2(veh->m_q.x, veh->m_q.y), veh->m_q.yaw);
296 veh->m_b2d_vehicle_body->SetLinearVelocity(
297 b2Vec2(veh->m_dq.vals[0], veh->m_dq.vals[1]));
298 veh->m_b2d_vehicle_body->SetAngularVelocity(veh->m_dq.vals[2]);
305 const xml_node<>* frict_node = veh_root_node.
first_node(
"friction");
309 veh->m_friction = std::shared_ptr<FrictionBase>(
315 veh->m_friction = std::shared_ptr<FrictionBase>(
317 ASSERT_(veh->m_friction);
324 it != veh_root_node.
end(); ++it)
326 if (!strcmp(it->name(),
"sensor"))
342 char* input_str =
const_cast<char*
>(xml_text.c_str());
346 xml.
parse<0>(input_str);
351 static_cast<long>(std::count(input_str, e.
where<
char>(),
'\n') + 1);
352 throw std::runtime_error(
354 "[VehicleBase::factory] XML parse error (Line %u): %s",
355 static_cast<unsigned>(line), e.
what()));
364 for (
size_t i = 0; i < m_fixture_wheels.size(); i++)
369 m_wheels_info[i].diameter * 0.5, m_wheels_info[i].width * 0.5,
370 b2Vec2(m_wheels_info[i].
x, m_wheels_info[i].
y),
371 m_wheels_info[i].yaw);
379 ASSERT_EQUAL_(m_torque_per_wheel.size(), nW);
382 const double massPerWheel =
384 const double weightPerWheel = massPerWheel * gravity;
386 std::vector<mrpt::math::TPoint2D> wheels_vels;
389 ASSERT_EQUAL_(wheels_vels.size(), nW);
391 std::vector<mrpt::math::TSegment3D>
394 for (
size_t i = 0; i < nW; i++)
401 -m_torque_per_wheel[i];
402 fi.
weight = weightPerWheel;
405 m_friction->setLogger(
408 mrpt::math::TPoint2D net_force_;
409 m_friction->evaluate_friction(fi, net_force_);
412 const b2Vec2 wForce = m_b2d_vehicle_body->GetWorldVector(
414 net_force_.x, net_force_.y));
415 const b2Vec2 wPt = m_b2d_vehicle_body->GetWorldPoint(
420 m_b2d_vehicle_body->ApplyForce(wForce, wPt,
true );
424 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)]->updateColumn(
426 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)]->updateColumn(
428 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)]->updateColumn(
430 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)]->updateColumn(
432 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)]->updateColumn(
434 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)]->updateColumn(
435 WL_FRIC_X, net_force_.x);
436 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)]->updateColumn(
437 WL_FRIC_Y, net_force_.y);
443 const double forceScale =
445 const mrpt::math::TPoint3D pt1(
446 wPt.
x, wPt.
y, m_chassis_z_max * 1.1 + m_q.z);
447 const mrpt::math::TPoint3D pt2 =
448 pt1 + mrpt::math::TPoint3D(wForce.
x, wForce.
y, 0) * forceScale;
449 force_vectors.push_back(mrpt::math::TSegment3D(pt1, pt2));
456 std::lock_guard<std::mutex> csl(m_force_segments_for_rendering_cs);
457 m_force_segments_for_rendering = force_vectors;
468 for (
size_t i = 0; i < nW; i++)
479 const double cur_abs_phi = std::abs(w.
getPhi());
480 if (cur_abs_phi > 1e4)
482 ::fmod(cur_abs_phi, 2 * M_PI) *
483 (w.
getPhi() < 0.0 ? -1.0 : 1.0));
487 m_loggers[LOGGER_POSE]->updateColumn(PL_Q_X, m_q.x);
488 m_loggers[LOGGER_POSE]->updateColumn(PL_Q_Y, m_q.y);
489 m_loggers[LOGGER_POSE]->updateColumn(PL_Q_Z, m_q.z);
490 m_loggers[LOGGER_POSE]->updateColumn(PL_Q_YAW, m_q.yaw);
491 m_loggers[LOGGER_POSE]->updateColumn(PL_Q_PITCH, m_q.pitch);
492 m_loggers[LOGGER_POSE]->updateColumn(PL_Q_ROLL, m_q.roll);
493 m_loggers[LOGGER_POSE]->updateColumn(PL_DQ_X, m_dq.vals[0]);
494 m_loggers[LOGGER_POSE]->updateColumn(PL_DQ_Y, m_dq.vals[1]);
495 m_loggers[LOGGER_POSE]->updateColumn(PL_DQ_Z, m_dq.vals[2]);
504 std::vector<mrpt::math::TPoint2D>& vels,
const vec3& veh_vel_local)
const 511 const double w = veh_vel_local.
vals[2];
515 for (
size_t i = 0; i < nW; i++)
519 vels[i].x = veh_vel_local.
vals[0] - w * wheel.
y;
520 vels[i].y = veh_vel_local.
vals[1] + w * wheel.
x;
528 local_vel.
vals[2] = m_dq.vals[2];
530 const mrpt::poses::CPose2D p(0, 0, -m_q.yaw);
532 m_dq.vals[0], m_dq.vals[1], local_vel.
vals[0], local_vel.
vals[1]);
538 return mrpt::poses::CPose2D(mrpt::math::TPose2D(m_q));
543 mrpt::opengl::COpenGLScene& scene,
bool defaultVehicleBody)
547 if (defaultVehicleBody)
552 m_gl_chassis = mrpt::opengl::CSetOfObjects::Create();
555 m_gl_wheels.resize(nWs);
556 for (
size_t i = 0; i < nWs; i++)
558 m_gl_wheels[i] = mrpt::opengl::CSetOfObjects::Create();
560 m_gl_chassis->insert(m_gl_wheels[i]);
563 mrpt::opengl::CPolyhedron::Ptr gl_poly =
564 mrpt::opengl::CPolyhedron::CreateCustomPrism(
565 m_chassis_poly, m_chassis_z_max - m_chassis_z_min);
566 gl_poly->setLocation(0, 0, m_chassis_z_min);
567 gl_poly->setColor(TColorf(m_chassis_color));
568 m_gl_chassis->insert(gl_poly);
573 m_gl_forces = mrpt::opengl::CSetOfLines::Create();
574 m_gl_forces->setLineWidth(3.0);
575 m_gl_forces->setColor_u8(TColor(0xff, 0xff, 0xff));
578 scene, 3, m_gl_forces);
583 m_gl_chassis->setPose(m_q);
585 for (
size_t i = 0; i < nWs; i++)
588 m_gl_wheels[i]->setPose(
595 internal_gui_update_sensors(scene);
596 internal_gui_update_forces(scene);
599 void VehicleBase::internal_gui_update_sensors(mrpt::opengl::COpenGLScene& scene)
601 for (TListSensors::iterator it = m_sensors.begin(); it != m_sensors.end();
603 (*it)->gui_update(scene);
606 void VehicleBase::internal_gui_update_forces(mrpt::opengl::COpenGLScene& scene)
610 std::lock_guard<std::mutex> csl(m_force_segments_for_rendering_cs);
611 m_gl_forces->clear();
612 m_gl_forces->appendLines(m_force_segments_for_rendering);
613 m_gl_forces->setVisibility(
true);
617 m_gl_forces->setVisibility(
false);
621 void VehicleBase::updateMaxRadiusFromPoly()
625 m_max_radius = 0.001f;
626 for (TPolygon2D::const_iterator it = m_chassis_poly.begin();
627 it != m_chassis_poly.end(); ++it)
629 const float n = it->norm();
630 keep_max(m_max_radius, n);
641 m_b2d_vehicle_body = world->
CreateBody(&bodyDef);
647 const size_t nPts = m_chassis_poly.size();
650 std::vector<b2Vec2> pts(nPts);
651 for (
size_t i = 0; i < nPts; i++)
652 pts[i] =
b2Vec2(m_chassis_poly[i].
x, m_chassis_poly[i].
y);
655 chassisPoly.
Set(&pts[0], nPts);
660 fixtureDef.
shape = &chassisPoly;
673 m_fixture_chassis = m_b2d_vehicle_body->CreateFixture(&fixtureDef);
677 m_fixture_chassis->GetMassData(&vehMass);
678 m_chassis_com.x = vehMass.
center.
x;
679 m_chassis_com.y = vehMass.
center.
y;
684 ASSERT_EQUAL_(m_fixture_wheels.size(), m_wheels_info.size());
686 for (
size_t i = 0; i < m_wheels_info.size(); i++)
690 m_wheels_info[i].diameter * 0.5, m_wheels_info[i].width * 0.5,
691 b2Vec2(m_wheels_info[i].
x, m_wheels_info[i].
y),
692 m_wheels_info[i].yaw);
696 fixtureDef.
shape = &wheelShape;
703 fixtureDef.
density = m_wheels_info[i].mass / mass.
mass;
708 m_fixture_wheels[i] = m_b2d_vehicle_body->CreateFixture(&fixtureDef);
719 m_loggers[LOGGER_POSE] = std::make_shared<CSVLogger>();
735 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)] =
736 std::make_shared<CSVLogger>();
751 m_loggers[LOGGER_WHEEL + std::to_string(i + 1)]->setFilepath(
753 std::to_string(i + 1) +
".log");
759 std::map<std::string, std::shared_ptr<CSVLogger>>::iterator it;
762 it->second->writeRow();
767 double fx,
double fy,
double local_ptx,
double local_pty)
769 ASSERT_(m_b2d_vehicle_body);
770 const b2Vec2 wPt = m_b2d_vehicle_body->GetWorldPoint(
771 b2Vec2(local_ptx, local_pty));
772 m_b2d_vehicle_body->ApplyForce(
b2Vec2(fx, fy), wPt,
true );
double force_scale
In meters/Newton.
This file contains rapidxml parser and DOM implementation.
virtual void create_multibody_system(b2World *world)
void getWheelsVelocityLocal(std::vector< mrpt::math::TPoint2D > &vels, const vec3 &veh_vel_local) const
virtual void dynamics_load_params_from_xml(const rapidxml::xml_node< char > *xml_node)=0
double simul_time
Current time in the simulated world.
#define REGISTER_VEHICLE_DYNAMICS(TEXTUAL_NAME, CLASS_NAME)
virtual void initLoggers()
virtual void apply_force(double fx, double fy, double local_ptx=0.0, double local_pty=0.0)
void getAs3DObject(mrpt::opengl::CSetOfObjects &obj)
std::shared_ptr< CSVLogger > getLoggerPtr(std::string logger_name)
b2Vec2 center
The position of the shape's centroid relative to the shape's origin.
TFSIMD_FORCE_INLINE const tfScalar & y() const
virtual void simul_post_timestep(const TSimulContext &context)
xml_node< Ch > * first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
double get_gravity() const
TClassFactory_vehicleDynamics classFactory_vehicleDynamics
static FrictionBase * factory(VehicleBase &parent, const rapidxml::xml_node< char > *xml_node)
size_t getNumWheels() const
void ComputeMass(b2MassData *massData, float32 density) const
float32 mass
The mass of the shape, usually in kilograms.
VehicleBase(World *parent, size_t nWheels)
CLASS * create(const std::string &class_name, ARG1 a1) const
void setPhi(double val)
Orientation (rad) wrt vehicle local frame.
double getW() const
Spinning velocity (rad/s) wrt shaft.
#define SCENE_INSERT_Z_ORDER(_SCENE, _ZORDER_INDEX, _OBJ_TO_INSERT)
std::shared_ptr< SensorBase > Ptr
virtual void simul_pre_timestep(const TSimulContext &context)
TGUI_Options m_gui_options
double diameter
[m,rad] (in local coords)
virtual const char * what() const
xml_attribute< Ch > * first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
#define b2_maxPolygonVertices
static void register_vehicle_class(const rapidxml::xml_node< char > *xml_node)
TFSIMD_FORCE_INLINE const tfScalar & x() const
std::map< std::string, std::shared_ptr< CSVLogger > > m_loggers
float32 density
The density, usually in kg/m^2.
const Wheel & getWheelInfo(const size_t idx) const
virtual void invoke_motor_controllers(const TSimulContext &context, std::vector< double > &out_force_per_wheel)=0
void SetAsBox(float32 hx, float32 hy)
double getPhi() const
Orientation (rad) wrt vehicle local frame.
void gui_update_common(mrpt::opengl::COpenGLScene &scene, bool defaultVehicleBody=true)
const rapidxml::xml_node< Ch > * first_node(const char *name)
virtual void gui_update(mrpt::opengl::COpenGLScene &scene)
TFSIMD_FORCE_INLINE const tfScalar & w() const
void Set(const b2Vec2 *points, int32 count)
virtual void writeLogStrings()
float32 restitution
The restitution (elasticity) usually in the range [0,1].
void simul_post_timestep_common(const TSimulContext &context)
const rapidxml::xml_node< char > * get(const std::string &xml_node_class) const
static SensorBase * factory(VehicleBase &parent, const rapidxml::xml_node< char > *xml_node)
b2World * getBox2DWorld()
This file contains rapidxml printer implementation.
mrpt::poses::CPose2D getCPose2D() const
void add(const std::string &input_xml_node_class)
void register_all_veh_dynamics()
XmlClassesRegistry veh_classes_registry("vehicle:class")
vec3 getVelocityLocal() const
This holds the mass data computed for a shape.
void add(const rapidxml::xml_node< Ch > *node)
float32 friction
The friction coefficient, usually in the range [0,1].
virtual double getChassisMass() const
b2Body * CreateBody(const b2BodyDef *def)
std::string m_name
User-supplied name of the vehicle (e.g. "r1", "veh1")
static VehicleBase * factory(World *parent, const rapidxml::xml_node< char > *xml_node)