#:package Google.Protobuf@3.33.0
#:package Grpc.Net.Client@2.71.0
using Grpc.Net.Client;
using Google.Protobuf;
using RSI.RapidCodeRemote;
using RSI.RapidServer;
using static
RSI.RapidCodeRemote.RMPService;
using static
RSI.RapidServer.ServerControlService;
using System.Diagnostics;
Console.WriteLine("📜 RapidCodeRemote: Quick Start");
Process serverProcess = ServerStart();
var address = $"http://{Constants.RAPIDSERVER_IP}:{Constants.RAPIDSERVER_PORT}";
var channel = GrpcChannel.ForAddress(address);
var serverClient = new ServerControlServiceClient(channel);
var rmpClient = new RMPServiceClient(channel);
try
{
ServerInfoGet(serverClient);
ControllerCreate(rmpClient);
AxisCountSet(rmpClient);
AxisStatusGet(rmpClient);
AxisMotionPointToPoint(rmpClient);
AxisMotionStreaming(rmpClient);
}
finally
{
await channel.ShutdownAsync();
channel.Dispose();
if (serverProcess != null && !serverProcess.HasExited)
{
serverProcess.Kill();
serverProcess.WaitForExit();
Console.WriteLine("Stopped RapidServer");
}
}
Console.WriteLine("\n✅ RapidCodeRemote Quick Start Complete");
void ServerInfoGet(ServerControlServiceClient client)
{
Console.WriteLine("\n 📜 Server Info");
ServerGetInfoRequest infoRequest = new ServerGetInfoRequest();
ServerGetInfoResponse infoResponse = client.GetInfo(infoRequest);
Console.WriteLine($"Connected to server named '{infoResponse.Name}' with ID: {infoResponse.Id:X}");
Console.WriteLine($"Server version: {infoResponse.Version}");
}
void ControllerCreate(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Controller Create");
MotionControllerResponse motionControllerResponse = client.MotionController(new MotionControllerRequest
{
Action = new MotionControllerAction { Create = new MotionControllerCreationParameters() }
});
Console.WriteLine("Motion Controller created successfully");
}
void AxisCountSet(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Axis Count");
MotionControllerResponse motionControllerResponse = client.MotionController(new MotionControllerRequest
{
});
Console.WriteLine($"Axis count set to: {motionControllerResponse.Config.AxisCount}");
}
void AxisStatusGet(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Axis Status");
Console.WriteLine($"Axis {Constants.AXIS_0_INDEX} state: {axisResponse.Status.State}");
}
#pragma warning disable CS8321
void ControllerShutdown(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Controller Shutdown");
client.MotionController(new MotionControllerRequest
{
Action = new MotionControllerAction { Shutdown = new MotionControllerAction.Types.Shutdown() }
});
Console.WriteLine("Motion Controller shut down successfully");
}
{
Console.WriteLine("\n 📜 Network Start");
var action = new NetworkAction();
if (discoverBeforeStart)
action.DiscoverAndStart = new NetworkAction.Types.DiscoverAndStart();
else
action.Start = new NetworkAction.Types.Start();
NetworkResponse networkResponse = rmpClient.Network(new NetworkRequest
{
Action = action
});
}
#pragma warning restore CS8321
void AxisMotionPointToPoint(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Axis Motion: Point-to-Point");
AxisResponse axisResponse = client.Axis(new AxisRequest
{
{
ErrorLimit = new AxisConfig.Types.ErrorLimit { Action = RSIAction.None }
}
});
axisResponse = client.Axis(new AxisRequest
{
Action = new AxisAction
{
Abort = new AxisAction.Types.Abort(),
ClearFaults = new AxisAction.Types.ClearFaults(),
PositionSet = new AxisAction.Types.PositionSet { Position = 0 }
}
});
var moveAction = new AxisAction
{
Move = new AxisAction.Types.Move
{
PointToPoint = new AxisMovePointToPoint
{
Acceleration = 100,
Deceleration = 100,
Velocity = 10,
Position = 10,
JerkPercent = 50
}
}
};
Console.WriteLine($"Commanded move to position 10");
Console.WriteLine("Waiting for axis to stop moving...");
while (true)
{
if (axisResponse.Status.State !=
RSIState.Moving)
break;
System.Threading.Thread.Sleep(100);
}
Console.WriteLine($"Final command position: {axisResponse.Status.Position.Command}");
}
void AxisMotionStreaming(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Axis Motion: Streaming");
AxisResponse axisResponse = client.Axis(new AxisRequest
{
{
ErrorLimit = new AxisConfig.Types.ErrorLimit { Action = RSIAction.None }
}
});
Console.WriteLine("Waiting for axis to stop moving...");
while (true)
{
if (axisResponse.Status.State !=
RSIState.Moving)
break;
System.Threading.Thread.Sleep(100);
}
axisResponse = client.Axis(new AxisRequest
{
Action = new AxisAction
{
ClearFaults = new AxisAction.Types.ClearFaults(),
PositionSet = new AxisAction.Types.PositionSet { Position = 0 }
}
});
int originalMotionId = (int)axisResponse.Status.MotionId;
var streamingMove = new MoveStreaming();
int numPoints = 100;
double amplitude = 1.0;
for (int i = 0; i < numPoints; i++)
{
double position = Math.Sin(i / (double)numPoints * 2 * Math.PI) * amplitude;
streamingMove.Positions.Add(position);
streamingMove.Times.Add(1.0 / numPoints);
}
streamingMove.EmptyCount = 50;
streamingMove.Retain = false;
streamingMove.Final = false;
var moveAction = new AxisAction
{
Move = new AxisAction.Types.Move { Streaming = streamingMove }
};
Console.WriteLine("Sent first streaming move batch");
int previousMotionId = (int)axisResponse.Status.MotionId - 1;
for (int batch = 2; batch <= 5; batch++)
{
while (true)
{
if (axisResponse.Status.MotionIdExecuting >= previousMotionId)
break;
System.Threading.Thread.Sleep(10);
}
streamingMove = new MoveStreaming();
amplitude = batch;
for (int i = 0; i < numPoints; i++)
{
double position = Math.Sin(i / (double)numPoints * 2 * Math.PI) * amplitude;
streamingMove.Positions.Add(position);
streamingMove.Times.Add(1.0 / numPoints);
}
streamingMove.EmptyCount = 50;
streamingMove.Retain = false;
streamingMove.Final = (batch == 5);
moveAction = new AxisAction
{
Move = new AxisAction.Types.Move { Streaming = streamingMove }
};
previousMotionId = (int)axisResponse.Status.MotionId - 1;
Console.WriteLine($"Sent streaming batch {batch} (amplitude={amplitude}, final={streamingMove.Final})");
}
Console.WriteLine("Waiting for streaming motion to complete...");
while (true)
{
if (axisResponse.Status.State !=
RSIState.Moving)
break;
System.Threading.Thread.Sleep(100);
}
Console.WriteLine($"Streaming motion complete. Final state: {axisResponse.Status.State}");
Console.WriteLine($"Final command position: {axisResponse.Status.Position.Command}");
}
{
if (header.Errors.Count > 0)
{
string message = "RPC had errors:\n";
foreach (var error in header.Errors)
{
message += $" {error.Message}\n";
}
throw new Exception(message);
}
}
Process ServerStart()
{
string serverProcessName = "rapidserver";
string serverPath;
#if WINDOWS
#elif LINUX
#endif
string cmdArgs = $"-grpc_port {Constants.RAPIDSERVER_PORT}";
Process serverProcess = Process.Start(serverPath, cmdArgs);
if (serverProcess == null || serverProcess.HasExited)
{
throw new Exception("Failed to start RapidServer process!");
}
Console.WriteLine($"Started RapidServer (PID: {serverProcess.Id}) on port {Constants.RAPIDSERVER_PORT}");
Thread.Sleep(1000);
return serverProcess;
}
Constants used in the C# sample apps.
const double AXIS_0_USER_UNITS
Default: 1.
const int AXIS_COUNT
Default: 6.
const int AXIS_0_INDEX
Default: 0.
const string RMP_LINUX_PATH
Default: /rsi.
const string RMP_WINDOWS_PATH
Default: .....
This namespace provides static methods and constants for user configuration in RMP applications....
void CheckErrors(RapidCodeObject *rsiObject, const std::source_location &location=std::source_location::current())
Checks for errors in the given RapidCodeObject and throws an exception if any non-warning errors are ...
void NetworkStart(MotionController *controller)
[CheckErrors]