Learn how to use RapidCodeRemote (gRPC) for remote control of RMP hardware in C#.
- Warning
- This is a sample program to assist in the integration of the RMP motion controller with your application. It may not contain all of the logic and safety features that your application requires. We recommend that you wire an external hardware emergency stop (e-stop) button for safety when using our code sample apps. Doing so will help ensure the safety of you and those around you and will prevent potential injury or damage.
The sample apps assume that the system (network, axes, I/O) are configured prior to running the code featured in the sample app. See the Configuration page for more information.
In this page:
📜 Client Creation
Learn how to set up the gRPC client to communicate with the RapidServer.
var address = $"http://{Constants.RAPIDSERVER_IP}:{Constants.RAPIDSERVER_PORT}";
var channel = GrpcChannel.ForAddress(address);
var serverClient = new ServerControlServiceClient(channel);
var rmpClient = new RMPServiceClient(channel);
📜 Server Info
Learn how to query server details and verify connection. Shows how to retrieve server name, ID, and version information.
void ServerInfoGet(ServerControlServiceClient client)
{
Console.WriteLine("\n 📜 Server Info");
ServerGetInfoRequest infoRequest = new ServerGetInfoRequest();
ServerGetInfoResponse infoResponse = client.GetInfo(infoRequest);
CheckErrors(infoResponse.Header);
Console.WriteLine($"Connected to server named '{infoResponse.Name}' with ID: {infoResponse.Id:X}");
Console.WriteLine($"Server version: {infoResponse.Version}");
}
📜 Controller Creation
Learn how to create a remote MotionController on the server. Shows how to initialize the motion control system via gRPC.
void ControllerCreate(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Controller Create");
MotionControllerResponse motionControllerResponse = client.MotionController(new MotionControllerRequest
{
Action = new MotionControllerAction { Create = new MotionControllerCreationParameters() }
});
CheckErrors(motionControllerResponse.Header);
Console.WriteLine("Motion Controller created successfully");
}
📜 Controller Shutdown
Learn how to properly shutdown the remote motion controller. Shows how to cleanly terminate the motion control system.
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");
}
📜 Network Start
Learn how to start the EtherCAT network.
void NetworkStart(bool discoverBeforeStart = false)
{
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
});
CheckErrors(networkResponse.Header);
}
#pragma warning restore CS8321
📜 Axis Count
Learn how to set the axis count for phantom axes. Shows how to configure the number of axes remotely.
void AxisCountSet(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Axis Count");
MotionControllerResponse motionControllerResponse = client.MotionController(new MotionControllerRequest
{
Config = new MotionControllerConfig { AxisCount = Constants.AXIS_COUNT }
});
CheckErrors(motionControllerResponse.Header);
Console.WriteLine($"Axis count set to: {motionControllerResponse.Config.AxisCount}");
}
📜 Axis Status
Learn how to check axis state and status remotely. Shows how to retrieve current axis information via gRPC.
void AxisStatusGet(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Axis Status");
AxisResponse axisResponse = client.Axis(new AxisRequest { Index = Constants.AXIS_0_INDEX });
CheckErrors(axisResponse.Header);
Console.WriteLine($"Axis {Constants.AXIS_0_INDEX} state: {axisResponse.Status.State}");
}
📜 Axis Motion: Point-to-Point
Learn how to execute simple position moves remotely. Shows how to configure axis, clear faults, and command point-to-point moves.
void AxisMotionPointToPoint(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Axis Motion: Point-to-Point");
AxisResponse axisResponse = client.Axis(new AxisRequest
{
Index = Constants.AXIS_0_INDEX,
Config = new AxisConfig
{
UserUnits = 1000,
ErrorLimit = new AxisConfig.Types.ErrorLimit { Action = RSIAction.None }
}
});
CheckErrors(axisResponse.Header);
axisResponse = client.Axis(new AxisRequest
{
Index = Constants.AXIS_0_INDEX,
Action = new AxisAction
{
ClearFaults = new AxisAction.Types.ClearFaults(),
PositionSet = new AxisAction.Types.PositionSet { Position = 0 }
}
});
CheckErrors(axisResponse.Header);
var moveAction = new AxisAction
{
Move = new AxisAction.Types.Move
{
PointToPoint = new AxisMovePointToPoint
{
Acceleration = 100,
Deceleration = 100,
Velocity = 10,
Position = 10,
JerkPercent = 50
}
}
};
axisResponse = client.Axis(new AxisRequest { Index = Constants.AXIS_0_INDEX, Action = moveAction });
CheckErrors(axisResponse.Header);
Console.WriteLine($"Commanded move to position 10");
System.Threading.Thread.Sleep(1000);
axisResponse = client.Axis(new AxisRequest { Index = Constants.AXIS_0_INDEX });
CheckErrors(axisResponse.Header);
Console.WriteLine($"Final command position: {axisResponse.Status.Position.Command}");
}
📜 Axis Motion: Streaming
Learn how to continuously stream motion points for complex trajectories. Shows how to send batches of streaming points and manage motion execution.
void AxisMotionStreaming(RMPServiceClient client)
{
Console.WriteLine("\n 📜 Axis Motion: Streaming");
AxisResponse axisResponse = client.Axis(new AxisRequest
{
Index = Constants.AXIS_0_INDEX,
Config = new AxisConfig
{
UserUnits = 1000,
ErrorLimit = new AxisConfig.Types.ErrorLimit { Action = RSIAction.None }
}
});
CheckErrors(axisResponse.Header);
Console.WriteLine("Waiting for axis to stop moving...");
while (true)
{
axisResponse = client.Axis(new AxisRequest { Index = Constants.AXIS_0_INDEX });
CheckErrors(axisResponse.Header);
if (axisResponse.Status.State !=
RSIState.Moving)
break;
System.Threading.Thread.Sleep(100);
}
axisResponse = client.Axis(new AxisRequest
{
Index = Constants.AXIS_0_INDEX,
Action = new AxisAction
{
ClearFaults = new AxisAction.Types.ClearFaults(),
PositionSet = new AxisAction.Types.PositionSet { Position = 0 }
}
});
CheckErrors(axisResponse.Header);
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 }
};
axisResponse = client.Axis(new AxisRequest { Index = Constants.AXIS_0_INDEX, Action = moveAction });
CheckErrors(axisResponse.Header);
Console.WriteLine("Sent first streaming move batch");
int previousMotionId = (int)axisResponse.Status.MotionId - 1;
for (int batch = 2; batch <= 5; batch++)
{
while (true)
{
axisResponse = client.Axis(new AxisRequest { Index = Constants.AXIS_0_INDEX });
CheckErrors(axisResponse.Header);
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 }
};
axisResponse = client.Axis(new AxisRequest { Index = Constants.AXIS_0_INDEX, Action = moveAction });
CheckErrors(axisResponse.Header);
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)
{
axisResponse = client.Axis(new AxisRequest { Index = Constants.AXIS_0_INDEX });
CheckErrors(axisResponse.Header);
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}");
}
📜 Error Handling
Learn how to check RPC responses for errors. Shows how to validate server responses and handle error conditions.
void CheckErrors(
RSI.RapidServer.ResponseHeader header)
{
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);
}
}