Resource | Link |
---|---|
Unstop Registration | Robotrix-2025 on Unstop |
OpenCV Learning Resources | OpenCV Session Materials |
Getting Started with CoppeliaSim | CoppeliaSim Guide |
Robotrix 2025 Problem Statement | Problem Statement Document |
CoppeliaSim Technical Session | Session Video |
How to Setup Stereo Vision and Depth Estimation | Video Link |
Objective:
The provided CoppeliaSim simulation scene contains an arena featuring a robot, a basketball hoop, and a basketball shooter. The robot can move the hoop along any of the three axes. The task is to successfully dunk the basketball into the hoop by adjusting its position to align with the trajectory of the basketball, which is shot automatically by the basketball shooter. Two cameras are mounted on the backboard to assist in this task
- Download Resources:
- No Modifications to Arena: Do not edit the provided world file
- Python Script: Edit the script template to achieve the stated objective
- Coding Standards: Ensure your code is neat, structured, and well-documented
- Arena Dimensions: 10000 mm x 10000 mm
- Hoop Diameter: 320 mm
- Backboard Dimensions: 960 mm x 720 mm
- Height of Ball Shooter: 400 mm
- Vision Sensors:
- Resolution: 512 x 512 px
- Field of View: 80°
- Distance Between Cameras: 700 mm
- Vertical Distance Between Cameras and Hoop: 390 mm
- Position Data: Use the dummy element
hoop_odom
to find the hoop’s position (thegetObjectPosition()
function is restricted to this purpose only) - Control Mechanism: All sliding joints can be controlled using velocity data.
Each run will have 10 shots. The simulation stops automatically after 10 shots. Teams score 10 points for every successful dunk, with a maximum score of 100 points
Since the getObjectPosition()
function is not available for the /ball
, its 3D position must be estimated using stereo cameras. The ball's unique orange color with RGB values
To detect the ball in the camera images:
- HSV Conversion: Convert the captured RGB images from the cameras to HSV using the
cv2.cvtColor()
function. - Color Mask: A mask is created by defining a range of HSV values around the ball's color. This ensures flexibility under different lighting conditions. For instance:
The range is tuned experimentally to detect only the ball. 4. Preprocessing Steps:
- Gaussian Blur: Smooth the image to reduce noise and improve contour detection.
blurred = cv2.GaussianBlur(mask, (5, 5), 0)
- Morphological Closing: Apply
cv2.morphologyEx()
with thecv2.MORPH_CLOSE
operation to close small gaps in the mask and create a solid region for the ball.
After preprocessing:
- Extract contours using
cv2.findContours()
. Contours represent the boundaries of detected objects in the binary mask. - Select the largest contour by area, assuming it corresponds to the ball. This is done using:
max_contour = max(contours, key=cv2.contourArea)
- Approximate the ball as a circle using
cv2.minEnclosingCircle()
, which provides the ball's center (in pixel coordinates) and its radius.
To estimate the ball's 3D position, stereo cameras are used. Stereo vision leverages the disparity between the same object's positions in the left and right camera images to calculate depth.
The disparity (
Where:
-
$$x_l$$ and$$x_r$$ are the horizontal pixel coordinates of the ball's center in the left and right camera images.
The depth (
Where:
-
$$f$$ = Focal length of the cameras (in pixels). -
$$B$$ = Baseline distance between the two cameras (700 mm). -
$$d$$ = Disparity (in pixels).
Using the depth (
Where:
-
$$x, y$$ = Ball's center in the image (pixels). -
$$c_x, c_y$$ = Camera's optical center (principal point). -
$$f$$ = Focal length.
To move the hoop accurately, the ball's trajectory must be predicted based on its current motion. This involves:
The ball's motion is governed by the physics of projectile motion:
Where:
-
$$v_x, v_y, v_z$$ = Initial velocities in the$$x, y, z$$ directions. -
$$x_0, y_0, z_0$$ = Initial position of the ball. -
$$g$$ = Gravitational acceleration ($$9.81 \ \text{m/s}^2$$ ). -
$$t$$ = Time.
The ball's velocity components are estimated from its positions in consecutive frames:
Where
Using the projectile motion equations, the ball's position at a future time
The hoop is controlled using PID controllers for each axis (X, Y, Z). These controllers minimize the error between the desired (predicted) position and the hoop's current position.
Where:
-
$$e(t)$$ = Error at time$$t$$ (difference between target and current position). -
$$K_p, K_i, K_d$$ = Proportional, Integral, and Derivative gains.
The error for each axis is calculated as:
The actuators (actuator_x
, actuator_y
, actuator_z
) are controlled using the PID outputs to minimize these errors.
The PID parameters (
- Responsiveness: Ensuring the hoop quickly moves to the predicted position.
- Stability: Avoiding oscillations or overshooting.
If the ball moves out of the cameras' FOV:
- Reactive Hoop Movement: Move the hoop toward the last known position of the ball to bring it back into view.
- Predefined Waypoints: Use a set of predefined positions to reset the hoop's position near the center, ensuring the ball remains in the cameras' FOV.
getVisionSensorImage()
: Captures images from the stereo cameras.cv2.GaussianBlur()
: Applies Gaussian blur for noise reduction.cv2.inRange()
: Creates a binary mask based on HSV color thresholds.cv2.morphologyEx()
: Performs morphological transformations like closing.cv2.findContours()
: Detects contours in binary images.cv2.minEnclosingCircle()
: Fits a circle around the largest contour.cv2.calcOpticalFlowPyrLK()
(Optional): Estimates ball motion between frames.
- PID Optimization: Test and adjust PID parameters to balance responsiveness and stability
- Edge Cases: Handle scenarios where the ball is partially occluded or moves out of the cameras' FOV