Cascading Detach

This is a post to explore the possibility of a "cascading detach".  This is when a Service is released from Mrl and is currently attached to other services.  The goal will be to release the service as cleanly as possible, and in the process notify other Services it has been released.  Potentially, this notification will "cascade" into mutliple detach calls to successfully remove the target Service.

Setup - Here is setup of the problem - ***Mats can you add to the script? to get the initial setup?***


#file : /home/GroG/detach.py edit raw
port = "COM99"
virtual = Runtime.start('virtual','VirtualArduino')
virtual.connect(port)
adafruit = Runtime.start('adafruit','Adafruit16CServoDriver')
arduino = Runtime.start('arduino','Arduino')
servo = Runtime.start('servo','Servo')
arduino.connect(port)
adafruit.setController(arduino,"0","0x40")
servo.attach(adafruit,3) 
# Now close the GUI

References :

  • Mats reference of where he is disabling pwm - but its not working, because Arduino service is already released - I would propose this call detach which will call other detaches to remove a service attached to other services

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Mats's picture

detach

Doh

How should I handle this....

public void detach(Attachable servo)

already exists

But what I need is 

public void detach(ServoControl servo)

public void detach(I2CController, i2cController)

Since both are Attachable, I can't differ between them.

Generic interfaces and two way attach doesn't play well together.

GroG's picture

public void detach(Attachable

public void detach(Attachable servo)  

is the master routing function - its the most general ... within its body it does the correct "default" routing. It inspects the incoming most general form and calls the appropriately "typed" method (or methods). This is identical to the way attach(Attachable service)  should behave.

You'll want to be explicit by writing the other detach methods preferrably with interfaces - but if you must be very explicit it might end up with classes as parameters.

The generic attach/detach only "routes" to the "as general but worky" method ..

Here is an example I put in the ssc servo controller ... its more simplistic because it handles only 1 type of interface - but others can be chained in the if statement 

I know its the "attach" and not "detach" but they should be handled in the same way ..  I just have not done it for detach in the Ssc servo controller ... (its on my the todo list ;)

 

Mats's picture

attach / detach

Thanks for the example. I hope I understand the patter now, so that I can continue the refactoring.  

At some stage you suggested this:

public void attach(MotorControl motor);

public void attach(ServoControl servo);

public void attach(UltrasonicSensor sensor);

But I think the discussion ended so that this is the code I would use in Adafruit16CServoDriver:

 

public void attach(Attachable service) throws Exception {

    // The necessary attach going from high level to low level
    if (I2Controller.class.isAssignableFrom(service.getClass())) {
      attachI2CController((I2CController) service);
      return;
    }
    // The helper attaches going from low level to high level  
    if (MotorControl.class.isAssignableFrom(service.getClass())) {
      attachMotorControl((MotorControl) service);
      return;
    }
    if (ServoControl.class.isAssignableFrom(service.getClass())) {
      attachServoControl((ServoControl) service);
      return;
    }
}
GroG's picture

Right, attach(Attachable)'s

Right, attach(Attachable)'s  purpose is to provide a "default" way to delegate to more specific or multiple attach methods.

To prevent the infinite loop and still let the parameterized service get a chance to attach, all routed methods need to check if they are attached and at the end of the routine call service.attach(this)

e.g.

public void attachMotorControl(MotorControl motor){
               
               // isAttached can be general or specific
               // depending on the need and capabilities of the Service
               // for example it could be written to "route" too  
               if (isAttached(motor)) { 
                      // we are done
                      return;
                }

                ....   attach logic - modify self data .....
 

              // call attach on parameterized service
              motor.attach(this);

}

Don't remember if I did this in Ssc Servo Controller .. but I think that's how its supposed to be.   Detach should be completely symmetric .. pretty sure I have work to do on Ssc Servo Controller to finish ..

Mats's picture

detach pattern

OK.

I tried the suggested pattern.

What happens now is that the Arduino service informs the Adafruit16CServoDriver that it will shutdown. The Adafruit16CServoDriver send a command to stop the pwm generation, but fails becasuse serial has already closed the port.

Back at square 1. 

This pattern only works when executing the stopService for a single service but not when closing MRL.

/Mats

 

 

 

GroG's picture

I don't think its back to

I don't think its back to square 1 .. I think the pattern is just getting more specific and clear.
I suspect the reason for the failure is because the port is closed before the detach is called.

I thought perhaps the order would be

  • check if already detached - if (isAttached(serviceB))
  • release internal resources (ie close port)
  • call detach on detaching service - serviceB.detach(this)

but as you pointed out closing the port - in case we are an Arduino happens too early in this process, because other service rely on Arduino as a communication channel to properly detach so the order should be this

  • check if already detached - if (isAttached(serviceB))
  • call detach on detaching service - serviceB.detach(this)
  • release internal resources (ie close port)

In a way the detach method now has become sort of a prepareForRelease event, but it does it in a blocking manner so we don't need to try to deal with the complexities of asynchronous events for this .. which might be a good thing ..

GroG's picture

In the process of polishing

In the process of polishing Ssc Servo Controller...  
I started adding the "routing" detach 

...

then I noticed the ServoController interface is not symmetric .. it has a 

attachServoControl

but not a

detachServoControl ..

I think this is an artifact of DeviceController ... and the ease of detaching vs the complexity of attaching, so detach was never needed to propegate up through the various interfaces. DeviceController.detach() handled it all..   but to be extensible, and allow detaching of different specific types of services - there should be the symmetric detach in every interface ...

This change change can be 'grown' without breaking scripts - since the routing attach/detach would be added at the same time.  Just observing ... not changing anything..   I have some OpenCV merges to work on ..

Mats's picture

attach/detach

I have seen the same thing in a few interfaces, and I agree that they should be symetric, and that the <Interface>detach also should specify the interface as a parameter. Trying to implement the attach / detach pattern starting with the i2c interfaces. I will proably hit a few other interfaces like ServoControl/Controller MotorControl/MotorController.

 

GroG's picture

I

I updated Ssc32UsbServoController to be symmetric and with the "routable" detach.  It's backwards compatible although the typed detach not enforced by the interface..   (more cleaning some other day)

I got rid of a type specific isAttachedServoControl  .. because I checked the hardware and it only really supports Servos - it seemed overkill.

This board is pretty simple - its designed only to support Servos, not continuous dc motors or steppers ...

But the code pattern gives it flexibility to grow, while still providing a very simple interface for the user.  I think it might have PinArrayControl capabilities ..  will need to investiage further.