IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> ubuntu20.04安装ros Noetic Ninjemys教程及部分问题汇总 -> 正文阅读

[系统运维]ubuntu20.04安装ros Noetic Ninjemys教程及部分问题汇总

双系统或者虚拟机都可用这种方法安装,亲测有效

参考博主:https://www.bilibili.com/read/cv13788562/

制作Ubuntu启动U盘和相关的安装比较简单,不在这儿讲了

1:准备工作:

一定要把Ubuntu里面的软件更新里面的网址改为阿里云镜像的,不然后续安装慢,容易time out,如图:
在这里插入图片描述源代码那一框可不勾选

2:添加源

之前版本的源文件应该有问题,看网上大佬说是不适配Ubuntu20.04,打开终端。输入:

sudo gedit /etc/apt/sources.list 

可以点出一个文件,在文件最下面添加下面代码,如果不进行添加的话会在第四步出现更新失败或者错误

#添加阿里源

deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse 

3:更新源

sudo apt-get update  

4:更新软件

sudo apt-get upgrade 

5:安装清华源

sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/ros-latest.list' 

6:设置秘钥

sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

7:运行一下更新

sudo apt update

8:安装ros-noetic版本

在网上看到不同版本其支持的ros版本不同,Ubuntu20.04支持ros-noetic

sudo apt install ros-noetic-desktop-full 

9:设置环境变量

每次在Ubuntu用右键打开一个新的终端都需要进行这个设置,但如果使用终端框左上角的小加号则不用
在这里插入图片描述

source /opt/ros/noetic/setup.bash

大佬说下面的命令是可以在每次启动新的shell窗口时很方便地为你自动source一下这个脚本。

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrcsource ~/.bashrc 

10:构建依赖关系

这个也是在每个终端打开的时候进行设置,不然有时候报错找不到相关命令,如果按照终端提示进行一些软件的安装和下载后运行相关的指令还是会无法创建,报错依赖关系相关的错误

sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential

11:初始化 rosdep

sudo apt install python3-rosdep 

12: 运行rosdep init

12.1: 运行rosdep init成功

sudo rosdep init 

关于这个命令一般不会出错,我第一次安装的是双系统,没有报错,然后安装的VMware虚拟机,报错了,如果没报错是让你运行rosdep update,直接转入运行rosdep update,如果报错进行以下修改

12.2:运行rosdep init失败

12.2.1:打开host及相关文件进行修改

进入hosts,打开文件

sudo gedit /etc/hosts

在ipv4的部分加入

185.199.108.133    raw.githubusercontent.com

185.199.109.133    raw.githubusercontent.com

185.199.110.133    raw.githubusercontent.com

185.199.111.133    raw.githubusercontent.com 

保存后退出

12.2.2:再次运行sudo rosdep init

sudo rosdep init

如果还是不行,切换个网络,比如手机热点再试几次

13: 运行rosdep update

rosdep update

13.1:如果运行rosdep update报错

13.1.1如果报错超时

一般报错为:The read operation timed out。
具体思路是下载报错内容20-default.list里面的5个网址,我们可以把这一步需要访问的包先下载下来,然后修改20-default.list文件,使其指向我们本地下载好的文件,离线更新,具体步骤如下:

1. 通过git clone将安装包下载:(要先安装git软件)
git clone https://github.com/ros/rosdistro.git

若下载较慢,可以通过访问Github镜像下载:

git clone https://github.com.cnpmjs.org/ros/rosdistro.git 

(这个网址我一般是无法访问)
到这一步会在Ubuntu下载一个rosdistro文件夹,需要进入根目录右键终端打开输入pwd查看路径,后面要用最好记住你自己的路径比如我的: /home/linder/DeskTop/rosdistro,大大们要自己查看路径别搞错了

2. 修改rep3.py

进入路径

cd /usr/lib/python3/dist-packages

如果已经是在这个路径下,会提示找不到,大大们注意观察
调出rep3.py文件

sudo gedit rosdep2/rep3.py

原文件

# Copyright (c) 2012, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the Willow Garage, Inc. nor the names of its
#       contributors may be used to endorse or promote products derived from
#       this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

try:
    from urllib.request import urlopen
except ImportError:
    from urllib2 import urlopen
import yaml
import warnings

from .core import DownloadFailure
from .rosdistrohelper import PreRep137Warning

# location of targets file for processing gbpdistro files
REP3_TARGETS_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/releases/targets.yaml'

# seconds to wait before aborting download of gbpdistro data
DOWNLOAD_TIMEOUT = 15.0


