Upgrading to RMP v10 (from v8)

I just finished the initial upgrade of our code to use RMP v10.

Overall, I’m very happy with the changes. Thanks for your work and consideration of the customer.

Interface Code (C++ headers)

The code is significantly more beautiful that from v8.

I use SWIG to generate interface code so that I can use the runtime API from Python. v10’s headers (without lots of CPP macros and indirection which tend to freak out everyone but the full-blown C/C++ compiler) worked right out of the box without me having to do any cleanup or anything! With v8, this was quite a chore, especially if I wanted to be able to upgrade to newer versions (with API changes).

Inline docs mean that I don’t have to switch to the web browser again and again to get the official word about what a function is supposed to do. It also means that I can see right away that “this function that looks like it might be useful” is actually deprecated.

Separating out enums into a different header is nice (for me) for two reasons. I can parse it separately (without having to know/care about most of C++ syntax) so that getting the enum name from its value is easier. I can search through the main header for a name and not spend the first 3-50 hits on enum names.

  • Using C++ class enums means that the names are no longer global. Excellent!
    • Using C++ class enums also means that there’s no implicit conversion to/from integral data types (VS 2017, --std=c++17).
      • It seems like some API functions take integers instead of enums. This means that I have to do a lot of static_cast<int32_t>(<enum_sym>). I ran into this when converting my code, but I didn’t take notes on what/when.
    • It might have been good to use this as an opportunity to strip off the (now, redundant) prefixes for all the enum symbols. For example, to use RSIMotorIoTypeMaskOUTPUT, I have to say RSIMotorIoTypeMask::RSIMotorIoTypeMaskOUTPUT. This can get pretty (needlessly) lengthy. Since switching to C++ class enums was going to break every customer anyway, why not use this opportunity to clean up the names, so that I would only need to say RSIMotorIoTypeMask::OUTPUT?

Is RSIAPP gone? I never wanted it before, even though it’s not unreasonable to insist that client code define it. However, stylistically, making clients jump through hoops to use the API is probably backward, since it should be a simple-to-use black box. Thanks for removing this thing on which I occasionally stub my toe when I forgot.

RapidSetup and Files

Switching to NodeInfo.xml from “EtherCATNodeInfo.xml” (“ENI”, but NOT the real ENI, which is named EtherCAT.xml—oh the time I spent trying to unconfuse people about this) seems like a good move.

Thank you for putting the client runtime DLLs in separate places and creating a commonly used “include”, “lib”, etc. directory structure.

Did v8 have the “Network Timing” and “Packet Errors” tools? I’m glad it’s here, even if it’s not new.

Thanks for including more info in RapidSetup. The more that’s there, the less I have to go writing C++ (or ,now, Python) apps to get things.

Thanks for bundling the samples in with the install. This makes it a lot easier to use sample code.


To illustrate my (very minor) assertion about enums, here are some unusual enums

  • The names inside RSINetworkIndexType do not follow the “normal” convention and are missing the leading “RSI”.
  • The enums inside RSIErrorMessage are categorized by their prefix, which is sensible. It just differs from the rest of the enums.
  • The names inside RSIFirmwareLogic do not have the same prefix.
  • RSI::RapidCode::IO::DigitalOutSet(...) takes an int and not an enum, like RSIMotorGeneralIo, but RSI::RapidCode::Axis::CreateDigitalOutput(...) takes an enum rather than an int.
    • I suppose the explanation in this case is that there’s not an enum for general IO on an IO object, though I’m not sure why there is one for motors. I suppose there’s no practical upper limit on how many I/O points could exist on a generic I/O device. ??

You could, perhaps, argue that the naming quirks I’ve mentioned would break backward compatibility, but switching to C++11 class enums did that already, so why not normalize the names?

My observations are also naive about the C# implementation, which could have some bearing on design decisions.

Anyway, I’m not necessarily lobbying for a change on your part. I just wanted to provide some constructive feedback.

Todd, thanks for all the feedback. We’re glad your overall impression was positive.

Yes, we did consider cleaning up the enum names(i.e. RSIMotorIOTypeMask::OUTPUT), but we decided against it in the name of trying to change as little as possible for existing customers. Tough call.

RSIAPP is gone. Good riddance!

v8 had Network Timing and Packet Errors, though they weren’t as pretty. We hope you’ll enjoy UserLimits in RapidSetup as much as we have.

We’ll consider the further enums cleanup you suggest. I suspect RSIErrorMessage won’t change, but the others seem worthwhile.

Yes, IO::DigitalOutSet() is using an integer index because there’s no practical limit. The RSIMotorGeneralIO is kind of a legacy thing for reading Axis IO. In the olden days, there were a fixed 32 inputs for each Axis. Nowadays, you’re probably better off using Axis->NetworkNode->DigitalInGet(index), etc.

@todd_mm if you can find examples of this, we’d like to address/fix them:

  • It seems like some API functions take integers instead of enums. This means that I have to do a lot of static_cast<int32_t>(<enum_sym>) . I ran into this when converting my code, but I didn’t take notes on what/when.

I suspect that the digital I/O enums associated with motors was what I was thinking of. If I notice something in the future, I’ll mention it.