65.9K
CodeProject 正在变化。 阅读更多。
Home

基于污染水平的 IoT 交通控制的现实模拟框架

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (6投票s)

2016年8月8日

CPOL

19分钟阅读

viewsIcon

23021

downloadIcon

158

高级物联网二氧化碳排放模拟。

引言

如今,城市面临着诸多挑战。交通拥堵控制和污染控制是任何城市面临的两大挑战。多年来,人们一直在开发和部署各种人工智能系统和自主系统,以缓解交通拥堵并降低城市污染水平。然而,此类产品的研发过程往往非常繁琐,因为产品测试成本高昂。

模拟环境为如此大规模的解决方案部署提供了急需的灵活性。

过去的研究表明,一个地方的总体污染取决于该地及其周边地区的工业产出和交通状况。研究发现,车辆在发动机运转时停滞时会排放更多的二氧化碳。人们注意到,在红绿灯等待期间发动机运转的交叉路口污染更严重。为了减少此类交通量,当局已采用基于流量的交通信号控制,通过物理传感器或机器视觉技术监控交通流量。

然而,由于车辆类型各异,每种车辆类型都有其自身的污染特征,因此基于密度的交通控制未能降低污染水平。因此,我们需要更智能的系统,在控制交通信号灯定时器时能够真正考虑污染水平。

由于城市交通从一个交通路口连接到另一个路口,因此需要大量资源在路口的所有部分部署物理传感器,以观察交通流量、污染情况,然后做出信号灯定时决策。

我们希望通过提供一个能够轻松地将物联网与真实的城市交通和车辆流量模拟相结合的框架,来减少这个繁琐而困难的过程。物理传感器被集成到模拟环境中,以便可以在模拟模式下针对真实的城市路口测试解决方案。


因此,我们的解决方案提供:

 

  • 使用 VANET 开源模拟器进行逼真的交通模拟
  • 基于 Intel Edison 的二氧化碳传感设备
  • 基于 Mqtt 网关的传感数据与模拟环境集成
  • 基于 ThingSpeak 的网关,将数据导入云端进行进一步分析
  • 一个智能对象,将二氧化碳监测数据与模拟环境中的某个交通路口关联起来,最终控制该特定路口的交通信号灯定时。

 

这是一个高端的临时交通系统模拟,展示了随着车辆的增加,二氧化碳消耗是如何发生的。该场景融合了虚拟和真实世界的地图场景。

该模拟基于交通系统领域的深入研究。我们收集了各种考虑因素的数据,并将其分解为小区域的地图,在那里我们可以密集地对车辆的人口统计学进行分类。考虑到关键因素,例如车辆及其类型,以及它们
油耗量、车辆碳足迹的更多组成部分及其原因。在此,我们测量了车辆的二氧化碳排放量,以及不同车辆密集的区域的工作方式。

该项目是对这篇论文中提出的概念的改编和改进。

物理世界

 

物理世界由一块带有 Grove 扩展板的 Intel Edison 板组成,其中一个 MQ7 传感器连接到一个模拟端口。

 

图:带 MQ7 传感器的 Intel Edison 板

该装置测量环境中的气体,模拟值随之变化。这个 10 位精度的模拟值需要映射到实际的 CO2 值(以 PPM 为单位),映射方式如下:


方法论

  1. 使用 VanetSim(一款基于 Java 的开源 VANET 模拟器)创建逼真的城市交通模拟。
  2. 使用 Intel Edison 和 MQ7 传感器实现实时污染传感设备。
  3. 使用高质量、低延迟的 Mqtt 协议将观测到的污染水平(CO2 水平)缓解到模拟环境中。
  4. 创建交通流量与拥堵水平之间的依赖图。
  5. 根据车流量控制城市交通信号灯。
  6. 将污染水平集成到交通信号灯控制系统中。
  7. 观察交通信号灯行为随特定路口污染水平变化而变化的性能。
  8. 通过大量车辆并整合车辆在多个路口之间的移动来验证此类系统能否确保真实结果。
  9. 监测到的二氧化碳值与交通信号灯之间的相关性通过以下方程表示:

其中 400 是正常的二氧化碳值(以 PPM 为单位),ParameterValue 是模拟对象,代表通过 Intel Edison 通过 Mqtt 分配给它的实际污染(二氧化碳水平)。10 是映射路口的绿灯相位增加的因子。

 

系统设计

 

 

主要要做的是将值推送到模拟器,同时将值保存在云端。iot.eclipse.org 提供云服务,但我们希望通过将值推送到名为 ThingSpeak 的云分析服务来实现大规模区域的实时可视化。

模拟概述

 

图:开放街道地图中的航点

图:节点(车辆)在路口移动

编码

通过物联网进行二氧化碳传感和发布