def download_targets_data(targets_url=None):
    """
    Download REP 3 targets file and unmarshal from YAML.
    DEPRECATED: this function is deprecated. List of targets should be obtained
                from the rosdistro module.
                The body of this function is an example.

    :param target_url: override URL of platform targets file. Defaults
      to ``REP3_TARGETS_URL``.
    :raises: :exc:`DownloadFailure`
    :raises: :exc:`InvalidData` If targets file does not pass cursory validation checks.
    """
    warnings.warn('deprecated, use rosdistro instead', PreRep137Warning)

    if targets_url is None:
        targets_url = REP3_TARGETS_URL
    try:
        f = urlopen(targets_url, timeout=DOWNLOAD_TIMEOUT)
        text = f.read()
        f.close()
        targets_data = yaml.safe_load(text)
    except Exception as e:
        raise DownloadFailure('Failed to download target platform data for gbpdistro:\n\t%s' % (str(e)))
    if type(targets_data) == list:
        # convert to dictionary
        new_targets_data = {}
        for t in targets_data:
            platform = list(t.keys())[0]
            new_targets_data[platform] = t[platform]
        targets_data = new_targets_data
    return targets_data

将原来的 REP3_TARGETS_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/releases/targets.yaml’用 # 注释掉,修改成以下代码,主要是把你的文件路径进行替换,下面的文件路径是我装的时候的路径,大家注意,大家注意,大家注意

REP3_TARGETS_URL = 'file: /home/linder/DeskTop/rosdistro/releases/targets.yaml'  

保存并关闭

2. 修改sources_list.py

调出sources_list.py 文件

sudo gedit rosdep2/sources_list.py

原文件

# Copyright (c) 2012, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the Willow Garage, Inc. nor the names of its
#       contributors may be used to endorse or promote products derived from
#       this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

# Author Ken Conley/kwc@willowgarage.com

from __future__ import print_function

import os
import sys
import yaml
try:
    from urllib.request import urlopen
    from urllib.error import URLError
    import urllib.request as request
except ImportError:
    from urllib2 import urlopen
    from urllib2 import URLError
    import urllib2 as request
try:
    import cPickle as pickle
except ImportError:
    import pickle

from .cache_tools import compute_filename_hash, PICKLE_CACHE_EXT, write_atomic, write_cache_file
from .core import InvalidData, DownloadFailure, CachePermissionError
from .gbpdistro_support import get_gbprepo_as_rosdep_data, download_gbpdistro_as_rosdep_data
from .meta import MetaDatabase
from ._version import __version__

try:
    import urlparse
except ImportError:
    import urllib.parse as urlparse  # py3k

try:
    import httplib
except ImportError:
    import http.client as httplib  # py3k

import rospkg
import rospkg.distro

from .loader import RosdepLoader
from .rosdistrohelper import get_index, get_index_url

# default file to download with 'init' command in order to bootstrap
# rosdep
DEFAULT_SOURCES_LIST_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list'

# seconds to wait before aborting download of rosdep data
DOWNLOAD_TIMEOUT = 15.0

SOURCES_LIST_DIR = 'sources.list.d'
SOURCES_CACHE_DIR = 'sources.cache'

# name of index file for sources cache
CACHE_INDEX = 'index'

# extension for binary cache
SOURCE_PATH_ENV = 'ROSDEP_SOURCE_PATH'


def get_sources_list_dirs(source_list_dir):
    if SOURCE_PATH_ENV in os.environ:
        sdirs = os.environ[SOURCE_PATH_ENV].split(os.pathsep)
    else:
        sdirs = [source_list_dir]
    for p in list(sdirs):
        if not os.path.exists(p):
            sdirs.remove(p)
    return sdirs


def get_sources_list_dir():
    # base of where we read config files from
    # TODO: windows
    if 0:
        # we can't use etc/ros because environment config does not carry over under sudo
        etc_ros = rospkg.get_etc_ros_dir()
    else:
        etc_ros = '/etc/ros'
    # compute default system wide sources directory
    sys_sources_list_dir = os.path.join(etc_ros, 'rosdep', SOURCES_LIST_DIR)
    sources_list_dirs = get_sources_list_dirs(sys_sources_list_dir)
    if sources_list_dirs:
        return sources_list_dirs[0]
    else:
        return sys_sources_list_dir


def get_default_sources_list_file():
    return os.path.join(get_sources_list_dir(), '20-default.list')


def get_sources_cache_dir():
    ros_home = rospkg.get_ros_home()
    return os.path.join(ros_home, 'rosdep', SOURCES_CACHE_DIR)


# Default rosdep.yaml format.  For now this is the only valid type and
# is specified for future compatibility.
TYPE_YAML = 'yaml'
# git-buildpackage repo list
TYPE_GBPDISTRO = 'gbpdistro'
VALID_TYPES = [TYPE_YAML, TYPE_GBPDISTRO]


