Chapter 19: Integration Lab: Building a Complete Robot Stack
Lesson 4: Simple Autonomy Demo (rule-based)
In this lab-style lesson we build a mathematically grounded, yet implementable, rule-based autonomy loop for a simple mobile robot. We treat the high-level autonomy as a piecewise-defined control law acting on sensor measurements and show how it can be realized as a finite-state logic system on top of familiar linear control primitives. We conclude with small implementations in Python, C++, Java, and MATLAB/Simulink that concretize the theory.
1. Conceptual Overview of Rule-Based Autonomy
A rule-based autonomous controller maps sensor measurements directly to actions using explicitly specified logic such as if–then–else rules. In contrast to path planners and optimization-based model predictive controllers, a rule-based controller is often memoryless (or has only a small discrete memory such as a mode/state flag) and is therefore easy to implement on embedded systems.
Denote by \( y_k \) the vector of sensor measurements at discrete time step \( k \) (e.g., distances from range sensors) and by \( u_k \) the control input (e.g., wheel velocity commands). A rule-based policy is a mapping
\[ \pi : \mathbb{R}^m \to \mathbb{R}^p, \quad u_k = \pi(y_k), \]
where \( \pi \) is typically defined piecewise on regions of the measurement space. For regions \( R_i \subset \mathbb{R}^m \), \( i = 1, \dots, M \), that form a partition of the measurement space, we can write
\[ \pi(y) = \sum_{i=1}^M u^{(i)} \mathbf{1}_{R_i}(y), \]
where \( u^{(i)} \) is the constant (or simple linear) action associated with region \( R_i \) and \( \mathbf{1}_{R_i} \) is the indicator function of that region. Each rule can be read informally as:
“If the sensor vector \( y \) falls in region \( R_i \), then apply control \( u^{(i)} \).”
At system level, these rules live inside the familiar Sense–Think–Act loop:
flowchart TD
S["Sensors (ranges, bump, imu)"] --> P["Preprocess / filter measurements"]
P --> R["Evaluate logical rules on measurements"]
R --> C["Compute command (v, omega)"]
C --> A["Actuators (motors, drivers)"]
A --> W["Robot moves in environment"]
W --> S
This lesson focuses on how to design these rules so that the robot realizes a simple autonomous task (e.g., obstacle avoidance and wall-following) and how to reason about the resulting behavior using basic discrete-time control theory.
2. Simple 1D Distance-Keeping Model
To keep the math transparent, we first study a one-dimensional abstraction: a robot moves along a line toward a wall and we want it to stop or slow down so that its distance to the wall never drops below a safe distance \( d_{\text{safe}} > 0 \).
Let \( x_k \) denote the robot position at time \( k \) (larger \( x_k \) means closer to the wall) and let \( u_k \) be the scalar command velocity. Approximating the robot motion as a discrete-time integrator with sampling period \( T > 0 \), we write
\[ x_{k+1} = x_k + T u_k. \]
If the wall is fixed at position \( x_{\text{wall}} \), then the distance between robot and wall at step \( k \) is
\[ d_k = x_{\text{wall}} - x_k. \]
The safety requirement is that the distance never becomes smaller than the threshold:
\[ d_k \ge d_{\text{safe}} \quad \text{for all } k \ge 0. \]
Using the discrete-time model we obtain the closed-loop dynamics of the distance. Because \( x_{k+1} = x_k + T u_k \), we have
\[ d_{k+1} = x_{\text{wall}} - x_{k+1} = x_{\text{wall}} - x_k - T u_k = d_k - T u_k. \]
Thus, specifying a rule that computes \( u_k \) from the current distance \( d_k \) determines the evolution of \( d_k \). The key question becomes: Can we design simple rules that make the set \( \{ d \mid d \ge d_{\text{safe}} \} \) invariant?
3. A Piecewise Linear Rule and Safety Invariance
Consider the following rule that combines a proportional controller with a hard stop very close to the wall:
\[ u_k = \begin{cases} k_p \bigl(d_k - d_{\text{safe}}\bigr), & d_k \ge d_{\text{safe}},\\[4pt] 0, & d_k < d_{\text{safe}}, \end{cases} \]
where \( k_p > 0 \) is a proportional gain. When the robot is far from the wall \( (d_k \gg d_{\text{safe}}) \), the velocity is large; as the robot approaches the wall, the velocity decreases linearly, and once the distance is below the safe threshold, the rule commands zero velocity.
Substituting this rule into the distance dynamics for the case \( d_k \ge d_{\text{safe}} \) yields
\[ d_{k+1} = d_k - T k_p \bigl(d_k - d_{\text{safe}}\bigr). \]
Let \( e_k = d_k - d_{\text{safe}} \) be the distance error with respect to the safe threshold. Then
\[ e_{k+1} = d_{k+1} - d_{\text{safe}} = d_k - T k_p(d_k - d_{\text{safe}}) - d_{\text{safe}} = \bigl(1 - T k_p\bigr) e_k. \]
This is a scalar linear system. The following proposition shows that the rule enforces safety if the step size and gain satisfy a simple inequality.
Proposition (Forward invariance of the safe set).
Suppose \( 0 < T k_p \le 1 \) and \( d_0 \ge d_{\text{safe}} \). Then for the rule above, the safe set \( \mathcal{S} = \{ d \mid d \ge d_{\text{safe}} \} \) is forward invariant, i.e., \( d_k \in \mathcal{S} \) for all \( k \ge 0 \).
Proof.
Because \( d_0 \ge d_{\text{safe}} \), \( e_0 = d_0 - d_{\text{safe}} \ge 0 \). Assume that for some \( k \ge 0 \) we have \( e_k \ge 0 \). Then by the update equation
\[ e_{k+1} = \bigl(1 - T k_p\bigr) e_k. \]
Under the condition \( 0 \le 1 - T k_p \le 1 \), the factor \( 1 - T k_p \) is nonnegative. Thus \( e_{k+1} \ge 0 \) whenever \( e_k \ge 0 \). By induction this implies \( e_k \ge 0 \) for all \( k \ge 0 \), and therefore \( d_k = e_k + d_{\text{safe}} \ge d_{\text{safe}} \) for all \( k \). Hence the safe set is forward invariant. \(\square\)
This calculation illustrates an important idea: even a simple rule-based controller can often be viewed as a hybrid system whose behavior on each region is governed by familiar linear dynamics and whose switching conditions are the logical rules.
4. From Rules to a Finite-State Behavior Machine
Real robots rarely operate in exactly one mode; instead, we often describe their autonomy as a finite-state machine (FSM) with modes such as “explore”, “avoid obstacle”, and “follow wall”. Each mode uses its own control law (often linear or linearized), and simple conditions trigger transitions between modes.
For a differential-drive robot with three range measurements \( y_k = (d_{f,k}, d_{\ell,k}, d_{r,k}) \) (front, left, right), a typical rule-based autonomy for corridor navigation is:
- State 1: Explore — move forward with constant velocity if the front is clear.
- State 2: Avoid — if the front distance is small, rotate in place until an opening is found.
- State 3: FollowRightWall — keep a roughly constant right distance by adjusting angular velocity.
The figure below shows the high-level FSM, where each node corresponds to a mode with its own low-level control law.
stateDiagram-v2
[*] --> Explore
Explore --> Avoid : "front_close"
Explore --> FollowRightWall : "right_detected"
Avoid --> Explore : "front_clear"
Avoid --> FollowRightWall : "right_detected"
FollowRightWall --> Avoid : "front_close"
FollowRightWall --> Explore : "no_wall_detected"
In code, these transitions are implemented with nested
if structures or a small state variable. Each state
corresponds to a rule set \( \pi^{(s)} \), and the
overall closed-loop dynamics are those of a switching system whose mode
is chosen by logical predicates on the measurements.
5. Example Rule Set for a Differential-Drive Robot
We now specify a concrete rule set for the corridor navigation task. Denote by \( d_{f,k} \), \( d_{\ell,k} \), and \( d_{r,k} \) the front, left, and right distances at time step \( k \). Let the control input be the pair \( u_k = (v_k, \omega_k) \), where \( v_k \) is the forward velocity command and \( \omega_k \) is the angular velocity command.
Choose positive thresholds \( d_{\text{front}}^{\text{safe}} \) and \( d_{\text{right}}^{\text{ref}} \), and gains \( k_v, k_{\omega} > 0 \). A simple rule set is:
\[ (v_k, \omega_k) = \begin{cases} (v_{\text{cruise}}, 0), & d_{f,k} \ge d_{\text{front}}^{\text{safe}} \text{ and } d_{r,k} \text{ not measured},\\[4pt] (0, \omega_{\text{turn}}), & d_{f,k} < d_{\text{front}}^{\text{safe}},\\[4pt] \bigl(v_{\text{cruise}}, k_{\omega}(d_{r,k} - d_{\text{right}}^{\text{ref}})\bigr), & d_{f,k} \ge d_{\text{front}}^{\text{safe}} \text{ and } d_{r,k} \text{ measured}, \end{cases} \]
where:
- \( v_{\text{cruise}} > 0 \) is a nominal forward speed in free space.
- \( \omega_{\text{turn}} > 0 \) is a constant angular rate for turning in place.
- In the third branch the robot follows a right wall by steering with a proportional law on the wall distance error \( d_{r,k} - d_{\text{right}}^{\text{ref}} \).
In this example, the continuous dynamics (e.g., the mapping from \( (v_k,\omega_k) \) to the robot pose) are handled by lower-level controllers and kinematics (which you will study in a later course), while this lesson focuses on how the high-level logic structures those continuous controllers.
6. Python Implementation Sketch (Rule Evaluation Node)
In Python, a typical robotics workflow uses ROS 2 via
rclpy. The snippet below shows a minimal structure of a
node that subscribes to range data, evaluates the rule set, and
publishes velocity commands. The focus is on the rule logic, not on ROS
boilerplate.
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Range
from geometry_msgs.msg import Twist
class SimpleRuleBasedController(Node):
def __init__(self):
super().__init__('simple_rule_based_controller')
# Parameters
self.d_front_safe = 0.5 # [m]
self.d_right_ref = 0.6 # [m]
self.v_cruise = 0.2 # [m/s]
self.omega_turn = 0.6 # [rad/s]
self.k_omega = 1.0 # proportional gain
# Internal measurements
self.d_front = None
self.d_right = None
# Subscriptions and publisher
self.create_subscription(
Range, '/front_range', self.front_callback, 10)
self.create_subscription(
Range, '/right_range', self.right_callback, 10)
self.cmd_pub = self.create_publisher(
Twist, '/cmd_vel', 10)
# Control loop timer
self.create_timer(0.05, self.control_loop) # 20 Hz
def front_callback(self, msg: Range):
self.d_front = msg.range
def right_callback(self, msg: Range):
self.d_right = msg.range
def control_loop(self):
# Only act when we have at least the front measurement
if self.d_front is None:
return
v = 0.0
omega = 0.0
# Rule 1: if front is too close, stop and turn
if self.d_front < self.d_front_safe:
v = 0.0
omega = self.omega_turn
# Rule 2: if front is clear and we have a right wall, follow it
elif self.d_right is not None:
v = self.v_cruise
error_right = self.d_right - self.d_right_ref
omega = self.k_omega * error_right
# Rule 3: otherwise, just cruise forward
else:
v = self.v_cruise
omega = 0.0
cmd = Twist()
cmd.linear.x = float(v)
cmd.angular.z = float(omega)
self.cmd_pub.publish(cmd)
def main(args=None):
rclpy.init(args=args)
node = SimpleRuleBasedController()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
The if structure implements the three-region rule set.
Provided the low-level motor drivers track the commanded velocities
accurately and the sampling time is small enough, the discrete-time
analysis of Sections 2–3 provides a first approximation of the closed
loop behavior.
7. C++ Implementation Sketch (ROS 2 Style)
In C++, the same logic can be implemented within a ROS 2 node using
rclcpp. Only the core structure is shown; error checking
and full initialization are omitted for brevity.
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/range.hpp>
#include <geometry_msgs/msg/twist.hpp>
class SimpleRuleBasedController : public rclcpp::Node {
public:
SimpleRuleBasedController()
: Node("simple_rule_based_controller"),
d_front_(std::numeric_limits<double>::quiet_NaN()),
d_right_(std::numeric_limits<double>::quiet_NaN())
{
d_front_safe_ = 0.5;
d_right_ref_ = 0.6;
v_cruise_ = 0.2;
omega_turn_ = 0.6;
k_omega_ = 1.0;
sub_front_ = this->create_subscription<sensor_msgs::msg::Range>(
"/front_range", 10,
std::bind(&SimpleRuleBasedController::frontCallback, this, std::placeholders::_1));
sub_right_ = this->create_subscription<sensor_msgs::msg::Range>(
"/right_range", 10,
std::bind(&SimpleRuleBasedController::rightCallback, this, std::placeholders::_1));
pub_cmd_ = this->create_publisher<geometry_msgs::msg::Twist>("/cmd_vel", 10);
timer_ = this->create_wall_timer(
std::chrono::milliseconds(50),
std::bind(&SimpleRuleBasedController::controlLoop, this));
}
private:
void frontCallback(const sensor_msgs::msg::Range::SharedPtr msg)
{
d_front_ = msg->range;
}
void rightCallback(const sensor_msgs::msg::Range::SharedPtr msg)
{
d_right_ = msg->range;
}
void controlLoop()
{
if (!std::isfinite(d_front_)) {
return;
}
double v = 0.0;
double omega = 0.0;
if (d_front_ < d_front_safe_) {
v = 0.0;
omega = omega_turn_;
} else if (std::isfinite(d_right_)) {
v = v_cruise_;
double error_right = d_right_ - d_right_ref_;
omega = k_omega_ * error_right;
} else {
v = v_cruise_;
omega = 0.0;
}
geometry_msgs::msg::Twist cmd;
cmd.linear.x = v;
cmd.angular.z = omega;
pub_cmd_->publish(cmd);
}
// Parameters
double d_front_safe_;
double d_right_ref_;
double v_cruise_;
double omega_turn_;
double k_omega_;
// Measurements
double d_front_;
double d_right_;
// ROS interfaces
rclcpp::Subscription<sensor_msgs::msg::Range>::SharedPtr sub_front_;
rclcpp::Subscription<sensor_msgs::msg::Range>::SharedPtr sub_right_;
rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr pub_cmd_;
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char ** argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<SimpleRuleBasedController>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
The logic mirrors the Python version. Because C++ is often used in performance-critical robot stacks, clarity in rule specification is crucial for debugging and safety analysis.
8. Java Implementation Sketch (Generic Robot Interface)
Java is widely used in educational and competition robotics (e.g., FIRST robotics via WPILib) and can interface with robots through a hardware abstraction layer. The example below illustrates how the same rule set can be implemented using a simple Java interface with polling.
public interface RangeSensors {
double getFront();
Double getRight(); // may be null if not available
}
public interface MobileBase {
void setVelocity(double v, double omega);
}
public class RuleBasedAutonomy implements Runnable {
private final RangeSensors sensors;
private final MobileBase base;
private final double dFrontSafe;
private final double dRightRef;
private final double vCruise;
private final double omegaTurn;
private final double kOmega;
private final long periodMillis;
public RuleBasedAutonomy(RangeSensors sensors,
MobileBase base,
long periodMillis) {
this.sensors = sensors;
this.base = base;
this.periodMillis = periodMillis;
this.dFrontSafe = 0.5;
this.dRightRef = 0.6;
this.vCruise = 0.2;
this.omegaTurn = 0.6;
this.kOmega = 1.0;
}
@Override
public void run() {
while (true) {
double dFront = sensors.getFront();
Double dRightObj = sensors.getRight();
boolean haveRight = (dRightObj != null);
double v = 0.0;
double omega = 0.0;
if (dFront < dFrontSafe) {
v = 0.0;
omega = omegaTurn;
} else if (haveRight) {
double dRight = dRightObj.doubleValue();
v = vCruise;
double errorRight = dRight - dRightRef;
omega = kOmega * errorRight;
} else {
v = vCruise;
omega = 0.0;
}
base.setVelocity(v, omega);
try {
Thread.sleep(periodMillis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
}
Here, the same mathematical rule set is expressed using Java control
structures. A real system would plug in hardware-specific
implementations of RangeSensors and
MobileBase.
9. MATLAB/Simulink Implementation Sketch
MATLAB is well suited to simulate discrete-time rule-based controllers before deploying them on actual robots. The following script simulates the one-dimensional distance-keeping rule from Section 3.
% Parameters
T = 0.05; % sampling period [s]
k_p = 0.8; % proportional gain
d_safe = 0.4; % safe distance [m]
N = 200; % number of steps
d = zeros(1, N+1); % distance trajectory
u = zeros(1, N); % control input
% Initial condition (safe)
d(1) = 1.2;
for k = 1:N
if d(k) >= d_safe
u(k) = k_p * (d(k) - d_safe);
else
u(k) = 0.0;
end
d(k+1) = d(k) - T * u(k);
end
% Plot results
k = 0:N;
figure; subplot(2,1,1);
plot(k*T, d);
hold on; yline(d_safe, '--');
xlabel('time [s]'); ylabel('distance d_k [m]');
legend('d_k', 'd_{safe}', 'Location', 'best');
grid on;
subplot(2,1,2);
stairs(k(1:end-1)*T, u);
xlabel('time [s]'); ylabel('velocity command u_k [m/s]');
grid on;
In Simulink, the same logic can be modeled using a discrete-time integrator for \( d_k \) and a MATLAB Function block or Switch blocks that encode the rules. This allows you to connect the rule-based autonomy to more detailed robot dynamics models while still reasoning about invariance using the discrete-time equations.
10. Problems and Solutions
Problem 1 (Safety with a Saturated Rule). Consider the 1D distance dynamics \( d_{k+1} = d_k - T u_k \) with the rule
\[ u_k = \begin{cases} u_{\max}, & d_k \ge d_{\text{far}},\\[4pt] k_p(d_k - d_{\text{safe}}), & d_{\text{safe}} \le d_k < d_{\text{far}},\\[4pt] 0, & d_k < d_{\text{safe}}, \end{cases} \]
with \( u_{\max} > 0 \), \( k_p > 0 \), and \( d_{\text{far}} > d_{\text{safe}} > 0 \). Give a sufficient condition on \( T \) and \( u_{\max} \) that guarantees \( d_k \ge d_{\text{safe}} \) for all \( k \) whenever \( d_0 \ge d_{\text{safe}} \).
Solution.
The potential danger is that in the saturated region \( d_k \ge d_{\text{far}} \), the step \( T u_{\max} \) might be so large that the distance jumps from above \( d_{\text{far}} \) to below \( d_{\text{safe}} \) in one step. To avoid this, it is sufficient to require
\[ T u_{\max} \le d_{\text{far}} - d_{\text{safe}}. \]
Indeed, if \( d_k \ge d_{\text{far}} \), then \( u_k = u_{\max} \) and \( d_{k+1} = d_k - T u_{\max} \). The worst case is the smallest admissible \( d_k = d_{\text{far}} \), for which
\[ d_{k+1} \ge d_{\text{far}} - T u_{\max} \ge d_{\text{far}} - (d_{\text{far}} - d_{\text{safe}}) = d_{\text{safe}}. \]
Once \( d_k \in [d_{\text{safe}}, d_{\text{far}}) \), the proportional rule of Problem 3 ensures forward invariance of \( d_{\text{safe}} \) if \( 0 < T k_p \le 1 \), as shown in Section 3. Thus the condition above is sufficient.
Problem 2 (Invariance Revisited). For the two-region rule
\[ u_k = \begin{cases} k_p(d_k - d_{\text{safe}}), & d_k \ge d_{\text{safe}},\\[4pt] 0, & d_k < d_{\text{safe}}, \end{cases} \]
show again that the safe set \( \mathcal{S} = \{ d \mid d \ge d_{\text{safe}} \} \) is invariant if \( 0 < T k_p \le 1 \), but now using the concept of set invariance directly instead of error variables.
Solution.
Suppose \( d_k \in \mathcal{S} \); then \( d_k \ge d_{\text{safe}} \) and the first branch of the rule applies: \( d_{k+1} = d_k - T k_p(d_k - d_{\text{safe}}) \). We want to prove that \( d_{k+1} \ge d_{\text{safe}} \). Rearranging gives
\[ d_{k+1} - d_{\text{safe}} = (1 - T k_p)(d_k - d_{\text{safe}}). \]
Because \( d_k - d_{\text{safe}} \ge 0 \) and \( 0 \le 1 - T k_p \le 1 \), the right-hand side is nonnegative, which implies \( d_{k+1} \ge d_{\text{safe}} \). Thus \( d_{k+1} \in \mathcal{S} \), and \( \mathcal{S} \) is forward invariant.
Problem 3 (Rule-Based Wall Following Gain Selection). In the wall-following branch of the rule in Section 5, the angular velocity is \( \omega_k = k_{\omega}(d_{r,k} - d_{\text{right}}^{\text{ref}}) \). Suppose that the inner loop from angular velocity command to wall distance behaves approximately as a first-order discrete system
\[ d_{r,k+1} - d_{\text{right}}^{\text{ref}} = (1 - \alpha)\bigl(d_{r,k} - d_{\text{right}}^{\text{ref}}\bigr) - \beta \omega_k, \]
with constants \( \alpha, \beta > 0 \). Insert the rule-based law and find a condition on \( k_{\omega} \) such that the error \( e_k = d_{r,k} - d_{\text{right}}^{\text{ref}} \) is asymptotically stable (in the linear sense).
Solution.
Substituting \( \omega_k = k_{\omega} e_k \) into the dynamics yields
\[ e_{k+1} = (1 - \alpha)e_k - \beta k_{\omega} e_k = \bigl(1 - \alpha - \beta k_{\omega}\bigr) e_k. \]
Asymptotic stability of the scalar linear system \( e_{k+1} = \lambda e_k \) requires \( |\lambda| < 1 \), i.e.
\[ \bigl|1 - \alpha - \beta k_{\omega}\bigr| < 1. \]
This inequality is equivalent to the double inequality \( -1 < 1 - \alpha - \beta k_{\omega} < 1 \), giving
\[ 0 < \alpha + \beta k_{\omega} < 2. \]
Solving for \( k_{\omega} \) gives
\[ -\tfrac{\alpha}{\beta} < k_{\omega} < \tfrac{2 - \alpha}{\beta}. \]
Since we require \( k_{\omega} > 0 \), the effective condition is \( 0 < k_{\omega} < (2 - \alpha)/\beta \). Any gain in this range yields an asymptotically stable linearized wall-following behavior.
Problem 4 (FSM Implementation with a State Variable).
Consider the three-mode FSM of Section 4 with states
EXPLORE, AVOID, and FOLLOW_RIGHT.
Describe how to encode this FSM using an integer state variable in a
control loop and give the pseudocode for the transition and action logic.
Solution.
We choose an integer \( s_k \in \{0,1,2\} \) to denote
the current mode at time step \( k \), with
0 for EXPLORE, 1 for
AVOID, and 2 for FOLLOW_RIGHT. At
each loop iteration, we:
-
Compute predicates
front_close,front_clear,right_detected, andno_wallfrom the sensor data. - Switch on \( s_k \) and update both the control command and the next mode \( s_{k+1} \).
Pseudocode (language-agnostic) is:
if s == EXPLORE:
if front_close:
s_next = AVOID
elif right_detected:
s_next = FOLLOW_RIGHT
else:
s_next = EXPLORE
# action
v, omega = explore_control()
elif s == AVOID:
if front_clear and right_detected:
s_next = FOLLOW_RIGHT
elif front_clear:
s_next = EXPLORE
else:
s_next = AVOID
# action
v, omega = avoid_control()
elif s == FOLLOW_RIGHT:
if front_close:
s_next = AVOID
elif no_wall:
s_next = EXPLORE
else:
s_next = FOLLOW_RIGHT
# action
v, omega = follow_right_control()
s = s_next
This structure explicitly implements the FSM of Section 4 and separates the logic for mode transitions from the continuous control actions within each mode.
11. Summary
In this lesson we constructed a simple rule-based autonomy loop for a mobile robot and analyzed it using discrete-time control concepts. Starting from a one-dimensional distance-keeping model, we showed how piecewise linear rules can guarantee invariance of a safety set under mild conditions on sampling and gains. We then lifted these ideas to a finite-state behavior machine for corridor navigation and illustrated how the same mathematical rules translate into Python, C++, Java, and MATLAB/Simulink implementations.
This style of autonomy is widely used in real systems when robustness and interpretability are more important than optimality. Later courses will connect these rule-based architectures with more advanced planning, learning, and formal verification techniques.
12. References
- Brooks, R.A. (1986). A robust layered control system for a mobile robot. IEEE Journal of Robotics and Automation, 2(1), 14–23.
- Brooks, R.A. (1991). Intelligence without representation. Artificial Intelligence, 47(1–3), 139–159.
- Antsaklis, P.J., & Nerode, A. (1998). Hybrid control systems: An introductory discussion to the special issue. IEEE Transactions on Automatic Control, 43(4), 457–460.
- Henzinger, T.A. (1996). The theory of hybrid automata. Proceedings of the 11th Annual IEEE Symposium on Logic in Computer Science (LICS), 278–292.
- Lygeros, J., Tomlin, C., & Sastry, S. (1999). Controllers for reachability specifications for hybrid systems. Automatica, 35(3), 349–370.
- Alur, R., Courcoubetis, C., Henzinger, T.A., & Ho, P.H. (1993). Hybrid automata: An algorithmic approach to the specification and verification of hybrid systems. Lecture Notes in Computer Science, 736, 209–229.
- Johansson, K.H., Egerstedt, M., Lygeros, J., & Sastry, S. (1999). On the regularization of Zeno hybrid automata. Systems & Control Letters, 38(3), 141–150.