模拟一个机器人在一个2D世界中巡航,世界中有5个独特可识别的地标,它们的位置未知,机器人配备了能够测量到这些地标距离和角度的传感器,但每个测量都受到噪声的影响(Matlab代码实现)

  💥💥💞💞欢迎来到本博客❤️❤️💥💥

🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。

⛳️座右铭:行百里者,半于九十。

📋📋📋本文目录如下:🎁🎁🎁

目录

 ⛳️赠与读者

💥1 概述

📚2 运行结果

🎉3 参考文献

🌈4 Matlab代码实现


 ⛳️赠与读者

👨‍💻做科研,涉及到一个深在的思想系统,需要科研者逻辑缜密,踏实认真,但是不能只是努力,很多时候借力比努力更重要,然后还要有仰望星空的创新点和启发点。当哲学课上老师问你什么是科学,什么是电的时候,不要觉得这些问题搞笑。哲学是科学之母,哲学就是追究终极问题,寻找那些不言自明只有小孩子会问的但是你却回答不出来的问题。建议读者按目录次序逐一浏览,免得骤然跌入幽暗的迷宫找不到来时的路,它不足为你揭示全部问题的答案,但若能让人胸中升起一朵朵疑云,也未尝不会酿成晚霞斑斓的别一番景致,万一它居然给你带来了一场精神世界的苦雨,那就借机洗刷一下原来存放在那儿的“躺平”上的尘埃吧。

     或许,雨过云收,神驰的天地更清朗.......🔎🔎🔎

💥1 概述

本文模拟了一个机器人在一个2D世界中巡航,世界中有5个独特可识别的地标,它们的位置未知。机器人配备了能够测量到这些地标距离和角度的传感器,但每个测量都受到噪声的影响。

这个实现基于Thrun等人的FastSLAM 1.0算法,算法通过粒子滤波器表示机器人的位置。每个粒子包含5个完全独立的扩展卡尔曼滤波器,每个滤波器负责跟踪一个地标。每次地标测量之后,根据最新地标测量与其预期的接近程度,给每个粒子评分。然后重新采样粒子,使得得分高的粒子可能会被复制,得分低的粒子可能会被删除。

 2D 世界中的机器人巡航模拟

 概述
本模拟文档描述了一个机器人在一个二维世界中巡航的过程。机器人在一个定义好的世界中移动,世界中有五个独特且可识别的地标,这些地标的位置对机器人来说是未知的。机器人配备了能够测量到这些地标的距离和角度的传感器,但每个测量都受到噪声的影响。此文档包括模拟环境的设定、传感器测量的实现及其结果的可视化。

世界设定
- **世界尺寸**:定义为100x100的二维空间。
- **地标**:五个独特的地标,位置未知但在模拟中预定义。
- **机器人初始位置**:在模拟开始时,机器人的位置在世界的中心,即坐标(50, 50)。

机器人和传感器
- **机器人位置**:机器人在二维空间中的当前坐标。
- **传感器噪声**:测量过程中加入的高斯噪声,标准差设定为1.0。角度测量噪声为距离噪声的10%。

 代码实现

