The bump sensor, cliff detection, and wall detection were all implemented with plain IR LED emitter/receiver pairs, and very carefully shaped plastic enclosures so that the sensors provided a binary signal (floor vs. cliff, wall present/absent, etc.) that would hold up for the millions of cycles the machines racked up. This 'filtering in the sensor' simplified the inputs to the 8 bit 8051 microcontroller, and lowered the cost to a couple of cents for each detector.
The cleaning head used the torque of the brush motor to actively control the height of the cleaning head as the machine moved from carpet to hard floors and back. That's the 'core trick' that let the Roomba clean well on multiple surfaces with about 15 watts of brush power. Details in the now-expired patent -- https://patents.google.com/patent/US6883201B2/en.
Dave Nugent came up with the original torque lift idea, and then we worked it into the 'floating pulley' approach used in the final design. It seems obvious now, but at the time this was a radically different approach to mobile cleaning. Everyone else (Electrolux, Karcher, etc.) tried to make a miniature vacuum, but that burned too much power for a mobile system.
Joe Jones (project originator and team physicist) wrote a book about the original team and our development process that I recommend: https://dancingwithroomba.com/
Minor tech notes: Phil Mass did the original programming on the first generation Roomba in C on the aforementioned Winbond 8051 microcontroller. I think it had 256 bytes (!!!) of RAM and 4K of ROM.
The code was burned into the chip at its creation (no onboard flash!) so it had to be right the first time. For the 2nd generation system they ported the behavior code to the internal LISP dialect in use at iRobot.
It was a wild ride. I'm both proud of what we did, and dismayed (but not surprised) at what happened afterwards.