dd5ac669e5
Today's session worked across the full Webots delivery stack — found and
fixed a cluster of bugs blocking the BC/RL transfer, then explored
training-side mitigations for the residual perception gap.
Bug fixes:
- Makefile FP_RATE default 2.0 → 0.0: BC demos used fp_rate=0 but RL
fine-tune defaulted to fp_rate=2, poisoning the BC obs distribution
and stalling PPO at 0% success across 1.46M+ steps.
- controllers/{shepherd_dog,sheep}/runtime.ini: Webots was launching
controllers under system python3 (no numpy) and they were crashing
silently. Pinned to the conda tir env.
- herding/config.py HERDING_WEBOTS preset: pen_latch_depth 0.5 → 2.0,
max_new_tracks_per_step 3 → 1, static_reject 0.8 → 1.2. Stops phantom
FPs near the gate from latching as permanently-penned tracks.
- herding/perception/sheep_tracker.py: penned tracks now decay at
forget_steps × 8 instead of living forever. Adds get_positions
min_freshness filter for deploy-time use.
Training/eval matches deployment:
- training/bc/collect.py: --dagger-policy flag for DAgger rollouts
(policy drives, teacher labels) + --use-webots-preset for matched
140° tracker + DR config.
- controllers/shepherd_dog/shepherd_dog.py: scan-fallback (0, 0.6) when
BC/RL sees empty sheep_positions — recovers from FOV gaps.
Tooling:
- tools/dagger_round.sh: one-shot DAgger round (collect + concat + bc).
- tools/webots_sweep_gt.sh: full sweep with HERDING_USE_GT=1 for the
perception-gap diagnosis matrix.
- protos/ShepherdDog360.proto: 360° FOV variant for the FOV-ablation
comparison. Canonical proto stays at 140° per project spec.
Artifacts: v1 BC/RL policies for all 4 (drive × world) combos trained
in clean gym (success: diff/field 90-100%, diff/round 58%, mec/field
60-100%, mec/round 50-100%). DAgger r1/r2 BCs for diff/field show
12%→38% progression on gym HERDING_WEBOTS proxy but did not close
to actual Webots LiDAR (0/5 throughout). Next: LSTM policy or
learned tracker per the project-state memory.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
692 lines
17 KiB
Protocol Buffer
692 lines
17 KiB
Protocol Buffer
#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
|
|
]
|
|
}
|
|
}
|
|
}
|