class DataSource(object):

    def __init__(self, type_, url, tags, origin=None):
        """
        :param type_: data source type, e.g. TYPE_YAML, TYPE_GBPDISTRO

        :param url: URL of data location.  For file resources, must
          start with the file:// scheme.  For remote resources, URL
          must include a path.

        :param tags: tags for matching data source to configurations
        :param origin: filename or other indicator of where data came from for debugging.

        :raises: :exc:`ValueError` if parameters do not validate
        """
        # validate inputs
        if type_ not in VALID_TYPES:
            raise ValueError('type must be one of [%s]' % (','.join(VALID_TYPES)))
        parsed = urlparse.urlparse(url)
        if not parsed.scheme or (parsed.scheme != 'file' and not parsed.netloc) or parsed.path in ('', '/'):
            raise ValueError('url must be a fully-specified URL with scheme, hostname, and path: %s' % (str(url)))
        if not type(tags) == list:
            raise ValueError('tags must be a list: %s' % (str(tags)))

        self.type = type_
        self.tags = tags

        self.url = url
        self.origin = origin

    def __eq__(self, other):
        return isinstance(other, DataSource) and \
            self.type == other.type and \
            self.tags == other.tags and \
            self.url == other.url and \
            self.origin == other.origin

    def __str__(self):
        if self.origin:
            return '[%s]:\n%s %s %s' % (self.origin, self.type, self.url, ' '.join(self.tags))
        else:
            return '%s %s %s' % (self.type, self.url, ' '.join(self.tags))

    def __repr__(self):
        return repr((self.type, self.url, self.tags, self.origin))


class RosDistroSource(DataSource):

    def __init__(self, distro):
        self.type = TYPE_GBPDISTRO
        self.tags = [distro]
        # In this case self.url is a list if REP-143 is being used
        self.url = get_index().distributions[distro]['distribution']
        self.origin = None

# create function we can pass in as model to parse_source_data.  The
# function emulates the CachedDataSource constructor but does the
# necessary full filepath calculation and loading of data.


def cache_data_source_loader(sources_cache_dir, verbose=False):
    def create_model(type_, uri, tags, origin=None):
        # compute the filename has from the URL
        filename = compute_filename_hash(uri)
        filepath = os.path.join(sources_cache_dir, filename)
        pickle_filepath = filepath + PICKLE_CACHE_EXT
        if os.path.exists(pickle_filepath):
            if verbose:
                print('loading cached data source:\n\t%s\n\t%s' % (uri, pickle_filepath), file=sys.stderr)
            with open(pickle_filepath, 'rb') as f:
                rosdep_data = pickle.loads(f.read())
        elif os.path.exists(filepath):
            if verbose:
                print('loading cached data source:\n\t%s\n\t%s' % (uri, filepath), file=sys.stderr)
            with open(filepath) as f:
                rosdep_data = yaml.safe_load(f.read())
        else:
            rosdep_data = {}
        return CachedDataSource(type_, uri, tags, rosdep_data, origin=filepath)
    return create_model


class CachedDataSource(object):

    def __init__(self, type_, url, tags, rosdep_data, origin=None):
        """
        Stores data source and loaded rosdep data for that source.

        NOTE: this is not a subclass of DataSource, though it's API is
        duck-type compatible with the DataSource API.
        """
        self.source = DataSource(type_, url, tags, origin=origin)
        self.rosdep_data = rosdep_data

    def __eq__(self, other):
        try:
            return self.source == other.source and \
                self.rosdep_data == other.rosdep_data
        except AttributeError:
            return False

    def __str__(self):
        return '%s\n%s' % (self.source, self.rosdep_data)

    def __repr__(self):
        return repr((self.type, self.url, self.tags, self.rosdep_data, self.origin))

    @property
    def type(self):
        """
        :returns: data source type
        """
        return self.source.type

    @property
    def url(self):
        """
        :returns: data source URL
        """
        return self.source.url

    @property
    def tags(self):
        """
        :returns: data source tags
        """
        return self.source.tags

    @property
    def origin(self):
        """
        :returns: data source origin, if set, or ``None``
        """
        return self.source.origin


class DataSourceMatcher(object):

    def __init__(self, tags):
        self.tags = tags

    def matches(self, rosdep_data_source):
        """
        Check if the datasource matches this configuration.

        :param rosdep_data_source: :class:`DataSource`
        """
        # all of the rosdep_data_source tags must be in our matcher tags
        return not any(set(rosdep_data_source.tags) - set(self.tags))

    @staticmethod
    def create_default(os_override=None):
        """
        Create a :class:`DataSourceMatcher` to match the current
        configuration.

        :param os_override: (os_name, os_codename) tuple to override
            OS detection
        :returns: :class:`DataSourceMatcher`
        """
        distro_name = rospkg.distro.current_distro_codename()
        if os_override is None:
            os_detect = rospkg.os_detect.OsDetect()
            os_name, os_version, os_codename = os_detect.detect_os()
        else:
            os_name, os_codename = os_override
        tags = [t for t in (distro_name, os_name, os_codename) if t]
        return DataSourceMatcher(tags)