var mqtt    = require('mqtt'); 
var client  = mqtt.connect('mqtt://iot.eclipse.org'); 

 

 在 Unix 系统中,可以使用 curl(命令行 URL)将数据推送到任何开放网站。从 JavaScript 中,可以访问 curl 命令,这是一个基于 Unix 的命令。然后通过调用 HTTP GET 方法将数据推送到云端。Thingspeak 使用 JavaScript ID。因此,Thingspeak 需要 HTTP 协议,我们通过 curl 命令调用 HTTP 协议。由于 Node.js 没有 HTTP 指令,我们可以通过 Node.js 访问 Unix 系统命令,使用 Unix 作为 Unix HTTP 功能将数据推送到 Thingspeak HTTP API。要执行此过程,请使用一个名为“sys”的库函数。

var sys = require('sys') 

这是一个 Unix 系统库,意味着像字数统计、ls 命令等所有 API 都可以通过“sys”库访问。

 

var exec = require('child_process').exec;

在这里,“exe”是一个进程,我们通过子进程获取一个 JavaScript 模块。在进行网络相关操作时,我们会创建一个后台进程,这样就不会阻塞主进程。Node.js 不会创建任何线程,Node.js 是一个单线程运行的系统。但问题是它无法访问 Unix 命令系统,因为那些是内核级别的命令。JS 运行一个单线程,无法从用户命令运行内核命令。因此,我们使用一个名为 child_process 的 Node 模块,它允许 Node.js 系统分叉一个子进程。如果我们能分叉一个子进程,我们就可以访问内核级别的程序,并且 ID 不会在用户级别运行。“exe”是 child_process 的一个变量。

 

function puts(error, stdout, stderr) { sys.puts(stdout) }

“puts”是一个函数,它将来自子进程的所有结果放在一起。当我们执行任何 Linux 命令(如 ls、wc 等)时,我们会得到设置结果。我们希望将其结果放在实际的命令提示符中。因此,“put”命令会将所有错误和标准输出放到当前命令中。

 

Node.js 程序有两种类型的库:

  1. 核心库
  2. 用户定义库

有些函数集是 Node.js 自带的,还有一些函数集是 Node.js 没有的。那些 Node.js 没有的函数可以通过 npm(Node 包管理器)安装。一旦我们通过运行 npm install 安装了 npm 包,我们就可以访问任何数量的库了。

var mraa=require('mraa');

“mraa”是一个库。这个 Node.js 库用于访问硬件。因为我们需要访问一个名为 GPIO 的数字引脚,所以我们使用“mraa”库。在 JavaScript 中,使用“require”函数来使用模块。有两种类型的模块:一种是核心模块,另一种是用户模块。JavaScript 支持一些核心模块,包括任何东西,例如数学库等。

//var LCD = require('jsupm_i2clcd');

//var myLCD = new LCD.Jhd1313m1(6, 0x3E, 0x62);

 

var a0=new mraa.Aio(3);

连接到模拟端口(引脚 3 (Aio(3)))的污染传感器。模拟引脚 3 用于读取来自 MQ7 传感器的车辆排放的 CO2 量。它将测量模拟值。

计算 ppm 值的公式如下。

根据公式:ppm=a*(Rs/R0)^b,

    var a=116.602;
    var b=-5.96;
    var In=4.5/3.34e+4;
    var R0=41000;
    

 

这些是默认电阻值。首先,我们从连接了污染传感器的 a0 引脚读取模拟值。然后,我们进行所有转换以获得污染值。污染值将以 ppm 为单位。CO2 水平将以 ppm 为单位测量。

 

 

    var Rs=v1/In; // Rs is resistance value calculated by v1/In where In is a normal current value.

var v2=Rs/R0; // R0 is default value where R0=41000

v2=Math.pow(v2,b); // That is (Rs/R0)^b

var ppm=179.73*v2; //The formula for calculating ppm value as ‘ppm=a*(Rs/R0)^b’

console.log("x="+val+" vo="+vo+" Rs="+Rs+" ppm"+ppm);     // The console.log used to       display the ‘x’,’vo’,’Rs’,’ppm’ values.

//myLCD.clear();

//myLCD.setCursor(0,1);

//myLCD.write(""+ppm);

//myLCD.setCursor(1,1);

//myLCD.write("Co2 in ppm");

 
if(ppm<420)

{

//myLCD.setColor(0,255,0);

}

else

{

//myLCD.setColor(255,0,0);

}

如果 ppm 值小于 420,则在显示屏上显示绿色,否则显示红色。

    ///////////// Update ThingSpeak/////////////

s="curl \"http://api.thingspeak.com/update?api_key=3ZXPXW3SPPDEC1HU&field1="+ppm+ "\"";

exec(s);

//////////////////////////////////////////

client.publish('rupam/Simulator', ""+ppm);

/// Send data to Simulator//////////

setTimeout(Loop,10000);

}

 

“curl”命令用于调用 thingspeak.com,在那里更新值。thingspeak.com/update 是一个 API 密钥,除了这个 API 密钥之外,只有一个字段是 thingspeak。在 thingspeak 通道中,我们可以推送八个传感器。因此,我们可以传递最多 8 个传感器。在我们的项目中,我们只使用一个传感器在 field1 中显示 ppm 值。

