Asked

Handling Global Variable To Continue Loop

Hello,

I need some help with JavaScript in ARC robotics programming. I have a script that runs perfectly but requires an adjustment to handle exceptions without stopping entirely.

Here’s a summary of how the script currently operates:

  • The script loops every 15 minutes (900,000 milliseconds).
  • It uses ControlCommand to start three separate scripts, one at a time. This parent script pauses after starting each one until they complete, then loops again after waiting 15 minutes.
  • A Global Variable is set to indicate that it's running, preventing other scripts from starting simultaneously.
  • It checks for a Global Variable that might be set by another script in ARC. If this variable is detected, the parent script will not run.

The issue arises when the script (or others) detects that Global Variable and does not start, causing the loop to break and the script to stop.

I would like the script to check for the Global Variable and, if detected, skip its action but keep the loop running. This way, the script will continue to loop and attempt to run again later.

Here’s my current script. How can I structure it to maintain the loop even if the script needs to skip a cycle because another script is running? Thank you!

while (true) {

  // Personality action wrapper - JavaScript
  // Skip if another personality action is running
  if (getVar("$Personality", "0") == "1") {
    print("Personality: busy - skipping");
    // Do not return; instead, loop to continue checking.
    // sleep(900000); // Uncomment this to maintain the loop.
    continue;
  }

  // Mark running
  setVar("$Personality", "1");

  // ---- Put your personality actions below ----

  ControlCommand("Head Section", "ScriptStart", "Bubble Full Down");

  // Temp
  //---------------
  setVar("$OutsideTemp", 1); // Sets Variable so Script will run
  ControlCommand("Time, Date & Temp", "ScriptStart", "Outside Temp");
  while (getVar("$OutsideTemp") == 1) { // Pause script for Temp report
    sleep(100);
  }

  // Humidity
  //----------------
  setVar("$Humid", 1); // Sets Variable so Script will run
  ControlCommand("Time, Date & Temp", "ScriptStart", "Humidity");
  while (getVar("$Humid") == 1) { // Pause script for Humidity report
    sleep(100);
  }

  // Wind Speed
  //-----------------
  setVar("$WSpeed", 1); // Sets Variable so Script will run
  ControlCommand("Time, Date & Temp", "ScriptStart", "Wind Speed");
  while (getVar("$WSpeed") == 1) { // Pause script for Wind Speed report
    sleep(100);
  }

  ControlCommand("Head Section", "ScriptStart", "Bubble Middle");

  // ---- End of actions ----

  // Clear lock
  setVar("$Personality", "0");

  sleep(900000); // Pause script for 15 minutes
}

Related Hardware EZ-B v4
Related Controls Script On Variable Changed

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.

#1   — Edited

LOL! Looks like the AI @Athena fixed the script as I posted it. There is a new line in there that I did not write. I'll see if this works. .

// Uncomment this to maintain the loop.
    continue;

FYI, Here's what I had:

// Personality action wrapper - JavaScript
// Skip if another personality action is running
if (getVar("$Personality", "0") == "1") {
  print("Personality: busy - skipping");
  return;
Author Avatar
PRO
Synthiam
#2  

You could also just use ScriptStartWait ControlCommand instead of looping to wait for another script to finish. ScriptStartWait will wait for the other script to finish before continuing.

#3  

OK, I haven't tried this new script yet but I see a potential problem.

It look like what the change does is pause another 15 minutes and then runs no matter what. However I need the script to again check if another script is running the next time it's set to start. It can keep doing this until it sees no other script is running.

Author Avatar
PRO
Synthiam
#4   — Edited

You can also use the GetStatus ControlCommand to check if a script is running.

No, what the change did was continue the looop to keep checking if the global variable $Personality has a string that contains "1"

Also, note that sometimes you're using a string "1" and other times you're using a number 1

You should choose to pick one.

When athena answers she'll add more detail to my responses.

#5  

Quote:

You could also just use ScriptStartWait ControlCommand instead of looping to wait for another script to finish. ScriptStartWait will wait for the other script to finish before continuing.
Ah, I never learned what that command did. Now I know. Thanks.

Author Avatar
PRO
Canada
#6   — Edited

Nice work - you’re on the right track. Below are two safe, robust options you can use in ARC JavaScript so your parent script never exits its loop and always re-checks the $Personality lock before attempting work.

Key points:

  • Be consistent with variable types. Use strings for the lock everywhere (setVar("$Personality","1") / "0") or numbers everywhere. I recommend strings since you already used "1"/"0".
  • Prefer ScriptStartWait when the target is a Script skill - it will block until the child script finishes, avoiding busy polling.
  • If a skill doesn’t implement ScriptStartWait, use controlCommand("SkillName","GetStatus") to test if it’s running before starting it.
  • To skip a cycle when busy but try again later, check the lock, sleep the 15 minutes (900000 ms), and continue.

Option A - Preferred (use ScriptStartWait). This will wait for each child script to finish and will skip the entire cycle if $Personality is busy, then re-check after 15 minutes:

while (true) {
  // If another personality action is running, skip this cycle and try again after 15 min
  if (getVar("$Personality", "0") == "1") {
    print("Personality: busy - skipping this cycle");
    sleep(900000); // wait 15 minutes before re-checking
    continue;
  }

  // Acquire lock
  setVar("$Personality", "1");

  // Start each child script and WAIT for it to finish (ScriptStartWait)
  controlCommand("Head Section", "ScriptStartWait", "Bubble Full Down");
  controlCommand("Time,Date & Temp", "ScriptStartWait", "Outside Temp");
  controlCommand("Time,Date & Temp", "ScriptStartWait", "Humidity");
  controlCommand("Time,Date & Temp", "ScriptStartWait", "Wind Speed");
  controlCommand("Head Section", "ScriptStartWait", "Bubble Middle");

  // Release lock
  setVar("$Personality", "0");

  // Wait 15 minutes before the next cycle
  sleep(900000);
}

Notes for Option A:

  • ScriptStartWait only works if the target robot skill implements the wait command. The Script skill does, and many Script-driven skills will too. Check the skill’s Cheat Sheet (right-click or editor cheat-sheet) to confirm.
  • Using ScriptStartWait removes the need for while(getVar("$OutsideTemp" ) == 1) style polling in the parent.

Option B - If you must keep your current child-signal polling (less preferred):

  • Keep your child scripts setting $OutsideTemp, $Humid, etc.
  • Ensure you use string "1"/"0".
  • When busy, skip but sleep 15 minutes and continue to re-check.
while (true) {
  if (getVar("$Personality", "0") == "1") {
    print("Personality: busy - skipping this cycle");
    sleep(900000); // try again after 15 minutes
    continue;
  }

  setVar("$Personality", "1");

  // Start child scripts (non-waiting start)
  controlCommand("Head Section", "ScriptStart", "Bubble Full Down");

  // If child scripts set variables to indicate completion, wait for them
  setVar("$OutsideTemp", "1");
  controlCommand("Time,Date & Temp", "ScriptStart", "Outside Temp");
  while (getVar("$OutsideTemp", "0") == "1") {
    sleep(100);
  }

  setVar("$Humid", "1");
  controlCommand("Time,Date & Temp", "ScriptStart", "Humidity");
  while (getVar("$Humid", "0") == "1") {
    sleep(100);
  }

  setVar("$WSpeed", "1");
  controlCommand("Time,Date & Temp", "ScriptStart", "Wind Speed");
  while (getVar("$WSpeed", "0") == "1") {
    sleep(100);
  }

  controlCommand("Head Section", "ScriptStart", "Bubble Middle");

  setVar("$Personality", "0");
  sleep(900000);
}

Extra tips & tools:

  • To check a child script’s running state before starting it, use GetStatus:
    • Example:
      var isRunning = controlCommand("Time,Date & Temp", "GetStatus");
      if (isRunning == true) {
        print("Time,Date & Temp is already running");
      } else {
        controlCommand("Time,Date & Temp", "ScriptStart", "Outside Temp");
      }
      
  • If you want the parent to poll more frequently when busy (instead of waiting a full 15 minutes), change the sleep inside the busy branch to a shorter value (e.g., sleep(60000) for 1 minute) so it retries sooner.

Resources:

Would you like me to:

  • Convert your actual current script to Option A using exact skill names you use,
  • Or add a GetStatus check before each child start so the parent never attempts to start an already-running child?

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.