def download_rosdep_data(url):
    """
    :raises: :exc:`DownloadFailure` If data cannot be
        retrieved (e.g. 404, bad YAML format, server down).
    """
    try:
        # http/https URLs need custom requests to specify the user-agent, since some repositories reject
        # requests from the default user-agent.
        if url.startswith("http://") or url.startswith("https://"):
            url_request = request.Request(url, headers={'User-Agent': 'rosdep/{version}'.format(version=__version__)})
        else:
            url_request = url
        f = urlopen(url_request, timeout=DOWNLOAD_TIMEOUT)
        text = f.read()
        f.close()
        data = yaml.safe_load(text)
        if type(data) != dict:
            raise DownloadFailure('rosdep data from [%s] is not a YAML dictionary' % (url))
        return data
    except (URLError, httplib.HTTPException) as e:
        raise DownloadFailure(str(e) + ' (%s)' % url)
    except yaml.YAMLError as e:
        raise DownloadFailure(str(e))


def download_default_sources_list(url=DEFAULT_SOURCES_LIST_URL):
    """
    Download (and validate) contents of default sources list.

    :param url: override URL of default sources list file
    :return: raw sources list data, ``str``
    :raises: :exc:`DownloadFailure` If data cannot be
            retrieved (e.g. 404, bad YAML format, server down).
    :raises: :exc:`urllib2.URLError` If data cannot be
        retrieved (e.g. 404, server down).
    """
    try:
        f = urlopen(url, timeout=DOWNLOAD_TIMEOUT)
    except (URLError, httplib.HTTPException) as e:
        raise URLError(str(e) + ' (%s)' % url)
    data = f.read().decode()
    f.close()
    if not data:
        raise DownloadFailure('cannot download defaults file from %s : empty contents' % url)
    # parse just for validation
    try:
        parse_sources_data(data)
    except InvalidData as e:
        raise DownloadFailure(
            'The content downloaded from %s failed to pass validation.'
            ' It is likely that the source is invalid unless the data was corrupted during the download.'
            ' The contents were:{{{%s}}} The error raised was: %s' % (url, data, e))
    return data


def parse_sources_data(data, origin='<string>', model=None):
    """
    Parse sources file format (tags optional)::

      # comments and empty lines allowed
      <type> <uri> [tags]

    e.g.::

      yaml http://foo/rosdep.yaml fuerte lucid ubuntu

    If tags are specified, *all* tags must match the current
    configuration for the sources data to be used.

    :param data: data in sources file format
    :param model: model to load data into.  Defaults to :class:`DataSource`

    :returns: List of data sources, [:class:`DataSource`]
    :raises: :exc:`InvalidData`
    """
    if model is None:
        model = DataSource

    sources = []
    for line in data.split('\n'):
        line = line.strip()
        # ignore empty lines or comments
        if not line or line.startswith('#'):
            continue
        splits = line.split(' ')
        if len(splits) < 2:
            raise InvalidData('invalid line:\n%s' % (line), origin=origin)
        type_ = splits[0]
        url = splits[1]
        tags = splits[2:]
        try:
            sources.append(model(type_, url, tags, origin=origin))
        except ValueError as e:
            raise InvalidData('line:\n\t%s\n%s' % (line, e), origin=origin)
    return sources


def parse_sources_file(filepath):
    """
    Parse file on disk

    :returns: List of data sources, [:class:`DataSource`]
    :raises: :exc:`InvalidData` If any error occurs reading
        file, so an I/O error, non-existent file, or invalid format.
    """
    try:
        with open(filepath, 'r') as f:
            return parse_sources_data(f.read(), origin=filepath)
    except IOError as e:
        raise InvalidData('I/O error reading sources file: %s' % (str(e)), origin=filepath)


def parse_sources_list(sources_list_dir=None):
    """
    Parse data stored in on-disk sources list directory into a list of
    :class:`DataSource` for processing.

    :returns: List of data sources, [:class:`DataSource`]. If there is
        no sources list dir, this returns an empty list.
    :raises: :exc:`InvalidData`
    :raises: :exc:`OSError` if *sources_list_dir* cannot be read.
    :raises: :exc:`IOError` if *sources_list_dir* cannot be read.
    """
    if sources_list_dir is None:
        sources_list_dir = get_sources_list_dir()
    sources_list_dirs = get_sources_list_dirs(sources_list_dir)

    filelist = []
    for sdir in sources_list_dirs:
        filelist += sorted([os.path.join(sdir, f) for f in os.listdir(sdir) if f.endswith('.list')])
    sources_list = []
    for f in filelist:
        sources_list.extend(parse_sources_file(f))
    return sources_list


def _generate_key_from_urls(urls):
    # urls may be a list of urls or a single string
    try:
        assert isinstance(urls, (list, basestring))
    except NameError:
        assert isinstance(urls, (list, str))
    # We join the urls by the '^' character because it is not allowed in urls
    return '^'.join(urls if isinstance(urls, list) else [urls])


