New robot class and file input#

Until now we used delays to wait until a robot program has completed processing. This is not reliable, because some programs may take longer than others. The class below features ProgramRunning that solves shortcomings of the delay approach.

You can use it in your project or copy parts of it.

Robot class#

The following diagram is a summary of the Robot.cs at the bottom.

        classDiagram
    class Robot {
        +bool ProgramRunning
        +bool Connected
        +string RobotMode
        +Robot(string ipAddress, int dashboardPort, int urscriptPort)
        +Connect() void
        +PowerOn() void
        +BrakeRelease() void
        +Disconnect() void
        +SendDashboard(string command) void
        +SendUrscript(string program) void
        +SendUrscriptFile(string path) void
        +ReadLineDashboard() string
    }
    
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace InventorySystem;

public class Robot(string ipAddress = "localhost", int dashboardPort = 29999, int urscriptPort = 30002)
{
    private readonly TcpClient _clientDashboard = new();
    private readonly TcpClient _clientUrscript = new();
    private Stream _streamDashboard;
    private StreamReader _streamReaderDashboard;
    private Stream _streamUrscript;
    public string IpAddress = ipAddress;

    public bool ProgramRunning
    {
        get
        {
            if (_clientDashboard.Connected)
            {
                SendDashboard("running\n");
                return ReadLineDashboard() == "Program running: true";
            }

            return false;
        }
    }

    public bool Connected => _clientDashboard.Connected && _clientUrscript.Connected;

    public string RobotMode
    {
        get
        {
            SendDashboard("robotmode\n");
            return ReadLineDashboard();
        }
    }

    public void Connect()
    {
        _clientDashboard.Connect(IpAddress, dashboardPort);
        _streamDashboard = _clientDashboard.GetStream();
        _streamReaderDashboard = new StreamReader(_streamDashboard, Encoding.ASCII);

        // Consume Dashboard welcome message
        ReadLineDashboard();

        _clientUrscript.Connect(IpAddress, urscriptPort);
        _streamUrscript = _clientUrscript.GetStream();
    }


    public async void PowerOn()
    {
        SendDashboard("power on\n");
        ReadLineDashboard(); // Consume
        while (RobotMode != "Robotmode: IDLE") await Task.Delay(1000);
    }

    public async void BrakeRelease()
    {
        SendDashboard("brake release\n");
        ReadLineDashboard(); // Consume
        while (RobotMode != "Robotmode: RUNNING") await Task.Delay(1000);
    }


    public void Disconnect()
    {
        _clientDashboard.Close();
        _clientUrscript.Close();
    }


    public void SendDashboard(string command)
    {
        _streamDashboard.Write(Encoding.ASCII.GetBytes(command));
    }

    public void SendUrscript(string program)
    {
        _streamUrscript.Write(Encoding.ASCII.GetBytes(program));
    }

    public void SendUrscriptFile(string path)
    {
        var program = File.ReadAllText(path) + Environment.NewLine;
        SendUrscript(program);
    }

    public string ReadLineDashboard()
    {
        return _streamReaderDashboard.ReadLine();
    }
}
⚡ Live programming

Using the class and waiting until a program finishes using ProgramRunning.

Note, a short delay is required as follows:

        SendUrscript(string.Format(CultureInfo.InvariantCulture, Program, itemId));
        do
        {
            await Task.Delay(100); // Wait for the robot to move
        } while (ProgramRunning);

File input#

If your robot program grows in size, it may be more convenient to work on a separate file. URScript files use typically .script suffix.

You can read a whole program into a string as follows:

using System.IO;
string Program = File.ReadAllText("file.txt") + Environment.NewLine;

Warning

If the URScript program does not have a newline after the last end, PolyScope silently ignores the program.

Copying an input file to the output folder in Rider#

If you want to read a file in Rider, copy the file automatically to the same folder where your program is executed. You can do this as follows:

  1. Add the file to your project

  2. Right-click on the file.

  3. Click Properties.

  4. Modify Copy to output directory to Copy if newer.

Now you can now directly read files as follows:

Activity 47

Read a file and print its contents on the console.