同时,我们将此值推送到模拟器。因此,我们需要使用 Mqtt 协议在一个通道中发布数据。

模拟部分

这是对开源 VANET 模拟器项目的改编,我们集成了我们的物理传感模型和嵌入式智能,以根据环境二氧化碳值控制交通信号灯。当交通在特定道路上拥堵并导致路口时,污染会增加。现在,污染水平还取决于其他几个因素,例如车辆类型(通常摩托车和卡车比汽车排放更多二氧化碳)。通常,现代交通流量不考虑这些因素,交通信号灯最多采用基于密度的控制模型,其中高密度道路获得更多优先级和较长的绿灯计时,以疏导该道路的交通。

但是,正如我们在上面详细介绍的那样,该方法并不总是能产生最优的污染控制。我们认为,当局必须采用更智能的解决方案,将二氧化碳等环境参数集成到交通控制中,而不是通过交通信号灯控制交通。

我们使用 VANET 模拟器采用逼真的城市交通场景,该模拟器不仅可以模拟交通信号灯、交叉路口,还可以模拟逼真的城市交通场景的许多重要方面,例如事故、坑洼、车间通信等。

 

我们已经了解了这个过程是如何工作的,现在重要的是了解数据和模拟是如何工作的。整个代码是用 Java 编写的。我们使用 Netbeans IDE 来编写程序。OpenStreetMap 允许加载您要处理的文件。它会生成一个 *.osn 文件供我们使用。然后将该文件上传到 VANET 模拟器中进行处理。代码的起始点如下所示。代码中的按钮用于选择我们正在做什么的精确选项。

    /*
 * VANETsim open source project - http://www.vanet-simulator.org
 * Copyright (C) 2008 - 2013  Andreas Tomandl, Florian Scheuer, Bernhard Gruber
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package vanetsim;

import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import vanetsim.localization.Messages;


public class VanetSimStarter {
	/**
	 * The main method.
	 * 
	 * @param args	command line arguments. No argument is given the simulator will start in GUI-Mode.
	 * if 3 arguments are given the simulator will start without GUI in console mode. args[0] = map path; args[1] = scenario path args[2] = time until the simulation stops 
	 * example for console mode: java -jar VanetSimStarter.jar /Users/Max_Mustermann/rgb-1.xml /Users/Max_Mustermann/rgb-1_scen.xml 50000 
	 */
	public static void main(String[] args) {
		if(args.length < 3) SwingUtilities.invokeLater(new VanetSimStart());
		else SwingUtilities.invokeLater(new ConsoleStart(args[0], args[1], args[2]));
	}

	public static void restartWithLanguage(String language){
		String[] buttons = {Messages.getString("VanetSimStarter.Yes", language), Messages.getString("VanetSimStarter.No", language)};
		if(JOptionPane.showOptionDialog(null, Messages.getString("VanetSimStarter.WarningMessage", language), "", JOptionPane.WARNING_MESSAGE, 0, null, buttons, buttons[1]) == 0){
			Messages.setLanguage(language);
			VanetSimStart.getMainFrame().dispose();
			SwingUtilities.invokeLater(new VanetSimStart());
		}	
	}
}

现在,关于 Intel Edison 中进行通信的 MQTT 部分,代码如下所示。

    var mqtt    = require('mqtt');
var client  = mqtt.connect('mqtt://iot.eclipse.org');
////////////////////
var sys = require('sys')

var exec = require('child_process').exec;
function puts(error, stdout, stderr) { sys.puts(stdout) }


var mraa=require('mraa');

//var LCD = require('jsupm_i2clcd');
//var myLCD = new LCD.Jhd1313m1(6, 0x3E, 0x62);

var a0=new mraa.Aio(3);
var a=116.602;
var b=-5.96;
var In=4.5/3.34e+4;
var R0=41000;
Loop();
function Loop()
{
 var val=a0.read();
var vo=val*5/1000;
var v1=5-vo;
var Rs=v1/In;
var v2=Rs/R0;
v2=Math.pow(v2,b);
var ppm=179.73*v2;
console.log("x="+val+" vo="+vo+" Rs="+Rs+" ppm"+ppm);
//myLCD.clear();
//myLCD.setCursor(0,1);
//myLCD.write(""+ppm);
//myLCD.setCursor(1,1);

//myLCD.write("Co2 in ppm");
if(ppm<420)
{
//myLCD.setColor(0,255,0);
}
else
{
//myLCD.setColor(255,0,0);
}
///////////// Update ThingSpeak/////////////
s="curl \"http://api.thingspeak.com/update?api_key=3ZXPXW3SPPDEC1HU&field1="+ppm+ "\"";
exec(s);
//////////////////////////////////////////
client.publish('rupam/Simulator', ""+ppm);
/// Send data to Simulator//////////

setTimeout(Loop,10000);
} 

代码详解

现在,我们将研究 VANET 模拟器的场景。一旦 OSM 文件上传,我们就可以生成我们区域的地图。它有助于复制最佳场景,我们可以考虑交通负载在高峰时段和非高峰时段的量以及地点。我们可以测试交通和特定地点的二氧化碳排放率的极端情况。