def update_sources_list(sources_list_dir=None, sources_cache_dir=None,
                        success_handler=None, error_handler=None,
                        skip_eol_distros=False, ros_distro=None):
    """
    Re-downloaded data from remote sources and store in cache.  Also
    update the cache index based on current sources.

    :param sources_list_dir: override source list directory
    :param sources_cache_dir: override sources cache directory
    :param success_handler: fn(DataSource) to call if a particular
        source loads successfully.  This hook is mainly for printing
        errors to console.
    :param error_handler: fn(DataSource, DownloadFailure) to call
        if a particular source fails.  This hook is mainly for
        printing errors to console.
    :param skip_eol_distros: skip downloading sources for EOL distros

    :returns: list of (`DataSource`, cache_file_path) pairs for cache
        files that were updated, ``[str]``
    :raises: :exc:`InvalidData` If any of the sources list files is invalid
    :raises: :exc:`OSError` if *sources_list_dir* cannot be read.
    :raises: :exc:`IOError` If *sources_list_dir* cannot be read or cache data cannot be written
    """
    if sources_cache_dir is None:
        sources_cache_dir = get_sources_cache_dir()

    sources = parse_sources_list(sources_list_dir=sources_list_dir)
    retval = []
    for source in list(sources):
        try:
            if source.type == TYPE_YAML:
                rosdep_data = download_rosdep_data(source.url)
            elif source.type == TYPE_GBPDISTRO:  # DEPRECATED, do not use this file. See REP137
                if not source.tags[0] in ['electric', 'fuerte']:
                    print('Ignore legacy gbpdistro "%s"' % source.tags[0])
                    sources.remove(source)
                    continue  # do not store this entry in the cache
                rosdep_data = download_gbpdistro_as_rosdep_data(source.url)
            retval.append((source, write_cache_file(sources_cache_dir, source.url, rosdep_data)))
            if success_handler is not None:
                success_handler(source)
        except DownloadFailure as e:
            if error_handler is not None:
                error_handler(source, e)

    # Additional sources for ros distros
    # In compliance with REP137 and REP143
    python_versions = {}

    print('Query rosdistro index %s' % get_index_url())
    distribution_names = get_index().distributions.keys()
    if ros_distro is not None and ros_distro not in distribution_names:
        raise ValueError(
            'Requested distribution "%s" is not in the index.' % ros_distro)

    for dist_name in sorted(distribution_names):
        distribution = get_index().distributions[dist_name]
        if dist_name != ros_distro:
            if ros_distro is not None:
                print('Skip distro "%s" different from requested "%s"' % (dist_name, ros_distro))
                continue
            if skip_eol_distros:
                if distribution.get('distribution_status') == 'end-of-life':
                    print('Skip end-of-life distro "%s"' % dist_name)
                    continue
        print('Add distro "%s"' % dist_name)
        rds = RosDistroSource(dist_name)
        rosdep_data = get_gbprepo_as_rosdep_data(dist_name)
        # Store Python version from REP153
        if distribution.get('python_version'):
            python_versions[dist_name] = distribution.get('python_version')
        # dist_files can either be a string (single filename) or a list (list of filenames)
        dist_files = distribution['distribution']
        key = _generate_key_from_urls(dist_files)
        retval.append((rds, write_cache_file(sources_cache_dir, key, rosdep_data)))
        sources.append(rds)

    # cache metadata that isn't a source list
    MetaDatabase().set('ROS_PYTHON_VERSION', python_versions)

    # Create a combined index of *all* the sources.  We do all the
    # sources regardless of failures because a cache from a previous
    # attempt may still exist.  We have to do this cache index so that
    # loads() see consistent data.
    if not os.path.exists(sources_cache_dir):
        os.makedirs(sources_cache_dir)
    cache_index = os.path.join(sources_cache_dir, CACHE_INDEX)
    data = "#autogenerated by rosdep, do not edit. use 'rosdep update' instead\n"
    for source in sources:
        url = _generate_key_from_urls(source.url)
        data += 'yaml %s %s\n' % (url, ' '.join(source.tags))
    write_atomic(cache_index, data)
    # mainly for debugging and testing
    return retval


def load_cached_sources_list(sources_cache_dir=None, verbose=False):
    """
    Load cached data based on the sources list.

    :returns: list of :class:`CachedDataSource` instance with raw
        rosdep data loaded.
    :raises: :exc:`OSError` if cache cannot be read
    :raises: :exc:`IOError` if cache cannot be read
    """
    if sources_cache_dir is None:
        sources_cache_dir = get_sources_cache_dir()
    cache_index = os.path.join(sources_cache_dir, 'index')
    if not os.path.exists(cache_index):
        if verbose:
            print('no cache index present, not loading cached sources', file=sys.stderr)
        return []
    try:
        with open(cache_index, 'r') as f:
            cache_data = f.read()
    except IOError as e:
        if e.strerror == 'Permission denied':
            raise CachePermissionError('Failed to write cache file: ' + str(e))
        else:
            raise
    # the loader does all the work
    model = cache_data_source_loader(sources_cache_dir, verbose=verbose)
    return parse_sources_data(cache_data, origin=cache_index, model=model)


