diff --git a/include/configwidget.h b/include/configwidget.h index df7cece2..433fe69a 100644 --- a/include/configwidget.h +++ b/include/configwidget.h @@ -157,7 +157,9 @@ class ConfigWidget : public VarTreeView DEF_FIELD_VALUE(double,Double,Field_Penalty_Width) DEF_FIELD_VALUE(double,Double,Field_Penalty_Depth) DEF_FIELD_VALUE(double,Double,Field_Penalty_Point) - DEF_FIELD_VALUE(double,Double,Field_Margin) + DEF_FIELD_VALUE(double,Double,Field_Margin_Touch_Line) + DEF_FIELD_VALUE(double,Double,Field_Margin_Goal_Line) + DEF_FIELD_VALUE(double,Double,Field_Goal_Substitution_Area_Width) DEF_FIELD_VALUE(double,Double,Field_Referee_Margin) DEF_FIELD_VALUE(double,Double,Wall_Thickness) DEF_FIELD_VALUE(double,Double,Goal_Thickness) diff --git a/src/configwidget.cpp b/src/configwidget.cpp index c88d732e..749d63b7 100644 --- a/src/configwidget.cpp +++ b/src/configwidget.cpp @@ -64,7 +64,9 @@ ConfigWidget::ConfigWidget() { ADD_VALUE(div_a_vars, Double, DivA_Field_Penalty_Width,3.60,"Penalty width") ADD_VALUE(div_a_vars, Double, DivA_Field_Penalty_Depth,1.80,"Penalty depth") ADD_VALUE(div_a_vars, Double, DivA_Field_Penalty_Point,8.00,"Penalty point") - ADD_VALUE(div_a_vars, Double, DivA_Field_Margin,0.3,"Margin") + ADD_VALUE(div_a_vars, Double, DivA_Field_Margin_Touch_Line,0.3,"Margin along the touch lines") + ADD_VALUE(div_a_vars, Double, DivA_Field_Margin_Goal_Line,0.6,"Margin behind the goal lines") + ADD_VALUE(div_a_vars, Double, DivA_Field_Goal_Substitution_Area_Width,0.3,"Substitution area width behind the goal lines") ADD_VALUE(div_a_vars, Double, DivA_Field_Referee_Margin,0.0,"Referee margin") ADD_VALUE(div_a_vars, Double, DivA_Wall_Thickness,0.050,"Wall thickness") ADD_VALUE(div_a_vars, Double, DivA_Goal_Thickness,0.020,"Goal thickness") @@ -80,7 +82,9 @@ ConfigWidget::ConfigWidget() { ADD_VALUE(div_b_vars, Double, DivB_Field_Penalty_Width,2.00,"Penalty width") ADD_VALUE(div_b_vars, Double, DivB_Field_Penalty_Depth,1.0,"Penalty depth") ADD_VALUE(div_b_vars, Double, DivB_Field_Penalty_Point,6.00,"Penalty point") - ADD_VALUE(div_b_vars, Double, DivB_Field_Margin,0.30,"Margin") + ADD_VALUE(div_b_vars, Double, DivB_Field_Margin_Touch_Line,0.3,"Margin along the touch lines") + ADD_VALUE(div_b_vars, Double, DivB_Field_Margin_Goal_Line,0.3,"Margin behind the goal lines") + ADD_VALUE(div_b_vars, Double, DivB_Field_Goal_Substitution_Area_Width,0.0,"Substitution area width behind the goal lines") ADD_VALUE(div_b_vars, Double, DivB_Field_Referee_Margin,0.0,"Referee margin") ADD_VALUE(div_b_vars, Double, DivB_Wall_Thickness,0.050,"Wall thickness") ADD_VALUE(div_b_vars, Double, DivB_Goal_Thickness,0.020,"Goal thickness") diff --git a/src/glwidget.cpp b/src/glwidget.cpp index 46af025d..4ef3d6d4 100644 --- a/src/glwidget.cpp +++ b/src/glwidget.cpp @@ -415,17 +415,17 @@ void GLWidget::changeCameraMode() cammode = static_cast(static_cast(cammode)%(static_cast(CameraMode::MAX_ACTIVE_MODE_FOR_CHANGEMODE)+1)); if (cammode==CameraMode::BIRDS_EYE_FROM_TOUCH_LINE) - ssl->g->setViewpoint(0,-(cfg->Field_Width()+cfg->Field_Margin()*2.0f)/2.0f,3,90,-45,0); + ssl->g->setViewpoint(0,-(cfg->Field_Width()+cfg->Field_Margin_Touch_Line()*2.0f)/2.0f,3,90,-45,0); else if (cammode==CameraMode::CURRENT_ROBOT_VIEW) ssl->g->getViewpoint(xyz,hpr); else if (cammode==CameraMode::TOP_VIEW) ssl->g->setViewpoint(0,0,5,0,-90,0); else if (cammode==CameraMode::BIRDS_EYE_FROM_OPPOSITE_TOUCH_LINE) - ssl->g->setViewpoint(0, (cfg->Field_Width()+cfg->Field_Margin()*2.0f)/2.0f,3,270,-45,0); + ssl->g->setViewpoint(0, (cfg->Field_Width()+cfg->Field_Margin_Touch_Line()*2.0f)/2.0f,3,270,-45,0); else if (cammode==CameraMode::BIRDS_EYE_FROM_BLUE) - ssl->g->setViewpoint(-(cfg->Field_Length()+cfg->Field_Margin()*2.0f)/2.0f,0,3,0,-45,0); + ssl->g->setViewpoint(-(cfg->Field_Length()+cfg->Field_Margin_Goal_Line()*2.0f)/2.0f,0,3,0,-45,0); else if (cammode==CameraMode::BIRDS_EYE_FROM_YELLOW) - ssl->g->setViewpoint((cfg->Field_Length()+cfg->Field_Margin()*2.0f)/2.0f,0,3,180,-45,0); + ssl->g->setViewpoint((cfg->Field_Length()+cfg->Field_Margin_Goal_Line()*2.0f)/2.0f,0,3,180,-45,0); } void GLWidget::putBall(dReal x,dReal y) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0460c905..9a16b9a4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -234,7 +234,8 @@ MainWindow::MainWindow(QWidget *parent) QObject::connect(configwidget->v_DivA_Field_Penalty_Width.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivA_Field_Penalty_Depth.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivA_Field_Penalty_Point.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); - QObject::connect(configwidget->v_DivA_Field_Margin.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); + QObject::connect(configwidget->v_DivA_Field_Margin_Touch_Line.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); + QObject::connect(configwidget->v_DivA_Field_Margin_Goal_Line.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivA_Field_Referee_Margin.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivA_Wall_Thickness.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivA_Goal_Thickness.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); @@ -250,7 +251,8 @@ MainWindow::MainWindow(QWidget *parent) QObject::connect(configwidget->v_DivB_Field_Penalty_Width.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivB_Field_Penalty_Depth.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivB_Field_Penalty_Point.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); - QObject::connect(configwidget->v_DivB_Field_Margin.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); + QObject::connect(configwidget->v_DivB_Field_Margin_Touch_Line.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); + QObject::connect(configwidget->v_DivB_Field_Margin_Goal_Line.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivB_Field_Referee_Margin.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivB_Wall_Thickness.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); QObject::connect(configwidget->v_DivB_Goal_Thickness.get(), SIGNAL(wasEdited(VarPtr)), this, SLOT(restartSimulator())); diff --git a/src/proto/ssl_vision_geometry.proto b/src/proto/ssl_vision_geometry.proto index 440fd1e1..d53efcdf 100644 --- a/src/proto/ssl_vision_geometry.proto +++ b/src/proto/ssl_vision_geometry.proto @@ -49,10 +49,14 @@ message SSL_GeometryFieldSize { required int32 goal_width = 3; required int32 goal_depth = 4; required int32 boundary_width = 5; + // Boundary width at the goal lines (distance from goal line centers to boundary walls) in mm + optional int32 boundary_width_goal_line = 16; repeated SSL_FieldLineSegment field_lines = 6; repeated SSL_FieldCircularArc field_arcs = 7; optional int32 penalty_area_depth = 8; optional int32 penalty_area_width = 9; + // Width of the goal substitution area (distance from boundary walls that count as "inside the substitution area") in mm + optional int32 goal_substitution_area_width = 17; } message SSL_GeometryCameraCalibration { diff --git a/src/sslworld.cpp b/src/sslworld.cpp index ab14858f..83c76d08 100644 --- a/src/sslworld.cpp +++ b/src/sslworld.cpp @@ -144,7 +144,7 @@ SSLWorld::SSLWorld(QGLWidget* parent, ConfigWidget* _cfg, RobotsFormation *form1 last_dt = -1; g = new CGraphics(parent); g->setSphereQuality(1); - g->setViewpoint(0,-(cfg->Field_Width()+cfg->Field_Margin()*2.0f)/2.0f,3,90,-45,0); + g->setViewpoint(0,-(cfg->Field_Width()+cfg->Field_Margin_Touch_Line()*2.0f)/2.0f,3,90,-45,0); p = new PWorld(0.05,9.81f,g,cfg->Robots_Count()); ball = new PBall (0,0,0.5,cfg->BallRadius(),cfg->BallMass(), 1,0.7,0); @@ -157,15 +157,22 @@ SSLWorld::SSLWorld(QGLWidget* parent, ConfigWidget* _cfg, RobotsFormation *form1 // Bounding walls const double thick = cfg->Wall_Thickness(); - const double increment = cfg->Field_Margin() + cfg->Field_Referee_Margin() + thick / 2; - const double pos_x = cfg->Field_Length() / 2.0 + increment; - const double pos_y = cfg->Field_Width() / 2.0 + increment; + const double increment_x = cfg->Field_Margin_Goal_Line() + cfg->Field_Referee_Margin() + thick / 2; + const double increment_y = cfg->Field_Margin_Touch_Line() + cfg->Field_Referee_Margin() + thick / 2; + const double pos_x = cfg->Field_Length() / 2.0 + increment_x; + const double pos_y = cfg->Field_Width() / 2.0 + increment_y; const double pos_z = 0.0; const double siz_x = 2.0 * pos_x; const double siz_y = 2.0 * pos_y; const double siz_z = 0.4; const double tone = 1.0; + // Bounding walls placement + // |-----[0]---- + // | | + // [3] [2] + // | | + // -----[1]----| walls[0] = new PFixedBox(thick/2, pos_y, pos_z, siz_x, thick, siz_z, tone, tone, tone); @@ -182,17 +189,24 @@ SSLWorld::SSLWorld(QGLWidget* parent, ConfigWidget* _cfg, RobotsFormation *form1 thick, siz_y, siz_z, tone, tone, tone); - // Goal walls + // Goal walls, side walls extend to the outside wall const double gthick = cfg->Goal_Thickness(); const double gpos_x = (cfg->Field_Length() + gthick) / 2.0 + cfg->Goal_Depth(); const double gpos_y = (cfg->Goal_Width() + gthick) / 2.0; const double gpos_z = cfg->Goal_Height() / 2.0; - const double gsiz_x = cfg->Goal_Depth() + gthick; + const double gsiz_x = cfg->Field_Margin_Goal_Line() + cfg->Field_Referee_Margin(); const double gsiz_y = cfg->Goal_Width(); const double gsiz_z = cfg->Goal_Height(); const double gpos2_x = (cfg->Field_Length() + gsiz_x) / 2.0; + // Yellow side + // (margin) │ + // ─[6]┬────│ + // │ │ + // [4] │ outside of wall + // │ │ + // ─[5]┴────| walls[4] = new PFixedBox(gpos_x, 0.0, gpos_z, gthick, gsiz_y, gsiz_z, tone, tone, tone); @@ -205,6 +219,13 @@ SSLWorld::SSLWorld(QGLWidget* parent, ConfigWidget* _cfg, RobotsFormation *form1 gsiz_x, gthick, gsiz_z, tone, tone, tone); + // Blue side + // │(margin) + // │────┬[9]─ + // │ │ + // outside of wall │ [7] + // │ │ + // |────┴[8]─ walls[7] = new PFixedBox(-gpos_x, 0.0, gpos_z, gthick, gsiz_y, gsiz_z, tone, tone, tone); @@ -1011,9 +1032,11 @@ SSL_WrapperPacket* SSLWorld::generatePacket(int cam_id) { // Field general info field->set_field_length(CONVUNIT(cfg->Field_Length())); field->set_field_width(CONVUNIT(cfg->Field_Width())); - field->set_boundary_width(CONVUNIT(cfg->Field_Margin())); + field->set_boundary_width(CONVUNIT(cfg->Field_Margin_Touch_Line())); + field->set_boundary_width_goal_line(CONVUNIT(cfg->Field_Margin_Goal_Line())); field->set_goal_width(CONVUNIT(cfg->Goal_Width())); field->set_goal_depth(CONVUNIT(cfg->Goal_Depth())); + field->set_goal_substitution_area_width(CONVUNIT(cfg->Field_Goal_Substitution_Area_Width())); // Field lines and arcs addFieldLinesArcs(field); @@ -1204,7 +1227,7 @@ void RobotsFormation::setAll(const dReal* xx, const dReal *yy) RobotsFormation::RobotsFormation(E_FORMATION type, ConfigWidget* _cfg) : cfg(_cfg) { switch (type) { case FORMATION_OUTSIDE: { - double yv = -(_cfg->Field_Width() / 2 + _cfg->Field_Margin() / 2); + double yv = -(_cfg->Field_Width() / 2 + _cfg->Field_Margin_Touch_Line() / 2); dReal teamPosX[MAX_ROBOT_COUNT] = {0.40, 0.80, 1.20, 1.60, 2.00, 2.40, 2.80, 3.20, 3.60, 4.00, 4.40, 4.80, 0.40, 0.80, 1.20, 1.60}; @@ -1233,7 +1256,7 @@ RobotsFormation::RobotsFormation(E_FORMATION type, ConfigWidget* _cfg) : cfg(_cf break; } case FORMATION_OUTSIDE_FIELD: { - double yv = -(_cfg->Field_Width() / 2 + _cfg->Field_Margin() + _cfg->Field_Referee_Margin() + 0.5); + double yv = -(_cfg->Field_Width() / 2 + _cfg->Field_Margin_Touch_Line() + _cfg->Field_Referee_Margin() + 0.5); dReal teamPosX[MAX_ROBOT_COUNT] = { 0.40, 0.80, 1.20, 1.60, 2.00, 2.40, 2.80, 3.20, 3.60, 4.00, 4.40, 4.80, 0.40, 0.80, 1.20, 1.60};