完成重要事项

将为数据供电并与互联网和其他服务通信的 Intel Edison 板应放置在路口点,而且是路口的第一盏交通信号灯处。这将有助于创建模拟环境的起点。

让我们开始编写代码

    
    /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package vanetsim;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

/**
 *
 * @author Rupam
 */
public class IoTSimulatorInterface extends javax.swing.JFrame implements MqttCallback {

    /**
     * Creates new form IoTSimulatorInterface
     */
    public IoTSimulatorInterface() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    //                           
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jtfBrokerUrl = new javax.swing.JTextField();
        jButton1 = new javax.swing.JButton();
        jlChart = new javax.swing.JLabel();
        jlConnectionStatus = new javax.swing.JLabel();
        jButton2 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jLabel1.setText("Connect IoT Module With Simulator Using MqTT Protocol");

        jLabel2.setText("Server URL:");

        jtfBrokerUrl.setText("tcp://iot.eclipse.org:1883");

        jButton1.setText("Connect Simulation With IoT");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jlChart.setText("jLabel3");

        jlConnectionStatus.setText("Not Connected");

        jButton2.setText("Run Simulator");
        jButton2.setEnabled(false);
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(55, 55, 55)
                        .addComponent(jlChart, javax.swing.GroupLayout.PREFERRED_SIZE, 848, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(178, 178, 178)
                        .addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel1)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 198, Short.MAX_VALUE)
                                    .addComponent(jtfBrokerUrl))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jlConnectionStatus)
                                    .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE))))))
                .addContainerGap(85, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addComponent(jLabel1)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(jtfBrokerUrl, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jlConnectionStatus))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jlChart, javax.swing.GroupLayout.PREFERRED_SIZE, 427, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(41, Short.MAX_VALUE))
        );

        pack();
    }//                         
String topic        = "rupam/Simulator";
        String content      = "Message from MqttPublishSample";
        int qos             = 2;
        String broker       = "tcp://iot.eclipse.org:1883";
        String clientId     = "RUPAM";
        MemoryPersistence persistence = new MemoryPersistence();
        MqttClient sampleClient=null;
        public static double ParameterValue=-1.0;
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        broker=jtfBrokerUrl.getText().trim();
         try {
           sampleClient = new MqttClient(broker, clientId, persistence);
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setCleanSession(true);
            System.out.println("Connecting to broker: "+broker);
            sampleClient.connect(connOpts);
            System.out.println("Connected");
            System.out.println("Publishing message: "+content);
            
            if(sampleClient.isConnected())
            {
                JOptionPane.showMessageDialog(this,"Connected");
                jlConnectionStatus.setText("Connected");
              sampleClient.subscribe(topic);
              sampleClient.setCallback(this );
              jButton2.setEnabled(true);
              ds=new DataSet();
              ds.colNames=new Object[]{"Co2 Emission"};
              data=new ArrayList<>();
            }
            else
            {
                JOptionPane.showMessageDialog(this,"Not Connected");
            }
           /*
            MqttMessage message = new MqttMessage(content.getBytes());
            message.setQos(qos);
            sampleClient.publish(topic, message);
            System.out.println("Message published");
            sampleClient.disconnect();
            System.out.println("Disconnected");
            */
            //System.exit(0);
        } 
         catch(MqttException me) {
            System.out.println("reason "+me.getReasonCode());
            System.out.println("msg "+me.getMessage());
            System.out.println("loc "+me.getLocalizedMessage());
            System.out.println("cause "+me.getCause());
            System.out.println("excep "+me);
            me.printStackTrace();
        }
    }                                        