class SourcesListLoader(RosdepLoader):
    """
    SourcesList loader implements the general RosdepLoader API.  This
    implementation is fairly simple as there is only one view the
    source list loader can create.  It is also a bit degenerate as it
    is not capable of mapping resource names to views, thus any
    resource-name-based API fails or returns nothing interesting.

    This loader should not be used directly; instead, it is more
    useful composed with other higher-level implementations, like the
    :class:`rosdep2.rospkg_loader.RospkgLoader`.  The general intent
    is to compose it with another loader by making all of the other
    loader's views depends on all the views in this loader.
    """

    ALL_VIEW_KEY = 'sources.list'

    def __init__(self, sources):
        """
        :param sources: cached sources list entries, [:class:`CachedDataSource`]
        """
        self.sources = sources

    @staticmethod
    def create_default(matcher=None, sources_cache_dir=None, os_override=None, verbose=False):
        """
        :param matcher: override DataSourceMatcher.  Defaults to
            DataSourceMatcher.create_default().
        :param sources_cache_dir: override location of sources cache
        """
        if matcher is None:
            matcher = DataSourceMatcher.create_default(os_override=os_override)
        if verbose:
            print('using matcher with tags [%s]' % (', '.join(matcher.tags)), file=sys.stderr)

        sources = load_cached_sources_list(sources_cache_dir=sources_cache_dir, verbose=verbose)
        if verbose:
            print('loaded %s sources' % (len(sources)), file=sys.stderr)
        sources = [x for x in sources if matcher.matches(x)]
        if verbose:
            print('%s sources match current tags' % (len(sources)), file=sys.stderr)
        return SourcesListLoader(sources)

    def load_view(self, view_name, rosdep_db, verbose=False):
        """
        Load view data into rosdep_db. If the view has already been
        loaded into rosdep_db, this method does nothing.

        :param view_name: name of ROS stack to load, ``str``
        :param rosdep_db: database to load stack data into, :class:`RosdepDatabase`

        :raises: :exc:`InvalidData`
        """
        if rosdep_db.is_loaded(view_name):
            return
        source = self.get_source(view_name)
        if verbose:
            print('loading view [%s] with sources.list loader' % (view_name), file=sys.stderr)
        view_dependencies = self.get_view_dependencies(view_name)
        rosdep_db.set_view_data(view_name, source.rosdep_data, view_dependencies, view_name)

    def get_loadable_resources(self):
        return []

    def get_loadable_views(self):
        return [x.url for x in self.sources]

    def get_view_dependencies(self, view_name):
        # use dependencies to implement precedence
        if view_name != SourcesListLoader.ALL_VIEW_KEY:
            # if the view_name matches one of our sources, return
            # empty list as none of our sources has deps.
            if any([x for x in self.sources if view_name == x.url]):
                return []

        # not one of our views, so it depends on everything we provide
        return [x.url for x in self.sources]

    def get_source(self, view_name):
        matches = [x for x in self.sources if x.url == view_name]
        if matches:
            return matches[0]
        else:
            raise rospkg.ResourceNotFound(view_name)

    def get_rosdeps(self, resource_name, implicit=True):
        """
        Always raises as SourceListLoader defines no concrete resources with rosdeps.

        :raises: :exc:`rospkg.ResourceNotFound`
        """
        raise rospkg.ResourceNotFound(resource_name)

    def get_view_key(self, resource_name):
        """
        Always raises as SourceListLoader defines no concrete resources with rosdeps.

        :returns: Name of view that *resource_name* is in, ``None`` if no associated view.
        :raises: :exc:`rospkg.ResourceNotFound` if *resource_name* cannot be found.
        """
        raise rospkg.ResourceNotFound(resource_name)

将原来的这一行代码修改成以下这种,注意改成自己的路径,注意改成自己的路径,注意改成自己的路径

DEFAULT_SOURCES_LIST_URL = 'file: /home/linderven/DeskTop/rosdistro/rosdep/sources.list.d/20-default.list'

保存并关闭

2. 修改__init__.py
sudo gedit rosdistro/__init__.py

原文件

# Software License Agreement (BSD License)
#
# Copyright (c) 2013, Open Source Robotics Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above
#    copyright notice, this list of conditions and the following
#    disclaimer in the documentation and/or other materials provided
#    with the distribution.
#  * Neither the name of Open Source Robotics Foundation, Inc. nor
#    the names of its contributors may be used to endorse or promote
#    products derived from this software without specific prior
#    written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

from __future__ import print_function

import gzip
import logging
import os
try:
    from cStringIO import StringIO
except ImportError:
    from io import BytesIO as StringIO
try:
    from urllib.parse import urlparse
except ImportError:
    from urlparse import urlparse
import yaml

logger = logging.getLogger('rosdistro')

from .distribution import Distribution  # noqa
from .distribution_cache import DistributionCache  # noqa
from .distribution_file import DistributionFile  # noqa
from .distribution_file import create_distribution_file  # noqa
from .external.appdirs import site_config_dir, user_config_dir  # noqa
from .index import Index  # noqa
from .loader import load_url  # noqa
from .manifest_provider.cache import CachedManifestProvider, CachedSourceManifestProvider  # noqa


# same version as in:
# - setup.py
# - stdeb.cfg
__version__ = '0.8.3'

# index information

