Using Messaging Domain, Multitasking, and PC SDK to calibrate a camera

Hello !

My goal is to automate camera calibration within the workspace of an ABB robot.
To do this, I need to take 60 images at 60 different positions above a calibration target.

I created three programs that communicate with each other:

  • C# software to capture images and retrieve the robot’s position
  • T_ROB1/CalibrationMotion.mod to manage the robot’s movements
  • CalibrationComm/CalibrationComm.mod to manage communication with C# in multitasking mode (SemiStatic task)

Here is a diagram to better visualize the communication between the three:

I’m having trouble retrieving rmqslot on RobotStudio.
Basically, I created a PERS rmqslot gPcSlot in my two modules, CalibrationMotion and CalibrationComm.
In CalibrationMotion, this allows me to send “READY_FOR_CAPTURE;i”:

PROC SendReadyForCapture(num index)
RMQSendMessage gPcSlot, “READY_FOR_CAPTURE;” + NumToStr(index,0);
ENDPROC

In CalibrationComm, I retrieve who is gPcSlot to send them the “Ok” message:

TRAP HandlePCCmd
VAR rmqmessage msg;
VAR rmqheader header;
VAR rmqslot senderSlot;

RMQGetMessage msg;
RMQGetMsgHeader msg \Header := header \SenderId := senderSlot \UserDef := userDef;
gPcSlot := senderSlot;

RMQSendMessage senderSlot, “OK”;
ENDTRAP

Except that rmqslot is not a ‘value’ class type, so I don’t understand how we can retrieve the queue from my C# software so that we can then manipulate it in RobotStudio.

On the C# side, I have:
private IpcQueue? _robotQueue; // RMQ_T_ROB1
private IpcQueue? _pcQueue; // PC_SDK_Q

_robotQueue = _controller.Ipc.GetQueue(“RMQ_T_ROB1”);
if (!_controller.Ipc.Exists(“PC_SDK_Q”))
_pcQueue = _controller.Ipc.CreateQueue(“PC_SDK_Q”, 10, _controller.Ipc.GetMaximumMessageSize());
else
_pcQueue = _controller.Ipc.GetQueue(“PC_SDK_Q”);

To receive the data, I use:
IpcReturnType ret = _pcQueue.Receive(5000, recvMsg);

And to send it:
byte data = Encoding.UTF8.GetBytes($“ACK;{i};{(isOk ? “1” : “0”)}”);
_sendMsg!.SetData(data);
_sendMsg.Sender = _pcQueue!.QueueId;
_robotQueue!.Send(_sendMsg);

I hope that’s clear enough, but if you need any further clarification, please don’t hesitate to ask.

Thank you to those who take the time to think about it :slight_smile:

I’m unsure if I understand you correctly, you do not receive the messages from C# in your RAPID task? In that case, have you configured your RAPID task for Remote RMQ messaging? Configuration→Controller→Task→RMQ Type→Remote ?

1 Like

The fact is that I couldn’t retrieve the rmqslot used to send my messages to the C# program because rmqslot cannot be used as a conventional variable at all.

I got around this by using RMQFindSlot gPcSlot, “PC_SDK_Q” and RMQFindSlot robotSlot, “RMQ_CalibrationComm” everywhere.

I basically tried to retrieve the slot using the response from “RMQGetMsgHeader msg \Header := header \SenderId := senderSlot \UserDef := userDef;” by simply doing “gPcSlot := senderSlot;”, but obviously that’s not how it works.

Great that you found a solution. However your first approach should be okay. I have a similar setup, which works just fine:

LOCAL VAR rmqslot m_txRMQSlot;

….

RMQGetMessage t_rmqmsg; ! Read message
RMQGetMsgHeader t_rmqmsg \Header:=header \SenderId:=m_txRMQSlot \UserDef:=seqNum; ! Read header and sequence number

RMQSendMessage m_txRMQSlot, seqNum \UserDef:=seqNum; ! Inform PC that the message has been read

On the PC I set the sender just as you do.

You could try for a start to define gPcSlot as LOCAL VAR instead of PERS, just for testing that.

1 Like

It might be you should remove senderSlot and use gPcSlot directly in RMQGetMsgHeader

I like your solution. I tried it, it works well, and I think it’s neat.

Thank you !