nasa-jpl / fastcat

C++ EtherCAT Device Command & Control Library
Other
42 stars 11 forks source link

Fastcat driver for Elmo's Platinum motor controller #76

Closed d-loret closed 1 year ago

d-loret commented 1 year ago

Adds the Fastcat driver for the Elmo's Platinum motor controller. This specific version corresponds to the basic functionality of the Platinum (i.e. equivalent functionality as Gold line).

The Actuator classes were refactored to facilitate the integration of the Platinum's Fastcat driver.

d-loret commented 1 year ago

fastcat_actuator_class_hierarchy

@alex-brinkman, hopefully this gives you a bird's-eye view of the changes.

d-loret commented 1 year ago

Comparison of the different modes between Gold and Platinum drives (ignore the title of the plots, all say Platinum):

CSP

EGD

plots

EPD

plots

CSV

EGD

plots

EPD

plots

CST

EGD

plots

EPD

plots

Profiled Position

EGD

plots

EPD

plots

Profiled Velocity

EGD

plots

EPD

plots

Profiled Torque

EGD

plots

EPD

plots

Differences are mostly due to tuning.

Only true differences are in Profiled Velocity and Profiled Torque modes. Profiled Velocity and Profiled Torque modes are not exactly the same between EPD and EGD when using a finite maximum duration parameter value. The EPD code is currently starting to count the time at the point of issuing the command as opposed to reaching the target. When the time is up, it immediately transitions into Disabled state.

With Profiled Velocity mode, it is possible to achieve the same behavior as trap by incorporating a couple of SDO configuration objects in the JSD driver what would allow to cleanly detect target velocity achieved and zero velocity achieved (i.e. you can configure windows in Elmo). I would just need an additional state machine's state in Fastcat. I could do this in a future MR since this detail is not critical right now.

For Profiled Torque mode, the slope torque parameter did not seem to make a difference. I tried testing it on the EGD JSD driver, but I couldn't even get Profiled Torque mode to work on it (the non-trap version for EGD). I can create a separate ticket to track the issue with the slope torque parameter as I follow up with Elmo.

alex-brinkman commented 1 year ago

So it looks like the only function invoked outside of the Actuator-flavored function is the GetActualPosition static method currently:

abrinkma@apb-home-u22:~/src/fastcat_ws/fastcat-dloret-epd-basic/src$ grep -ir GetFastcatFaultCodeAsString
jsd/actuator.h:  static std::string GetFastcatFaultCodeAsString(const DeviceState& state);
jsd/actuator.cc:std::string fastcat::Actuator::GetFastcatFaultCodeAsString(

abrinkma@apb-home-u22:~/src/fastcat_ws/fastcat-dloret-epd-basic/src$ grep -ir GetJSDFaultCodeAsString
jsd/actuator.h:  static std::string GetJSDFaultCodeAsString(const DeviceState& state);
jsd/actuator_fsm_helpers.cc:        GetJSDFaultCodeAsString(*state_).c_str());
jsd/actuator.cc:std::string fastcat::Actuator::GetJSDFaultCodeAsString(const DeviceState& state)

abrinkma@apb-home-u22:~/src/fastcat_ws/fastcat-dloret-epd-basic/src$ grep -ir IsJsdFaultCodePresent
jsd/actuator.h:  static bool        IsJsdFaultCodePresent(const DeviceState& state);
jsd/actuator_fsm_helpers.cc:  if (IsJsdFaultCodePresent(*state_)) {
jsd/actuator_fsm_helpers.cc:  if (IsJsdFaultCodePresent(*state_)) {
jsd/actuator_fsm_helpers.cc:  if (IsJsdFaultCodePresent(*state_)) {
jsd/actuator_fsm_helpers.cc:      IsJsdFaultCodePresent(*state_)) {
jsd/actuator.cc:bool fastcat::Actuator::IsJsdFaultCodePresent(const DeviceState& state)
jsd/actuator.cc:        "IsJsdFaultCodePresent must be called on states of Elmo actuator "

abrinkma@apb-home-u22:~/src/fastcat_ws/fastcat-dloret-epd-basic/src$ grep -irn GetActualPosition
jsd/actuator.h:68:  static double      GetActualPosition(const DeviceState& state);
jsd/actuator_fsm_helpers.cc:419:    target_position = GetActualPosition(*state_) + cal_range;
jsd/actuator_fsm_helpers.cc:421:    target_position = GetActualPosition(*state_) - cal_range;
jsd/actuator_fsm_helpers.cc:428:                GetActualPosition(*state_),  // consider cmd position
jsd/actuator.cc:487:      "Changing Position from: ", GetActualPosition(*state_),
jsd/actuator.cc:763:double fastcat::Actuator::GetActualPosition(const DeviceState& state)
jsd/actuator.cc:772:        "GetActualPosition must be called on states of Elmo actuator "
jsd/actuator.cc:784:        cmd.actuator_prof_pos_cmd.target_position + GetActualPosition(*state_);
manager.cc:1067:    apd.position                = Actuator::GetActualPosition(*dev_state);

I don't believe there is any reason prevent us from changing this an Actuator base class virtual function that the manager can directly call to get position:

1045 void fastcat::Manager::GetActuatorPositions()
1046 { 
1047   std::shared_ptr<DeviceState> dev_state;
1048   std::shared_ptr<Actuator>    actuator;
1049   std::string                  dev_name;
1050   for (auto device = jsd_device_list_.begin(); device != jsd_device_list_.end();
1051        ++device) {
1052     dev_state = (*device)->GetState();
1053     dev_name  = (*device)->GetName();
1054 
1055     if (dev_state->type != EGD_ACTUATOR_STATE &&
1056         dev_state->type != EPD_ACTUATOR_STATE) {
1057       continue;
1058     }
1059
1060     actuator = std::dynamic_pointer_cast<Actuator>(*device);
...
1066     ActuatorPosData apd         = {0};
1067     apd.position                = Actuator::GetActualPosition(*dev_state);
1068     actuator_pos_map_[dev_name] = apd;
1069   
1070     MSG("Actuator: %s position is %lf", dev_name.c_str(), apd.position);
1071   }
alex-brinkman commented 1 year ago

I just merged an outstanding branch relating to adding actuator UTs that adds a friend class to permit access to protected/private methods. I'm happy to migrate the UTs to be consistent with the latest release on master

d-loret commented 1 year ago

Ran tests on both the Gold and the Platinum drives for the 6 modes of operation. The results seemed to be similar to the ones I posted first. Hence, I am going to merge.