VanetSimStarter  vss=null;
DataSet ds=null;
    ArrayList data;
    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        vss=new VanetSimStarter();
        vss.Main();
        
    }                                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(IoTSimulatorInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(IoTSimulatorInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(IoTSimulatorInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(IoTSimulatorInterface.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new IoTSimulatorInterface().setVisible(true);
                
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jlChart;
    private javax.swing.JLabel jlConnectionStatus;
    private javax.swing.JTextField jtfBrokerUrl;
    // End of variables declaration                   

    @Override
    public void connectionLost(Throwable thrwbl) {
        
        //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    
    @Override
    public void messageArrived(String string, MqttMessage mm) throws Exception {
       String para=new String(mm.getPayload());
        System.out.println();
        try
        {
            ParameterValue=Double.parseDouble(para);
            data.add(ParameterValue);
            //double[] da=new double[data.size()];
            ds.numericData=new double[1][data.size()];
            for(int i=0;i
                
                

第一部分链接到 iot.eclipse.org,VANET 模拟器和 Intel Edison 可以在此相互通信。MQTT 消息交换在此类情况下,爱迪生和 VANET 模拟器之间的通信是如何工作的。让我们特别强调消息到达函数。这里的关键是 ParameterValue 变量的声明,它获取 CO2 值。现在,在下一个代码块中,我们将看到随着 ParameterValue 的增加,绿灯相位值也会增加。

 

    /*
 * VANETsim open source project - http://www.vanet-simulator.org
 * Copyright (C) 2008 - 2013  Andreas Tomandl, Florian Scheuer, Bernhard Gruber
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package vanetsim.map;





/**
 * This class represents a traffic light at a junction.
 */
public class TrafficLight {
	
	/** Default time intervals for state switching. */
	private static final double[] DEFAULT_SWITCH_INTERVALS = new double[] {5000, 1000, 5000};
	
	/** A static time to free a junction after a change of phases in ms. */
	private static final double JUNCTION_FREE_TIME = 2000;
	
	/** Duration of the red phase in ms for the priority street. */
	private double redPhaseLength_;
	
	/** Duration of the yellow phase in ms for the priority street. */
	private double yellowPhaseLength_;
	
	/** Duration of the green phase in ms for the priority street. */
	private double greenPhaseLength_;
	
	/** status of traffic light: 0 green : 1 green-orange : 2 red 3: freephase */
	private int state = 0;
	
	/** Traffic Light Collections */
	private Street[] streets_;

	
	/** Stores if a street is a priority street or not; used to distinguish between times. */
	private boolean[] streetIsPriority_;
		
	/** Timer for this traffic light; because all traffic lights on a junction run synchronously just one timer is needed. */
	private double timer_;
	
	/** The Junction this traffic light. */
	private Junction junction_;

	/** switcher between long and short signal length */
	private boolean switcher = true;

	/**
	 * Constructor.
	 */
	public TrafficLight(Junction junction) {
		junction_ = junction;
		//set the phases with standard times
		junction_.getNode().setTrafficLight_(this);
		
		redPhaseLength_ = DEFAULT_SWITCH_INTERVALS[0];
		yellowPhaseLength_ = DEFAULT_SWITCH_INTERVALS[1];
		greenPhaseLength_ = DEFAULT_SWITCH_INTERVALS[2];
		
		initialiseTrafficLight();
	}
	
	/**
	 * Constructor.
	 */
	public TrafficLight(double redPhaseLength, double yellowPhaseLength, double greenPhaseLength, Junction junction) {		
		junction_ = junction;
		
		junction_.getNode().setTrafficLight_(this);

		//set the phases from the given times
		redPhaseLength_ = redPhaseLength;
		yellowPhaseLength_ = yellowPhaseLength;
		greenPhaseLength_ = greenPhaseLength;
		
		initialiseTrafficLight();
	}
	
	/**
	 * This functions initializes the time arrays for each phase of the traffic light for each street;
	 * starts of with the priority streets at green and the crossing streets at red
	 * 
	 */
	private void initialiseTrafficLight(){			

		streetIsPriority_ = new boolean[junction_.getNode().getCrossingStreetsCount()];
		
		if(!junction_.getNode().hasNonDefaultSettings()){
			junction_.getNode().setStreetHasException_(new int[junction_.getNode().getCrossingStreetsCount()]);
			for(int m = 0; m < junction_.getNode().getStreetHasException_().length; m++) junction_.getNode().getStreetHasException_()[m] = 1;
		}

			
		streets_ = junction_.getNode().getCrossingStreets();
		Street[] tmpPriorityStreets = junction_.getPriorityStreets();
		
		boolean isOneway = false;
		
		for(int i = 0; i < streets_.length; i++){
			streetIsPriority_[i] = false;
			for(int j = 0; j < tmpPriorityStreets.length; j++){
				if(streets_[i] == tmpPriorityStreets[j]) streetIsPriority_[i] = true;
			}
			if(streets_[i].isOneway() && streets_[i].getStartNode() == junction_.getNode()) isOneway = true;

			if(!isOneway){
				if(streetIsPriority_[i]){
					if(junction_.getNode() == streets_[i].getStartNode()){
						streets_[i].setStartNodeTrafficLightState(0);
						if(junction_.getNode().hasNonDefaultSettings()){
							streets_[i].setStartNodeTrafficLightState(junction_.getNode().getStreetHasException_()[i]);
						}
						streets_[i].setPriorityOnStartNode(true);
					}
					else{
						streets_[i].setEndNodeTrafficLightState(0);	
						if(junction_.getNode().hasNonDefaultSettings()){
							streets_[i].setEndNodeTrafficLightState(junction_.getNode().getStreetHasException_()[i]);
						}
						streets_[i].setPriorityOnEndNode(true);
					}
				}
				else{
					if(junction_.getNode() == streets_[i].getStartNode()){
						streets_[i].setStartNodeTrafficLightState(4);
						if(junction_.getNode().hasNonDefaultSettings()){
							streets_[i].setStartNodeTrafficLightState(junction_.getNode().getStreetHasException_()[i]);
						}
					}
					else {
						streets_[i].setEndNodeTrafficLightState(4);
						if(junction_.getNode().hasNonDefaultSettings()){
							streets_[i].setEndNodeTrafficLightState(junction_.getNode().getStreetHasException_()[i]);
						}
					}
				}
			}

			isOneway = false;
			
			//lets calculate the drawing positions of the traffic light ... now its better for the performance
			calculateTrafficLightPosition(streets_[i]);
		}		
		timer_ = greenPhaseLength_;
		
		//tell the node, that he now has a traffic light
		junction_.getNode().setHasTrafficSignal_(true);
	
	}
	
	/**
	 * This function should change the states of the traffic lights if necessary. Should be called after the first greenphase
	 */
	public void changePhases(int timePerStep){
		//if remaining time is smaller than the timerPerStep we have to change the states
		if(timer_ < timePerStep){
			state = (state +1) % 4;		
 greenPhaseLength_=1000*(vanetsim.IoTSimulatorInterface.ParameterValue-400)/10;
 System.out.println("Green Light Period="+greenPhaseLength_+" red light period="+redPhaseLength_+" yellow time period= "+yellowPhaseLength_);
			//could be less code, but this way I get a better performanz
			//(non)priorties where green: Change to orange
			if(state == 1) timer_ = yellowPhaseLength_;
			//(non)priorties where green-orange: Change to red for a freephase
			else if(state == 2)timer_ = JUNCTION_FREE_TIME;
			//priorties where free: Change to red
			else if(state == 0 && switcher)
                        {
                            if(vanetsim.IoTSimulatorInterface.ParameterValue>0.0)
                            {
                               
                                timer_ = greenPhaseLength_;
                                //increase the green light time
                            }
                            else
                            {
                            timer_ = greenPhaseLength_;
                            }
                        }
			//non-priorties where free: Change to red
			else if(state == 0 && !switcher)timer_ = redPhaseLength_;
			//yellow
			else if(state == 3)timer_ = yellowPhaseLength_;	
			
			
			switcher = !switcher;
			//update all street + 1

			for(int i = 0; i < streets_.length; i++){
				if(streets_[i].getStartNode() == junction_.getNode() && streets_[i].getStartNodeTrafficLightState() != -1){
					streets_[i].updateStartNodeTrafficLightState();
				}
				else if(streets_[i].getEndNode() == junction_.getNode() && streets_[i].getEndNodeTrafficLightState() != -1){
					streets_[i].updateEndNodeTrafficLightState();
				}
			}
		}
		//else change timer
		else timer_ = timer_ - timePerStep;
	}
	
	/* Calculates Traffic light position */
	/**
	 * Calculates Traffic light position for drawing
	 */
	public void calculateTrafficLightPosition(Street tmpStreet){	
		double junctionX = junction_.getNode().getX();
		double junctionY = junction_.getNode().getY();
		
		double nodeX;
		double nodeY;
		
		if(junction_.getNode().equals(tmpStreet.getStartNode())){
			nodeX = tmpStreet.getEndNode().getX();
			nodeY = tmpStreet.getEndNode().getY();
		}
		else{
			nodeX = tmpStreet.getStartNode().getX();
			nodeY = tmpStreet.getStartNode().getY();		
		}

		//calculate the linear function (y = mx + n) between junction node an the other node
		double m = (nodeY-junctionY)/(nodeX-junctionX);
		double n = nodeY - m*nodeX;
		
		double a = 1 + (m * m);
		double b = (2 * m * n) - (2 * m * junctionY) - (2 * junctionX);
		double c = (n * n) - (2 * n * junctionY) + (junctionY * junctionY) - (700 * 700) + (junctionX * junctionX);

		if(junction_.getNode().equals(tmpStreet.getStartNode())){
			if(nodeX < junctionX){
				tmpStreet.setTrafficLightStartX_((int)Math.round((-b - Math.sqrt((b*b) - (4*a*c))) / (2*a))); 
				tmpStreet.setTrafficLightStartY_((int)Math.round((m * tmpStreet.getTrafficLightStartX_()) + n));
			 }
			 else{
				tmpStreet.setTrafficLightStartX_((int)Math.round((-b + Math.sqrt((b*b) - (4*a*c))) / (2*a)));
				tmpStreet.setTrafficLightStartY_((int)Math.round((m * tmpStreet.getTrafficLightStartX_()) + n));
			 }
		}
		else{
			if(nodeX < junctionX){
				tmpStreet.setTrafficLightEndX_((int)Math.round((-b - Math.sqrt((b*b) - (4*a*c))) / (2*a))); 
				tmpStreet.setTrafficLightEndY_((int)Math.round((m * tmpStreet.getTrafficLightEndX_()) + n));
			 }
			 else{
				tmpStreet.setTrafficLightEndX_((int)Math.round((-b + Math.sqrt((b*b) - (4*a*c))) / (2*a)));
				tmpStreet.setTrafficLightEndY_((int)Math.round((m * tmpStreet.getTrafficLightEndX_()) + n));
			 }	
		}

	}


	/**
	 * Gets the length of the green phase.
	 * 
	 * @return the length of the green phase
	 */
	public double getGreenPhaseLength() {
		return greenPhaseLength_;
	}

	
	/**
	 * Sets the length for the green Phase.
	 * 
	 * @param greenPhaseLength the length for the green phase
	 */
	public void setGreenPhaseLength(double greenPhaseLength) {
		this.greenPhaseLength_ = greenPhaseLength;
	}
	
	/**
	 * Sets the length of the yellow phase.
	 * 
	 * @param yellowPhaseLength the length of the yellow phase
	 */
	public void setYellowPhaseLength(double yellowPhaseLength) {
		this.yellowPhaseLength_ = yellowPhaseLength;
	}

	/**
	 * Gets the length of the yellow phase.
	 * 
	 * @return the length of the yellow phase
	 */
	public double getYellowPhaseLength() {
		return yellowPhaseLength_;
	}

	/**
	 * Sets the length of the red phase.
	 * 
	 * @param redPhaseLength the length of the red phase
	 */
	public void setRedPhaseLength(double redPhaseLength) {
		this.redPhaseLength_ = redPhaseLength;
	}

	/**
	 * Gets the length of the red phase.
	 * 
	 * @return the length of the red phase
	 */
	public double getRedPhaseLength() {
		return redPhaseLength_;
	}


	/**
	 * @param state the state to set
	 */
	public void setState(int state) {
		this.state = state;
	}

	/**
	 * @return the state
	 */
	public int getState() {
		return state;
	}

	/**
	 * @return the streets_
	 */
	public Street[] getStreets_() {
		return streets_;
	}

	/**
	 * @param streets_ the streets_ to set
	 */
	public void setStreets_(Street[] streets_) {
		this.streets_ = streets_;
	}




}

结果

 

Intel Edison 板有两个端口:一个靠近开关的端口是电源端口。它直接从 PC 获取电源。另一个是串行端口,PC 可以通过串行端口向板发送命令。一旦板连接到 Wi-Fi 网络,我们就可以远程编程板。该板通过 USB 端口连接到 PC。连接后,板上的 LED 会发光,表示板已通电。插入 USB 后,右键单击“我的电脑”。单击“属性”,如下图所示:

 

                              图:连接串行端口。

接下来单击设备管理器,然后单击“COM 和 LPT 端口”,选择 USB 串行端口用于通信目的,以便计算机通过此串行端口通信。

                  图:选择 COM 和 LPT 端口。

要检查端口号,请使用一个名为 PuTTY 的串行通信软件。PuTTY 是一个非常流行的串行通信软件。下一步是打开 PuTTY 软件。它有两种连接:SSH 和串行。此处板通过串行连接连接,因此单击设备管理器中的“串行”并查看配置了哪个端口。这取决于 PC,我的计算机配置为 COM18。在 PuTTY 中,单击“串行”选项卡,然后在 COM 前输入 18。该板的波特率是 115200。将速度更改为 115200,即每秒比特数。输入值并选择“打开”后,PC 就可以与该板通信了。会出现一个黑屏。

              图:输入串行线路和比特率

输入后,我们需要以 root 身份登录并输入密码。首先,将 Edison 板连接到我们的 Wi-Fi 网络。该板将通过我们的本地网络(即我们的 Wi-Fi 网络)连接到互联网。使用的命令是 configure_edison --wifi。运行此命令后。

                图:登录 PuTTY 并配置 Wi-Fi。

它将配置周围所有可用的 Wi-Fi 网络,如下图所示。我的调制解调器号是 4。它会要求输入网络 SSID,并通过输入“Yes”确认我们的网络 ID。然后输入我们的网络密码。

            图:配置 Edison Wi-Fi 连接。

输入密码后,Edison 板将连接到我们的本地网络。然后它将显示 IP 地址。对于不同的 PC,它可能具有不同的 IP 地址,它使用 SSH 连接。ls 命令用于查看我们的程序。

我的程序是 PollutionSim.js。可以通过输入 node PollutionSim.js 来运行它。它将显示 x 值,其中 x 是模拟值。传感器感应到的模拟值可以感应到来自车辆的 CO2 水平。CO2 值以 ppm 显示。

                     图:运行程序以获取 ppm 值。

下一部分是运行项目 VanetSimulatorIoT。

VanetSimulatorIoT 包包含运行模拟的源包,例如 IoTSimulatorInterface.java 包。在此右键单击 IoTSimulatorInterface.java 包并调试该文件以连接服务器。

                                 图:将模拟与物联网连接

调试 IoTSimulatorInterface.java 包后,我们将连接 MQTT 服务器。MQTT 是一种机器对机器通信协议,基于发布/订阅服务。创建了一个通道来将数据存储到通道并从通道检索数据。这里用于消息交换的通道是 rupam/simulator。我们可以在 MQTT 服务器上创建自己的通道。

首先,我们连接 MQTT 代理。如果代理已连接。如上图所示,将显示“代理已连接”消息。MQTT 包含两个服务器:iot.eclipse.org 和 test.mosquitto.org。

我们的目标是显示模拟器上的本地图表,同时在 ThingSpeak 上也进行绘制。我们希望在本地图表中显示 CO2 水平的变化。为了显示模拟结果,我们使用一个数据数组来存储数据。模拟结果如下图所示。

在运行模拟器之前,请先将 IoT 设备连接到系统,然后通过 COM18 串行端口使用 putty 软件登录。Node PollutionSim.js 是一个获取当前 ppm 值的 JavaScript 程序。然后 ping google.com。一旦 ping 通 google,就可以确保 ppm 值已更新。运行项目,同时打开 Thingspeak 通道以实时可视化模拟值。通道是 thingspeak.com/channels/105527,如下图所示:

图:ThingSpeak 更新结果

一旦我们连接到物联网。运行模拟。在此期间,请注意交通信号灯值未达到断点,因为我们没有重置地图。

下一步是编辑 Open Street Map 部分。

图:编辑部分用于获取 Open Street Map。

图:使用值创建地图的过程

图:Gulbarga 市的开放街道地图

让我们通过打开任何城市的开放街道地图来开始编辑部分。我们选择 Gulbarga 的开放街道地图,文件名为 gulbarga3.osm。

                              图:选择特定路口

然后启用编辑模式以在路口放置交通信号灯和车辆。

                             图:在路口选择交通信号灯

启用编辑模式后。在开放街道地图上选择特定路口以放置交通信号灯和车辆。接下来进入设置,为每个路口选择一盏交通信号灯。

                              图:在一个特定路口放置一盏交通信号灯

接下来,仅从设置部分选择车辆数量。

                      图:从设置中选择车辆选项

选择“车辆”选项后,我们将输入车辆数量。

图:通过点击选项进行选择

在此,我们使用单击选项。通过单击,我们在街道地图上选择并添加车辆。        

                                图:添加所选数量的车辆

一旦我们选择了车辆数量,例如 30 辆。车辆以 10 秒的间隔从源点移动到目标点。我们必须为车辆设置航点,即所选数量车辆的源点和目标点,并且它们必须经过放置了交通信号灯的指定路口。

                                    图:选择路边单元

                                                   图:放置路边单元

通过在设置中选择路边单元选项。然后选择路边单元并将其放置在开放街道地图的道路上。路边单元可以扩展车辆之间的通信范围。

        图:选择事件操作

现在,让我们放置一些事件。事件选项仅从设置中选择。

                           图:选择特定的事件点

事件就是医院、损坏的路面、学校区域等。我们在此选择损坏的路面作为事件点。

 图:放置损坏的路面事件点

选择损坏的路面后。此事件将放置在道路上。当车辆从一个地方移动到另一个地方时,车辆在到达损坏的路面之前就会获得有关损坏路面的信息,当车辆靠近损坏的路面时,车辆会减速以避免事故。

图:选择禁用模式

完成编辑部分后,我们通过禁用模式(统计信息)禁用编辑部分。

                                     图:运行模拟部分

最后,运行模拟。一旦模拟开始,车辆就会通过放置了交通信号灯的特定路口。

一旦模拟开始,绿灯计时就会根据二氧化碳水平和交通拥堵情况显示在 IoTSimulatorInterface.java 界面(控制台)上。当二氧化碳水平和交通拥堵增加时,绿灯计时也会增加。这样,车辆就可以顺利通过路口。

模拟-真实世界映射

当二氧化碳消耗量较大时的模拟点。

让我们再次查看我们如何处理代码

第一张图显示了我们在 NetBeans 中开始处理代码的过程。

第二张图用红勾突出显示了绿灯相位长度的计算位置。

第三张图描绘了交通模拟是如何开始的,以及交通信号灯显示二氧化碳消耗。

第四张图也显示了相同的内容,并描绘了交通的到达来源。

显著的绿灯显示了绿灯是如何产生的。因此,通过所有图片,我们展示了模拟是如何发生的。

模拟结果表明,通过控制交通

结论

 城市交通规划和管理通常需要良好的模拟引擎。VANET 模拟器就是这样一款逼真的模拟器,可以借助 OpenStreet Map 投影任何城市的交通场景。如今,城市面临的最严峻的挑战之一就是减少污染。尽管模拟引擎在开发用于交通规划和管理的运行算法方面表现出色,但要根据现实世界场景进行验证却很困难。在这项工作中,我们展示了一个单一的污染传感物理节点如何集成到模拟环境中,以及如何将通过物理设备获取的数据用作模拟环境中的变量。这项工作可以作为一个框架,设备可以被视为部署在不同已知地理空间位置的资产,同时广播其位置和污染数据。通过在代码中添加资产发现接口,可以将这些实时资产导入模拟环境,并利用多路口污染数据来开发更好的交通规划场景。此外,使用 Android 手机的车辆如果广播其 GPS 数据,则可以在地图上观察到真实交通的整个交通流量。在这些场景中,可以将模拟和实时数据进行混合使用,并以协作的方式来开发更健壮的城市交通规划场景。

 

历史

在此处保持您所做的任何更改或改进的实时更新。

© . All rights reserved.