This repository contains a ROS2 package for following sheep using YOLO object detection. The system provides two different approaches: high-level navigation using Nav2 and low-level velocity control.
yolo_sheep_follower/
├── sheep_follower/ # Main ROS2 package
│ ├── package.xml
│ ├── setup.py
│ ├── setup.cfg
│ ├── resource/
│ ├── sheep_follower/ # Python source code
│ │ ├── __init__.py
│ │ ├── nav2_sheep_follower.py
│ │ ├── direct_sheep_follower.py
│ │ └── wolf_distance_detector.py
│ ├── launch/
│ │ ├── sheep_follower_simulation.launch.py
│ │ ├── nav2_sheep_follower.launch.py
│ │ └── direct_sheep_follower.launch.py
│ └── config/
│ ├── nav2_sheep_follower.yaml
│ ├── direct_sheep_follower.yaml
│ └── sheep_follower.rviz
├── deps/ # Git submodules
│ ├── yolo_ros/ # YOLO ROS2 (includes yolo_msgs)
│ └── gps_ignition_simulation/ # Gazebo worlds & robot models
├── logos/
├── .gitignore
├── .gitmodules
├── CITATION.cff
└── README.md
# Clone with submodules
cd ~/ros2_ws/src
git clone --recursive https://github.com/luispri2001/yolo_sheep_follower.git
# Install ROS dependencies
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
# Build
colcon build --symlink-install
# Source
source install/setup.bashNote: If you cloned without
--recursive, run:git submodule update --init --recursive
Launch the full sheep following simulation with one command:
ros2 launch sheep_follower sheep_follower_simulation.launch.pyThis launches:
- Gazebo Ignition with campus world and sheep
- LeoRover robot
- Nav2 navigation stack
- YOLO 3D detection
- Sheep follower node
ros2 launch sheep_follower sheep_follower_simulation.launch.py \
sheep_id:=any \
yolo_model:=yolov8m.pt \
yolo_device:=cuda:0 \
use_rviz:=true| Parameter | Default | Description |
|---|---|---|
sheep_id |
any |
Target sheep ID or "any" to follow first detected |
yolo_model |
yolov8m.pt |
YOLO model to use |
yolo_device |
cuda:0 |
Device for inference (cuda:0, cpu) |
use_rviz |
true |
Launch RViz with visualization |
use_sim_time |
true |
Use simulation time |
Note: The system accepts both "sheep" and "cow" detections since YOLO may confuse them in simulation.
- ROS2: Humble / Iron
- Python: 3.8+
- OS: Ubuntu 22.04
nav2_msgs,geometry_msgs,tf2_ros,tf2_geometry_msgsvision_msgs,std_msgs,visualization_msgs,sensor_msgscv_bridge,numpy,opencv-pythonyolo_msgs(included as submodule)
This system implements autonomous sheep following capabilities for robotic applications in agricultural and research environments. It uses YOLO-based 3D object detection to identify and track specific sheep by ID or any sheep in the field.
A high-level navigation approach that uses the Nav2 navigation stack to follow sheep. This implementation is ideal for complex environments requiring path planning and obstacle avoidance.
- High-level navigation: Uses Nav2's
NavigateToPoseaction for robust path planning - Transform handling: Properly handles coordinate transformations between frames
- Goal optimization: Avoids sending redundant navigation goals
- Graceful recovery: Continues to last goal when sheep detection is lost
- Configurable parameters: Adjustable timeouts, tolerances, and target frames
target_frame(default: "map"): Target coordinate frame for navigationlost_timeout(default: 2.0s): Time before considering sheep lostgoal_tolerance(default: 0.5m): Minimum distance between goals to send new commandgoal_offset(default: 1.0m): Distance to maintain from sheep position
# Run with launch file (recommended)
ros2 launch sheep_follower nav2_sheep_follower.launch.py sheep_id:=3
# Or run the node directly
ros2 run sheep_follower nav2_sheep_follower --id 3
# Follow any sheep (default - follows first detected and sticks with it)
ros2 run sheep_follower nav2_sheep_follower --id anyYOLO Detections → TF Transformations → Goal Calculation → Nav2 Action Client
A low-level approach that directly controls robot velocity using cmd_vel commands. This implementation provides more immediate response and fine-grained control.
- Direct velocity control: Publishes
Twistmessages to/cmd_vel - Distance-based behavior: Adjusts speed based on proximity to target
- Visual servoing: Uses both 3D position and 2D image coordinates for control
- Safety mechanisms: Automatic stopping when target is lost
- Real-time control: High-frequency control loop (10Hz)
max_linear_speed(default: 0.3 m/s): Maximum forward/backward speedmax_angular_speed(default: 0.6 rad/s): Maximum rotation speedmin_follow_distance(default: 2.5m): Minimum distance to maintainmax_follow_distance(default: 5.0m): Maximum following distancecenter_threshold(default: 30 pixels): Tolerance for centering targetlost_object_timeout(default: 2.0s): Time before stopping when target lost
# Run with launch file (recommended)
ros2 launch sheep_follower direct_sheep_follower.launch.py sheep_id:=3
# Or run the node directly
ros2 run sheep_follower direct_sheep_follower --id 3
# Follow any sheep (default - follows first detected and sticks with it)
ros2 run sheep_follower direct_sheep_follower --id any- Linear velocity: Based on distance to target (approach/retreat/maintain)
- Angular velocity: Combination of 3D lateral offset and 2D image centering
- Safety: Automatic stop when target lost or invalid data received
You can customize the behavior of the nodes with launch file parameters:
# For Nav2 follower
ros2 launch sheep_follower nav2_sheep_follower.launch.py \
sheep_id:=3 \
target_frame:=map \
lost_timeout:=3.0 \
goal_tolerance:=0.7 \
use_sim_time:=true
# For Direct velocity follower
ros2 launch sheep_follower direct_sheep_follower.launch.py \
sheep_id:=3 \
max_linear_speed:=0.4 \
min_follow_distance:=2.0 \
use_sim_time:=trueYAML configuration files in config/:
nav2_sheep_follower.yamldirect_sheep_follower.yaml
rclpy: ROS2 Python client librarygeometry_msgs: For Twist and PoseStamped messagesnav2_msgs: For NavigateToPose actionyolo_msgs: Custom YOLO detection messagestf2_ros: Transform librarytf2_geometry_msgs: Geometry message transformationsvision_msgs: Vision-related message definitions
/detections_3d(yolo_msgs/DetectionArray): 3D YOLO detection results/tracking(yolo_msgs/DetectionArray): YOLO tracking results with IDs
- Nav2 Sheep Follower:
/navigate_to_pose(nav2_msgs/NavigateToPose) - Direct Velocity Follower:
/cmd_vel(geometry_msgs/Twist)
This node detects wolves using YOLO detections and publishes both the estimated 3D distance to the wolf and a visualization. It also publishes an annotated image with the 2D bounding box and distance overlay.
- Wolf detection: Identifies wolves in YOLO detection messages
- Distance estimation: Calculates and publishes the 3D distance to the detected wolf
- RViz visualization: Publishes 3D bounding box and distance as markers
- Annotated image: Publishes a camera image with the wolf's 2D bounding box and distance overlay
| Topic | Type | Description |
|---|---|---|
/wolf/distance |
std_msgs/Float32 |
Distance to the detected wolf |
/wolf/visualization |
visualization_msgs/MarkerArray |
Markers for RViz |
/wolf/image_detection |
sensor_msgs/Image |
Annotated image with bounding box |
ros2 run sheep_follower wolf_distance_detectorTo visualize the wolf detection and distance in RViz:
- Run the
wolf_distance_detectornode. - In RViz, add a "Marker" display type and subscribe to the
/wolf/visualizationtopic. - Add a "Image" display type and subscribe to the
/wolf/image_detectiontopic for annotated images.
If you use this software, please cite the following paper:
@inproceedings{herds2025,
title = {HERDS: A ROS 2-based animal detection and herding system},
author = {Prieto-L{\'o}pez, Luis and Mayoko Biong, Jean Chrysostome and
S{\'a}nchez de la Fuente, Sergio and Gonz{\'a}lez-Santamarta, Miguel A. and
Rodr{\'i}guez-Lera, Francisco J. and S{\'a}nchez-Gonz{\'a}lez, Lidia},
booktitle = {Proceedings of the Eight Iberian Robotics Conference (ROBOT 2025)},
year = {2025},
month = {November},
publisher = {IEEE Press},
address = {Porto, Portugal}
}This project has been partially funded by the Recovery, Transformation, and Resilience Plan, financed by the European Union (Next Generation), thanks to the AURORAS project, and by grant PID2024-161761OB-C21 funded by MICIU/AEI/10.13039/501100011033 and by the ERDF/EU.