DEFAULT_INDEX_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/index-v4.yaml'


def get_index_url():
    # environment variable has precedence over configuration files
    if 'ROSDISTRO_INDEX_URL' in os.environ:
        return os.environ['ROSDISTRO_INDEX_URL']

    def read_cfg_index_url(fname):
        try:
            with open(fname) as f:
                return yaml.safe_load(f.read())['index_url']
        except (IOError, KeyError, yaml.YAMLError):
            return None

    cfg_file = 'config.yaml'

    # first, look for the user configuration (usually ~/.config/rosdistro)
    user_cfg_path = os.path.join(user_config_dir('rosdistro'), cfg_file)
    index_url = read_cfg_index_url(user_cfg_path)
    if index_url is not None:
        return index_url

    # if not found, look for the global configuration *usually /etc/xdg/rosdistro)
    site_cfg_paths = os.path.join(site_config_dir('rosdistro', multipath=True), cfg_file).split(os.pathsep)
    for site_cfg_path in site_cfg_paths:
        index_url = read_cfg_index_url(site_cfg_path)
        if index_url is not None:
            return index_url

    # if nothing is found, use the default
    return DEFAULT_INDEX_URL


def get_index(url):
    logger.debug('Load index from "%s"' % url)
    yaml_str = load_url(url)
    data = yaml.safe_load(yaml_str)
    base_url = os.path.dirname(url)
    url_parts = urlparse(url)
    return Index(data, base_url, url_query=url_parts.query)


# distribution information

def get_distribution(index, dist_name):
    dist_file = get_distribution_file(index, dist_name)
    return Distribution(dist_file)


def get_distribution_file(index, dist_name):
    data = _get_dist_file_data(index, dist_name, 'distribution')
    return create_distribution_file(dist_name, data)


def get_distribution_files(index, dist_name):
    data = _get_dist_file_data(index, dist_name, 'distribution')
    if not isinstance(data, list):
        data = [data]
    dist_files = []
    for d in data:
        dist_file = DistributionFile(dist_name, d)
        dist_files.append(dist_file)
    return dist_files


def get_cached_distribution(index, dist_name, cache=None, allow_lazy_load=False):
    if cache is None:
        try:
            cache = get_distribution_cache(index, dist_name)
        except Exception:
            if not allow_lazy_load:
                raise
            # create empty cache instance
            dist_file_data = _get_dist_file_data(index, dist_name, 'distribution')
            cache = DistributionCache(dist_name, distribution_file_data=dist_file_data)
    dist = Distribution(
        cache.distribution_file,
        [CachedManifestProvider(cache, Distribution.default_manifest_providers if allow_lazy_load else None)],
        [CachedSourceManifestProvider(cache, Distribution.default_source_manifest_providers if allow_lazy_load else None)])
    assert cache.distribution_file.name == dist_name
    return dist


def get_distribution_cache_string(index, dist_name):
    if dist_name not in index.distributions.keys():
        raise RuntimeError("Unknown distribution: '{0}'. Valid distribution names are: {1}".format(dist_name, ', '.join(sorted(index.distributions.keys()))))
    dist = index.distributions[dist_name]
    if 'distribution_cache' not in dist.keys():
        raise RuntimeError("Distribution has no cache: '{0}'".format(dist_name))
    url = dist['distribution_cache']

    logger.debug('Load cache from "%s"' % url)
    if url.endswith('.yaml'):
        yaml_str = load_url(url)
    elif url.endswith('.yaml.gz'):
        yaml_gz_str = load_url(url, skip_decode=True)
        yaml_gz_stream = StringIO(yaml_gz_str)
        f = gzip.GzipFile(fileobj=yaml_gz_stream, mode='rb')
        yaml_str = f.read()
        f.close()
        if not isinstance(yaml_str, str):
            yaml_str = yaml_str.decode('utf-8')
    else:
        raise NotImplementedError('The url of the cache must end with either ".yaml" or ".yaml.gz"')
    return yaml_str


def get_distribution_cache(index, dist_name):
    yaml_str = get_distribution_cache_string(index, dist_name)
    data = yaml.safe_load(yaml_str)
    return DistributionCache(dist_name, data)


# internal

def _get_dist_file_data(index, dist_name, type_):
    if dist_name not in index.distributions.keys():
        raise RuntimeError("Unknown release: '{0}'. Valid release names are: {1}".format(dist_name, ', '.join(sorted(index.distributions.keys()))))
    dist = index.distributions[dist_name]
    if type_ not in dist.keys():
        raise RuntimeError('unknown release type "%s"' % type_)
    url = dist[type_]

    def _load_yaml_data(url):
        logger.debug('Load file from "%s"' % url)
        yaml_str = load_url(url)
        return yaml.safe_load(yaml_str)

    if not isinstance(url, list):
        data = _load_yaml_data(url)
    else:
        data = []
        for u in url:
            data.append(_load_yaml_data(u))
    return data


from .legacy import *  # noqa

同理,注意改路径,注意改路径,注意改路径

