I would like to use an MCLPoseProvider taking range values from multiple ultrasonic sensors.

I understand that the MCLPoseProvider uses the getRangeValues method of RangeScanner to get a RangeReadings object. The RangeReadings object is a list a RangeReading objects (an object that stores a relative heading and a distance). The MCLPoseProvider then uses these RangeReading objects to compute the robots pose.

Am I right up till now?

To use several different ultrasonic sensors, it would seem I need to create my own RangeScanner implementation.

I'm having trouble understanding the relationship between the RangeScanner and RangeFinder. One thing that confuses me is the getRangeFinder method in the RangeScanner interface. When is this method used and for what? To implement this method, I am essentially being forced to use a RangeFinder object (and only one). I don't know how to do this while supporting multiple sensors.

Also, the setAngles method is confusing. When is this method used and for what? Does my implementation of RangeScanner support getting the range of any set of angles defined by the setAngles method?

Sorry I can't help with your specific questions. What I suggest you do is spend some time studying the MCL code to understand how it uses the various interfaces. The various robotics interfaces and classes were designed to be general purpose and to be used in a variety of situations and a potentially wide range of hardware. Unfortunately doing this (especially without actually testing the design with that wide range of situations of hardware) can be very difficult, it can be very hard to design very generic interfaces. So for instance although it may be nice to be able to obtain a RangeFinder it may be that (as in your case) it does not make a lot of sense, but remember if the MCL code never calls this method (and it probably does not), you can simply return null. Similarly I suspect that the designer had in mid a rotating scanner with this design so allowing the caller to specify at what angles to take readings seems like a good one, but it actually makes the interface less generic. Again have a look at the MCL code it may not ever call this method, or if it does it may be a hint as to how many Ultrasonic sensors you will need as the MCL code may not work well if you supply too few readings.