Asked
Resolved Resolved by Athena AI!

Lidar-Based Obstacle Avoidance Script

I'm developing a LiDAR-based obstacle avoidance script for my Roomba robot using Synthiam ARC. My setup utilizes the following ARC robot skills:

  • iRobot Roomba Movement Panel for controlling the chassis movement.
  • RPLidar for scanning the environment.

The RPLidar skill updates these global variables:

  • $LidarFurthestDegree
  • $LidarFurthestDistance
  • $LidarNearestDegree
  • $LidarNearestDistance

I aim to achieve the following behaviors:

Front Obstacle Detection:

  • If an obstacle is detected directly ahead at a distance of less than 20 cm, the robot should reverse approximately 10 cm, perform an exploratory scan to find clear paths, and then navigate toward the safest direction.

Side Obstacle Detection:

  • If obstacles are detected on either side at a distance of less than 15 cm, the robot should stop, reverse slightly, adjust its heading with a minor turn, and then continue forward.

I would like to implement this functionality using a JavaScript script within ARC. Here are my questions:

  1. How should I structure the script to continuously monitor the global LiDAR variables and determine which avoidance routine to execute?
  2. What are the best practices for utilizing the Roomba Movement Panel functions (such as Movement.forward(), Movement.reverse(), etc.) in this scenario?
  3. Could you provide an example code snippet illustrating a basic loop where the script checks the LiDAR distance values, identifies whether a front or side obstacle is present, and then issues the corresponding movement commands?

Any sample code, guidance, or debugging tips would be greatly appreciated!

Thank you in advance for your assistance!


Related Hardware AdventureBot

ARC Pro

Upgrade to ARC Pro

Don't limit your robot's potential – subscribe to ARC Pro and transform it into a dynamic, intelligent machine.

PRO
Canada
#1  

Below is one way to approach your obstacle avoidance logic. In our ARC JavaScript, you can set up a continuous while (true) loop that reads the global LiDAR variables, determines if an obstacle is in a critical zone, and then commands the Roomba Movement Panel accordingly. Here are some points to consider:

  1. Structure the Script

Create an infinite loop (or use setInterval in your script if you prefer nonblocking code) that checks the live global variables.
Convert the global variable values to numbers (using getVar() with defaults if needed) so you can compare distances.
Define zones for your front versus side fields. For example, you might say that an obstacle detected with a degree from -30 to +30 (or equivalently 330-360 and 0-30) is front. Similarly, you can define side zones as any readings between, say, 60-120 for the right and 240-300 for the left.
Inside the loop, use if/else conditions to choose which routine to run.

  1. Best Practices for Using Movement Panel Functions

Use the provided Movement functions (such as Movement.forward(), Movement.reverse(), Movement.left(), and Movement.right()) to issue your commands.
Provide an optional speed (0-255) and optionally a timeout (in milliseconds) to let the command run for a set period.
When commanding movements that are short (like reversing 10 cm), ensure you include sleep() delays so that the command has time to finish before checking sensors again.
Avoid blocking the ARC interface for too long in your loop. Small sleep delays (e.g., sleep(200)) can prevent your script from starving other processes.

  1. Sample Code Snippet

Below is an example code snippet illustrating one possible approach. In this sample, we assume:
The front danger zone is defined as obstacles detected between 330-30 with a distance less than 20 cm.
A side obstacle might be similarly detected on either side if the distance is under 15 cm.
After a front obstacle is detected the robot will stop, reverse briefly, then turn away from the obstacle before continuing forward.
You can adjust speed, timeouts, and thresholds as needed.

// Sample LiDAR-based Obstacle Avoidance Script for ARC
// This script continuously monitors the global LiDAR values and uses the Roomba  Movement Panel functions

// Define thresholds (in centimeters) and degree limits for front and side zones.
var FRONT_DISTANCE_THRESHOLD = 20;
var SIDE_DISTANCE_THRESHOLD = 15;
var FRONT_ZONE_RIGHT_MIN = 0;
var FRONT_ZONE_RIGHT_MAX = 30;
var FRONT_ZONE_LEFT_MIN = 330;
var FRONT_ZONE_LEFT_MAX = 360;

// You may add side zone definitions if needed. For this example, side obstacles will be a simple check.
var SAFE_SPEED = 150; // Adjust the command speed (0-255)