DEFAULT_INDEX_URL = 'file:/home/linderven/DeskTop/rosdistro/index-v4.yaml' 
3:修改20-default.list
cd /etc/ros/rosdep/sources.list.d 
sudo gedit 20-default.list

原文件

# os-specific listings first
yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml osx

# generic
yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
gbpdistro https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml fuerte

# newer distributions (Groovy, Hydro, ...) must not be listed anymore, they are being fetched from the rosdistro index.yaml instead

修改后文件(/home/linderven/DeskTop/rosdistro/rosdep)


# os-specific listings first

yaml file: /home/linderven/DeskTop/rosdistro/rosdep/osx-homebrew.yaml osx

 

# generic

yaml file: /home/linderven/DeskTop/rosdistro/rosdep/base.yaml

yaml file: /home/linderven/DeskTop/rosdistro/rosdep/python.yaml

yaml file: /home/linderven/DeskTop/rosdistro/rosdep/ruby.yaml

gbpdistro file: /home/linderven/DeskTop/rosdistro/releases/fuerte.yaml fuerte 

也是进行路径修改

13.1.2如果报错路径

从之前那个环境变量配置那儿重新配置一下,一般是运行下面两行

source /opt/ros/noetic/setup.bash
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrcsource ~/.bashrc

13.2:如果运行rosdep update成功

13.2.1:运行rosdep update成功后 ,终端显示结果:

inderven@linderVen:/etc/ros/rosdep/sources.list.d$ rosdep update
reading in sources list data from /etc/ros/rosdep/sources.list.d
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml
Query rosdistro index file:/home/linderven/DeskTop/rosdistro/index-v4.yaml
Skip end-of-life distro "ardent"
Skip end-of-life distro "bouncy"
Skip end-of-life distro "crystal"
Skip end-of-life distro "dashing"
Skip end-of-life distro "eloquent"
Add distro "foxy"
Add distro "galactic"
Skip end-of-life distro "groovy"
Skip end-of-life distro "hydro"
Skip end-of-life distro "indigo"
Skip end-of-life distro "jade"
Skip end-of-life distro "kinetic"
Skip end-of-life distro "lunar"
Add distro "melodic"
Add distro "noetic"
Add distro "rolling"
updated cache in /home/linderven/.ros/rosdep/sources.cache
linderven@linderVen:/etc/ros/rosdep/sources.list.d$ 

接着进行14步

14:运行roscore

roscore

结果:

linderven@linderVen:/etc/ros/rosdep/sources.list.d$ roscore
... logging to /home/linderven/.ros/log/0ce2d1fa-b09b-11ec-9fb7-fbefee69b858/roslaunch-linderVen-52942.log
Checking log directory for disk usage. This may take a while.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://linderVen:36025/
ros_comm version 1.15.14


SUMMARY
========

PARAMETERS
 * /rosdistro: noetic
 * /rosversion: 1.15.14

NODES

auto-starting new master
process[master]: started with pid [52952]
ROS_MASTER_URI=http://linderVen:11311/

setting /run_id to 0ce2d1fa-b09b-11ec-9fb7-fbefee69b858
process[rosout-1]: started with pid [52962]
started core service [/rosout]

15:新打开一个终端运行turtlesim_node

输入

rosrun turtlesim turtlesim_node

如果报错找不到命令,重新配置一下环境变量,然后运行,如下

source /opt/ros/noetic/setup.bash

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrcsource ~/.bashrc

rosrun turtlesim turtlesim_node

结果

linderven@linderVen:/etc/ros/rosdep/sources.list.d$ rosrun turtlesim turtlesim_node
[ INFO] [1648694267.602281083]: Starting turtlesim with node name /turtlesim
[ INFO] [1648694267.606405459]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]

在这里插入图片描述

16:再打开一个终端运行turtle_teleop_key,调出控制键盘

输入

rosrun turtlesim turtle_teleop_key

结果

linder@linder:~/桌面$ source /opt/ros/noetic/setup.bash
linder@linder:~/桌面$ echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrcsource ~/.bashrc
linder@linder:~/桌面$ rosrun turtlesim turtle_teleop_key
Reading from keyboard
---------------------------
Use arrow keys to move the turtle. 'q' to quit.

点击一下,用方向键控制

17:操作小乌龟

注意,鼠标要放在调出的turtle_teleop_key终端上,然后用方向键控制
在这里插入图片描述

其他错误(建议先看一下)

如果第一次运行rosdep init 成功,后面再运行的时候提示文件已经存在,则运行下列代码:

sudo rm /etc/ros/rosdep/sources.list.d/20-default.list

然后再运行 rosdep init

如果报错路径或者某些命令找不到的话,可以尝试重新配置下环境变量

source /opt/ros/noetic/setup.bash

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrcsource ~/.bashrc

最后感谢大佬
作者:被打愣的猫 https://www.bilibili.com/read/cv13788562/ 出处:bilibili
大家可以去总结一下经验

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 16:28:46  更:2022-04-06 16:31:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 22:30:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码