```python
import numpy as np
import matplotlib.pyplot as plt

# 设定世界参数
world_size = 100  # 世界的大小为100x100
landmarks = np.array([[20, 30], [80, 80], [50, 10], [20, 80], [80, 20]])  # 地标的位置

# 设定机器人参数
robot_pos = np.array([50, 50])  # 机器人的初始位置
sensor_noise_std = 1.0  # 传感器噪声的标准差

def sense(robot_pos, landmarks, sensor_noise_std):
    """模拟机器人传感器对地标的测量"""
    measurements = []
    for landmark in landmarks:
        distance = np.linalg.norm(landmark - robot_pos)
        angle = np.arctan2(landmark[1] - robot_pos[1], landmark[0] - robot_pos[0])
        
        # 加入噪声
        distance += np.random.normal(0, sensor_noise_std)
        angle += np.random.normal(0, sensor_noise_std * 0.1)
        
        measurements.append((distance, angle))
    return measurements

# 进行一次传感器测量
measurements = sense(robot_pos, landmarks, sensor_noise_std)

# 打印测量结果
print("测量结果(距离, 角度):")
for i, measurement in enumerate(measurements):
    print(f"地标 {i+1}: {measurement}")

# 可视化世界、地标和机器人的位置
plt.figure(figsize=(8, 8))
plt.xlim(0, world_size)
plt.ylim(0, world_size)
plt.scatter(landmarks[:, 0], landmarks[:, 1], color='red', label='Landmarks')
plt.scatter(robot_pos[0], robot_pos[1], color='blue', label='Robot')

# 画出测量线
for i, (distance, angle) in enumerate(measurements):
    lx, ly = robot_pos[0] + distance * np.cos(angle), robot_pos[1] + distance * np.sin(angle)
    plt.plot([robot_pos[0], lx], [robot_pos[1], ly], label=f'Measurement {i+1}')

plt.legend()
plt.grid()
plt.show()


 

主要步骤
1. **设定世界参数**:定义二维世界的尺寸和地标的位置。
2. **设定机器人参数**:定义机器人的初始位置和传感器的噪声水平。
3. **传感器测量**:通过 `sense` 函数模拟机器人对地标的测量,加入噪声。
4. **测量结果输出**:打印出每个地标的测量结果(包括距离和角度)。
5. **结果可视化**:使用 `matplotlib` 可视化世界、地标和机器人的位置,以及测量的结果。

扩展
可以根据需要进一步扩展这个模拟,例如:
- 添加机器人运动模型,模拟机器人在二维世界中的移动。
- 引入更多类型的噪声(如系统噪声)。
- 改变测量频率,以模拟不同传感器刷新率。

通过这些扩展,可以更加真实地模拟机器人在未知环境中的导航和定位过程。

📚2 运行结果

部分代码:


% The number of timesteps for the simulation
timesteps = 200;

% The maximum distance from which our sensor can sense a landmark
max_read_distance = 1.5;

% The actual positions of the landmarks (each column is a separate landmark)
real_landmarks = [1.0,  2.0,  0.0, 0.0, 1.0;     % x
                  3.0,  2.5   3.4, 1.5, 3.5;     % y
                  0.0,  0.0   0.0, 0.0, 0.0];    % Nothing

% The initial starting position of the robot
real_position = [0.0;      % x
                 -1.0;     % y
                 pi/3.0];  % rotation

% The movement command given tot he robot at each timestep                 
movement_command = [.05;     % Distance
                    .01];    % Rotation
                    
% The Gaussian variance of the movement commands
movement_variance = [.1;   % Distance
                     .05]; % Rotation
M = [movement_variance(1), 0.0;
     0.0, movement_variance(2)];

% The Gaussian variance of our sensor readings
measurement_variance = [0.1;    % Distance
                        0.01;   % Angle
                        .0001]; % Landmark Identity
R = [measurement_variance(1), 0.0, 0.0;
     0.0, measurement_variance(2), 0.0;
     0.0, 0.0, measurement_variance(3)];

% Create the particles and initialize them all to be in the same initial
% position. 
particles = [];
num_particles = 100;
for i = 1:num_particles
  particles(i).w = 1.0/num_particles;
  particles(i).position = real_position;
  for lIdx=1:size(real_landmarks,2)
    particles(i).landmarks(lIdx).seen = false;
  end
end

pos_history = [];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SIMULATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

for timestep = 1:timesteps
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Move the actual robot
  real_position = moveParticle(real_position, movement_command, movement_variance);
  pos_history = [pos_history, real_position];

  % Move the actual particles
  for pIdx = 1:num_particles
    particles(pIdx).position = moveParticle( ...
        particles(pIdx).position, movement_command, movement_variance);
     particles(pIdx).position(3) = real_position(3);
  end

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Try to take a reading from each landmark
  doResample = false;
  for lIdx = 1:size(real_landmarks,2)
    real_landmark = real_landmarks(:, lIdx);

    % Take a real (noisy) measurement from the robot to the landmark
    [z_real, G] = getMeasurement(real_position, real_landmark, measurement_variance);
    read_distance(lIdx) = z_real(1);
    read_angle(lIdx)    = z_real(2);

    % If the landmark is close enough, then we can spot it
    if(read_distance(lIdx) < max_read_distance)
      doResample = true;

      for pIdx = 1:num_particles

        if(particles(pIdx).landmarks(lIdx).seen == false)

          % If we have never seen this landmark, then we need to initialize it.
          % We'll just use whatever first reading we recieved.
          particles(pIdx).landmarks(lIdx).pos = [particles(pIdx).position(1) + cos(read_angle(lIdx))*read_distance(lIdx);
                                                 particles(pIdx).position(2) + sin(read_angle(lIdx))*read_distance(lIdx);
                                                 0];
          % Initialize the landmark position covariance
          particles(pIdx).landmarks(lIdx).E = inv(G) * R * inv(G)';

          particles(pIdx).landmarks(lIdx).seen = true;

        else
          % Get an ideal reading to our believed landmark position (note 0 variance here).
          [z_p, Gp] = getMeasurement(particles(pIdx).position, particles(pIdx).landmarks(lIdx).pos, [0;0]);
          residual = z_real - z_p;

          %Calculate the Kalman gain
          Q = G' * particles(pIdx).landmarks(lIdx).E * G + R;
          K = particles(pIdx).landmarks(lIdx).E * G * inv(Q);

          % Mix the ideal reading, and our actual reading using the Kalman gain, and use the result
          % to predict a new landmark position
          particles(pIdx).landmarks(lIdx).pos = particles(pIdx).landmarks(lIdx).pos + K*(residual); 

          % Update the covariance of this landmark
          particles(pIdx).landmarks(lIdx).E = (eye(size(K)) - K*G')*particles(pIdx).landmarks(lIdx).E;

          % Update the weight of the particle
          particles(pIdx).w = particles(pIdx).w * norm(2*pi*Q).^(-1/2)*exp(-1/2*(residual)'*inv(Q)*(residual));
        end %else
      end %pIdx
    end %distance


  end %for landmark
  % Resample all particles based on their weights
  if(doResample)
    particles = resample(particles);
  end

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % PLOTTING
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  clf;
  hold on;

  % Plot the landmarks
  for lIdx=1:size(real_landmarks,2)
    plot(real_landmarks(1,lIdx), real_landmarks(2,lIdx), 'b*');
  end

  for lIdx = 1:size(real_landmarks,2)
    if(particles(1).landmarks(lIdx).seen)
      avg_landmark_guess =[0;0;0];
      for pIdx = 1:length(particles)
        avg_landmark_guess = avg_landmark_guess + particles(pIdx).landmarks(lIdx).pos;
      end
      avg_landmark_guess = avg_landmark_guess / length(particles);
      plot(avg_landmark_guess(1), avg_landmark_guess(2), 'ko');
    end
  end

  % Plot the particles
  particles_pos = [particles.position];
  plot(particles_pos(1,:), particles_pos(2,:), 'r.');

  % Plot the real robot
  plot(pos_history(1,:), pos_history(2,:), 'r');
  w = .1;
  l = .3;
  x = real_position(1);
  y = real_position(2);
  t = real_position(3);
  plot(real_position(1), real_position(2), 'mo', ...
                                           'LineWidth',1.5, ...
                                           'MarkerEdgeColor','k', ...
                                           'MarkerFaceColor',[0 1 0], ...
                                           'MarkerSize',10);

  % Show the sensor measurement as an arrow
  for lIdx=1:size(real_landmarks,2)
    real_landmark = real_landmarks(:, lIdx);
    if(read_distance(lIdx) < max_read_distance)
      line([real_position(1), real_position(1)+cos(read_angle(lIdx))*read_distance(lIdx)], ...
           [real_position(2), real_position(2)+sin(read_angle(lIdx))*read_distance(lIdx)]);
    end
  end

🎉3 参考文献

文章中一些内容引自网络,会注明出处或引用为参考文献,难免有未尽之处,如有不妥,请随时联系删除。

[1]李秀芳.面向水下机器人的水下目标检测算法研究[D].中国海洋大学[2024-06-25].

[2]王海涛.水下机器人自主导航算法的研究[D].中国海洋大学[2024-06-25].DOI:CNKI:CDMD:2.1014.367966.

🌈4 Matlab代码实现

资料获取,更多粉丝福利,MATLAB|Simulink|Python资源获取

                                                           在这里插入图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值