Announcement

Collapse
No announcement yet.

Bulk Read Help for a Non Software Coach...

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bulk Read Help for a Non Software Coach...

    The kids want to try odometry this coming season. And I suspect the question "Hey Coach Z, is there a way to speed up encoder reading and ensure all the encoder counters are read at the same moment?" is coming in a month or so. I have been looking at the ConceptMotorBulkRead.java example, and have some questions:

    - I infer that since they are used to coding in Interative Opmode that the manual cache approach makes the most sense for them, right? They clear the cache. Bulk read happens. The do their computations and "thinking." Command motors and such. And then loop() finishes and waits to come around again. Right? Or is "auto" better for some reason in this case?

    - Is there anything I ought to know about coaching them to use this example in Interative opmode other than the obvious steps of moving things from the example into the right places in init(), start() and loop()?

    - Can somebody explain what is happening behind the scenes here? What is "LynxModule" doing 'in the background' or whatever? And is there any reason to think all the encoder counters are being read at all simultaneously or close to it such that the various values of Position are in phase in time? It's not even obvious to me what bulk read is doing to make team code execution times better. When do the actual reads to cache happen?

    Thanks for helping a MechE coach out!

    Coach Z

  • #2
    To understand why bulk reads are helpful for increasing control loop speed, you first have to understand how the REV hardware communicates with the SDK (it uses a different model than with Modern Robotics). The REV model is that every hardware command, (e.g. set servo position, read encoder, set DIO, etc.) is synchronous. What that means is that the control flow when issuing a hardware command (using a phone setup) is as follows:

    Code:
    --> User calls motor.setPower()
    --> SDK serializes a datagram for the setPower command and sends it out to the USB bus
    --> SDK now enters a blocking WAIT until an ACK is received from the ExH
    --> FTDI USB to UART bridge in ExH receives USB datagram, and relays it out over UART to the ExH's microcontroller.
    --> ExH deserializes the datagram and performs the setPower operation
    --> ExH sends an ACK packet over UART to the FTDI bridge
    --> FTDI receives ACK packet and relays it out to the USB bus
    --> SDK receives ACK and exits WAIT state, allowing user code to continue.
    All this can take a fair amount of time, usually about 3ms. When communicating to a slave module over the 485 bus, it's even worse, because in addition to everything outlined above, there's another relay step needed between the master and slave hubs.

    Note: a Control Hub cuts out the FTDI relay step, because the Android SOC communicates directly with the ExH microcontroller over internal UART.

    Anyway, so, assuming a phone+ExH master setup, generally a hardware command takes about 3ms. Let's consider a case where you read all 4 encoder positions, and set all 4 motor powers. That's 8 hardware calls at 3ms each, so your loop will take about 24ms per iteration, which is about 41Hz. Not bad, but certainly not great.

    What a bulk read does is allows you to read a large swatch of data with the same command in-flight time as any other hardware call. A bulk read includes all 4 motor encoder positions, so now you're down to just 5 hardware calls instead of 8 for the same thing. That means your control loop is now running at about 66Hz.

    The other beautiful thing about a bulk read is that all the encoder positions are recorded at (essentially) the exact same moment in time inside the ExH's microcontroller (instead of being offset by 3ms each as with individual commands), which is crucial for accurate pose integration with tracking wheels.

    the manual cache approach makes the most sense for them, right? They clear the cache. Bulk read happens. The do their computations and "thinking." Command motors and such. And then loop() finishes and waits to come around again
    Spot on.

    Is there anything I ought to know about coaching them to use this example in Interative opmode other than the obvious steps of moving things from the example into the right places in init(), start() and loop()?
    Not that I can think of at the moment

    When do the actual reads to cache happen?
    I don't have the source code in front of me at the moment, but going on memory: assuming MANUAL mode, the bulk read to cache happens on the first bulk-cachable hardware call (not all are) after the bulk cache was cleared by the user.

    Comment


    • #3
      Thank you that was super helpful. A few related follow on questions if you don't mind:

      - Which kinds of "reads" is bulk read good for vs doesn't work on? I understand your answers above as they relate to the encoder-counters, what about the IMU? Or the digital & analog I/O? And especially what about the I2C sensors and all their I2C specific overhead? I can see how this might apply to all of them, or just some of them. Or perhaps it speeds up all, but isn't essentially simultaneous reads for things like IMU and I2C sensors? Or... how do I want to think about these other sensor types differently, or not?

      - And clearly this isn't a vision / vuforia type discussion, right? Or... is it... ???

      - Back to just encoders and motors: with the extra RS485 delay, this seems like it defines the choice of whether the motors are plugged into Control Hub or Expansion Hub, right? It seems like ideally the odometry encoders go to the Control hub, and skip any RS485 delays. Whereas the motor encoders (and power obviously) go to the Expansion Hub. Because unless there is some reason to *read* those encoder or motor velocities, they can be left in RUN_USING_ENCODERS closed loop velocity mode and just given commanded speed/powers and the Expansion Hub does its thing closing the loop within itself. Whereas the odometry encoders are going to be read every loop, along with other sensors, and probably want to be on the faster responding Control Hub, right?

      - In previous years with two expansion hubs being the norm, the prior-now-graduated-kids would put a USB hub between the phone and the two hubs (and cameras). And this seemed to do away with master-slave differences, and it didn't look to me to matter much which hub was doing what. It seems this kind of approach isn't possible with a control-hub & expansion-hub robot, is it?

      thanks again for your time!

      Z

      Comment


      • #4
        Originally posted by zain View Post

        Which kinds of "reads" is bulk read good for vs doesn't work on?
        A bulk read returns the following data:
        • All digital inputs
        • All analog inputs
        • All encoder positions
        • All encoder velocities
        • All motor statuses (e.g. H-bridge over-temp)

        Originally posted by zain View Post

        And especially what about the I2C sensors and all their I2C specific overhead?
        I2C sensors are not bulkable, and in fact are the worst offenders of all hardware operations, as they often require more than one low-level command to complete.

        Originally posted by zain View Post

        And clearly this isn't a vision / vuforia type discussion, right? Or... is it... ???
        I'm not sure where you're going with that...?


        Originally posted by zain View Post

        It seems like ideally the odometry encoders go to the Control hub, and skip any RS485 delays. Whereas the motor encoders (and power obviously) go to the Expansion Hub. Because unless there is some reason to *read* those encoder or motor velocities, they can be left in RUN_USING_ENCODERS closed loop velocity mode and just given commanded speed/powers and the Expansion Hub does its thing closing the loop within itself. Whereas the odometry encoders are going to be read every loop, along with other sensors, and probably want to be on the faster responding Control Hub, right?
        Well, yes, but also potentially no. Because now you're incurring the RS485 relay delay 4 times per loop (for the motor set powers) instead of just once (for the bulk read)....

        Originally posted by zain View Post
        In previous years with two expansion hubs being the norm, the prior-now-graduated-kids would put a USB hub between the phone and the two hubs (and cameras). And this seemed to do away with master-slave differences, and it didn't look to me to matter much which hub was doing what. It seems this kind of approach isn't possible with a control-hub & expansion-hub robot, is it?
        So with the Control Hub, since the FTDI relay step is cut out, communicating with an ExH over 485 is sorta kinda equivalent to an ExH directly attached to a phone over USB. But you could also connect the ExH to one of the Control Hub's USB ports. The performance increase would probably be marginal over 485 on the CH, though. And you reduce reliability because you're reintroducing USB into the system. (Remember, the Control Hub talks to the embedded ExH over internal UART).

        However, the one benefit you get with connecting the ExH over USB to the CH (or, both ExHs over USB to the phone) is that then, you can actually see a performance increase with multi-threading. There is a global bus lock for each master module, so multithreading when using a 485 slave gets you nothing other than thread contention which is bad for many reasons. But when you use a dual-master setup, you technically can have a dedicated hardware thread for each module. E.g. you could have one thread that does nothing but poll your tracking wheel encoders in a tight loop from the USB attached ExH, and then have your main control thread controlling the motors on the CH embedded ExH simply working off the positioning calculations provided from the other thread. I will warn you, though, that when multithreading - especially if you don't have much experience with concurrency - "there be dragons there"...

        Comment


        • #5
          Super helpful. Thanks!

          And yeah, I haven't done anything multi threaded with these kids as yet. Since it always seemed to me that down in the hardware stuff was very synchronous and blocking, I figured there'd be no gain for all the headaches. Except possibly when doing vision/vuforia things (sorry for that poorly constructed question there...). And the one team of graduated seniors who did vision stuff their last couple seasons didn't end up using multi-threaded code either, despite having a hardware setup that might have benefitted.

          I have generally focused the kids on using iterative opmode only with no separately spawned threads, so the concepts of state machines and event driven programming design are at the fore. And because I am no kind of coder anyway.... lolz.

          Comment

          Working...
          X