#VRML_SIM R2025a utf8
# Shepherd Dog Robot - wheeled base with dog character on top, tail-mounted 360 lidar

EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/appearances/protos/TireRubber.proto"

PROTO ShepherdDog360 [
  field SFVec3f    translation     0 0 0
  field SFRotation rotation        0 1 0 0
  field SFString   name            "ShepherdDog"
  field SFString   controller      "shepherd_dog"
  field MFString   controllerArgs  []
  field SFString   customData      ""
  field SFBool     supervisor      FALSE
  field SFBool     synchronization TRUE
]
{
  Robot {
    translation IS translation
    rotation IS rotation
    name IS name
    controller IS controller
    controllerArgs IS controllerArgs
    customData IS customData
    supervisor IS supervisor
    synchronization IS synchronization
    children [
      # ========== CHASSIS / BASE ==========
      DEF CHASSIS Transform {
        translation 0 0 0.05
        children [
          Shape {
            appearance DEF CHASSIS_APP PBRAppearance {
              baseColor 0.2 0.2 0.2
              roughness 0.6
              metalness 0.3
            }
            geometry Box {
              size 0.32 0.16 0.06
            }
          }
        ]
      }
      # Front slope
      DEF CHASSIS_FRONT Transform {
        translation 0.14 0 0.07
        children [
          Shape {
            appearance USE CHASSIS_APP
            geometry Box {
              size 0.06 0.14 0.04
            }
          }
        ]
      }
      # Rear slope
      DEF CHASSIS_REAR Transform {
        translation -0.14 0 0.07
        children [
          Shape {
            appearance USE CHASSIS_APP
            geometry Box {
              size 0.06 0.14 0.04
            }
          }
        ]
      }

      # ========== DOG BODY on top of chassis ==========
      DEF BODY Transform {
        translation 0 0 0.11
        children [
          Shape {
            appearance DEF FUR_BROWN PBRAppearance {
              baseColor 0.55 0.35 0.17
              roughness 0.85
              metalness 0.0
            }
            geometry Box {
              size 0.30 0.16 0.08
            }
          }
        ]
      }

      # ========== CHEST ==========
      DEF CHEST Transform {
        translation 0.12 0 0.11
        children [
          Shape {
            appearance DEF FUR_CREAM PBRAppearance {
              baseColor 0.85 0.72 0.55
              roughness 0.85
              metalness 0.0
            }
            geometry Box {
              size 0.08 0.18 0.08
            }
          }
        ]
      }

      # ========== HEAD ==========
      DEF HEAD Transform {
        translation 0.20 0 0.17
        children [
          Shape {
            appearance USE FUR_BROWN
            geometry Box {
              size 0.10 0.12 0.09
            }
          }
        ]
      }

      # ========== SNOUT + LIDAR ==========
      DEF SNOUT Transform {
        translation 0.28 0 0.155
        children [
          Shape {
            appearance USE FUR_CREAM
            geometry Box {
              size 0.08 0.07 0.05
            }
          }
          # Nose
          Transform {
            translation 0.04 0 0.01
            children [
              Shape {
                appearance PBRAppearance {
                  baseColor 0.1 0.1 0.1
                  roughness 0.4
                }
                geometry Sphere {
                  radius 0.013
                  subdivision 2
                }
              }
            ]
          }
          # Lidar — 360° FOV (was 140°/2.44 rad). Wider FOV closes the
          # FOV-loss perception gap so policies trained on 360° gym sim
          # transfer cleanly without retraining.
          Lidar {
            translation 0.05 0 0.01
            name "lidar"
            horizontalResolution 360
            fieldOfView 6.28
            numberOfLayers 1
            minRange 0.10
            maxRange 15.0
            noise 0.005
          }
        ]
      }

      # ========== LEFT EAR ==========
      DEF LEFT_EAR HingeJoint {
        jointParameters HingeJointParameters {
          axis 0 0 1
          anchor 0.19 0.055 0.21
        }
        device [
          RotationalMotor {
            name "left ear motor"
            maxVelocity 10.0
            minPosition -0.5
            maxPosition 0.5
          }
        ]
        endPoint Solid {
          translation 0.19 0.055 0.21
          rotation 0 0 1 0.2
          name "left ear"
          children [
            Shape {
              appearance DEF FUR_DARK PBRAppearance {
                baseColor 0.35 0.20 0.10
                roughness 0.85
                metalness 0.0
              }
              geometry Box {
                size 0.035 0.025 0.06
              }
            }
          ]
          boundingObject Box {
            size 0.035 0.025 0.06
          }
          physics Physics {
            density -1
            mass 0.005
          }
        }
      }

      # ========== RIGHT EAR ==========
      DEF RIGHT_EAR HingeJoint {
        jointParameters HingeJointParameters {
          axis 0 0 1
          anchor 0.19 -0.055 0.21
        }
        device [
          RotationalMotor {
            name "right ear motor"
            maxVelocity 10.0
            minPosition -0.5
            maxPosition 0.5
          }
        ]
        endPoint Solid {
          translation 0.19 -0.055 0.21
          rotation 0 0 -1 0.2
          name "right ear"
          children [
            Shape {
              appearance USE FUR_DARK
              geometry Box {
                size 0.035 0.025 0.06
              }
            }
          ]
          boundingObject Box {
            size 0.035 0.025 0.06
          }
          physics Physics {
            density -1
            mass 0.005
          }
        }
      }

      # ========== EYES ==========
      DEF LEFT_EYE Transform {
        translation 0.25 0.05 0.19
        children [
          Shape {
            appearance PBRAppearance {
              baseColor 0.95 0.95 0.95
              roughness 0.3
            }
            geometry Sphere {
              radius 0.016
              subdivision 2
            }
          }
          # Pupil
          Transform {
            translation 0.012 0 0.004
            children [
              Shape {
                appearance PBRAppearance {
                  baseColor 0.1 0.1 0.1
                  roughness 0.2
                }
                geometry Sphere {
                  radius 0.009
                  subdivision 2
                }
              }
            ]
          }
        ]
      }
      DEF RIGHT_EYE Transform {
        translation 0.25 -0.05 0.19
        children [
          Shape {
            appearance PBRAppearance {
              baseColor 0.95 0.95 0.95
              roughness 0.3
            }
            geometry Sphere {
              radius 0.016
              subdivision 2
            }
          }
          # Pupil
          Transform {
            translation 0.012 0 0.004
            children [
              Shape {
                appearance PBRAppearance {
                  baseColor 0.1 0.1 0.1
                  roughness 0.2
                }
                geometry Sphere {
                  radius 0.009
                  subdivision 2
                }
              }
            ]
          }
        ]
      }

      # ========== COLLAR ==========
      DEF COLLAR Transform {
        translation 0.16 0 0.125
        children [
          Shape {
            appearance PBRAppearance {
              baseColor 0.8 0.1 0.1
              roughness 0.5
            }
            geometry Cylinder {
              height 0.02
              radius 0.095
              subdivision 16
            }
          }
          # ID tag
          Transform {
            translation 0 0.10 0
            rotation 1 0 0 1.5708
            children [
              Shape {
                appearance PBRAppearance {
                  baseColor 0.75 0.75 0.0
                  metalness 0.8
                  roughness 0.2
                }
                geometry Cylinder {
                  height 0.003
                  radius 0.018
                  subdivision 8
                }
              }
            ]
          }
        ]
      }

      # ========== TAIL (lidar inside tail tip ball) ==========
      DEF TAIL HingeJoint {
        jointParameters HingeJointParameters {
          axis 0 1 0
          anchor -0.15 0 0.11
        }
        device [
          RotationalMotor {
            name "tail motor"
            maxVelocity 5.0
            minPosition -1.0
            maxPosition 1.0
          }
        ]
        endPoint Solid {
          translation -0.17 0 0.13
          name "tail solid"
          children [
            Shape {
              appearance USE FUR_BROWN
              geometry Capsule {
                height 0.12
                radius 0.013
                top FALSE
              }
            }
            # Tail tip ball
            Transform {
              translation 0 0 0.08
              children [
                Shape {
                  appearance PBRAppearance {
                    baseColor 0.2 0.2 0.2
                    roughness 0.3
                    metalness 0.6
                  }
                  geometry Sphere {
                    radius 0.028
                    subdivision 4
                  }
                }
              ]
            }
          ]
          boundingObject Group {
            children [
              Capsule {
                height 0.12
                radius 0.013
              }
              Transform {
                translation 0 0 0.08
                children [
                  Sphere {
                    radius 0.028
                  }
                ]
              }
            ]
          }
          physics Physics {
            density -1
            mass 0.08
          }
        }
      }

      # ========== RIGHT AXLE ARM (horizontal bar from chassis to wheel) ==========
      DEF RIGHT_AXLE Transform {
        translation 0 -0.115 0.038
        children [
          Shape {
            appearance PBRAppearance {
              baseColor 0.5 0.5 0.5
              roughness 0.3
              metalness 0.8
            }
            geometry Box {
              size 0.02 0.08 0.02
            }
          }
        ]
      }

      # ========== LEFT AXLE ARM ==========
      DEF LEFT_AXLE Transform {
        translation 0 0.115 0.038
        children [
          Shape {
            appearance PBRAppearance {
              baseColor 0.5 0.5 0.5
              roughness 0.3
              metalness 0.8
            }
            geometry Box {
              size 0.02 0.08 0.02
            }
          }
        ]
      }

      # ========== RIGHT WHEEL ==========
      DEF RIGHT_WHEEL_JOINT HingeJoint {
        jointParameters HingeJointParameters {
          axis 0 1 0
          anchor 0 -0.14 0.038
        }
        device [
          RotationalMotor {
            name "right wheel motor"
            maxVelocity 70.0
            maxTorque 20.0
          }
          PositionSensor {
            name "right wheel sensor"
            resolution 0.00628
          }
        ]
        endPoint Solid {
          translation 0 -0.14 0.038
          rotation 0 -1 0 1.570796
          children [
            DEF WHEEL_VIS Pose {
              rotation 1 0 0 -1.5708
              children [
                Shape {
                  appearance PBRAppearance {
                    baseColor 0.15 0.15 0.15
                    roughness 0.4
                    metalness 0.5
                  }
                  geometry Cylinder {
                    height 0.016
                    radius 0.035
                    subdivision 24
                  }
                }
                Shape {
                  appearance PBRAppearance {
                    baseColor 0.6 0.6 0.6
                    roughness 0.3
                    metalness 0.7
                  }
                  geometry Cylinder {
                    height 0.018
                    radius 0.014
                    subdivision 12
                  }
                }
                Shape {
                  appearance TireRubber {
                    textureTransform TextureTransform {
                      scale 1.5 0.6
                    }
                    type "bike"
                  }
                  geometry Cylinder {
                    height 0.022
                    radius 0.038
                    subdivision 24
                  }
                }
              ]
            }
          ]
          name "right wheel"
          boundingObject Pose {
            rotation 1 0 0 -1.5708
            children [
              Cylinder {
                height 0.022
                radius 0.038
              }
            ]
          }
          physics Physics {
            density -1
            mass 0.06
            centerOfMass [
              0 0 0
            ]
          }
        }
      }

      # ========== LEFT WHEEL ==========
      DEF LEFT_WHEEL_JOINT HingeJoint {
        jointParameters HingeJointParameters {
          axis 0 1 0
          anchor 0 0.14 0.038
        }
        device [
          RotationalMotor {
            name "left wheel motor"
            maxVelocity 70.0
            maxTorque 20.0
          }
          PositionSensor {
            name "left wheel sensor"
            resolution 0.00628
          }
        ]
        endPoint Solid {
          translation 0 0.14 0.038
          rotation 0.707105 0 0.707109 -3.14159
          children [
            USE WHEEL_VIS
          ]
          name "left wheel"
          boundingObject Pose {
            rotation 1 0 0 -1.5708
            children [
              Cylinder {
                height 0.022
                radius 0.038
              }
            ]
          }
          physics Physics {
            density -1
            mass 0.12
            centerOfMass [
              0 0 0
            ]
          }
        }
      }

      # ========== FRONT CASTER ==========
      DEF FRONT_CASTER BallJoint {
        jointParameters BallJointParameters {
          anchor 0.14 0 0.02
        }
        endPoint Solid {
          translation 0.14 0 0.02
          name "front caster"
          children [
            Shape {
              appearance PBRAppearance {
                baseColor 0.2 0.2 0.2
                roughness 0.3
                metalness 0.5
              }
              geometry Sphere {
                radius 0.02
                subdivision 2
              }
            }
          ]
          boundingObject Sphere {
            radius 0.02
          }
          physics Physics {
            density -1
            mass 0.03
          }
        }
      }

      # ========== REAR CASTER ==========
      DEF REAR_CASTER BallJoint {
        jointParameters BallJointParameters {
          anchor -0.14 0 0.02
        }
        endPoint Solid {
          translation -0.14 0 0.02
          name "rear caster"
          children [
            Shape {
              appearance PBRAppearance {
                baseColor 0.2 0.2 0.2
                roughness 0.3
                metalness 0.5
              }
              geometry Sphere {
                radius 0.02
                subdivision 2
              }
            }
          ]
          boundingObject Sphere {
            radius 0.02
          }
          physics Physics {
            density -1
            mass 0.03
          }
        }
      }

      # ========== IMU SENSORS ==========
      Accelerometer {
        translation 0 0 0.10
        name "accelerometer"
      }
      Gyro {
        translation 0 0 0.10
        name "gyro"
      }
      Compass {
        translation 0 0 0.10
        name "compass"
      }

      # ========== GPS ==========
      GPS {
        translation 0 0 0.17
        name "gps"
      }

      # ========== RECEIVER ==========
      Receiver {
        name "receiver"
        channel 1
      }

      # ========== EMITTER ==========
      Emitter {
        name "emitter"
        channel 1
        range 50.0
      }
    ]

    # ========== BOUNDING OBJECT ==========
    boundingObject Group {
      children [
        # Chassis box
        Transform {
          translation 0 0 0.05
          children [
            Box {
              size 0.32 0.16 0.06
            }
          ]
        }
        # Body box
        Transform {
          translation 0 0 0.11
          children [
            Box {
              size 0.30 0.16 0.08
            }
          ]
        }
      ]
    }

    # ========== PHYSICS ==========
    physics Physics {
      density -1
      mass 5.0
      centerOfMass [
        0 0 0.03
      ]
    }
  }
}