// Main loop
while (true) {
  // Retrieve LiDAR values (using default values if not set)
  var nearestDistance = parseFloat(getVar("$LidarNearestDistance", "100"));
  var nearestDegree   = parseFloat(getVar("$LidarNearestDegree", "0"));
  var furthestDistance = parseFloat(getVar("$LidarFurthestDistance", "100"));
  var furthestDegree   = parseFloat(getVar("$LidarFurthestDegree", "0"));

  // For debugging: print the sensor readings
  print("Nearest: " + nearestDistance + "cm at " + nearestDegree + " | Furthest: " + furthestDistance + "cm at " + furthestDegree + "");
  
  // Check for a front obstacle based on the degree reading 
  // (i.e., if the nearest obstacle is in front and too close)
  if (
      ((nearestDegree >= FRONT_ZONE_RIGHT_MIN && nearestDegree <= FRONT_ZONE_RIGHT_MAX) || 
       (nearestDegree >= FRONT_ZONE_LEFT_MIN && nearestDegree <= FRONT_ZONE_LEFT_MAX)) &&
       (nearestDistance < FRONT_DISTANCE_THRESHOLD)
     )
  {
    print("Front obstacle detected! Distance: " + nearestDistance + " cm.");
    
    // Stop any forward movement
    Movement.stop();
    sleep(200);
    
    // Reverse to clear some distance (adjust the timeout so it reverses ~10 cm)
    print("Reversing...");
    Movement.reverse(SAFE_SPEED, 800);
    sleep(800);
    
    // Perform an exploratory turn:
    // For a simple strategy, we'll check which side is clearer.
    // Here we use the furthest reading as an indication of a clear path.
    if (furthestDegree > 180) {  
      // Assume greater degrees are toward the right
      print("Turning left to avoid obstacle.");
      // Slight left turn
      Movement.left(SAFE_SPEED, 500);
    } else {
      print("Turning right to avoid obstacle.");
      // Slight right turn
      Movement.right(SAFE_SPEED, 500);
    }
    sleep(500);
    
    // Continue forward 
    Movement.forward(SAFE_SPEED);
  }
  // Else check for side obstacles.
  // (Assume side obstacles are identified with degrees away from front zone and distance less than the side threshold)
  else if (
         ((nearestDegree > 30 && nearestDegree < 90) || (nearestDegree > 270 && nearestDegree < 330)) &&
         (nearestDistance < SIDE_DISTANCE_THRESHOLD)
         )
  {
    print("Side obstacle detected! Distance: " + nearestDistance + " cm.");
    
    // Stop movement then reverse slightly
    Movement.stop();
    sleep(200);
    print("Reversing slightly...");
    Movement.reverse(SAFE_SPEED, 500);
    sleep(500);
    
    // Adjust heading with a minor turn (choose the turn direction based on sensor reading)
    if (nearestDegree > 30 && nearestDegree < 90) {
      // Obstacle on the front-right, so turn left slightly
      print("Turning left slightly.");
      Movement.left(SAFE_SPEED, 300);
    } else {
      // Obstacle on the front-left, so turn right slightly
      print("Turning right slightly.");
      Movement.right(SAFE_SPEED, 300);
    }
    sleep(300);
    
    // Continue forward after adjustment
    Movement.forward(SAFE_SPEED);
  }
  else {
    // If no immediate obstacles, continue moving forward.
    Movement.forward(SAFE_SPEED);
  }
  
  // Wait a short interval before the next check
  sleep(200);
}

Debugging & Additional Tips

Use print() statements (as in the snippet) to see which branch of your decision tree is executing.
Adjust the sleep delays and movement timeouts so that the robot has sufficient time to complete each command.
Fine-tune your degree ranges (and even use more granular checks if needed) so that the front and side regions match your robot’s physical layout.
If needed, incorporate more sophisticated scanning methods (for example, calculating averages over multiple measurements) to help with choosing the safest direction.

Feel free to adjust thresholds, timeouts, and movement percentages to suit your specific robot’s performance and the characteristics of your environment. Let me know if you need further tweaks or additional explanation on any of these points!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
PRO
Germany
#2  

thanks for your help. Have to test the script ASAP.