`
lzj0470
  • 浏览: 1284236 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

用 Lucene 加速 Web 搜索应用程序的开发

阅读更多
Lucene 是基于 Java 的全文信息检索包,它目前是 Apache Jakarta 家族下面的一个开源项目。在这篇文章中,我们首先来看如何利用 Lucene 实现高级搜索功能,然后学习如何利用 Lucene 来创建一个健壮的 Web 搜索应用程序。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

在本篇文章中,你会学习到如何利用 Lucene 实现高级搜索功能以及如何利用 Lucene 来创建 Web 搜索应用程序。通过这些学习,你就可以利用 Lucene 来创建自己的搜索应用程序。

架构概览

通常一个 Web 搜索引擎的架构分为前端和后端两部分,就像图一中所示。在前端流程中,用户在搜索引擎提供的界面中输入要搜索的关键词,这里提到的用户界面一般是一个带有输入框的 Web 页面,然后应用程序将搜索的关键词解析成搜索引擎可以理解的形式,并在索引文件上进行搜索操作。在排序后,搜索引擎返回搜索结果给用户。在后端流程中,网络爬虫或者机器人从因特网上获取 Web 页面,然后索引子系统解析这些 Web 页面并存入索引文件中。如果你想利用 Lucene 来创建一个 Web 搜索应用程序,那么它的架构也和上面所描述的类似,就如图一中所示。


Figure 1. Web 搜索引擎架构
Web搜索引擎架构

利用 Lucene 实现高级搜索

Lucene 支持多种形式的高级搜索,我们在这一部分中会进行探讨,然后我会使用 Lucene 的 API 来演示如何实现这些高级搜索功能。

布尔操作符

大多数的搜索引擎都会提供布尔操作符让用户可以组合查询,典型的布尔操作符有 AND, OR, NOT。Lucene 支持 5 种布尔操作符,分别是 AND, OR, NOT, 加(+), 减(-)。接下来我会讲述每个操作符的用法。

  • OR: 如果你要搜索含有字符 A 或者 B 的文档,那么就需要使用 OR 操作符。需要记住的是,如果你只是简单的用空格将两个关键词分割开,其实在搜索的时候搜索引擎会自动在两个关键词之间加上 OR 操作符。例如,“Java OR Lucene” 和 “Java Lucene” 都是搜索含有 Java 或者含有 Lucene 的文档。
  • AND: 如果你需要搜索包含一个以上关键词的文档,那么就需要使用 AND 操作符。例如,“Java AND Lucene” 返回所有既包含 Java 又包含 Lucene 的文档。
  • NOT: Not 操作符使得包含紧跟在 NOT 后面的关键词的文档不会被返回。例如,如果你想搜索所有含有 Java 但不含有 Lucene 的文档,你可以使用查询语句 “Java NOT Lucene”。但是你不能只对一个搜索词使用这个操作符,比如,查询语句 “NOT Java” 不会返回任何结果。
  • 加号(+): 这个操作符的作用和 AND 差不多,但它只对紧跟着它的一个搜索词起作用。例如,如果你想搜索一定包含 Java,但不一定包含 Lucene 的文档,就可以使用查询语句“+Java Lucene”。
  • 减号(-): 这个操作符的功能和 NOT 一样,查询语句 “Java -Lucene” 返回所有包含 Java 但不包含 Lucene 的文档。

接下来我们看一下如何利用 Lucene 提供的 API 来实现布尔查询。清单1 显示了如果利用布尔操作符进行查询的过程。


清单1:使用布尔操作符

  //Test boolean operator
public void testOperator(String indexDirectory) throws Exception{
   Directory dir = FSDirectory.getDirectory(indexDirectory,false);
   IndexSearcher indexSearcher = new IndexSearcher(dir);
   String[] searchWords = {"Java AND Lucene", "Java NOT Lucene", "Java OR Lucene", 
                    "+Java +Lucene", "+Java -Lucene"};
   Analyzer language = new StandardAnalyzer();
   Query query;
   for(int i = 0; i < searchWords.length; i++){
      query = QueryParser.parse(searchWords[i], "title", language);
      Hits results = indexSearcher.search(query);
      System.out.println(results.length() + "search results for query " + searchWords[i]);
   }
}

 

域搜索(Field Search)

Lucene 支持域搜索,你可以指定一次查询是在哪些域(Field)上进行。例如,如果索引的文档包含两个域,TitleContent,你就可以使用查询 “Title: Lucene AND Content: Java” 来返回所有在 Title 域上包含 Lucene 并且在 Content 域上包含 Java 的文档。清单 2 显示了如何利用 Lucene 的 API 来实现域搜索。


清单2:实现域搜索

//Test field search
public void testFieldSearch(String indexDirectory) throws Exception{
    Directory dir = FSDirectory.getDirectory(indexDirectory,false);
    IndexSearcher indexSearcher = new IndexSearcher(dir);
    String searchWords = "title:Lucene AND content:Java";
    Analyzer language = new StandardAnalyzer();
    Query query = QueryParser.parse(searchWords, "title", language);
    Hits results = indexSearcher.search(query);
    System.out.println(results.length() + "search results for query " + searchWords);
}

 

通配符搜索(Wildcard Search)

Lucene 支持两种通配符:问号(?)和星号(*)。你可以使用问号(?)来进行单字符的通配符查询,或者利用星号(*)进行多字符的通配符查询。例如,如果你想搜索 tiny 或者 tony,你就可以使用查询语句 “t?ny”;如果你想查询 Teach, Teacher 和 Teaching,你就可以使用查询语句 “Teach*”。清单3 显示了通配符查询的过程。


清单3:进行通配符查询

//Test wildcard search
public void testWildcardSearch(String indexDirectory)throws Exception{
   Directory dir = FSDirectory.getDirectory(indexDirectory,false);
   IndexSearcher indexSearcher = new IndexSearcher(dir);
   String[] searchWords = {"tex*", "tex?", "?ex*"};
   Query query;
   for(int i = 0; i < searchWords.length; i++){
      query = new WildcardQuery(new Term("title",searchWords[i]));
      Hits results = indexSearcher.search(query);
      System.out.println(results.length() + "search results for query " + searchWords[i]);
   }
}

 

模糊查询

Lucene 提供的模糊查询基于编辑距离算法(Edit distance algorithm)。你可以在搜索词的尾部加上字符 ~ 来进行模糊查询。例如,查询语句 “think~” 返回所有包含和 think 类似的关键词的文档。清单 4 显示了如果利用 Lucene 的 API 进行模糊查询的代码。


清单4:实现模糊查询

//Test fuzzy search
public void testFuzzySearch(String indexDirectory)throws Exception{
   Directory dir = FSDirectory.getDirectory(indexDirectory,false);
   IndexSearcher indexSearcher = new IndexSearcher(dir);
   String[] searchWords = {"text", "funny"};
   Query query;
   for(int i = 0; i < searchWords.length; i++){
      query = new FuzzyQuery(new Term("title",searchWords[i]));
      Hits results = indexSearcher.search(query);
      System.out.println(results.length() + "search results for query " + searchWords[i]);
   }
}

 

范围搜索(Range Search)

范围搜索匹配某个域上的值在一定范围的文档。例如,查询 “age:[18 TO 35]” 返回所有 age 域上的值在 18 到 35 之间的文档。清单5显示了利用 Lucene 的 API 进行返回搜索的过程。


清单5:测试范围搜索

//Test range search
public void testRangeSearch(String indexDirectory)throws Exception{
    Directory dir = FSDirectory.getDirectory(indexDirectory,false);
    IndexSearcher indexSearcher = new IndexSearcher(dir);
    Term begin = new Term("birthDay","20000101");
    Term end   = new Term("birthDay","20060606");
    Query query = new RangeQuery(begin,end,true);
    Hits results = indexSearcher.search(query);
    System.out.println(results.length() + "search results is returned");
}





回页首


在 Web 应用程序中集成 Lucene

接下来我们开发一个 Web 应用程序利用 Lucene 来检索存放在文件服务器上的 HTML 文档。在开始之前,需要准备如下环境:

  1. Eclipse 集成开发环境
  2. Tomcat 5.0
  3. Lucene Library
  4. JDK 1.5

这个例子使用 Eclipse 进行 Web 应用程序的开发,最终这个 Web 应用程序跑在 Tomcat 5.0 上面。在准备好开发所必需的环境之后,我们接下来进行 Web 应用程序的开发。

1、创建一个动态 Web 项目

  1. 在 Eclipse 里面,选择 File > New > Project,然后再弹出的窗口中选择动态 Web 项目,如图二所示。


图二:创建动态Web项目
创建动态Web项目

  1. 在创建好动态 Web 项目之后,你会看到创建好的项目的结构,如图三所示,项目的名称为 sample.dw.paper.lucene。


图三:动态 Web 项目的结构
动态 Web 项目的结构

2. 设计 Web 项目的架构

在我们的设计中,把该系统分成如下四个子系统:

  1. 用户接口: 这个子系统提供用户界面使用户可以向 Web 应用程序服务器提交搜索请求,然后搜索结果通过用户接口来显示出来。我们用一个名为 search.jsp 的页面来实现该子系统。
  2. 请求管理器: 这个子系统管理从客户端发送过来的搜索请求并把搜索请求分发到搜索子系统中。最后搜索结果从搜索子系统返回并最终发送到用户接口子系统。我们使用一个 Servlet 来实现这个子系统。
  3. 搜索子系统: 这个子系统负责在索引文件上进行搜索并把搜索结构传递给请求管理器。我们使用 Lucene 提供的 API 来实现该子系统。
  4. 索引子系统: 这个子系统用来为 HTML 页面来创建索引。我们使用 Lucene 的 API 以及 Lucene 提供的一个 HTML 解析器来创建该子系统。

图4 显示了我们设计的详细信息,我们将用户接口子系统放到 webContent 目录下面。你会看到一个名为 search.jsp 的页面在这个文件夹里面。请求管理子系统在包 sample.dw.paper.lucene.servlet 下面,类 SearchController 负责功能的实现。搜索子系统放在包 sample.dw.paper.lucene.search 当中,它包含了两个类,SearchManagerSearchResultBean,第一个类用来实现搜索功能,第二个类用来描述搜索结果的结构。索引子系统放在包 sample.dw.paper.lucene.index 当中。类 IndexManager 负责为 HTML 文件创建索引。该子系统利用包 sample.dw.paper.lucene.util 里面的类 HTMLDocParser 提供的方法 getTitlegetContent 来对 HTML 页面进行解析。


图四:项目的架构设计
项目的架构设计

3. 子系统的实现

在分析了系统的架构设计之后,我们接下来看系统实现的详细信息。

  1. 用户接口: 这个子系统有一个名为 search.jsp 的 JSP 文件来实现,这个 JSP 页面包含两个部分。第一部分提供了一个用户接口去向 Web 应用程序服务器提交搜索请求,如图5所示。注意到这里的搜索请求发送到了一个名为 SearchController 的 Servlet 上面。Servlet 的名字和具体实现的类的对应关系在 web.xml 里面指定。


图5:向Web服务器提交搜索请求
向Web服务器提交搜索请求

这个JSP的第二部分负责显示搜索结果给用户,如图6所示:


图6:显示搜索结果
显示搜索结果

  1. 请求管理器: 一个名为 SearchController 的 servlet 用来实现该子系统。清单6给出了这个类的源代码。


清单6:请求管理器的实现

package sample.dw.paper.lucene.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sample.dw.paper.lucene.search.SearchManager;

/**
 * This servlet is used to deal with the search request
 * and return the search results to the client
 */
public class SearchController extends HttpServlet{

    private static final long serialVersionUID = 1L;

    public void doPost(HttpServletRequest request, HttpServletResponse response)
                      throws IOException, ServletException{
        String searchWord = request.getParameter("searchWord");
        SearchManager searchManager = new SearchManager(searchWord);
        List searchResult = null;
        searchResult = searchManager.search();
        RequestDispatcher dispatcher = request.getRequestDispatcher("search.jsp");
        request.setAttribute("searchResult",searchResult);
        dispatcher.forward(request, response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
                     throws IOException, ServletException{
        doPost(request, response);
    }
}

 

清单6中,doPost 方法从客户端获取搜索词并创建类 SearchManager 的一个实例,其中类 SearchManager 在搜索子系统中进行了定义。然后,SearchManager 的方法 search 会被调用。最后搜索结果被返回到客户端。

  1. 搜索子系统: 在这个子系统中,我们定义了两个类:SearchManagerSearchResultBean。第一个类用来实现搜索功能,第二个类是个JavaBean,用来描述搜索结果的结构。清单7给出了类 SearchManager 的源代码。


清单7:搜索功能的实现

package sample.dw.paper.lucene.search;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;

import sample.dw.paper.lucene.index.IndexManager;

/**
 * This class is used to search the 
 * Lucene index and return search results
 */
public class SearchManager {
	
    private String searchWord;
    
    private IndexManager indexManager;
    
    private Analyzer analyzer;
    
    public SearchManager(String searchWord){
        this.searchWord   =  searchWord;
        this.indexManager =  new IndexManager();
        this.analyzer     =  new StandardAnalyzer();
    }
    
    /**
     * do search
     */
    public List search(){
        List searchResult = new ArrayList();
        if(false == indexManager.ifIndexExist()){
        try {
            if(false == indexManager.createIndex()){
                return searchResult;
            }
        } catch (IOException e) {
          e.printStackTrace();
          return searchResult;
        }
        }
    	
        IndexSearcher indexSearcher = null;

        try{
            indexSearcher = new IndexSearcher(indexManager.getIndexDir());
        }catch(IOException ioe){
            ioe.printStackTrace();
        }

        QueryParser queryParser = new QueryParser("content",analyzer);
        Query query = null;
        try {
            query = queryParser.parse(searchWord);
        } catch (ParseException e) {
          e.printStackTrace();
        }
        if(null != query >> null != indexSearcher){			
            try {
                Hits hits = indexSearcher.search(query);
                for(int i = 0; i < hits.length(); i ++){
                    SearchResultBean resultBean = new SearchResultBean();
                    resultBean.setHtmlPath(hits.doc(i).get("path"));
                    resultBean.setHtmlTitle(hits.doc(i).get("title"));
                    searchResult.add(resultBean);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return searchResult;
    }
}
 

 

清单7中,注意到在这个类里面有三个私有属性。第一个是 searchWord,代表了来自客户端的搜索词。第二个是 indexManager,代表了在索引子系统中定义的类 IndexManager 的一个实例。第三个是 analyzer,代表了用来解析搜索词的解析器。现在我们把注意力放在方法 search 上面。这个方法首先检查索引文件是否已经存在,如果已经存在,那么就在已经存在的索引上进行检索,如果不存在,那么首先调用类 IndexManager 提供的方法来创建索引,然后在新创建的索引上进行检索。搜索结果返回后,这个方法从搜索结果中提取出需要的属性并为每个搜索结果生成类 SearchResultBean 的一个实例。最后这些 SearchResultBean 的实例被放到一个列表里面并返回给请求管理器。

在类 SearchResultBean 中,含有两个属性,分别是 htmlPathhtmlTitle,以及这个两个属性的 get 和 set 方法。这也意味着我们的搜索结果包含两个属性:htmlPathhtmlTitle,其中 htmlPath 代表了 HTML 文件的路径,htmlTitle 代表了 HTML 文件的标题。

  1. 索引子系统: 类 IndexManager 用来实现这个子系统。清单8 给出了这个类的源代码。


清单8:索引子系统的实现

package sample.dw.paper.lucene.index;

import java.io.File;
import java.io.IOException;
import java.io.Reader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import sample.dw.paper.lucene.util.HTMLDocParser;

/**
 * This class is used to create an index for HTML files
 *
 */
public class IndexManager {

    //the directory that stores HTML files 
    private final String dataDir  = "c:\\dataDir";

    //the directory that is used to store a Lucene index
    private final String indexDir = "c:\\indexDir";

    /**
     * create index
     */
    public boolean createIndex() throws IOException{
        if(true == ifIndexExist()){
            return true;	
        }
        File dir = new File(dataDir);
        if(!dir.exists()){
            return false;
        }
        File[] htmls = dir.listFiles();
        Directory fsDirectory = FSDirectory.getDirectory(indexDir, true);
        Analyzer  analyzer    = new StandardAnalyzer();
        IndexWriter indexWriter = new IndexWriter(fsDirectory, analyzer, true);
        for(int i = 0; i < htmls.length; i++){
            String htmlPath = htmls[i].getAbsolutePath();

            if(htmlPath.endsWith(".html") || htmlPath.endsWith(".htm")){
        		addDocument(htmlPath, indexWriter);
        	}
        }
        indexWriter.optimize();
        indexWriter.close();
        return true;

    }

    /**
     * Add one document to the Lucene index
     */
    public void addDocument(String htmlPath, IndexWriter indexWriter){
        HTMLDocParser htmlParser = new HTMLDocParser(htmlPath);
        String path    = htmlParser.getPath();
        String title   = htmlParser.getTitle();
        Reader content = htmlParser.getContent();

        Document document = new Document();
        document.add(new Field("path",path,Field.Store.YES,Field.Index.NO));
        document.add(new Field("title",title,Field.Store.YES,Field.Index.TOKENIZED));
        document.add(new Field("content",content));
        try {
              indexWriter.addDocument(document);
    } catch (IOException e) {
              e.printStackTrace();
          }
    }

    /**
     * judge if the index exists already
     */
    public boolean ifIndexExist(){
        File directory = new File(indexDir);
        if(0 < directory.listFiles().length){
            return true;
        }else{
            return false;
        }
    }

    public String getDataDir(){
        return this.dataDir;
    }

    public String getIndexDir(){
        return this.indexDir;
    }

}

 

这个类包含两个私有属性,分别是 dataDirindexDirdataDir 代表存放等待进行索引的 HTML 页面的路径,indexDir 代表了存放 Lucene 索引文件的路径。类 IndexManager 提供了三个方法,分别是 createIndex, addDocumentifIndexExist。如果索引不存在的话,你可以使用方法 createIndex 去创建一个新的索引,用方法 addDocument 去向一个索引上添加文档。在我们的场景中,一个文档就是一个 HTML 页面。方法 addDocument 会调用由类 HTMLDocParser 提供的方法对 HTML 文档进行解析。你可以使用最后一个方法 ifIndexExist 来判断 Lucene 的索引是否已经存在。

现在我们来看一下放在包 sample.dw.paper.lucene.util 里面的类 HTMLDocParser。这个类用来从 HTML 文件中提取出文本信息。这个类包含三个方法,分别是 getContentgetTitlegetPath。第一个方法返回去除了 HTML 标记的文本内容,第二个方法返回 HTML 文件的标题,最后一个方法返回 HTML 文件的路径。清单9 给出了这个类的源代码。


清单9:HTML 解析器

package sample.dw.paper.lucene.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;

import org.apache.lucene.demo.html.HTMLParser;

public class HTMLDocParser {
    private String htmlPath;

    private HTMLParser htmlParser;

    public HTMLDocParser(String htmlPath){
        this.htmlPath = htmlPath;
        initHtmlParser();
    }

    private void initHtmlParser(){
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(htmlPath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if(null != inputStream){
	        try {
                htmlParser = new HTMLParser(new InputStreamReader(inputStream, "utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }

    public String getTitle(){
        if(null != htmlParser){
            try {
                return htmlParser.getTitle();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    return "";
    }

    public Reader getContent(){
    if(null != htmlParser){
            try {
                  return htmlParser.getReader();
              } catch (IOException e) {
                  e.printStackTrace();
              }
        }
        return null;
    }

    public String getPath(){
        return this.htmlPath;		
    }
}

 

5.在 Tomcat 5.0 上运行应用程序

现在我们可以在 Tomcat 5.0 上运行开发好的应用程序。

  1. 右键单击 search.jsp,然后选择 Run as > Run on Server,如图7所示。


图7:配置 Tomcat 5.0
配置 Tomcat 5.0

  1. 在弹出的窗口中,选择 Tomcat v5.0 Server 作为目标 Web 应用程序服务器,然后点击 Next,如图8 所示:


图8:选择 Tomcat 5.0
选择 Tomcat 5.0

  1. 现在需要指定用来运行 Web 应用程序的 Apache Tomcat 5.0 以及 JRE 的路径。这里你所选择的 JRE 的版本必须和你用来编译 Java 文件的 JRE 的版本一致。配置好之后,点击 Finish。如 图9 所示。


图9:完成Tomcat 5.0的配置
完成Tomcat 5.0的配置

  1. 配置好之后,Tomcat 会自动运行,并且会对 search.jsp 进行编译并显示给用户。如 图10 所示。


图10:用户界面
用户界面

  1. 在输入框中输入关键词 “information” 然后单击 Search 按钮。然后这个页面上会显示出搜索结果来,如 图11 所示。


图11:搜索结果
搜索结果

  1. 单击搜索结果的第一个链接,页面上就会显示出所链接到的页面的内容。如 图12 所示.


图12:详细信息
详细信息

现在我们已经成功的完成了示例项目的开发,并成功的用Lucene实现了搜索和索引功能。你可以下载这个项目的源代码(下载)。

 




回页首


总结

Lucene 提供了灵活的接口使我们更加方便的设计我们的 Web 搜索应用程序。如果你想在你的应用程序中加入搜索功能,那么 Lucene 是一个很好的选择。在设计你的下一个带有搜索功能的应用程序的时候可以考虑使用 Lucene 来提供搜索功能。





回页首


下载

描述 名字 大小 下载方法 Lucene Web 应用程序示例
wa-lucene2_source_code.zip 504KB HTTP
关于下载方法的信息
分享到:
评论

相关推荐

    vue3 访问通义千问聊天代码例子

    vue3 访问通义千问聊天代码例子

    基于Python的Flask-vue基于Hadoop的智慧校园数据共享平台实现源码-演示视频.zip

    基于Python的Flask-vue基于Hadoop的智慧校园数据共享平台实现源码-演示视频 项目关键技术 开发工具:Pycharm 编程语言: python 数据库: MySQL5.7+ 后端技术:Flask 前端技术:HTML 关键技术:HTML、MYSQL、Python 数据库工具:Navicat、SQLyog

    C#调用Ni板卡进行实现采集任务(模拟量输入输出)示例1

    【实验1】:读取一次AI0通道数值 【实验2】:一次读取AI0通道多个数值 【实验3】:单次模拟量输出 【实验4】:连续模拟量输出(输出一个正弦曲线)

    无人船的Smith-PID跟踪控制方法研究及实现:融合传统与最优PID策略的LOS曲线跟踪资料,基于无人船Smith-PID改进

    无人船的Smith-PID跟踪控制方法研究及实现:融合传统与最优PID策略的LOS曲线跟踪资料,基于无人船Smith-PID改进跟踪控制技术及其LOS曲线跟踪方法研究资料,基于无人船的smith-pid跟踪控制资料。 首先,针对pid进行了改进,有传统pid,最优pid和基于smith的pid三种控制方式。 然后还在smithpid基础上设计了LOS的曲线跟踪方法。 (有对应参考文献)。 有意者可直接联系,参考学习资料。 python语言。 ,基于无人船的Smith-PID跟踪控制; PID改进(传统PID、最优PID、基于Smith的PID); Smith-PID曲线跟踪方法; 参考学习资料; Python语言。,基于无人船的Smith-PID优化跟踪控制资料

    自研船舶电力推进系统MATLAB仿真报告:从柴油机+同步发电机到异步电机直接转矩控制的全面模拟与实践,船舶电力推进系统自搭MATLAB仿真报告:从柴油机同步发电机到异步电机直接转矩控制的完整过程与参

    自研船舶电力推进系统MATLAB仿真报告:从柴油机+同步发电机到异步电机直接转矩控制的全面模拟与实践,《船舶电力推进系统自搭MATLAB仿真报告:从柴油机同步发电机到异步电机直接转矩控制的完整过程与参数配置详解》,自己搭建的船舶电力推进系统(船舶电力推进自动控制)完全自搭MATLAB仿真,可适度,含对应27页正文的中文报告,稀缺资源,仿真包括船舶电站,变流系统和异步电机直接转矩控制,放心用吧。 三个文件逐层递进 柴油机+同步发电机(船舶电站) 柴油机+同步发电机+不控整流全桥逆变 柴油机+同步发电机+变流模块+异步电机直接转矩控制 所有参数都是配好的,最大负载参考变流系统所带负载两倍,再大柴油机和同步发电机参数就不匹配了,有能力可以自己调 ,核心关键词:船舶电力推进系统; MATLAB仿真; 船舶电站; 变流系统; 异步电机直接转矩控制; 柴油机; 同步发电机; 不控整流全桥逆变; 参数配比。,《船舶电力推进系统MATLAB仿真报告》

    西门子博图WinCC V15自动化系统项目实战:多服务器客户端下的PID DCS闭环控制及参数调整实战指南,西门子博图WinCC V15自动化系统项目实战:多服务器客户端下的PID DCS闭环控制及参

    西门子博图WinCC V15自动化系统项目实战:多服务器客户端下的PID DCS闭环控制及参数调整实战指南,西门子博图WinCC V15自动化系统项目实战:多服务器客户端下的PID DCS闭环控制及参数调整实战指南,西门子博图WinCC V 15大型自动化系统项目,包含多台服务器客户端项目,系统采用安全1516F -3PN DP 外挂多台精智面板,1200PLC ET200SP 变频器 对整个工艺过程PID DCS 闭环过程控制,如何调整温度压力流量液位等参数,实用工程项目案例 ,西门子博图WinCC V 15; 大型自动化系统; 多台服务器客户端; 安全外挂; 精智面板; 1200PLC ET200SP; 变频器; PID DCS; 闭环过程控制; 温度压力流量液位调整; 工程项目案例,西门子博图WinCC V15大型项目:多服务器客户端的PID DCS闭环控制与实用参数调整

    计算机网络资源全解析: 硬件、软件、协议及安全机制详解与应用

    内容概要:本文详尽介绍了计算机网络相关资源及其各方面构成要素,首先阐述了硬件层面的各种传输媒介和设备如双绞线、同轴电缆、光纤以及台式电脑、笔记本、大型计算机等设备,还包括网络互联所需的各类组件如网卡、交换机、路由器等。其次探讨了多种操作系统的特性和主要功能,以及各类通讯和支持应用程序的概述,涵盖浏览器、图像和视频编辑等常用软件。再深入讨论了多种常见网络协议如TCP、UDP、HTTP等的功能特性。最后还提到了确保网络安全运行的重要措施和工具如MIB、SNMP以及防火墙、入侵检测系统等。并且简要提到计算机网络在不同的应用环境,从局域网到移动网络。 适合人群:所有对计算机网络技术感兴趣的初学者和希望深入了解各个组成成分的技术人员. 使用场景及目标:为用户提供计算机网络资源全面而系统的认识,帮助他们建立对于该领域的理论和技术的扎实认知基础,提高在实际环境中识别配置及维护计算机网络系统的能力.

    【GPS北斗定位】基于matlab卡尔曼滤波KF北斗GPS单模和双模定位比较【含Matlab源码 10974期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    ABAQUS中隧道结构模型的无限元应用:超声激励源的施加方法、3D无限元吸收边界的添加技巧、模型结果精确性校核流程及教学视频与CAE、INP文件解析,ABAQUS隧道模型中3D无限元吸收边界的应用:超

    ABAQUS中隧道结构模型的无限元应用:超声激励源的施加方法、3D无限元吸收边界的添加技巧、模型结果精确性校核流程及教学视频与CAE、INP文件解析,ABAQUS隧道模型中3D无限元吸收边界的应用:超声激励源的施加与模型结果精确性校核的实践教程,ABAQUS无限元吸收边界,abaqus隧道无限元,1.超声激励源施加;2.3D无限元吸收边界添加方法;3.模型结果精确性校核;4.提供教学视频,cae、inp文件。 ,ABAQUS无限元吸收边界;ABAQUS隧道无限元;超声激励源施加;3D无限元吸收边界添加;模型结果精确性校核;CAE和INP文件。,ABAQUS中超声激励下无限元吸收边界设置及模型精度验证教程

    【SLAM】基于matlab扩展卡尔曼滤波器EKF同步定位与建图SLAM【含Matlab源码 10978期】复现.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    git自用lllllllllllllllllll

    git自用lllllllllllllllllll

    【Django小白项目】参照本,包含python、HTML、Django

    本资源与文章【Django小白项目】为一体,此为已成功项目,供给给Django初学者做参考,有不会的问题可以私信我噢~

    C++矩阵运算库matrix

    使用一维数据表示向量和二维矩阵,支持常用运算。

    基于STM32的宠物自动喂食器系统设计.pdf

    1、以上文章可用于参考,请勿直接抄袭,学习、当作参考文献可以,主张借鉴学习 2、资源本身不含 对应项目代码,如需完整项目源码,请私信博主获取

    基于多目标粒子群优化算法(MOPSO)的微电网多目标经济运行分析与优化策略考虑响应侧响应的协同调度策略,基于多目标粒子群优化算法(MOPSO)的微电网经济调度优化:含风光储荷一体化模型与需求侧响应策略

    基于多目标粒子群优化算法(MOPSO)的微电网多目标经济运行分析与优化策略考虑响应侧响应的协同调度策略,基于多目标粒子群优化算法(MOPSO)的微电网经济调度优化:含风光储荷一体化模型与需求侧响应策略,考虑需求侧响应的微电网多目标经济运行 建立了含风光储荷的微电网模型,以发电侧成本(包括风光储以及电网的购电成本)和负荷侧成本最小为目标,考虑功率平衡以及储能SOC约束,建立了多目标优化模型,通过分时电价引导负荷需求侧响应,得到可削减负荷量,同时求解模型,得到风光储以及电网的运行计划。 这段代码是一个使用多目标粒子群优化算法(MOPSO)解决问题的程序。下面我将对程序进行详细的分析和解释。 首先,程序的目标是通过优化算法来解决一个多目标优化问题。程序中使用的优化算法是多目标粒子群优化算法(MOPSO),该算法通过迭代更新粒子的位置和速度来搜索最优解。 程序的主要功能是对能源系统进行优化调度,包括光伏发电、风力发电、储能和电网供电。程序的目标是最小化能源系统的成本,并满足负荷需求。 程序的主要思路是使用粒子群优化算法来搜索最优解。程序中定义了一个粒子类(Particle),每个粒子代

    data.gov.sg geojson部分项目整理

    data.gov.sg geojson部分项目整理

    基于MATLAB Simulink的避障功能欠驱动无人船航迹跟踪控制仿真实验研究,基于MATLAB Simulink的欠驱动无人船避障功能路径跟踪控制仿真实验研究,包含避障功能的欠驱动无人船航迹(路径

    基于MATLAB Simulink的避障功能欠驱动无人船航迹跟踪控制仿真实验研究,基于MATLAB Simulink的欠驱动无人船避障功能路径跟踪控制仿真实验研究,包含避障功能的欠驱动无人船航迹(路径)跟踪控制仿真实验,基于MATLAB Simulink制作 ,避障功能; 欠驱动无人船; 航迹(路径)跟踪控制; MATLAB Simulink 仿真实验; 避障算法。,基于MATLAB Simulink的避障无人船航迹跟踪控制仿真实验

    【车间调度】基于matlab樽海鞘算法求解带小车的车间调度AGV-fjsp问题【含Matlab源码 3283期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【雷达干扰】基于matlab汽车雷达系统中FMCW雷达干扰【含Matlab源码 10018期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

Global site tag (gtag.js) - Google Analytics