Styling and sheep behaviour

This commit is contained in:
Johnny Fernandes
2026-04-22 21:01:42 +01:00
parent 79e4a3e698
commit f256e99a76
8 changed files with 2122 additions and 5 deletions
+2
View File
@@ -0,0 +1,2 @@
# Stuff
_example/
+213
View File
@@ -0,0 +1,213 @@
"""
Sheep flocking controller (Webots, Reynolds boids variant).
Each sheep broadcasts its GPS position every 3 steps on channel 1 and
listens for the dog and peer sheep positions. Peers are keyed by robot
name so each neighbour has exactly one current entry in the dict.
Force stack each step (summed then converted to a heading + speed):
flee — away from dog, quadratic ramp, dominant when close
cohesion — toward flock centre, halved while fleeing
separation — inverse-distance push, prevents physical overlap
walls — linear repulsion from field boundary
wander — small persistent drift for natural idle motion
Pen behaviour: on first entry into the quarantine pen the sheep latches
permanently — it turns pink (via the exposed woolColor PROTO field) and
the normal force stack is replaced by pen-confinement forces only.
"""
import random
import math
from controller import Supervisor
# ---------------------------------------------------------------------------
# Tuning constants
# ---------------------------------------------------------------------------
MAX_SPEED = 22.0 # rad/s hard clamp on both motors
FLEE_SPEED = 20.0 # rad/s upper bound while panicking
WANDER_SPEED = 3.0 # rad/s lower bound during calm wandering
X_MIN, X_MAX = -14.5, 14.5 # stone wall inner edges (metres)
Y_MIN, Y_MAX = -14.5, 14.5
WALL_MARGIN = 3.5 # avoidance starts this far from the wall
FLEE_DIST = 7.0 # dog within this radius triggers flee (metres)
SEPARATION_DIST = 2.5 # inverse-distance push active inside this radius
COHESION_DIST = 8.0 # pull toward flock centre active inside this radius
PEN_X_MIN, PEN_X_MAX = 10.0, 13.0 # quarantine pen extents (metres)
PEN_Y_MIN, PEN_Y_MAX = -15.0, -8.0 # open entrance at y=-8, gate at y=-15
PEN_MARGIN = 0.8 # confinement force starts this far from pen wall
# ---------------------------------------------------------------------------
# Device setup
# ---------------------------------------------------------------------------
robot = Supervisor()
timestep = int(robot.getBasicTimeStep())
name = robot.getName()
self_node = robot.getSelf()
left_motor = robot.getDevice("left wheel motor")
right_motor = robot.getDevice("right wheel motor")
left_motor.setPosition(float("inf"))
right_motor.setPosition(float("inf"))
left_motor.setVelocity(0.0)
right_motor.setVelocity(0.0)
gps = robot.getDevice("gps"); gps.enable(timestep)
compass = robot.getDevice("compass"); compass.enable(timestep)
receiver = robot.getDevice("receiver"); receiver.enable(timestep)
emitter = robot.getDevice("emitter")
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def norm_angle(a):
return math.atan2(math.sin(a), math.cos(a))
def bearing():
# Compass returns north direction in sensor frame; for this Z-up world
# with north = +Y, atan2(n[0], n[1]) gives the standard math angle
# (0 = east, π/2 = north) matching atan2(fy, fx) used for heading.
n = compass.getValues()
return math.atan2(n[0], n[1])
def drive(heading, speed):
err = norm_angle(heading - bearing())
# Scale forward component by cos(err): at 90° error fwd→0 so the robot
# spins in place to realign rather than driving sideways at full speed.
fwd = speed * max(0.0, math.cos(err))
k = 4.0
left_motor.setVelocity( max(-MAX_SPEED, min(MAX_SPEED, fwd - k * err)))
right_motor.setVelocity(max(-MAX_SPEED, min(MAX_SPEED, fwd + k * err)))
def paint_pink():
# woolColor is declared as a PROTO field with IS binding to the DEF WOOL
# PBRAppearance baseColor. Changing it here propagates to every USE WOOL
# shape on the body. Direct field access avoids PROTO-internal opacity.
self_node.getField("woolColor").setSFColor([1.0, 0.55, 0.72])
# ---------------------------------------------------------------------------
# State
# ---------------------------------------------------------------------------
wander_angle = random.uniform(-math.pi, math.pi)
step = 0
dog_x = None
dog_y = None
peers = {} # name → (x, y), one entry per neighbour, cleared every 30 steps
penned = False
# ---------------------------------------------------------------------------
# Main loop
# ---------------------------------------------------------------------------
while robot.step(timestep) != -1:
step += 1
pos = gps.getValues()
x, y = pos[0], pos[1]
# Pen entry: one-way latch, never unset
if not penned and PEN_X_MIN < x < PEN_X_MAX and PEN_Y_MIN < y < PEN_Y_MAX:
penned = True
paint_pink()
# Refresh peer table (clear before receiving so fresh data is never lost)
if step % 30 == 0:
peers.clear()
while receiver.getQueueLength() > 0:
msg = receiver.getString()
receiver.nextPacket()
p = msg.split(":")
if p[0] == "dog" and len(p) >= 3:
dog_x, dog_y = float(p[1]), float(p[2])
elif p[0] == "sheep" and len(p) >= 4 and p[1] != name:
peers[p[1]] = (float(p[2]), float(p[3]))
fx, fy = 0.0, 0.0
if penned:
# Inside pen: wander freely, strong boundary forces prevent exit,
# separation still active to avoid collisions with other penned sheep.
pm = PEN_MARGIN
if x < PEN_X_MIN + pm: fx += ((PEN_X_MIN + pm - x) / pm) * 15.0
if x > PEN_X_MAX - pm: fx -= ((x - (PEN_X_MAX - pm)) / pm) * 15.0
if y < PEN_Y_MIN + pm: fy += ((PEN_Y_MIN + pm - y) / pm) * 15.0
if y > PEN_Y_MAX - pm: fy -= ((y - (PEN_Y_MAX - pm)) / pm) * 15.0
for px, py in peers.values():
dx, dy = px - x, py - y
d = math.hypot(dx, dy)
if 0.05 < d < SEPARATION_DIST:
push = (SEPARATION_DIST - d) / d
fx -= (dx / d) * push * 2.5
fy -= (dy / d) * push * 2.5
if random.random() < 0.02:
wander_angle += random.uniform(-0.6, 0.6)
fx += math.cos(wander_angle) * 0.5
fy += math.sin(wander_angle) * 0.5
else:
fleeing = False
# Flee — quadratic ramp so force grows rapidly as the dog closes in
if dog_x is not None:
dx = dog_x - x
dy = dog_y - y
dist = math.hypot(dx, dy)
if 0.01 < dist < FLEE_DIST:
fleeing = True
t = 1.0 - dist / FLEE_DIST
s = t * t * 20.0
fx -= (dx / dist) * s
fy -= (dy / dist) * s
# Cohesion — halved while fleeing to reduce mid-panic collisions
cx, cy, cn = 0.0, 0.0, 0
for px, py in peers.values():
d = math.hypot(px - x, py - y)
if 0.3 < d < COHESION_DIST:
cx += px; cy += py; cn += 1
if cn > 0:
w = 0.08 if fleeing else 0.15
fx += (cx / cn - x) * w
fy += (cy / cn - y) * w
# Separation — inverse-distance: huge when nearly overlapping, fades quickly
for px, py in peers.values():
dx, dy = px - x, py - y
d = math.hypot(dx, dy)
if 0.05 < d < SEPARATION_DIST:
push = (SEPARATION_DIST - d) / d
fx -= (dx / d) * push * 2.5
fy -= (dy / d) * push * 2.5
# Walls
if x < X_MIN + WALL_MARGIN: fx += ((X_MIN + WALL_MARGIN - x) / WALL_MARGIN) * 6.0
if x > X_MAX - WALL_MARGIN: fx -= ((x - (X_MAX - WALL_MARGIN)) / WALL_MARGIN) * 6.0
if y < Y_MIN + WALL_MARGIN: fy += ((Y_MIN + WALL_MARGIN - y) / WALL_MARGIN) * 6.0
if y > Y_MAX - WALL_MARGIN: fy -= ((y - (Y_MAX - WALL_MARGIN)) / WALL_MARGIN) * 6.0
# Wander — suppressed while fleeing so drift cannot deflect the flee heading
if not fleeing:
if random.random() < 0.02:
wander_angle += random.uniform(-0.6, 0.6)
fx += math.cos(wander_angle) * 0.5
fy += math.sin(wander_angle) * 0.5
heading = math.atan2(fy, fx)
mag = math.hypot(fx, fy)
speed = max(WANDER_SPEED, min(FLEE_SPEED, mag * 3.0))
drive(heading, speed)
if step % 3 == 0:
emitter.send(f"sheep:{name}:{x:.4f}:{y:.4f}")
+88
View File
@@ -0,0 +1,88 @@
"""
Shepherd Dog controller (Webots, manual keyboard control).
WASD / arrow keys drive the robot. +/- adjust speed in 10 % increments.
GPS position is broadcast every step on channel 1 so sheep controllers
can compute flee forces. Ears wag continuously via sinusoidal position
targets — purely cosmetic.
"""
import math
from controller import Robot, Keyboard
robot = Robot()
timestep = int(robot.getBasicTimeStep())
left_motor = robot.getDevice("left wheel motor")
right_motor = robot.getDevice("right wheel motor")
left_motor.setPosition(float("inf"))
right_motor.setPosition(float("inf"))
left_motor.setVelocity(0.0)
right_motor.setVelocity(0.0)
lidar = robot.getDevice("lidar")
lidar.enable(timestep)
lidar.enablePointCloud()
gps = robot.getDevice("gps"); gps.enable(timestep)
compass = robot.getDevice("compass"); compass.enable(timestep)
emitter = robot.getDevice("emitter")
receiver = robot.getDevice("receiver"); receiver.enable(timestep)
left_ear = robot.getDevice("left ear motor")
right_ear = robot.getDevice("right ear motor")
left_ear.setPosition(float("inf"))
right_ear.setPosition(float("inf"))
left_ear.setVelocity(0.0)
right_ear.setVelocity(0.0)
keyboard = robot.getKeyboard()
keyboard.enable(timestep)
MOTOR_MAX = left_motor.getMaxVelocity()
speed_level = 0.5 # fraction of MOTOR_MAX; adjusted by +/-
EAR_AMPLITUDE = 0.35 # rad, peak ear deflection
EAR_RATE = 8.0 # rad/s, how fast the ears are driven
ear_phase = 0.0
while robot.step(timestep) != -1:
speed = MOTOR_MAX * speed_level
turn = speed * 0.6 # differential turn radius
left_vel = 0.0
right_vel = 0.0
key = keyboard.getKey()
while key > 0:
if key in (ord('W'), Keyboard.UP):
left_vel = speed
right_vel = speed
elif key in (ord('S'), Keyboard.DOWN):
left_vel = -speed
right_vel = -speed
elif key in (ord('A'), Keyboard.LEFT):
left_vel = -turn
right_vel = turn
elif key in (ord('D'), Keyboard.RIGHT):
left_vel = turn
right_vel = -turn
elif key in (ord('+'), ord('=')):
speed_level = min(1.0, speed_level + 0.1)
print(f"Speed: {speed_level:.0%} ({MOTOR_MAX * speed_level:.1f} rad/s)")
elif key in (ord('-'), ord('_')):
speed_level = max(0.1, speed_level - 0.1)
print(f"Speed: {speed_level:.0%} ({MOTOR_MAX * speed_level:.1f} rad/s)")
key = keyboard.getKey()
left_motor.setVelocity(left_vel)
right_motor.setVelocity(right_vel)
pos = gps.getValues()
emitter.send(f"dog:{pos[0]}:{pos[1]}")
ear_phase += 0.12
ear_pos = EAR_AMPLITUDE * math.sin(ear_phase)
left_ear.setVelocity(EAR_RATE)
right_ear.setVelocity(EAR_RATE)
left_ear.setPosition( ear_pos)
right_ear.setPosition(-ear_pos)
+56
View File
@@ -0,0 +1,56 @@
# Group G25 - Formal & Title & Goals
## Team members
- Diogo Costa <up202502576@up.pt>
- Johnny Fernandes <up202402612@up.pt>
- Nelson Neto <up202108117@up.pt>
## (i) Title and General objectives
**RL-Based Autonomous Shepherd Robot for Livestock Herding**
- Implement effective herding behaviors through proximity and movement strategies
- Build a 3D environment with realistic robot dynamics and LIDAR-based perception
- Develop a mobile robot capable of autonomously guiding a flock of sheep into a designated target area using Reinforcement Learning
# Group G25 - (ii) Intermediate Goals
## Intermediate goals
- Set up the Webots simulation environment with an open field and target zone
- Implement lightweight Gymnasium-based 2D herding environment
- Design a Sheep and Dog robot
- Implement a sheep flocking model for fast RL iteration
- Validate LiDAR sensor feedback for sheep detection and distance estimation
# Group G25 - Course Project (Final) Goals
## (iii) Main goals
- State-of-the-art survey on shepherding algorithms and multi-agent RL herding
- Train the robot using PPO to successfully herd a single sheep into the goal
- Achieve fully autonomous herding of multiple sheep and a full flock into the target area
- Optimize robot trajectory to minimize the time required to group the flock
- Ensure zero collisions between the robot and the sheep during the task
- Quantitative evaluation: success rate, time-to-pen, flock dispersion metrics
- Article, demo video, and final presentation
## (iv) Extra Merit
- Curriculum Learning (scaling from 1 sheep to a flock)
- Comparison of performance between Differential Drive and Mecanum wheels
- Robustness testing under sensor noise or varying sheep speeds, configurations and parameters
- Multi-shepherd cooperative mode: 2 dogs learn role specialization (collector vs. driver)
- Obstacles and terrain (walls, narrow gates, corridors) the flock must be funneled through
# Group G25 - Tools & Limitations
## (v) Tools
- Webots for 3D physics simulation with ROS2 integration via `webots_ros2` package
- Stable-Baselines3 for the PPO algorithm implementation
- Gymnasium (OpenAI) for the RL environment wrapper (lightweight 2D herding env for fast RL training)
- Python as the primary programming language (sheep flocking model, reward shaping, evaluation)
## (vi) Limitations
- Computational Power: Training time might be high for complex flock behaviors
- Sim-to-Real Gap: No real-world validation of the herding controller; project is simulation-only (2D + Webots 3D)
- Model Complexity: Simplified sheep behavior (scripted) may not account for all biological livestock nuances
+531
View File
@@ -0,0 +1,531 @@
#VRML_SIM R2025a utf8
# Sheep - wheeled base with sheep character on top
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/appearances/protos/TireRubber.proto"
PROTO Sheep [
field SFVec3f translation 0 0 0
field SFRotation rotation 0 1 0 0
field SFString name "sheep"
field SFString controller "sheep"
field MFString controllerArgs []
field SFString customData ""
field SFBool supervisor TRUE
field SFBool synchronization TRUE
field SFColor woolColor 0.92 0.90 0.85
]
{
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 SHEEP_CHASSIS Transform {
translation 0 0 0.04
children [
Shape {
appearance DEF SHEEP_CHASSIS_APP PBRAppearance {
baseColor 0.25 0.25 0.25
roughness 0.6
metalness 0.3
}
geometry Box {
size 0.24 0.14 0.05
}
}
]
}
# ========== FLUFFY WOOL BODY ==========
DEF SHEEP_BODY Transform {
translation 0 0 0.12
children [
Shape {
appearance DEF WOOL PBRAppearance {
baseColor IS woolColor
roughness 0.95
metalness 0.0
}
geometry Box {
size 0.26 0.16 0.12
}
}
# Fluffy wool bumps 6 spheres clustered on top of the body box
Transform {
translation -0.04 0 0.07
children [
Shape {
appearance USE WOOL
geometry Sphere {
radius 0.055
subdivision 3
}
}
]
}
Transform {
translation 0.04 0.035 0.07
children [
Shape {
appearance USE WOOL
geometry Sphere {
radius 0.05
subdivision 3
}
}
]
}
Transform {
translation 0.04 -0.035 0.07
children [
Shape {
appearance USE WOOL
geometry Sphere {
radius 0.05
subdivision 3
}
}
]
}
Transform {
translation -0.04 0.035 0.07
children [
Shape {
appearance USE WOOL
geometry Sphere {
radius 0.05
subdivision 3
}
}
]
}
Transform {
translation -0.04 -0.035 0.07
children [
Shape {
appearance USE WOOL
geometry Sphere {
radius 0.05
subdivision 3
}
}
]
}
Transform {
translation 0 0 0.07
children [
Shape {
appearance USE WOOL
geometry Sphere {
radius 0.06
subdivision 3
}
}
]
}
]
}
# ========== HEAD ==========
DEF SHEEP_HEAD Transform {
translation 0.16 0 0.12
children [
Shape {
appearance DEF SHEEP_DARK PBRAppearance {
baseColor 0.25 0.22 0.18
roughness 0.8
metalness 0.0
}
geometry Box {
size 0.08 0.10 0.08
}
}
# Left eye (white sphere + dark pupil)
Transform {
translation 0.04 0.03 0.02
children [
Shape {
appearance PBRAppearance {
baseColor 0.95 0.95 0.95
roughness 0.3
}
geometry Sphere {
radius 0.013
subdivision 2
}
}
Transform {
translation 0.008 0 0.003
children [
Shape {
appearance PBRAppearance {
baseColor 0.1 0.1 0.1
roughness 0.2
}
geometry Sphere {
radius 0.007
subdivision 2
}
}
]
}
]
}
# Right eye
Transform {
translation 0.04 -0.03 0.02
children [
Shape {
appearance PBRAppearance {
baseColor 0.95 0.95 0.95
roughness 0.3
}
geometry Sphere {
radius 0.013
subdivision 2
}
}
Transform {
translation 0.008 0 0.003
children [
Shape {
appearance PBRAppearance {
baseColor 0.1 0.1 0.1
roughness 0.2
}
geometry Sphere {
radius 0.007
subdivision 2
}
}
]
}
]
}
# Left ear
Transform {
translation 0 0.055 0.03
rotation 0 0 -1 0.3
children [
Shape {
appearance USE SHEEP_DARK
geometry Box {
size 0.05 0.018 0.03
}
}
]
}
# Right ear
Transform {
translation 0 -0.055 0.03
rotation 0 0 1 0.3
children [
Shape {
appearance USE SHEEP_DARK
geometry Box {
size 0.05 0.018 0.03
}
}
]
}
]
}
# ========== SHORT TAIL ==========
Transform {
translation -0.15 0 0.14
children [
Shape {
appearance USE WOOL
geometry Sphere {
radius 0.035
subdivision 2
}
}
]
}
# ========== RIGHT AXLE ARM ==========
DEF SHEEP_RIGHT_AXLE Transform {
translation 0 -0.085 0.031
children [
Shape {
appearance PBRAppearance {
baseColor 0.5 0.5 0.5
roughness 0.3
metalness 0.8
}
geometry Box {
size 0.02 0.05 0.02
}
}
]
}
# ========== LEFT AXLE ARM ==========
DEF SHEEP_LEFT_AXLE Transform {
translation 0 0.085 0.031
children [
Shape {
appearance PBRAppearance {
baseColor 0.5 0.5 0.5
roughness 0.3
metalness 0.8
}
geometry Box {
size 0.02 0.05 0.02
}
}
]
}
# ========== RIGHT WHEEL ==========
DEF SHEEP_RIGHT_WHEEL HingeJoint {
jointParameters HingeJointParameters {
axis 0 1 0
anchor 0 -0.10 0.031
}
device [
RotationalMotor {
name "right wheel motor"
maxVelocity 25.0
maxTorque 3.0
}
PositionSensor {
name "right wheel sensor"
resolution 0.00628
}
]
endPoint Solid {
translation 0 -0.10 0.031
rotation 0 -1 0 1.570796
children [
DEF SHEEP_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.014
radius 0.028
subdivision 24
}
}
Shape {
appearance TireRubber {
textureTransform TextureTransform {
scale 1.2 0.5
}
type "bike"
}
geometry Cylinder {
height 0.018
radius 0.031
subdivision 24
}
}
Shape {
appearance PBRAppearance {
baseColor 0.5 0.5 0.5
metalness 0.6
}
geometry Cylinder {
height 0.016
radius 0.012
subdivision 12
}
}
]
}
]
name "right wheel"
boundingObject Pose {
rotation 1 0 0 -1.5708
children [
Cylinder {
height 0.018
radius 0.031
}
]
}
physics Physics {
density -1
mass 0.04
centerOfMass [
0 0 0
]
}
}
}
# ========== LEFT WHEEL ==========
DEF SHEEP_LEFT_WHEEL HingeJoint {
jointParameters HingeJointParameters {
axis 0 1 0
anchor 0 0.10 0.031
}
device [
RotationalMotor {
name "left wheel motor"
maxVelocity 25.0
maxTorque 3.0
}
PositionSensor {
name "left wheel sensor"
resolution 0.00628
}
]
endPoint Solid {
translation 0 0.10 0.031
rotation 0.707105 0 0.707109 -3.14159
children [
USE SHEEP_WHEEL_VIS
]
name "left wheel"
boundingObject Pose {
rotation 1 0 0 -1.5708
children [
Cylinder {
height 0.018
radius 0.031
}
]
}
physics Physics {
density -1
mass 0.04
centerOfMass [
0 0 0
]
}
}
}
# ========== FRONT CASTER ==========
BallJoint {
jointParameters BallJointParameters {
anchor 0.10 0 0.016
}
endPoint Solid {
translation 0.10 0 0.016
name "front caster"
children [
Shape {
appearance PBRAppearance {
baseColor 0.2 0.2 0.2
roughness 0.3
}
geometry Sphere {
radius 0.016
subdivision 2
}
}
]
boundingObject Sphere {
radius 0.016
}
physics Physics {
density -1
mass 0.02
}
}
}
# ========== REAR CASTER ==========
BallJoint {
jointParameters BallJointParameters {
anchor -0.10 0 0.016
}
endPoint Solid {
translation -0.10 0 0.016
name "rear caster"
children [
Shape {
appearance PBRAppearance {
baseColor 0.2 0.2 0.2
roughness 0.3
}
geometry Sphere {
radius 0.016
subdivision 2
}
}
]
boundingObject Sphere {
radius 0.016
}
physics Physics {
density -1
mass 0.02
}
}
}
# ========== RECEIVER ==========
Receiver {
name "receiver"
channel 1
}
# ========== EMITTER ==========
Emitter {
name "emitter"
channel 1
range 30.0
}
# ========== GPS ==========
GPS {
translation 0 0 0.15
name "gps"
}
# ========== COMPASS ==========
Compass {
translation 0 0 0.10
name "compass"
}
]
boundingObject Group {
children [
# Chassis box
Transform {
translation 0 0 0.04
children [
Box {
size 0.24 0.14 0.05
}
]
}
# Body box
Transform {
translation 0 0 0.12
children [
Box {
size 0.26 0.16 0.12
}
]
}
]
}
physics Physics {
density -1
mass 5.0
centerOfMass [
0 0 0.02
]
}
}
}
+689
View File
@@ -0,0 +1,689 @@
#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 ShepherdDog [
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 front-facing 140° FOV, mounted at snout tip
Lidar {
translation 0.05 0 0.01
name "lidar"
horizontalResolution 180
fieldOfView 2.44
numberOfLayers 1
minRange 0.10
maxRange 12.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
]
}
}
}
+22
View File
@@ -0,0 +1,22 @@
"""
Viewpoint inspector — prints position, orientation and FOV to the console
once per second. Attach as the controller of a dummy supervisor robot to
copy-paste exact camera values into field.wbt.
"""
from controller import Supervisor
robot = Supervisor()
timestep = int(robot.getBasicTimeStep())
vp = robot.getFromDef("VIEWPOINT")
step = 0
while robot.step(timestep) != -1:
if step % 60 == 0:
pos = vp.getField("position").getSFVec3f()
ori = vp.getField("orientation").getSFRotation()
fov = vp.getField("fieldOfView").getSFFloat()
print(f"position: {pos[0]:.3f} {pos[1]:.3f} {pos[2]:.3f}")
print(f"orientation: {ori[0]:.3f} {ori[1]:.3f} {ori[2]:.3f} {ori[3]:.3f}")
print(f"fieldOfView: {fov:.3f}\n")
step += 1
+521 -5
View File
@@ -1,13 +1,529 @@
#VRML_SIM R2025a utf8
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/objects/backgrounds/protos/TexturedBackground.proto"
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/objects/backgrounds/protos/TexturedBackgroundLight.proto"
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/objects/floors/protos/UnevenTerrain.proto"
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/appearances/protos/Grass.proto"
EXTERNPROTO "../protos/ShepherdDog.proto"
EXTERNPROTO "../protos/Sheep.proto"
# World
WorldInfo {
info [
"RL-Based Autonomous Shepherd Robot"
"Group G25"
]
title "Shepherd Herding"
ERP 0.62
basicTimeStep 16
contactProperties [
ContactProperties {
coulombFriction [
12
]
softCFM 1e-05
}
Viewpoint {
orientation -0.5773 0.5773 0.5773 2.0944
position 0 0 10
]
}
TexturedBackground {
# Viewpoint
DEF VIEWPOINT Viewpoint {
position 4.34 -100.99 41.73
orientation 0.199 -0.190 -0.961 4.624
fieldOfView 0.785
}
TexturedBackgroundLight {
# Background
Background {
skyColor [0.55 0.75 0.95]
}
# Single sun (diagonal from SW)
DirectionalLight {
ambientIntensity 1
direction -0.3 0.5 -0.85
color 1 0.98 0.92
intensity 2.5
castShadows TRUE
}
# Grass terrain
UnevenTerrain {
rotation 0 0 1 -1.5708
size 100 100 0.3
xDimension 50
yDimension 50
appearance Grass {
colorOverride 0.78 0.88 0.68
textureTransform TextureTransform {
scale 100 100
}
}
perlinNOctaves 4
}
# ==================== APPEARANCES ====================
Transform {
children [
Shape { appearance DEF STONE_A PBRAppearance { baseColor 0.48 0.45 0.40 roughness 0.95 metalness 0 } }
Shape { appearance DEF STONE_B PBRAppearance { baseColor 0.36 0.33 0.29 roughness 0.95 metalness 0 } }
Shape { appearance DEF STONE_C PBRAppearance { baseColor 0.58 0.55 0.50 roughness 0.90 metalness 0 } }
Shape { appearance DEF CAP PBRAppearance { baseColor 0.54 0.51 0.46 roughness 0.80 metalness 0 } }
Shape { appearance DEF BARN_RED PBRAppearance { baseColor 0.62 0.18 0.12 roughness 0.80 metalness 0 } }
Shape { appearance DEF BARN_ROOF PBRAppearance { baseColor 0.28 0.20 0.13 roughness 0.72 metalness 0 } }
Shape { appearance DEF WOOD PBRAppearance { baseColor 0.48 0.32 0.16 roughness 0.90 metalness 0 } }
Shape { appearance DEF TRUNK PBRAppearance { baseColor 0.38 0.24 0.11 roughness 0.90 metalness 0 } }
Shape { appearance DEF LEAF_A PBRAppearance { baseColor 0.22 0.52 0.16 roughness 0.85 metalness 0 } }
Shape { appearance DEF LEAF_B PBRAppearance { baseColor 0.16 0.42 0.10 roughness 0.85 metalness 0 } }
Shape { appearance DEF LEAF_C PBRAppearance { baseColor 0.30 0.60 0.20 roughness 0.80 metalness 0 } }
Shape { appearance DEF STRAW PBRAppearance { baseColor 0.85 0.75 0.35 roughness 0.95 metalness 0 } }
Shape { appearance DEF HAT PBRAppearance { baseColor 0.50 0.35 0.18 roughness 0.85 metalness 0 } }
Shape { appearance DEF SHIRT PBRAppearance { baseColor 0.60 0.30 0.30 roughness 0.80 metalness 0 } }
Shape { appearance DEF PANTS PBRAppearance { baseColor 0.25 0.25 0.30 roughness 0.80 metalness 0 } }
Shape { appearance DEF DOOR_MAT PBRAppearance { baseColor 0.55 0.38 0.20 roughness 0.72 metalness 0 } }
Shape { appearance DEF GLASS PBRAppearance { baseColor 0.60 0.80 0.95 roughness 0.20 metalness 0.05 } }
Shape { appearance DEF HAY PBRAppearance { baseColor 0.82 0.72 0.32 roughness 0.95 metalness 0 } }
]
}
DEF TRIM PBRAppearance { baseColor 0.90 0.88 0.82 roughness 0.70 metalness 0 }
# ==================== STONE WALL ENCLOSURE (±15 m) ====================
# East wall + cap
Solid { translation 15 0 0.40 children [ Shape { appearance USE STONE_A geometry Box { size 0.16 30.5 0.80 } } ] boundingObject Box { size 0.16 30.5 0.80 } }
Solid { translation 15 0 0.84 children [ Shape { appearance USE CAP geometry Box { size 0.26 30.6 0.07 } } ] boundingObject Box { size 0.26 30.6 0.07 } }
# West wall + cap
Solid { translation -15 0 0.40 children [ Shape { appearance USE STONE_B geometry Box { size 0.16 30.5 0.80 } } ] boundingObject Box { size 0.16 30.5 0.80 } }
Solid { translation -15 0 0.84 children [ Shape { appearance USE CAP geometry Box { size 0.26 30.6 0.07 } } ] boundingObject Box { size 0.26 30.6 0.07 } }
# North wall + cap
Solid { translation 0 15 0.40 children [ Shape { appearance USE STONE_C geometry Box { size 30.0 0.16 0.80 } } ] boundingObject Box { size 30.0 0.16 0.80 } }
Solid { translation 0 15 0.84 children [ Shape { appearance USE CAP geometry Box { size 30.1 0.26 0.07 } } ] boundingObject Box { size 30.1 0.26 0.07 } }
# South wall + cap (split for gate, near SE corner)
Solid { translation -2.5 -15 0.40 children [ Shape { appearance USE STONE_A geometry Box { size 25.0 0.16 0.80 } } ] boundingObject Box { size 25.0 0.16 0.80 } }
Solid { translation -2.5 -15 0.84 children [ Shape { appearance USE CAP geometry Box { size 25.1 0.26 0.07 } } ] boundingObject Box { size 25.1 0.26 0.07 } }
Solid { translation 14 -15 0.40 children [ Shape { appearance USE STONE_A geometry Box { size 2.0 0.16 0.80 } } ] boundingObject Box { size 2.0 0.16 0.80 } }
Solid { translation 14 -15 0.84 children [ Shape { appearance USE CAP geometry Box { size 2.1 0.26 0.07 } } ] boundingObject Box { size 2.1 0.26 0.07 } }
# Gate posts
Solid { translation 10 -15 0.56 children [ Shape { appearance USE STONE_B geometry Box { size 0.44 0.44 1.12 } } Shape { appearance USE CAP geometry Box { size 0.54 0.54 0.08 } } ] boundingObject Box { size 0.44 0.44 1.12 } }
Solid { translation 13 -15 0.56 children [ Shape { appearance USE STONE_B geometry Box { size 0.44 0.44 1.12 } } Shape { appearance USE CAP geometry Box { size 0.54 0.54 0.08 } } ] boundingObject Box { size 0.44 0.44 1.12 } }
# Outer gate (wooden, slightly ajar, Z-brace)
Solid { translation 11.5 -15.08 0.55 rotation 0 0 1 0.25 children [
Shape { appearance USE WOOD geometry Box { size 2.80 0.05 1.00 } }
Transform { translation 0 0.02 0 rotation 0 1 0 0.34 children [ Shape { appearance DEF FPOST PBRAppearance { baseColor 0.35 0.22 0.10 roughness 0.90 } geometry Box { size 2.97 0.04 0.06 } } ] }
] boundingObject Box { size 2.80 0.08 1.00 } }
# ==================== QUARANTINE PEN (wooden post-and-rail fence, inside field) ====================
# Flow: main field → inner gate → quarantine area → outer gate → outside
# West wall (x=10, ~7m along Y)
Solid { translation 10 -11.46 0.55 children [
Transform { translation 0 -3.46 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 -1.73 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 0 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 1.73 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 3.46 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 0 -0.38 children [ Shape { appearance USE WOOD geometry Box { size 0.06 6.92 0.08 } } ] }
Transform { translation 0 0 -0.05 children [ Shape { appearance USE WOOD geometry Box { size 0.06 6.92 0.08 } } ] }
Transform { translation 0 0 0.30 children [ Shape { appearance USE WOOD geometry Box { size 0.06 6.92 0.08 } } ] }
Transform { translation 0 0 0.53 children [ Shape { appearance USE FPOST geometry Box { size 0.14 6.92 0.04 } } ] }
] boundingObject Box { size 0.14 6.92 1.10 } }
# East wall (x=13)
Solid { translation 13 -11.46 0.55 children [
Transform { translation 0 -3.46 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 -1.73 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 0 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 1.73 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 3.46 0 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] }
Transform { translation 0 0 -0.38 children [ Shape { appearance USE WOOD geometry Box { size 0.06 6.92 0.08 } } ] }
Transform { translation 0 0 -0.05 children [ Shape { appearance USE WOOD geometry Box { size 0.06 6.92 0.08 } } ] }
Transform { translation 0 0 0.30 children [ Shape { appearance USE WOOD geometry Box { size 0.06 6.92 0.08 } } ] }
Transform { translation 0 0 0.53 children [ Shape { appearance USE FPOST geometry Box { size 0.14 6.92 0.04 } } ] }
] boundingObject Box { size 0.14 6.92 1.10 } }
# North wall - open entrance (no wall, just corner posts)
Solid { translation 10 -8 0.55 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] boundingObject Box { size 0.12 0.12 1.10 } }
Solid { translation 13 -8 0.55 children [ Shape { appearance USE FPOST geometry Box { size 0.12 0.12 1.10 } } ] boundingObject Box { size 0.12 0.12 1.10 } }
# Corner pillars
Solid { translation 15 15 0.56 children [ Shape { appearance USE STONE_B geometry Box { size 0.44 0.44 1.12 } } Shape { appearance USE CAP geometry Box { size 0.54 0.54 0.08 } } ] boundingObject Box { size 0.44 0.44 1.12 } }
Solid { translation 15 -15 0.56 children [ Shape { appearance USE STONE_B geometry Box { size 0.44 0.44 1.12 } } Shape { appearance USE CAP geometry Box { size 0.54 0.54 0.08 } } ] boundingObject Box { size 0.44 0.44 1.12 } }
Solid { translation -15 15 0.56 children [ Shape { appearance USE STONE_B geometry Box { size 0.44 0.44 1.12 } } Shape { appearance USE CAP geometry Box { size 0.54 0.54 0.08 } } ] boundingObject Box { size 0.44 0.44 1.12 } }
Solid { translation -15 -15 0.56 children [ Shape { appearance USE STONE_B geometry Box { size 0.44 0.44 1.12 } } Shape { appearance USE CAP geometry Box { size 0.54 0.54 0.08 } } ] boundingObject Box { size 0.44 0.44 1.12 } }
# Mid-pillars every 5 m — East
Solid { translation 15 10 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation 15 5 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation 15 0 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation 15 -5 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation 15 -10 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
# West
Solid { translation -15 10 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation -15 5 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation -15 0 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation -15 -5 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation -15 -10 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
# North
Solid { translation 10 15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation 5 15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation 0 15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation -5 15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation -10 15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
# South
Solid { translation 5 -15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation 0 -15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation -5 -15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
Solid { translation -10 -15 0.53 children [ Shape { appearance USE STONE_B geometry Box { size 0.34 0.34 1.06 } } Shape { appearance USE CAP geometry Box { size 0.44 0.44 0.07 } } ] boundingObject Box { size 0.34 0.34 1.06 } }
# ==================== BARN 1 — Gambrel/Dutch style (NE, outside fence) ====================
# Body 10×7×4, weathered gray-brown wood, gambrel roof, large double doors
Solid {
translation 18.5 25.49 2
children [
Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 10 7 4 } }
# Gambrel roof
Transform { translation -3.5 0 3.05 rotation 0 1 0 -0.611 children [ Shape { appearance PBRAppearance { baseColor 0.20 0.18 0.16 roughness 0.82 metalness 0.02 } geometry Box { size 3.9 7.2 0.18 } } ] }
Transform { translation 3.5 0 3.05 rotation 0 1 0 0.611 children [ Shape { appearance PBRAppearance { baseColor 0.20 0.18 0.16 roughness 0.82 metalness 0.02 } geometry Box { size 3.9 7.2 0.18 } } ] }
Transform { translation -1.0 0 4.55 rotation 0 1 0 -0.422 children [ Shape { appearance PBRAppearance { baseColor 0.20 0.18 0.16 roughness 0.82 metalness 0.02 } geometry Box { size 2.5 7.2 0.18 } } ] }
Transform { translation 1.0 0 4.55 rotation 0 1 0 0.422 children [ Shape { appearance PBRAppearance { baseColor 0.20 0.18 0.16 roughness 0.82 metalness 0.02 } geometry Box { size 2.5 7.2 0.18 } } ] }
Transform { translation 0 0 5.04 children [ Shape { appearance PBRAppearance { baseColor 0.20 0.18 0.16 roughness 0.82 metalness 0.02 } geometry Box { size 1.6 7.2 0.22 } } ] }
# South gable fill
Transform { translation 0 -3.57 2.40 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 8.8 0.16 0.80 } } ] }
Transform { translation 0 -3.57 3.10 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 6.8 0.16 0.70 } } ] }
Transform { translation 0 -3.57 3.70 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 5.1 0.16 0.60 } } ] }
Transform { translation 0 -3.57 4.10 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 4.0 0.16 0.40 } } ] }
Transform { translation 0 -3.57 4.42 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 2.7 0.16 0.60 } } ] }
Transform { translation 0 -3.57 4.84 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 0.9 0.16 0.36 } } ] }
# North gable fill
Transform { translation 0 3.57 2.40 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 8.8 0.16 0.80 } } ] }
Transform { translation 0 3.57 3.10 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 6.8 0.16 0.70 } } ] }
Transform { translation 0 3.57 3.70 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 5.1 0.16 0.60 } } ] }
Transform { translation 0 3.57 4.10 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 4.0 0.16 0.40 } } ] }
Transform { translation 0 3.57 4.42 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 2.7 0.16 0.60 } } ] }
Transform { translation 0 3.57 4.84 children [ Shape { appearance PBRAppearance { baseColor 0.52 0.42 0.30 roughness 0.92 metalness 0 } geometry Box { size 0.9 0.16 0.36 } } ] }
# Double barn doors (south face)
Transform {
translation 0 -3.51 -0.50
children [
Shape { appearance PBRAppearance { baseColor 0.44 0.30 0.14 roughness 0.88 metalness 0 } geometry Box { size 2.8 0.10 3.0 } }
Transform { rotation 0 0 1 0.83 children [ Shape { appearance PBRAppearance { baseColor 0.34 0.22 0.10 roughness 0.90 metalness 0 } geometry Box { size 0.10 0.12 3.75 } } ] }
Transform { rotation 0 0 1 -0.83 children [ Shape { appearance PBRAppearance { baseColor 0.34 0.22 0.10 roughness 0.90 metalness 0 } geometry Box { size 0.10 0.12 3.75 } } ] }
Transform { translation -1.45 0 0 children [ Shape { appearance PBRAppearance { baseColor 0.34 0.22 0.10 roughness 0.90 metalness 0 } geometry Box { size 0.12 0.14 3.24 } } ] }
Transform { translation 1.45 0 0 children [ Shape { appearance PBRAppearance { baseColor 0.34 0.22 0.10 roughness 0.90 metalness 0 } geometry Box { size 0.12 0.14 3.24 } } ] }
Transform { translation 0 0 1.62 children [ Shape { appearance PBRAppearance { baseColor 0.34 0.22 0.10 roughness 0.90 metalness 0 } geometry Box { size 3.04 0.14 0.14 } } ] }
]
}
# Windows
Transform { translation -3.6 -3.52 0.55 children [ Shape { appearance PBRAppearance { baseColor 0.60 0.80 0.95 roughness 0.20 metalness 0.05 } geometry Box { size 1.40 0.12 1.10 } } ] }
Transform { translation 3.6 -3.52 0.55 children [ Shape { appearance PBRAppearance { baseColor 0.60 0.80 0.95 roughness 0.20 metalness 0.05 } geometry Box { size 1.40 0.12 1.10 } } ] }
Transform { translation 5.06 2.0 0.55 children [ Shape { appearance PBRAppearance { baseColor 0.60 0.80 0.95 roughness 0.20 metalness 0.05 } geometry Box { size 0.12 1.20 1.0 } } ] }
Transform { translation 5.06 -2.0 0.55 children [ Shape { appearance PBRAppearance { baseColor 0.60 0.80 0.95 roughness 0.20 metalness 0.05 } geometry Box { size 0.12 1.20 1.0 } } ] }
Transform { translation 0 -3.52 3.90 children [ Shape { appearance PBRAppearance { baseColor 0.44 0.30 0.14 roughness 0.88 metalness 0 } geometry Box { size 1.30 0.12 1.00 } } ] }
]
boundingObject Box { size 10 7 7 }
}
# ==================== BARN 3 — Red barn (NE, outside fence, gate facing fence) ====================
# Body 7×9×3.5, red walls, steep dark roof
Solid {
translation 29.76 9.52 1.75
rotation 0 0 1 -1.5708
children [
Shape { appearance USE BARN_RED geometry Box { size 7 9 3.5 } }
# Roof
Transform { translation -2.0 0 3.0 rotation 0 1 0 -0.70 children [ Shape { appearance USE BARN_ROOF geometry Box { size 4.2 9.2 0.20 } } ] }
Transform { translation 2.0 0 3.0 rotation 0 1 0 0.70 children [ Shape { appearance USE BARN_ROOF geometry Box { size 4.2 9.2 0.20 } } ] }
Transform { translation 0 0 4.28 children [ Shape { appearance USE BARN_ROOF geometry Box { size 2.0 9.2 0.24 } } ] }
# South gable fill
Transform { translation 0 -4.52 2.05 children [ Shape { appearance USE BARN_RED geometry Box { size 6.2 0.16 0.60 } } ] }
Transform { translation 0 -4.52 2.65 children [ Shape { appearance USE BARN_RED geometry Box { size 4.5 0.16 0.60 } } ] }
Transform { translation 0 -4.52 3.25 children [ Shape { appearance USE BARN_RED geometry Box { size 2.9 0.16 0.60 } } ] }
Transform { translation 0 -4.52 3.85 children [ Shape { appearance USE BARN_RED geometry Box { size 1.2 0.16 0.60 } } ] }
# North gable fill
Transform { translation 0 4.52 2.05 children [ Shape { appearance USE BARN_RED geometry Box { size 6.2 0.16 0.60 } } ] }
Transform { translation 0 4.52 2.65 children [ Shape { appearance USE BARN_RED geometry Box { size 4.5 0.16 0.60 } } ] }
Transform { translation 0 4.52 3.25 children [ Shape { appearance USE BARN_RED geometry Box { size 2.9 0.16 0.60 } } ] }
Transform { translation 0 4.52 3.85 children [ Shape { appearance USE BARN_RED geometry Box { size 1.2 0.16 0.60 } } ] }
# Door
Transform {
translation 0 -4.52 -0.62
children [
Shape { appearance USE DOOR_MAT geometry Box { size 1.70 0.14 2.26 } }
Transform { translation 0 0 1.22 children [ Shape { appearance USE WOOD geometry Box { size 2.10 0.18 0.26 } } ] }
Transform { translation -0.90 0 0 children [ Shape { appearance USE WOOD geometry Box { size 0.24 0.18 2.52 } } ] }
Transform { translation 0.90 0 0 children [ Shape { appearance USE WOOD geometry Box { size 0.24 0.18 2.52 } } ] }
Transform { translation 0 0 -0.68 children [ Shape { appearance USE WOOD geometry Box { size 1.60 0.12 0.12 } } ] }
Transform { translation 0 0 0.30 children [ Shape { appearance USE WOOD geometry Box { size 1.60 0.12 0.12 } } ] }
]
}
# Windows — south face
Transform { translation -2.2 -4.53 0.30 children [ Shape { appearance USE GLASS geometry Box { size 0.80 0.14 0.70 } } ] }
Transform { translation 2.2 -4.53 0.30 children [ Shape { appearance USE GLASS geometry Box { size 0.80 0.14 0.70 } } ] }
# East-face windows
Transform { translation 3.52 3.0 0.30 children [ Shape { appearance USE GLASS geometry Box { size 0.14 0.80 0.70 } } ] }
Transform { translation 3.52 0.0 0.30 children [ Shape { appearance USE GLASS geometry Box { size 0.14 0.80 0.70 } } ] }
Transform { translation 3.52 -3.0 0.30 children [ Shape { appearance USE GLASS geometry Box { size 0.14 0.80 0.70 } } ] }
]
boundingObject Box { size 7 9 6 }
}
# ==================== TREES (outside fence) ====================
# Tree A — large oak, SE
Solid {
translation 20 -18 0
children [
Transform { translation 0 0 2.0 children [ Shape { appearance USE TRUNK geometry Cylinder { height 4.0 radius 0.30 subdivision 10 } } ] }
Transform { translation 0.0 0.0 4.6 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 2.6 subdivision 4 } } ] }
Transform { translation 1.2 0.6 5.6 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 1.9 subdivision 4 } } ] }
Transform { translation -1.0 0.9 5.3 children [ Shape { appearance USE LEAF_C geometry Sphere { radius 1.7 subdivision 4 } } ] }
Transform { translation 0.4 -1.1 5.1 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 1.5 subdivision 4 } } ] }
Transform { translation -0.5 -0.4 6.2 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 1.0 subdivision 4 } } ] }
]
}
# Tree B — medium, NE near barn
Solid {
translation -8 26 0
children [
Transform { translation 0 0 1.7 children [ Shape { appearance USE TRUNK geometry Cylinder { height 3.4 radius 0.25 subdivision 10 } } ] }
Transform { translation 0.0 0.0 3.8 children [ Shape { appearance USE LEAF_C geometry Sphere { radius 2.2 subdivision 4 } } ] }
Transform { translation 0.9 -0.7 4.7 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 1.6 subdivision 4 } } ] }
Transform { translation -0.6 0.8 4.4 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 1.4 subdivision 4 } } ] }
]
}
# Tree C — large, NW
Solid {
translation -23 20 0
children [
Transform { translation 0 0 2.3 children [ Shape { appearance USE TRUNK geometry Cylinder { height 4.6 radius 0.36 subdivision 10 } } ] }
Transform { translation 0.0 0.0 5.2 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 2.9 subdivision 4 } } ] }
Transform { translation 1.3 0.9 6.3 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 2.1 subdivision 4 } } ] }
Transform { translation -1.1 1.1 6.0 children [ Shape { appearance USE LEAF_C geometry Sphere { radius 1.9 subdivision 4 } } ] }
Transform { translation 0.6 -1.3 5.8 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 1.6 subdivision 4 } } ] }
]
}
# Tree D — small, SW
Solid {
translation -20 -23 0
children [
Transform { translation 0 0 1.4 children [ Shape { appearance USE TRUNK geometry Cylinder { height 2.8 radius 0.20 subdivision 10 } } ] }
Transform { translation 0.0 0.0 3.2 children [ Shape { appearance USE LEAF_C geometry Sphere { radius 1.9 subdivision 4 } } ] }
Transform { translation -0.7 0.6 4.0 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 1.4 subdivision 4 } } ] }
Transform { translation 0.6 -0.5 3.8 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 1.2 subdivision 4 } } ] }
]
}
# Tree E — north cluster
Solid {
translation 7 23 0
children [
Transform { translation 0 0 1.9 children [ Shape { appearance USE TRUNK geometry Cylinder { height 3.8 radius 0.27 subdivision 10 } } ] }
Transform { translation 0.0 0.0 4.1 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 2.3 subdivision 4 } } ] }
Transform { translation 1.0 0.5 5.0 children [ Shape { appearance USE LEAF_C geometry Sphere { radius 1.7 subdivision 4 } } ] }
Transform { translation -0.6 -0.9 4.8 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 1.4 subdivision 4 } } ] }
]
}
# Tree F — SW
Solid {
translation -2.98 -22.8 0
children [
Transform { translation 0 0 1.3 children [ Shape { appearance USE TRUNK geometry Cylinder { height 2.6 radius 0.19 subdivision 10 } } ] }
Transform { translation 0.0 0.0 2.9 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 1.7 subdivision 4 } } ] }
Transform { translation 0.6 0.4 3.7 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 1.2 subdivision 4 } } ] }
]
}
# Tree G — west side
Solid {
translation -23 -5 0
children [
Transform { translation 0 0 2.0 children [ Shape { appearance USE TRUNK geometry Cylinder { height 4.0 radius 0.29 subdivision 10 } } ] }
Transform { translation 0.0 0.0 4.4 children [ Shape { appearance USE LEAF_C geometry Sphere { radius 2.4 subdivision 4 } } ] }
Transform { translation -1.0 0.8 5.3 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 1.8 subdivision 4 } } ] }
Transform { translation 0.9 -0.7 5.0 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 1.6 subdivision 4 } } ] }
]
}
# Tree H — east side
Solid {
translation 21.35 -1.05 0
children [
Transform { translation 0 0 1.5 children [ Shape { appearance USE TRUNK geometry Cylinder { height 3.0 radius 0.22 subdivision 10 } } ] }
Transform { translation 0.0 0.0 3.4 children [ Shape { appearance USE LEAF_A geometry Sphere { radius 2.0 subdivision 4 } } ] }
Transform { translation 0.7 0.6 4.2 children [ Shape { appearance USE LEAF_C geometry Sphere { radius 1.4 subdivision 4 } } ] }
Transform { translation -0.5 -0.8 4.0 children [ Shape { appearance USE LEAF_B geometry Sphere { radius 1.2 subdivision 4 } } ] }
]
}
# ==================== SCARECROW (east side, outside fence) ====================
Solid {
translation 20 -10 0
children [
Transform { translation 0 0 1.22 children [ Shape { appearance USE TRUNK geometry Cylinder { height 2.44 radius 0.045 subdivision 8 } } ] }
Transform { translation 0 0 2.02 rotation 1 0 0 1.5708 children [ Shape { appearance USE TRUNK geometry Cylinder { height 1.60 radius 0.032 subdivision 8 } } ] }
Transform {
translation 0 0 2.44
children [
Shape { appearance USE STRAW geometry Sphere { radius 0.17 subdivision 3 } }
Transform { translation 0.13 0.05 0.06 children [ Shape { appearance PBRAppearance { baseColor 0.06 0.06 0.06 } geometry Sphere { radius 0.028 subdivision 2 } } ] }
Transform { translation 0.13 -0.05 0.06 children [ Shape { appearance PBRAppearance { baseColor 0.06 0.06 0.06 } geometry Sphere { radius 0.028 subdivision 2 } } ] }
Transform { translation 0.16 0 -0.02 rotation 0 1 0 1.5708 children [ Shape { appearance PBRAppearance { baseColor 0.75 0.50 0.30 } geometry Cone { height 0.07 bottomRadius 0.032 subdivision 6 } } ] }
Transform { translation 0.14 0.04 -0.06 children [ Shape { appearance PBRAppearance { baseColor 0.18 0.08 0.08 } geometry Box { size 0.01 0.04 0.01 } } ] }
Transform { translation 0.14 -0.04 -0.06 children [ Shape { appearance PBRAppearance { baseColor 0.18 0.08 0.08 } geometry Box { size 0.01 0.04 0.01 } } ] }
]
}
Transform { translation 0 0 2.62 children [ Shape { appearance USE HAT geometry Cylinder { height 0.04 radius 0.28 subdivision 12 } } ] }
Transform { translation 0 0 2.80 children [ Shape { appearance USE HAT geometry Cylinder { height 0.30 radius 0.17 subdivision 10 } } ] }
Transform { translation 0 0 1.60 children [ Shape { appearance USE SHIRT geometry Box { size 0.20 0.40 0.46 } } ] }
Transform { translation 0 0 1.14 children [ Shape { appearance USE PANTS geometry Box { size 0.17 0.32 0.34 } } ] }
Transform { translation 0 0.68 2.03 rotation 0 0 1 0.25 children [ Shape { appearance USE STRAW geometry Box { size 0.03 0.24 0.03 } } ] }
Transform { translation 0 -0.68 2.03 rotation 0 0 -1 0.25 children [ Shape { appearance USE STRAW geometry Box { size 0.03 0.24 0.03 } } ] }
Transform { translation 0.10 0.08 1.82 children [ Shape { appearance USE STRAW geometry Box { size 0.03 0.03 0.14 } } ] }
Transform { translation 0.10 -0.08 1.82 children [ Shape { appearance USE STRAW geometry Box { size 0.03 0.03 0.14 } } ] }
]
}
# ==================== HAY BALES (near barn) ====================
Solid { translation 25.75 13.76 0.62 children [ Transform { rotation 1 0 0 1.5708 children [ Shape { appearance USE HAY geometry Cylinder { height 1.30 radius 0.62 subdivision 14 } } ] } ] boundingObject Box { size 1.30 1.24 1.24 } }
Solid { translation 24.34 12.32 0.62 children [ Transform { rotation 1 0 0 1.5708 children [ Shape { appearance USE HAY geometry Cylinder { height 1.30 radius 0.62 subdivision 14 } } ] } ] boundingObject Box { size 1.30 1.24 1.24 } }
Solid { translation 24.28 13.79 0.62 children [ Transform { rotation 1 0 0 1.5708 children [ Shape { appearance USE HAY geometry Cylinder { height 1.30 radius 0.62 subdivision 14 } } ] } ] boundingObject Box { size 1.30 1.24 1.24 } }
# ==================== TRACTOR (near barn) ====================
Solid {
translation 17 19 0
rotation 0 0 1 1.9
children [
# Chassis
Transform { translation 0 0 0.35 children [ Shape { appearance PBRAppearance { baseColor 0.20 0.20 0.20 roughness 0.6 metalness 0.3 } geometry Box { size 2.0 0.90 0.12 } } ] }
# Engine hood
Transform { translation 0.60 0 0.60 children [ Shape { appearance PBRAppearance { baseColor 0.15 0.50 0.12 roughness 0.7 metalness 0.1 } geometry Box { size 0.65 0.80 0.45 } } ] }
# Main body
Transform { translation -0.15 0 0.60 children [ Shape { appearance PBRAppearance { baseColor 0.15 0.50 0.12 roughness 0.7 metalness 0.1 } geometry Box { size 0.80 0.85 0.45 } } ] }
# Cabin
Transform { translation -0.20 0 0.95 children [ Shape { appearance PBRAppearance { baseColor 0.15 0.50 0.12 roughness 0.7 metalness 0.1 } geometry Box { size 0.75 0.80 0.45 } } ] }
# Cabin roof
Transform { translation -0.20 0 1.22 children [ Shape { appearance PBRAppearance { baseColor 0.12 0.40 0.10 roughness 0.75 metalness 0.1 } geometry Box { size 0.85 0.90 0.06 } } ] }
# Windshield
Transform { translation 0.12 0 0.95 children [ Shape { appearance USE GLASS geometry Box { size 0.02 0.55 0.35 } } ] }
# Rear window
Transform { translation -0.58 0 0.95 children [ Shape { appearance USE GLASS geometry Box { size 0.02 0.55 0.35 } } ] }
# Side windows
Transform { translation -0.20 0.40 0.95 children [ Shape { appearance USE GLASS geometry Box { size 0.55 0.02 0.30 } } ] }
Transform { translation -0.20 -0.40 0.95 children [ Shape { appearance USE GLASS geometry Box { size 0.55 0.02 0.30 } } ] }
# Seat
Transform { translation -0.25 0 0.55 children [ Shape { appearance PBRAppearance { baseColor 0.12 0.12 0.12 roughness 0.9 } geometry Box { size 0.30 0.35 0.06 } } ] }
# Exhaust stack
Transform { translation 0.50 0.30 0.60 children [
Shape { appearance PBRAppearance { baseColor 0.25 0.25 0.25 roughness 0.4 metalness 0.6 } geometry Cylinder { height 0.90 radius 0.03 subdivision 6 } }
Transform { translation 0 0 0.50 children [ Shape { appearance PBRAppearance { baseColor 0.20 0.20 0.20 roughness 0.4 metalness 0.6 } geometry Cylinder { height 0.04 radius 0.045 subdivision 6 } } ] }
] }
# Rear axle
Transform { translation -0.45 0 0.40 children [ Shape { appearance PBRAppearance { baseColor 0.25 0.25 0.25 roughness 0.5 metalness 0.5 } geometry Box { size 0.08 1.15 0.08 } } ] }
# Front axle
Transform { translation 0.60 0 0.25 children [ Shape { appearance PBRAppearance { baseColor 0.25 0.25 0.25 roughness 0.5 metalness 0.5 } geometry Box { size 0.08 0.90 0.08 } } ] }
# Rear left wheel
Transform { translation -0.45 0.60 0.40 rotation 1 0 0 1.5708 children [
Shape { appearance PBRAppearance { baseColor 0.08 0.08 0.08 roughness 0.95 } geometry Cylinder { height 0.22 radius 0.40 subdivision 20 } }
Shape { appearance PBRAppearance { baseColor 0.35 0.35 0.35 metalness 0.5 } geometry Cylinder { height 0.24 radius 0.14 subdivision 10 } }
] }
# Rear right wheel
Transform { translation -0.45 -0.60 0.40 rotation 1 0 0 1.5708 children [
Shape { appearance PBRAppearance { baseColor 0.08 0.08 0.08 roughness 0.95 } geometry Cylinder { height 0.22 radius 0.40 subdivision 20 } }
Shape { appearance PBRAppearance { baseColor 0.35 0.35 0.35 metalness 0.5 } geometry Cylinder { height 0.24 radius 0.14 subdivision 10 } }
] }
# Front left wheel
Transform { translation 0.60 0.45 0.25 rotation 1 0 0 1.5708 children [
Shape { appearance PBRAppearance { baseColor 0.08 0.08 0.08 roughness 0.95 } geometry Cylinder { height 0.16 radius 0.25 subdivision 16 } }
Shape { appearance PBRAppearance { baseColor 0.35 0.35 0.35 metalness 0.5 } geometry Cylinder { height 0.18 radius 0.09 subdivision 8 } }
] }
# Front right wheel
Transform { translation 0.60 -0.45 0.25 rotation 1 0 0 1.5708 children [
Shape { appearance PBRAppearance { baseColor 0.08 0.08 0.08 roughness 0.95 } geometry Cylinder { height 0.16 radius 0.25 subdivision 16 } }
Shape { appearance PBRAppearance { baseColor 0.35 0.35 0.35 metalness 0.5 } geometry Cylinder { height 0.18 radius 0.09 subdivision 8 } }
] }
# Rear fenders
Transform { translation -0.45 0.50 0.72 children [ Shape { appearance PBRAppearance { baseColor 0.12 0.40 0.10 roughness 0.75 metalness 0.1 } geometry Box { size 0.50 0.12 0.20 } } ] }
Transform { translation -0.45 -0.50 0.72 children [ Shape { appearance PBRAppearance { baseColor 0.12 0.40 0.10 roughness 0.75 metalness 0.1 } geometry Box { size 0.50 0.12 0.20 } } ] }
# Front bumper
Transform { translation 0.95 0 0.35 children [ Shape { appearance PBRAppearance { baseColor 0.35 0.35 0.35 roughness 0.7 metalness 0.3 } geometry Box { size 0.12 0.75 0.30 } } ] }
# Headlights
Transform { translation 0.97 0.25 0.45 children [ Shape { appearance PBRAppearance { baseColor 0.95 0.92 0.70 roughness 0.3 } geometry Sphere { radius 0.05 subdivision 3 } } ] }
Transform { translation 0.97 -0.25 0.45 children [ Shape { appearance PBRAppearance { baseColor 0.95 0.92 0.70 roughness 0.3 } geometry Sphere { radius 0.05 subdivision 3 } } ] }
# Taillights
Transform { translation -0.58 0.25 0.45 children [ Shape { appearance PBRAppearance { baseColor 0.80 0.10 0.10 roughness 0.4 } geometry Box { size 0.04 0.08 0.06 } } ] }
Transform { translation -0.58 -0.25 0.45 children [ Shape { appearance PBRAppearance { baseColor 0.80 0.10 0.10 roughness 0.4 } geometry Box { size 0.04 0.08 0.06 } } ] }
# Drawbar hitch
Transform { translation -0.95 0 0.20 children [ Shape { appearance PBRAppearance { baseColor 0.25 0.25 0.25 roughness 0.5 metalness 0.5 } geometry Box { size 0.12 0.06 0.06 } } ] }
]
boundingObject Box { size 2.2 1.4 1.3 }
}
# ==================== GRASS PATCHES (inside field, decorative) ====================
Solid { translation -8 6 0.15 children [
Transform { translation 0.10 0.00 0 children [ Shape { appearance USE LEAF_B geometry Box { size 0.04 0.02 0.30 } } ] }
Transform { translation -0.05 0.12 0 rotation 0 0 1 0.4 children [ Shape { appearance USE LEAF_A geometry Box { size 0.04 0.02 0.26 } } ] }
Transform { translation 0.08 -0.10 0 rotation 0 0 1 -0.3 children [ Shape { appearance USE LEAF_C geometry Box { size 0.04 0.02 0.28 } } ] }
Transform { translation -0.12 0.04 0 rotation 0 0 1 0.2 children [ Shape { appearance USE LEAF_B geometry Box { size 0.04 0.02 0.24 } } ] }
] }
Solid { translation 6 -9 0.15 children [
Transform { translation 0.08 0.06 0 children [ Shape { appearance USE LEAF_A geometry Box { size 0.04 0.02 0.28 } } ] }
Transform { translation -0.10 0.00 0 rotation 0 0 1 -0.3 children [ Shape { appearance USE LEAF_C geometry Box { size 0.04 0.02 0.32 } } ] }
Transform { translation 0.02 -0.12 0 rotation 0 0 1 0.35 children [ Shape { appearance USE LEAF_B geometry Box { size 0.04 0.02 0.26 } } ] }
Transform { translation -0.06 0.10 0 children [ Shape { appearance USE LEAF_A geometry Box { size 0.04 0.02 0.22 } } ] }
] }
Solid { translation -3 11 0.15 children [
Transform { translation 0.06 -0.06 0 children [ Shape { appearance USE LEAF_C geometry Box { size 0.04 0.02 0.26 } } ] }
Transform { translation -0.08 0.08 0 rotation 0 0 1 0.3 children [ Shape { appearance USE LEAF_A geometry Box { size 0.04 0.02 0.30 } } ] }
Transform { translation 0.12 0.02 0 rotation 0 0 1 -0.25 children [ Shape { appearance USE LEAF_B geometry Box { size 0.04 0.02 0.28 } } ] }
] }
Solid { translation 10 8 0.15 children [
Transform { translation -0.07 0.05 0 children [ Shape { appearance USE LEAF_B geometry Box { size 0.04 0.02 0.24 } } ] }
Transform { translation 0.09 -0.07 0 rotation 0 0 1 0.4 children [ Shape { appearance USE LEAF_C geometry Box { size 0.04 0.02 0.28 } } ] }
Transform { translation 0.00 0.11 0 rotation 0 0 1 -0.2 children [ Shape { appearance USE LEAF_A geometry Box { size 0.04 0.02 0.26 } } ] }
] }
Solid { translation -11 -7 0.15 children [
Transform { translation 0.05 0.08 0 children [ Shape { appearance USE LEAF_A geometry Box { size 0.04 0.02 0.30 } } ] }
Transform { translation -0.09 -0.04 0 rotation 0 0 1 0.35 children [ Shape { appearance USE LEAF_B geometry Box { size 0.04 0.02 0.28 } } ] }
Transform { translation 0.10 -0.09 0 rotation 0 0 1 -0.3 children [ Shape { appearance USE LEAF_C geometry Box { size 0.04 0.02 0.24 } } ] }
Transform { translation -0.03 0.12 0 children [ Shape { appearance USE LEAF_A geometry Box { size 0.04 0.02 0.26 } } ] }
] }
# ==================== SHEPHERD DOG ====================
ShepherdDog {
translation 0 0 0.5
rotation 0 0 1 0
controller "shepherd_dog"
}
# ==================== SHEEP ====================
Sheep {
translation 3 2 0.5
name "sheep1"
controller "sheep"
}
Sheep {
translation 3 -2 0.5
name "sheep2"
controller "sheep"
}
Sheep {
translation 4 0 0.5
name "sheep3"
controller "sheep"
}
Sheep {
translation 3.5 1 0.5
name "sheep4"
controller "sheep"
}
Sheep {
translation 3.5 -1 0.5
name "sheep5"
controller "sheep"
}